@levnikolaevich/hex-line-mcp 1.3.0 → 1.3.2

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/README.md CHANGED
@@ -16,14 +16,14 @@ Every line carries an FNV-1a content hash. Every edit must present those hashes
16
16
  | Tool | Description | Key Feature |
17
17
  |------|-------------|-------------|
18
18
  | `read_file` | Read file with hash-annotated lines and range checksums | Partial reads via `offset`/`limit` |
19
- | `edit_file` | Hash-verified edits with anchor or text replacement | Returns compact diff via `diff` package |
19
+ | `edit_file` | Hash-verified anchor edits (set_line, replace_lines, insert_after) | Returns compact diff via `diff` package |
20
20
  | `write_file` | Create new file or overwrite, auto-creates parent dirs | Path validation, no hash overhead |
21
- | `grep_search` | Search with ripgrep, returns hash-annotated matches | Edit-ready results -- search then edit directly |
21
+ | `grep_search` | Search with ripgrep, 3 output modes, per-group checksums | Edit-ready: grep -> edit directly with checksums |
22
22
  | `outline` | AST-based structural overview via tree-sitter WASM | 95% token reduction (10 lines instead of 500) |
23
23
  | `verify` | Check if held range checksums are still valid | Single-line response avoids full re-read |
24
- | `directory_tree` | Compact directory tree with .gitignore support | Skips node_modules/.git, shows file sizes |
24
+ | `directory_tree` | Compact directory tree with root .gitignore support | Skips node_modules/.git, shows file sizes |
25
25
  | `get_file_info` | File metadata without reading content | Size, lines, mtime, type, binary detection |
26
- | `setup_hooks` | Configure PreToolUse + PostToolUse hooks for Claude/Gemini/Codex | One call sets up everything, idempotent |
26
+ | `setup_hooks` | Configure Claude hooks + install output style | Gemini/Codex get guidance only; no hooks |
27
27
  | `changes` | Compare file against git ref, shows added/removed/modified symbols | AST-level semantic diff |
28
28
  | `bulk_replace` | Search-and-replace across multiple files by glob | Per-file diffs, dry_run, max_files safety |
29
29
 
@@ -33,13 +33,13 @@ Every line carries an FNV-1a content hash. Every edit must present those hashes
33
33
  |-------|---------|--------|
34
34
  | **PreToolUse** | Read/Edit/Write/Grep on text files | Blocks built-in, forces hex-line tools |
35
35
  | **PreToolUse** | Bash with dangerous commands | Blocks `rm -rf /`, `git push --force`, etc. Agent must confirm with user |
36
- | **PostToolUse** | Bash with 50+ lines output | RTK: deduplicates, truncates, summarizes |
36
+ | **PostToolUse** | Bash with 50+ lines output | RTK: deduplicates, truncates, shows filtered summary to Claude as feedback |
37
37
  | **SessionStart** | Session begins | Injects full tool preference list into agent context |
38
38
 
39
39
 
40
40
  ### Bash Redirects
41
41
 
42
- PreToolUse also intercepts simple Bash commands: cat, head, tail, ls, tree, find, stat, wc -l, grep, rg, sed -i, diff — redirects to hex-line equivalents. Compound commands with pipes are allowed.
42
+ PreToolUse also intercepts simple Bash commands: cat, head, tail, tree, find, stat, wc -l, grep, rg, sed -i — redirects to hex-line equivalents. `ls`/`dir` only redirected for recursive listing (`ls -R`, `dir /s`); simple `ls path` is allowed. Compound commands with pipes are allowed.
43
43
  ## Install
44
44
 
45
45
  ### MCP Server
@@ -69,35 +69,55 @@ mcp__hex-line__setup_hooks(agent="claude")
69
69
 
70
70
  The `setup_hooks` tool automatically installs the output style to `~/.claude/output-styles/hex-line.md` and activates it if no other style is set. To activate manually: `/config` > Output style > hex-line.
71
71
 
