{"slug": "show-hn-n3mo-deterministic-code-intelligence-via-ast-parsing-no-embeddings", "title": "Show HN: N3MO – Deterministic code intelligence via AST parsing, no embeddings", "summary": "N3MO, a deterministic code intelligence tool that parses source code ASTs into a queryable knowledge graph without embeddings or LLM calls, launched on Hacker News. It enables transitive dependency mapping, blast radius analysis, and AI agent integration via MCP, targeting engineering teams to reduce regression risks and accelerate onboarding. The tool is licensed under PolyForm Noncommercial 1.0.0 with commercial licenses available.", "body_md": "**A structural code intelligence layer that transforms source code into a queryable knowledge graph for search, impact analysis, and AI-powered development.**\n\n*Parse once. Query forever. Know exactly what breaks before it does.*\n\n**📜 Licensed under PolyForm Noncommercial 1.0.0** — Source available for noncommercial use. • [Need commercial use? Get a commercial license →](#-license)\n\n[What is N3MO](#-what-is-n3mo) • [Benchmarks](#-benchmarks) • [Architecture](#-architecture) • [Installation](#-installation) • [MCP](#-model-context-protocol-mcp) • [Usage](#-usage) • [Roadmap](#-roadmap)\n\nN3MO is a symbol-centric code intelligence layer. Instead of scanning raw text, it parses your source code's ASTs, maps call graphs, and models dependencies in a queryable relational database — deterministically, with **zero LLM calls at index time**.\n\nFor engineering leaders and teams, N3MO acts as a **structural insurance policy** for your codebases.\n\n**🛡️ Eliminate Regression Risks**— Utility functions are rarely refactored because developers fear unknown side effects. N3MO maps the transitive blast radius of any symbol to arbitrary depth, showing you exactly what will break before you make the edit.**🏎️ Rapid Developer Onboarding**— Instead of senior engineers spending hours explaining codebase flow to new hires, developers run one command to visualize complex call chains and parent-child dependencies interactively.**🤖 AI-Agent Ready Infrastructure**— Modern LLM agents (Cursor, Claude Desktop) are limited by context windows and text search. N3MO's native MCP server lets agents query the actual code graph, enabling fast, hallucination-free refactoring.**⚡ No Embeddings, No Drift**— N3MO is pure static analysis: Tree-sitter AST parsing into PostgreSQL. There's no vector index to keep in sync, no embedding cost per repo, and no semantic-similarity guesswork — every edge in the graph is an exact, verifiable relationship.\n\n| Capability | Grep / Text Search | IDE \"Find References\" | N3MO Code Graph |\n|---|---|---|---|\nAnalysis Basis |\nSubstring matching | AST-based, direct refs only | Relational knowledge graph |\nTransitive Traversal |\n❌ None | ❌ Manual, one level at a time | ⚡ Instant to arbitrary depth |\nBlast Radius Mapping |\n❌ None | ❌ Flat search-result list | 🎨 Interactive visual orbit map |\nCI/CD Integration |\n❌ None | ❌ Bound to IDE runtime | ⚙️ Dockerized CLI + CTE queries |\nAI Agent Integration |\n❌ Injected file chunks | 🤖 Native MCP server |\n|\nLanguage Coverage |\n✅ Any text file | ✅ 27 Tree-sitter grammars |\n|\nIndexing Method |\nN/A | N/A | ✅ Deterministic AST parse — no embeddings, no LLM calls |\n\n|\n\n```\nDeveloper: \"Where does 'login' appear?\"\nTool:      grep -r \"login\" .\nResult:    647 matches across 89 files\n           ...now what?\n```\n\n |\n\n```\nDeveloper: \"What breaks if I change login?\"\nTool:      n3mo impact \"login\"\nResult:    3 direct callers → 5 ripple effects\n           Full blast radius in < 50ms\n```\n\n |\n\nN3MO doesn't find text — it understands structure.It traces the actual call graph, not string matches.\n\n**Questions N3MO answers instantly:**\n\n| Question | How | |\n|---|---|---|\n| 🔎 | What functions and classes exist in this repo? | Full symbol index across 27 languages |\n| 🎯 | Where is this symbol used — directly and transitively? |\nRecursive CTE traversal to arbitrary depth |\n| 💥 | What is the blast radius of changing this function? |\nInteractive orbit map with depth slider |\n| 🕸️ | How do these components actually connect? | Call graph + parent-child hierarchy |\n| 🤖 | Can my AI agent understand this codebase structurally? | Native MCP server for Cursor / Claude |\n\nAll benchmarks measured on **Intel i5-13450HX, 24 GB RAM, NVMe SSD**.\n\nDjango is the primary benchmark target: **3,021 files**, **~43K symbols**, **~181K calls**.\n\n```\nDjango Index Time (minutes)\n═══════════════════════════════════════════════════════════════\n\nv0.3 Baseline       ██████████████████████████████████████████████  23 min   1×\nSPLIT_PART Fix      ██████████████████████                          11 min   2×\nBatch Inserts       █████████                                        5 min   4.6×\n+ Multiprocessing   ████                                           2.5 min   9× 🚀\n\n═══════════════════════════════════════════════════════════════\n```\n\n| Optimization | Index Time | Speedup | What Changed |\n|---|---|---|---|\n| v0.3 baseline | 23 min | 1× | Per-symbol DB inserts, naive call resolution |\n| + SPLIT_PART query fix | 11 min | 2× | Eliminated redundant string splitting in call resolution |\n| + Batch inserts | 5 min | 4.6× | Symbols, imports, and calls batched per file (1 transaction) |\n| + Multiprocessing | ~2.5 min | ~9× |\n`ProcessPoolExecutor` distributes AST parsing across cores |\n\n✅ All results are real measurements on the\n\n[Django]repository. Multiprocessing gains scale with core count.\n\n**Tested on TensorFlow** — a 36,000-file, multi-language (C++/Python) monorepo.\n\n| Metric | Result |\n|---|---|\nRepo size (total files) |\n~36,000 |\nFiles processed & indexed |\n14,611 (after filtering tests, configs, and non-source files) |\nTotal symbols extracted |\n79,523 |\nTotal call edges extracted |\n480,851 |\nFull index time (cold start) |\n14.06 minutes |\nPeak memory (Docker container) |\n185 MB RAM |\nCPU utilization |\n~5% |\n\nN3MO scales from a 3K-file pure-Python repo (Django) to a 36K-file multi-language enterprise monorepo (TensorFlow) — roughly a\n\n5× larger indexing job at near-linear throughput, without significant resource overhead. Symbol/edge-per-file and incremental (warm) re-index numbers for TensorFlow are being finalized in the full benchmark report.\n\n**Tested on ScanCode Toolkit** — ~600K lines of Python.\n\n| Metric | Result |\n|---|---|\nLines of code |\n~600,000 |\nFull index time |\n~3 minutes |\nProcessing mode |\nSingle-threaded (v0.3) |\n\nN3MO uses SHA-256 file hashing to skip unchanged files on subsequent runs.\n\n| Scenario | Time | Notes |\n|---|---|---|\nFull index (first run) |\nBaseline | All files parsed and inserted |\nNo changes (re-run) |\n< 1 second |\nHash comparison only, zero DB writes |\n1 file modified |\n< 2 seconds |\nOnly the changed file is re-parsed and upserted |\n\nThese results are from the built-in benchmark script on a 20-file synthetic repository. Real-world incremental performance is proportional to the number of changed files, not the total repository size.\n\nImpact analysis uses PostgreSQL recursive CTEs with cycle guards. Query times are independent of repository size — they depend only on the size of the result subgraph.\n\n| Query Type | Typical Latency |\n|---|---|\n| Direct callers of a symbol | < 10 ms |\n| Full blast radius (depth ≤ 5) | < 50 ms |\n| Complete graph traversal | < 200 ms |\n\n```\npython benchmarks/benchmark_indexing.py\n```\n\nN3MO builds a **symbol-centric knowledge graph** stored in PostgreSQL:\n\n``` php\ngraph TD\n    A[\"📄 Source Code\"] -->|Tree-sitter| B[\"🌳 AST Parser\"]\n    B --> C[\"🔍 Symbol Extractor\"]\n    D[\"🔄 Git Hooks\"] -->|post-commit| A\n\n    C --> E[(\"🗄️ PostgreSQL<br/>Projects · Symbols · Calls<br/>Imports · Files\")]\n\n    E --> F[\"💥 Impact Analysis\"]\n    E --> G[\"📞 Call Graph\"]\n    E --> H[\"📊 Dependency Graph\"]\n\n    F --> I[\"🎨 Visualizer\"]\n    G --> I\n    H --> I\n\n    F --> J[\"🤖 MCP Server\"]\n\n    style A fill:#6c63ff,stroke:#4a3fbf,color:#fff\n    style B fill:#7c74ff,stroke:#4a3fbf,color:#fff\n    style C fill:#7c74ff,stroke:#4a3fbf,color:#fff\n    style D fill:#ffd93d,stroke:#d4b800,color:#1a202c\n    style E fill:#ff6b6b,stroke:#c53030,color:#fff,stroke-width:3px\n    style F fill:#45b7d1,stroke:#2c8ea8,color:#1a202c\n    style G fill:#45b7d1,stroke:#2c8ea8,color:#1a202c\n    style H fill:#45b7d1,stroke:#2c8ea8,color:#1a202c\n    style I fill:#9ae6b4,stroke:#2f855a,color:#1a202c\n    style J fill:#ffd93d,stroke:#d4b800,color:#1a202c\nsequenceDiagram\n    participant User as User / CI\n    participant CLI as N3MO CLI\n    participant DB as PostgreSQL (Docker)\n    participant Viz as Graph Visualizer\n\n    rect rgb(26, 27, 46)\n    Note over User, DB: Indexing Flow (Local CLI)\n    User->>CLI: n3mo index\n    CLI->>DB: Start PostgreSQL container (if not running)\n    CLI->>CLI: Walk file tree (SHA-256 hash checks)\n    CLI->>CLI: Parse AST (Tree-sitter, multiprocessing)\n    CLI->>DB: Batch insert symbols, calls, imports\n    CLI->>DB: Resolve imports & call links\n    DB-->>CLI: Success\n    CLI-->>User: Complete summary\n    end\n\n    rect rgb(26, 27, 46)\n    Note over User, Viz: Query & Visualization Flow\n    User->>CLI: n3mo impact \"symbol\" --graph\n    CLI->>DB: Recursive CTE traversal (depth & file filters)\n    DB-->>CLI: Blast radius subgraph\n    CLI->>Viz: Generate orbital vis.js HTML\n    CLI->>User: Launch local web server & open browser\n    end\nerDiagram\n    PROJECT ||--o{ SYMBOL : contains\n    PROJECT ||--o{ CALL : tracks\n    PROJECT ||--o{ IMPORT : tracks\n    PROJECT ||--o{ FILE : indexes\n    SYMBOL ||--o{ CALL : \"source of\"\n    SYMBOL ||--o{ CALL : \"resolved to\"\n    SYMBOL ||--o{ SYMBOL : \"parent of\"\n\n    PROJECT {\n        uuid id PK\n        text name\n        text repo_url\n        timestamp created_at\n    }\n    SYMBOL {\n        uuid id PK\n        uuid project_id FK\n        text name\n        text file_path\n        text kind \"function|class|method\"\n        text signature\n        int start_line\n        int end_line\n        uuid parent_id FK\n    }\n    CALL {\n        uuid id PK\n        uuid project_id FK\n        uuid source_symbol_id FK\n        text call_name\n        int line_number\n        uuid resolved_symbol_id FK\n    }\n    IMPORT {\n        uuid id PK\n        uuid project_id FK\n        text file_path\n        text module\n        text name\n        text alias\n        uuid resolved_symbol_id FK\n    }\n    FILE {\n        uuid project_id FK\n        text file_path PK\n        text sha256\n    }\n```\n\n**Multi-language support**— 27 Tree-sitter grammars supported (dynamically loaded); actively benchmarked on 10 major languages including Python, JS/TS, Go, Java, and C/C++**Parallel AST ingestion**—`ProcessPoolExecutor`\n\ndistributes CPU-bound parsing across all available cores**Incremental re-indexing**— SHA-256 file hashing skips unchanged files automatically** Idempotent operations**— re-indexing updates existing data without duplication** Smart exclusions**— case-insensitive directory filters and camelCase-aware filename checks prevent false positives (e.g. allows`contest.py`\n\nwhile skipping`test_*.py`\n\n)\n\n**Symbol extraction**— functions, classes, methods with full file path + line context** Hierarchical modeling**— parent-child relationships (Module → Class → Method)** Call graph construction**— who calls whom, resolved at ingestion time** Scope-aware resolution**— class scope > local file > imports > qualified dot paths > global** Blast radius analysis**— recursive CTE traversal to arbitrary depth with cycle guards\n\n**Connection pooling**—`ThreadedConnectionPool`\n\neliminates per-symbol DB round trips**Batch inserts**— symbols, imports, and calls batched per file in single transactions** Optimized queries**—`SPLIT_PART`\n\nfix delivered a 2× speedup on call resolution\n\n**Interactive graph**— vis.js orbit map with click-to-inspect nodes, sidebar, and depth slider** Dark mode**— toggleable canvas dark mode with real-time node/edge updates, persisted in`localStorage`\n\n**Premium styling**— sleek interactive dashboard landing page UI and graph visualizer styled with`Bricolage Grotesque`\n\n,`Inter`\n\n, and`JetBrains Mono`\n\ntypographyprofile — system instructions to configure Claude as an impact-aware coding agent[SKILL.md](/RajX-dev/N3MO/blob/main/SKILL.md)**Native MCP server**— first-class integration with Cursor, Claude Desktop, and Windsurf** Git hooks**— automatic re-indexing on every commit** CI pipeline**— GitHub Actions with linting (`ruff`\n\n), type checking (`mypy`\n\n), and`pytest`\n\nTree-sitter parsing supported for 27 languages. Deep semantic call graph mapping currently optimized for Python, JS/TS, and Java.\n\nInstall N3MO directly from PyPI:\n\n```\n# Install the package\npip install n3mo\n\n# Start Docker containers & initialize the database\nn3mo setup\n```\n\nAlternatively, for contributors running in editable mode:\n\n```\ngit clone https://github.com/RajX-dev/N3MO.git\ncd N3MO\npip install -e .\nn3mo setup\n```\n\nN3MO includes a native MCP server that exposes repository analysis and graph traversal tools to LLM agents (like Claude, Cursor, or Windsurf).\n\n```\n# Navigate to the workspace you want Claude to analyze, then run:\nn3mo mcp install\n```\n\nThis registers N3MO and sets up the paths automatically. Restart Claude Desktop and you're ready!\n\nTo configure Claude to run N3MO impact queries proactively before changing code in the editor, import or copy-paste the custom instructions from the ** SKILL.md** profile.\n\n- Go to\n**Settings → Models → MCP**. - Click\n**+ Add New MCP Server**. - Set the configuration details:\n**Name**:`n3mo`\n\n**Type**:`command`\n\n**Command**:`n3mo mcp start`\n\n(or`uvx n3mo mcp start`\n\nto run directly)**Environment Variables**:`TARGET_CODE_DIR=/absolute/path/to/your/active/workspace`\n\n- Click Save, and Cursor will instantly be able to index and query your workspace blast radius.\n\n| Tool | Description |\n|---|---|\n`n3mo_index` |\nIngests and indexes the codebase |\n`n3mo_search_symbol` |\nLocates the definition of a symbol across the workspace (file path, line number) |\n`n3mo_get_dependencies` |\nFinds all external symbols that a given symbol calls (forward-dependency graph) |\n`n3mo_get_file_symbols` |\nLists all classes and functions defined inside a specific file |\n`n3mo_get_blast_radius` |\nTraces the transitive impact/call graph of a code symbol |\n\nFor team collaboration and automated pull-request analysis in your CI/CD pipeline, visit ** n3mo.shop** to get started with the GitHub Webhook integration.\n\nN3MO is free under the **PolyForm Noncommercial 1.0.0 License** for local usage and single-developer MCP integrations.\n\n**100% Free & Local**— CLI queries, local MCP integrations, and the visualizer with zero limits.** Enterprise Licensing**— for large-scale organization deployments or commercial licensing terms, reach out to the author.\n\n```\ncd /path/to/your/project\nn3mo index\n```\n\n**What gets indexed:**\n\n- ✅ Source files in all 27 supported languages\n- ❌ Virtual environments (\n`venv/`\n\n,`.venv/`\n\n) - ❌ Dependencies (\n`node_modules/`\n\n,`site-packages/`\n\n) - ❌ Build artifacts (\n`.git/`\n\n,`__pycache__/`\n\n,`dist/`\n\n) - ❌ Test / fixture directories (\n`tests/`\n\n,`mocks/`\n\n,`specs/`\n\n)\n\n**Example terminal output:**\n\n```\n  ◈ IMPACT ANALYSIS\n  ──────────────────────────────────────────────────────────────────\n  Target:  authenticate_user\n  ──────────────────────────────────────────────────────────────────\n\n  ◉ Direct Callers  (3 symbols)\n\n  ▸ login_endpoint             api/auth.py:12\n  ▸ refresh_token              api/token.py:23\n  ▸ validate_session           middleware/auth.py:89\n\n  ◎ Ripple Effects  (5 symbols)\n\n    ╰─▸ POST /login              routes.py:67\n    ╰─▸ admin_login              admin/views.py:34\n    ╰─▸ require_auth             decorators.py:12\n    ╰─▸ dashboard_view           views/dashboard.py:8\n    ╰─▸ settings_view            views/settings.py:22\n\n  ──────────────────────────────────────────────────────────────────\n  Total impacted: 8 references  │  depth ≤ 3\nphp\ngraph LR\n    A[main.py] --> B[auth.py::login]\n    A --> C[db.py::connect]\n    B --> D[utils.py::hash_password]\n    B --> E[models.py::User]\n    C --> F[config.py::DB_URI]\n\n    style A fill:#ff6b6b,stroke:#c92a2a,stroke-width:2px,color:#fff\n    style B fill:#4ecdc4,stroke:#0ca89e,stroke-width:2px,color:#000\n    style C fill:#45b7d1,stroke:#1098ad,stroke-width:2px,color:#000\n    style D fill:#96ceb4,stroke:#63b598,stroke-width:2px,color:#000\n    style E fill:#ffd93d,stroke:#f5c200,stroke-width:2px,color:#000\n    style F fill:#e0e0e0,stroke:#a0a0a0,stroke-width:2px,color:#000\n```\n\nAll four development phases have been completed. N3MO is stable and actively maintained.\n\n| Phase | Component | Status |\n|---|---|---|\nPhase 1 — Foundations |\n||\n| Docker setup | ✅ Complete | |\n| Database schema | ✅ Complete | |\n| Tree-sitter integration | ✅ Complete | |\n| Symbol + call extraction | ✅ Complete | |\n| Blast radius (recursive CTE) | ✅ Complete | |\n| Interactive visualizer | ✅ Complete | |\nPhase 2 — Performance |\n||\n| Connection pooling | ✅ Complete | |\n| Batch DB operations (symbols/imports/calls) | ✅ Complete | |\n| SPLIT_PART query optimization | ✅ Complete | |\n`--file` / `--depth` CLI flags |\n✅ Complete | |\n| Interactive depth slider | ✅ Complete | |\nPhase 3 — Correctness & Scaling |\n||\n| Incremental re-index (file hashing) | ✅ Complete | |\n| Multiprocessing (AST parsing) | ✅ Complete | |\n| Scope-aware call resolution | ✅ Complete | |\n| CTE cycle guard | ✅ Complete | |\n| Full type annotations + mypy | ✅ Complete | |\n| pytest suite + CI | ✅ Complete | |\n| Multi-language support (27 languages) | ✅ Complete | |\nPhase 4 — Distribution |\n||\n| MCP server (Cursor / Claude / Windsurf) | ✅ Complete | |\n| Real-time git-hook indexing | ✅ Complete |\n\n**Phase 1: Foundations** ✅ Complete\n\n- Docker environment (PostgreSQL)\n- Database schema — Projects, Symbols, Calls, Imports tables\n- Tree-sitter parser integration\n- Symbol extractor with full AST traversal\n- Idempotent upsert logic\n- Blast radius via recursive CTE\n- Interactive vis.js visualizer\n\n**Phase 2: Performance** ✅ Complete\n\n-\n`psycopg2.pool.ThreadedConnectionPool`\n\n— replace per-call connections -\n`execute_values()`\n\nbatch inserts for symbols, imports, and calls — 1 transaction per file - SPLIT_PART query optimization for call resolution\n-\n`--file`\n\nand`--depth`\n\nCLI flags for targeted impact analysis - Interactive depth slider in visualizer\n\n**Results:** Django (3,021 files, ~43K symbols, ~181K calls) — 23min → 2.5min (9× faster)\n\n**Phase 3: Correctness + Scaling** ✅ Complete\n\n- SHA-256 file hashing for incremental re-index\n-\n`ProcessPoolExecutor`\n\nfor parallel AST parsing - Scope-aware call resolution using imports table\n- CTE cycle guard (visited node tracking)\n- Full type annotations,\n`mypy`\n\nclean checking in CI - pytest unit + integration test suite\n- GitHub Actions CI pipeline\n- Multi-language support (27 languages)\n\n**Phase 4: Distribution** ✅ Complete\n\n- MCP server — N3MO as a tool for Cursor, Claude Code, Windsurf\n- Real-time incremental indexing via git hooks\n\n**1. Structure before semantics**\nMap the code skeleton (AST) before adding AI analysis. A correct graph is worth more than a smart but wrong one.\n\n**2. Database as source of truth**\nAll state lives in PostgreSQL, eliminating in-memory complexity and enabling graph queries that application-level traversal cannot match.\n\n**3. Correctness over speed**\nThe parser must handle syntax errors gracefully without corrupting the graph. A fast indexer that silently drops symbols is worse than a slow one that gets everything right.\n\n**4. Idempotent operations**\nRe-running ingestion produces identical results, enabling safe incremental updates and CI/CD integration.\n\nContributions are welcome! Please read the ** CONTRIBUTING.md** guide to get started with setting up the project, coding standards, and running checks locally.\n\n```\n# Install with dev dependencies\npip install -e \".[dev]\"\n\n# Lint\nruff check n3mo/\n\n# Type check\nmypy n3mo/\n\n# Tests\npytest tests/\n```\n\nLicensed under the **PolyForm Noncommercial 1.0.0** License.\n\n- ✅ Free for personal projects, academic research, and hobby tools\n- ✅ Source available — view, modify, and distribute for noncommercial purposes\n⚠️ Noncommercial — you may not use it for commercial purposes⚠️ Restrictions apply on offering it as a service\n\nFor commercial deployments or proprietary modifications, contact for licensing options.\n\nSee [LICENSE](/RajX-dev/N3MO/blob/main/LICENSE) for full legal details.\n\n**Raj Shekhar** — Delhi Technological University\n\n— for robust, incremental, error-tolerant parsing[Tree-sitter](https://tree-sitter.github.io/)— for making recursive graph queries possible without a graph database[PostgreSQL](https://www.postgresql.org/)— for reproducible, single-command environments[Docker](https://www.docker.com/)— for the interactive graph visualization[vis.js](https://visjs.org/)— for the high-performance REST layer[FastAPI](https://fastapi.tiangolo.com/)", "url": "https://wpnews.pro/news/show-hn-n3mo-deterministic-code-intelligence-via-ast-parsing-no-embeddings", "canonical_source": "https://github.com/RajX-dev/N3MO", "published_at": "2026-07-09 08:54:28+00:00", "updated_at": "2026-07-09 09:12:26.886134+00:00", "lang": "en", "topics": ["developer-tools", "ai-tools"], "entities": ["N3MO", "Tree-sitter", "PostgreSQL", "Cursor", "Claude Desktop", "Django"], "alternates": {"html": "https://wpnews.pro/news/show-hn-n3mo-deterministic-code-intelligence-via-ast-parsing-no-embeddings", "markdown": "https://wpnews.pro/news/show-hn-n3mo-deterministic-code-intelligence-via-ast-parsing-no-embeddings.md", "text": "https://wpnews.pro/news/show-hn-n3mo-deterministic-code-intelligence-via-ast-parsing-no-embeddings.txt", "jsonld": "https://wpnews.pro/news/show-hn-n3mo-deterministic-code-intelligence-via-ast-parsing-no-embeddings.jsonld"}}