Content
# Girder
<!-- mcp-name: io.github.dhishwasher/girder -->
**Girder saves AI coding-agent context by giving the agent exactly the code
it needs instead of whole files.** It builds a local semantic graph of your
repository so Claude Code, Codex, Cursor, and other agents can retrieve
exact functions, definitions, callers, callees, and task context without
filling their context window with irrelevant code. It runs as one static
binary, with no account and no cloud dependency.
```bash
npx -y girder-mcp setup
```
That one command detects and configures Claude Code, Codex, and Cursor.
[](https://github.com/dhishwasher/Girder/actions/workflows/ci.yml)
Latest stable release: [v0.3.3](https://github.com/dhishwasher/Girder/releases/tag/v0.3.3) (Apache-2.0).
Contributions: see [`CONTRIBUTING.md`](./CONTRIBUTING.md).
**Measured output bytes, not tokens (no tokenizer was run):**
- CLI stdout of `girder context ... --json --source-only` (MCP `get_source`)
vs reading the whole file: **97.85% fewer bytes**, across ten functions
sampled by source-size decile
([method and honest limits](./docs/context-vs-read-cost.md)).
- CLI stdout of `girder names ... --json` (MCP `find_definition`) vs plain
grep: **97.98% fewer bytes**, across ten identifiers
([method](./docs/names-cost.md)).
- `orient` (one bundled call: source, callers, callees, tests, and impact
for one node) vs the equivalent chain of separate calls: **48,814 bytes
vs 101,302**, using **15 calls vs 78**, on a 15-task corpus spanning ten
pinned repositories ([method](./docs/orient-tool.md)).
The two percentages measure CLI output; MCP transport overhead was not measured.
## Support Girder
Girder is independently developed to help coding agents consume less code:
precise semantic context instead of whole-file reads and repeated repository
greps. Sponsorship helps fund context efficiency, semantic graph correctness,
agent integrations, reproducible benchmarks, and maintenance. Girder publishes
its measurements, including failures and limitations. If Girder saves you
context, compute, or development time, [sponsor its continued development](https://github.com/sponsors/dhishwasher).
**Funding goal:** $1,000/month to fund ongoing maintenance, releases,
benchmarks, and continued context-efficiency work on Girder. See
[what sponsorship supports](./docs/sponsorship.md).
Real, captured output (see
[`docs/observations/release-prep/`](./docs/observations/release-prep/) for
exact provenance):
```
$ girder context demo-project --nodes crate::greeter::shout_greeting --json --source-only
{
"nodes": [{
"language": "python",
"path": "crate::greeter::shout_greeting",
"source": "def shout_greeting(name):\n return format_greeting(name).upper()"
}]
}
```
One function's exact source returned, not the whole file around it — that
is the core of what Girder gives an agent's context window.
**Languages, stated plainly, not as parity:** Rust and Python each have a
completed 100-call-site audit across three pinned repositories, with no unsound
answers in that sample. Each produced **1 Must and 99 Unknown** answers; the
precision evidence is limited ([measurement](./docs/observations/stage3-audit-reconciliation/after-observation.md)).
TypeScript is measured and gated but explicitly **in progress** — it still has a separate, disclosed node-identity collision
mechanism (duplicate `it()`/`describe()` description strings can silently
overwrite each other's graph node; see
[`docs/observations/stage3-typescript-audit/`](./docs/observations/stage3-typescript-audit/)).
Go's Stage 3 audit is **not complete**. See
[`docs/typescript-support.md`](./docs/typescript-support.md) and
[`docs/go-support.md`](./docs/go-support.md) for the exact, measured limits
of each.
**Also included, as an additional capability built on the same graph —
conservative change-impact and test selection:** `test-impact` names the
tests a change may affect, from the same semantic graph, erring toward
including a test it can't rule out rather than silently dropping it. Real
captured output:
```
$ girder test-impact . --quiet
test-impact: 82 unresolved call-evidence boundaries found; this selection is the conservative must∪may∪unknown union — pass --classified to see why each test is included
test_farewell
test_format_greeting
test_shout_greeting_delegates_to_format_greeting
```
See [Status](#status) for exactly what that selection does and doesn't
prove.
**Pricing and license:** Girder is free and open source under the
[Apache License 2.0](./LICENSE). There is no current paid tier, and no license
key or account is required — see [License](#license).
**Evidence, for a skeptical reader:**
[`docs/evidence-index.md`](./docs/evidence-index.md) points at every
committed audit, measurement, and adversarial finding behind the claims
above — including the bugs found and fixed along the way, not just a final
number.
Girder also includes a native GUI, a parallel agent swarm, a time-travel
debugger, graph-native collaboration, and a declarative extension system —
all real, all documented below under
[Other systems](#other-systems-gui-swarm-collaboration-debugger-extensions),
and all secondary to the semantic-graph core above.
## Install
A prebuilt binary, no Rust toolchain needed:
```bash
curl -fsSL https://raw.githubusercontent.com/dhishwasher/Girder/main/install.sh | sh
girder --version
```
Or from source:
```bash
cargo install --path crates/aether-app
girder --help
```
This builds the default headless profile and installs the `girder` binary to
`~/.cargo/bin` (make sure it's on your `PATH`). No GPU, display, network, or API
key is required — the default AI provider is an offline `MockProvider`. The GUI
and live AI providers are opt-in Cargo features not included in a plain
install; see [The GUI](#the-gui) and [Local-first AI](#local-first-ai) below.
### Windows installer
Each Windows release also includes `Girder-<version>-setup.exe`. It installs
for the current user under `%LOCALAPPDATA%\Programs\Girder`, adds Girder to the
user `PATH`, creates a Start Menu shortcut, and does not request administrator
access. Open a new terminal after installation so it sees the updated `PATH`.
The installer includes the desktop GUI, and its Start Menu shortcut opens it.
The archives and npm installation continue to provide the headless CLI.
The installer is **not code-signed yet**, so Windows SmartScreen will warn on
first run. After downloading the installer from the GitHub release, double-click
it, choose **More info** on the “Windows protected your PC” dialog, verify that
the app is Girder and the publisher is shown as unknown, then choose **Run
anyway**. If those details do not match, cancel instead.
## Search accuracy
Exact-symbol lookup is Girder's strongest search path. Natural-language intent
search is experimental: it reached **41.9% top-1** and **77.4% top-5** accuracy
on the committed 31-item corpus, below the precommitted 75% and 90% thresholds.
See the [observation](./docs/description-search-accuracy-observation.json) and
[policy](./docs/description-search-accuracy-policy.json).
## Competitor benchmark
On the 20-task modest cross-language base set, Girder passed **5/20** versus
Ripwire's **7/20** — a loss. But across the 60 attempts where both products
passed, Girder returned **35,764 bytes** versus Ripwire's **158,514** — 77.4%
fewer — at identical call counts (120 each). GitNexus could not be scored: its
install exceeded the frozen 1 GiB ceiling on this measurement machine, which is
a fact about install footprint on a constrained host, not a claim about its
quality.
No product in this benchmark reached full correctness, and the benchmark does
not establish an overall best product. See the full
[report](./docs/competitor-benchmark/results/modest-final/report.md) for
methodology, per-language results, and everything the numbers above don't
establish.
## Use it from an AI coding agent
`girder mcp` serves the read-only graph commands over the
[Model Context Protocol](https://modelcontextprotocol.io), so an agent can ask
about your codebase instead of reading files into its context window.
Preview the changes, then configure detected agents:
```bash
npx -y girder-mcp setup --dry-run
npx -y girder-mcp setup
```
`setup` detects Claude Code (`~/.claude` or an existing in-home project
`.mcp.json`), Codex (`~/.codex` or an in-home `CODEX_HOME`), and Cursor
(`~/.cursor`). It merges the `girder` MCP entry into each detected agent's
documented config and installs nested `PreToolUse` and `PostToolUse` hooks for
Claude Code and Codex. Pre hooks cover structured `Read`, `read_file`, and
`mcp__.*__read_file` events; post hooks cover Claude's
`Edit|Write|NotebookEdit` and Codex's `apply_patch|Edit|Write` edit names.
Shell commands are intentionally not parsed. Cursor is MCP-only: its documented
post-edit hook input and output semantics do not establish the standalone
additional-context protocol used by this launcher, so setup does not register a
hook there. A generic MCP client has no universal config path and is reported as
not detected. Setup never writes outside your home directory. Existing foreign
`girder` entries remain untouched, including with `--force`; `girder setup
--uninstall` removes only setup-owned changes.
The packaged hook launcher forwards each event to the pinned native `girder hook`
executable and fails open on errors. Only standalone `PreToolUse` JSON is
forwarded on stdout; post-edit native diagnostics pass through stderr, and MCP
continues to use JSON-RPC on its own stdout. The read advisory only gives
guidance when `project.aether` already exists. The post-edit advisory uses that
saved graph snapshot, does not scan or rebuild the project, and describes the
last analyzed version of changed files. See the [setup and client path
guide](./docs/setup.md) for config paths, ownership, and the manual JSON
fallback.
For clients setup cannot detect, add this entry to their documented MCP config
manually:
```json
{
"mcpServers": {
"girder": {
"command": "npx",
"args": ["-y", "girder-mcp", "."]
}
}
}
```
With a binary already installed, `"command": "girder", "args": ["mcp", "."]`
skips npm entirely.
Girder 0.2.6 and later can opt into a cached graph generation with
`girder mcp . --watch` or `npx -y girder-mcp . --watch`. The server keeps
one validated graph generation in memory and incrementally reparses changed
files. The committed watcher measurement matched fresh cold analysis after all
45 mutations while reusing 98.70% of file extractions; the claim is limited to
preserving cold-analysis resolution while reusing parsing. See the
[watcher result and limitations](./docs/mcp-watching.md).
Seven tools, all read-only and all free:
| Tool | What it answers |
|---|---|
| `get_source` | The source of specific functions, without the file around them. |
| `find_definition` | Where an exact identifier is declared. Not a substring search. |
| `search_code` | Which functions match a description, when you don't know the name. |
| `ask_codebase` | Callers, callees, and blast radius, by graph traversal. |
| `impacted_tests` | The conservative set of tests a change might reach — advisory, see below. |
| `review_changes` | What changed in the working tree, as semantics rather than text. |
| `orient` | Source, callers, callees, tests, and impact for one node, in one call. |
### What that saves, and what it doesn't
`orient` bundles what `get_source` + `ask_codebase` (callers, callees, and
impact) + `impacted_tests` otherwise answer across 5-6 separate calls into
one. On a 15-task corpus spanning ten pinned repositories, that one call used
**fewer aggregate bytes than the chain it replaces** (48,814 vs 101,302,
a 0.48 ratio) while cutting 78 round trips to 15 — one per task — and, after
two disclosed defects were fixed, **37 of 37 gated checks pass**. The first
run found `impacted_tests --quiet` silently dropping non-Rust/Python test
names (`orient`'s own test-coverage section did not share the bug, which is
how it was found); that filter is now removed. Its natural-language `intent`
input still inherits `search_code`'s accuracy — all three intent tasks in
this corpus resolved to the wrong node, unchanged and out of scope for this
fix — but `orient`'s confidence heuristic, which originally caught none of
the three, now flags all three `"confidence": "low"` with candidate scores
attached, at the cost of also flagging some correct resolutions when a
runner-up is close. See [`docs/orient-tool.md`](./docs/orient-tool.md) and
the committed [policy](./docs/orient-tool-policy.json) /
[original observation](./docs/orient-tool-observation.json) /
[post-fix observation](./docs/orient-tool-observation-post-fix.json).
Two additional precommitted measurements, both counting **bytes of command output rather
than tokens** (no tokenizer was run):
- `girder context ... --json --source-only` (what MCP `get_source` routes to)
against a naive whole-file-read baseline: **97.85% fewer CLI stdout bytes**
across ten functions sampled by source-size decile, cheaper on all ten
([`docs/context-vs-read-cost.md`](./docs/context-vs-read-cost.md)).
- `girder names ... --json` (what MCP `find_definition` routes to) against a
plain-grep baseline: **97.98% fewer CLI stdout bytes** across ten
identifiers ([`docs/names-cost.md`](./docs/names-cost.md)).
MCP transport overhead and tokens were not measured.
Both are single-repository measurements. The direction is structural — files
are much larger than the functions in them, and grep returns every mention
where `find_definition` returns only declarations — but the exact percentages
are not portable.
These comparisons do not measure a competent agent choosing grep searches and
bounded file reads adaptively. No agentic-grep cost claim is established here.
The subsequent [agentic-grep campaign](./docs/agentic-grep.md) with a local
1.5B model stopped incomplete and produced no pairs with two correct answers.
It establishes no comparative cost advantage or frontier-model behavior.
`impacted_tests` is **advisory**. It over-selects unrelated tests, and some
dynamic-dispatch shapes still aren't resolved — when Girder can't prove a call
site, the frozen policy requires including the related tests rather than
guessing they're safe to skip, so the current, measured consequence is
over-inclusion (recall `1.000`, precision `0.667` on the representative
polymorphic-dispatch case) rather than a silent miss. The underlying
dispatch-resolution gap is still open; only the selection no longer drops the
test silently. See
[`docs/core-representative-mutations.md`](./docs/core-representative-mutations.md)
for the measurement and exactly what changed. A full test run remains the
authority before calling a change safe.
Selecting extra tests costs CPU time; missing a relevant test can conceal a
regression.
The project root is fixed when the server starts, so no tool call can reach
another directory. `GIRDER_MCP_TIMEOUT_SECONDS` (default 120) bounds each
call; raise it for a very large repository.
Everything below assumes `girder` is on your `PATH`. Building from a source
checkout without installing works the same way with `cargo run -p aether-app --`
in place of `girder`.
## Quickstart
```bash
# Full end-to-end demo — no GPU, display, or API key required:
girder
# Run the test suite:
cargo test --workspace
```
### Analyze a repository
Use the CLI to build and query a repository's semantic graph:
```bash
# Build the semantic graph from a project and save it as <dir>/project.aether:
girder analyze sample-project
# Inspect a saved graph and a node's impact set:
girder inspect sample-project/project.aether crate::lib::add
# Concept search: rank functions by relevance to a natural-language query:
girder search sample-project "sum numbers in a list"
# Graph-semantic rename — follows Calls edges (not text search) and rewrites
# only the real callers, then saves the updated graph:
girder refactor sample-project rename crate::lib::add plus
# Emit graph context, a real Plan Format v2 authoring schema, and a plan
# skeleton as one JSON object — for pasting into any external chat model.
# See "External authoring" below for the full loop to a verified, applied edit:
girder context demo-project --nodes crate::greeter::farewell "add an exclamation mark to the farewell" --json
# Validate/inspect/execute a plan file directly:
girder plan validate my-plan.json
girder plan explain my-plan.json
girder plan run my-plan.json --dry
# Semantic code review vs HEAD (typed mutations, not text diffs):
girder review sample-project --since HEAD~1
# Conservative test selection: find every test that might be reachable
# from changed functions:
girder test-impact sample-project --run
# Knowledge-graph query — answer a question by traversing the semantic graph:
girder query sample-project "what would break if I change add?"
girder query sample-project "what calls sum_list?"
girder query sample-project # interactive REPL (reads stdin)
# Full help:
girder --help
```
The agent swarm (`forge`/`do`/`swarm-plan`), graph-native collaboration
(`collab`), the Python execution tracer and DAP adapter (`debug`/`dap`), and
the declarative extension system (`extension`) are real, documented, and
have their own commands — see [Other
systems](#other-systems-gui-swarm-collaboration-debugger-extensions) below.
They are not part of the core graph/context/test-impact workflow above.
`analyze`/`forge` walk every `.rs`, `.py`, `.ts`, `.tsx`, `.mts`, `.cts`, and
`.go` file (skipping `target`, `.git`, …),
build the graph with directory-aware module paths, resolve free and
receiver-qualified method calls across files, and persist the `.aether` graph.
Supported languages are Rust, Python, TypeScript/TSX, and Go. The TypeScript and Go
graph surfaces are measured and gated, but remain less mature than Rust and
Python: TypeScript meets its precision and recall gates, while Go currently
records one false negative (micro-recall 0.954545 against a 1.0 gate). See the
honest support boundaries and results for
[TypeScript](docs/typescript-support.md) and [Go](docs/go-support.md), with the
committed observations for
[TypeScript](docs/typescript-support-observation.json) and
[Go](docs/go-support-observation.json).
Rust module-scope imports retain renamed symbol identity across bounded public
re-export chains, including crate-root and `mod.rs` facades, so collisions are
resolved by exact path while ambiguous or cyclic aliases stay unlinked.
Rust parameter annotations and direct type-qualified local constructors provide
bounded receiver types, including inside macro token trees. Function signatures
also supply parser-owned return types for local factory bindings through `?`,
`unwrap`/`expect`, and result-preserving error adapters. Instance factories
returning `Self` resolve to their owning type, while single-argument generic
wrappers propagate an inner receiver only when their signatures prove the same
direct type parameter flows through. Recursive factory hints have a hard size
budget. Unknown receiver types remain unresolved rather than being linked to an
unrelated same-named method.
### Project configuration
Girder works without configuration. To materialize and inspect the validated
defaults for a project:
```bash
girder config sample-project --init
girder config sample-project
```
`girder.toml` controls source roots and ignore globs, symlink policy, graph
storage, structured impacted-test commands, the agent output module/file, and
candidate-validation commands, timeouts, diagnostic limits, and copy budgets.
Commands are argv arrays rather than interpolated shell strings. On Linux,
available `bubblewrap` support mounts the host filesystem read-only while the
candidate and approved build caches remain writable; other platforms still run
inside the disposable candidate copy. Invalid keys, escaping paths, broken
globs, unsupported graph extensions, malformed commands, and unsupported config
versions fail before project analysis starts.
## External authoring: `girder context` + `plan run --authored`
`girder do` drives a wired-in provider (OpenAI, Anthropic, Ollama, or the
offline `MockProvider`) automatically. `girder context` and `plan run
--authored` split that same workflow at the model boundary, so *any* chat
model — one with no API integration in this codebase at all — can author a
verified graph edit.
> **Reading, not authoring?** Add `--source-only`. The default output below
> carries a Plan Format v2 schema and plan skeleton, which is a fixed ~6 KB
> that a model authoring an edit needs and a model merely *reading* code does
> not — it measured *more expensive* than reading the whole file on 2 of 10
> nodes, and 15.6× the file for a small one. `--source-only` drops the
> envelope and measured 97.85% cheaper than a file read across the same ten
> nodes ([`docs/context-vs-read-cost.md`](./docs/context-vs-read-cost.md)).
> It also needs no git repository, having no `base_commit` to pin.
The authoring loop:
```bash
# 1. Emit graph context, a real Plan Format v2 authoring schema, and a plan
# skeleton (base_commit, on_failure, the mandatory tests.impacted check)
# as one JSON object:
girder context demo-project --nodes crate::greeter::farewell \
"add an exclamation mark to the farewell" --json > context.json
# 2. Paste context.json into any chat model. Ask it to fill in the plan
# skeleton's step (id, description, edits) so the step satisfies the
# schema exactly, and save its response as plan.json — the schema is the
# literal Plan Format v2 the executor loads, not an approximation of it,
# so a model that follows it produces a file that loads without
# translation.
# 3. Run and verify it. `plan run` has no project-directory argument — the
# root is always the current directory, so run this from inside
# demo-project/. --authored applies the same harness guarantees `do`
# applies internally to a model-authored plan: on_failure is forced to
# rollback_plan, a tests.impacted check is injected if the plan doesn't
# already carry one, and a zero-step plan is refused outright rather than
# passing vacuously. --authored-by <name> records who authored it in the
# written report:
(cd demo-project && girder plan run ../plan.json --authored --authored-by claude-opus-5)
```
A passing run applies the edit to the real tree and writes a report under
`.girder/reports/`; a failing check rolls the tree back to `base_commit`
automatically, so a bad edit from an untrusted external model never lands
half-applied. `plan_schema()`'s exact shape (a `oneOf` discriminated union
per edit/check kind, matching `planfile::schema`'s deserializer field for
field) is what makes step 2 reliable — see gap 17 in
[`docs/core-gap-analysis.md`](docs/core-gap-analysis.md) for the defect this
closed and the round-trip test that proves it.
### Demo target: `demo-project/`, never `sample-project/`
`girder do` and `plan run --authored` both refuse `sample-project/` as a
target outright, with an error naming `demo-project/` as the place to run
instead:
```
$ girder do sample-project "uppercase greet's return value"
error: sample-project/ is a pinned measurement fixture (see gap 18/21 in
docs/core-gap-analysis.md) and refuses authored writes; run demos against
demo-project/ instead
```
`sample-project/` is a pinned baseline `tools/authoring_task_check.py` and
`tools/plan_executor_oracle.py` read against a specific clean source commit
for the graph-addressed-authoring-cost measurement corpus, not a scratch
target. A real (non-dry) authored write there mutates the same file the
measurement harness depends on — this happened twice, three days apart, and
cost a full day of debugging a broken referee before the fixture drift was
found; see gap 18 in `docs/core-gap-analysis.md`. `demo-project/` exists so
that never has to happen again: a small, disposable Python project nothing
under `tools/` or `docs/` reads, safe for real (non-dry) authored writes.
Read-only commands (`context`, `search`, `analyze`, `test-impact`) still work
against `sample-project/` — only the two commands that write are refused.
### The pipeline demo
`girder` (no args) walks the entire pipeline over stdout:
1. **Builds a semantic graph** from source with tree-sitter (the graph is the
source of truth; text is a projection).
2. **Dispatches the agent swarm** on a natural-language intent
(*"Add a multiply function to the math module"*). The graph-aware Planner reads
existing nodes before planning; the Coder generates each function, wires Calls
edges, and emits a FeatureComplete summary; Tester, Documenter, Refactorer,
SecurityAuditor, and Optimizer annotate in parallel.
3. **Runs predictive impact analysis** over the graph.
4. **Time-travels a deliberate bug**: records an execution trace via `sys.settrace`,
branches a what-if alternative (variable overridden at a specific step via
CPython's `PyFrame_LocalsToFast`), shows exactly where the two timelines diverge.
## Workspace
| Crate | Role |
|---|---|
| `aether-graph` | The living semantic graph: nodes/edges, impact analysis, `.aether` serialization, and convergent collaboration replicas. **Source of truth.** |
| `aether-builder` | tree-sitter → graph mapping, incremental edit sync, syntax-highlight spans. |
| `aether-ai` | `AiProvider` trait, offline `MockProvider`, OpenAI/Anthropic live providers, multi-provider `Router`, provider extension points. |
| `aether-agents` | The parallel swarm: message bus, orchestrator, 8 specialized agents. |
| `aether-debugger` | Recording interpreter, execution trace, branching timeline, what-if + AI root-cause. |
| `aether-dap` | Debug Adapter Protocol client/session layer with graph-aware breakpoint support. |
| `aether-extensions` | Strict declarative recipes, digest-bound grants, graph-native lifecycle, bounded UI and project contributions. |
| `aether-app` | The `girder` binary: every CLI subcommand, plus the egui/wgpu GUI behind feature `gui`. |
## Other systems: GUI, swarm, collaboration, debugger, extensions
Everything above (graph, source lookup, impact, conservative test selection)
is the core product. Girder also ships several larger, independent systems
built on the same graph — real and documented, but not part of evaluating
whether the core product is useful to you, so they're grouped here rather
than interleaved into the quickstart above.
```bash
# Agent swarm: preview what it would build, or dispatch it for real:
girder swarm-plan sample-project "add user authentication"
girder forge sample-project "add a subtract function"
girder do demo-project "add an exclamation mark to the farewell"
# Python execution tracer and DAP adapter:
girder debug script.py
girder debug script.py --what-if x=10 at 2
girder dap script.py --dry-run
# Declarative extensions and the built-in marketplace:
girder extension sample-project generate "show call impact" --approve
girder extension sample-project list
girder extension sample-project marketplace search impact
# Graph-native collaboration — see the full command set below:
girder collab init sample-project alice alice.aetherc
```
`forge` plans every candidate byte, checks conflict baselines, validates the
candidate in a copied workspace, runs Cargo build/tests when a manifest is
present plus configured validation commands, and only then journal-commits
the source projection and graph together.
`collab` exchanges semantic graph operations rather than text ranges. Each
human or agent replica has a validated actor id and causal version vector;
minimal idempotent deltas converge regardless of delivery order. Concurrent
deletes win, concurrent updates have a deterministic tie-break, and deleting
then recreating a node cannot resurrect edges from its old generation. RON
`.aetherc` bundles are reviewable; `.aethercb` bundles use compact bincode.
Init/sync reconciles source with the durable graph so graph-owned agent and
extension metadata participates instead of being discarded. Bundle saves use a
synced atomic replacement.
Membership is part of the causal operation history rather than a local address
book. An approved `collab fork` registers the invited actor in both the source
and forked bundles; if writing the fork fails, the source roster is rolled back.
`collab member add|remove ... --approve` records convergent add/remove
operations, concurrent removal wins, normal replica APIs reject new operations
after the local actor is removed, and membership changes invalidate stale
acknowledgements. A history has one genesis self-membership root: separately
initialized actors cannot self-invite through a relayed delta. Removal records
the highest counter observed for that actor; unseen later counters fail until
their context observes a causal re-add, so a removed offline actor cannot keep
extending a stale membership epoch. Version
1 and 2 bundles migrate conservatively by retaining the local actor, previously
acknowledged peers, and non-bootstrap actors already present in the causal
clock. Use `fork` to allocate a new actor replica; direct `member add` is for
re-authorizing an already allocated unique actor, since it does not create that
actor's bundle. Version 1-3 bundles load as explicit unsigned legacy history;
version 4 stores operation attestations without changing existing CRDT dots.
Live 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.
Strict identity sessions also give every retained non-bootstrap CRDT operation a
durable Ed25519 attestation. A delta importing a new operation, or a new
retroactive attestation for an already-known dot, triggers verification of that
actor's complete retained history before any bundle is replaced. The signature
binds the dot, causal context, and exact action, so action tampering, actor
forgery, unsigned relay, conflicting proofs, and replayed dot changes fail
atomically. Local legacy operations can be upgraded with `identity attest`;
`identity verify` audits a whole bundle against the local private identity and
peer trust store.
Key rotation is a causal operation signed by the previous key with a second
proof from the successor key. Verification walks this chain backward from the
currently pinned fingerprint, so a retired key remains valid for its historical
counters but cannot authorize later ones. Rotation operations are never removed
by compaction. Deterministic bootstrap snapshot operations remain an explicitly
pre-shared bundle baseline rather than pretending to have a human signature;
strict deltas cannot introduce new bootstrap history. Group-secret-only live
sessions and the unpinned `collab merge` workflow ignore incoming attestation
metadata, preventing an unauthenticated path from poisoning later strict
verification. Actor-key transparency beyond exact local pins is still a
separate layer.
The 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.
An optional `--discovery-dir` publishes an atomic, HMAC-authenticated,
process-bound lease for the loopback host. The current-user directory and
tickets must be private (new paths are mode 700 and 600 on Unix), symlinks are
rejected, each scan is capped at 256 entries, dead process ids on Unix and
actors outside the local bundle's active remote roster are ignored, and
`join-peer` refuses ambiguous same-actor tickets. A normal host shutdown removes
its unchanged ticket.
Tickets are only endpoint hints: PID reuse or a stale ticket cannot authorize a
session because the existing roster-bound mutual-authentication handshake still
decides every join.
`collab compact`
requires an acknowledgement from every active remote member, then prunes only
causally superseded operations while retaining concurrent winners, membership
removal barriers, and node-generation tombstones. Peers older than the recorded
history floor fail safely and need a current bundle. Network/continuous
discovery, continuous presence/subscriptions, encrypted remote transport, and
operation-level signatures/key transparency remain future work.
Group-secret-only migration mode remains a group credential: roster checks
reject an unlisted claimed actor, but any secret holder can impersonate an
active actor. Pinned identity mode prevents that endpoint impersonation after
fingerprints have been verified. It does not retroactively prove the author of
every historical CRDT operation: authenticated peers can relay the existing
multi-actor operation set, so provenance of stored history remains trusted at
the collaboration-group boundary until operations themselves are signed.
Every parsed module carries a bounded `file-v1` whole-file projection in the
semantic graph. `collab review` compares the remote and freshly reconciled local
graphs, lists file and semantic changes, and reparses every remote file to prove
its nodes and projection-derived edges agree with the claimed graph. Missing
modules, path escapes, oversized files, inconsistent concurrent winners, and
stale local baselines are conflicts. `collab apply --approve` reruns the plan,
executes configured validation in an isolated candidate, then journal-commits
added/modified/deleted files and the reconciled graph together. Native approval
is SHA-256-bound to every candidate and expected baseline byte, so any project
or bundle change forces another review.
The full `collab` command set, including the remaining subcommands
(`sync`, `merge`, `materialize`, `secret`, the full `identity` family,
`host`/`join`/`discover`/`join-peer`, `compact`, `review`/`apply`):
```bash
# Give another replica its own actor, record its current source graph,
# and deterministically merge it:
girder collab fork alice.aetherc bob bob.aetherc --approve
girder collab sync sample-project bob.aetherc
girder collab merge alice.aetherc bob.aetherc merged.aethercb
girder collab materialize merged.aethercb merged.aether
girder collab member add alice.aetherc carol --approve
girder collab member remove alice.aetherc carol --approve
# Exchange deltas in a mutually authenticated live loopback session
# (group-secret-only migration mode):
girder collab secret collaboration.secret
# Strict identity mode pins each roster actor to an Ed25519 key:
girder collab identity generate alice.aetherc alice.identity alice.identity.pub
girder collab identity generate bob.aetherc bob.identity bob.identity.pub
girder collab identity show bob.identity.pub
girder collab identity trust alice.trust bob.identity.pub --approve <bob-fingerprint>
girder collab identity trust bob.trust alice.identity.pub --approve <alice-fingerprint>
girder collab identity attest alice.aetherc alice.identity
girder collab identity attest bob.aetherc bob.identity
girder collab host alice.aetherc 127.0.0.1:7331 \
--identity-file alice.identity --trust-store alice.trust \
--secret-file collaboration.secret --discovery-dir .bitcode/peers \
--presence "reviewing parser changes"
girder collab discover bob.aetherc .bitcode/peers --secret-file collaboration.secret
girder collab join-peer bob.aetherc alice .bitcode/peers \
--identity-file bob.identity --trust-store bob.trust \
--secret-file collaboration.secret --presence "running transport tests"
# An explicit address remains available when local discovery is not in use:
girder collab join bob.aetherc 127.0.0.1:7331 \
--secret-file collaboration.secret \
--identity-file bob.identity --trust-store bob.trust
girder collab identity verify alice.aetherc alice.identity alice.trust
# Key rotation: generate a new pair, then record a dual-signed causal
# transition while both private keys are available:
girder collab identity generate alice.aetherc alice-new.identity alice-new.identity.pub
girder collab identity rotate-local alice.aetherc alice.identity alice-new.identity \
--from <old-alice-fingerprint> --approve <new-alice-fingerprint>
girder collab identity rotate alice.trust bob-new.identity.pub \
--from <old-bob-fingerprint> --approve <new-bob-fingerprint>
girder collab identity remove alice.trust bob --approve <new-bob-fingerprint>
# Once every active member has acknowledged superseded history, prune it:
girder collab compact alice.aetherc
# Rebuild remote whole-file projections, show changes/conflicts, then
# explicitly validate and journal-commit the reviewed bytes:
girder collab review sample-project alice.aetherc
girder collab apply sample-project alice.aetherc --approve
```
Full extension/marketplace command set:
```bash
girder extension sample-project generate "show call impact"
girder extension sample-project disable dev.bitcode.generated.show-call-impact
girder extension sample-project remove dev.bitcode.generated.show-call-impact
girder extension sample-project install recipe.json --approve
girder extension sample-project marketplace show org.bitcode.impact-navigator
girder extension sample-project marketplace adapt org.bitcode.impact-navigator
girder extension sample-project marketplace adapt org.bitcode.impact-navigator --approve
girder extension sample-project marketplace list --catalog marketplace/girder-extensions.json
```
Every flag above is also in `girder collab --help` / `girder extension --help`.
## The GUI
```bash
cargo run -p aether-app --features gui -- --gui sample-project
```
The 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.
The semantic graph is an interactive navigation surface rather than a static
diagram. Its retained force layout keeps positions stable while the graph
changes; pan/zoom, fit-to-view, text search, node/edge type filters, one- and
two-hop focus, viewport culling, and zoom-dependent labels keep large graphs
legible. At overview scale, implementation nodes and their relationships
collapse into weighted module-level connections; zooming in restores exact
types, functions, and enabled relationships. The overview ranks and bounds
module connections so the strongest architectural signals remain readable.
Selecting a node exposes its source location and agent metadata, and
double-clicking or choosing **Open source** moves the editor cursor to its span.
Editor saves use a recoverable journaled transaction for the source projection
and semantic graph. Dirty buffers guard project/file switches, saves detect
external source or graph changes, and startup rolls back an interrupted
multi-file commit before indexing. GUI agent runs mutate a checkpointed graph
and remain visibly pending while validation runs off the render thread. Commit
stays disabled until the exact graph snapshot passes candidate build/tests;
diagnostics remain inspectable and failed candidates can be revalidated or
rolled back. **Commit** projects generated functions to the configured output
file and persists the graph, while **Roll back** cancels validation and restores
the pre-run graph without touching source files.
The right workspace has separate **Agents**, **Extensions**, **Collaboration**,
and **Author** views. Extensions contains Generate, Marketplace, and Installed
tabs. Extension generation returns
a strict JSON recipe; installation stays disabled until the user reviews its
exact SHA-256 digest, capabilities, contributions, projections, and full JSON.
The marketplace searches bounded declarative catalogs, displays the catalog and
listing/reference-recipe fingerprints plus reviews bound to both, and
regenerates a listing intent against a bounded sample of the current semantic graph. Adapted
recipes preserve the listing ID and show every added/removed capability scope.
A catalog review never grants installation authority: the adapted recipe still
requires a fresh approval bound to its own exact digest.
Reviewer identities are catalog metadata rather than cryptographic signatures;
verify an external catalog's printed SHA-256 fingerprint through the channel
that distributed it.
The **Collaboration** view initializes, inspects, and synchronizes the full
workspace graph, generates private secrets, verifies bounded local discovery
tickets, and lets the user select an authenticated active-roster endpoint
before joining on a background thread so rendering never blocks. It shows
causal version/operation counts and the deterministic conflict policy, durable
acknowledgements, and compacted history floor; it can conservatively compact
acknowledged history. A live join updates the collaboration bundle only.
Optional identity controls generate an actor-bound key, display a peer's exact
fingerprint for out-of-band review, pin the unchanged public file, list trusted
actors, and make strict identity mode visibly distinct from legacy group-secret
mode. Explicit rotation/removal remains available in the CLI.
Separate Review and Apply controls keep remote graph-to-source projection
explicit, consistency-checked, digest-bound, validated, and atomic. CLI `host`
is the persistent serving surface.
The **Author** view exposes both authoring paths from "External authoring"
above without a terminal: type an intent, click **Search** to run the same
concept search `girder do`/`context` use (only the top-scored hit starts
checked — narrower than the CLI default on purpose, since gap 15 in
`docs/core-gap-analysis.md` exists to shrink what a model can touch), and
adjust the checkboxes to pin the exact nodes a plan may edit — the same
`--nodes` a terminal invocation would otherwise require typing full paths
for. **Local model** mode mirrors `girder do`: **Run** streams each
provider attempt into a live log and shows pass/fail plus the report.
**External model** mode mirrors `girder context` + `plan run --authored`:
**Copy context JSON** puts exactly what the CLI command would print onto the
clipboard, paste a model's plan response back in, and **Run authored**
applies the same guarantees (forced `rollback_plan`, the mandatory
`tests.impacted` check, zero-step refusal). A non-dry Run in either mode
requires a second, explicit confirming click — a GUI button that silently
writes to the tree has no command line to review first. Open `demo-project/`
to try the full loop for real:
```bash
cargo run -p aether-app --features gui -- --gui demo-project
```
Then, in the Author tab: type "add an exclamation mark to the farewell",
click Search, leave `crate::greeter::farewell` checked, and either click Run
(Local model) or use Copy Context JSON / paste a plan back in / Run authored
(External model) — Dry run stays checked by default in both, so nothing
writes to the tree until it's unchecked and confirmed. Like `girder do`
against a terminal, both refuse `sample-project/` outright; only
`demo-project/` (or another project you point it at) accepts a real,
non-dry Run.
Installed 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.
CI type-checks the `gui` feature on the stable Rust toolchain. Rendering needs a
GPU — or a software Vulkan adapter (Mesa **lavapipe**) plus the usual X11 libs
(e.g. `libxkbcommon-x11`). If no surface can be created the binary logs the wgpu
error and **falls back to the headless demo** automatically, so it never
hard-fails. It has been verified headlessly under `Xvfb` + lavapipe:
> The **default headless build, all tests, and `girder`'s demo require none
> of this** — no GPU, display, or extra system libraries.
## Local-first AI
The default provider is a deterministic, offline `MockProvider`, so everything
runs with no network and no API key. OpenAI and Anthropic are implemented live
providers behind the `live-providers` feature. OpenAI uses the Responses API and
is selected when `OPENAI_API_KEY` is set:
```bash
export OPENAI_API_KEY=sk-...
export OPENAI_MODEL=gpt-5.6 # optional; this is the default
cargo run -p aether-app --features live-providers -- forge sample-project "add a divide function"
```
Anthropic remains available as a second live provider:
```bash
export ANTHROPIC_API_KEY=sk-ant-...
cargo run -p aether-app --features live-providers -- forge sample-project "add a divide function"
```
The `Router` tries OpenAI first when configured, uses Anthropic as a secondary
live provider for planning/codegen, and falls back to the mock otherwise. Gemini,
xAI Grok, and local Ollama remain compile-clean extension-point structs; they
deliberately do not enter routing until their HTTP bodies are implemented.
## Status
Girder is a semantic-graph MCP server and CLI for coding agents. The native
GUI, agent swarm, and time-travel debugger are supporting components; the
measurements below describe the graph's current behavior and limits.
The checked
[Core Trustworthiness Measurement](docs/core-trustworthiness-measurement.md)
compares affected-test selection with isolated runtime execution. Its bounded
baseline measures both Rust and Python precision/recall at `1.000/1.000`
(the earlier `0.667` Rust precision defect is closed). That is a result on
small fixtures, not a representative-repository superiority claim — and the
counter-evidence is checked in alongside it: on a real dependency, a
polymorphic-dispatch mutation currently measures recall `1.000`, precision
`0.667` ([`docs/core-representative-mutations.md`](docs/core-representative-mutations.md))
— a 2026-10 fix stopped the selection from silently dropping the test when
the dispatch can't be resolved, falling back to the conservative union
instead; the underlying dispatch-resolution gap is unchanged, only the
silent-miss symptom is fixed. This is why test selection is documented as
advisory rather than authoritative.
Implemented features:
| Feature | What it does |
|---|---|
| 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 |
| Graph explorer | Retained force layout, pan/zoom, search and typed filters, neighborhood focus, LOD/culling, metadata inspection, source navigation |
| Agent swarm | Planner + Coder + Tester + Documenter + Refactorer + Optimizer + SecurityAuditor + QueryAgent |
| Intent-first planning | Planner reads the graph before planning; generates ordered `FeatureSpec` with Calls-edge wiring |
| Real Python tracer | `sys.settrace` execution recording, what-if branching via `PyFrame_LocalsToFast` |
| Knowledge-graph queries | Natural-language → concept / impact / callers / callees / explain / neighbourhood |
| Semantic review | Typed diff (added/modified/removed nodes + edges), impact radius, test gap report |
| Conservative test selection | Call-graph reachability from changed functions, optional `--run` |
| 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 |
| Project contract | Validated `girder.toml` for source scope, graph path, test runners, and agent output |
| Source projection | GUI/CLI agent output and graph rename commit validated source plus graph through recoverable journaled transactions |
| Candidate validation | Disposable project copy, optional bubblewrap isolation, Cargo build/tests, configured checks, cancellation/timeouts, bounded diagnostics, snapshot-bound commit gate |
| DAP integration | Two-phase DAP launch, graph-node breakpoints, stop/stack inspection, and real `debugpy` coverage |
| Declarative extensions | AI/JSON recipe generation, exact digest-bound approval, parameterized capabilities, graph-native records/contributions, GUI/CLI lifecycle, reversible validated projections |
| Generative marketplace | Bounded portable catalogs, deterministic fingerprints/search, digest-bound reviews, project-aware regeneration, exact capability deltas, CLI and native browser |
| 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 |
Optional DAP adapter smoke test:
```bash
python3 -m pip install debugpy
cargo test -p aether-dap --test debugpy -- --ignored --nocapture
```
The measured table-stakes comparison, current correctness evidence, and
prioritized open risks are maintained in
[`docs/core-gap-analysis.md`](docs/core-gap-analysis.md).
## License
Girder's source in this repository is licensed under the [Apache License,
Version 2.0](./LICENSE). That permits commercial use, modification,
redistribution, forks, and hosted use, subject to the license terms; `LICENSE`
is the authoritative text.
The previously published v0.3.2 npm package and release binaries remain under
the BUSL license they shipped with; published releases are immutable. The
current v0.3.3 npm package and release binaries ship with Apache-2.0.
There is no current paid tier, and every shipped tool is ungated: no account
or license key is required. Anyone who already holds a signed license key from
an earlier release keeps it working for whatever it unlocked then; the key
system itself (`GIRDER_LICENSE_KEY` or a per-OS key file, verified offline, no
phone-home) remains only for that historical compatibility.
Earlier releases remain under the terms they shipped with; this is not a
retroactive relicensing. See [`CONTRIBUTING.md`](./CONTRIBUTING.md) for
contribution terms.
Connection Info
You Might Also Like
No recommendations available