72
- ## Token Efficiency
73
-
74
- Benchmark v3 (21 code files, 4,801 lines, 18 scenarios):
75
-
76
- | # | Scenario | Baseline | Hex-line | Savings | Ops | Steps |
77
- |---|----------|----------|----------|---------|-----|-------|
78
- | 1 | Read full (<50L) | 1,837 ch | 1,676 ch | 9% | 1→1 | 1→1 |
79
- | 1 | Read full (50-200L) | 4,976 ch | 4,609 ch | 7% | 1→1 | 1→1 |
80
- | 1 | Read full (200-500L) | 11,702 ch | 10,796 ch | 8% | 1→1 | 1→1 |
81
- | 1 | Read full (500L+) | 76,079 ch | 71,578 ch | 6% | 1→1 | 1→1 |
82
- | 2 | Outline+read (200-500L) | 11,702 ch | 3,620 ch | **69%** | 1→2 | 1→2 |
83
- | 2 | Outline+read (500L+) | 76,079 ch | 19,020 ch | **75%** | 1→2 | 1→2 |
84
- | 3 | Grep search | 2,816 ch | 2,926 ch | -4% | 1→1 | 1→1 |
85
- | 4 | Directory tree | 1,967 ch | 699 ch | **64%** | 1→1 | 1→1 |
86
- | 5 | File info | 371 ch | 197 ch | **47%** | 1→1 | 1→1 |
87
- | 6 | Create file (200L) | 113 ch | 85 ch | **25%** | 1→1 | 1→1 |
88
- | 7 | Edit x5 sequential | 2,581 ch | 1,529 ch | **41%** | 5→5 | 5→5 |
89
- | 8 | Verify checksums (4 ranges) | 8,295 ch | 93 ch | **99%** | 4→1 | 4→1 |
90
- | 9 | Multi-file read (2 files) | 3,674 ch | 3,358 ch | 9% | 2→1 | 1→1 |
91
- | 10 | bulk_replace dry_run (5 files) | 2,795 ch | 1,706 ch | **39%** | 5→1 | 5→1 |
92
- | 11 | Changes (semantic diff) | 830 ch | 271 ch | **67%** | 1→1 | 1→1 |
93
- | 12 | FILE_NOT_FOUND recovery | 2,071 ch | 101 ch | **95%** | 3→1 | 3→1 |
94
- | 13 | Hash mismatch recovery | 8,918 ch | 423 ch | **95%** | 3→1 | 3→1 |
95
- | 14 | Bash redirects (cat+ls+stat) | 5,602 ch | 4,695 ch | **16%** | 3→3 | 1→1 |
96
- | 15 | HASH_HINT multi-match recovery | 8,888 ch | 653 ch | **93%** | 3→2 | 3→1 |
97
-
98
- **Average savings: 45% (flat) / 52% (weighted) | 39→28 ops (28% fewer) | 36→25 steps.**
99
-
100
- Reproduce: `node benchmark.mjs` or `node benchmark.mjs --with-graph --repo /path/to/repo`
72
+ ## Benchmarking
73
+
74
+ `hex-line-mcp` now distinguishes:
75
+
76
+ - `tests` correctness and regression safety
77
+ - `benchmarks` — comparative workflow efficiency against built-in tools
78
+ - `diagnostics` modeled tool-level measurements for engineering inspection
79
+
80
+ Public benchmark mode reports only comparative multi-step workflows:
81
+
82
+ ```bash
83
+ npm run benchmark -- --repo /path/to/repo
84
+ ```
85
+
86
+ Optional diagnostics stay available separately:
87
+
88
+ ```bash
89
+ npm run benchmark:diagnostic -- --repo /path/to/repo
90
+ npm run benchmark:diagnostic:graph -- --repo /path/to/repo
91
+ ```
92
+
93
+ The diagnostics output includes synthetic tool-level comparisons such as read, grep, verify, and graph-enrichment helpers. Those numbers are useful for inspecting output shape and token behavior, but they are not the public workflow benchmark score.
94
+
95
+ Current sample run on the `hex-line-mcp` repo with session-derived workflows:
96
+
97
+ | ID | Workflow | Built-in | hex-line | Savings | Ops |
98
+ |----|----------|---------:|---------:|--------:|----:|
99
+ | W1 | Debug hook file-listing redirect | 23,143 chars | 882 chars | 96% | 3→2 |
100
+ | W2 | Adjust `setup_hooks` guidance and verify | 24,877 chars | 1,637 chars | 93% | 3→3 |
101
+ | W3 | Repo-wide benchmark wording refresh | 137,796 chars | 38,918 chars | 72% | 15→1 |
102
+ | W4 | Inspect large smoke test before edit | 49,566 chars | 2,104 chars | 96% | 3→3 |
103
+
104
+ Workflow summary: `89%` average token savings, `24→9` tool calls (`63%` fewer).
105
+
106
+ These workflows are derived from recent real Claude sessions, but executed against local reproducible fixtures in the repository. They should be read as workflow-efficiency measurements, not as correctness or semantic-quality claims.
107
+
108
+ ### Optional Graph Enrichment
109
+
110
+ If a project already has `.codegraph/index.db`, `hex-line` can add lightweight graph hints to `read_file`, `outline`, `grep_search`, and `edit_file`.
111
+
112
+ - Graph enrichment is optional. If `.codegraph/index.db` is missing, `hex-line` falls back to standard behavior silently.
113
+ - `better-sqlite3` is optional. If it is unavailable, `hex-line` still works without graph hints.
114
+ - `edit_file` reports **Call impact**, not full semantic blast radius. The warning uses call-graph callers only.
115
+
116
+ `hex-line` does not read `hex-graph` internals directly anymore. The integration uses a small read-only contract exposed by `hex-graph-mcp`:
117
+
118
+ - `hex_line_contract`
119
+ - `hex_line_symbol_annotations`
120
+ - `hex_line_call_edges`
101
121
 
