@fodx/codelens 2.0.1 → 2.1.1

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/docs/routing.md CHANGED
@@ -25,6 +25,12 @@ reads from disk — never stale), and `cl_save`/`cl_load` to persist working
25
25
  context across compaction. If a query result has `stale:true`, read that file
26
26
  from disk before relying on indexed snippets/edges.
27
27
 
28
+ If `cl_current.inGitRepo` is false or `repo` points outside the current
29
+ workspace, CodeLens is not attached to this workspace. Report the setup issue and
30
+ ask the user to run `codelens install --target cursor --location local --yes`
31
+ from the workspace root (or restart the MCP server after roots attach). Do not
32
+ silently fall back to raw `find`/`grep` for discovery.
33
+
28
34
  ## When raw grep/find/read is fine (or better)
29
35
 
30
36
  - you already know an exact string/symbol/path
@@ -42,7 +48,9 @@ you're looking for.
42
48
  Results are scoped to the **current branch/worktree index only** by default.
43
49
  After `git checkout`, results will not leak from the old branch. If you switch
44
50
  branches mid-task, call `cl_current` again; the tool activates/creates the new
45
- branch's index automatically.
51
+ branch's index automatically. MCP clients that provide Roots let CodeLens attach
52
+ to the active workspace even from a global MCP config; otherwise use `--cwd` or
53
+ project-local MCP config.
46
54
 
47
55
  ## Freshness
48
56
 
package/docs/tools.md CHANGED
@@ -24,8 +24,8 @@ JSON-serialized text content.
24
24
  - **Line-range format**: `cl_search` reports `lines` as a `"start-end"` string for compact display; `cl_map` and `cl_expand` use numeric `startLine`/`endLine` for programmatic use. This difference is intentional.
25
25
 
26
26
  ## cl_explore
27
- - **Input**: `{ query: string, limit?: number=8, cursor?: string, contentType?: "code"|"prose", snippet?: "none"|"headline"|"compact"|"full", relatedDepth?: number=1 }`
28
- - **Returns**: `{ indexId, query, count, files:[{path, stale?, results:[{handle,lines,score,why,preview,signature?,collapsed?,stale?}]}], related:[{sourcePath,path,edgeType,hops,confidence,stale?}], freshness, pendingFiles?, nextCursor? }`
27
+ - **Input**: `{ query: string, limit?: number=8, cursor?: string, contentType?: "code"|"prose", snippet?: "none"|"headline"|"compact"|"full", relatedDepth?: number=1, maxFiles?: number=6, maxResultsPerFile?: number=3, maxRelated?: number=20 }`
28
+ - **Returns**: `{ indexId, query, count, files:[{path, stale?, results:[{handle,lines,score,why,preview,signature?,collapsed?,stale?}]}], related:[{sourcePath,path,edgeType,hops,confidence,stale?}], freshness, pendingFiles?, nextCursor?, truncated? }`
29
29
  - **Use**: broad orientation in one call — "how does X work?", "show the flow around Y", or surveying an unfamiliar area. It fuses `cl_search` + grouped previews + graph relationships; use `cl_search` when you only need to locate handles.
30
30
 
31
31
  ## cl_related
@@ -35,8 +35,8 @@ JSON-serialized text content.
35
35
 
36
36
  ## cl_impact
37
37
  - **Input**: `{ symbol?: string, path?: string, depth?: number=2, includeTests?: boolean=true }`
38
- - **Returns**: `{ indexId, target?, candidates?, callers, callees, affectedFiles, affectedTests, depth, confidenceNote, freshness?, pendingFiles? }`
39
- - **Use**: before changing shared code. Pass `symbol` plus `path` when possible; if a symbol is ambiguous, CodeLens returns `candidates` instead of guessing. Impact is edge-derived and includes confidence/hop counts; use `cl_expand` to inspect exact current code before editing.
38
+ - **Returns**: `{ indexId, target?, candidates?, callers, callees, affectedFiles, affectedTests, depth, summary?, confidenceNote, freshness?, pendingFiles? }`
39
+ - **Use**: before changing shared code. Pass `symbol` plus `path` when possible; if a symbol is ambiguous, CodeLens returns `candidates` instead of guessing. Impact is edge-derived and includes confidence/hop counts plus provenance labels (`graph` or conservative `path-heuristic`); use `cl_expand` to inspect exact current code before editing.
40
40
 
41
41
  ## cl_map
42
42
  - **Input**: `{ path?: string, limit?: number=50, all?: boolean }`
