Skip to main content

Codebase knowledge management CLI for AI coding agents

Project description

relic

CI PyPI Python 3.11+ License: MIT

Relic solves the cold-read problem in AI coding agents.

Every time an agent opens a file it reads that file, then the files it imports, then the files those import — just to understand what connects to what. That's 5-10 file reads before it can start on your actual task. Every read costs tokens.

Relic builds a static knowledge graph from your source code in seconds (no LLM). Before the agent touches any file, it calls relic_query and gets:

  • What that file exports (symbol names, signatures, line numbers, intent from docstrings)
  • What it imports (resolved paths, not guesses)
  • What else in the codebase depends on it (callers at the symbol level)
  • Which test file covers it
  • Class inheritance chains
  • Decorator/annotation index (search by @pytest.mark.parametrize, @app.route, etc.)
  • String literal index (search by quoting: relic_search '"payment failed"')
  • Full blast-radius of any change (relic impact) — every file transitively affected
  • Shortest dependency path between any two files or symbols (relic path A B)
  • Architecture clusters — file communities discovered from the import graph (relic communities)
  • Graph centrality weights — PageRank + betweenness to find load-bearing files (relic centrality)
  • Circular dependency detection across the full file graph (relic cycles)
  • Interactive D3 force-directed knowledge graph in the browser (relic viz)

300–1200 tokens. Via MCP — works with Claude Code, Cursor, Copilot, and any MCP-compatible agent.

Relic also measures its own cost. relic audit shows exactly what relic adds to your agent's context (instructions block + MCP tool schemas) and proves it's a fraction of what it saves. No "trust us" — verifiable per project.


When to use relic

Relic pays off when your codebase is too large for an agent to hold in context at once — roughly 40+ files or 80k+ tokens. Below that threshold, an agent can read files directly and relic adds friction without much payoff.

relic index detects this automatically and warns you if your codebase is small. If it does, run relic --uninit claude to remove the MCP registration and let the agent work directly. You can always re-enable with relic --init claude.

relic benchmark <file> --vs ripgrep shows the exact token difference on your actual codebase, so you can decide with data rather than guessing.


How it works

relic init              # scan project, build knowledge graph (seconds, no LLM)
relic --init claude     # write CLAUDE.md + register MCP server in .mcp.json

Agent calls relic_query before touching unfamiliar code:

focus: src/core/PageExtension.ts

neighbors[9]{path,language}:
  src/types.ts,typescript
  src/layout/presets.ts,typescript
  src/pagination/PaginationPlugin.ts,typescript
  ...

exports[8]{name,type,line,signature,intent}:
  resolvePageSize,function,21,resolvePageSize(doc: PageDocument) -> number,Compute the effective page size for a document
  resolveMargins,function,29,resolveMargins(config: MarginConfig) -> Margins,Apply margin config to a page layout
  resolveHeader,function,38,resolveHeader(page: Page) -> HeaderBlock,Build the header block for a page
  FolioStorage,interface,67,FolioStorage,
  ...

imports[8]{from,to}:
  src/core/PageExtension.ts,src/types.ts
  src/core/PageExtension.ts,src/layout/presets.ts
  ...

imported_by[1]{from,to}:
  src/index.ts,src/core/PageExtension.ts

tested_by[1]{source,test}:
  src/core/PageExtension.ts,tests/PageExtension.test.ts

callers[2]{file,symbol}:
  src/index.ts,resolvePageSize
  src/render/engine.ts,resolveMargins

Agent knows the structure — including signatures, intent, test files, and callers — before reading the code. Fewer follow-up reads. No hallucinated imports. No surprise broken callers.


Install

pip install relic-graph

Or with uv:

uv tool install relic-graph

If relic is not found after install:

uv tool update-shell

Then open a new terminal tab.

Upgrade

pip install --upgrade relic-graph

Or:

relic --update

Local dev

uv tool install --editable . --force

Setup

Run all setup commands in your terminal — not inside the agent.

1. Initialize and index

cd your-project
relic init

Scans the entire project tree, builds the knowledge graph via static analysis (no LLM), and adds .knowledge/ to .gitignore. No config file required — every source file with a recognized extension is indexed automatically.

To rebuild after changes:

relic index

Shows a delta (what changed since last index), which directories were skipped, and how many files were excluded by .relicignore. After the first relic index, agents call relic_reindex themselves — it's incremental (sub-second) and the response header tells them when it's needed.

Optional: To exclude files from indexing, create a .relicignore in your project root (same syntax as .gitignore):