102
122
  ## Tools Reference
103
123
 
@@ -124,7 +144,7 @@ checksum: 1-50:f7e2a1b0
124
144
 
125
145
  ### edit_file
126
146
 
127
- Edit using hash-verified anchors or text replacement. Returns a unified diff.
147
+ Edit using hash-verified anchors. For text rename use bulk_replace.
128
148
 
129
149
  | Parameter | Type | Required | Description |
130
150
  |-----------|------|----------|-------------|
@@ -140,7 +160,6 @@ Edit operations (JSON array):
140
160
  {"set_line": {"anchor": "ab.12", "new_text": "replacement line"}},
141
161
  {"replace_lines": {"start_anchor": "ab.10", "end_anchor": "cd.15", "new_text": "..."}},
142
162
  {"insert_after": {"anchor": "ab.20", "text": "inserted line"}},
143
- {"replace": {"old_text": "find this", "new_text": "replace with", "all": false}}
144
163
  ]
145
164
  ```
146
165
 
@@ -155,20 +174,28 @@ Create a new file or overwrite an existing one. Creates parent directories autom
155
174
 
156
175
  ### grep_search
157
176
 
158
- Search file contents using ripgrep with hash-annotated results.
177
+ Search file contents using ripgrep. Three output modes: `content` (hash-annotated with checksums), `files` (paths only), `count` (match counts).
159
178
 
160
179
  | Parameter | Type | Required | Description |
161
180
  |-----------|------|----------|-------------|
162
- | `pattern` | string | yes | Regex search pattern |
181
+ | `pattern` | string | yes | Search pattern (regex by default, literal if `literal:true`) |
163
182
  | `path` | string | no | Directory or file to search (default: cwd) |
164
183
  | `glob` | string | no | Glob filter, e.g. `"*.ts"` |
165
184
  | `type` | string | no | File type filter, e.g. `"js"`, `"py"` |
185
+ | `output` | enum | no | Output format: `"content"` (default), `"files"`, `"count"` |
166
186
  | `case_insensitive` | boolean | no | Ignore case |
167
- | `smart_case` | boolean | no | Case-insensitive when pattern is all lowercase, case-sensitive if it has uppercase (`-S`) |
168
- | `context` | number | no | Context lines around matches |
187
+ | `smart_case` | boolean | no | CI when lowercase, CS when uppercase (`-S`) |
188
+ | `literal` | boolean | no | Literal string search, no regex (`-F`) |
189
+ | `multiline` | boolean | no | Pattern can span multiple lines (`-U`) |
190
+ | `context` | number | no | Symmetric context lines around matches (`-C`) |
191
+ | `context_before` | number | no | Context lines BEFORE match (`-B`) |
192
+ | `context_after` | number | no | Context lines AFTER match (`-A`) |
169
193
  | `limit` | number | no | Max matches per file (default: 100) |
194
+ | `total_limit` | number | no | Total match events across all files; multiline matches count as 1 (0 = unlimited) |
170
195
  | `plain` | boolean | no | Omit hash tags, return `file:line:content` |
171
196
 
197
+ **Content mode** returns per-group checksums enabling direct `replace_lines` from grep results without intermediate `read_file`.
198
+
172
199
  ### outline
173
200
 
174
201
  AST-based structural outline: functions, classes, interfaces with line ranges.
@@ -194,7 +221,7 @@ Returns a single-line confirmation or lists changed ranges.
194
221
 
195
222
  ### directory_tree
196
223
 
197
- Compact directory tree with .gitignore support and file sizes.
224
+ Compact directory tree with root .gitignore support (path-based rules, negation, dir-only). Nested .gitignore files are not loaded.
198
225
 
199
226
  | Parameter | Type | Required | Description |
200
227
  |-----------|------|----------|-------------|
@@ -202,7 +229,7 @@ Compact directory tree with .gitignore support and file sizes.
202
229
  | `pattern` | string | no | Glob filter on names (e.g. `"*-mcp"`, `"*.mjs"`). Returns flat match list instead of tree |
203
230
  | `type` | string | no | `"file"`, `"dir"`, or `"all"` (default). Like `find -type f/d` |
204
231
  | `max_depth` | number | no | Max recursion depth (default: 3, or 20 in pattern mode) |
205
- | `gitignore` | boolean | no | Respect .gitignore patterns (default: true) |
232
+ | `gitignore` | boolean | no | Respect root .gitignore patterns (default: true). Nested .gitignore not supported |
206
233
  | `format` | string | no | `"compact"` = names only, no sizes, depth 1. `"full"` = default with sizes |
207
234
 
208
235
  Skips `node_modules`, `.git`, `dist`, `build`, `__pycache__`, `.next`, `coverage` by default.
@@ -219,47 +246,58 @@ Returns: size, line count, modification time (absolute + relative), file type, b
219
246
 
220
247
  ## Hook
221
248
 
222
- The unified PostToolUse hook (`hook.mjs`) handles two concerns:
249
+ The unified hook (`hook.mjs`) handles four events:
223
250
 
224
- ### Hex-line Reminder
251
+ ### PreToolUse: Tool Redirect
225
252
 
226
- Triggers on built-in `Read`, `Edit`, `Write`, `Grep` tool usage for text files. Outputs a short reminder to stderr (exit code 2) nudging the agent to use the corresponding hex-line tool instead.
253
+ Blocks built-in `Read`, `Edit`, `Write`, `Grep` on text files and redirects to hex-line equivalents. Binary files (images, PDFs, notebooks, archives, executables, fonts, media) are excluded.
227
254
 
228
- Binary files (images, PDFs, notebooks, archives, executables, fonts, media) are excluded -- those should use built-in tools.
255
+ ### PreToolUse: Bash Redirect + Dangerous Blocker
229
256
 
230
- ### RTK Output Filter
257
+ Intercepts simple Bash commands (`cat`, `head`, `tail`, `ls`, `find`, `grep`, `sed -i`, etc.) and redirects to hex-line tools. Blocks dangerous commands (`rm -rf /`, `git push --force`, `git reset --hard`, `DROP TABLE`, `chmod 777`, `mkfs`, `dd`).
258
+
259
+ ### PostToolUse: RTK Output Filter
231
260
 
232
261
  Triggers on `Bash` tool output exceeding 50 lines. Pipeline:
233
262
 
234
263
  1. **Detect command type** -- npm install, test, build, pip install, git verbose, or generic
235
- 2. **Type-specific summary** -- extracts key metrics (e.g., `npm install: 42 added, 3 warnings`)
236
- 3. **Normalize** -- replaces UUIDs, timestamps, IPs, hex values, large numbers with placeholders
237
- 4. **Deduplicate** -- collapses identical normalized lines with `(xN)` counts
238
- 5. **Truncate** -- keeps first 12 + last 12 lines, omits the middle
264
+ 2. **Normalize** -- replaces UUIDs, timestamps, IPs, hex values, large numbers with placeholders
265
+ 3. **Deduplicate** -- collapses identical normalized lines with `(xN)` counts
266
+ 4. **Truncate** -- keeps first 15 + last 15 lines, omits the middle
239
267
 
240
268
  Configuration constants in `hook.mjs`:
241
269
 
242
270
  | Constant | Default | Purpose |
243
- |----------|---------|---------|
271
+ |----------|---------|--------|
244
272
  | `LINE_THRESHOLD` | 50 | Minimum lines to trigger filtering |
245
- | `TRUNCATE_LIMIT` | 30 | Lines below this are kept as-is after dedup |
246
- | `HEAD_LINES` | 12 | Lines to keep from start |
247
- | `TAIL_LINES` | 12 | Lines to keep from end |
273
+ | `HEAD_LINES` | 15 | Lines to keep from start |
274
+ | `TAIL_LINES` | 15 | Lines to keep from end |
275
+
276
+ ### SessionStart: Tool Preferences
277
+
278
+ Injects hex-line tool preference list into agent context at session start.
248
279
 
249
280
  ## Architecture
250
281
 
251
282
  ```