@@ -0,0 +1,89 @@
1
+ # Usage metrics — how "saved" is calculated
2
+
3
+ `cl_usage` reports per-tool call counts, bytes served, and an **estimated**
4
+ context-window saving. The saving is an *estimate*, not a measurement — this
5
+ page explains exactly how it's computed and its limits.
6
+
7
+ ## Which tools are tracked
8
+
9
+ Only the agent's **retrieval + context-management** tools are tracked as
10
+ "usage" — the ones that represent the agent actually using CodeLens to
11
+ find/read/save code:
12
+
13
+ | Tool | tracked | calls | bytes_served | bytes_saved |
14
+ |------|---------|-------|--------------|-------------|
15
+ | `cl_search` | ✅ | ✅ | ✅ | ✅ (discovery) |
16
+ | `cl_explore` | ✅ | ✅ | ✅ | ✅ (discovery) |
17
+ | `cl_related` | ✅ | ✅ | ✅ | ✅ (discovery) |
18
+ | `cl_impact` | ✅ | ✅ | ✅ | ✅ (discovery) |
19
+ | `cl_expand` | ✅ | ✅ | ✅ | 0 (it *is* the scoped read step) |
20
+ | `cl_save` / `cl_load` | ✅ | ✅ | ✅ | 0 (context management) |
21
+
22
+ **Operational tools are NOT tracked** (they're maintenance, not usage):
23
+ `cl_refresh`, `cl_doctor`, `cl_stats`, `cl_prune`, `cl_drop`, `cl_current`,
24
+ `cl_usage`. So `cl_refresh` (building the index) does not appear in the usage
25
+ report, and checking `cl_usage` never inflates the numbers.
26
+
27
+ Only the **discovery** tools (`cl_search`, `cl_explore`, `cl_related`, `cl_impact`) accrue `bytes_saved` —
28
+ the ones that replace "grep + read a bunch of files" with compact indexed context.
29
+
30
+ ## The formula (refined — actual file sizes)
31
+
32
+ For a discovery call, CodeLens computes savings from the **real sizes of the
33
+ files in the results**, which it already indexes (`files.size`):
34
+
35
+ ```
36
+ saved = max(0, Σ(distinct result files' indexed sizes) − bytesServed)
37
+ ```
38
+
39
+ - `distinct result files` = the unique paths among the returned handles/files
40
+ (`cl_search`/`cl_related` carry `results[].path`; `cl_explore` carries
41
+ `files[].path`; `cl_impact` carries paths in target/candidates/callers/callees/affected lists).
42
+ - `indexed sizes` = `files.size` for those paths in the current branch index.
43
+ - `bytesServed` = bytes of the JSON actually sent to the model.
44
+ - **Capped at 50 distinct files** so a `cl_related` result returning 100
45
+ importers doesn't inflate the total (the agent wouldn't read all 100
46
+ without the tool).
47
+
48
+ **Counterfactual being modeled:** without the index, the agent would `grep` +
49
+ `read` the relevant files (whole-file reads at their real sizes); with the tool
50
+ it got compact handles. The difference is the saved context.
51
+
52
+ ### Fallback (flat proxy)
53
+
54
+ If the size lookup fails (e.g. index not ready, paths not yet indexed), CodeLens
55
+ falls back to a flat proxy:
56
+
57
+ ```
58
+ saved = max(0, handles × 4096 − bytesServed)
59
+ ```
60
+
61
+ where `4096` is a rough average file size and `handles` = number of result
62
+ entries. This is the older, less-accurate estimate, kept only as a graceful
63
+ fallback.
64
+
65
+ ## Honest limits
66
+
67
+ 1. **It's a counterfactual estimate, not a measurement.** We don't know exactly
68
+ which files the agent *would have* read without the tool — we assume the
69
+ result files, whole.
70
+ 2. **Whole-file assumption.** We credit the full file size, but a raw `read`
71
+ might be partial, or the agent might read only the relevant part — so the
72
+ estimate can overstate for large files with small relevant regions.
73
+ 3. **No grep-output cost.** It ignores the bytes `grep` itself would have dumped
74
+ into context, which would make the real saving *larger*.
75
+ 4. **No multi-round exploration.** It counts one call, not the exploration
76
+ rounds the agent avoids.
77
+ 5. The 50-file cap is a judgment call to curb broad relationship/impact results.
78
+
79
+ Net: treat `saved(est)` as an order-of-magnitude indicator of how much context
80
+ the index tools are sparing, not an audited figure.
81
+
82
+ ## Storage
83
+
84
+ Usage is **global** (`~/.codelens/usage.db`), aggregated across all repos, with
85
+ a `(tool, repo_id)` key so `cl_usage` can break it down per repo. It survives
86
+ restarts and core-index rebuilds (it's separate from the per-branch index DBs).
87
+
88
+ Reset with `cl_usage` is not exposed as a tool; from code, `UsageTracker.reset()`
89
+ clears it.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fodx/codelens",
3
- "version": "2.0.1",
3
+ "version": "2.1.1",
4
4
  "description": "Local, branch-aware code search & relation graph. SQLite FTS5 + tree-sitter symbols + source-graph edges, exposed as an MCP server and CLI. No chat LLM required.",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -39,8 +39,10 @@
39
39
  "adapters/pi",
40
40
  "README.md",
41
41
  "docs/agent-guide.md",
42
+ "docs/how-it-works.md",
42
43
  "docs/routing.md",
43
44
  "docs/tools.md",
45
+ "docs/usage-metrics.md",
44
46
  "docs/codelens-preview.png"
45
47
  ],
46
48
  "pi": {
@@ -58,7 +60,8 @@
58
60
  "mcp:smoke": "node build/src/server.js --smoke",
59
61
  "start": "node build/src/server.js",
60
62
  "benchmark": "npx tsx bench/run.ts",
61
- "quality": "npx tsx bench/quality.ts"
63
+ "quality": "npx tsx bench/quality.ts",
64
+ "eval:agent": "npx tsx bench/agent-eval.ts"
62
65
  },
63
66
  "dependencies": {
64
67
  "@modelcontextprotocol/sdk": "^1.26.0",