{"slug": "girder-an-mcp-server-that-gives-coding-agents-a-code-graph", "title": "Girder – an MCP server that gives coding agents a code graph", "summary": "Girder, an open-source MCP server from developer dhishwasher, gives coding agents a semantic code graph instead of whole files, cutting context bytes by 97.85% (8,765 vs 408,137 bytes) on a committed ten-node measurement. The single static Rust binary supports Rust, Python, TypeScript, and Go, offers a permanent free tier with paid tools for impact analysis and test selection, and serves seven read-only tools over the Model Context Protocol.", "body_md": "**Girder gives coding agents exactly the code they need, instead of whole\nfiles.** It parses your repository into a living semantic graph — functions,\ndefinitions, call edges — and answers questions against that graph: exact\nfunction source, callers and callees, impact analysis, minimal test selection,\nand verified graph-addressed edits. It is one static Rust binary that any agent\ncan drive over MCP, plus an optional native IDE.\n\n```\ncurl -fsSL https://raw.githubusercontent.com/dhishwasher/Girder/main/install.sh | sh\n```\n\n**Languages:** Rust, Python, TypeScript, and Go. Rust and Python are the most\nmature; TypeScript and Go are measured and gated, with their limits written\ndown ([TypeScript](/dhishwasher/Girder/blob/main/docs/typescript-support.md), [Go](/dhishwasher/Girder/blob/main/docs/go-support.md)).\n\n**Tiers:** the free tier is permanent and needs no account — `get_source`,\n`find_definition`, `search_code`, `ask_codebase`, and `review_changes` on a\nsingle repository. The `orient` and `impacted_tests` tools need a\n[paid license](#license). Keys are verified offline; the binary never phones\nhome.\n\nOn this repository's committed ten-node measurement, `girder context --source-only` returned 8,765 bytes where full-file reads returned 408,137 — a\n[97.85% reduction](/dhishwasher/Girder/blob/main/docs/context-vs-read-cost-observation.json). That counts\nbytes, not tokens.\n\nA prebuilt binary, no Rust toolchain needed:\n\n```\ncurl -fsSL https://raw.githubusercontent.com/dhishwasher/Girder/main/install.sh | sh\ngirder --version\n```\n\nOr from source:\n\n```\ncargo install --path crates/aether-app\ngirder --help\n```\n\nThis builds the default headless profile and installs the `girder` binary to\n`~/.cargo/bin` (make sure it's on your `PATH`). No GPU, display, network, or API\nkey is required — the default AI provider is an offline `MockProvider`. The GUI\nand live AI providers are opt-in Cargo features not included in a plain\ninstall; see [The GUI](#the-gui) and [Local-first AI](#local-first-ai) below.\n\nEach Windows release also includes `Girder-<version>-setup.exe`. It installs\nfor the current user under `%LOCALAPPDATA%\\Programs\\Girder`, adds Girder to the\nuser `PATH`, creates a Start Menu shortcut, and does not request administrator\naccess. Open a new terminal after installation so it sees the updated `PATH`.\nThe installer includes the desktop GUI, and its Start Menu shortcut opens it.\nThe archives and npm installation continue to provide the headless CLI.\n\nThe installer is **not code-signed yet**, so Windows SmartScreen will warn on\nfirst run. After downloading the installer from the GitHub release, double-click\nit, choose **More info** on the “Windows protected your PC” dialog, verify that\nthe app is Girder and the publisher is shown as unknown, then choose **Run\nanyway**. If those details do not match, cancel instead.\n\nExact-symbol lookup is Girder's strongest search path. Natural-language intent\nsearch is experimental: it reached **41.9% top-1** and **77.4% top-5** accuracy\non the committed 31-item corpus, below the precommitted 75% and 90% thresholds.\nSee the [observation](/dhishwasher/Girder/blob/main/docs/description-search-accuracy-observation.json) and\n[policy](/dhishwasher/Girder/blob/main/docs/description-search-accuracy-policy.json).\n\n`girder mcp` serves the read-only graph commands over the\n[Model Context Protocol](https://modelcontextprotocol.io), so an agent can ask\nabout your codebase instead of reading files into its context window.\n\nClaude Code:\n\n```\nclaude mcp add girder -- npx -y girder-mcp .\n```\n\nAny MCP client config:\n\n```\n{\n  \"mcpServers\": {\n    \"girder\": {\n      \"command\": \"npx\",\n      \"args\": [\"-y\", \"girder-mcp\", \".\"]\n    }\n  }\n}\n```\n\nWith a binary already installed, `\"command\": \"girder\", \"args\": [\"mcp\", \".\"]`\nskips npm entirely.\n\nSeven tools, all read-only:\n\n| Tool | What it answers | \n|---|---|\n| `get_source` | The source of specific functions, without the file around them. | \n| `find_definition` | Where an exact identifier is declared. Not a substring search. | \n| `search_code` | Which functions match a description, when you don't know the name. | \n| `ask_codebase` | Callers, callees, and blast radius, by graph traversal. | \n| `impacted_tests` | Only the tests that can reach what changed. | \n| `review_changes` | What changed in the working tree, as semantics rather than text. | \n| `orient` | Source, callers, callees, tests, and impact for one node, in one call. | \n\nTwo precommitted measurements, both counting **bytes of command output rather\nthan tokens** (no tokenizer was run):\n\n- `get_source` against reading the whole file:**97.85% fewer bytes** across ten\nfunctions sampled by source-size decile, cheaper on all ten\n([`docs/context-vs-read-cost.md`](/dhishwasher/Girder/blob/main/docs/context-vs-read-cost.md) ).\n- `find_definition` against`grep` :**97.98% fewer bytes** across ten\nidentifiers ([`docs/names-cost.md`](/dhishwasher/Girder/blob/main/docs/names-cost.md) ).\n\nBoth are single-repository measurements. The direction is structural — files\nare much larger than the functions in them, and grep returns every mention\nwhere `find_definition` returns only declarations — but the exact percentages\nare not portable.\n\n`impacted_tests` is **advisory**. It over-selects unrelated tests, and it\nmisses tests reached only through dynamic dispatch (measured: recall 0.000 on a\npolymorphic-dispatch case, [`docs/core-representative-mutations.md`](/dhishwasher/Girder/blob/main/docs/core-representative-mutations.md)).\nA full test run remains the authority before calling a change safe.\n\n`orient` bundles what `get_source` + `ask_codebase` (callers, callees, and\nimpact) + `impacted_tests` otherwise answer across 5-6 separate calls into\none. On a 15-task corpus spanning ten pinned repositories, that one call used\n**fewer aggregate bytes than the chain it replaces** (48,814 vs 101,302,\na 0.48 ratio) while cutting 78 round trips to 15 — one per task — and, after\ntwo disclosed defects were fixed, **37 of 37 gated checks pass**. The first\nrun found `impacted_tests --quiet` silently dropping non-Rust/Python test\nnames (`orient`'s own test-coverage section did not share the bug, which is\nhow it was found); that filter is now removed. Its natural-language `intent`\ninput still inherits `search_code`'s accuracy — all three intent tasks in\nthis corpus resolved to the wrong node, unchanged and out of scope for this\nfix — but `orient`'s confidence heuristic, which originally caught none of\nthe three, now flags all three `\"confidence\": \"low\"` with candidate scores\nattached, at the cost of also flagging some correct resolutions when a\nrunner-up is close. See [`docs/orient-tool.md`](/dhishwasher/Girder/blob/main/docs/orient-tool.md) and\nthe committed [policy](/dhishwasher/Girder/blob/main/docs/orient-tool-policy.json) /\n[original observation](/dhishwasher/Girder/blob/main/docs/orient-tool-observation.json) /\n[post-fix observation](/dhishwasher/Girder/blob/main/docs/orient-tool-observation-post-fix.json).\n\nThe project root is fixed when the server starts, so no tool call can reach\nanother directory. `GIRDER_MCP_TIMEOUT_SECONDS` (default 120) bounds each\ncall; raise it for a very large repository.\n\nEverything below assumes `girder` is on your `PATH`. Building from a source\ncheckout without installing works the same way with `cargo run -p aether-app --`\nin place of `girder`.\n\n```\n# Full end-to-end demo — no GPU, display, or API key required:\ngirder\n\n# Run the test suite (graph, builder, AI router, agent swarm, debugger):\ncargo test --workspace\n\n# Optional: compile live providers and run the real debugpy adapter test:\ncargo check -p aether-ai --features live-providers\npython3 -m pip install debugpy\ncargo test -p aether-dap --test debugpy -- --ignored\n```\n\nGirder is also a CLI that operates on actual directories:\n\n```\n# Build the semantic graph from a project and save it as <dir>/project.aether:\ngirder analyze sample-project\n\n# Inspect a saved graph and a node's impact set:\ngirder inspect sample-project/project.aether crate::lib::add\n\n# Concept search: rank functions by relevance to a natural-language query:\ngirder search sample-project \"sum numbers in a list\"\n\n# Graph-semantic rename — follows Calls edges (not text search) and rewrites\n# only the real callers, then saves the updated graph:\ngirder refactor sample-project rename crate::lib::add plus\n\n# Preview what the swarm would build — graph-aware Planner only, no code written:\ngirder swarm-plan sample-project \"add user authentication\"\n\n# Dispatch the agent swarm on a project with a natural-language intent:\ngirder forge sample-project \"add a subtract function\"\n\n# Author a single graph-addressed plan step via a wired-in model (the\n# offline MockProvider by default) and execute it through the same\n# verified plan executor as `plan run` below, repairing from check\n# failures automatically. Never point this — or `plan run --authored` —\n# at sample-project/: it is a pinned measurement fixture, not a demo\n# target, and both refuse it outright (see \"Demo target\" below):\ngirder do demo-project \"add an exclamation mark to the farewell\"\n\n# Emit graph context, a real Plan Format v2 authoring schema, and a plan\n# skeleton as one JSON object — for pasting into any external chat model\n# that isn't wired in as a provider. See \"External authoring\" below for\n# the full loop from here to a verified, applied edit:\ngirder context demo-project --nodes crate::greeter::farewell \"add an exclamation mark to the farewell\" --json\n\n# Validate/inspect/execute a plan file directly. `--authored` is for a plan\n# an external model wrote by hand (see \"External authoring\" below); without\n# it, `run` executes a plan exactly as authored (used internally by `do`):\ngirder plan validate my-plan.json\ngirder plan explain my-plan.json\ngirder plan run my-plan.json --dry\n\n# Semantic code review vs HEAD (typed mutations, not text diffs):\ngirder review sample-project --since HEAD~1\n\n# Minimal test selection: find every test reachable from changed functions:\ngirder test-impact sample-project --run\n\n# Knowledge-graph query — answer a question by traversing the semantic graph:\ngirder query sample-project \"what would break if I change add?\"\ngirder query sample-project \"what calls sum_list?\"\ngirder query sample-project  # interactive REPL (reads stdin)\n\n# Start a graph-native collaboration history, give another replica its own actor,\n# record that replica's current source graph, and deterministically merge it:\ngirder collab init sample-project alice alice.aetherc\ngirder collab fork alice.aetherc bob bob.aetherc --approve\ngirder collab sync sample-project bob.aetherc\ngirder collab merge alice.aetherc bob.aetherc merged.aethercb\ngirder collab materialize merged.aethercb merged.aether\n# Membership changes are causal operations and require explicit approval:\ngirder collab member add alice.aetherc carol --approve\ngirder collab member remove alice.aetherc carol --approve\n\n# Or exchange deltas in a mutually authenticated live loopback session.\n# Secret contents are generated with private permissions and never printed.\n# Group-secret-only operation remains available as a migration mode:\ngirder collab secret collaboration.secret\n\n# Strict identity mode additionally pins each roster actor to an Ed25519 key.\n# Generate each actor's private/shareable-public pair, compare the printed\n# SHA-256 fingerprints out of band, and approve the exact peer fingerprint:\ngirder collab identity generate alice.aetherc \\\n  alice.identity alice.identity.pub\ngirder collab identity generate bob.aetherc \\\n  bob.identity bob.identity.pub\ngirder collab identity show bob.identity.pub\ngirder collab identity trust alice.trust \\\n  bob.identity.pub --approve <bob-fingerprint>\ngirder collab identity trust bob.trust \\\n  alice.identity.pub --approve <alice-fingerprint>\n# Sign existing local-authored history now (strict host/join also does this\n# in memory before exchange), then audit a fully attested bundle offline:\ngirder collab identity attest alice.aetherc alice.identity\ngirder collab identity attest bob.aetherc bob.identity\n\ngirder collab host alice.aetherc 127.0.0.1:7331 \\\n  --identity-file alice.identity --trust-store alice.trust \\\n  --secret-file collaboration.secret --discovery-dir .bitcode/peers \\\n  --presence \"reviewing parser changes\"\ngirder collab discover bob.aetherc .bitcode/peers \\\n  --secret-file collaboration.secret\ngirder collab join-peer bob.aetherc alice .bitcode/peers \\\n  --identity-file bob.identity --trust-store bob.trust \\\n  --secret-file collaboration.secret --presence \"running transport tests\"\n# An explicit address remains available when local discovery is not in use:\ngirder collab join bob.aetherc 127.0.0.1:7331 \\\n  --secret-file collaboration.secret \\\n  --identity-file bob.identity --trust-store bob.trust\n# Verify every retained non-bootstrap operation against the current local pins:\ngirder collab identity verify \\\n  alice.aetherc alice.identity alice.trust\n# To rotate your own key, first generate a new pair, then record a dual-signed\n# causal transition while both private keys are available. Peers can then rotate\n# their current pin before the next strict session:\ngirder collab identity generate alice.aetherc \\\n  alice-new.identity alice-new.identity.pub\ngirder collab identity rotate-local alice.aetherc \\\n  alice.identity alice-new.identity \\\n  --from <old-alice-fingerprint> --approve <new-alice-fingerprint>\n# Peer trust rotation/removal also requires the exact reviewed fingerprints:\ngirder collab identity rotate alice.trust \\\n  bob-new.identity.pub --from <old-bob-fingerprint> --approve <new-bob-fingerprint>\ngirder collab identity remove alice.trust bob \\\n  --approve <new-bob-fingerprint>\n# Successful sessions persist both peers' causal acknowledgements. Once every\n# active member has acknowledged superseded history, prune it conservatively:\ngirder collab compact alice.aetherc\n# Rebuild remote whole-file projections, show semantic/file changes and\n# conflicts, then explicitly validate and journal-commit the reviewed bytes:\ngirder collab review sample-project alice.aetherc\ngirder collab apply sample-project alice.aetherc --approve\n\n# Real Python execution tracer — records every variable at every line/call/return:\ngirder debug script.py\ngirder debug script.py --what-if x=10 at 2\n\n# DAP adapter dry-run: resolve graph breakpoints without launching an adapter:\ngirder dap script.py --dry-run\n\n# Generate and review an extension recipe without changing the project:\ngirder extension sample-project generate \"show call impact\"\n\n# Grant the exact recipe digest/capabilities, then manage its lifecycle:\ngirder extension sample-project generate \"show call impact\" --approve\ngirder extension sample-project list\ngirder extension sample-project disable dev.bitcode.generated.show-call-impact\ngirder extension sample-project remove dev.bitcode.generated.show-call-impact\n\n# Install a hand-authored declarative recipe after the same explicit review:\ngirder extension sample-project install recipe.json --approve\n\n# Browse the built-in reviewed marketplace and inspect a listing:\ngirder extension sample-project marketplace search impact\ngirder extension sample-project marketplace show org.bitcode.impact-navigator\n\n# Regenerate a reviewed intent for this project, preview its capability delta,\n# then explicitly approve the adapted recipe:\ngirder extension sample-project marketplace adapt org.bitcode.impact-navigator\ngirder extension sample-project marketplace adapt org.bitcode.impact-navigator --approve\n\n# Portable catalogs use the same bounded parser and print a catalog fingerprint:\ngirder extension sample-project marketplace list \\\n  --catalog marketplace/girder-extensions.json\n\n# Full help:\ngirder --help\n```\n\n`analyze`/` forge` walk every `.rs`, `.py`, `.ts`, `.tsx`, `.mts`, `.cts`, and\n`.go` file (skipping `target`, `.git`, …),\nbuild the graph with directory-aware module paths, resolve free and\nreceiver-qualified method calls across files, and persist the `.aether` graph.\nSupported languages are Rust, Python, TypeScript, and Go. The TypeScript and Go\ngraph surfaces are measured and gated, but remain less mature than Rust and\nPython: TypeScript meets its precision and recall gates, while Go currently\nrecords one false negative (micro-recall 0.954545 against a 1.0 gate). See the\nhonest support boundaries and results for\n[TypeScript](/dhishwasher/Girder/blob/main/docs/typescript-support.md) and [Go](/dhishwasher/Girder/blob/main/docs/go-support.md), with the\ncommitted observations for\n[TypeScript](/dhishwasher/Girder/blob/main/docs/typescript-support-observation.json) and\n[Go](/dhishwasher/Girder/blob/main/docs/go-support-observation.json).\nRust module-scope imports retain renamed symbol identity across bounded public\nre-export chains, including crate-root and `mod.rs` facades, so collisions are\nresolved by exact path while ambiguous or cyclic aliases stay unlinked.\nRust parameter annotations and direct type-qualified local constructors provide\nbounded receiver types, including inside macro token trees. Function signatures\nalso supply parser-owned return types for local factory bindings through `?`,\n`unwrap`/` expect`, and result-preserving error adapters. Instance factories\nreturning `Self` resolve to their owning type, while single-argument generic\nwrappers propagate an inner receiver only when their signatures prove the same\ndirect type parameter flows through. Recursive factory hints have a hard size\nbudget. Unknown receiver types remain unresolved rather than being linked to an\nunrelated same-named method.\n`forge` plans every candidate byte, checks conflict\nbaselines, validates the candidate in a copied workspace, runs Cargo build/tests\nwhen a manifest is present plus configured validation commands, and only then\njournal-commits the source projection and graph together.\n\n`collab` exchanges semantic graph operations rather than text ranges. Each\nhuman or agent replica has a validated actor id and causal version vector;\nminimal idempotent deltas converge regardless of delivery order. Concurrent\ndeletes win, concurrent updates have a deterministic tie-break, and deleting\nthen recreating a node cannot resurrect edges from its old generation. RON\n`.aetherc` bundles are reviewable; `.aethercb` bundles use compact bincode.\nInit/sync reconciles source with the durable graph so graph-owned agent and\nextension metadata participates instead of being discarded. Bundle saves use a\nsynced atomic replacement.\n\nMembership is part of the causal operation history rather than a local address\nbook. An approved `collab fork` registers the invited actor in both the source\nand forked bundles; if writing the fork fails, the source roster is rolled back.\n`collab member add|remove ... --approve` records convergent add/remove\noperations, concurrent removal wins, normal replica APIs reject new operations\nafter the local actor is removed, and membership changes invalidate stale\nacknowledgements. A history has one genesis self-membership root: separately\ninitialized actors cannot self-invite through a relayed delta. Removal records\nthe highest counter observed for that actor; unseen later counters fail until\ntheir context observes a causal re-add, so a removed offline actor cannot keep\nextending a stale membership epoch. Version\n1 and 2 bundles migrate conservatively by retaining the local actor, previously\nacknowledged peers, and non-bootstrap actors already present in the causal\nclock. Use `fork` to allocate a new actor replica; direct `member add` is for\nre-authorizing an already allocated unique actor, since it does not create that\nactor's bundle. Version 1-3 bundles load as explicit unsigned legacy history;\nversion 4 stores operation attestations without changing existing CRDT dots.\n\nLive host/join uses fresh random challenges, mutual HMAC-SHA256 group authentication, direction- and sequence-bound message integrity, bounded frames checked before allocation, and socket timeouts. Secrets are read from non-symlink regular files owned by the current user with private permissions. Optional identity mode adds transcript-bound Ed25519 proofs and a local actor-to-key trust store: both endpoints must configure it, each public key must match the peer actor's exact pinned fingerprint, and either attempted downgrade to group-secret-only mode is refused. The signed transcript also authenticates fresh X25519 keys, deriving a session-integrity key that another group-secret holder cannot calculate from captured traffic. Private identity files receive the same ownership, symlink, and permission checks. New trust, rotation, and removal are explicit fingerprint-approved operations, and identity files are actor-bound to their collaboration bundle.\n\nStrict identity sessions also give every retained non-bootstrap CRDT operation a\ndurable Ed25519 attestation. A delta importing a new operation, or a new\nretroactive attestation for an already-known dot, triggers verification of that\nactor's complete retained history before any bundle is replaced. The signature\nbinds the dot, causal context, and exact action, so action tampering, actor\nforgery, unsigned relay, conflicting proofs, and replayed dot changes fail\natomically. Local legacy operations can be upgraded with `identity attest`;\n`identity verify` audits a whole bundle against the local private identity and\npeer trust store.\n\nKey rotation is a causal operation signed by the previous key with a second\nproof from the successor key. Verification walks this chain backward from the\ncurrently pinned fingerprint, so a retired key remains valid for its historical\ncounters but cannot authorize later ones. Rotation operations are never removed\nby compaction. Deterministic bootstrap snapshot operations remain an explicitly\npre-shared bundle baseline rather than pretending to have a human signature;\nstrict deltas cannot introduce new bootstrap history. Group-secret-only live\nsessions and the unpinned `collab merge` workflow ignore incoming attestation\nmetadata, preventing an unauthenticated path from poisoning later strict\nverification. Actor-key transparency beyond exact local pins is still a\nseparate layer.\n\nThe transport deliberately binds loopback only: graph payloads are authenticated but not encrypted, so remote peers must connect through an encrypted tunnel such as SSH. After both sides verify that the other actor is active in the roster and durably persist a converged version, they persist monotonic peer acknowledgements. A delta that would remove either authenticated endpoint is rejected before persistence. A session claiming an unlisted actor is rejected even with a valid group-secret proof. Host and join may explicitly share a single-line status of at most 256 UTF-8 bytes. Both statuses and optional public keys are bound into the authenticated handshake. Status is reported to the peer and discarded after that synchronization; it is never written to graph operations, acknowledgements, discovery tickets, or collaboration bundles.\n\nAn optional `--discovery-dir` publishes an atomic, HMAC-authenticated,\nprocess-bound lease for the loopback host. The current-user directory and\ntickets must be private (new paths are mode 700 and 600 on Unix), symlinks are\nrejected, each scan is capped at 256 entries, dead process ids on Unix and\nactors outside the local bundle's active remote roster are ignored, and\n`join-peer` refuses ambiguous same-actor tickets. A normal host shutdown removes\nits unchanged ticket.\nTickets are only endpoint hints: PID reuse or a stale ticket cannot authorize a\nsession because the existing roster-bound mutual-authentication handshake still\ndecides every join.\n\n`collab compact`\nrequires an acknowledgement from every active remote member, then prunes only\ncausally superseded operations while retaining concurrent winners, membership\nremoval barriers, and node-generation tombstones. Peers older than the recorded\nhistory floor fail safely and need a current bundle. Network/continuous\ndiscovery, continuous presence/subscriptions, encrypted remote transport, and\noperation-level signatures/key transparency remain future work.\nGroup-secret-only migration mode remains a group credential: roster checks\nreject an unlisted claimed actor, but any secret holder can impersonate an\nactive actor. Pinned identity mode prevents that endpoint impersonation after\nfingerprints have been verified. It does not retroactively prove the author of\nevery historical CRDT operation: authenticated peers can relay the existing\nmulti-actor operation set, so provenance of stored history remains trusted at\nthe collaboration-group boundary until operations themselves are signed.\n\nEvery parsed module carries a bounded `file-v1` whole-file projection in the\nsemantic graph. `collab review` compares the remote and freshly reconciled local\ngraphs, lists file and semantic changes, and reparses every remote file to prove\nits nodes and projection-derived edges agree with the claimed graph. Missing\nmodules, path escapes, oversized files, inconsistent concurrent winners, and\nstale local baselines are conflicts. `collab apply --approve` reruns the plan,\nexecutes configured validation in an isolated candidate, then journal-commits\nadded/modified/deleted files and the reconciled graph together. Native approval\nis SHA-256-bound to every candidate and expected baseline byte, so any project\nor bundle change forces another review.\n\nGirder works without configuration. To materialize and inspect the validated defaults for a project:\n\n```\ngirder config sample-project --init\ngirder config sample-project\n```\n\n`girder.toml` controls source roots and ignore globs, symlink policy, graph\nstorage, structured impacted-test commands, the agent output module/file, and\ncandidate-validation commands, timeouts, diagnostic limits, and copy budgets.\nCommands are argv arrays rather than interpolated shell strings. On Linux,\navailable `bubblewrap` support mounts the host filesystem read-only while the\ncandidate and approved build caches remain writable; other platforms still run\ninside the disposable candidate copy. Invalid keys, escaping paths, broken\nglobs, unsupported graph extensions, malformed commands, and unsupported config\nversions fail before project analysis starts.\n\n`girder do` drives a wired-in provider (OpenAI, Anthropic, Ollama, or the\noffline `MockProvider`) automatically. `girder context` and `plan run --authored` split that same workflow at the model boundary, so *any* chat\nmodel — one with no API integration in this codebase at all — can author a\nverified graph edit.\n\n**Reading, not authoring?** Add `--source-only`. The default output below\ncarries a Plan Format v2 schema and plan skeleton, which is a fixed ~6 KB\nthat a model authoring an edit needs and a model merely *reading* code does\nnot — it measured *more expensive* than reading the whole file on 2 of 10\nnodes, and 15.6× the file for a small one. `--source-only` drops the\nenvelope and measured 97.85% cheaper than a file read across the same ten\nnodes ([`docs/context-vs-read-cost.md`](/dhishwasher/Girder/blob/main/docs/context-vs-read-cost.md)).\nIt also needs no git repository, having no `base_commit` to pin.\n\nThe authoring loop:\n\n```\n# 1. Emit graph context, a real Plan Format v2 authoring schema, and a plan\n#    skeleton (base_commit, on_failure, the mandatory tests.impacted check)\n#    as one JSON object:\ngirder context demo-project --nodes crate::greeter::farewell \\\n  \"add an exclamation mark to the farewell\" --json > context.json\n\n# 2. Paste context.json into any chat model. Ask it to fill in the plan\n#    skeleton's step (id, description, edits) so the step satisfies the\n#    schema exactly, and save its response as plan.json — the schema is the\n#    literal Plan Format v2 the executor loads, not an approximation of it,\n#    so a model that follows it produces a file that loads without\n#    translation.\n\n# 3. Run and verify it. `plan run` has no project-directory argument — the\n#    root is always the current directory, so run this from inside\n#    demo-project/. --authored applies the same harness guarantees `do`\n#    applies internally to a model-authored plan: on_failure is forced to\n#    rollback_plan, a tests.impacted check is injected if the plan doesn't\n#    already carry one, and a zero-step plan is refused outright rather than\n#    passing vacuously. --authored-by <name> records who authored it in the\n#    written report:\n(cd demo-project && girder plan run ../plan.json --authored --authored-by claude-opus-5)\n```\n\nA passing run applies the edit to the real tree and writes a report under\n`.girder/reports/`; a failing check rolls the tree back to `base_commit`\nautomatically, so a bad edit from an untrusted external model never lands\nhalf-applied. `plan_schema()`'s exact shape (a `oneOf` discriminated union\nper edit/check kind, matching `planfile::schema`'s deserializer field for\nfield) is what makes step 2 reliable — see gap 17 in\n[`docs/core-gap-analysis.md`](/dhishwasher/Girder/blob/main/docs/core-gap-analysis.md) for the defect this\nclosed and the round-trip test that proves it.\n\n`girder do` and `plan run --authored` both refuse `sample-project/` as a\ntarget outright, with an error naming `demo-project/` as the place to run\ninstead:\n\n``` bash\n$ girder do sample-project \"uppercase greet's return value\"\nerror: sample-project/ is a pinned measurement fixture (see gap 18/21 in\ndocs/core-gap-analysis.md) and refuses authored writes; run demos against\ndemo-project/ instead\n```\n\n`sample-project/` is a pinned baseline `tools/authoring_task_check.py` and\n`tools/plan_executor_oracle.py` read against a specific clean source commit\nfor the graph-addressed-authoring-cost measurement corpus, not a scratch\ntarget. A real (non-dry) authored write there mutates the same file the\nmeasurement harness depends on — this happened twice, three days apart, and\ncost a full day of debugging a broken referee before the fixture drift was\nfound; see gap 18 in `docs/core-gap-analysis.md`. `demo-project/` exists so\nthat never has to happen again: a small, disposable Python project nothing\nunder `tools/` or `docs/` reads, safe for real (non-dry) authored writes.\nRead-only commands (`context`, `search`, `analyze`, `test-impact`) still work\nagainst `sample-project/` — only the two commands that write are refused.\n\n`girder` (no args) walks the entire pipeline over stdout:\n\n1. **Builds a semantic graph** from source with tree-sitter (the graph is the\nsource of truth; text is a projection).\n2. **Dispatches the agent swarm** on a natural-language intent\n(*\"Add a multiply function to the math module\"* ). The graph-aware Planner reads\nexisting nodes before planning; the Coder generates each function, wires Calls\nedges, and emits a FeatureComplete summary; Tester, Documenter, Refactorer,\nSecurityAuditor, and Optimizer annotate in parallel.\n3. **Runs predictive impact analysis** over the graph.\n4. **Time-travels a deliberate bug** : records an execution trace via`sys.settrace` ,\nbranches a what-if alternative (variable overridden at a specific step via\nCPython's`PyFrame_LocalsToFast` ), shows exactly where the two timelines diverge.\n\n| Crate | Role | \n|---|---|\n| `aether-graph` | The living semantic graph: nodes/edges, impact analysis, `.aether` serialization, and convergent collaboration replicas.**Source of truth.** | \n| `aether-builder` | tree-sitter → graph mapping, incremental edit sync, syntax-highlight spans. | \n| `aether-ai` | `AiProvider` trait, offline`MockProvider` , OpenAI/Anthropic live providers, multi-provider`Router` , provider extension points. | \n| `aether-agents` | The parallel swarm: message bus, orchestrator, 8 specialized agents. | \n| `aether-debugger` | Recording interpreter, execution trace, branching timeline, what-if + AI root-cause. | \n| `aether-dap` | Debug Adapter Protocol client/session layer with graph-aware breakpoint support. | \n| `aether-extensions` | Strict declarative recipes, digest-bound grants, graph-native lifecycle, bounded UI and project contributions. | \n| `aether-app` | The `girder` binary: every CLI subcommand, plus the egui/wgpu GUI behind feature`gui` . | \n\n```\ncargo run -p aether-app --features gui -- --gui sample-project\n```\n\nThe native workspace opens a configured project, indexes its Rust, Python, and TypeScript source, provides file navigation and language-aware editing, folds edits into the graph, and reconciles those fresh projections with the durable graph. Agent summaries, graph-owned nodes, and inferred relationships survive reopen and editor refresh while source-derived structure follows the files on disk.\n\nThe semantic graph is an interactive navigation surface rather than a static\ndiagram. Its retained force layout keeps positions stable while the graph\nchanges; pan/zoom, fit-to-view, text search, node/edge type filters, one- and\ntwo-hop focus, viewport culling, and zoom-dependent labels keep large graphs\nlegible. At overview scale, implementation nodes and their relationships\ncollapse into weighted module-level connections; zooming in restores exact\ntypes, functions, and enabled relationships. The overview ranks and bounds\nmodule connections so the strongest architectural signals remain readable.\nSelecting a node exposes its source location and agent metadata, and\ndouble-clicking or choosing **Open source** moves the editor cursor to its span.\n\nEditor saves use a recoverable journaled transaction for the source projection\nand semantic graph. Dirty buffers guard project/file switches, saves detect\nexternal source or graph changes, and startup rolls back an interrupted\nmulti-file commit before indexing. GUI agent runs mutate a checkpointed graph\nand remain visibly pending while validation runs off the render thread. Commit\nstays disabled until the exact graph snapshot passes candidate build/tests;\ndiagnostics remain inspectable and failed candidates can be revalidated or\nrolled back. **Commit** projects generated functions to the configured output\nfile and persists the graph, while **Roll back** cancels validation and restores\nthe pre-run graph without touching source files.\n\nThe right workspace has separate **Agents**, **Extensions**, **Collaboration**,\nand **Author** views. Extensions contains Generate, Marketplace, and Installed\ntabs. Extension generation returns\na strict JSON recipe; installation stays disabled until the user reviews its\nexact SHA-256 digest, capabilities, contributions, projections, and full JSON.\nThe marketplace searches bounded declarative catalogs, displays the catalog and\nlisting/reference-recipe fingerprints plus reviews bound to both, and\nregenerates a listing intent against a bounded sample of the current semantic graph. Adapted\nrecipes preserve the listing ID and show every added/removed capability scope.\nA catalog review never grants installation authority: the adapted recipe still\nrequires a fresh approval bound to its own exact digest.\nReviewer identities are catalog metadata rather than cryptographic signatures;\nverify an external catalog's printed SHA-256 fingerprint through the channel\nthat distributed it.\n\nThe **Collaboration** view initializes, inspects, and synchronizes the full\nworkspace graph, generates private secrets, verifies bounded local discovery\ntickets, and lets the user select an authenticated active-roster endpoint\nbefore joining on a background thread so rendering never blocks. It shows\ncausal version/operation counts and the deterministic conflict policy, durable\nacknowledgements, and compacted history floor; it can conservatively compact\nacknowledged history. A live join updates the collaboration bundle only.\nOptional identity controls generate an actor-bound key, display a peer's exact\nfingerprint for out-of-band review, pin the unchanged public file, list trusted\nactors, and make strict identity mode visibly distinct from legacy group-secret\nmode. Explicit rotation/removal remains available in the CLI.\nSeparate Review and Apply controls keep remote graph-to-source projection\nexplicit, consistency-checked, digest-bound, validated, and atomic. CLI `host`\nis the persistent serving surface.\n\nThe **Author** view exposes both authoring paths from \"External authoring\"\nabove without a terminal: type an intent, click **Search** to run the same\nconcept search `girder do`/` context` use (only the top-scored hit starts\nchecked — narrower than the CLI default on purpose, since gap 15 in\n`docs/core-gap-analysis.md` exists to shrink what a model can touch), and\nadjust the checkboxes to pin the exact nodes a plan may edit — the same\n`--nodes` a terminal invocation would otherwise require typing full paths\nfor. **Local model** mode mirrors `girder do`: **Run** streams each\nprovider attempt into a live log and shows pass/fail plus the report.\n**External model** mode mirrors `girder context` + `plan run --authored`:\n**Copy context JSON** puts exactly what the CLI command would print onto the\nclipboard, paste a model's plan response back in, and **Run authored**\napplies the same guarantees (forced `rollback_plan`, the mandatory\n`tests.impacted` check, zero-step refusal). A non-dry Run in either mode\nrequires a second, explicit confirming click — a GUI button that silently\nwrites to the tree has no command line to review first. Open `demo-project/`\nto try the full loop for real:\n\n```\ncargo run -p aether-app --features gui -- --gui demo-project\n```\n\nThen, in the Author tab: type \"add an exclamation mark to the farewell\",\nclick Search, leave `crate::greeter::farewell` checked, and either click Run\n(Local model) or use Copy Context JSON / paste a plan back in / Run authored\n(External model) — Dry run stays checked by default in both, so nothing\nwrites to the tree until it's unchecked and confirmed. Like `girder do`\nagainst a terminal, both refuse `sample-project/` outright; only\n`demo-project/` (or another project you point it at) accepts a real,\nnon-dry Run.\n\nInstalled records and their contribution nodes live in the semantic graph and survive source reconciliation. Enable/disable affects only contribution visibility. Removal conflict-checks every installed projection, restores replaced files, deletes files created by the extension, and commits the project plus graph as one recoverable transaction. Model output is never loaded as native code. Contributed validation commands resolve back to an installed, enabled recipe and require Bubblewrap; they run with networking disabled and a cleared environment in the disposable candidate workspace.\n\nCI type-checks the `gui` feature on the stable Rust toolchain. Rendering needs a\nGPU — or a software Vulkan adapter (Mesa **lavapipe**) plus the usual X11 libs\n(e.g. `libxkbcommon-x11`). If no surface can be created the binary logs the wgpu\nerror and **falls back to the headless demo** automatically, so it never\nhard-fails. It has been verified headlessly under `Xvfb` + lavapipe:\n\nThe **default headless build, all tests, and `girder`'s demo require none\nof this** — no GPU, display, or extra system libraries.\n\nThe default provider is a deterministic, offline `MockProvider`, so everything\nruns with no network and no API key. OpenAI and Anthropic are implemented live\nproviders behind the `live-providers` feature. OpenAI uses the Responses API and\nis selected when `OPENAI_API_KEY` is set:\n\n```\nexport OPENAI_API_KEY=sk-...\nexport OPENAI_MODEL=gpt-5.6   # optional; this is the default\ncargo run -p aether-app --features live-providers -- forge sample-project \"add a divide function\"\n```\n\nAnthropic remains available as a second live provider:\n\n```\nexport ANTHROPIC_API_KEY=sk-ant-...\ncargo run -p aether-app --features live-providers -- forge sample-project \"add a divide function\"\n```\n\nThe `Router` tries OpenAI first when configured, uses Anthropic as a secondary\nlive provider for planning/codegen, and falls back to the mock otherwise. Gemini,\nxAI Grok, and local Ollama remain compile-clean extension-point structs; they\ndeliberately do not enter routing until their HTTP bodies are implemented.\n\nA focused, honest prototype: the three pillars (graph-as-truth, agent swarm, time-travel debug) are real, tested, and runnable.\n\nThe checked\n[Core Trustworthiness Measurement](/dhishwasher/Girder/blob/main/docs/core-trustworthiness-measurement.md)\ncompares affected-test selection with isolated runtime execution. Its bounded\nbaseline measures both Rust and Python precision/recall at `1.000/1.000`\n(the earlier `0.667` Rust precision defect is closed). That is a result on\nsmall fixtures, not a representative-repository superiority claim — and the\ncounter-evidence is checked in alongside it: on a real dependency, a\npolymorphic-dispatch mutation measured recall `0.000`\n([`docs/core-representative-mutations.md`](/dhishwasher/Girder/blob/main/docs/core-representative-mutations.md)),\nwhich is why test selection is documented as advisory rather than\nauthoritative.\n\nImplemented features:\n\n| Feature | What it does | \n|---|---|\n| Semantic graph | Nodes/edges, Rust alias/return/scoped-pattern/Cargo-entrypoint-aware and Python alias/nullable-annotation/constructor-aware cross-file call resolution, literal-aware macro calls, impact BFS, similarity edges, strict versioned `.aether` persistence and source reconciliation | \n| Graph explorer | Retained force layout, pan/zoom, search and typed filters, neighborhood focus, LOD/culling, metadata inspection, source navigation | \n| Agent swarm | Planner + Coder + Tester + Documenter + Refactorer + Optimizer + SecurityAuditor + QueryAgent | \n| Intent-first planning | Planner reads the graph before planning; generates ordered `FeatureSpec` with Calls-edge wiring | \n| Real Python tracer | `sys.settrace` execution recording, what-if branching via`PyFrame_LocalsToFast` | \n| Knowledge-graph queries | Natural-language → concept / impact / callers / callees / explain / neighbourhood | \n| Semantic review | Typed diff (added/modified/removed nodes + edges), impact radius, test gap report | \n| Minimal test selection | Call-graph reachability from changed functions, optional `--run` | \n| Graph collaboration | Deterministic operation-set CRDT, causal membership/deltas/tombstones, atomic RON/bincode bundles, roster-gated authenticated loopback host/join with optional downgrade-resistant pinned Ed25519 actor identities, private authenticated local discovery leases, all-member acknowledgement compaction, and reviewed whole-file source projection | \n| Project contract | Validated `girder.toml` for source scope, graph path, test runners, and agent output | \n| Source projection | GUI/CLI agent output and graph rename commit validated source plus graph through recoverable journaled transactions | \n| Candidate validation | Disposable project copy, optional bubblewrap isolation, Cargo build/tests, configured checks, cancellation/timeouts, bounded diagnostics, snapshot-bound commit gate | \n| DAP integration | Two-phase DAP launch, graph-node breakpoints, stop/stack inspection, and real `debugpy` coverage | \n| Declarative extensions | AI/JSON recipe generation, exact digest-bound approval, parameterized capabilities, graph-native records/contributions, GUI/CLI lifecycle, reversible validated projections | \n| Generative marketplace | Bounded portable catalogs, deterministic fingerprints/search, digest-bound reviews, project-aware regeneration, exact capability deltas, CLI and native browser | \n| External authoring | `girder context` emits graph context plus a real Plan Format v2 schema for any external chat model;`plan run --authored` re-enforces rollback/impacted-test guarantees on the result | \n\nOptional DAP adapter smoke test:\n\n```\npython3 -m pip install debugpy\ncargo test -p aether-dap --test debugpy -- --ignored --nocapture\n```\n\nThe measured table-stakes comparison, current correctness evidence, and\nprioritized open risks are maintained in\n[`docs/core-gap-analysis.md`](/dhishwasher/Girder/blob/main/docs/core-gap-analysis.md).\n\nGirder is **source-available**, not open source, under the\n[Business Source License 1.1](/dhishwasher/Girder/blob/main/LICENSE).\n\nThe free tier is genuinely free and permanent: it has no expiry and requires no\naccount. For a single repository it includes `get_source`, `find_definition`,\n`search_code`, `ask_codebase`, and `review_changes`. The `orient` and\n`impacted_tests` tools require a paid license.\n\nLicenses are signed keys verified locally by the Girder binary. The binary never phones home, makes no network call for licensing, and works fully offline in both tiers.\n\nOn September 4, 2030, the license converts to the Apache License, Version 2.0.\nSee [`LICENSE`](/dhishwasher/Girder/blob/main/LICENSE) for the authoritative terms and\n[`CONTRIBUTING.md`](/dhishwasher/Girder/blob/main/CONTRIBUTING.md) for contribution terms.", "url": "https://wpnews.pro/news/girder-an-mcp-server-that-gives-coding-agents-a-code-graph", "canonical_source": "https://github.com/dhishwasher/Girder", "published_at": "2026-09-07 20:49:20+00:00", "updated_at": "2026-09-07 21:01:17.234936+00:00", "lang": "en", "topics": ["developer-tools", "ai-tools", "ai-agents"], "entities": ["Girder", "dhishwasher", "Model Context Protocol", "Claude Code", "Rust", "Python", "TypeScript", "Go"], "alternates": {"html": "https://wpnews.pro/news/girder-an-mcp-server-that-gives-coding-agents-a-code-graph", "markdown": "https://wpnews.pro/news/girder-an-mcp-server-that-gives-coding-agents-a-code-graph.md", "text": "https://wpnews.pro/news/girder-an-mcp-server-that-gives-coding-agents-a-code-graph.txt", "jsonld": "https://wpnews.pro/news/girder-an-mcp-server-that-gives-coding-agents-a-code-graph.jsonld"}}