252
283
  hex-line-mcp/
253
- server.mjs MCP server (stdio transport, 6 tools)
254
- hook.mjs PostToolUse hook (reminder + RTK filter)
284
+ server.mjs MCP server (stdio transport, 11 tools)
285
+ hook.mjs Unified hook (PreToolUse + PostToolUse + SessionStart)
255
286
  package.json
256
287
  lib/
257
288
  hash.mjs FNV-1a hashing, 2-char tags, range checksums
258
289
  read.mjs File reading with hash annotation
259
- edit.mjs Anchor-based and text-based edits, diff output
290
+ edit.mjs Anchor-based edits, diff output
260
291
  search.mjs ripgrep wrapper with hash-annotated results
261
292
  outline.mjs tree-sitter WASM AST outline
262
293
  verify.mjs Range checksum verification
294
+ info.mjs File metadata (size, lines, mtime, type)
295
+ tree.mjs Directory tree with .gitignore support
296
+ changes.mjs Semantic git diff via AST
297
+ bulk-replace.mjs Multi-file search-and-replace
298
+ setup.mjs Claude hook installation + output style setup
299
+ format.mjs Output formatting utilities
300
+ coerce.mjs Parameter pass-through (identity)
263
301
  security.mjs Path validation, binary detection, size limits
264
302
  normalize.mjs Output normalization, deduplication, truncation
