Installs into .claude/skills of the current project.
Are you the author of astria?
Add the live security badge to your README. It updates with every re-scan.
[](https://www.skillsdirectory.com/skills/nodesify-astria)
---
name: astria
description: Turn any directory into a queryable knowledge graph. Trigger: /astria
---
# /astria
Turn any directory of source code into a queryable knowledge graph with community detection, hub node analysis, and a plain-language graph report. Uses AST-based extraction via tree-sitter for deterministic, fast analysis.
## What You Must Do When Invoked
If no path was given, use `.` (current directory). Do not ask the user for a path.
Follow these steps in order. Do not skip steps.
### Step 1 - Check graph state and build if needed
```bash
node -e "const fs=require('fs');const p='.astria/graph.json';if(!fs.existsSync(p)){console.log('missing');process.exit(0)}const age=Math.round((Date.now()-fs.statSync(p).mtimeMs)/60000);console.log(age>30?'stale':'fresh')"
```
Act on the result:
- `missing`: Run `astria run .` — this builds the full graph from scratch. Wait for it to complete.
- `stale`: Run `astria update .` — incremental rebuild of changed files. Wait for it to complete.
- `fresh`: Skip to Step 2.
After running `run` or `update`, verify with `astria stats --graph .` that Nodes > 0 (an incremental update with no changes correctly reports 0 nodes added). If Nodes is 0, tell the user: "No supported files found. astria supports Python, JS, TS, Rust, Go, Java, C, C++, Ruby, Swift, Scala, PHP, C#, Lua, Haskell, Elixir, Bash, Dart, Zig, CSS, Markdown, plain text, and PDF."
### Step 2 - Read the graph report
Read `.astria/graph_report.md`. Present a clean summary:
```
Knowledge graph built: X nodes, Y edges, Z communities
Hub nodes (most connected):
1. NodeName — N connections (community C)
2. ...
Surprising connections:
- SourceNode → TargetNode [cross-community edge]
Suggested questions:
- "Question 1?"
- "Question 2?"
```
Do NOT dump the raw report. Summarize it.
### Step 3 - Ready for queries
Tell the user the graph is ready and they can ask questions. Example queries they might try:
- `astria query "authentication flow"`
- `astria path "AuthService" "UserModel"`
- `astria explain "validate_token"`
## Enforcement Rules
When working in a project with a `.astria/` directory, these rules are MANDATORY:
### FORBIDDEN
Do NOT use `Grep`, `Glob`, or file browsing as your first step for architecture or codebase questions. This includes:
- Searching for "where is X defined"
- Looking for "how does X connect to Y"
- Exploring "what files are in this project"
- Finding "all files that reference X"
### REQUIRED
Instead, use these astria commands:
| User asks | Use this command |
|-----------|-----------------|
| "Where is X implemented?" | `astria query "X"` |
| "How does X connect to Y?" | `astria path "X" "Y"` |
| "What does X do?" | `astria explain "X"` |
| "What is the architecture?" | Read `.astria/wiki/index.md` if present, else `.astria/graph_report.md` |
| "Give me a navigable overview" | `astria wiki --graph .` then read `.astria/wiki/index.md` |
| "Find all references to X" | `astria query "X" --depth 3` |
| "What community is X in?" | `astria explain "X"` |
Only use native file reading AFTER the graph has identified the exact files you need.
### When native tools ARE appropriate
- Editing a specific file (after graph identified which file)
- Reading a file the user explicitly named
- Running tests or build commands
- Git operations
### When direct search / file reading is better than the graph
The graph models entities and relationships — it does NOT model behavior.
Use Grep/Glob/file reads first for:
- **Predicate-level bugs**: "is this window check off by one?", "does this
regex match branch slugs?" — expression semantics are invisible to a
graph. Read the code.
- **Exact string audits**: checking every occurrence of a literal in a
handful of files, or auditing env var names and CLI flags. Grep is
deterministic and fast here.
- **Natural-language discovery**: the graph anchors on symbol names.
`query` handles typos and partial matches, but if you don't know any
symbol name yet, a broad grep for a distinctive string is often faster.
Rule of thumb: use the graph to identify WHICH files matter (blast radius,
architecture, cross-module dependencies), then read those files directly
for exact logic. Graph output includes `file:line` anchors precisely so
you can jump straight from a node or edge to the source.
### Provenance and reference nodes
- Every `NODE` line in `query` output carries `src=path:line`, and every
`EDGE` line ends with `@path:line` — the exact spot the relationship was
extracted from. `explain` prints `File: path:line` for the node and each
neighbor.
- Edge evidence tiers: `EXTRACTED` (verified in source), `RESOLVED` (a call
expression from source whose name binds to exactly one definition —
trustworthy for impact analysis), `INFERRED` (reconstructed or unbindable
— weaker evidence, marked with a legend in `affected` output).
- `explain`/`neighbors` arrows show real edge direction: `-->` the node
calls/imports the neighbor, `<--` the neighbor calls/imports the node.
- Identifier-shaped string literals (env vars like `PLANE_URL`, snake_case
keys like `needs_human`, dotted/kebab/slash chains like
`harness/hr-101-fix-redis-leak`) are indexed as global `reference` nodes
with `references` edges — so "where is this config key / status value
used?" is a graph query, not a grep. Query output ends with a
`# graph built at <timestamp>` line so you can judge freshness.
## Command Reference
### `astria run <path>`
Full pipeline: detect → extract → build → cluster → analyze → report.
Creates `.astria/` with `db.sqlite`, `graph.json`, `graph_report.md`.
Optional enrichment (each needs a semantic backend: `ASTRIA_LLM_API_KEY` /
`OPENAI_API_KEY` / `GEMINI_API_KEY`):
- `--label-communities` — names communities thematically with one LLM call
per *changed* community (membership-hash cached; unchanged groups cost
nothing on later runs). LLM labels carry provenance (`label_source`), so
a themed label is always distinguishable from a deterministic one.
- `--deep` — second extraction tier: one LLM call per file links the file's
symbols to concept nodes from other files as INFERRED edges
(`context='deep'`). Cached per file content hash — an unchanged file is
never re-billed.
- `--judge jev` — TypeSafe decision layer over the backend: gates trivial
files before they cost engine calls, re-judges relations/node types from
the allowlists, drops spurious edges, and stores a calibrated
`confidence_score` on semantic edges. Needs an explicit backend (Jev
cannot generate extractions itself); judge calls count toward the budget.
- `ASTRIA_LLM_BUDGET` caps total tokens for a run; every backend response's
usage block is counted and printed after the run.
### `astria update <path>`
Incremental rebuild — only re-extracts files that changed (SHA-256 detection).
Much faster than `run` for existing projects.
Options (all also available on `run`, except `--quiet`/`--if-stale`):
- `--no-dedup` — skip near-duplicate node merging
- `--backend <name>` / `--model <name>` — semantic LLM backend (claude, openai, gemini) and model
- `--judge jev` — optional decision layer over the backend (gate, verify, calibrated edge confidence)
- `--embed` — compute local embeddings: `similar_to` edges + semantic query recall
- `--label-communities` — name changed communities thematically (one LLM call per changed community)
- `--deep` — second extraction tier: LLM-linked cross-file concept edges
- `--quiet` — suppress progress lines and the token benchmark (for hooks/CI)
- `--if-stale <minutes>` — skip the rebuild entirely when the graph is fresher than N minutes
### `astria health [options]`
Code-health report (heuristic 0-100 score): unreachable-symbol candidates,
circular file dependencies, hub concentration, graph staleness. `--json` for
machines. Read-only.
### `astria risk [options]`
Maps the current git diff (or `--staged`) onto the graph and renders the
blast radius — impacted symbols by depth, communities touched, review
focus — as a PR-ready report with a heuristic risk score. `--json` for CI.
### `astria query <question> [options]`
BFS (default) or DFS graph traversal from nodes matching your question.
```
astria query "authentication" # BFS, depth 2, budget 2000
astria query "database" --dfs --depth 3 # DFS, deeper
astria query "error handling" --budget 3000 # more output
```
Options:
- `--dfs` — depth-first search (traces specific paths)
- `--depth <n>` — traversal depth (default: 2)
- `--budget <n>` — token budget for output (default: 2000)
- `--directed` — follow edges only in their stored direction (caller -> callee, importer -> module)
- `--detail high` — keep only EXTRACTED/DECLARED facts, dropping inferred/semantic edges
- `--cursor <n>` — continuation token from a previous truncated query
- `--graph <path>` — project root (default: `.`)
### `astria explain <node> [options]`
Show a node's details and all its connections.
```
astria explain "UserService"
```
### `astria path <A> <B> [options]`
Find shortest path between two concepts.
```
astria path "AuthService" "Database"
astria path "AuthService" "Database" --directed # only caller -> callee direction
```
### `astria affected <node> [options]`
Blast radius — everything impacted by changing a node (reverse reachability over calls/imports/uses).
```
astria affected "UserService" --depth 3
astria affected "UserService" --relation calls
```
### `astria map [options]`
Aider-style repo map: files ranked by PageRank over the reference graph, with each file's most-connected symbols. Best first command when orienting on a codebase.
```
astria map --budget 2000
```
### Semantic layer (local embeddings)
When the graph was built with `run --embed`, `query` automatically merges semantic recall with token matching — conceptual questions with zero string overlap still find their symbols, and `similar_to` edges link related concepts across files. No API key; the model is downloaded once and cached (`ASTRIA_EMBED_CACHE_DIR` overrides the location).
### Learning from usage
Repeated queries leave a trace: node pairs that keep coming up across distinct questions are promoted to `learned` edges on the next `run`/`update`. The graph gets better connected in exactly the places the codebase is actually explored.
### MCP server
`astria mcp --graph .` runs an MCP stdio server exposing the graph to AI agents with tools: `query_graph` (supports `cursor` continuation and `detail` tiers), `repo_map`, `explain`, `get_neighbors`, `shortest_path`, `affected`, `god_nodes`, `list_communities`, `graph_stats`, `health`.
### Git hooks
`astria hook install|uninstall|status` — per-machine git hooks that run a quiet, freshness-throttled `astria update .` after every code commit and branch switch, so the graph stays current without anyone remembering to run `update`. Skips during rebase/merge; re-run `astria hook install` after upgrading astria to refresh the installed template. `astria hook-guard <mode>` installs the editor PreToolUse guard (`search | read | gemini`).
### `astria stats [options]`
Quick graph health check: node count, edge count, communities, files.
### `astria status [options]`
Graph staleness check: fresh/stale/very_stale with age in minutes.
### `astria export [options]`
Export graph to JSON, HTML, GraphML, SVG, Cypher (Neo4j), or FalkorDB Cypher.
```
astria export --format html --out graph.html
astria export --format svg --out graph.svg # static, embeds anywhere
astria export --format graphml --out graph.graphml
astria export --format cypher --out astria.cypher # idempotent MERGE script for Neo4j
astria export --format falkordb --out astria.cypher # Cypher for FalkorDB/Redis
```
`--format html` writes a self-contained interactive viewer (opens as community bubbles; click to expand, search symbols or community names to jump, focus a node to see its relation-labeled neighbors, "All nodes" for the full graph). `--mode standard` allows up to 5,000 nodes; `--mode large` lifts the cap. For a filesystem-hierarchy view instead, `astria tree --out tree.html`.
`--neo4j-push <bolt://host:port>` pushes the cypher export live to Neo4j; `--redis-push <host:port>` pushes a falkordb export to FalkorDB/Redis. (Obsidian is a wiki format: `astria wiki --format obsidian`.)
### `astria wiki [options]`
Wikipedia-style markdown wiki of the graph: `index.md` plus one article per community and per god node, cross-linked with relative markdown links. Readable by any agent without the CLI — point an agent at `.astria/wiki/index.md` and it navigates by reading files.
```
astria wiki --graph . # writes .astria/wiki/
astria wiki --out docs/wiki # e.g. for GitHub
astria wiki --format obsidian --out my-vault # Obsidian vault + canvas
```
## Post-Edit Protocol
With git hooks installed (`astria hook install`), the graph refreshes itself after every commit — nothing to do.
After modifying code files in a session with an active graph (no hooks):
```bash
astria update .
```
Or start a watcher at session beginning:
```bash
astria watch . --debounce 3000
```
This keeps the graph current so subsequent queries reflect your changes.
## Troubleshooting
**"Graph is empty (0 nodes)"**
- Run `astria run .` to build from scratch
- Check that the directory has supported file types
**"Query returns no results"**
- Try different search terms (partial matches work)
- Use broader terms: "auth" instead of "authenticateUserWithOAuth"
- Check `astria stats` to verify graph has data
**"Graph seems stale"**
- Run `astria update .` for incremental refresh
- Or `astria run .` for full rebuild
**"Status says stale"**
- The `graph.json` was built more than 30 minutes ago
- Run `astria update .` before querying