generated/
*.pb.py
vendor/**

Optional: If you want subproject labels (for filtering search results), create a relic.yaml manually:

subprojects:
  api:
    path: ./src/api
    description: REST API
  web:
    path: ./src/web
    description: Frontend

2. Wire your agent

relic --init claude     # Claude Code    → CLAUDE.md + .mcp.json
relic --init copilot    # GitHub Copilot → .github/copilot-instructions.md + .vscode/mcp.json
relic --init cursor     # Cursor         → .cursorrules + .cursor/mcp.json
relic --init codex      # OpenAI Codex   → AGENTS.md
relic --init all        # all of the above

Writes agent instructions and registers the relic MCP server in the right config file per agent. Re-running is safe — updates the existing block without duplicating.


MCP tools

Relic exposes four tools over MCP (stdio transport). Every response is prefixed with an index{age_s,stale,files_changed} freshness header and a cost{response_tokens,focus_file_tokens} header so agents know when to reindex and can decide whether to skip a query on small files.

Tool When to call
relic_query Before editing unfamiliar code — returns imports, exports (with intent), signatures, neighbors, callers, calls, decorators, test files. Supports batch ("A B C"), dotted notation (Class.method), include_intent toggle. Shorthands: "impact:TARGET" for blast-radius, "A->B" for shortest path.
relic_search When you don't know where a class/function/file lives. Quote the query ("error message") to search string literals inside function bodies.
relic_reindex When the response header reports stale=true, or after creating, editing, or deleting source files. Incremental, sub-second.
relic_diff When you want a per-file breakdown of what changed before reindexing

See docs/MCP.md for full tool reference and agent setup.


Query context manually

relic query src/core/PageExtension.ts
relic query resolveMargins                         # by symbol name
relic query PageExtension.resolveMargins           # dotted notation — scoped to one symbol
relic query "src/foo.ts src/bar.ts"                # batch — merged TOON for multiple targets
relic query src/core/PageExtension.ts --depth 3    # wider graph

Output is TOON (Token-Oriented Object Notation) — tabular format that declares column names once and lists values row by row. ~40% fewer tokens than equivalent JSON for the same data.


Keep the index fresh

The agent owns this. relic_reindex is incremental — it stat-sweeps the project tree, reparses only files whose mtime changed, and finishes in well under a second on large repos. Every MCP response carries two headers:

index{age_s,stale,files_changed}: 42,false,0
cost{response_tokens,focus_file_tokens}: 847,312

stale=true means call relic_reindex. cost{focus_file_tokens} lets the agent decide whether a relic_query on a tiny file is worth the roundtrip — if it's under 200 tokens the agent can just read the file directly (SKIP rule). No background watcher process, no extra terminal tab, no separate stats tool.

If you want to rebuild manually (after a big rebase or a tooling change), run relic index — same as before.

Audit coverage

relic coverage
relic coverage --verbose    # list every skipped file

Shows the count and identity of files that were indexed vs silently dropped, classified by reason: no_parser (extension not supported), too_large (over 200 KB), symlink (skipped for safety). Use this when a query unexpectedly comes back empty — it tells you whether the file is a tool limit instead of a model error.

Check for drift

relic diff

Compares on-disk source files against the last indexed graph. Shows new files, deleted files, and changed symbols (added or removed functions/classes). Agents use this to decide whether to call relic_reindex after big PR merges. Humans use it to sanity-check the index before a session.


Verify relic's own cost

relic audit
relic audit --usage    # show MCP tool call counts from .knowledge/usage.json

Shows three numbers: the instructions block written to CLAUDE.md / .cursorrules / AGENTS.md, the MCP tool schemas the agent loads every turn, and a sample relic_query against your real graph. --usage adds a breakdown of how many times each MCP tool was called.

⬢  audit
   instructions block     ~651 tokens   CLAUDE.md / .cursorrules / AGENTS.md
   mcp tool schemas       ~365 tokens   4 tools, every turn
   ─────────────────────────────────
   baseline tax / turn  ~1,016 tokens

   sample query · src/core/PageExtension.ts · depth=2
   relic_query response  ~5,627 tokens
   manual baseline      ~27,952 tokens
   net savings          ~22,325 tokens (80%)

✓ baseline tax under 1,500 tokens — within healthy range

Background: 90-day instrumentation of Claude Code sessions found that 73% of tokens go to invisible chrome (CLAUDE.md bloat, MCP schemas, hooks, skills) before the agent reads a single user message. Relic's pitch is "save tokens" — it would be dishonest if relic itself were part of the problem. CI guards keep the instructions block under 800 tokens and the MCP schemas under 500 tokens. Loosening either is a deliberate decision, not a drift.

Benchmark token savings on a real file

relic benchmark src/core/PageExtension.ts
relic benchmark src/core/PageExtension.ts --depth 2

For a single target file, prints what an agent would read manually (target file + every direct import), what relic provides instead (one TOON subgraph + the target file), and the resulting savings. Also surfaces the imported_by callers — files an agent has no way to discover from the file alone.


relic init vs relic index

relic init relic index
When First-time setup After code changes
Builds graph Yes Yes
Adds .knowledge/ to .gitignore Yes No
Shows delta No Yes (new/removed files, symbols, edges)
Shows skip stats No Yes (skipped dirs, .relicignore exclusions)

Run relic init once per project. After that, the agent's relic_reindex tool keeps the graph current incrementally; only run relic index again if you want a manual full rebuild.


Commands

relic init                         # first-time setup: build graph, configure .gitignore
relic index                        # rebuild graph, show delta + skip stats
relic query <file|symbol>          # print TOON context subgraph to stdout
relic query Class.method           # symbol-scoped query via dotted notation
relic query "fileA fileB"          # batch query — merged TOON output
relic query <file> --depth N       # adjust traversal depth (default 2)
relic search <term>                # ranked search across files and symbols
relic search '"literal text"'      # search string literals inside function bodies
relic search <term> -k symbol      # filter to symbols (or `file`, `all`)
relic search <term> -s <name>      # restrict to a subproject
relic impact <file|symbol>         # blast-radius: every file transitively affected
relic path <source> <dest>         # shortest dependency path between two nodes
relic communities                  # show file clusters from Louvain graph clustering
relic centrality [--top N] [--by pagerank|betweenness|in_degree|out_degree]
relic cycles [--limit N]           # detect circular dependencies in the file graph
relic viz [--out path.html]        # open interactive D3 knowledge graph in browser
relic stats                        # index health: counts, last_updated, subprojects
relic diff                         # what changed since last index (new/deleted/changed)
relic coverage                     # what's indexed vs skipped, with reasons
relic coverage -v                  # list every skipped file (not just samples)
relic audit                        # measure relic's own token footprint
relic audit --usage                # show per-tool MCP call counts
relic benchmark <file>             # compare token cost of context with vs without relic
relic benchmark <symbol> --vs ripgrep  # compare relic vs ripgrep for a symbol search
relic mcp                          # start MCP stdio server (4 tools)

relic --list                       # list subprojects (if relic.yaml exists)
relic --init <agent>               # write agent config + MCP registration
relic --init all                   # write config for all supported agents
relic --uninit <agent>             # remove relic MCP registration + instructions
relic --uninit all                 # remove for all agents
relic --update                     # install latest GitHub release
relic --version                    # print version

What gets indexed

Language Files Symbols + Signatures Intent Decorators Imports Calls Inheritance Test mapping
Python classes, functions (full signatures) ✓ (docstring) ✓ (@decorator) ✓ (ast) ✓ (ast) ✓ (extends) ✓ (test_foo.py)
TypeScript / TSX classes, functions, interfaces, types ✓ (leading comment) ✓ (@decorator) ✓ (regex) ✓ (extends) ✓ (foo.test.ts)
JavaScript / JSX classes, functions ✓ (leading comment) ✓ (@decorator) ✓ (regex)
Go structs, interfaces, functions ✓ (leading //)
Rust structs, enums, traits, functions ✓ (leading ///) ✓ (#[attr]) ✓ (impl)
Java classes, interfaces, methods ✓ (Javadoc) ✓ (@Annotation) ✓ (extends)
C# classes, interfaces, methods ✓ (leading //) ✓ ([Attr])
Kotlin classes, functions ✓ (leading //)
Scala classes, traits, objects, functions ✓ (leading //)
PHP classes, interfaces, functions ✓ (leading //)
Swift classes, structs, protocols, functions ✓ (leading //)
Markdown H1/H2 headings as symbols
OpenAPI YAML/JSON HTTP endpoints (GET /path) ✓ (summary)
JSON Schema definitions/$defs entries ✓ (description)
pyproject.toml package name + script entry points ✓ (description)
package.json package name + npm scripts ✓ (description)

Go, Rust, Java, C#, Kotlin, Scala, PHP, and Swift support requires the optional treesitter extra:

pip install relic-graph[treesitter]

Graph analysis

Blast-radius before refactoring

relic impact src/core/payments.py
relic impact PaymentProcessor

Shows every file that transitively imports, uses, or calls the target — and how many hops away each is. Run this before renaming a class or changing a function signature. Agents can call the same analysis via relic_query "impact:TARGET".

Shortest path between two nodes

relic path src/api/views.py src/core/database.py
relic path UserSerializer PaymentProcessor

Finds the shortest chain of import/call/use edges connecting SOURCE to DEST, with each hop's edge type and evidence label (ast/treesitter/regex/convention). Useful for understanding unexpected coupling. MCP shorthand: relic_query "src/api/views.py->src/core/database.py".

Architecture communities

relic communities
relic communities --limit 10

Runs Louvain clustering on the file import graph and prints each community as a TOON table. Communities represent cohesive module boundaries — files that strongly import each other end up together. Useful for spotting unexpected cross-module coupling or planning a monorepo split.

Graph centrality

relic centrality --top 10
relic centrality --by betweenness

Computes PageRank and betweenness centrality on the file dependency graph. PageRank identifies the most structurally important files (many important files depend on them). Betweenness identifies bridge files that sit between communities — highest risk to change. Run before a refactor to find load-bearing files.

Circular dependency detection

relic cycles
relic cycles --limit 5

Detects all circular import chains in the file dependency graph using nx.simple_cycles(). Cycles are shown as chains sorted by length. Each cycle is a set of files that mutually depend on each other — fix by extracting shared code into a common module. MCP shorthand: relic_query "cycles".

Interactive knowledge graph

relic viz
relic viz --out graph.html   # save instead of opening

Opens a self-contained D3.js force-directed graph in your browser. Node size = PageRank, color = community (Nord palette), edge opacity = evidence quality (ast > treesitter > regex > convention). Features:

  • Click any node → blast-radius overlay (red = affected files) + side panel with metadata
  • Double-click any node → focus mode: collapses graph to 2-hop neighborhood, auto-zooms to fit
  • Double-click canvas → exit focus mode
  • Filter dropdowns → filter by language, community, or subproject with auto-zoom to matching nodes
  • Search box → highlight matching nodes by filename
  • Zoom controls → in/out/reset

Agentic pipelines (LangGraph, custom orchestrators)

Relic slots into multi-agent workflows. One relic index call, every agent in the chain benefits.

Typical integration:

  • Orchestratorrelic_query to identify relevant files without reading them, scope the task cheaply
  • Planning agent — knows the dependency graph before planning, avoids plans that break callers
  • Implementation agent — gets exact symbol names and paths, no hallucinated imports
  • Review agent — sees imported_by edges, knows what to test beyond the changed file

Register once per project, all agents in the session get all four relic tools natively.


Token comparison

Approach Context per file touch
Agent reads file + all imports manually 5,000–40,000 tokens
relic_query (depth=1) 300–1,200 tokens
relic_query (depth=2) 800–3,000 tokens

Security

Static analysis only — relic never executes your source. Python is parsed with ast.parse (parse-only, no eval); TypeScript and JavaScript are matched with regex. Reading a malicious repo cannot run code through relic.

Path traversal prevention — if subproject paths are defined in relic.yaml, they are resolved and checked against the project root. Entries like path: /etc or path: ../../secrets are rejected.

Symlinks skipped — the indexer ignores all symbolic links during traversal, so a malicious symlink pointing outside the project cannot pull foreign files into the graph. Same rule applies to relic coverage and incremental reindexes.

File size limit — skips files over 200 KB. Bounds per-file work and prevents a single bloated file from dominating the index.

No filesystem writes outside the project — relic only writes to .knowledge/ and (when explicitly invoked) .gitignore and the agent config files you ask it to update.

No external calls — no API calls, no telemetry. Code never leaves your machine. The only network calls relic makes are during relic --update: one GitHub API call to find the latest release tag, then uv tool install to reinstall from that tag.

For vulnerability reports see SECURITY.md.


Contributing

PRs welcome. See CONTRIBUTING.md for setup, conventions, and what we will (and won't) accept.


License

MIT

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

relic_graph-0.8.1.tar.gz (186.5 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

relic_graph-0.8.1-py3-none-any.whl (85.3 kB view details)

Uploaded Python 3

File details

Details for the file relic_graph-0.8.1.tar.gz.

File metadata

  • Download URL: relic_graph-0.8.1.tar.gz
  • Upload date:
  • Size: 186.5 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for relic_graph-0.8.1.tar.gz
Algorithm Hash digest
SHA256 6b878afb03f58a59bf08c4027e3d8dca7db97b612274f3e5e1110670a1f7fb6d
MD5 08bc415edc7de51c67875c1ba3b152aa
BLAKE2b-256 3af95cc59e9fdd5321d7a405815cdcfdc877d0bc58ed060d85ec64a8c5d6600d

See more details on using hashes here.

Provenance

The following attestation bundles were made for relic_graph-0.8.1.tar.gz:

Publisher: release.yml on Swanand58/relic

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file relic_graph-0.8.1-py3-none-any.whl.

File metadata

  • Download URL: relic_graph-0.8.1-py3-none-any.whl
  • Upload date:
  • Size: 85.3 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for relic_graph-0.8.1-py3-none-any.whl
Algorithm Hash digest
SHA256 45cfefb4d9d2b40465542bfd4d5688af6ce69dfa2a1f897f2b94b99c7e1688d8
MD5 c390524be551c7ec6e15600eb62ec685
BLAKE2b-256 61c3612e137a7db4858b8a79ba010144733829123521a12e0e927d08c5b818f8

See more details on using hashes here.

Provenance

The following attestation bundles were made for relic_graph-0.8.1-py3-none-any.whl:

Publisher: release.yml on Swanand58/relic

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page