265
303
  ```
@@ -297,7 +335,7 @@ FNV-1a accumulator over all line hashes in the range (little-endian byte feed).
297
335
  <details>
298
336
  <summary><b>Does it work without Claude Code?</b></summary>
299
337
 
300
- Yes. hex-line-mcp is a standard MCP server (stdio transport). It works with any MCP-compatible client -- Claude Code, Gemini CLI, Codex CLI, or custom integrations. Hooks are Claude/Gemini/Codex-specific.
338
+ Yes. hex-line-mcp is a standard MCP server (stdio transport). It works with any MCP-compatible client -- Claude Code, Gemini CLI, Codex CLI, or custom integrations. Hook installation is Claude-specific; Gemini/Codex use MCP Tool Preferences guidance instead.
301
339
 
302
340
  </details>
303
341
 
@@ -316,9 +354,9 @@ Outline works on code files only (15+ languages via tree-sitter WASM). For markd
316
354
  </details>
317
355
 
318
356
  <details>
319
- <summary><b>How does the RTK filter reduce tokens?</b></summary>
357
+ <summary><b>How does the RTK filter work?</b></summary>
320
358
 
321
- The PostToolUse hook normalizes Bash output (replaces UUIDs, timestamps, IPs with placeholders), deduplicates identical lines, and truncates to first 12 + last 12 lines. Average savings: 45% (flat) / 52% (weighted) across 18 benchmark scenarios.
359
+ The PostToolUse hook normalizes Bash output (replaces UUIDs, timestamps, IPs with placeholders), deduplicates identical lines, and truncates to first 15 + last 15 lines. The filtered summary is shown to Claude as stderr feedback via exit code 2.
322
360
 
323
361
  </details>
324
362