archbird
Map codebases. Verify architecture. Plan and apply structural changes.
Archbird scans a repository and builds a deterministic map of its files, symbols, dependencies, public interfaces, tests, build routes, and components. Use it to understand unfamiliar code, give coding agents focused context, enforce reviewed architecture constraints in CI, compare ports or frontends, and check that coordinated changes produced the required structural result.
JavaScript documentation · Python documentation · Open the browser app
# Python 3.9+
python -m pip install archbird
# Or Node 18+
npm install --save-dev archbird
archbird map . # map the current repository; npm: npx archbird map .
archbird serve # explore it locally; npm: npx archbird serve
Language support
All interfaces produce the same Map model. The C core provides portable lexical and Tree-sitter syntax analysis; the Python, Node, and browser hosts add the precision available in their own runtimes.
| libarchbird | archbird.js | archbird.py | archbird app | |
|---|---|---|---|---|
| C and C++ | ✓ Tree-sitter + lexical | ✓ Tree-sitter + lexical | ✓ Tree-sitter + lexical | ✓ Tree-sitter + lexical |
| Python | ✓ Tree-sitter + lexical | ✓ Tree-sitter + lexical | ✓ CPython AST + Tree-sitter + lexical | ✓ Tree-sitter + lexical |
| JavaScript, TypeScript, and TSX | ✓ Tree-sitter + lexical | ✓ TypeScript compiler + Tree-sitter + lexical | ✓ Tree-sitter + lexical | ✓ TypeScript compiler + Tree-sitter + lexical |
| R | ✓ Tree-sitter + lexical | ✓ Tree-sitter + lexical | ✓ Tree-sitter + lexical | ✓ Tree-sitter + lexical |
Lexical providers conservatively recover declarations, calls, and explicit protocols from source text. Tree-sitter adds syntax, scopes, imports, and exact spans. CPython AST and the TypeScript compiler add host-specific precision. SCIP is optional input for resolved definitions, references, and relationships; Archbird reads a supplied index but does not invoke an indexer.
Stages
| Stage | Question | Output |
|---|---|---|
| Map | What exists, and how is it connected? | Searchable files, symbols, dependencies, tests, and build routes |
| Query | Which exact evidence matters for this task? | Focused, ranked context with source witnesses |
| Path | How are two explicit architecture entities connected? | Bounded shortest witnesses with typed relations, direction, evidence, and completeness |
| Verify | Does the code follow the architecture constraints? | Constraint status, violations, code locations, and unknowns |
| Plan | What structural change follows from current evidence, and what remains unknown? | An editable language-neutral Plan with objectives, operators, applicability, and acceptance constraints |
| Act | How does that Plan ground into exact repository changes, and does its after-state pass? | An accepted, sealed Act bound to exact transitions plus fresh Map and Verification evidence |
Map builds the canonical repository IR. Architecture is normally scattered across source languages, packages, public interfaces, native/frontend bridges, tests, build systems, and generated artifacts. Map joins those facts once so every later stage works from the same files, symbols, relationships, and source locations. Provider-specific lexical, syntax, host-AST, and SCIP facts are normalized into this language-neutral intermediate representation without discarding their provenance or uncertainty.
Query and Path evaluate projections over the Map IR. Query selects, traverses, and ranks the small neighborhood relevant to one task. Path answers a narrower question: whether two explicit entities are connected and which relationships form the connection. They share typed projection and graph indexes, but neither operation rewrites the Map or promotes an uncertain relationship into a confirmed one.
Verify checks architectural intent against the complete relevant model. Each constraint compiles into exhaustive projections over the Map IR plus a predicate such as required symbols, allowed dependencies, acyclicity, parity, or a numeric bound. Verify never uses a ranked or truncated Query result. Its Verification artifact records pass, failure, or unknown together with the exact operands and source locations responsible.
Plan describes a structural transition. Archbird can derive a Plan from the Map IR, current Verification findings, and a requested goal, but a developer or agent may also author or edit one directly. The language-neutral Plan records ordered objectives, applicable transformation operators, acceptance constraints, source identities, and explicitly manual work; it does not contain unreviewed guessed code.
Act grounds and checks the Plan. Act combines the reviewed Plan with exact source bytes and executor input, produces candidate file transitions, and evaluates their isolated after-state through a fresh Map and Verify run. A passing result can be sealed as an accepted Act without touching the worktree. Apply is the only mutating operation: it revalidates every source lock and replays that accepted Act.
The stages therefore form one traceable pipeline:
providers ───────────────→ Map IR ──→ projections ──→ Query / Path
│
└─────→ constraints ──→ Verification
│
Map IR + Verification + intent ──────────┴──→ Plan (derived or authored)
│
source + executor input ───────────────────────────┴──→ Act candidate
│
fresh Map + Verify
│
accepted Act → Apply
Every output retains its source and configuration links. Missing, conflicting, incomplete, and stale information remains visible instead of being guessed away.
Command-line workflow
The CLI follows the product stages directly. Run it from the repository root;
archbird.json is discovered automatically when present.
Map a repository
archbird map .
archbird map . --view architecture \
--group-by component --level file --relations imports,calls
archbird map . --view tests --group-by directory
archbird map . --view evidence --detail full
map scans the configured/discovered scope and builds Archbird’s canonical
derived evidence model of files, symbols, dependencies, public interfaces,
tests, build routes, artifacts, and components. Unsupported inputs, unresolved
relationships, provider recovery, and other unknown frontiers remain explicit.
The default Markdown output is a readable architecture overview; use JSON when
you want to save the canonical Map for later commands.
Query focused context
archbird query . --symbol 'src/runtime.c:runtime_start' \
--depth 1 --test-depth 1 --max-chars 12000 --check
archbird query . --search 'provider registry' \
--search-limit 8 --max-chars 12000 --check
archbird impact . --path src/runtime.c --depth 2 --check
query loads or builds that Map, selects a starting point, follows its recorded
relationships, and returns a focused neighborhood. Use typed selectors such as
--symbol, --path, --component, --package, or --artifact when you know
what you are looking for. File ordering prefers routes with stronger evidence
state (current, then unknown, then stale) and semantic resolution before
distance. Each selected file exposes the
best route’s state, resolution counts, provenance count, and last hop; the
canonical Query still retains the underlying candidate edges and their full
evidence. Repository discovery/completeness remains a separate property rather
than an edge-confidence score.
query --search helps find that starting point when you do not know its exact
path or symbol. It ranks lexical matches from repository names, paths,
signatures, descriptions, and package metadata, then runs the same focused
Query from those candidates. It tolerates prefixes, substrings, and small
typos, but it does not interpret a natural-language question or turn a text
match into a proven code relationship.
Query selectors accept exact or partial symbols, paths, mapped directories,
globs, layers, components, tests, packages, artifacts, builds, provider
surfaces, parity surfaces, and named entries. query is bidirectional by
default; impact starts upstream. Occurrence-backed symbol relations are used
before conservative file expansion.
--search KEYWORDS is deterministic lexical retrieval for cases where you do
not yet know a path or symbol. Use concise repository vocabulary such as
provider registry; it does not interpret questions, intent, or synonyms. It
ranks candidate symbols, files, components, packages, and artifacts from names,
paths, signatures, component descriptions, and package metadata, shows the
exact field and match behind every score, then expands the selected candidates
through the same typed graph. Prefix, substring, and bounded typo matches are
advisory seeds; they never become semantic edges or make a constraint pass.
Prefer --symbol, --path, or another typed selector once you know the target.
Symbol neighbors reached only from advisory seeds do not strengthen a static
test route.
Focused test routes keep file distance and symbol-hop distance separate. A case that calls a wrapper reached from the requested symbol is labeled with that wrapper and its hop distance; another case in the same file is not promoted merely because the file is nearby. Static routes remain candidates until reviewed configuration or imported per-test observations provide stronger evidence.
query --view changes uses the same complete Query artifact and ranking policy,
but presents it as a coding packet: change seeds, affected code, strongest
routes, ranked tests, packages/builds/artifacts, explicit uncertainty, and a
ledger of collapsed evidence. It does not infer an edit or change the canonical
Query.
--git-diff REVISION asks the host CLI for Git’s tracked name/status changes
and passes a typed change set to the same core Query operation. Current paths
seed the architecture neighborhood; deletions and paths outside the Map remain
visible instead of being invented as current code. External diff drivers and
text-conversion commands are disabled. Untracked files require an explicit
--path until they enter Git’s diff.
--verification-result PATH adds the architecture constraints and findings
whose subject-side source paths overlap the selected change. The brief shows
their constraint IDs, requirement IDs, owners, severity, source paths, and whether
the verification input and producer still match the current Map. It does not
rerun verification, match reference-only evidence, or treat a path-free constraint
as relevant.
The default is an architecture-first overview for a person or coding agent; canonical JSON still contains every selected file and mapped fact. Choose the human projection and its amount of detail independently:
archbird map --view overview --detail compact
archbird map --view architecture \
--group-by component --level file --relations imports,calls
archbird map --view tests --group-by directory
archbird map --view evidence --detail full
archbird query --symbol runtime_start --view source
archbird query --symbol runtime_start --dump
--view selects a question-oriented preset. overview includes project
landmarks and broad package/build/test connections; architecture emphasizes
code dependencies; tests isolates test routes; and evidence exposes
coverage, diagnostics, and completeness. --group-by reorganizes the same
selected entities by directory, configured component, layer, or language.
--level chooses component, file, or symbol nodes. --relations overrides the
preset’s relation families and accepts comma-separated values or repeated
flags. These semantic axes compile to one exhaustive graph ProjectionPlan and
the resulting typed ProjectionResult drives both Markdown and the application.
--detail changes rendering density only. --compact and --full are aliases
for its corresponding values. --max-chars is a final presentation guard; it
never changes the canonical Map or turns incomplete evidence into success.
Compact and standard Markdown rank structural groups, aggregated dependency
flows, and file landmarks while reporting what the presentation omitted. File
landmarks use separate bounded production/API, test/fixture, and build/artifact
shortlists, followed by an unresolved-import frontier. Classification consults
the Map’s file-role evidence first and then conservative repository-path
conventions. Build outputs/tooling and third-party/generated candidates take
precedence over test candidates, while participation metadata such as
artifact-input does not by itself demote production source. Visible relation,
degree, and symbol counts are orientation signals rather than correctness
claims. Standard dependency rows show at most eight relation kinds and disclose
the omitted and total counts. Diagnostics retain their exact canonical cause
count; recognized Tree-sitter recovery and missing node messages are additionally
summarized by language and parser action, with node-count ranges and
representative paths. Other diagnostics remain grouped by exact severity, code,
and message. --detail full enumerates the exhaustive selected graph records
instead. Dependency flow is shown provider to consumer; the underlying canonical
relation remains consumer to provider (A uses B).
Graph completeness and repository coverage are reported separately. A graph can
exhaustively represent every selected supported fact while discovery still
reports unsupported, ignored, oversized, or otherwise unknown repository
inputs. Presentation omissions never change either classification.
Query context profiles (exact, change, architecture, audit), per-kind
quotas, route provenance/confidence, and candidate/conservative policies remain
separate Query behavior.
--view source materializes source bytes selected by the Map or Query instead
of storing source text in the canonical artifact. Compact detail is an indexed
declaration outline. Standard detail expands exact declarations matched by a
symbol Query, returns a complete directly selected file for a path Query, and
leaves related files as outlines. Full detail returns every selected file;
--dump is an alias for --view source --detail full. Full source cannot be
combined with --max-chars, because silently dropping part of a requested dump
would make it misleading.
Every emitted file is matched by repository-relative path and SHA-256 against the Map before its bytes are rendered. A saved Map therefore needs the source checkout explicitly:
archbird query --map .archbird/map.json --root . \
--symbol 'src/runtime.c:runtime_start' --view source
archbird query --map .archbird/map.json --root . \
--symbol 'src/runtime.c:runtime_start' --dump \
--output .archbird/runtime-start-source.md
When a provider cannot establish an exact declaration extent, standard source shows the indexed outline and states that exact source is unavailable; it does not guess where the declaration ends. Non-UTF-8 bytes and terminal control sequences are hash-validated but are not embedded in Markdown. When valid semantic-AST and concrete-syntax extents differ, the concrete source boundary is canonical for rendering while every alternate boundary and provider remains recorded in the merge-variation ledger.
Find a connection with Path
archbird path 'src/cli.c' 'src/runtime.c' --root . \
--relation calls --direction downstream
path SOURCE TARGET resolves exact or glob-shaped endpoint sets and finds
globally shortest witnesses over the Map’s exhaustive typed graph projection.
It preserves parallel relation kinds, traversal direction, evidence state,
semantic resolution, and provenance. found requires an all-current,
source-evidenced route and prefers it even when a shorter candidate shortcut
exists. When only candidate/unknown relations connect the endpoints, Path
renders those witnesses as unknown with reason candidate-witnesses, and
--check fails. A missing route is reported as absent only when the selected
graph and bounded search are complete; unresolved endpoints, unsupported
evidence, or a depth frontier remain unknown.
Add --check when a script specifically requires a proven found result.
Repository-dependent examples omit it because an honest unknown is a valid
answer.
Rendering a saved Path validates its exact artifact shape, content digest, and
cross-field proof invariants before producing Markdown. A current witness
requires current endpoints and relations, nonempty relation evidence, and
unique, builtin, or not-applicable resolution; the renderer never trusts an
outcome label by itself.
Verify architecture
Reviewed architecture policy belongs in the constraints collection of the
same archbird.json that defines project structure. Typed constraints infer
their exhaustive Map projections; primitive assertions can use inline literals,
observations, or named/inline projections. The complete
quickstart.archbird.json combines these
stages and needs no second suite file.
For a first check in an unfamiliar repository, configuration may contain only the reviewed constraint; discovery supplies the project model and layers:
archbird verify --config - --check <<'JSON'
{
"constraints": {
"NO-LARGE-SOURCE": {
"kind": "max_file_bytes",
"include": ["src/**"],
"max": 1048576,
"owner": "architecture",
"rationale": "Keep source files reviewable."
}
}
}
JSON
The same fragment can be saved unchanged as archbird.json. Explicit
project-model sections replace discovery; omitted sections inherit it.
# Run one saved Query plan or an ad-hoc query.
archbird query public-api-impact
archbird query --symbol demo_open --direction upstream
# Evaluate the whole reviewed policy or one named constraint.
archbird verify --check
archbird verify CORE-PUBLIC-API --check
# Preserve exhaustive repository-inventory operands when verifying a saved Map.
archbird verify --map .archbird/map.json \
--resolution .archbird/resolution.json --check
# Emit CI-native reports from the same constraints.
archbird verify --format sarif --output .archbird/architecture.sarif --check
archbird verify --format junit --output .archbird/architecture.junit.xml --check
# Freeze reviewed existing debt and coverage as a ratchet.
archbird verify --freeze .archbird/architecture.baseline.json \
--freeze-owner architecture \
--freeze-rationale "Reviewed starting point"
verify without IDs evaluates every configured constraint. Positional IDs
select an explicit subset and the Verification artifact records configured,
requested, evaluated, and omitted counts; a successful subset is never reported
as whole-policy compliance. Unknown IDs are errors. The CLI defaults to a
human-readable Markdown verdict; use --format json when saving the canonical
Verification artifact. Repository selection is
execution context: run in the project root or use --root PATH; an external
configuration uses --config CONFIG --root PROJECT. Query and Impact also
accept an unambiguous path-shaped positional root, such as
archbird query . --symbol demo_open.
archbird impact ../project --path src/api.c works similarly. A bare
positional token remains a saved query ID; use ./project rather than
project when selecting a relative repository path.
A saved Map contains mapped facts, not the complete discovery inventory.
Pass its matching config show artifact with --resolution when constraints
depend on ignored, unsupported, oversized, or forbidden repository paths.
Archbird validates the Map/resolution identities and rejects a mismatched pair.
Live verify derives both from one repository state automatically.
Common typed constraints cover required/forbidden paths and symbols, file-size bounds, symbol cardinality, component membership and cycles, allowed/forbidden/ required component or file edges, package entrypoints, bridges, test routes, and provider surfaces. They require no projection boilerplate. General predicates cover set/value equality, mapped equality, directional subsets, cardinality, numeric bounds, graph edges, acyclicity, minimum test routes, and observation equality.
provider_surface normally treats configured providers as one combined
declaration surface. Set require_all_providers: true when every capability
must appear in every configured provider, such as a public header and a Wasm
export list. Verify then reports the exact missing provider witnesses instead
of accepting a declaration found only on another surface.
A projection result is exhaustive for its declared Map domain. If discovery, provider, resource, freshness, or source-lock evidence prevents a complete answer, the operand is partial or unknown and cannot make a constraint pass. Query may rank and bound context; Verify may not. Derived Map facts, asserted literals/mappings/waivers, and observed runner evidence retain distinct provenance.
Named projections are reusable configuration for constraints and queries, not a separate required CLI stage. One-off primitive operands stay inline:
{
"constraints": {
"API-SIZE": {
"assert": "cardinality",
"actual": {
"projection": {
"select": "symbols",
"paths": ["include/**"],
"public_only": true
}
},
"max": 30,
"owner": "core",
"rationale": "Keep the supported native surface reviewable."
}
}
}
Constraint-owned waivers require an ID, owner, rationale, an exact finding
fingerprint or comparison/key pair, and an expiry date or input-digest boundary.
Baselines classify new, known, reintroduced, and resolved findings while
ratcheting covered facts. Cross-repository constraints receive explicitly named
saved Maps with --map-input ID=PATH; behavioral parity receives reviewed
artifacts with --observation ID=PATH. Similar names alone never establish
semantic equivalence.
Every constraint has a stable ID, owner, rationale, optional requirement IDs, tags and severity. Findings cite exact evidence and separately record comparison, evidence state, applicability, disposition, baseline state, and a stable fingerprint. JSON, Markdown, SARIF, and JUnit are views of the same canonical Verification result.
Add observed test evidence
Static test routes are candidates. observe converts project-owned per-test
coverage reports into exact runtime test-to-symbol evidence:
archbird observe . --map .archbird/map.json \
--request .archbird/coverage-request.json \
--output .archbird/test-symbols.json
archbird query --symbol runtime_start \
--test-symbol-observations .archbird/test-symbols.json
Python supports coverage.py JSON with dynamic test contexts; Node supports V8
JSON. Both hosts support isolated Istanbul, llvm-cov export, and gcov JSON.
Formats without per-test contexts require one isolated report per case.
Archbird checks source hashes and rejects aggregate coverage that cannot prove
which test produced a hit; it never runs the tests or coverage tools.
Plan, Act, and Apply
Plan evaluates the complete current Verify policy and derives one editable artifact. Omit the constraint name to include every current issue, or scope generation by existing constraint ID:
Build and behavioral acceptance commands are stable project policy. Define
them once as direct argument arrays in archbird.json; Archbird never invokes
a shell:
{
"gates": {
"build": {
"argv": ["cmake", "--build", "build"],
"timeout_seconds": 600
},
"focused-tests": {
"argv": ["ctest", "--test-dir", "build", "--output-on-failure"],
"depends_on": ["build"],
"timeout_seconds": 600,
"max_output_bytes": 1048576
}
}
}
Every configured gate runs over the same copied after-state used to build the acceptance Map. Dependencies provide a deterministic order and allow build outputs to feed later tests. Any failure, timeout, output-limit breach, or blocked dependency rejects the Act before the working tree is changed. The accepted Act seals each normalized definition, status, duration, environment identity, complete output digests, bounded output tails, and the initial after-state workspace identity. These are trusted reviewed commands with source isolation and provenance, not an operating-system security sandbox.
# Inspect the current task DAG without saving a second artifact.
archbird plan --format markdown
archbird plan --output .archbird/plan.json
archbird plan CORE-PUBLIC-API --output .archbird/plan.json
# Review a derived rename candidate, then assert the intended transformation.
archbird plan CORE-PUBLIC-API --rename old_api=new_api \
--output .archbird/plan.json
# Derive residual work from a committed base without changing the worktree.
# ...developer or agent partially changes the implementation and consumers...
archbird plan FFI-SURFACE --git-diff HEAD \
--output .archbird/plan.json
# Or save an explicit Map before work begins.
archbird map --format json --output .archbird/before-map.json
# ...developer or agent changes the implementation and consumers...
archbird plan FFI-SURFACE --before-map .archbird/before-map.json \
--output .archbird/plan.json
# Ground, verify, and inspect the exact Act without writing.
archbird act .archbird/plan.json
# Supply reviewed implementation semantics for exact unresolved items.
archbird act .archbird/plan.json \
--submit IMPLEMENT_ITEM=reviewed-module.py \
--submit TEST_ITEM=reviewed-test.py
archbird act .archbird/plan.json --format patch
archbird act .archbird/plan.json --format json \
--output .archbird/act.json
# Replay only the accepted Act after review.
archbird apply .archbird/act.json
Plan’s target contract is language-neutral: it names architectural objectives,
operators, exhaustive applicability, dependencies, executor capability, and
acceptance without embedding source syntax or replacement bytes.
When a reviewed constraint identifies one exact missing symbol or test route
but does not determine implementation code, Plan retains that target as a
structured non-executable add_symbol or add_test_route operation instead
of reducing it to an opaque manual note. This lets Plan order a semantic
implementation before its declaration and its tests while continuing to state
that Act has no authorized source transformation. A developer or agent may
submit reviewed full-file content for one exact add_symbol destination, or
for an add_test_route item when Map identifies exactly one file in its
reviewed test group, with repeatable act --submit ITEM=FILE. The symbol
destination may be an existing mapped file or a missing exact path. The Plan
remains byte-identical and language-neutral; the native Act core observes the
destination, chooses an exact create or replace transition, records
read/write/match evidence, builds one real isolated after-Map, and rejects the
entire Act unless the original and preserved constraints pass. A missing
definition, declaration, and test route can therefore form one useful
agent/developer task DAG without Archbird inventing a signature, body, or
test. plan --format markdown renders that same canonical Plan as a review
packet; it does not create another artifact. Absent or ambiguous test
locations remain manual.
An exact missing path from required_paths similarly becomes a path-only
create_file objective. Plan does not embed the future file bytes. Supply
reviewed content with act --submit ITEM=FILE; native Act requires the
destination to remain absent, previews one exact creation, and accepts it only
when the isolated after-Map closes the constraint.
An exact missing required_file_edge similarly becomes an input-required
add_dependency objective containing only the source path, target path,
relation kind, and optional relation name. A reviewed source-file submission
must produce that edge in the fresh Map; an unchanged or unrelated edit is
rejected with zero worktree writes. Plan also records an exhaustive
source-scoped file_edges projection and the one permitted item-key addition.
Act compares the real before/after ProjectionResults and rejects any extra
dependency addition or removal even when the selected constraint passes.
An exact current forbidden_file_edges violation between two mapped files
becomes the symmetric input-required remove_dependency objective. Plan
records the exact source, target, and relation without choosing replacement
semantics. Reviewed source content must remove the forbidden relation from the
fresh Map; preserving the edge rejects the complete Act with zero worktree
writes. The same source-scoped delta contract permits only that one edge
removal, so deleting an unrelated import is rejected independently of
constraint closure. Aggregated component edges, incomplete evidence, and
external or unmapped targets remain on the reviewed redirect/manual path.
redirect_dependency and declare_symbol currently follow this boundary end
to end. Given reviewed --redirect OLD=NEW intent, Plan stores the exhaustive
edge ProjectionPlan, exact relation, affected source paths, and symbol
identities. Act reevaluates that projection once and dispatches its typed
evidence by mapped source language. The native C executor resolves exact
declarations, definitions, include spelling, and call sites. The native Python
executor resolves one exact imported binding and its CPython-AST calls, uses an
already observed import-module spelling for the replacement, and preserves an
explicit local alias. The native ECMAScript executor supports JavaScript,
TypeScript, and TSX named imports when Tree-sitter proves the binding and the
TypeScript compiler proves every redirected call. It uses a replacement module
spelling already observed from the same source directory and preserves explicit
aliases, including aliases whose local name equals the old imported name. The
Node frontend supplies the required TypeScript evidence by default; a
syntax-only Map is rejected. Incomplete projections, ambiguous definitions,
missing observed include/import routes, multi-name imports, non-call
references, and non-unique call sites block Act instead of producing partial
edits.
Low-level asserted operations currently include replace_range,
delete_file, move_file, and edit_json_pointer. They are useful for
bounded edits supplied by a developer or agent, but are not the model for
derived Plan operations. create_file, add_dependency, and
remove_dependency are
language-neutral, input-required Plan objectives; exact content belongs to Act
submission.
A one-extra/one-missing symbol constraint may suggest a rename, but that does
not establish intent: the derived candidate stays non-executable until a
developer or agent supplies --rename OLD=NEW. The reviewed command evaluates
one exhaustive symbol_occurrences projection seeded by the constraint’s
selected declaration paths. Plan stores only the language-independent symbol
objective, normalized ProjectionPlan identity, and repository-relative source
scope. Act reevaluates the projection, requires identical complete evidence,
and lets the native Python or ECMAScript executor validate and materialize
exact declaration, import, export, binding, and reference edits. Unrelated
same-name declarations outside the selected scope are not renamed. Qualified
identities may rename only their terminal identifier while preserving the same
enclosing identity. Python coverage includes exact same-module references,
qualified imported-attribute references, and literal __all__ export tokens;
ECMAScript reference sites require TypeScript-compiler evidence. Public alias
or CommonJS assignment targets are separate reviewed surface identities and
are not rewritten as though they were internal declaration occurrences.
For an exact provider_surface issue, Plan can add a missing configured Make
registration, C header file_pattern declaration, or bounded C/N-API
exports registration. It can also use reviewed --rename OLD=NEW intent to
replace a stale Make entry when the target resolves uniquely. Each provider
definition has a canonical digest in Map and Plan, so distinct definitions
over one path do not collapse into one identity. Plan records the neutral
provider objective and bounded source scope; it stores no Make token, C
signature, export-table syntax, anchor, source hash, byte range, or replacement
text. Act validates the provider digest against the current configuration and
Map. Act/Make derives the token spelling and requires one registration anchor.
Act/C rederives a single-line declaration from the exact implementation and an
existing declaration peer. For an exports addition it requires one effective
mapped C file, one mapped napi_<capability> wrapper, syntax-clean source,
and an existing mapped DECLARE_NAPI_METHOD or N-API descriptor peer; it
clones that peer while preserving multiline layout and line endings.
Selectors that map the provider to multiple files, active uses of stale
entries, unresolved targets, ambiguous implementations, missing anchors,
multiple token matches, and distinct provider definitions that would require
one coincident source edit remain manual or are rejected by Act.
If the replacement is already registered by that provider, Plan normalizes
the target state to removal of the stale old registration instead of
proposing a duplicate.
For an exact required_package_entrypoint failure with one npm package and a
literal package-relative target, Plan emits the language-neutral
set_package_entrypoint objective. Act’s native JSON executor grounds main,
direct exports, and existing-object bin routes through the lossless JSON
Pointer editor, then requires the fresh after-Map to close the original
constraint. The target must be an existing regular file but need not be a
mapped source file; extensionless npm executables are therefore supported.
Act resolves it relative to the package manifest and seals its exact
read-only source state. Conditional or nested exports, ambiguous package
selectors, missing targets, and route shapes that would require replacing an
existing object remain manual. Plan contains the package route and target,
not JSON syntax, byte offsets, or replacement text.
--before-map OLD.json can derive the same provider registration replacement
without asserted rename intent when an observed partial migration proves it.
The old surface member must have been uniquely resolved in the before Map; the
current old registration must be unused and unresolved; and exactly one new
current member must retain the same implementation paths and use ledger with
declaration and implementation signatures differing only by the symbol name.
Both Maps must share project, configuration, and producer identities and have
no error diagnostics. Plan and Act retain both Map identities. Missing
signatures, incompatible histories, or multiple matching targets do not
authorize an edit.
--git-diff REVISION constructs that before Map from one verified Git commit
in an isolated raw-object snapshot under Archbird’s cache directory, using the
current project configuration and ordinary discovery/provider pipeline. It
does not run checkout filters and never checks out or writes the source
worktree. The option accepts a commit, not a revision range, and cannot be
combined with --map or --before-map. The temporary snapshot is removed
after its canonical Map is built; unchanged provider facts remain eligible for
the normal content-addressed cache.
When a constraint itself requires a missing surface member, that reviewed
policy supplies the intent. If the member has one implementation candidate
and is already declared by another provider or has current uses, Plan derives
one add_provider_capability item per missing supported provider without
another flag. An exact C/N-API export may instead use the current bridge use
plus the uniquely mapped wrapper in its configured provider file. A C
declaration item precedes its Make or export registration for the same surface
member. Both the missing and unregistered findings remain origins, and
every generated item is explicitly derived. Incomplete evidence, ambiguous
implementations, unsupported provider kinds, or colliding edit targets remain
manual.
When several reviewed surface members are missing from the same Make provider, Plan emits one item per obligation and Act composes their distinct insertions into one source-locked file transition. Composition is limited to the same variable, anchor, and side; tokens are ordered canonically. Byte-identical edits produced by separate Plan obligations also compose once while the transition retains every originating item ID. Coincident edits with different effects remain conflicts.
For a required_symbols constraint scoped to one exact C header, Plan can
derive the neutral declare_symbol objective when one same-language mapped
definition establishes a bounded two-file evidence scope. Plan records only
the destination, symbol, and source paths that the executor may read. Act/C
then requires an existing declaration/definition peer and rederives the exact
single-line implementation signature and placement from those hash-checked
sources; no C syntax, byte range, source hash, or anchor is stored in Plan. It
preserves indentation and line endings. Globs, multiple implementations,
missing peers, multiline or internal definitions, header-only decoration
differences, and source comments at the insertion anchor remain manual or are
rejected. This can be combined with a missing Make registration in one Plan
and accepted as one two-file architecture change.
An unresolved, unused registration can likewise become a derived removal when the Map proves zero implementation candidates, zero uses, one exact Make declaration, and at least one other uniquely resolved declaration from the same provider. The last guard prevents Plan from emptying a configured provider or treating two stale entries as proof for each other. Mixed replacement cases, active or ambiguous entries, duplicate token spellings, and removals that do not close the complete constraint remain manual.
An asserted edit_json_pointer operation handles reviewed manifest and export
table changes without replacing or reformatting the whole file. It names one
source-locked file, one RFC 6901 pointer, the exact expected old JSON value (or
explicit absence), and the replacement value. The native core rejects stale
hashes, duplicate keys, missing parents, ambiguous expectations, and invalid
JSON, then returns one exact byte edit. Archbird does not derive this
representation-level intent from a generic architecture finding.
The native provider executors ground add_provider_capability,
remove_provider_capability, and rename_provider_capability. Act/Make
preserves assignment operators, comments, continuations, whitespace, and
unrelated variables. It handles direct tokens only; variable expansion is not
inferred. Act/C supports the bounded header and N-API forms above. Zero,
duplicate, ambiguous, stale, multi-file, or syntax-recovered matches block the
Act. Unified-diff text is selected with
archbird act PLAN --format patch; it is only an Act rendering, not another
artifact or lifecycle stage.
The CPython provider establishes Python declaration, binding, and reference sites. Tree-sitter establishes ECMAScript declarations and import/export bindings; the TypeScript compiler must establish ECMAScript reference targets, including aliased import origins without rewriting their local aliases. Candidate or unresolved calls, duplicate targets, unsupported inputs, and lexical-only C/C++ call binding prevent Act from producing a partial edit.
Existing sources are locked by SHA-256; ranges use UTF-8 byte offsets and include the expected text. Multiple range edits to one file become one atomic file transition and one unified diff. Paths must be canonical repository-relative paths. Symlinks, non-regular files, overlapping edits, stale hashes, conflicting destinations, and dependency cycles block before the first write.
Verify evidence often establishes a required state without establishing the
code that should implement it. Plan records those cases as non-executable
manual items with candidate paths and explicit unknowns. Act refuses to apply
until every item has a reviewed executable operation; it never invents a
function body, replacement dependency, package target, or test.
For file and component dependency issues, the exhaustive edge projection also retains each exact inducing import, include, call, or semantic-reference site. An exact mapped forbidden file edge can therefore retain a neutral removal objective. Broader issues produce a manual item exposing sites with fact identity, line, UTF-8 byte range, expected text, and source SHA-256 when the provider supplies a nonempty editable span. A zero-width semantic anchor remains explicit evidence and a non-executable reason, not a fabricated text edit. This bounds the locations a developer, agent, or structured executor must inspect without pretending that an aggregated forbidden edge determines its intended replacement route.
Act first rebuilds the current Map and Verify result. Their project,
input, configuration, producer, policy, and result identities must match the
Plan’s source snapshot. Act then applies the prepared create/modify/delete/move
set to an immutable source overlay, reruns discovery and providers from those
bytes, and evaluates the union of item acceptance constraints and preserved
constraints against that isolated after-Map. A not_satisfied, unknown, or
evaluation failure emits no accepted Act and performs no worktree write.
Satisfied acceptance seals the exact Act bytes and after-state identities.
Apply observes every affected path and native preflight classifies the whole
Act as ready, already satisfied, partially applied, or drifted. A complete
after-state replay succeeds with zero writes; partial application and drift
fail. Ready bytes are replayed transactionally under an exclusive
repository-local lock. Commit failures restore only Act-owned paths;
concurrent changes to those paths are detected and never overwritten.
Archbird does not run project compilers or tests; configure test observations
and build evidence when those results must participate in Verify.
Destructive generated items require a current, complete, exhaustive relation projection. Unresolved imports or other relation frontiers make the item non-executable rather than allowing an apparently unused file or symbol to be removed. Every constraint in the source Verification is checked against the isolated after-state before commit, including constraints that passed when the Plan was generated.
Plan ingestion is bounded before expensive work: 64 MiB for canonical Plan JSON
and each source, 4,096 items or touched files, 16 MiB per operation text field,
256 MiB aggregate touched source and patch, 64 MiB per file patch, and 64 KiB
per metadata string. Source coordinates stop at JavaScript’s exact integer
limit (2^53 - 1) so Python and Node consume the same Plan.
Explore the live repository
archbird serve
archbird serve --no-config
archbird serve --root ../project
serve starts a browser-based architecture explorer and immediately prints its
loopback URL. Use it to expand selected components into files and selected files
into symbols while the rest of the architecture stays collapsed; inspect typed
connections and source witnesses; overlay configured constraint coverage and
findings; run focused queries; and compare Map snapshots as the repository
changes. Analysis progress is visible from the first page render. If an update
fails, the explorer reports the failure and keeps showing the last valid Map
and generation-matched Verification.
archbird serve
archbird serve --no-config
archbird serve --root ../project
serve prints a loopback URL immediately, analyzes in a worker, publishes only
valid generations, and retains the last good Map when a later candidate fails.
Live Map, Query, projection, Verify, and graph-view work runs in the server’s
native Archbird core; the page does not fetch browser Wasm for live repository
exploration. Wasm is reserved for the static app’s local folder/ZIP and saved
artifact workflows.
The application provides:
- useful zero-config exploration from the same exhaustive graph
ProjectionResult used by Markdown: switch overview, architecture, tests, and
evidence views, then independently group by directory, configured component,
layer, or language; configured components and constraints refine the graph
when
archbird.jsonexists but never gate the zero-config path; - one mixed-resolution architecture graph: double-click, press Enter, or use the inspector to expand a component or inferred layer through directories into files, then expand one file into symbols while unrelated groups remain collapsed; collapse, hide, and restore controls are presentation state and never rewrite Map or Projection evidence;
- entity-type colors, generation-matched constraint/finding overlays, keyboard navigation, pointer-centered normalized wheel zoom, slider zoom, layout direction, evidence-class, and edge-kind controls; selecting never changes the viewport, while expanding animates children from the activated node and keeps that node at the same screen position; dependency arrows default to provider → consumer flow and can switch explicitly to consumer → provider uses;
- compact node and edge hover details for identity, relation counts, evidence, and verification state; external symbol relations stay at the file frontier until explicitly revealed for one symbol;
- graph-local filtering plus focused typed or lexical Query from the current canonical Map;
- exact source witnesses for live repositories, retained last-good evidence, repository snapshots, and structural comparison between saved generations;
- canonical artifact and graph-view JSON downloads plus GraphML and Mermaid graph exports;
- task-oriented Diff and change-artifact summaries, Verification finding review with explicit waiver candidates, and project-configuration review;
- system, light, and dark themes with responsive graph and inspector layouts.
The same application can run statically on GitHub Pages. A browser can open a
saved artifact, local directory, or ZIP and analyze supplied files through the
Wasm Worker without uploading source or requiring a server. Directory input
passes path/size metadata and discovery documents through native discovery
before reading selected source bytes, so default-excluded dependency/build
trees do not fail merely because they contain large binaries. Saved artifacts
do not contain repository source bytes, so source viewing is available only
while a live server or browser repository session owns those bytes. Browser
directory and ZIP inputs are explicit snapshots rather than watched filesystem
handles; reload changed input to create another generation.
Server mode evaluates Map and ProjectionPlans in the native Node/Python host
and sends typed ProjectionResults to the page. Normal live exploration does not
download the canonical Map; Save canonical artifact fetches those bytes
explicitly. Static folder/ZIP and saved-Map workflows evaluate the same plans
in the browser Wasm host. A successfully
mapped repository with no supported source files shows an explicit empty-scope
state rather than a blank graph.
Reuse saved evidence safely
Save complete evidence when subsequent operations must use the exact same repository state:
mkdir -p .archbird
archbird map . --format json --pretty \
--output .archbird/map.json --check
archbird config show . --pretty \
--output .archbird/resolution.json --check
archbird query --map .archbird/map.json \
--symbol 'src/runtime.c:runtime_start' --depth 1 --max-chars 12000 --check
archbird query --map .archbird/map.json \
--search 'provider registry' --search-limit 8
archbird impact --map .archbird/map.json \
--path src/runtime.c --depth 2
archbird path 'src/cli.c' 'src/runtime.c' \
--map .archbird/map.json --relation calls --direction downstream
archbird query --map .archbird/map.json \
--symbol 'src/runtime.c:runtime_start' \
--view changes --detail compact --check
archbird query --git-diff HEAD \
--view changes --detail compact --check
archbird query --git-diff HEAD --view changes \
--verification-result .archbird/verify.json --check
Archbird excludes .archbird/** by default, so saving generated artifacts
there does not change repository discovery or freshness. Use
--no-default-excludes only when that tool-output tree is intentionally part
of the analyzed scope.
Plain saved-Map queries accept every supported Map schema even when another
Archbird core produced the artifact. Add --check when the result will drive a
decision: it also requires the saved producer digest to match the active core.
That producer check does not establish live-source freshness; use freshness
for a new Map-to-repository comparison. C/API query requests use
producer_policy: "compatible"|"current"; every Query records the effective
policy and its current, different, or unknown producer classification.
Progress is adaptive: --progress auto updates one terminal line only when an
analysis takes long enough to notice and stays silent for pipes and agents.
Use --progress always for captured agent/CI logs or --progress never for
silence.
direct, candidate, and conservative are static evidence strengths, not
claims that a test ran. Zero error diagnostics means selected analysis
completed; unresolved calls, parser recovery, partial surfaces, and unsupported
coverage remain visible.
Audit a saved Map against live source before treating it as current:
archbird freshness . --snapshot .archbird/map.json \
--output .archbird/freshness.json --check
Programmatic APIs
Python
from archbird import Project, compile_plan_json, render_plan_markdown
project = Project.from_repository(".")
map_json = project.map_json(pretty=True)
print(project.map_markdown(max_chars=12_000).decode())
print(project.query_markdown(symbols=["runtime_start"], depth=1).decode())
selection = project.query_json(symbols=["runtime_start"], depth=0)
print(project.source_markdown(
artifact_json=selection
).decode())
if project.verification_configured:
verification_json = project.verify_json()
plan_json = compile_plan_json(
project, project.map_json(), verification_json
)
print(render_plan_markdown(plan_json).decode())
print(project.query_markdown(
symbols=["runtime_start"], depth=1, view="changes", detail="compact"
).decode())
JavaScript / Node
const { Project, compilePlan, renderPlanMarkdown } = require("archbird");
const project = Project.fromRepository(".");
try {
console.log(project.mapMarkdown({ maxChars: 12000 }).toString("utf8"));
const selectionJson = project.queryJson({
symbols: ["runtime_start"], depth: 0,
});
console.log(project.sourceMarkdown({
artifactJson: selectionJson,
}).toString("utf8"));
if (project.verificationConfigured) {
const mapJson = project.mapJson();
const verificationJson = project.verifyJson();
const planJson = compilePlan(project, mapJson, verificationJson);
console.log(renderPlanMarkdown(planJson).toString("utf8"));
}
console.log(project.queryMarkdown({
symbols: ["runtime_start"], depth: 1, view: "changes", detail: "compact",
}).toString("utf8"));
} finally {
project.dispose();
}
Browser
const { createBrowserArchbird } = require("archbird/browser");
const archbird = await createBrowserArchbird();
const project = archbird.Project.fromFiles([
new archbird.Source(
"src/index.ts",
new TextEncoder().encode("export const answer = 42;\n"),
),
]);
try {
console.log(project.map());
const selectionJson = project.queryJson({ symbols: ["answer"], depth: 0 });
console.log(project.sourceMarkdown({
artifactJson: selectionJson,
}).toString("utf8"));
} finally {
project.dispose();
}
C
#include <archbird/archbird.h>
ArchbirdEngine *engine = NULL;
ArchbirdStatus status = archbird_engine_create(NULL, &engine);
if (status == ARCHBIRD_OK) {
/* Supply repository-relative sources or normalized provider facts, then
call Map, Verify, Query, Diff, or workspace APIs. */
archbird_engine_destroy(engine);
}
The public C ABI uses opaque handles, allocator-aware byte buffers, explicit statuses, and canonical JSON boundaries. It is experimental ABI v0.
Complete API inventory
Python and Node expose parallel Map, Query, Verify, Plan, and Act capabilities
where their runtimes permit them. The inventories below are checked against
archbird.__all__ and Object.keys(require("archbird")); host-specific schema,
cache, OKF, observation, and runtime inspection helpers intentionally differ.
| Python area | Public names |
| — | — |
| Repository model | Project, Source, Workspace |
| Map, Query, and Path | analyze_workspace_json, audit_map_freshness, diff_maps_json, export_graph, path_map_json, path_map_markdown, query_map_json, query_map_markdown, render_map_markdown, render_path_markdown, render_source_markdown, resolve_discovery |
| Projection and policy | compile_project_configuration, compile_query_plan_json, evaluate_constraints_json, evaluate_projection_json, freeze_constraints_json |
| Plan and Act | accept_act_json, act_overlay, act_source_requirements, apply_accepted_act, compile_plan_json, inspect_ast_grep_executable, materialize_act_json, materialize_ast_grep_operations, observe_act_sources, observe_plan_sources, plan_source_requirements, preflight_act_apply, render_act, render_plan_markdown, run_act_gates, validate_act, validate_plan |
| Observations and OKF | analyze_okf_source, compile_test_observations, export_okf_bundle, publish_okf_bundle, validate_test_symbol_observations, write_okf_bundle |
| Runtime and schemas | __version__, implementation_digest, PATTERN_CONTRACT, PATTERN_CONTRACT_VERSION, PATTERN_ENGINE, PATTERN_OPTIONS, PATTERN_UNICODE, read_schema, schema_names |
| Node area | Public names |
| — | — |
| Repository model | Project, Source, Workspace |
| Map, Query, and Path | analyzeWorkspace, auditMapFreshness, diffMaps, exportGraph, pathMap, pathMapMarkdown, queryMap, queryMapMarkdown, renderMapMarkdown, renderPathMarkdown, renderSourceMarkdown, resolveDiscovery |
| Projection and policy | compileProjectConfiguration, compileQueryPlan, evaluateConstraints, evaluateProjection, freezeConstraints, reportConstraints |
| Plan and Act | acceptAct, actOverlay, actSourceRequirements, applyAcceptedAct, compilePlan, materializeAct, observeActSources, observePlanSources, planSourceRequirements, preflightActApply, renderAct, renderPlanMarkdown, runActGates, validateAct, validatePlan |
| Observations and OKF | analyzeOkfSource, compileTestObservations, publishOkfBundle |
| Runtime and planning | defaultProviderCacheDir, defaultProviderCacheMaxBytes, discoveryPlan, jsonCanonicalize |
| Runtime metadata | ENGINE, IMPLEMENTATION_SHA256, NATIVE_ABI_VERSION, PATTERN_CONTRACT, PATTERN_CONTRACT_VERSION, PATTERN_ENGINE, PATTERN_OPTIONS, PATTERN_UNICODE, PROVIDER_SUPPORT, VERSION |
archbird/browser exports createBrowserArchbird(). Browser repository input
is an explicit inventory/byte snapshot, not ambient filesystem access.
Project.fromFiles() resolves discovery from supplied bytes. Hosts that receive
large directory inventories can call Project.discoveryContentPaths(), read
only those small discovery inputs, call Project.resolveInventory(), then read
resolution.files and construct the project with
Project.fromResolvedFiles(). This is the metadata-first path used by the app.
The resolved facade is:
Project, Source, auditMapFreshness, ENGINE, NATIVE_ABI_VERSION,
PATTERN_CONTRACT, PATTERN_CONTRACT_VERSION, VERSION, and core.
The core property is the advanced raw Wasm facade.
npm package entrypoints are archbird, archbird/browser,
archbird/schema/*, archbird/serve, archbird/wasm,
archbird/wasm-sync, and archbird/worker.
The complete C ABI is declared in
include/archbird/archbird.h:
| C area | Public functions |
| — | — |
| Engine and structured edits | archbird_engine_create, archbird_engine_destroy, archbird_engine_error, archbird_engine_error_offset, archbird_engine_options_init, archbird_engine_options_init_for_input, archbird_graph_options_init, archbird_implementation_sha256, archbird_json_canonicalize, archbird_json_pointer_edit, archbird_json_pointer_edit_options_init, archbird_json_pointer_edit_result_init, archbird_json_validate, archbird_make_variable_token_edit, archbird_make_variable_token_edit_options_init, archbird_make_variable_token_edit_result_init, archbird_make_variable_token_insert, archbird_make_variable_token_insert_options_init, archbird_make_variable_token_insert_result_init, archbird_unified_diff_options_init |
| Discovery | archbird_discovery_add_ignore, archbird_discovery_add_path, archbird_discovery_create, archbird_discovery_destroy, archbird_discovery_render, archbird_discovery_resolve, archbird_discovery_should_descend |
| Configuration, projections, constraints | archbird_constraints_evaluate, archbird_constraints_freeze, archbird_constraints_report, archbird_constraints_report_with_blocking, archbird_project_configuration_compile, archbird_projection_evaluate, archbird_projection_render_markdown, archbird_query_plan_compile |
| Project evidence | archbird_project_add_provider_facts, archbird_project_add_source, archbird_project_add_test_symbol_observations, archbird_project_config_sha256, archbird_project_create, archbird_project_destroy, archbird_project_finalize_providers, archbird_project_finalize_sources, archbird_project_manifest_sha256, archbird_project_map_input_sha256, archbird_project_merge_summary, archbird_project_provider_count, archbird_project_provider_fact_count, archbird_project_render_file_facts, archbird_project_render_map, archbird_project_render_merge_conflicts, archbird_project_render_merge_ledger, archbird_project_render_provider_facts, archbird_project_render_source_markdown, archbird_project_scan_builtin, archbird_project_scan_builtin_provider, archbird_project_scan_builtin_provider_file, archbird_project_set_config, archbird_project_source, archbird_project_source_count, archbird_provider_facts_validate, archbird_source_manifest_validate, archbird_test_symbol_observations_validate |
| Map, Query, Path, interchange | archbird_map_diff, archbird_map_export_graph, archbird_map_freshness, archbird_map_path, archbird_map_path_markdown, archbird_map_query, archbird_map_query_markdown, archbird_map_query_markdown_view, archbird_map_query_markdown_view_with_verification, archbird_map_render_markdown, archbird_map_render_markdown_view, archbird_okf_analyze, archbird_okf_publish, archbird_path_render_markdown, archbird_unified_diff |
| Workspace | archbird_workspace_analyze, archbird_workspace_plan |
| Plan and Act | archbird_act_accept, archbird_act_materialize, archbird_act_preflight_apply, archbird_act_source_requirements, archbird_act_validate, archbird_plan_compile, archbird_plan_render_markdown, archbird_plan_source_requirements, archbird_plan_validate |
Agent protocol
The Python CLI and source launcher expose the same live repository service over MCP stdio:
archbird mcp
archbird mcp --root ../project
archbird mcp --no-config
An MCP host launches that command and communicates through stdin/stdout. The server maps the repository once, watches it for changes, retains recent valid generations, and exposes read-only tools for status, Map presentation, exhaustive projections, focused Query, hash-checked source, Verify, and Diff. It does not advertise Act because the current live service does not yet provide Map-aware change planning.
Map, Projection, Query, source, Verification, and Diff results include
generation- and digest-bound resource links. Tool results are structured JSON
plus text where useful, and are bounded to 2 MiB; Map and Query have smaller
configurable presentation budgets. archbird_source validates the requested
repository-relative path and current bytes against the selected Map generation.
Project configuration can come from the repository or a file, but not stdin,
because MCP owns stdin.
The transport follows the MCP stdio transport and the tool/resource shapes follow the MCP server specification.
CI and agent workflow
archbird map . --progress always \
--format json --output .archbird/map.json --check
archbird verify \
--format sarif --output .archbird/architecture.sarif --check
For agents:
Copy this compact policy into a project’s AGENTS.md, CLAUDE.md, or
equivalent agent instructions:
Use Archbird before broad source exploration.
- Start with `archbird map . --view overview --detail standard --max-chars
12000 --check`.
- When an exact identity is known, use `archbird query . --symbol
'PATH:SYMBOL' --depth 1 --test-depth 1 --max-chars 12000 --check`.
- When the identity is unknown, use `archbird query . --search 'CONCISE
REPOSITORY TERMS' --max-chars 12000 --check`. Search is lexical; its ranked
matches are advisory starting points, not proven semantic edges.
- Read an exact declaration with `archbird query . --symbol 'PATH:SYMBOL'
--view source --detail standard --max-chars 12000 --check`. Read one complete
selected file with `archbird query . --path PATH --dump --check`; do not add
`--max-chars` to `--dump`.
- Use `archbird path SOURCE TARGET --check` for an explicit connection
question. Only a current, source-evidenced witness is `found`; candidate-only
or incomplete connectivity remains `unknown`.
- Run `archbird verify --root . --check` before and after architecture-sensitive
work. Verify is exhaustive; Query may rank, collapse, and bound context.
- Treat static test routes as navigation candidates, not proof that a test ran.
Use project-owned runner observations for execution evidence.
- Before reusing `.archbird/map.json`, run `archbird freshness --root .
--snapshot .archbird/map.json --check`.
- Review generated Plans and accepted Acts. Never run `archbird apply` unless
repository mutation is explicitly authorized and the exact Act was reviewed.
- If Archbird disagrees with source, inspect source directly and report a
general reproducer; never hide uncertainty or manufacture observed evidence.
For repeated read-only exploration, an MCP-capable agent can launch
archbird mcp --root . and use its generation-bound Map, Projection, Query,
source, Verify, and Diff tools. Plan, Act, and Apply remain explicit CLI review
steps.
Project configuration
Archbird works without config. Add archbird.json when names and boundaries
are reviewed project intent. CLI arguments override project config, which
overrides versioned discovery defaults.
archbird config show . --pretty
archbird config init . --output archbird.json
config init is a review candidate, not architecture truth.
For monorepos, discovery follows explicit npm/Yarn workspaces and uv
[tool.uv.workspace] member patterns (including uv exclusions). It also probes
a direct-child Python pyproject.toml only when inventoried Python source exists
below that directory. The native resolver requests exact regular manifest files;
each request is limited to 256 KiB, with at most 128 npm and 32 Python
candidates. config show exposes the request ledger, limits, provenance, and
overlap/truncation/conflict diagnostics. Authored project, layers, and
packages fields still take precedence over every inferred candidate.
At the repository root, the same bounded request protocol reads at most one
setup.cfg and one CMakeLists.txt. Literal setuptools metadata can contribute
a source-backed Python package/import root; one literal lexical-root CMake
project() call can contribute project identity. Archbird does not evaluate
setuptools directives, interpolation, CMake variables, includes, macros, or
conditional/function bodies. It distinguishes modules, regular packages, and
namespace-package discovery, rejects unsupported include/exclude ambiguity,
and rejects a CMake identity if project is redefined or unreachable after a
root return(). Rejected identity is omitted from the project model and
recorded as a warning: discovery-manifest-invalid for malformed or ambiguous
input, and discovery-manifest-identity-unsupported for valid CMake or
setup.cfg that this reader cannot resolve statically. npm/PEP 621/setup.cfg/R/
Autoconf identity keeps priority over the CMake fallback; CLI and authored
project identity remain authoritative over all of them.
{
"project": "demo",
"layers": [
{
"name": "core",
"role": "core",
"language": "c",
"globs": ["include/**/*.h", "src/**/*.c"],
"public_headers": ["include/demo.h"]
},
{
"name": "javascript",
"role": "frontend",
"language": "typescript",
"globs": ["js/src/**/*.ts"]
}
],
"components": [
{"name": "native-core", "paths": ["include/**", "src/**"]},
{"name": "javascript-api", "paths": ["js/src/**"]}
]
}
That first file changes only Map construction. Add a reusable exhaustive projection, a named Query, and a constraint when the project is ready to make reviewed architecture policy persistent:
{
"projections": {
"public-core-api": {
"select": "symbols",
"paths": ["include/demo.h"],
"public_only": true
}
},
"queries": {
"public-api-impact": {
"projection": "public-core-api",
"direction": "upstream",
"depth": 1
}
},
"constraints": {
"CORE-PUBLIC-API": {
"assert": "required_subset",
"expected": {"literal": ["demo_close", "demo_open"]},
"actual": {"projection": "public-core-api"},
"severity": "error",
"owner": "core",
"rationale": "Supported native entrypoints must remain public."
}
}
}
These are top-level members of the same archbird.json; the fragment is shown
separately to make the progression visible. The complete configuration
vocabulary is:
| Section | Purpose |
| — | — |
| project, description | optional stable project identity and human context |
| exclude, discovery | project-level selection and explicit discovery policy |
| layers, components | selected source/provider groups and reviewed architecture groupings |
| packages, builds, artifacts | manifests, public entrypoints, compilation-database/Autoconf/Make/npm routes, logical outputs and loaders |
| bridges | declared/used/implemented ABI, binding, or message surfaces |
| tests | static cases, reviewed case routes, and generated-source relations |
| named_entries, parity | configured entrypoint protocols and reviewed surface relationships |
| indexes | one or more SCIP indexes with prefixes, position encoding, and build variants |
| projections, queries, constraints | reusable derivations, saved Query plans, and reviewed architecture policy |
| gates | reviewed build or test commands that must pass in Act’s isolated after-state |
| limits | bounded Map analysis policy |
Selectors are segment-aware: src/*.c matches immediate children and
src/**/*.c is recursive. Components group selected files; they do not discover
new source. route_to records broad asserted intent; case_routes is
case-specific. Patterns use the pinned archbird-pcre2-v1 contract rather than
Python re or JavaScript RegExp.
Zero-config discovery consumes conventional root compile_commands.json and
index.scip files when present. Declare multiple compiler outputs explicitly
and give each one a stable variant when a repository has CPU, CUDA, Wasm, or
other builds:
{
"builds": [
{"name": "wasm-db", "kind": "compile_commands", "path": "build/wasm/compile_commands.json", "variant": "wasm"}
],
"indexes": [
{"name": "wasm-scip", "format": "scip", "path": "build/wasm/index.scip", "variant": "wasm"}
]
}
Archbird reads these artifacts; it never invokes the compiler or indexer. Compilation routes retain repository source paths, the compiler basename, and a command digest without publishing absolute build-machine paths. SCIP facts retain their variant, producer, source anchoring, coverage, and freshness.
Map also uses repository-local C/C++ include search paths from compilation
databases. It follows compiler search order for each translation unit and
propagates that context through the headers reached by its literal includes.
Variants must resolve an include to the same selected file; disagreement stays
unresolved. Resolved edges cite the repository-relative compilation-database
path, while external roots and absolute machine paths remain private.
In zero-config mode, a conventional repository include/ match remains useful
candidate evidence but does not establish the import. An authored
import_roots entry or agreeing compilation-database evidence promotes the
same connection to current.
The block above is mirrored by
examples/minimal.archbird.json. A complete
native/Python/TypeScript/package/build/test example is
examples/quickstart.archbird.json. The
Draft 2020-12 project-configuration schema is
schema/archbird.schema.json. The native
configuration compiler is authoritative and additionally enforces relational
invariants that standard JSON Schema cannot express, such as min <= max.
A shared accepted/rejected corpus keeps the schema and native C, Python, Node,
and Wasm compilers aligned for their common contract. Project configuration is
unversioned: absent project-model fields inherit discovery, while explicitly
present fields replace the corresponding discovered value. Generated Map,
ProjectionResult, Query, Verification, and change artifacts each carry an
independent schema version and migration schedule; Archbird has no global
schema version.
Evidence providers
Archbird stores normalized facts, not parser-specific trees. Several providers can contribute without erasing provenance or blindly unioning contradictions.
| Level | Evidence | Providers |
|---|---|---|
| L0 | paths, bytes, hashes, manifests, coverage | shared C/Wasm core |
| L1 | declarations, calls, test/build/FFI strings | portable lexical/protocol providers |
| L2 | syntax, scopes, imports, call shapes, spans, recovery | pinned Tree-sitter C, C++, Python, JS, TS/TSX, R |
| L3 | resolved definitions, references, relationships | supplied SCIP; CPython AST; TypeScript compiler |
| L4 | behavior and exact runtime hits | project-owned observed artifacts |
Tree-sitter recovery is fact-local. Semantic indexes retain producer, document coverage, source anchoring, and freshness. Provider conflicts, ambiguity, and unresolved targets remain explicit.
Interchange and command surface
Canonical Archbird JSON is authoritative. Optional inputs/projections are:
| Format | Direction | Role |
|---|---|---|
| SCIP | input | semantic definitions, references, relationships |
| OKF v0.1 | Python input/output; Node library projection | browsable knowledge bundle; prose never becomes constraints |
| graph-view JSON | output | typed interactive graph |
| GraphML, Mermaid | output | graph interchange and bounded diagrams |
| SARIF, JUnit | output | Verify/change CI integration |
archbird export json --map .archbird/map.json --view components \
--output .archbird/components.json
archbird export graphml --map .archbird/map.json \
--output .archbird/architecture.graphml
archbird export mermaid --map .archbird/map.json \
--output .archbird/architecture.mmd
The command names are:
Python: map, config, query, impact, path, diff, observe, freshness,
workspace, verify, plan, act, apply, export, okf,
serve, mcp, support.
Node: map, config, query, impact, path, diff, observe, freshness,
workspace, verify, plan, act, apply, export, serve,
support.
config provides show|init; export provides json|graphml|mermaid and
Python additionally provides okf; Python okf provides
validate|index|query. Use
archbird COMMAND --help for flags. Exit status is 0 for success, 1 when
requested --check blocks, and 2 for invalid input/configuration.
Persistent caches are content-addressed and core-validated. Archbird reuses
per-file provider facts after a file changes and reuses a materialized complete
Map when the configuration, selected source bytes, providers, and core are all
unchanged. Both tiers share a 1 GiB default budget; use --cache-max-bytes,
ARCHBIRD_CACHE_MAX_BYTES, --cache-dir, or --no-cache to control storage.
Cache eviction or write failure never changes canonical analysis output.
Concurrent writers use owned atomic temporaries: live or unverifiable writers
are preserved, while abandoned same-execution-domain writes are reclaimed when
the host has a safe process-liveness probe. The Python host supervises bounded
multiprocess CPython-AST worker batches and terminates its workers when a batch
does not return within
--python-provider-timeout seconds; this execution policy does not enter
canonical Map identity.
Guarantees, limits, and distribution
- Identical selected source, config, provider implementations, and supplied evidence produce byte-identical canonical output under the same Archbird implementation.
- Archbird performs no analyzed-project import/execution, network call, model
call, or agent invocation. Repository mutation occurs only through explicit
archbird apply ACT.json; Plan compilation and Act are non-mutating. - Lexical/syntax evidence is not whole-program semantic resolution; static test routes are not runtime execution or behavioral coverage.
- Dynamic dispatch/reflection, C preprocessing, complete Make evaluation, ABI layout, and arbitrary generated code need stronger supplied evidence or remain unknown.
- PyPI supplies CPython-AST precision and a CPython 3.10 manylinux x86-64 wheel; other supported Python/platform combinations build the included C snapshot.
- npm requires Node 18, has a Linux x64 glibc prebuild, and otherwise uses bundled Wasm unless native compilation is explicitly requested.
- Schemas and ABI are pre-1 and can evolve under semantic versioning.
Archbird is licensed under Apache-2.0. The shared core uses pinned yyjson, PCRE2 10.47, Tree-sitter runtime, and grammar submodules under their upstream licenses; source distributions retain the corresponding license files.
Development
Clone the pinned third-party sources together with Archbird:
git clone --recurse-submodules --shallow-submodules \
https://github.com/zemlyansky/archbird.git
cd archbird
# For an existing clone made without submodules:
git submodule update --init --recursive --depth 1
# Build and test the C core and shared library.
make native-test
# Build the live source frontends against build/libarchbird.so.
make build-py
./archbird map
make build-js
node js/src/cli.js .
# Complete local gates.
make test
make verify
make native-wasm-smoke
make app-test
Native CMake builds and cppcheck use BUILD_JOBS=2 by default so complete
gates remain bounded on development hosts without swap. Increase the explicit
bound on larger machines, for example make verify BUILD_JOBS=8; outer
make -jN controls target scheduling but does not replace this nested-build
limit.
Use make editable-install PYTHON=/path/to/python for Python source development
and make build-c after C edits. The root submodules are development inputs;
PyPI and npm releases contain generated, content-hashed C snapshots and never
require Git or submodules at installation time. tools/sync_csrc.py creates
those publishable snapshots from the pinned gitlinks; generated snapshots are
not a second source of truth.