Commands reference

All commands run against the current directory. Run stacklit <command> --help for the built-in help.

Command Purpose
init First-time scan, write all outputs, open the visual map
generate Regenerate the outputs from current source
view Rebuild stacklit.html from stacklit.json and open it
diff Check whether the index is stale
derive Print the compact navigation map, or inject it into an agent config file
export Render the index as markdown, or export the graph as GraphML, Cypher, JSON, DOT, Mermaid, an Obsidian vault or a markdown wiki
setup Configure detected AI tools and install the git hook
serve Run the MCP server over stdio
graph, query, explain, impact, path, hubs, communities, report, slice, watch Symbol-level graph and token-budgeted queries
doctor Diagnose config, hooks, a stale index and parse errors
ingest Add docs, OpenAPI, SQL schemas and ownership to stacklit.context.json
check Enforce layer boundaries, cycles, fan-in and fan-out limits and orphans (exit code 3 on violation)
merge-graphs Merge symbol graphs from several repos and link them by package names
completion Shell completions for bash, zsh, fish and PowerShell

Global flags: --version, --help.

stacklit init

stacklit init [--hook] [--summary] [--multi FILE] [--workspace PATH]

Scans the current directory, writes stacklit.json, DEPENDENCIES.md and stacklit.html, then opens the HTML in your default browser.

Flag Description
--hook Install a git post-commit hook that runs stacklit generate --quiet and stages stacklit.json and the configured mermaid file (DEPENDENCIES.md by default). An existing hook is appended to, never replaced. (The flag’s built-in help text says “pre-commit”; the hook that is installed is post-commit.)
--summary Add an AI-written architecture narrative to the index. This is the only opt-in feature that sends data anywhere, see Summary.
--multi FILE Polyrepo mode: scan every repo path listed in FILE. See Polyrepo scanning.
--workspace PATH Accepted but currently has no effect on the scan. Monorepo workspaces are detected automatically.

stacklit generate

stacklit generate [--quiet]

Same scan and outputs as init, without opening a browser. Use this in scripts, hooks and CI.

Flag Description
--quiet Suppress progress output

stacklit view

stacklit view

Reads stacklit.json, rewrites stacklit.html and opens it. It does not rescan the source, so run generate first if the code changed.

The HTML is one self-contained file with four views:

  • Graph: force-directed dependency map. Click a node for exports, types and files.
  • Tree: collapsible directory hierarchy with file and line counts.
  • Table: sortable module table with search.
  • Flow: top-down dependency flow from entrypoints to leaves.

A Share button downloads a standalone copy.

stacklit diff

stacklit diff

Recomputes a content hash (Merkle hash) of the current source files and compares it with the merkle_hash stored in stacklit.json. It prints either “Index is up to date” or tells you to run generate. It exits with status 0 in both cases, so scripts should compare the output text or use the GitHub Action’s check mode. Requires an index that has a merkle_hash field.

stacklit derive

stacklit derive [--inject claude|cursor|aider]

Prints a compact navigation map built from stacklit.json: one header line, an entry and test line, one line per module with its purpose and key dependencies, hot files, the add-feature hint and do-not-touch paths. Size grows with the number of modules: 122 tokens for a 6-module Go repo, 1,122 for a 72-module TypeScript repo (see bench/RESULTS.md).

Flag Description
--inject TARGET Insert or replace the map, between marker comments, in CLAUDE.md (claude), .cursorrules (cursor) or .aider.conf.yml (aider). The file is created if missing. Re-running replaces the previous block.

stacklit export

stacklit export [--format md] [--source FILE] [-o FILE]

Renders the index as markdown for people: a PR description, an issue, a chat message.

Flag Default Description
--format md md, or a graph format: graphml, cypher, json, dot, mermaid, obsidian, markdown-wiki
--scope auto Graph scope for single-file graph formats: modules or symbols. Auto picks symbols when stacklit.graph.json exists.
--graph stacklit.graph.json Symbol graph file for graph formats
--budget 2000 Token budget per markdown-wiki page. Env: STACKLIT_EXPORT_PAGE_TOKENS.
--source stacklit.json Index file to read
-o, --output stdout Write to this file (one-file formats) or directory (obsidian, markdown-wiki) instead

The markdown contains the project title and totals, a language and framework table, entrypoints and key directories, a modules table, collapsible per-module export lists, the dependency edges with most-depended and isolated modules, hot files when git data exists, and the hints. Output is deterministic: the same stacklit.json always gives byte-identical markdown.

Graph formats

