Ariadne
Provides a GitHub Action for CI that performs structural analysis on pull requests, posting comments with impact radius, risk score, public API breaks, and policy status.
Click on "Install Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@AriadneFind all references to the function handleLogin"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
Ariadne
Semantic code index and gatekeeper for AI coding agents. Builds a compiler-grade symbol graph (defs/refs) via SCIP and a file-level dependency graph via import extraction. Exposes queries via CLI and MCP tools.
No LLMs involved — just static analysis.
What it does
Indexes your codebase (TypeScript, Python, Go, Rust, Java/Kotlin, Scala, C#, Ruby) into a SQLite graph of symbols, references, imports, and definitions
Queries let you search symbols, jump to definitions, find all references, trace impact of changes, explore call graphs, and compute structural metrics
Analyzes transitive impact with risk scoring — BFS across the symbol graph to find all affected files, packages, public API breaks, and relevant tests
Detects structural drift — dependency cycles (Tarjan's SCC), module coupling (Ca/Ce/instability), and public API surface tracking with snapshot-based diffing
Enforces architectural policies via
ariadne.policies.json— deny new cycles, cap API growth, limit coupling increasesVerifies repo consistency: stale index detection, empty index detection, missing test runs, type errors, architecture boundary violations, and policy compliance
Indexes non-code artifacts —
.envvars,package.jsonscripts, SQL migrations, OpenAPI schemas — and links them to source referencesIntegrates with Claude Code via hooks (auto-update on edit, gatekeeper on stop) and MCP tools
Works on any existing project — run
setupand it indexes everything from disk
Related MCP server: RepoMap
Install
Standalone binary (recommended)
Download the prebuilt binary for your platform:
curl -fsSL https://raw.githubusercontent.com/simonrueba/ariadne/main/scripts/install.sh | bashOr specify a version: ARIADNE_VERSION=v0.2.0 curl -fsSL ... | bash
Then set up on your project:
ariadne setup /path/to/your/projectFrom source
Requires Bun >= 1.0
git clone https://github.com/simonrueba/ariadne.git && cd ariadne && bun install
# Set up on your project
bun run packages/cli/src/index.ts setup /path/to/your/projectSCIP indexers are optional — structural import analysis works without them. Install per language as needed (see Toolchains by language below). Run ariadne doctor to check what's available.
Quick start
Use on any project (recommended)
# Set up on your project — does everything in one step:
# init → index → generate hooks + MCP config
bun run packages/cli/src/index.ts setup /path/to/your/projectThis creates:
.ariadne/— SQLite database, hook scripts, SCIP cache.claude/settings.json— Claude Code hooks (impact context on edit, auto-update, verify gate).mcp.json— MCP server config (14 read-only tools)ariadne.boundaries.json— auto-generated architecture boundary config (monorepos)
Then restart Claude Code in your project to pick up the hooks and MCP server.
GitHub Action (CI)
Add structural analysis to your pull requests with a single workflow file:
# .github/workflows/ariadne.yml
name: Ariadne Structural Guard
on:
pull_request:
branches: [main]
permissions:
contents: read
pull-requests: write
jobs:
structural-analysis:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- uses: simonrueba/ariadne-action@v1
with:
comment: 'true'
fail-on-policy: 'true'This posts a PR comment with impact radius, risk score, public API breaks, new cycles, test coverage, and policy status. See action/ for full configuration options.
Manual setup (step by step)
# Initialize .ariadne/ directory
bun run packages/cli/src/index.ts init /path/to/your/project
# Build the full index (structural imports + SCIP symbols)
bun run packages/cli/src/index.ts index /path/to/your/project
# Check prerequisites
bun run packages/cli/src/index.ts doctor /path/to/your/project
# Run gatekeeper checks
bun run packages/cli/src/index.ts verify /path/to/your/projectQuery examples
# Search for a symbol
bun run packages/cli/src/index.ts query search "MyFunction"
# Find definition
bun run packages/cli/src/index.ts query def "<symbol-id>"
# Find all references
bun run packages/cli/src/index.ts query refs "<symbol-id>"
# Impact analysis — what's affected by changes to a file?
bun run packages/cli/src/index.ts query impact src/foo.ts
# Detailed impact — includes symbol defs, docs, and reference snippets
bun run packages/cli/src/index.ts query impact src/foo.ts --details
# Call graph — who calls a function, and what does it call?
bun run packages/cli/src/index.ts query call-graph "<symbol-id>"
bun run packages/cli/src/index.ts query call-graph "<symbol-id>" --depth 2
# File dependency graph (imports only)
bun run packages/cli/src/index.ts query module-graph
# Hybrid module graph (imports + SCIP semantic edges with weights)
bun run packages/cli/src/index.ts query module-graph --mode hybrid
# Scoped to a directory
bun run packages/cli/src/index.ts query module-graph --path packages/core/All commands output JSON. Symbol IDs are SCIP symbol strings returned by search.
Transitive impact analysis
# Full transitive impact with risk scoring
bun run packages/cli/src/index.ts impact src/core.ts
# Limit BFS depth
bun run packages/cli/src/index.ts impact src/core.ts --max-depth 2
# Include call graph traversal
bun run packages/cli/src/index.ts impact src/core.ts --call-graph
# Multiple files
bun run packages/cli/src/index.ts impact src/core.ts src/utils.tsReturns: changed symbols (with public API flag), affected files (with depth and reason), affected packages, public API breaks (with downstream consumers), test files (direct vs transitive), risk score and category (low/medium/high/critical), boundary violation risk.
Structural metrics
# Current metrics (coupling, cycles, API surface)
bun run packages/cli/src/index.ts metrics
# Save baseline snapshot
bun run packages/cli/src/index.ts metrics --snapshot
# Diff current vs baseline
bun run packages/cli/src/index.ts metrics --diffPolicy enforcement
Create ariadne.policies.json in your project root:
{
"policies": {
"deny_new_cycles": true,
"max_public_api_growth": 5,
"max_coupling_increase": 3
}
}Policies are checked automatically by ariadne verify. They compare current metrics against the saved baseline snapshot — run ariadne metrics --snapshot to establish the baseline.
CLI commands
Command | Description |
| One-command setup: init + index + generate hooks & MCP config. |
| Create |
| Full index: structural imports + SCIP analysis. |
| Incremental update: structural imports + auto SCIP when dirty source files exist. |
| Fuzzy search symbols by name |
| Get definition location, docs, and code snippet |
| Find all references across the codebase |
| Changed files → impacted symbols → dependent files → recommended tests. |
| Approximate call graph: callers and callees at the given depth (default 1) |
| File dependency graph (imports, semantic, or hybrid) |
| Transitive impact analysis with risk scoring. BFS across symbol graph up to N depths (default 5). |
| Structural metrics: coupling (Ca/Ce/I), dependency cycles, API surface. |
| Compile agent-friendly context for files: symbols, imports, importers, semantic refs. Modes: |
| Pre-edit blast radius analysis: symbols defined in files, their call sites across the codebase, boundary violations, and risk assessment. |
| CI command: runs impact + verify + metrics on changed files vs base branch. Outputs JSON (default) or |
| Run gatekeeper checks including policy enforcement (exit 0 = OK, exit 1 = FAIL) |
| Index stats (file count, symbol count, edge count, dirty count) |
| Mark a file as needing re-index |
| Append event to execution ledger |
| Check prerequisites (Bun, Node, SCIP indexers for all languages) and warn about stale legacy directories |
MCP server
The MCP server exposes 14 read-only tools for AI agents:
Tool | Description |
| Fuzzy search symbols by name |
| Get symbol definition with docs and code snippet |
| Find all references to a symbol (optionally scoped) |
| Blast radius analysis for changed files (with optional |
| Full transitive impact with risk scoring, public API break detection, and affected package mapping |
| Structural metrics: module coupling (Ca/Ce/instability), dependency cycles, API surface per package |
| Dependency cycle detection using Tarjan's SCC algorithm |
| File dependency graph (imports/semantic/hybrid, json/dot/mermaid) |
| Dependency subgraph centered on a specific symbol |
| List all symbols defined in a file |
| Index stats: files, symbols, dirty count, timestamps |
| Approximate call graph: callers and callees for a symbol |
| Agent-friendly file context: symbols, imports, importers, semantic refs via BFS graph traversal |
| Pre-edit blast radius: symbols in target files, call sites, boundary risks, and blast radius summary |
Configuration
ariadne setup generates this automatically. To configure manually, add .mcp.json to your project root:
{
"mcpServers": {
"ariadne": {
"command": "bun",
"args": ["run", "/path/to/ariadne/packages/mcp/src/index.ts"],
"env": { "ARIADNE_ROOT": "." }
}
}
}If you installed via npm (bun add --global ariadne-mcp), use:
{
"mcpServers": {
"ariadne": {
"command": "bunx",
"args": ["ariadne-mcp"],
"env": { "ARIADNE_ROOT": "." }
}
}
}The MCP server starts gracefully even if .ariadne/ doesn't exist yet — it creates the directory and logs a helpful message.
Claude Code hooks
ariadne setup generates .claude/settings.json automatically. The hooks reference portable scripts in .ariadne/hooks/ that resolve the ariadne binary dynamically at runtime.
What the hooks do
Pre-edit impact hook (
Edit|WritePreToolUse): runsariadne impactbefore every source file edit and injects the blast radius (changed symbols, dependent files, recommended tests) as context so Claude sees what will be affected. Silently skips test files, non-source files, and uninitialized projects. ~240ms latency.Post-edit hook (
Edit|WritePostToolUse): marks edited source files dirty, runsariadne update --files <path>for fast single-file updates (no full repo walk), logs the edit to the ledger. Non-source files (README, config, etc.) are skipped to avoid false-positive freshness failures.Post-test hook (
BashPostToolUse): detects test runner commands (vitest, jest, pytest, bun test, mocha, ava, cargo test, go test, mvn test, dotnet test, sbt test, bundle exec, playwright), logstest_runto the ledgerStop hook: runs
ariadne update(auto-triggers SCIP when dirty source files exist), thenariadne verify. On failure, outputs{"decision":"block","reason":"..."}to prevent Claude from stopping until issues are fixed
The stop hook uses atomic mkdir-based locking to prevent concurrent runs, checks stop_hook_active from stdin to prevent infinite loops, and has a 120s stale lock timeout.
All hooks guard against missing .ariadne/ — they silently exit if the project hasn't been initialized.
Gatekeeper checks
ariadne verify runs these checks:
Empty index — fails if zero files are indexed (prevents vacuous pass on uninitialized projects)
Index freshness — checks the dirty set (files marked changed by hooks or
update), filtering to source files only. Fails if any dirty source files exist that haven't been covered by a SCIP index pass. Non-source files are ignored since SCIP can't index them.Missing test runs — checks the ledger for a
test_runevent after the most recentedit. Fails if no tests were run after editing.Typecheck — runs language-appropriate type checkers (
tsc --noEmit,go vet,cargo check,mvn compile,sbt compile,dotnet build) against detected projects. Fails on any type errors. On failure, includes recommendations withariadne query impactandariadne query searchcommands for the affected files and identifiers. Skipped if no supported project is detected.Architecture boundaries — reads
ariadne.boundaries.jsonand checks allimportsedges against layer allowlists. Fails if any file imports from a layer not in itscanImportlist. Skipped if no config file exists.Policy compliance — reads
ariadne.policies.jsonand compares current structural metrics against the saved baseline snapshot. Checks:deny_new_cycles(no new dependency cycles),max_public_api_growth(cap on new exported symbols per package),max_coupling_increase(cap on coupling metric increases per module). Skipped if no config file or no baseline snapshot exists.
Architecture
graph TD
subgraph Indexing Pipeline
A[Source Files<br>.ts .tsx .js .jsx .py .go .rs<br>.java .kt .scala .cs .rb] --> B[Structural Pass<br>import/export extraction]
A --> C[SCIP Pass<br>scip-typescript / scip-python<br>scip-go / rust-analyzer<br>scip-java / scip-dotnet / scip-ruby]
D[Artifact Files<br>.env package.json *.sql] --> E[Artifact Pass<br>pseudo-symbol extraction]
end
subgraph SQLite Store
B --> F[(index.db<br>WAL mode)]
C --> F
E --> F
F --- G[files · symbols · edges<br>occurrences · dirty · ledger]
end
subgraph Consumption
F --> H[CLI Queries<br>search · refs · impact<br>call-graph · module-graph<br>transitive-impact · metrics<br>context · preflight]
F --> I[MCP Server<br>14 read-only tools]
F --> J[Verify Engine<br>freshness · tests · typecheck<br>boundaries · policies]
end
subgraph Claude Code Hooks
K[Pre-edit] -->|impact context| H
L[Post-edit] -->|dirty mark + update| F
M[Post-test] -->|ledger log| F
N[Stop] -->|update + verify| J
endHow indexing works
Three-pass pipeline:
Structural pass (instant, per-file) — regex-based extraction of
import/export/from/use/require/usingstatements across all supported languages. Creates file-levelimportsedges with resolved file paths (e.g../utils→src/utils.ts) so edges point to actual file nodes. Runs on everyupdate.SCIP pass (slower, full project) — runs the appropriate SCIP indexer per detected sub-project, producing a protobuf index. The parser decodes it and extracts symbols, occurrences (with line:col ranges), and definition/reference roles. Creates symbol-level
defines,references, and approximatecallsedges (via enclosing-definition heuristic). Runs onindex,update(when dirty source files exist), andupdate --full(forced).Artifact pass (instant, per-file) — extracts pseudo-symbols from non-code files:
.envvars (env_var),package.json/tsconfig.jsonkeys (config_key), SQL migrations (table,index), and OpenAPI specs (api_endpoint,api_schema). Scans dirty source files for references (process.env.KEY,os.environ, SQL table names) and createsconfig_refedges. Runs on everyupdate.
All passes write to the same SQLite database (.ariadne/index.db). The database uses WAL mode, busy_timeout=5000 for concurrent access from hooks, and transactions for atomic SCIP ingestion. Bulk ingestion uses index-drop/recreate and PRAGMA synchronous=OFF for faster writes, and skips unchanged files by content hash comparison.
Multi-project support
Ariadne auto-detects sub-projects in monorepos by scanning for language-specific config files (tsconfig.json, pyproject.toml/setup.py, go.mod, Cargo.toml, pom.xml/build.gradle, build.sbt, .sln/.csproj, Gemfile). Each sub-project is indexed independently with correct path prefixing so that SCIP-relative paths map correctly to repo-root-relative file paths.
Module graph modes
The module-graph query supports three modes:
imports (default) — structural import edges only
semantic — SCIP-derived edges with occurrence weights (how many times symbols from file A are referenced in file B)
hybrid — union of both, with source tagging (
import,semantic, orimport+semantic)
Output formats: json (default), dot (Graphviz), mermaid.
Project structure
packages/
core/ ariadne-core library (636 tests)
src/
store/ SQLite schema, queries (7 focused query classes + facade), types, transactions
scip/ protobuf parser + SCIP types + call graph derivation
indexers/ scip-typescript, scip-python, scip-go, scip-rust, scip-java, scip-csharp, scip-ruby, import extractor, project detector, artifact extractor, config ref scanner
graph/ refs, impact analysis (basic + transitive with risk scoring), call graph, module graph (import/semantic/hybrid), structural metrics (coupling, cycles, API surface), context compiler, preflight analyzer, shared utils
verify/ gatekeeper engine + checks (freshness, tests, typecheck, boundaries, policies)
ledger/ execution event log
cli/ CLI command router + hooks
src/
commands/ init, setup, index, update, query, verify, status, dirty, doctor, ledger, impact, metrics, ci, context, preflight
hooks/ pre-edit-impact.sh, post-edit.sh, post-test.sh, stop-verify.sh
lib/ context, output helpers
mcp/ MCP stdio server (14 read-only tools)Performance
Benchmarked on Ariadne's own codebase (95 files, 3 sub-projects). Apple M3.
Operation | Time | Notes |
Full index (structural + SCIP + artifacts) | ~17s | One-time; 3 SCIP sub-projects indexed in parallel sequence |
Incremental update (no changes) | ~120ms | Hash comparison, no I/O |
Single-file update (hook path) | ~155ms | Targeted file only, no repo walk |
Pre-edit impact hook | ~170ms | Includes blast radius + symbol details |
Symbol search | ~80ms | SQLite LIKE query |
Impact analysis (--details) | ~95ms | Symbols + dependents + test recommendations |
Verify (all checks) | ~250ms | Freshness + test coverage + typecheck + boundaries |
Hook latency stays under 200ms — fast enough to run on every edit without noticeable delay in Claude Code.
Development
bun install
bun test # 636 tests across 29 files
bunx tsc --noEmit # type-check all packages
bun run packages/cli/src/index.ts doctor # check prerequisitesToolchains by language
Required: Bun >= 1.0
Optional: SCIP indexers add symbol-level analysis (defs/refs/call graph) on top of structural imports. Without them, you still get file-level dependency graphs, import edges, and artifact indexing.
Language | Extensions | Structural imports | SCIP indexer | Type checker | Install SCIP |
TypeScript / JS |
| ES modules, CJS, dynamic | scip-typescript |
|
|
Python |
|
| scip-python | — |
|
Go |
|
| scip-go |
|
|
Rust |
|
| rust-analyzer |
|
|
Java / Kotlin |
|
| scip-java |
|
|
Scala |
|
| scip-java |
|
|
C# |
|
| scip-dotnet |
|
|
Ruby |
|
| scip-ruby | — |
|
Language roadmap
SCIP indexers exist for these languages and could be integrated:
Language | SCIP Indexer | Status |
C / C++ | Not yet integrated | |
PHP | Not yet integrated | |
Swift | sourcekit-lsp SCIP export | Not yet integrated |
Contributions welcome — see CONTRIBUTING.md.
License
MIT — see LICENSE
This server cannot be installed
Maintenance
Latest Blog Posts
- Your AI Chatbot Just Exposed Your CEO's Salary to an InternBy Om-Shree-0709 on .Agent IdentityMCP SecurityOAuth Delegation
- Why MCP Servers Need Execution Sandboxing (And Why Your Current Stack Isn't Enough)By Om-Shree-0709 on .Agentic AiPrompt InjectionWebAssembly
MCP directory API
We provide all the information about MCP servers via our MCP API.
curl -X GET 'https://glama.ai/api/mcp/v1/servers/simonrueba/ariadne'
If you have feedback or need assistance with the MCP directory API, please join our Discord server