Big News: Socket raises $60M Series C at a $1B valuation to secure software supply chains for AI-driven development.Announcement
Sign In

codetree-claude

Package Overview
Dependencies
Maintainers
1
Versions
29
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

codetree-claude

MCP server & CLI: codebase index + cache for Claude Code, Cursor, OpenAI Codex, Google Antigravity/Gemini. Model Context Protocol tools (codetree_read, codetree_search, …), hooks on Claude, rules on other IDEs. Token savings, SQLite index, symbol search,

latest
npmnpm
Version
1.6.1
Version published
Maintainers
1
Created
Source

CodeTree

Persistent codebase index + Model Context Protocol (MCP) server for AI coding assistants. Cuts redundant Read / Grep / Glob token usage by routing AI tool calls through a cached SQLite index with symbol-aware APIs.

npm VS Code License Node

CodeTree works with Anthropic Claude Code, Cursor, OpenAI Codex, Google Antigravity / Gemini, and any MCP-compatible editor or CLI. A single codetree init wires the same MCP server into every tool's config format.

Table of Contents

Why CodeTree

Teams using AI coding assistants spend a large fraction of their context window / tokens on re-reading the same files. Every chat re-runs Glob, Grep, and Read, and the model sees the same source again and again.

CodeTree solves this by maintaining a local, persistent SQLite index of your repo and serving requests through MCP tools that return:

  • Cached file content (mtime-validated, never silently stale)
  • Compact diffs when the file is mostly unchanged
  • Symbol outlines instead of full bodies
  • Symbol-aware search that bypasses raw text grep
  • Token-efficient project tree instead of Glob "**/*"

For Claude Code, CodeTree additionally installs PreToolUse hooks that intercept native Read/Grep/Glob calls and redirect them to the cache. For Cursor / Codex / Antigravity, the model is steered to the same MCP tools via project rules and AGENTS.md / GEMINI.md.

Features

  • Persistent SQLite index — survives restarts; cold start uses cached postings
  • In-memory LRU + compressed SQLite content cache — two-tier read path
  • Symbol extraction for JS/TS/JSX/TSX, Python, Java/Kotlin/C#, Go, Rust, Ruby
  • Token-postings index for fast multi-token content scans (avoids full-corpus grep)
  • mtime-validated reads — branch switches, external edits, merges all reflected
  • File watcher (chokidar) + safety-net rescan every 10 min for missed events
  • Singleton IPC server — deterministic per-project port; duplicates exit cleanly
  • Hooks for Claude CodePreToolUse, PostToolUse, SessionStart, Pre/PostCompact
  • Multi-IDE setup — one codetree init configures Claude, Cursor, Codex, Antigravity
  • VS Code extension — sidebar with token savings, indexed files, symbols, dashboard
  • Cross-platform — Windows \r\n safe, forward-slash paths in MCP configs
  • Per-tool telemetry — read/search/glob hits, misses, tokens saved, scan-cache hit rate

Quick Start

Option 1 — npm global

npm install -g codetree-claude
cd your-project
codetree init

Option 2 — per-project dev dependency

npm install --save-dev codetree-claude
npx codetree init

Option 3 — VS Code extension

Install "CodeTree — Cache for Claude Code" from the VS Code Marketplace. The extension activates CodeTree in the editor and shows the live dashboard.

After codetree init, reload your editor (Cursor / VS Code: Cmd/Ctrl+Shift+P → Developer: Reload Window). The MCP server starts automatically per project on the next AI session.

Supported AI Tools (multi-IDE)

ProductWhat CodeTree configuresHow tokens are saved
Claude Code (Anthropic)Root .mcp.json, .claude/settings.json hooks, CLAUDE.md, .claude/rules/codetree.mdHooks redirect native Read/Grep/Glob/Edit/Write to codetree_* when the cache can serve
Cursor.cursor/mcp.json, .cursor/rules/codetree.mdcMCP tools + alwaysApply rules steer the agent
OpenAI Codex.codex/config.toml [mcp_servers.codetree], AGENTS.mdMCP tools + agent instructions (merge-safe TOML)
Google Antigravity / Gemini.antigravity/mcp.json, AGENTS.md, GEMINI.mdMCP + portable docs
VS CodeMarketplace extension "CodeTree — Cache for Claude Code"Sidebar dashboard + auto-mirroring MCP into .cursor/mcp.json
Any MCP hostSame node …/dist/server/mcp-server.js entryRegister the MCP server manually if your tool uses a custom config path