Graph formats print to stdout unless you pass -o, and never write into the repo on their own. Every node carries source_file, and symbol edges carry their confidence (EXTRACTED, INFERRED or EXACT) and score.

Format Output
graphml One GraphML file (Gephi, yEd, NetworkX)
cypher CREATE and MATCH ... CREATE statements for Neo4j and compatible stores
json {scope, nodes, edges}
dot Graphviz. Inferred edges are dashed. Capped to the highest-degree nodes (STACKLIT_EXPORT_MAX_NODES, default 300).
mermaid Mermaid flowchart with the same cap
obsidian A vault folder: Index.md plus one note per module with [[wikilinks]] to dependencies, and symbol headings that other notes link to as [[module#Symbol]]
markdown-wiki index.md plus modules/<module>.md, each page cut off at the token budget with a ”… N more” line. Same input gives identical files.
stacklit export --format graphml -o /tmp/graph.graphml
stacklit export --format obsidian -o ~/vault/myproject
stacklit export --format markdown-wiki --budget 1500 -o /tmp/wiki

stacklit setup

stacklit setup [claude|cursor|aider]

Uses the existing stacklit.json, or generates one if none exists, then configures AI tools:

Target Detected by What it changes
claude claude on PATH or a CLAUDE.md file injects the map into CLAUDE.md, adds the stacklit server to .mcp.json
cursor a .cursor directory or .cursorrules injects the map into .cursorrules, adds .cursor/mcp.json
aider aider on PATH or .aider.conf.yml injects the map into .aider.conf.yml

With no argument it configures every detected tool and installs the post-commit hook. If no tool is detected it prints the map to stdout so you can paste it. .mcp.json is listed in this repository’s .gitignore because it is user-specific; decide for your own repo whether to commit it.

Claude Code crawl guard (opt in): stacklit setup claude --crawl-guard[=nudge|redirect|off] installs a PreToolUse hook that recognises repo-wide crawls (find ., ls -R, tree, grep -r or rg on the root, Glob **/*, a Read of a directory, generic “explore the codebase” subagent prompts). A bare --crawl-guard means nudge; pass a mode with =. nudge adds a pointer to the stacklit command. redirect denies with a reason naming the command, at most twice in a row per session and only while the index is current. off removes the hook, as does --uninstall. Supports --dry-run. Details in docs/SESSIONS.md.

stacklit guide

stacklit guide [--json]

Prints the agent usage guide (rules, command list, examples). It is the same text the strict rules block (steering d) uses, so you can paste it into any tool.

stacklit refresh, digest and stats

Session plumbing, see docs/SESSIONS.md for the design.

stacklit refresh --files a.go,b.go [--json]    # or: --stdin with a hook payload
stacklit digest [--check] [--session ID]
stacklit stats [--json] [--since 7d]
  • refresh updates stacklit.json (and stacklit.graph.json when it exists) for just the named files. Unchanged files are skipped by content hash, concurrent callers coalesce behind a lock, and writes are atomic. The result matches a full generate.
  • digest prints the structure hash (module names, edges and exported names only). --check exits 0 when it equals what a session was given, 1 when it changed, 2 when nothing was recorded.
  • stats reports the opt-in local usage log (STACKLIT_STATS=1). served is measured (bytes/4); replaced_est is an estimate of whole-file read cost, not a measured saving.

Claude Code hooks (opt-in, written to .claude/settings.json, or ~/.claude with --global):

Flag Installs
--session-hook SessionStart for startup, resume, clear and compact; SubagentStart for Explore and Plan
--refresh-hook async PostToolUse on Edit, Write, MultiEdit and NotebookEdit

stacklit serve

stacklit serve

Starts the MCP server on stdio. Run it from the repo root: it reads stacklit.json from the working directory. See MCP server.

Symbol graph commands

stacklit graph                          # build stacklit.graph.json (query commands build it in memory if it is missing)
stacklit query "where is auth checked?" # scoped subgraph for a question, hard limit via --budget (default 2000 tokens)
stacklit explain <symbol>               # definition, location, callers, callees (--budget, default 1500)
stacklit impact <symbol|file>           # everything that depends on it (--depth, default 4)
stacklit path <from> <to>               # shortest path between two symbols
stacklit hubs -n 15                     # most connected symbols
stacklit communities                    # deterministic file clusters with labels
stacklit report -o GRAPH_REPORT.md      # key concepts, surprising links, suggested questions
stacklit slice <symbol>                 # only that symbol's source, with line numbers
stacklit watch                          # keep the graph current as files change

query prints files in relevance order: each file group is numbered (1. path) by the best score among its symbols (ties by path), symbols inside a file go by score then line, and a best match: <file>:<line> <symbol> line names the top result. Output is byte-stable between runs, and the --budget limit drops the lowest ranked results first. --order relevance|path picks the layout; path is the older alphabetical grouping with no numbers (default from STACKLIT_QUERY_ORDER, otherwise relevance). With --json each file has rank (1 is best) and score (0 to about 1.2, relative to the best seed), each symbol has its own score, and files stay in the printed order. The MCP query_graph and query tools return the same text. Two scoring knobs: STACKLIT_AUX_PENALTY (default 0.6) multiplies the score of files under test, example, benchmark or fixture directories unless the question mentions them (1 turns it off), and STACKLIT_IDENT_TOKEN_BOOST (default 0.5) raises symbols named exactly like a camelCase or snake_case word in the question.

All of them accept --root, --graph, --include-tests (keep test files in the graph; also STACKLIT_GRAPH_INCLUDE_TESTS=1) and (except watch) --json. Twenty languages produce symbols and call, import and inheritance edges; the per-language table is in docs/ARCHITECTURE.md. STACKLIT_GRAPH_MAX_PARSE_BYTES (default 196608) sets the largest file parsed with tree-sitter, and STACKLIT_PARSE_MEMORY_MB bounds concurrent parse memory. watch uses fsnotify and falls back to polling above STACKLIT_WATCH_MAX directories (default 4096); STACKLIT_WATCH_POLL_MS sets the polling interval.

stacklit doctor

stacklit doctor [path] [--json] [--strict]

Checks the config file, git hook, index freshness and parse errors. --strict also fails on warnings.

stacklit ingest

stacklit ingest [--docs] [--api] [--schema] [--owners] [--git-owners]

Writes stacklit.context.json next to the index and leaves stacklit.json untouched. With no connector flag, all but --git-owners run. Limits: STACKLIT_INGEST_MAX_BYTES, STACKLIT_INGEST_MAX_ITEMS.

Adapters

stacklit ingest --adapter "<command>" [--adapter-name NAME] [--adapter-files GLOBS] [--into-graph]

Runs your command with file paths on stdin (one per line, relative to the root) and reads JSON Lines back: {"type":"node","id","name","kind","summary","source_file"} and {"type":"edge","from","to","kind"}. Use it for concepts from PDFs, images, audio or anything else stacklit does not parse. Results are stored in stacklit.context.json as concepts and concept_links, always tagged INFERRED with a source field, and a rerun replaces that adapter’s earlier output. --into-graph also adds them to stacklit.graph.json as concept nodes. Stacklit makes no network or model calls itself. Limits: STACKLIT_ADAPTER_TIMEOUT_SEC (60), STACKLIT_ADAPTER_MAX_BYTES (4 MiB), STACKLIT_ADAPTER_MAX_ITEMS (5000). The full contract and an example are in examples/adapters.

SCIP

stacklit ingest --scip index.scip [--graph stacklit.graph.json]

Reads a SCIP index (from scip-go, scip-typescript and similar) with a built-in decoder and upgrades INFERRED graph edges to EXACT where the index shows a reference from the edge’s source to a symbol defined at its target. It never adds or removes edges and rewrites the graph file in place. Size cap: STACKLIT_SCIP_MAX_BYTES (512 MiB).

stacklit check

stacklit check [--root DIR] [--source stacklit.json] [--json]

Evaluates the check block of .stacklitrc.json against the module graph. Exit code 3 when any rule is violated, 0 otherwise, so it works as a CI step.

{
  "check": {
    "forbidden": [{ "from": "ui/**", "to": "core/db", "reason": "go through the service layer" }],
    "cycles": true,
    "max_fan_in": 12,
    "max_fan_out": 8,
    "orphans": true
  }
}

Patterns are module paths with * wildcards; dir/** matches dir and everything below it. With no check block the command passes. --json prints {ok, violations:[{rule, message, modules}]}.

stacklit merge-graphs

stacklit merge-graphs a/stacklit.graph.json b/stacklit.graph.json -o merged.json [--multi stacklit-multi.json]

Combines symbol graphs from several repos. Node IDs get a repo: prefix, each node keeps its source_file and gets a repo field. Name a repo explicitly with name=path.json. With --multi (the output of generate --multi), repo nodes and depends_on edges are added for repos that depend on each other through manifest package names, plus import edges from the importing files to the provider repo.