codetree-claude 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.codetreerc.default.json +41 -0
- package/README.md +171 -0
- package/dist/cli.d.ts +3 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +185 -0
- package/dist/cli.js.map +1 -0
- package/dist/config.d.ts +131 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +111 -0
- package/dist/config.js.map +1 -0
- package/dist/hook/hook-client.d.ts +6 -0
- package/dist/hook/hook-client.d.ts.map +1 -0
- package/dist/hook/hook-client.js +48 -0
- package/dist/hook/hook-client.js.map +1 -0
- package/dist/hook/pre-tool-use.bundled.js +162 -0
- package/dist/hook/pre-tool-use.d.ts +14 -0
- package/dist/hook/pre-tool-use.d.ts.map +1 -0
- package/dist/hook/pre-tool-use.js +140 -0
- package/dist/hook/pre-tool-use.js.map +1 -0
- package/dist/index.d.ts +10 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +12 -0
- package/dist/index.js.map +1 -0
- package/dist/indexer/extractor-registry.d.ts +10 -0
- package/dist/indexer/extractor-registry.d.ts.map +1 -0
- package/dist/indexer/extractor-registry.js +39 -0
- package/dist/indexer/extractor-registry.js.map +1 -0
- package/dist/indexer/extractors/generic.d.ts +11 -0
- package/dist/indexer/extractors/generic.d.ts.map +1 -0
- package/dist/indexer/extractors/generic.js +12 -0
- package/dist/indexer/extractors/generic.js.map +1 -0
- package/dist/indexer/extractors/go.d.ts +10 -0
- package/dist/indexer/extractors/go.d.ts.map +1 -0
- package/dist/indexer/extractors/go.js +119 -0
- package/dist/indexer/extractors/go.js.map +1 -0
- package/dist/indexer/extractors/java.d.ts +10 -0
- package/dist/indexer/extractors/java.d.ts.map +1 -0
- package/dist/indexer/extractors/java.js +89 -0
- package/dist/indexer/extractors/java.js.map +1 -0
- package/dist/indexer/extractors/javascript.d.ts +11 -0
- package/dist/indexer/extractors/javascript.d.ts.map +1 -0
- package/dist/indexer/extractors/javascript.js +190 -0
- package/dist/indexer/extractors/javascript.js.map +1 -0
- package/dist/indexer/extractors/python.d.ts +11 -0
- package/dist/indexer/extractors/python.d.ts.map +1 -0
- package/dist/indexer/extractors/python.js +115 -0
- package/dist/indexer/extractors/python.js.map +1 -0
- package/dist/indexer/extractors/types.d.ts +26 -0
- package/dist/indexer/extractors/types.d.ts.map +1 -0
- package/dist/indexer/extractors/types.js +36 -0
- package/dist/indexer/extractors/types.js.map +1 -0
- package/dist/indexer/hasher.d.ts +11 -0
- package/dist/indexer/hasher.d.ts.map +1 -0
- package/dist/indexer/hasher.js +41 -0
- package/dist/indexer/hasher.js.map +1 -0
- package/dist/indexer/ignore.d.ts +15 -0
- package/dist/indexer/ignore.d.ts.map +1 -0
- package/dist/indexer/ignore.js +63 -0
- package/dist/indexer/ignore.js.map +1 -0
- package/dist/indexer/indexer.d.ts +64 -0
- package/dist/indexer/indexer.d.ts.map +1 -0
- package/dist/indexer/indexer.js +295 -0
- package/dist/indexer/indexer.js.map +1 -0
- package/dist/indexer/watcher.d.ts +16 -0
- package/dist/indexer/watcher.d.ts.map +1 -0
- package/dist/indexer/watcher.js +79 -0
- package/dist/indexer/watcher.js.map +1 -0
- package/dist/server/ipc.d.ts +38 -0
- package/dist/server/ipc.d.ts.map +1 -0
- package/dist/server/ipc.js +212 -0
- package/dist/server/ipc.js.map +1 -0
- package/dist/server/mcp-server.d.ts +2 -0
- package/dist/server/mcp-server.d.ts.map +1 -0
- package/dist/server/mcp-server.js +133 -0
- package/dist/server/mcp-server.js.map +1 -0
- package/dist/server/tools/codetree-find-refs.d.ts +46 -0
- package/dist/server/tools/codetree-find-refs.d.ts.map +1 -0
- package/dist/server/tools/codetree-find-refs.js +83 -0
- package/dist/server/tools/codetree-find-refs.js.map +1 -0
- package/dist/server/tools/codetree-read.d.ts +46 -0
- package/dist/server/tools/codetree-read.d.ts.map +1 -0
- package/dist/server/tools/codetree-read.js +82 -0
- package/dist/server/tools/codetree-read.js.map +1 -0
- package/dist/server/tools/codetree-search.d.ts +59 -0
- package/dist/server/tools/codetree-search.d.ts.map +1 -0
- package/dist/server/tools/codetree-search.js +92 -0
- package/dist/server/tools/codetree-search.js.map +1 -0
- package/dist/server/tools/codetree-structure.d.ts +55 -0
- package/dist/server/tools/codetree-structure.d.ts.map +1 -0
- package/dist/server/tools/codetree-structure.js +137 -0
- package/dist/server/tools/codetree-structure.js.map +1 -0
- package/dist/server/tools/codetree-summary.d.ts +36 -0
- package/dist/server/tools/codetree-summary.d.ts.map +1 -0
- package/dist/server/tools/codetree-summary.js +94 -0
- package/dist/server/tools/codetree-summary.js.map +1 -0
- package/dist/setup/install.d.ts +26 -0
- package/dist/setup/install.d.ts.map +1 -0
- package/dist/setup/install.js +127 -0
- package/dist/setup/install.js.map +1 -0
- package/dist/storage/cache.d.ts +29 -0
- package/dist/storage/cache.d.ts.map +1 -0
- package/dist/storage/cache.js +54 -0
- package/dist/storage/cache.js.map +1 -0
- package/dist/storage/database.d.ts +52 -0
- package/dist/storage/database.d.ts.map +1 -0
- package/dist/storage/database.js +346 -0
- package/dist/storage/database.js.map +1 -0
- package/package.json +60 -0
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "./codetree-config.schema.json",
|
|
3
|
+
"projectRoot": ".",
|
|
4
|
+
"ignore": [
|
|
5
|
+
".git",
|
|
6
|
+
"node_modules",
|
|
7
|
+
"dist",
|
|
8
|
+
"build",
|
|
9
|
+
"coverage",
|
|
10
|
+
".next",
|
|
11
|
+
"__pycache__",
|
|
12
|
+
".cache",
|
|
13
|
+
".turbo",
|
|
14
|
+
".vercel",
|
|
15
|
+
".output"
|
|
16
|
+
],
|
|
17
|
+
"ignoreBinary": true,
|
|
18
|
+
"maxFileSize": 1048576,
|
|
19
|
+
"cache": {
|
|
20
|
+
"memoryLimitMB": 256,
|
|
21
|
+
"dbPath": ".codetree/index.db",
|
|
22
|
+
"contentCacheMaxMB": 512
|
|
23
|
+
},
|
|
24
|
+
"ipc": {
|
|
25
|
+
"port": 0,
|
|
26
|
+
"host": "127.0.0.1"
|
|
27
|
+
},
|
|
28
|
+
"watch": {
|
|
29
|
+
"enabled": true,
|
|
30
|
+
"debounceMs": 300,
|
|
31
|
+
"usePolling": false
|
|
32
|
+
},
|
|
33
|
+
"symbols": {
|
|
34
|
+
"enabled": true,
|
|
35
|
+
"languages": ["javascript", "typescript", "python", "java", "go", "rust", "ruby", "csharp"]
|
|
36
|
+
},
|
|
37
|
+
"telemetry": {
|
|
38
|
+
"enabled": true,
|
|
39
|
+
"statsFile": ".codetree/stats.json"
|
|
40
|
+
}
|
|
41
|
+
}
|
package/README.md
ADDED
|
@@ -0,0 +1,171 @@
|
|
|
1
|
+
# CodeTree
|
|
2
|
+
|
|
3
|
+
**Reduce Claude Code token usage by 60-70%** by caching codebase reads in a persistent index.
|
|
4
|
+
|
|
5
|
+
## The Problem
|
|
6
|
+
|
|
7
|
+
When your team uses Claude Code, **~70% of tokens** go to re-reading the same files across conversations — Glob, Grep, and Read calls that scan the same codebase over and over.
|
|
8
|
+
|
|
9
|
+
## The Solution
|
|
10
|
+
|
|
11
|
+
CodeTree indexes your codebase into a persistent SQLite database and intercepts Claude Code's file operations. When a file hasn't changed since the last read, Claude uses the cached version.
|
|
12
|
+
|
|
13
|
+
### How it works
|
|
14
|
+
|
|
15
|
+
```
|
|
16
|
+
Developer asks Claude to work on a feature
|
|
17
|
+
│
|
|
18
|
+
├── Claude calls Read("src/api/auth.ts")
|
|
19
|
+
│ └── Hook intercepts → file cached? YES → redirect to codetree_read
|
|
20
|
+
│ └── Returns cached content + symbols metadata
|
|
21
|
+
│
|
|
22
|
+
├── Claude calls Grep("handleAuth")
|
|
23
|
+
│ └── Hook intercepts → symbol indexed? YES → redirect to codetree_search
|
|
24
|
+
│ └── Returns indexed symbol locations instantly
|
|
25
|
+
│
|
|
26
|
+
└── Claude calls Glob("src/**/*.ts")
|
|
27
|
+
└── Hook intercepts → tree indexed? YES → redirect to codetree_structure
|
|
28
|
+
└── Returns file tree from index
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
## Install
|
|
32
|
+
|
|
33
|
+
### Option 1: npm package (any project)
|
|
34
|
+
|
|
35
|
+
```bash
|
|
36
|
+
npm install -g codetree-claude
|
|
37
|
+
|
|
38
|
+
# In your project root:
|
|
39
|
+
codetree init
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
### Option 2: VS Code Extension
|
|
43
|
+
|
|
44
|
+
Install "CodeTree — Cache for Claude Code" from the VS Code marketplace. It auto-activates when you open a project.
|
|
45
|
+
|
|
46
|
+
### Option 3: Per-project dev dependency
|
|
47
|
+
|
|
48
|
+
```bash
|
|
49
|
+
npm install --save-dev codetree-claude
|
|
50
|
+
npx codetree init
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
## What gets created
|
|
54
|
+
|
|
55
|
+
```
|
|
56
|
+
your-project/
|
|
57
|
+
.codetreerc.json # Config (ignore patterns, cache size, etc.)
|
|
58
|
+
.claude/settings.json # PreToolUse hook registration
|
|
59
|
+
.mcp.json # MCP server registration
|
|
60
|
+
.codetree/ # Index database (gitignored)
|
|
61
|
+
index.db
|
|
62
|
+
ipc.port
|
|
63
|
+
stats.json
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
## CLI Commands
|
|
67
|
+
|
|
68
|
+
```bash
|
|
69
|
+
codetree init # Set up CodeTree in current project
|
|
70
|
+
codetree status # Check if running + index health
|
|
71
|
+
codetree stats # View cache hit rate + token savings
|
|
72
|
+
codetree reindex # Force full re-index
|
|
73
|
+
codetree help # Show help
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
## Configuration
|
|
77
|
+
|
|
78
|
+
Edit `.codetreerc.json` in your project root:
|
|
79
|
+
|
|
80
|
+
```json
|
|
81
|
+
{
|
|
82
|
+
"ignore": [".git", "node_modules", "dist", "build"],
|
|
83
|
+
"maxFileSize": 1048576,
|
|
84
|
+
"cache": {
|
|
85
|
+
"memoryLimitMB": 256,
|
|
86
|
+
"contentCacheMaxMB": 512
|
|
87
|
+
},
|
|
88
|
+
"symbols": {
|
|
89
|
+
"enabled": true,
|
|
90
|
+
"languages": ["javascript", "typescript", "python", "java", "go"]
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
## MCP Tools
|
|
96
|
+
|
|
97
|
+
CodeTree exposes 5 tools that Claude Code uses instead of native Read/Grep/Glob:
|
|
98
|
+
|
|
99
|
+
| Tool | Replaces | What it does |
|
|
100
|
+
|------|----------|-------------|
|
|
101
|
+
| `codetree_read` | Read | Cached file read with symbol metadata |
|
|
102
|
+
| `codetree_search` | Grep | Symbol index search (functions, classes, types) |
|
|
103
|
+
| `codetree_structure` | Glob | Project tree browser with language stats |
|
|
104
|
+
| `codetree_find_refs` | — | Cross-file reference finder |
|
|
105
|
+
| `codetree_summary` | — | Full project overview for session start |
|
|
106
|
+
|
|
107
|
+
## Supported Languages
|
|
108
|
+
|
|
109
|
+
Symbol extraction works for:
|
|
110
|
+
- JavaScript / TypeScript (JSX, TSX)
|
|
111
|
+
- Python
|
|
112
|
+
- Java / Kotlin / C#
|
|
113
|
+
- Go
|
|
114
|
+
- All other files get indexed (content cached) but without symbol extraction
|
|
115
|
+
|
|
116
|
+
## Architecture
|
|
117
|
+
|
|
118
|
+
```
|
|
119
|
+
┌─────────────────────────────────────────────┐
|
|
120
|
+
│ Claude Code │
|
|
121
|
+
│ ┌───────────────────────────────────────┐ │
|
|
122
|
+
│ │ PreToolUse Hook │ │
|
|
123
|
+
│ │ Intercepts Read/Grep/Glob │ │
|
|
124
|
+
│ │ Queries IPC server (<30ms) │ │
|
|
125
|
+
│ │ Redirects to MCP tools if cached │ │
|
|
126
|
+
│ └─────────────┬─────────────────────────┘ │
|
|
127
|
+
│ │ │
|
|
128
|
+
│ ┌─────────────▼─────────────────────────┐ │
|
|
129
|
+
│ │ MCP Server (codetree) │ │
|
|
130
|
+
│ │ ├── codetree_read │ │
|
|
131
|
+
│ │ ├── codetree_search │ │
|
|
132
|
+
│ │ ├── codetree_structure │ │
|
|
133
|
+
│ │ ├── codetree_find_refs │ │
|
|
134
|
+
│ │ └── codetree_summary │ │
|
|
135
|
+
│ └─────────────┬─────────────────────────┘ │
|
|
136
|
+
│ │ │
|
|
137
|
+
│ ┌─────────────▼─────────────────────────┐ │
|
|
138
|
+
│ │ Indexer + File Watcher │ │
|
|
139
|
+
│ │ ├── SQLite database (persistent) │ │
|
|
140
|
+
│ │ ├── LRU in-memory cache (hot files) │ │
|
|
141
|
+
│ │ ├── Symbol extraction (regex-based) │ │
|
|
142
|
+
│ │ └── chokidar watcher (live updates) │ │
|
|
143
|
+
│ └───────────────────────────────────────┘ │
|
|
144
|
+
└─────────────────────────────────────────────┘
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
## Org-wide Rollout
|
|
148
|
+
|
|
149
|
+
1. Add `codetree-claude` as a dev dependency in your repos
|
|
150
|
+
2. Commit `.codetreerc.json` and `.mcp.json` to version control
|
|
151
|
+
3. Add `.codetree/` to `.gitignore` (done automatically by `codetree init`)
|
|
152
|
+
4. Each developer runs `npx codetree init` once (or use the VS Code extension)
|
|
153
|
+
|
|
154
|
+
The index database is local to each machine — it rebuilds automatically on first run.
|
|
155
|
+
|
|
156
|
+
## Token Savings Estimate
|
|
157
|
+
|
|
158
|
+
For a typical session on a 10K-file TypeScript project:
|
|
159
|
+
|
|
160
|
+
| Without CodeTree | With CodeTree |
|
|
161
|
+
|-----------------|---------------|
|
|
162
|
+
| ~50 Read calls per task | ~10 Read calls (rest cached) |
|
|
163
|
+
| ~20 Grep calls per task | ~5 Grep calls (rest from index) |
|
|
164
|
+
| ~15 Glob calls per task | ~3 Glob calls (rest from tree) |
|
|
165
|
+
| **~800K tokens/task** | **~250K tokens/task** |
|
|
166
|
+
|
|
167
|
+
Run `codetree stats` to see actual savings for your project.
|
|
168
|
+
|
|
169
|
+
## License
|
|
170
|
+
|
|
171
|
+
MIT
|
package/dist/cli.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":""}
|
package/dist/cli.js
ADDED
|
@@ -0,0 +1,185 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { resolve, join, dirname } from "node:path";
|
|
3
|
+
import { existsSync, readFileSync } from "node:fs";
|
|
4
|
+
import { fileURLToPath } from "node:url";
|
|
5
|
+
import { findProjectRoot, loadConfig } from "./config.js";
|
|
6
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
7
|
+
const __dirname = dirname(__filename);
|
|
8
|
+
import { installHook, installMcpServer, createDefaultConfig, updateGitignore } from "./setup/install.js";
|
|
9
|
+
const args = process.argv.slice(2);
|
|
10
|
+
const command = args[0];
|
|
11
|
+
async function main() {
|
|
12
|
+
switch (command) {
|
|
13
|
+
case "init":
|
|
14
|
+
await handleInit();
|
|
15
|
+
break;
|
|
16
|
+
case "status":
|
|
17
|
+
await handleStatus();
|
|
18
|
+
break;
|
|
19
|
+
case "stats":
|
|
20
|
+
await handleStats();
|
|
21
|
+
break;
|
|
22
|
+
case "reindex":
|
|
23
|
+
await handleReindex();
|
|
24
|
+
break;
|
|
25
|
+
case "help":
|
|
26
|
+
default:
|
|
27
|
+
printHelp();
|
|
28
|
+
break;
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
async function handleInit() {
|
|
32
|
+
const projectRoot = findProjectRoot(process.cwd());
|
|
33
|
+
console.log(`\n CodeTree — Codebase Cache for Claude Code\n`);
|
|
34
|
+
console.log(` Project root: ${projectRoot}\n`);
|
|
35
|
+
// 1. Create config
|
|
36
|
+
const configResult = createDefaultConfig(projectRoot);
|
|
37
|
+
console.log(` [1/4] Config: ${configResult.path}`);
|
|
38
|
+
// 2. Update .gitignore
|
|
39
|
+
updateGitignore(projectRoot);
|
|
40
|
+
console.log(` [2/4] Added .codetree/ to .gitignore`);
|
|
41
|
+
// 3. Register hook
|
|
42
|
+
// Find the hook script path — it's relative to this package
|
|
43
|
+
const packageRoot = findPackageRoot();
|
|
44
|
+
const hookScript = join(packageRoot, "dist", "hook", "pre-tool-use.js");
|
|
45
|
+
const hookResult = installHook(projectRoot, hookScript);
|
|
46
|
+
console.log(` [3/4] Hook: ${hookResult.message}`);
|
|
47
|
+
// 4. Register MCP server
|
|
48
|
+
const serverScript = join(packageRoot, "dist", "server", "mcp-server.js");
|
|
49
|
+
const mcpResult = installMcpServer(projectRoot, serverScript);
|
|
50
|
+
console.log(` [4/4] MCP: ${mcpResult.message}`);
|
|
51
|
+
console.log(`
|
|
52
|
+
Setup complete. CodeTree will:
|
|
53
|
+
|
|
54
|
+
1. Start automatically when Claude Code opens this project (via MCP server)
|
|
55
|
+
2. Index your codebase into a persistent SQLite database
|
|
56
|
+
3. Intercept Read/Grep/Glob calls via the PreToolUse hook
|
|
57
|
+
4. Redirect Claude to cached results, saving ~60-70% tokens on exploration
|
|
58
|
+
|
|
59
|
+
Files created:
|
|
60
|
+
.codetreerc.json — Configuration (edit to customize ignores, cache size, etc.)
|
|
61
|
+
.claude/settings.json — Hook registration
|
|
62
|
+
.mcp.json — MCP server registration
|
|
63
|
+
|
|
64
|
+
Commands:
|
|
65
|
+
codetree status — Check if the index is running and healthy
|
|
66
|
+
codetree stats — View cache hit rates and token savings
|
|
67
|
+
codetree reindex — Force a full re-index
|
|
68
|
+
|
|
69
|
+
The index database lives in .codetree/ (gitignored).
|
|
70
|
+
`);
|
|
71
|
+
}
|
|
72
|
+
async function handleStatus() {
|
|
73
|
+
const projectRoot = findProjectRoot(process.cwd());
|
|
74
|
+
const portFile = join(projectRoot, ".codetree", "ipc.port");
|
|
75
|
+
if (!existsSync(portFile)) {
|
|
76
|
+
console.log(" CodeTree is not running. Start a Claude Code session to launch it.");
|
|
77
|
+
return;
|
|
78
|
+
}
|
|
79
|
+
const port = parseInt(readFileSync(portFile, "utf-8").trim(), 10);
|
|
80
|
+
try {
|
|
81
|
+
const response = await fetch(`http://127.0.0.1:${port}/status`);
|
|
82
|
+
const status = await response.json();
|
|
83
|
+
console.log(`\n CodeTree Status`);
|
|
84
|
+
console.log(` ───────────────`);
|
|
85
|
+
console.log(` Running: yes (port ${port})`);
|
|
86
|
+
console.log(` Ready: ${status.ready}`);
|
|
87
|
+
console.log(` Indexing: ${status.indexing}`);
|
|
88
|
+
console.log(` Files: ${status.fileCount}`);
|
|
89
|
+
console.log();
|
|
90
|
+
}
|
|
91
|
+
catch {
|
|
92
|
+
console.log(" CodeTree server is not responding. It may have stopped.");
|
|
93
|
+
console.log(" Start a new Claude Code session to relaunch.");
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
async function handleStats() {
|
|
97
|
+
const projectRoot = findProjectRoot(process.cwd());
|
|
98
|
+
const portFile = join(projectRoot, ".codetree", "ipc.port");
|
|
99
|
+
// Try live stats first
|
|
100
|
+
if (existsSync(portFile)) {
|
|
101
|
+
const port = parseInt(readFileSync(portFile, "utf-8").trim(), 10);
|
|
102
|
+
try {
|
|
103
|
+
const response = await fetch(`http://127.0.0.1:${port}/stats`);
|
|
104
|
+
const stats = await response.json();
|
|
105
|
+
printStats(stats);
|
|
106
|
+
return;
|
|
107
|
+
}
|
|
108
|
+
catch {
|
|
109
|
+
// Fall through to file-based stats
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
// Try stats file
|
|
113
|
+
const config = loadConfig(projectRoot);
|
|
114
|
+
if (existsSync(config.telemetry.statsFile)) {
|
|
115
|
+
try {
|
|
116
|
+
const stats = JSON.parse(readFileSync(config.telemetry.statsFile, "utf-8"));
|
|
117
|
+
printStats(stats);
|
|
118
|
+
return;
|
|
119
|
+
}
|
|
120
|
+
catch {
|
|
121
|
+
// Fall through
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
console.log(" No stats available. Run a Claude Code session with CodeTree first.");
|
|
125
|
+
}
|
|
126
|
+
function printStats(stats) {
|
|
127
|
+
const hitRate = stats.hitRate;
|
|
128
|
+
const tokensSaved = stats.estimatedTokensSaved || stats.tokensSaved || 0;
|
|
129
|
+
console.log(`\n CodeTree Statistics`);
|
|
130
|
+
console.log(` ──────────────────`);
|
|
131
|
+
console.log(` Hook queries: ${stats.hookQueries}`);
|
|
132
|
+
console.log(` Cache hits: ${stats.cacheHits}`);
|
|
133
|
+
console.log(` Cache misses: ${stats.cacheMisses}`);
|
|
134
|
+
console.log(` Hit rate: ${(hitRate * 100).toFixed(1)}%`);
|
|
135
|
+
console.log(` Tokens saved: ~${formatNumber(tokensSaved)}`);
|
|
136
|
+
console.log(` Est. cost saved: ~$${((tokensSaved / 1_000_000) * 3).toFixed(2)} (at $3/MTok)`);
|
|
137
|
+
console.log();
|
|
138
|
+
}
|
|
139
|
+
async function handleReindex() {
|
|
140
|
+
console.log(" Triggering full reindex...");
|
|
141
|
+
console.log(" This is done automatically — just restart your Claude Code session.");
|
|
142
|
+
console.log(" To force it: delete .codetree/index.db and restart Claude Code.");
|
|
143
|
+
}
|
|
144
|
+
function printHelp() {
|
|
145
|
+
console.log(`
|
|
146
|
+
CodeTree — Codebase Cache for Claude Code
|
|
147
|
+
|
|
148
|
+
Usage:
|
|
149
|
+
codetree init Set up CodeTree in the current project
|
|
150
|
+
codetree status Check if CodeTree is running
|
|
151
|
+
codetree stats View cache hit rates and estimated token savings
|
|
152
|
+
codetree reindex Force a full re-index
|
|
153
|
+
codetree help Show this help
|
|
154
|
+
|
|
155
|
+
How it works:
|
|
156
|
+
CodeTree indexes your codebase into a persistent SQLite database
|
|
157
|
+
and intercepts Claude Code's Read/Grep/Glob calls. When a file is
|
|
158
|
+
cached and unchanged, Claude uses the cached version instead of
|
|
159
|
+
re-reading it, saving ~60-70% of tokens spent on codebase exploration.
|
|
160
|
+
`);
|
|
161
|
+
}
|
|
162
|
+
function findPackageRoot() {
|
|
163
|
+
let dir = resolve(__dirname);
|
|
164
|
+
for (let i = 0; i < 10; i++) {
|
|
165
|
+
if (existsSync(join(dir, "package.json")))
|
|
166
|
+
return dir;
|
|
167
|
+
const parent = resolve(dir, "..");
|
|
168
|
+
if (parent === dir)
|
|
169
|
+
break;
|
|
170
|
+
dir = parent;
|
|
171
|
+
}
|
|
172
|
+
return resolve(__dirname, "..");
|
|
173
|
+
}
|
|
174
|
+
function formatNumber(n) {
|
|
175
|
+
if (n < 1_000)
|
|
176
|
+
return String(n);
|
|
177
|
+
if (n < 1_000_000)
|
|
178
|
+
return `${(n / 1_000).toFixed(1)}K`;
|
|
179
|
+
return `${(n / 1_000_000).toFixed(1)}M`;
|
|
180
|
+
}
|
|
181
|
+
main().catch((err) => {
|
|
182
|
+
console.error(`Error: ${err.message}`);
|
|
183
|
+
process.exit(1);
|
|
184
|
+
});
|
|
185
|
+
//# sourceMappingURL=cli.js.map
|
package/dist/cli.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"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"}
|
package/dist/config.d.ts
ADDED
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
declare const ConfigSchema: z.ZodObject<{
|
|
3
|
+
projectRoot: z.ZodDefault<z.ZodString>;
|
|
4
|
+
ignore: z.ZodDefault<z.ZodArray<z.ZodString, "many">>;
|
|
5
|
+
ignoreBinary: z.ZodDefault<z.ZodBoolean>;
|
|
6
|
+
maxFileSize: z.ZodDefault<z.ZodNumber>;
|
|
7
|
+
cache: z.ZodDefault<z.ZodObject<{
|
|
8
|
+
memoryLimitMB: z.ZodDefault<z.ZodNumber>;
|
|
9
|
+
dbPath: z.ZodDefault<z.ZodString>;
|
|
10
|
+
contentCacheMaxMB: z.ZodDefault<z.ZodNumber>;
|
|
11
|
+
}, "strip", z.ZodTypeAny, {
|
|
12
|
+
memoryLimitMB: number;
|
|
13
|
+
dbPath: string;
|
|
14
|
+
contentCacheMaxMB: number;
|
|
15
|
+
}, {
|
|
16
|
+
memoryLimitMB?: number | undefined;
|
|
17
|
+
dbPath?: string | undefined;
|
|
18
|
+
contentCacheMaxMB?: number | undefined;
|
|
19
|
+
}>>;
|
|
20
|
+
ipc: z.ZodDefault<z.ZodObject<{
|
|
21
|
+
port: z.ZodDefault<z.ZodNumber>;
|
|
22
|
+
host: z.ZodDefault<z.ZodString>;
|
|
23
|
+
}, "strip", z.ZodTypeAny, {
|
|
24
|
+
port: number;
|
|
25
|
+
host: string;
|
|
26
|
+
}, {
|
|
27
|
+
port?: number | undefined;
|
|
28
|
+
host?: string | undefined;
|
|
29
|
+
}>>;
|
|
30
|
+
watch: z.ZodDefault<z.ZodObject<{
|
|
31
|
+
enabled: z.ZodDefault<z.ZodBoolean>;
|
|
32
|
+
debounceMs: z.ZodDefault<z.ZodNumber>;
|
|
33
|
+
usePolling: z.ZodDefault<z.ZodBoolean>;
|
|
34
|
+
}, "strip", z.ZodTypeAny, {
|
|
35
|
+
enabled: boolean;
|
|
36
|
+
debounceMs: number;
|
|
37
|
+
usePolling: boolean;
|
|
38
|
+
}, {
|
|
39
|
+
enabled?: boolean | undefined;
|
|
40
|
+
debounceMs?: number | undefined;
|
|
41
|
+
usePolling?: boolean | undefined;
|
|
42
|
+
}>>;
|
|
43
|
+
symbols: z.ZodDefault<z.ZodObject<{
|
|
44
|
+
enabled: z.ZodDefault<z.ZodBoolean>;
|
|
45
|
+
languages: z.ZodDefault<z.ZodArray<z.ZodString, "many">>;
|
|
46
|
+
}, "strip", z.ZodTypeAny, {
|
|
47
|
+
enabled: boolean;
|
|
48
|
+
languages: string[];
|
|
49
|
+
}, {
|
|
50
|
+
enabled?: boolean | undefined;
|
|
51
|
+
languages?: string[] | undefined;
|
|
52
|
+
}>>;
|
|
53
|
+
telemetry: z.ZodDefault<z.ZodObject<{
|
|
54
|
+
enabled: z.ZodDefault<z.ZodBoolean>;
|
|
55
|
+
statsFile: z.ZodDefault<z.ZodString>;
|
|
56
|
+
}, "strip", z.ZodTypeAny, {
|
|
57
|
+
enabled: boolean;
|
|
58
|
+
statsFile: string;
|
|
59
|
+
}, {
|
|
60
|
+
enabled?: boolean | undefined;
|
|
61
|
+
statsFile?: string | undefined;
|
|
62
|
+
}>>;
|
|
63
|
+
}, "strip", z.ZodTypeAny, {
|
|
64
|
+
projectRoot: string;
|
|
65
|
+
ignore: string[];
|
|
66
|
+
ignoreBinary: boolean;
|
|
67
|
+
maxFileSize: number;
|
|
68
|
+
cache: {
|
|
69
|
+
memoryLimitMB: number;
|
|
70
|
+
dbPath: string;
|
|
71
|
+
contentCacheMaxMB: number;
|
|
72
|
+
};
|
|
73
|
+
ipc: {
|
|
74
|
+
port: number;
|
|
75
|
+
host: string;
|
|
76
|
+
};
|
|
77
|
+
watch: {
|
|
78
|
+
enabled: boolean;
|
|
79
|
+
debounceMs: number;
|
|
80
|
+
usePolling: boolean;
|
|
81
|
+
};
|
|
82
|
+
symbols: {
|
|
83
|
+
enabled: boolean;
|
|
84
|
+
languages: string[];
|
|
85
|
+
};
|
|
86
|
+
telemetry: {
|
|
87
|
+
enabled: boolean;
|
|
88
|
+
statsFile: string;
|
|
89
|
+
};
|
|
90
|
+
}, {
|
|
91
|
+
projectRoot?: string | undefined;
|
|
92
|
+
ignore?: string[] | undefined;
|
|
93
|
+
ignoreBinary?: boolean | undefined;
|
|
94
|
+
maxFileSize?: number | undefined;
|
|
95
|
+
cache?: {
|
|
96
|
+
memoryLimitMB?: number | undefined;
|
|
97
|
+
dbPath?: string | undefined;
|
|
98
|
+
contentCacheMaxMB?: number | undefined;
|
|
99
|
+
} | undefined;
|
|
100
|
+
ipc?: {
|
|
101
|
+
port?: number | undefined;
|
|
102
|
+
host?: string | undefined;
|
|
103
|
+
} | undefined;
|
|
104
|
+
watch?: {
|
|
105
|
+
enabled?: boolean | undefined;
|
|
106
|
+
debounceMs?: number | undefined;
|
|
107
|
+
usePolling?: boolean | undefined;
|
|
108
|
+
} | undefined;
|
|
109
|
+
symbols?: {
|
|
110
|
+
enabled?: boolean | undefined;
|
|
111
|
+
languages?: string[] | undefined;
|
|
112
|
+
} | undefined;
|
|
113
|
+
telemetry?: {
|
|
114
|
+
enabled?: boolean | undefined;
|
|
115
|
+
statsFile?: string | undefined;
|
|
116
|
+
} | undefined;
|
|
117
|
+
}>;
|
|
118
|
+
export type CodeTreeConfig = z.infer<typeof ConfigSchema>;
|
|
119
|
+
/**
|
|
120
|
+
* Find the project root by walking up from startDir looking for config files or .git
|
|
121
|
+
*/
|
|
122
|
+
export declare function findProjectRoot(startDir: string): string;
|
|
123
|
+
/**
|
|
124
|
+
* Load config from .codetreerc.json, merging with defaults
|
|
125
|
+
*/
|
|
126
|
+
export declare function loadConfig(projectRoot?: string): CodeTreeConfig;
|
|
127
|
+
export declare function normalizePath(p: string): string;
|
|
128
|
+
export declare const BINARY_EXTENSIONS: Set<string>;
|
|
129
|
+
export declare function isBinaryExtension(ext: string): boolean;
|
|
130
|
+
export {};
|
|
131
|
+
//# sourceMappingURL=config.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AA+BxB,QAAA,MAAM,YAAY;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAahB,CAAC;AAEH,MAAM,MAAM,cAAc,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,YAAY,CAAC,CAAC;AAI1D;;GAEG;AACH,wBAAgB,eAAe,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAoBxD;AAED;;GAEG;AACH,wBAAgB,UAAU,CAAC,WAAW,CAAC,EAAE,MAAM,GAAG,cAAc,CAyB/D;AAGD,wBAAgB,aAAa,CAAC,CAAC,EAAE,MAAM,GAAG,MAAM,CAE/C;AAGD,eAAO,MAAM,iBAAiB,aAQ5B,CAAC;AAEH,wBAAgB,iBAAiB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAEtD"}
|
package/dist/config.js
ADDED
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
import { readFileSync, existsSync } from "node:fs";
|
|
2
|
+
import { resolve, join, dirname } from "node:path";
|
|
3
|
+
import { z } from "zod";
|
|
4
|
+
const CacheConfigSchema = z.object({
|
|
5
|
+
memoryLimitMB: z.number().min(32).max(4096).default(256),
|
|
6
|
+
dbPath: z.string().default(".codetree/index.db"),
|
|
7
|
+
contentCacheMaxMB: z.number().min(64).max(8192).default(512),
|
|
8
|
+
});
|
|
9
|
+
const IpcConfigSchema = z.object({
|
|
10
|
+
port: z.number().min(0).max(65535).default(0), // 0 = auto-assign
|
|
11
|
+
host: z.string().default("127.0.0.1"),
|
|
12
|
+
});
|
|
13
|
+
const WatchConfigSchema = z.object({
|
|
14
|
+
enabled: z.boolean().default(true),
|
|
15
|
+
debounceMs: z.number().min(50).max(5000).default(300),
|
|
16
|
+
usePolling: z.boolean().default(false),
|
|
17
|
+
});
|
|
18
|
+
const SymbolsConfigSchema = z.object({
|
|
19
|
+
enabled: z.boolean().default(true),
|
|
20
|
+
languages: z.array(z.string()).default([
|
|
21
|
+
"javascript", "typescript", "python", "java", "go", "rust", "ruby", "csharp",
|
|
22
|
+
]),
|
|
23
|
+
});
|
|
24
|
+
const TelemetryConfigSchema = z.object({
|
|
25
|
+
enabled: z.boolean().default(true),
|
|
26
|
+
statsFile: z.string().default(".codetree/stats.json"),
|
|
27
|
+
});
|
|
28
|
+
const ConfigSchema = z.object({
|
|
29
|
+
projectRoot: z.string().default("."),
|
|
30
|
+
ignore: z.array(z.string()).default([
|
|
31
|
+
".git", "node_modules", "dist", "build", "coverage",
|
|
32
|
+
".next", "__pycache__", ".cache", ".turbo",
|
|
33
|
+
]),
|
|
34
|
+
ignoreBinary: z.boolean().default(true),
|
|
35
|
+
maxFileSize: z.number().min(1024).default(1_048_576), // 1MB
|
|
36
|
+
cache: CacheConfigSchema.default({}),
|
|
37
|
+
ipc: IpcConfigSchema.default({}),
|
|
38
|
+
watch: WatchConfigSchema.default({}),
|
|
39
|
+
symbols: SymbolsConfigSchema.default({}),
|
|
40
|
+
telemetry: TelemetryConfigSchema.default({}),
|
|
41
|
+
});
|
|
42
|
+
const CONFIG_FILENAMES = [".codetreerc.json", ".codetreerc", "codetree.config.json"];
|
|
43
|
+
/**
|
|
44
|
+
* Find the project root by walking up from startDir looking for config files or .git
|
|
45
|
+
*/
|
|
46
|
+
export function findProjectRoot(startDir) {
|
|
47
|
+
let dir = resolve(startDir);
|
|
48
|
+
const root = dirname(dir) === dir ? dir : undefined;
|
|
49
|
+
while (true) {
|
|
50
|
+
// Check for config file
|
|
51
|
+
for (const name of CONFIG_FILENAMES) {
|
|
52
|
+
if (existsSync(join(dir, name)))
|
|
53
|
+
return dir;
|
|
54
|
+
}
|
|
55
|
+
// Check for .git
|
|
56
|
+
if (existsSync(join(dir, ".git")))
|
|
57
|
+
return dir;
|
|
58
|
+
// Check for package.json
|
|
59
|
+
if (existsSync(join(dir, "package.json")))
|
|
60
|
+
return dir;
|
|
61
|
+
const parent = dirname(dir);
|
|
62
|
+
if (parent === dir)
|
|
63
|
+
break; // reached filesystem root
|
|
64
|
+
dir = parent;
|
|
65
|
+
}
|
|
66
|
+
return startDir; // fallback to startDir
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* Load config from .codetreerc.json, merging with defaults
|
|
70
|
+
*/
|
|
71
|
+
export function loadConfig(projectRoot) {
|
|
72
|
+
const root = projectRoot ?? findProjectRoot(process.cwd());
|
|
73
|
+
let rawConfig = {};
|
|
74
|
+
for (const name of CONFIG_FILENAMES) {
|
|
75
|
+
const configPath = join(root, name);
|
|
76
|
+
if (existsSync(configPath)) {
|
|
77
|
+
try {
|
|
78
|
+
const content = readFileSync(configPath, "utf-8");
|
|
79
|
+
rawConfig = JSON.parse(content);
|
|
80
|
+
break;
|
|
81
|
+
}
|
|
82
|
+
catch {
|
|
83
|
+
// Invalid JSON, use defaults
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
const config = ConfigSchema.parse(rawConfig);
|
|
88
|
+
// Resolve relative paths against project root
|
|
89
|
+
config.projectRoot = resolve(root, config.projectRoot);
|
|
90
|
+
config.cache.dbPath = resolve(root, config.cache.dbPath);
|
|
91
|
+
config.telemetry.statsFile = resolve(root, config.telemetry.statsFile);
|
|
92
|
+
return config;
|
|
93
|
+
}
|
|
94
|
+
// Normalize paths to forward slashes for cross-platform consistency
|
|
95
|
+
export function normalizePath(p) {
|
|
96
|
+
return p.replace(/\\/g, "/");
|
|
97
|
+
}
|
|
98
|
+
// Binary file extensions to skip
|
|
99
|
+
export const BINARY_EXTENSIONS = new Set([
|
|
100
|
+
".png", ".jpg", ".jpeg", ".gif", ".ico", ".bmp", ".webp", ".svg",
|
|
101
|
+
".woff", ".woff2", ".ttf", ".eot", ".otf",
|
|
102
|
+
".pdf", ".zip", ".tar", ".gz", ".bz2", ".7z", ".rar",
|
|
103
|
+
".exe", ".dll", ".so", ".dylib", ".bin",
|
|
104
|
+
".mp3", ".mp4", ".avi", ".mov", ".wmv", ".flv", ".webm",
|
|
105
|
+
".sqlite", ".db", ".lock",
|
|
106
|
+
".wasm",
|
|
107
|
+
]);
|
|
108
|
+
export function isBinaryExtension(ext) {
|
|
109
|
+
return BINARY_EXTENSIONS.has(ext.toLowerCase());
|
|
110
|
+
}
|
|
111
|
+
//# sourceMappingURL=config.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Fast HTTP client for hook -> IPC server communication.
|
|
3
|
+
* Must resolve in <30ms to keep total hook latency under 50ms.
|
|
4
|
+
*/
|
|
5
|
+
export declare function queryIpc(port: number, path: string, timeoutMs?: number): Promise<Record<string, unknown> | null>;
|
|
6
|
+
//# sourceMappingURL=hook-client.d.ts.map
|