Note: Token-saving hooks (PreToolUse interception) are a Claude Code feature. Cursor / Codex / Antigravity rely on MCP + project rules — the model is steered to call codetree_read, codetree_search, etc., instead of native tools. The indexer, cache, and MCP tool surface are identical for all hosts.

Architecture

CodeTree is composed of six layered subsystems, each with a single responsibility. The whole stack is one Node process per project, started on demand by the MCP host.

┌──────────────────────────────────────────────────────────────────────┐
│  AI client                                                           │
│  (Claude Code / Cursor / Codex / Antigravity / any MCP host)         │
│                                                                      │
│  ┌────────────────────────────────────────────────────────────────┐ │
│  │  Steering layer                                                 │ │
│  │  - Claude Code: PreToolUse hooks + .claude/rules               │ │
│  │  - Cursor:      .cursor/rules/codetree.mdc (alwaysApply)       │ │
│  │  - Codex:       AGENTS.md + .codex/config.toml                 │ │
│  │  - Antigravity: AGENTS.md + GEMINI.md + .antigravity/mcp.json  │ │
│  └────────────────────────────┬───────────────────────────────────┘ │
└───────────────────────────────┼──────────────────────────────────────┘
                                │ MCP / stdio
┌───────────────────────────────▼──────────────────────────────────────┐
│  MCP Server  (src/server/mcp-server.ts)                              │
│  - Registers 10 tools, dispatches CallToolRequest                    │
│  - Routes telemetry through HTTP IPC                                 │
└──────────┬──────────────────────────────────┬────────────────────────┘
           │                                  │
