@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 +100 -62
- package/benchmark/atomic.mjs +502 -0
- package/benchmark/graph.mjs +80 -0
- package/benchmark/index.mjs +144 -0
- package/benchmark/workflows.mjs +259 -0
- package/hook.mjs +77 -41
- package/lib/bulk-replace.mjs +8 -6
- package/lib/changes.mjs +9 -7
- package/lib/coerce.mjs +2 -48
- package/lib/edit.mjs +116 -162
- package/lib/format.mjs +138 -0
- package/lib/graph-enrich.mjs +76 -58
- package/lib/info.mjs +14 -32
- package/lib/outline.mjs +2 -1
- package/lib/read.mjs +7 -25
- package/lib/search.mjs +213 -77
- package/lib/security.mjs +10 -12
- package/lib/setup.mjs +7 -24
- package/lib/tree.mjs +69 -97
- package/lib/verify.mjs +4 -3
- package/output-style.md +5 -4
- package/package.json +11 -3
- package/server.mjs +31 -18
- package/benchmark.mjs +0 -1106
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
|
|
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,
|
|
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
|
|
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,
|
|
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,
|
|
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
|
-
##
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
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
|
|
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
|
|
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 |
|
|
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 |
|
|
168
|
-
| `
|
|
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
|
|
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
|
|
249
|
+
The unified hook (`hook.mjs`) handles four events:
|
|
223
250
|
|
|
224
|
-
###
|
|
251
|
+
### PreToolUse: Tool Redirect
|
|
225
252
|
|
|
226
|
-
|
|
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
|
-
|
|
255
|
+
### PreToolUse: Bash Redirect + Dangerous Blocker
|
|
229
256
|
|
|
230
|
-
|
|
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. **
|
|
236
|
-
3. **
|
|
237
|
-
4. **
|
|
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
|
-
| `
|
|
246
|
-
| `
|
|
247
|
-
|
|
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,
|
|
254
|
-
hook.mjs
|
|
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
|
|
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.
|
|
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
|
|
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
|
|
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
|
|