CLI reference
All commands accept --graph . to point at an existing .astria/ directory (defaults to the current directory).
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> # Incremental rebuild (only changed files; regenerates an existing wiki)
astria watch <path> [--debounce 3000] # Watch for file changes, auto-rebuild
astria cluster-only <path> # Re-cluster + analyze + report without re-extracting
astria merge <pathA> <pathB> <outPath> # Merge two graphs
astria diff <pathA> <pathB> # Compare two graphs
run and update accept --backend <claude|openai|gemini> and --model <name> (per-run LLM enrichment without env vars) and --no-dedup (skip near-duplicate node merging).
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). - Transcript sidecars — any
.txt/.mdyou drop into.astria/transcripts/is ingested as document nodes on the next run/update. The contract for external transcribers: run any tool you like, write the text there, let the graph index it.
Querying
astria explain <node> [--graph .] # Explain a node and its connections
astria query <question> [--dfs] [--depth 2] [--budget 2000] [--directed] [--detail high] [--cursor N] [--graph .] # BFS/DFS traversal
astria path <A> <B> [--directed] [--detail high] [--graph .] # Shortest path between two concepts
astria affected <node> [--depth 2] [--relation R] [--graph .] # Blast radius - what breaks if you change this node
astria map [--budget 2000] [--detail high] [--graph .] # PageRank-ranked repo map with top symbols
astria stats [--graph .] # Node/edge/community counts
astria status [--graph .] # Graph health and staleness
astria history [--limit 20] [--graph .] # Show recent query history
Query flags
--dfs— depth-first instead of breadth-first traversal--depth N— maximum traversal depth--budget N— output token budget (default 2000)--directed— follow edge direction instead of treating the graph as undirected--detail high— fidelity tier: only declared (EXTRACTED) facts--cursor N— continuation cursor for truncated traversals
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 log (for tooling)
Every query can also append a JSONL line (ts, kind, question, nodes, duration) to a log file for agent/tooling consumption:
ASTRIA_QUERY_LOG=<path>— log to a specific file;ASTRIA_QUERY_LOG=1uses the default locationASTRIA_QUERY_LOG_ENABLE=1— turn on logging without choosing a pathASTRIA_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] [--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] [--graph .] # Map open PRs onto the graph - impact + merge-order risk
export --format html creates an interactive vis-network graph view. The default --mode standard exports the full interactive graph when it contains at most 5,000 nodes and fails with an actionable message for larger graphs. --mode large opts into a precomputed-layout viewer (physics-free, key nodes first, batched search) that opens instantly on any repo size.
--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.
Graph health
astria diagnose [--graph .] [--json]
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.
Migrating from pre-1.0 layouts
astria migrate [--graph .]
One-time rename migration: moves a pre-1.0 .graphify/ data folder to .astria/, renames .graphifyignore to .astriaignore, and moves ~/.nodesify-graphify/global.db to ~/.astria/global.db. Idempotent, and never overwrites an existing target — if the graph is locked by a running editor or MCP server it says so and can simply be re-run.
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/. Cited node ids link the answer to the graph.- The next
run/updateingests memory docs as graph nodes, so settled questions become part of the graph. 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. Types sharing (namespace, label) across repos get same_type_as edges, 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] [--contributor] # Fetch arXiv/tweet/webpage/image/PDF into ./raw + update graph
astria add --scip <index.json> # Ingest a simplified SCIP JSON index (rust-analyzer & co.)
astria add --postgres <dsn> # Introspect a live PostgreSQL schema (requires psql on PATH)
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 information_schema (tables/views/routines/FKs → contains + references edges, no credentials stored). The Postgres DSN is opt-in by flag — nothing calls the network by default.
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 .] # Run MCP stdio server - query the graph from any AI agent
astria install [--platform claude] # Install skill files for AI coding assistants
astria uninstall [--platform claude] # Uninstall skill files
astria hook install|uninstall|status # Git hook management
astria hook-guard <mode> # Editor PreToolUse guard (search | read | gemini) — installed into .claude/settings.json
Supported platforms for install: claude, codex, gemini, cursor, copilot, aider, opencode, kiro, trae, zcode. Setup walkthrough in Agent integration; the nine 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.