┌──────────▼──────────────┐        ┌──────────▼────────────────────────┐
│  Tool Handlers          │        │  IPC Server (singleton, HTTP)     │
│  src/server/tools/*.ts  │        │  src/server/ipc.ts                │
│  - codetree_read        │        │  - Deterministic per-project port │
│  - codetree_search      │        │  - /check, /check-search,         │
│  - codetree_structure   │        │    /check-glob   (hook decisions) │
│  - codetree_outline     │        │  - /stats, /status, /mcp-call     │
│  - codetree_probe       │        │  - Owner / shared mode coordination│
│  - codetree_find_refs   │        └──────────┬────────────────────────┘
│  - codetree_summary     │                   │
│  - codetree_memory      │                   │ same process
│  - codetree_edit        │                   │
│  - codetree_write       │                   │
└──────────┬──────────────┘                   │
           │                                  │
┌──────────▼──────────────────────────────────▼────────────────────────┐
│  Indexer  (src/indexer/indexer.ts)                                   │
│  - fullScan / indexFile / safetyNetRescan                            │
│  - In-memory token postings  (Map<token, Set<relPath>>)              │
│  - readCached / readForScan  (mtime revalidation, disk fallback)     │
│  - looksBinary heuristic, file size cap                              │
│  - Uses ExtractorRegistry to pull symbols + dependencies             │
└──────────┬──────────────────────┬────────────────┬───────────────────┘
           │                      │                │
┌──────────▼──────────┐  ┌────────▼──────────┐  ┌──▼──────────────────┐
│  Storage            │  │  ContentCache LRU │  │  FileWatcher         │
│  src/storage/       │  │  (in-memory)      │  │  src/indexer/        │
│  database.ts        │  │  cache.ts         │  │  watcher.ts          │
│  - sql.js (WASM)    │  │  - hash-keyed     │  │  - chokidar          │
│  - files,           │  │  - mtime/size/    │  │  - debounce 300ms    │
│    symbols,         │  │    hash metadata  │  │  - .git/HEAD watcher │
│    dependencies,    │  │                   │  │    → branch switch   │
│    content_cache,   │  │                   │  │    cache invalidation│
│    token_postings,  │  │                   │  │  - error handler     │
│    trigrams,        │  │                   │  │    (EMFILE/ENOSPC)   │
│    previous_content │  │                   │  │                      │
│  - persistToDisk    │  │                   │  │                      │
└─────────────────────┘  └───────────────────┘  └──────────────────────┘

Layer Responsibilities

LayerFile(s)Responsibility
Steeringtemplates/, setup/install.tsIdempotent install of MCP configs + rules into each IDE
MCP Serversrc/server/mcp-server.tsStdio transport, tool registration, lifecycle management
Tool Handlerssrc/server/tools/*.tsOne file per MCP tool; pure functions of (config, indexer, db)
IPC Serversrc/server/ipc.tsHTTP server on deterministic port; serves hook decisions + telemetry
Indexersrc/indexer/indexer.tsThe orchestrator — read / scan / extract / postings / token cache
Storagesrc/storage/database.ts, cache.tsSQLite (sql.js WASM) + in-memory LRU
Watchersrc/indexer/watcher.tschokidar + branch-switch detection + safety-net rescan
Hooks (Claude only)src/hook/*.tsBundled standalone scripts invoked by Claude Code per tool call
CLIsrc/cli.tsinit, status, stats, reindex, doctor, help

Component Design

Indexer

The Indexer class (src/indexer/indexer.ts) is the heart of CodeTree.

  • fullScan() — incremental scan of the project tree. Each file goes through indexFile(), which short-circuits on (size, mtime) match (the cheap path) and only re-extracts on real change.
  • indexFile() — reads file, runs looksBinary heuristic (>5% unprintable bytes ⇒ skip), computes content hash, extracts symbols + dependencies via the language-specific extractor, writes to SQLite, populates LRU + content-cache, and updates the token-postings index.
  • readCached(relPath) — two-tier read: in-memory LRU first (with periodic mtime revalidation), then SQLite content cache (with mtime check against disk). On mismatch, re-indexes and serves fresh.
  • readForScan(relPath) — used by content-search loops. Like readCached but never returns null for files that exist: falls back to direct readFileSync and re-seats both caches. Counts hits/misses for scan telemetry.
  • safetyNetRescan() — cheap incremental sweep (mostly statSync + short-circuit) run every 10 min as backup against missed chokidar events on Windows / OneDrive / network drives.
  • Token postings (Map<lowercase-token, Set<relPath>>) — drives codetree_search content search, codetree_find_refs, and codetree_probe. Persisted to SQLite for instant cold start. Tokens are extracted with /[A-Za-z_][A-Za-z0-9_]{2,}/ (≥3 chars, capped per-file at 4000).

Storage

src/storage/database.ts — SQLite via sql.js (WASM, no native build). Tables:

TablePurpose
filespath, hash, size, mtime, language, line count, indexed-at
symbolsname, kind, line span, signature, exported flag — keyed by file path
dependenciessource path → target import specifier (resolved is null in current pass)
content_cachezlib-deflated file content; capped by cache.contentCacheMaxMB
token_postingsper-file token list (for postings cold start)
trigramscontent trigrams (for fuzzy content search)
previous_contentolder deflated content for diff-based reads (24h TTL, capped at 200 rows)

src/storage/cache.ts — small in-memory LRU keyed by relPath. Stores raw text plus hash/mtime/size metadata. Hit/miss counters exposed on /stats.

IPC Server

src/server/ipc.ts (~1000 lines, single class IpcServer) exposes an HTTP API on a deterministic per-project port. Two responsibilities:

  • Hook decisions/check, /check-search, /check-glob answer Claude Code hooks in <50 ms.
  • Telemetry/stats, /status, /clear-cache, /mcp-call. Per-tool counters: readHits, searchHits, globHits, mcpCalls, tokensSaved, scanCacheHits, scanHitRate.

The IPC server is a singleton per project: it picks a deterministic port from the project root path. If another instance is already bound, it retries with backoff (200/400/800/1200 ms). On failure the duplicate process exits cleanly so two instances never race on the same SQLite write lock.

Hooks (Claude Code only)

Bundled into dist/hook/*.js (esbuild standalone scripts) and invoked by Claude Code via .claude/settings.json:

HookWhen it firesWhat it does
pre-tool-useBefore every Read/Grep/GlobAsks IPC /check*; on cache hit, exits 2 with redirect message → Claude calls codetree_* instead
post-tool-useAfter every tool callUpdates session memory
session-startNew chat sessionInjects compact project summary (capped at 2 KB)
pre-compactBefore context compactionSaves current insights for recall
post-compactAfter compactionRestores compact session context

All hooks must complete in <50 ms and fail open (any error ⇒ exit 0, native tool runs).

Data Flow Diagrams

Flow 1 — AI agent reads a file (Claude Code)

Agent: Read("src/api/auth.ts")
  │
  ▼
Claude Code  ──── PreToolUse hook ────► pre-tool-use.js
                                          │
                                          ▼
                                        IpcServer  /check?path=…
                                          │
                          ┌───────────────┴───────────────┐
                          │                               │
                       cached                          not cached
                          │                               │
                          ▼                               ▼
              exit 2 + stderr message            exit 0 (allow)
              "Use codetree_read …"                  │
                          │                          │
                          ▼                          ▼
              Agent calls codetree_read       Native Read runs
                          │                          │
                          ▼                          ▼
              Indexer.readCached → LRU/SQLite   Disk read
                          │
                          ▼
              JSON: { content, hash, lineCount,
                      symbols, language,
                      unchanged_since_last_read? }

Flow 2 — AI agent reads a file (Cursor / Codex / Antigravity)

Agent (steered by .cursor/rules/codetree.mdc or AGENTS.md)
  │
  ▼ (decides to call codetree_read directly)
MCP Server  ──► CallToolRequest("codetree_read", {file_path, session_id?})
  │
  ▼
Tool handler (src/server/tools/codetree-read.ts)
  │
  ├── session+hash short-circuit?  → unchanged_since_last_read: true (no body)
  ├── expected_hash match?         → unchanged: true (no body)
  ├── outline_only or auto-fallback → symbols + metadata only (no body)
  └── focus_symbol set?            → return only symbol body + context
  │
  ▼
Indexer.readCached(relPath)
  │
  ├── LRU hit?  → mtime revalidate periodically → return content
  ├── SQLite content_cache hit? → mtime check vs disk → re-index if stale
  └── miss → null  (handler falls back to direct disk read for non-scan paths)
  │
  ▼
Response → MCP Server → JSON over stdio → Agent
  │
  └── (in parallel) IPC /mcp-call?tool=codetree_read&tokens=N updates telemetry

Flow 3 — Indexer lifecycle (server startup)

MCP host spawns:  node dist/server/mcp-server.js
  │
  ▼
loadConfig()  ──►  Database.init() (sql.js loads .codetree/index.db)
  │
  ▼
ContentCache(memoryLimitMB)  ──►  Indexer.init() (load token postings from SQLite)
  │
  ▼
IpcServer.start()  ──►  bind deterministic port
  │
  ├── port owned by another live codetree → retry (200/400/800/1200ms) → exit if duplicate
  ├── port acquired           → owner mode
  └── port already ours       → shared mode (skip scan + watcher)
  │
  ▼ (owner mode only)
indexer.fullScan()  ──►  walk project, indexFile() per file (incremental)
  │
  ▼
FileWatcher.start()  ──►  chokidar + .git/HEAD watcher + safetyNetRescan timer
  │
  ▼
Server.connect(StdioServerTransport())  ──►  ready for AI host requests

Flow 4 — File change → index update

Editor saves file  →  chokidar 'change' event  →  debounce 300ms
                                                       │
                                                       ▼
                                              Indexer.indexFile(absPath)
                                                       │
                              ┌────────────────────────┴────────────────────────┐
                              │                                                 │
                        size+mtime same                              size or mtime changed
                              │                                                 │
                              ▼                                                 ▼
                  short-circuit: skip extract                          read file → looksBinary?
                  (reseat content_cache if evicted)                            │
                                                          ┌────────────────────┴────────────────────┐
                                                          │                                         │
                                                       binary                                    text
                                                          │                                         │
                                                          ▼                                         ▼
                                                  delete from index                       hash → ExtractorRegistry
                                                                                                    │
                                                                                                    ▼
                                                                                  upsert files / symbols / deps
                                                                                  save trigrams + token postings
                                                                                  save previous content (for diffs)
                                                                                  update LRU + content_cache

Flow 5 — codetree init setup

codetree init
  │
  ▼
findGitRepos(cwd)  ──►  for each repo:
                          1.  createDefaultConfig            → .codetreerc.json
                          2.  updateGitignore                → adds .codetree/
                          3.  installHook                    → .claude/settings.json
                          4.  installMcpServer               → .mcp.json (Claude)
                          5.  installClaudeMd                → CLAUDE.md
                          6.  installClaudeRules             → .claude/rules/codetree.md
                          7.  installCursorMcp               → .cursor/mcp.json
                          8.  installCursorRules             → .cursor/rules/codetree.mdc
                          9.  installAntigravityMcp          → .antigravity/mcp.json
                         10.  installCodexMcp                → .codex/config.toml
                         11.  installAgentsMd                → AGENTS.md (block)
                         12.  installGeminiMd                → GEMINI.md

All install steps are idempotent — re-running codetree init only refreshes generated blocks.

MCP Tools Reference

All ten tools are available on every MCP host (Claude Code, Cursor, Codex, Antigravity, …).

ToolReplaces / complementsWhat it does
codetree_readReadCached read; supports outline_only, expected_hash (returns diff or "unchanged"), session_id short-circuit, focus_symbol narrowing, offset/limit pagination. Mtime-validated.
codetree_outlineRead (lite)File metadata + exported symbols + imports. No body. Cheapest browse primitive.
codetree_probeGrep (lite)Returns only { file_path, line_numbers[] } per match. No snippets. Use for "does X mention Y?" triage.
codetree_searchGrepSymbol-name search + optional content search via token postings. Pagination via next_cursor. file_pattern narrows before scanning.
codetree_find_refsCross-file references for a symbol; uses postings to narrow candidates.
codetree_structureGlobProject file tree. format='text' ≈ 40% fewer tokens than JSON. path/depth/pattern narrow. Auto-collapses huge repos.
codetree_summaryWhole-project overview: language breakdown, top files by symbol count, total estimated tokens. Use at session start.
codetree_memorySave / recall insights across sessions. get_context is aggressively trimmed.
codetree_editEditEdit without prior Read. \r\n-safe on Windows. Updates index in place.
codetree_writeWriteWrite file without prior Read. Creates parent dirs. Updates index.

Token-saving knobs (selected)

ToolKnobDefaultEffect
codetree_readoutline_onlyfalseSymbols + metadata only
codetree_readexported_symbols_onlytrueDrop private symbols
codetree_readexpected_hashUnchanged ⇒ no body; changed ⇒ compact diff
codetree_readsession_id"Already-read this session" short-circuit
codetree_readfocus_symbolReturn only the named function / class body + context
codetree_searchfile_patternNarrow candidate pool before the scan cap
codetree_structureformat='text''json'Compact indented tree

CLI Commands

codetree init       # Configure CodeTree + Claude + Cursor + Antigravity + Codex in every git repo under cwd
codetree status     # Per-project: running? indexed file count? ready?
codetree stats      # Aggregated cache hit rates + estimated tokens / cost saved
codetree reindex    # Drop .codetree/index.db (rebuilds on next session)
codetree doctor     # Verify MCP paths, hook scripts, IPC port (run after Node/npm changes)
codetree help       # Show help

codetree init discovers all .git directories under the current working directory and configures each one independently.

Configuration

Edit .codetreerc.json in your project root (a default is created by codetree init):

{
  "projectRoot": ".",
  "ignore": [".git", "node_modules", "dist", "build", "coverage", ".next", "__pycache__", ".cache", ".turbo", ".vercel", ".output"],
  "ignoreBinary": true,
  "maxFileSize": 1048576,
  "cache": {
    "memoryLimitMB": 256,
    "dbPath": ".codetree/index.db",
    "contentCacheMaxMB": 512
  },
  "ipc": { "port": 0, "host": "127.0.0.1" },
  "watch": { "enabled": true, "debounceMs": 300, "usePolling": false },
  "symbols": {
    "enabled": true,
    "languages": ["javascript", "typescript", "python", "java", "go", "rust", "ruby", "csharp"]
  },
  "telemetry": { "enabled": true, "statsFile": ".codetree/stats.json" },
  "tokenSave": {
    "read": {
      "includeSymbolsByDefault": true,
      "maxSymbols": 40,
      "exportedSymbolsOnlyByDefault": true,
      "unchangedShortCircuit": true,
      "outlineFallbackBytes": 81920
    },
    "search":       { "defaultLimit": 20, "snippetMaxChars": 120 },
    "structure":    { "compactText": false },
    "sessionStart": { "maxBytes": 2048 }
  }
}

The schema is enforced via zod in src/config.ts — invalid values fall back to defaults rather than crashing the server.

Repository Layout

codetree/
├── src/
│   ├── cli.ts                       # `codetree` CLI entry point
│   ├── config.ts                    # zod schema + project-root discovery
│   ├── doctor.ts                    # `codetree doctor` checks
│   ├── diff.ts                      # compact diff format for codetree_read
│   ├── index.ts                     # programmatic API exports
│   ├── utils.ts                     # findGitRepos, findIpcPort, formatNumber
│   │
│   ├── server/
│   │   ├── mcp-server.ts            # MCP stdio entry; lifecycle + shutdown
│   │   ├── ipc.ts                   # HTTP IPC server (singleton per project)
│   │   └── tools/
│   │       ├── codetree-read.ts
│   │       ├── codetree-outline.ts
│   │       ├── codetree-probe.ts
│   │       ├── codetree-search.ts
│   │       ├── codetree-find-refs.ts
│   │       ├── codetree-structure.ts
│   │       ├── codetree-summary.ts
│   │       ├── codetree-memory.ts
│   │       ├── codetree-edit.ts
│   │       └── codetree-write.ts
│   │
│   ├── indexer/
│   │   ├── indexer.ts               # the orchestrator
│   │   ├── watcher.ts               # chokidar + .git/HEAD + safety-net rescan
│   │   ├── hasher.ts                # xxhash content + quick (size,mtime) hash
│   │   ├── ignore.ts                # gitignore-compatible ignore filter
│   │   ├── extractor-registry.ts    # routes file → language extractor
│   │   └── extractors/              # JS/TS, Python, Java, Go, Rust, Ruby, C#, generic
│   │
│   ├── storage/
│   │   ├── database.ts              # sql.js wrapper + schema + migrations
│   │   ├── cache.ts                 # in-memory LRU
│   │   └── disk-manager.ts          # disk-budget management
│   │
│   ├── hook/
│   │   ├── pre-tool-use.ts          # bundled standalone (esbuild)
│   │   ├── post-tool-use.ts
│   │   ├── session-start.ts
│   │   ├── pre-compact.ts
│   │   ├── post-compact.ts
│   │   └── hook-client.ts           # tiny HTTP client → IPC server
│   │
│   └── setup/
│       ├── install.ts               # all install* functions used by `codetree init`
│       └── template-load.ts         # reads templates/ and copies into project
│
├── templates/                       # bundled with npm package; copied by init
│   ├── claude-md-codetree.snippet.md
│   ├── claude-rules-codetree.md
│   ├── cursor-codetree.mdc
│   ├── agents-codetree.snippet.md
│   ├── gemini-codetree.snippet.md
│   └── README.md
│
├── vscode-extension/                # standalone published extension
│   ├── src/
│   │   ├── extension.ts             # activation, commands, MCP mirror
│   │   ├── dashboard.ts             # webview dashboard (live token savings)
│   │   └── tree-views.ts            # sidebar trees (stats / files / symbols)
│   ├── media/                       # icons
│   └── package.json                 # publisher: rishuni30
│
├── scripts/
│   ├── bundle-hook.js               # esbuild bundle for hook/*.ts
│   └── postinstall.js
│
├── docs/
│   ├── INSTALL_PATH_AND_IGNORE_ISSUES.md
│   └── INTEGRATION_CURSOR_ANTIGRAVITY_CODEX.md
│
├── test/
│   ├── diff.test.ts
│   ├── extractors.test.ts
│   ├── utils.test.ts
│   └── integration.mjs              # end-to-end against a live server
│
├── dist/                            # build output (gitignored — but shipped on npm)
├── .codetree/                       # local index DB + stats (gitignored)
├── .codetreerc.json                 # project config
├── .codetreerc.default.json         # template default
├── .mcp.json                        # Claude Code MCP entry for THIS repo
├── .gitignore                       # node_modules/, dist/, .codetree/, *.tsbuildinfo
├── package.json                     # name: codetree-claude
├── tsconfig.json
├── CHANGELOG.md
├── LICENSE                          # MIT
└── README.md                        # this file

How codetree init Wires Each IDE

IDEMCP configRules / instructions
Claude CodeRoot .mcp.jsonCLAUDE.md + .claude/rules/codetree.md + hooks in .claude/settings.json
Cursor.cursor/mcp.json.cursor/rules/codetree.mdc (alwaysApply)
OpenAI Codex.codex/config.toml ([mcp_servers.codetree])AGENTS.md (also: trust the project in Codex if required)
Google Antigravity.antigravity/mcp.jsonAGENTS.md (full table) + GEMINI.md (Gemini pointer)

All written files are safe to commit (the team setup) except .codetree/ itself which is gitignored. Re-running codetree init only refreshes the CodeTree-managed blocks.

Reliability & Cross-Platform Notes

Never stale

  • External edits — periodic mtime revalidation on read; immediate re-index on mismatch
  • Branch switches.git/HEAD watcher invalidates relevant cache
  • Missed watcher events — safety-net rescan every 10 min (1 min after startup)

Cross-platform

  • Windows \r\ncodetree_edit normalizes for matching, preserves style on write
  • Paths — forward slashes in MCP JSON for portability across OSs
  • ShutdownSIGINT/SIGTERM/SIGHUP + transport.onclose + stdin.end/stdin.close (Windows doesn't reliably deliver SIGTERM to Node child processes)

Safe at scale

  • Large filesoutlineFallbackBytes (default 80 KB) auto-degrades to outline mode rather than truncating mid-byte; per-call slice capped at 5000 lines
  • Large repos — structure view paginates via next_cursor; auto-collapses on huge trees
  • Hooks (Claude) — redirect only when CodeTree can serve; otherwise native tools run
  • Graceful degradation — non-critical failures wrapped so core reads do not break
  • Single owner — duplicate processes detect via deterministic IPC port and exit cleanly to avoid SQLite write-lock contention

Telemetry

Per-tool counters available on IPC /stats:

readHits / readMisses          searchHits / searchMisses          globHits / globMisses
readTokensSaved                 searchTokensSaved                   globTokensSaved
sessionTokensSaved              mcpTokensSaved                      mcpCalls
scanCacheHits / scanCacheMisses scanHitRate                         scanDiskReadBytes
hitRate (= cacheHits / (cacheHits + cacheMisses))                   avgTokensPerHit

A persistently low scanHitRate on a large repo is a clear signal that cache.contentCacheMaxMB is too small.

Development

Prerequisites

  • Node.js ≥ 20
  • npm (or pnpm / yarn — npm is what CI uses)

Setup

git clone <your-repo-url> codetree
cd codetree
npm install
npm run build

npm run build runs tsc and then scripts/bundle-hook.js (esbuild) to produce standalone bundles for dist/hook/*.js.

Useful scripts

ScriptWhat it does
npm run buildFull build: TypeScript compile + hook bundling
npm run build:hookRe-bundle hook scripts only
npm run devtsc --watch
npm run linttsc --noEmit (no separate ESLint dependency)
npm testVitest run
npm run test:watchVitest watch mode
npm startRun the MCP server directly (node dist/server/mcp-server.js)

Local install for testing

npm pack
npm install -g ./codetree-claude-*.tgz
cd /path/to/test-project
codetree init
codetree doctor

Testing

Unit tests (Vitest)

npm test

Covers:

  • test/diff.test.ts — diff formatter
  • test/extractors.test.ts — symbol + import extraction per language
  • test/utils.test.ts — utility helpers

Integration tests

node test/integration.mjs

Spins up a real MCP server against a test fixture and asserts:

  • /stats shape and arithmetic invariants (cacheHits == readHits + searchHits + globHits)
  • Phantom-hit regression (a /check against a path with no DB record correctly counts as a miss)
  • /check-search and /check-glob token-saving credits
  • Cold-cache disk fallback for multi-word queries
  • scanStats reachability
  • File-pattern narrowing on probe and content search

Contributing

  • Fork and create a feature branch off main.
  • Install dependencies (npm install) and build (npm run build).
  • Add tests under test/ for any behavior change.
  • Run npm run lint && npm test && node test/integration.mjs.
  • Update CHANGELOG.md under a new ## [x.y.z] - YYYY-MM-DD entry.
  • Open a PR with a clear description of the user-visible change and a reference to the symptom you observed (CHANGELOG entries on this project lead with the symptom — see CHANGELOG.md for examples).

Coding conventions

  • TypeScript strict mode; no any casts in committed code
  • Forward-slash paths in any string written to disk
  • Tool handlers are pure functions of (config, indexer, db) — easy to unit-test
  • Failures in non-critical paths are wrapped (try { … } catch { /* non-critical */ }) so a corrupted index row never breaks the whole server

License

MIT © CodeTree contributors

Acknowledgements

Built on top of:

Keywords

claude

FAQs

Package last updated on 19 Apr 2026

Did you know?

Socket

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Install

Related posts