CLI reference
All query and read commands accept --graph . to point at an existing .astria/ directory (defaults to the current directory); mutating commands (run, update, watch, merge, diff, global, add, save-result, reflect, install) operate on their own arguments instead — add, save-result, and reflect also accept --graph.
Building the graph
astria run <path> # Full pipeline: detect → extract → build → cluster → analyze → report
astria run <path> --wiki # ...also export a markdown wiki to .astria/wiki
astria run <path> --embed # ...also compute local embeddings (similar_to edges + semantic query recall)
astria run <path> --backend openai --model gpt-4o-mini # ...with LLM semantic enrichment (see Semantic enrichment)
astria run <path> --global --as <tag> # ...also merge this repo into the cross-repo global graph (see Global graph)
astria update <path> # Reuse cached ASTs, reconcile current corpus; regenerate an existing wiki
astria watch <path> [--debounce 3000] [--max-wait 15000] [--timeout 600] # Reconcile at startup and after file changes; kill a rebuild that exceeds the timeout (0 disables)
astria cluster-only <path> [--resolution 0.5] [--exclude-hubs] # Re-cluster + analyze + report without re-extracting
astria merge <pathA> <pathB> <outPath> [--same-repo] # Merge two graphs (namespaced per repo; --same-repo shares ids and errors on conflicts)
astria diff <pathA> <pathB> # Compare two graphs
astria merge-driver install # Union-merge .astria/graph.json on parallel-branch commits (see Team serving & CI)
cluster-only accepts two clustering controls: --resolution <r> (0.0–1.0, default 0.0 = classic label propagation) requires a minimum share of a node's neighbors to agree on the winning community before the node joins it — higher values produce more, smaller communities — and --exclude-hubs keeps high-degree hub nodes out of propagation so they cannot glue every community into one (hubs are attached to their strongest community afterwards, so every node still lands in one).
run and update accept --backend <claude|openai|gemini|none>, --model <name>, and --judge <name> (per-run LLM enrichment without env vars; --judge jev layers the TypeSafe judge over the backend), --no-dedup (skip near-duplicate semantic entity merging), --label-communities (LLM thematic names for changed communities), and --deep (per-file concept linking) — the two LLM features require --backend and are described in Semantic enrichment. --judge requires --backend. update additionally accepts --embed (compute/recompute local embeddings, same as run --embed), --quiet (suppress progress lines and the token benchmark, used by git hooks), and --if-stale <minutes> (skip when the graph was published less than N minutes ago). Code definitions retain their identities even when labels match across classes or files.
Backend selection must be explicit through --backend or ASTRIA_LLM_BACKEND; credentials alone do not activate it. none disables enrichment. Cached ASTs avoid reparsing unchanged files, while references are reconciled across the current corpus. Graph facts and the manifest commit together after successful extraction; derived passes rerun after that commit and can be retried on the next update.
The published indexing policy is saved in .astria/indexing-profile.json without credentials. Ordinary update, watch, hook and ingestion updates reuse its backend, model, endpoint, budget and feature flags. A project with no saved policy defaults to structural indexing during automatic updates. Changing a paid policy requires --refresh-policy; selecting a paid replacement also requires --llm-budget <positive tokens>. For example, astria update . --backend openai --model <name> --refresh-policy --llm-budget 50000. To disable enrichment, use astria update . --backend none --refresh-policy. Project writers hold one OS-backed lock across indexing and publication; readers can continue using database snapshots. Artifact writes use unique temporary siblings and atomic replacement, with generation stamps to detect different publications.
Watch installs its listener before startup reconciliation, coalesces changes, and bounds continuous debounce with --max-wait. It runs one owned update child at a time, queues another when needed, and stops that child on shutdown.
update can explicitly disable saved options with --no-embed, --no-label-communities, and --no-deep, and re-enable merging with --dedup. Disabling embeddings removes stored vectors and similarity edges; a cached model does not trigger embedding work when the effective policy disables it. Use --embed to enable it again. Paid-option changes follow the refresh/budget rules above.
Builds also pick up, automatically:
- Cargo workspaces — when a
Cargo.tomlis present, workspace members and internal path dependencies becomecrate::*nodes withcrate_depends_onedges (honoringpackage =renames andworkspace = trueinheritance). No LLM involved — dependency structure is fact. - MCP configs —
.mcp.json,mcp_servers.json, andclaude_desktop_config.jsonbecomemcp_server/mcp_command/mcp_packagenodes withrequires_envedges (env names only — values are never read). - Video/audio transcription —
mp4/mov/webm/mkv/avivideo andmp3/wav/m4a/flac/ogg/opus/aac/wmaaudio files are transcribed duringrun/updatewhen whisper.cpp'swhisper-cliis on PATH (video also needsffmpeg); the transcript becomes document and chunk nodes exactly like a markdown file. The model comes fromASTRIA_WHISPER_MODELor the first*.binin<project>/.astria/models/or~/.astria/models/. Missing binaries or model skip the files with a one-line notice — builds never fail on media. - Media URLs —
astria add <url>accepts YouTube/Youtube-music, Vimeo, Dailymotion and Twitch links (plus direct.mp4/.mp3/… URLs): the audio track is downloaded with yt-dlp (16 kHz mono WAV whenffmpegis available) and transcribed by the same whisper pipeline as local media. The download is vetted before any media byte moves: yt-dlp first resolves the destination in metadata-only mode and every post-redirect media URL must pass the same private/internal-network policy as the regular fetch path; a download that would land inside your network is refused. yt-dlp missing degrades to a stub node with the install hint. - Office documents —
.docx(headings, paragraphs, lists, tables) and.xlsx(one markdown table per sheet, capped at 500 rows / 30 columns) are extracted locally and become document nodes. - Google Workspace —
.gdoc/.gsheet/.gslidesDrive shortcut files resolve to a file id and export as text/CSV → markdown through the Drive API; see Google Workspace env vars. Missing credentials skip the file with a one-line notice. Cloud edits never change the local shortcut bytes, so plainrun/updateprobe the remote revision for unchanged shortcuts and rebuild when it has moved — remote edits are picked up without touching the file. Offline (or without credentials) the cached extraction stands: remote freshness requires connectivity. - More doc formats —
.qmdrides the markdown path;.html/.htmare tag-stripped (scripts/styles dropped);.yaml/.ymlare chunked as text. - More languages — 42 registered languages: SQL (tables, views, functions/procedures, triggers incl.
CREATE TRIGGER), Julia, R, Fortran, Solidity, Groovy, Luau, Objective-C, OCaml (.ml) + OCaml Interface (.mli), Common Lisp, BYOND DreamMaker, Astro; Vue and Svelte extract their embedded<script>TS/JS through the JavaScript/TypeScript grammars; VB.NET and Pascal/Delphi use regex-declaration extraction (no grammar crate exists upstream). - Transcript sidecars — any
.txt/.mdyou drop into.astria/transcripts/is ingested as document nodes on the next run/update (handy for tools or languages the built-in transcription does not cover). The contract for external transcribers: run any tool you like, write the text there, let the graph index it — or pipe it through the built-in writer:astria add --transcript <file>keeps the file's name,astria add --transcript -reads piped stdin (e.g.whisper ... | astria add --transcript -) and stores it under a timestamped name.
Querying
AST citations use one-based lines. Queries return qualifying relationships between all selected nodes, including relationships between seeds and cycles; depth controls node discovery. Repo maps exclude unlocated references and stubs and budget complete records using the response tokenizer. Lexical corpus data is cached per graph generation. Markdown frontmatter can set status: current, resolved, or superseded, plus resolution and superseded_by; document sections, chunks and enriched concepts inherit this metadata. Rendered answers disclose it, and historical documents receive less relevance unless the question asks for history.
astria explain <node> [--graph .] [--json] # Explain a node and its connections
astria query <question> [--seed <symbol>]... [--dfs] [--depth 2] [--budget 2000] [--directed] [--detail high] [--cursor N] [--no-embed] [--json] [--graph .] # BFS/DFS traversal; --seed anchors it at known symbols
astria path <A> <B> [--directed] [--detail high] [--json] [--graph .] # Shortest path between two concepts
astria affected <node> [--depth 2] [--relation R] [--json] [--graph .] # Blast radius - what breaks if you change this node
astria map [--budget 2000] [--detail high] [--json] [--graph .] # PageRank-ranked repo map with top symbols
astria stats [--graph .] [--json] # Node/edge/community counts
astria god-nodes [--graph .] [--json] # Highest-degree hub nodes (MCP god_nodes parity)
astria communities [--graph .] [--json] # Communities with labels, size, cohesion (MCP list_communities parity)
astria neighbors <node> [--relation R] [--json] [--graph .] # A node's neighbors, optionally one relation (MCP get_neighbors parity)
astria status [--graph .] [--json] # Graph freshness, staleness, and build provenance
astria callflow <node> [--depth 2] [--direction out|in|both] [--out flow.md] [--graph .] # Mermaid call graph
astria history [--limit 20] [--graph .] # Show recent query history
Query flags
--seed <symbol>— repeatable explicit entry point: a node ID, label, bare symbol name, or unique source path. Ambiguous names return candidate IDs and locations instead of choosing a declaration. Re-run with the exact candidate ID. JSON exposes completeambiguousSeedsandunresolvedSeeds; rendered diagnostics stay within the text budget. When no explicit seed resolves, the query reports a miss rather than falling back to keywords.--dfs— depth-first instead of breadth-first traversal--depth N— maximum traversal depth (default 2, or[query] depthin.astria.toml; an explicit flag always wins)--budget N— maximum query text tokens usingo200k_base, including headers and continuation metadata (default 2000, or[query] budgetin.astria.toml; an explicit flag always wins). A malformed[query]entry warns and falls back to the built-in default--directed— follow edge direction instead of treating the graph as undirected--detail high— fidelity tier: onlyEXTRACTED/DECLAREDfacts (a provenance-class filter, not a numeric threshold), dropping inferred, semantic and learned edges, regardless of usage-adjusted confidence scores--cursor N— continuation cursor for truncated traversals; use the returned value, which advances through node and edge records--no-embed— skip auto-merged embedding seeds even when the graph carries vectors (same switch asASTRIA_EMBED=off; see Environment variables)--json— machine-readable output instead of prose:queryreports counts, the continuation cursor, build provenance, and the answer text;explain/neighborsreturn the strongest 20 neighbors, each with its edge direction inoutgoing(the native layer caps the list —explain --jsonalso reportsneighborCount, the true total);affectedreturns every hit with depth, relation, and edge provenance;statsreturns counts and type breakdown
path reports conservative confidence: among equal-length shortest routes it returns the one whose weakest hop is weakest, marks that hop with *, and ends with a summary naming it (plus the equal-route count when there was a tie). Each hop prints its evidence — [EXTRACTED]/[DECLARED] stay bare; other classes show their numeric score, e.g. [INFERRED 0.75]. Weaker parallel edges between the same pair are preserved as also seen lines instead of being dropped.
affected reports the evidence tier of every hop. RESOLVED (the default case) marks a call expression extracted from source whose name bound to exactly one definition — trustworthy for impact analysis. EXTRACTED marks directly-verified facts (contains/imports). Hops reached through INFERRED edges — no source locus, or a name too common to bind — are marked with a legend line, so a blast radius never presents guesswork as verified.
god-nodes, communities, and neighbors give the CLI the same answers the MCP tools expose, so scripts and non-MCP agents can reach them too.
TypeScript import resolution uses project metadata: exact and wildcard tsconfig path aliases with baseUrl, workspace package entries, and scoped subpaths can resolve to authored source files. Generated build output is not substituted for authored source. Changes to graph-input configuration refresh affected bindings on the next update.
status judges freshness from the graph itself, not just file timestamps: every run/update stamps the npm CLI version and the extraction-rules version into the graph, and status --json exposes them (astriaVersion, extractionHashVersion, currentExtractionHashVersion, extractionOutdated) so tooling can detect a graph that predates the installed binary's extraction rules. Graphs built before stamping report nulls.
CLI and MCP share hybrid retrieval and load a fresh SQLite graph snapshot for each request. Query output reports when the graph was last built, so agents can judge freshness. Repeated queries promote recurring node pairs into learned edges — see learning from usage.
Query ranking favors complete identifier matches and implementing definitions. Explicit requests for tests, examples, or documentation retain those results; inline Rust test functions are classified from their test attributes and modules. JavaScript and TypeScript extraction includes functions assigned to variables, object properties, members, and CommonJS exports. TypeScript receivers can resolve through declared types, constructor parameter properties, typed fields and locals, and new assignments. Bindings remain scoped to their function or block; unambiguous instance-field assignments can supply type evidence, while conflicting, deleted, computed-unknown, static, or shadowed bindings remain unresolved. These are source-derived bindings, not proof of runtime dispatch. Python overload declarations yield to a concrete implementation in the same scope, preserving its body and documentation.
Query budgets must be positive and large enough for metadata and the next complete record; otherwise the query returns an error. Continuation cursors address the current result's node and edge records. Start a new query after rebuilding the graph, and do not reuse cursors from older versions that counted only nodes.
Query log (for tooling)
Every query can also append a JSONL line (ts, kind, question, nodes, duration_ms) to a log file for agent/tooling consumption:
ASTRIA_QUERY_LOG=<path>— log to a specific file (any non-empty value is used verbatim as the path)ASTRIA_QUERY_LOG_ENABLE=1— turn on logging with the default location (~/.cache/astria-queries.log)ASTRIA_QUERY_LOG_DISABLE=1— always wins; logging never breaks a query (fails silent)
Exports and visualization
astria export [--graph .] [--out graph.json] [--format json|html|graphml|cypher|svg|falkordb] [--mode standard|large]
astria tree [--out tree.html] [--max-children 40] # Collapsible filesystem tree of all symbols (HTML)
astria wiki [--out .astria/wiki] [--max-nodes 25] [--format markdown|obsidian] [--graph .] # Wikipedia-style markdown wiki, or an Obsidian vault
astria prs [20] [--conflicts] [--triage] [--queue] [--json] [--graph .] # Revision-aware PR review queue (requires gh and local base/head Git objects)
Every run/update also writes two machine-readable artifacts next to the report: .astria/graph.json (the full graph — nodes, edges, hyperedges, communities; the file the git merge driver union-merges) and .astria/cost.json (the run's measured LLM spend — this run plus lifetime totals, with a dollar estimate when ASTRIA_COST_*_PER_MTOK are set; see Environment variables).
export --format html creates a self-contained interactive graph view. The default --mode standard accepts graphs of at most 5,000 nodes and fails with an actionable message for larger graphs; --mode large lifts the cap. The viewer opens as community bubbles (click to expand into member nodes), supports search over symbols and community names, 1-hop neighborhood focus with relation-labeled links and direction arrows, and a level-of-detail "All nodes" mode that stays responsive on any repo size because positions are precomputed, physics is disabled, and only what is on screen is drawn. The page is a single file that embeds the whole graph, so very large repositories produce proportionally large HTML files.
--format cypher writes an idempotent Neo4j import script (MERGE statements — safe to re-run):
astria export --graph . --format cypher --out astria.cypher
cypher-shell -u neo4j -p <password> -f astria.cypher
See Wiki and exports for details.
--format svg creates a deterministic static diagram. --format falkordb writes openCypher for FalkorDB; add --redis-push <host:port> and optionally --graph-name <name> to send it through redis-cli. --neo4j-push <bolt://host:port> sends Cypher directly to Neo4j, with --neo4j-user and --neo4j-pass (or their environment variables). wiki --format only distinguishes obsidian; any other value (including the default) produces the markdown wiki.
Graph health
astria diagnose [--graph .] [--json]
astria health [--graph .] [--json] [--min-score <n>]
astria risk [--graph .] [--staged | --base <ref> [--head <ref>]] [--json]
astria merge-gate [--max-age-hours 24] [--min-health 60] [--max-risk 70] [--staged] [--base <ref> --head <ref>] [--json] # CI merge gate (see Team serving & CI)
astria digest [--out .astria/digest.md] [--json] # Engineering digest brief (see Team serving & CI)
Read-only health report over an existing graph: dangling edge endpoints (stub vs actionable), self-loops, duplicate edges, unclassified files, and zero-cohesion communities. --json emits machine-readable output. Never mutates the graph.
health scores code-health heuristics (unreachable-symbol candidates, file cycles, hub concentration, and staleness) from 0 to 100. --min-score <n> exits non-zero when the score falls below n, which is the direct CI form (astria health --min-score 70 || exit 1); without it the command always exits 0, since a report that only prints is not a gate.
risk produces a source-based change review using the same engine as merge-gate and prs. It reads Git objects and source bytes into memory, without checking out revisions or updating the published graph. The default compares HEAD with the working tree, including untracked files; --staged compares HEAD with the index. --base origin/main --head HEAD compares the merge base with the specified head; head defaults to HEAD, and range mode cannot be combined with --staged.
Changed line hunks select their innermost declarations. Before/after source graphs retain evidence for removed APIs, deleted files and renames. The report includes changed declarations, surviving and also-removed consumers, complete relationship chains with evidence classes, related test consumers, and file-based CODEOWNERS matches with rule locations. Type-signature edits include member consumers; method-only edits do not seed unrelated siblings. Commit IDs, source-content digests, before/after indexed-file counts and total indexing/review time identify the analyzed snapshots and their cost.
Coverage gaps are explicit: unsupported or malformed source, ambiguous declaration spans, excluded source, unavailable files, non-code changes and metadata-only changes produce coverageComplete: false, score: null, and exit 1. Review currently supports compiled tree-sitter code grammars; embedded-component and regex-only language routes are reported as unavailable. Each source file is limited to 2 MiB and each snapshot to 256 MiB. Unresolved relationship targets are counted separately. Structural reachability cannot establish runtime safety. The numeric score is secondary and uncalibrated: two points per changed declaration plus one per surviving consumer, capped at 100. Both risk and health support --json.
prs reads each PR's immutable base/head commit IDs and files through gh, then runs that same local revision comparison. The required commits and merge base must already be available locally; the command does not fetch, switch branches or create checkouts. API failures, changed PR heads and missing Git objects appear as unavailable coverage and produce exit 1 instead of zero impact. The ranked queue combines CI/review state with source-based impact. --conflicts shows overlapping changed/affected symbols as review-coordination signals; overlap is not proof of a Git merge conflict. Actual merge-conflict status is identified separately as GitHub's report. --json includes each complete review and any coverage error.
Memory and reflection
The feedback loop that complements learned edges: learned edges are automatic, memory is curated. Full walkthrough in Memory and learning.
astria save-result <question> --answer <text> [--answer-file <path>] \
[--outcome useful|dead_end|corrected] [--correction <text>] [--nodes <ids>] [--graph .]
astria reflect [--graph .]
save-resultwrites a Q/A memory doc (with outcome and corrections) into.astria/memory/, and immediately inserts it into the graph as a document node withreferencesedges to the cited code — settled questions become part of the graph right away. (Rebuilding the database does not re-ingest saved memory docs, so keep.astria/memory/when recreating a graph from scratch.)reflectaggregates outcomes into.astria/reflections/LESSONS.mdwith outcome tallies.
Global graph (cross-repo)
Merge many repo graphs into one queryable store at ~/.astria/global.db — merging behavior in detail in Global graph:
astria run <path> --global --as <tag> # build, then merge into the global store
astria global add <path> [--as <tag>] # same merge, standalone (idempotent per tag)
astria global remove <tag> # prune a repo from the global graph
astria global list # registered repos
astria global path <A> <B> # shortest path across repos
Design notes: sourced node ids are prefixed with the repo tag (<tag>::<id>); external/stub symbols stay unprefixed and dedupe by label, so serde_json::Value means the same thing in every repo. Same-label type declarations across repos get same_type_as edges (name-based unification), and parked unresolved calls are resolved when exactly one cross-repo candidate exists (fail closed on ambiguity). Query against the merged store with the usual --graph flag pointed at the global db:
astria query "where is the shared auth type" --graph ~/.astria/global.db
Knowledge ingestion
astria add <url> [--author <name>] [--contributor <name>] # Fetch arXiv/tweet/webpage/image/PDF into ./raw + update graph
astria add --scip <index.scip> # Ingest a standard SCIP protobuf index (or protobuf JSON)
astria add --postgres <dsn> # Introspect a live PostgreSQL schema (requires psql on PATH)
astria add --transcript <file|-> # Save a transcript into .astria/transcripts/ + update graph
Both --scip and --postgres are offline/local alternatives to URL fetching: SCIP indexes bring external toolchain symbols into the graph (scip_impl/scip_typed/scip_def/scip_ref edges, deterministic ids); Postgres introspection is read-only over the pg system catalogs (pg_class/pg_namespace/pg_constraint — tables/views/FKs → contains + references edges, no credentials stored). The Postgres DSN is opt-in by flag — nothing calls the network by default.
SCIP uses the official protocol's metadata.project_root file URI, document relative_path, symbol information, and occurrence ranges. Source citations point to the indexed document at one-based definition or reference lines. Global symbols share an identity across documents; local symbols remain scoped to their document. All enabled relationship flags produce their own edge. Native .scip protobuf and standard protobuf JSON are accepted; the former custom JSON shape is unsupported. Re-importing an index replaces its owned facts independently of the symbol's source location. External symbols without a definition occurrence have no fabricated source citation.
URL fetching is SSRF-guarded: only http/https schemes are accepted; each host is checked by name and DNS-resolved, and any loopback/private/CGNAT/link-local address (IPv4 or IPv6, including mapped forms like ::ffff:127.0.0.1) is rejected — so cloud metadata endpoints and localhost services are unreachable no matter how the URL is spelled. Redirects are followed manually (max 5 hops) and every hop is re-validated, meaning a public server cannot bounce a fetch to an internal address. Downloads are capped at 50 MB with a 30-second timeout, and saved filenames are slugified from the URL, so a hostile URL segment cannot escape the output directory.
Assistant integration
astria mcp [--graph .] # MCP over stdio (the default)
astria mcp --http [--port 8620] [--host 127.0.0.1] [--token <t>] [--projects a=./b name2=./c] [--allow-origin http://localhost:5173] # MCP over HTTP, multi-project
astria install [--platform claude] [--all] [--scope project|user] # Skill + MCP registration for one AI platform or all (claude, codex, gemini, cursor, copilot, aider, opencode, kiro, trae, zcode, vscode, windsurf, cline, roo, amp, pi)
astria uninstall [--platform claude] [--all] [--scope project|user] [--purge-project] [--purge-global]
astria hook install|uninstall|status # Git hook management
astria hook-guard <mode> # Editor PreToolUse guard (search | read | gemini) — installed into .claude/settings.json
astria merge-driver install|uninstall|run # Gitattributes merge driver for the graph file
Team serving & CI
MCP over HTTP. astria mcp --http serves one or many project graphs over MCP Streamable HTTP (JSON responses): POST /mcp speaks the same JSON-RPC as stdio, GET /healthz is a liveness probe. Clients pick a project with the x-astria-project header or a ?project= query parameter (unlisted names 404 — no silent fallback); the --graph root is the default project and --projects name=path adds more. Requests must carry --token (or ASTRIA_MCP_TOKEN) as a bearer token whenever the server binds a non-loopback host — unauthenticated remote serving is refused at startup, never allowed. Requests carrying an Origin header (browsers) are refused unless their origin is listed with --allow-origin — native clients send no Origin and always pass — and loopback serving validates the Host header as a DNS-rebinding defense.
Git merge driver for the graph file. Parallel branches both rebuild and both commit .astria/graph.json; astria merge-driver install wires a three-way union-merge driver into .gitattributes + git config (merge.astria.*) so those commits merge instead of conflicting: additions from both sides survive, a side's deletion is respected, community renumbering resolves to whichever side changed (the next update re-clusters anyway). astria/graph_report.md gets git's built-in union driver. uninstall removes the wiring.
Merge gate. astria merge-gate fails (exit 1) when the graph is missing, older than --max-age-hours, extracted by outdated rules, does not cover the current HEAD, scores below --min-health, or the source-based change review has incomplete coverage or exceeds --max-risk. The complete review is included in text and JSON output. Use --base origin/main --head HEAD for committed PR changes; the default reviews working-tree changes and --staged reviews the index. Head coverage is a separate published-graph check: commit identity plus hashes of manifest files. The source review builds its own before/after graphs in memory, so removed symbols remain available even when the published graph represents only HEAD. An unknown review score never passes the gate.
Engineering digest. astria digest renders a deterministic markdown brief — graph overview, health score, hub concentration, largest communities, LLM spend from cost.json — for stdout or --out <file>. Schedule it in cron/CI for a weekly cadence.
Docker. A Dockerfile ships in the repo root: docker build -t astria . produces a slim image running the same CLI — analyze a mounted workspace (docker run --rm -v "$PWD":/workspace astria run /workspace) or serve the HTTP MCP on the exposed port 8620. Build with --build-arg NAPI_FEATURES=--no-default-features for a smaller image without the local embedding runtime (--embed then fails loudly, everything else works).
The hosted tier (app.graphify.com) builds on these same primitives — hosted MCP, merge-gate verification, graph-aware review, and the engineering digest — for teams that do not want to run them.
Supported platforms for install: claude, codex, gemini, cursor, copilot, aider, opencode, kiro, trae, zcode, vscode, windsurf, cline, roo, amp, pi. Setup walkthrough in Agent integration; the ten MCP tools are documented in the MCP tools reference.
install also injects an always-on ## astria instruction block into AGENTS.md/CLAUDE.md (query before grep, run update after edits) — idempotent, removed by uninstall. hook-guard is the editor-side companion to git hooks: it nudges agents toward query before raw searches and can (strict mode, opt-in) gate un-indexed reads. It fails open — any error means the tool call proceeds untouched.
Learning from usage
The graph compounds in value as you query it. Every query records which (seed, discovered) node pairs its traversal connected; when the same pair recurs across at least 2 distinct questions with 3+ total hits, the next run/update promotes it to a learned edge (INFERRED, hits-scored, provenance query_history). Learned edges flow into clustering, analysis, and every export — the graph remembers which connections you actually keep asking about. High-fidelity traversals (--detail high) can filter them like any INFERRED fact.
Installation diagnostics
astria doctor [--graph .] [--scope project|user] [--json]
Checks Node, native loading, embedding support, executable resolution, scoped integrations, managed file integrity, permissions, git hooks and graph compatibility. Exit 1 on errors; warnings are advisory. Installation defaults to project scope. Project and global data deletion are separate options; the combined --purge option is removed. See Install, upgrade and remove Astria for setup, recovery and package removal.
Retrieval explanations and refresh recommendations
Query nodes include retrievalReason in structured output and a retrieval: line
in rendered text. This identifies query relevance, traversal neighbors, or an
unresolved endpoint; it is separate from relationship evidence and is not a
calibrated correctness score. Located code declarations win relevance/distance
ties over file hubs unless file preference is requested. Explanations count
against the rendered token budget.
astria status --json includes a recommendations array. Regenerate stale SCIP
indexes from current source and reimport them with astria add --scip <index-file>;
astria update . refreshes structural facts but does not regenerate compiler indexes.