@levnikolaevich/hex-line-mcp 1.5.0 → 1.6.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/README.md +38 -30
- package/dist/hook.mjs +15 -2
- package/dist/server.mjs +769 -416
- package/output-style.md +2 -0
- package/package.json +4 -4
package/README.md
CHANGED
|
@@ -36,7 +36,7 @@ Advanced / occasional:
|
|
|
36
36
|
| `edit_file` | Revision-aware anchor edits (`set_line`, `replace_lines`, `insert_after`, `replace_between`) | Batched same-file edits + conservative auto-rebase |
|
|
37
37
|
| `write_file` | Create new file or overwrite, auto-creates parent dirs | Path validation, no hash overhead |
|
|
38
38
|
| `grep_search` | Search with ripgrep, 3 output modes, per-group checksums | Plain `files`/`count`, compact edit-ready `content` |
|
|
39
|
-
| `outline` | AST-based structural overview via tree-sitter WASM | 95% token reduction
|
|
39
|
+
| `outline` | AST-based structural overview with hash anchors via tree-sitter WASM. Supports code (15+ langs) and fence-aware markdown headings | 95% token reduction, direct edit anchors |
|
|
40
40
|
| `verify` | Check if held checksums / revision are still current | Staleness check without full re-read |
|
|
41
41
|
| `directory_tree` | Compact directory tree with root .gitignore support | Skips node_modules/.git, shows file sizes |
|
|
42
42
|
| `get_file_info` | File metadata without reading content | Size, lines, mtime, type, binary detection |
|
|
@@ -88,29 +88,24 @@ mcp__hex-line__setup_hooks(agent="claude")
|
|
|
88
88
|
|
|
89
89
|
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.
|
|
90
90
|
|
|
91
|
-
##
|
|
91
|
+
## Validation
|
|
92
92
|
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
- `/benchmark-compare` — balanced built-in vs hex-line comparison inside Claude Code, validated by scenario manifests and saved diffs
|
|
96
|
-
- `npm run benchmark` — hex-line standalone workflow metrics (Node.js, all real library calls, no simulations)
|
|
93
|
+
Use the normal package checks:
|
|
97
94
|
|
|
98
95
|
```bash
|
|
99
|
-
npm
|
|
100
|
-
npm run
|
|
96
|
+
npm test
|
|
97
|
+
npm run lint
|
|
98
|
+
npm run check
|
|
101
99
|
```
|
|
102
100
|
|
|
103
|
-
|
|
101
|
+
Maintainers can also run the internal scenario harness when they want reproducible repo-local workflow regressions:
|
|
104
102
|
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
| W3 | Repo-wide benchmark wording refresh | 213 chars | 1 |
|
|
110
|
-
| W4 | Inspect large smoke test before edit | 2,322 chars | 3 |
|
|
111
|
-
| W5 | Follow-up edit after unrelated line shift | 1,267 chars | 3 |
|
|
103
|
+
```bash
|
|
104
|
+
npm run scenarios -- --repo /path/to/repo
|
|
105
|
+
npm run scenarios:diagnostic -- --repo /path/to/repo
|
|
106
|
+
```
|
|
112
107
|
|
|
113
|
-
|
|
108
|
+
Comparative built-in vs hex-line benchmarks are maintained outside this package.
|
|
114
109
|
|
|
115
110
|
### Optional Graph Enrichment
|
|
116
111
|
|
|
@@ -152,7 +147,7 @@ Use `bulk_replace` for text rename patterns across one or more files. Returns co
|
|
|
152
147
|
|
|
153
148
|
### read_file
|
|
154
149
|
|
|
155
|
-
Read a file
|
|
150
|
+
Read a file as canonical edit-ready blocks. Each valid range becomes a `read_range` block with absolute span, line entries, and a checksum covering exactly the emitted lines. Invalid ranges become explicit diagnostic blocks. Supports batch reads, multi-range reads, and directory listing.
|
|
156
151
|
|
|
157
152
|
| Parameter | Type | Required | Description |
|
|
158
153
|
|-----------|------|----------|-------------|
|
|
@@ -164,18 +159,20 @@ Read a file with FNV-1a hash-annotated lines, range checksums, file checksum, an
|
|
|
164
159
|
| `include_graph` | boolean | no | Opt in to graph annotations when the graph index exists |
|
|
165
160
|
| `plain` | boolean | no | Omit hashes, output `lineNum\|content` instead |
|
|
166
161
|
|
|
167
|
-
Default output is compact:
|
|
162
|
+
Default output is compact but block-structured:
|
|
168
163
|
|
|
169
164
|
```
|
|
170
165
|
File: lib/search.mjs
|
|
171
|
-
meta: lines
|
|
166
|
+
meta: 282 lines, 10.2KB, 2 hours ago
|
|
172
167
|
revision: rev-12-a1b2c3d4
|
|
173
168
|
file: 1-282:beefcafe
|
|
174
169
|
|
|
170
|
+
block: read_range
|
|
171
|
+
span: 1-3
|
|
175
172
|
ab.1 import { resolve } from "node:path";
|
|
176
173
|
cd.2 import { readFileSync } from "node:fs";
|
|
177
|
-
...
|
|
178
|
-
checksum: 1-
|
|
174
|
+
ef.3 ...
|
|
175
|
+
checksum: 1-3:f7e2a1b0
|
|
179
176
|
```
|
|
180
177
|
|
|
181
178
|
### edit_file
|
|
@@ -222,7 +219,7 @@ Create a new file or overwrite an existing one. Creates parent directories autom
|
|
|
222
219
|
|
|
223
220
|
### grep_search
|
|
224
221
|
|
|
225
|
-
Search file contents using ripgrep. Three output modes: `content` (
|
|
222
|
+
Search file contents using ripgrep. Three output modes: `content` (canonical `search_hunk` blocks), `files` (plain path list), `count` (plain `file:count` list).
|
|
226
223
|
|
|
227
224
|
| Parameter | Type | Required | Description |
|
|
228
225
|
|-----------|------|----------|-------------|
|
|
@@ -240,13 +237,13 @@ Search file contents using ripgrep. Three output modes: `content` (hash-annotate
|
|
|
240
237
|
| `context_after` | number | no | Context lines AFTER match (`-A`) |
|
|
241
238
|
| `limit` | number | no | Max matches per file (default: 100) |
|
|
242
239
|
| `total_limit` | number | no | Total match events across all files; multiline matches count as 1 (0 = unlimited) |
|
|
243
|
-
| `plain` | boolean | no | Omit hash tags, return `
|
|
240
|
+
| `plain` | boolean | no | Omit hash tags inside block entries, return `lineNum\|content` |
|
|
244
241
|
|
|
245
|
-
`content` mode returns per-
|
|
242
|
+
`content` mode returns canonical `search_hunk` blocks with per-hunk checksums enabling direct `replace_lines` from grep results without intermediate `read_file`.
|
|
246
243
|
|
|
247
244
|
### outline
|
|
248
245
|
|
|
249
|
-
AST-based structural outline
|
|
246
|
+
AST-based structural outline with hash anchors for direct `edit_file` usage. Supports code files (15+ languages) and fence-aware markdown heading navigation (`.md`/`.mdx`). Each entry includes a hash tag for immediate anchor use without intermediate `read_file`.
|
|
250
247
|
|
|
251
248
|
| Parameter | Type | Required | Description |
|
|
252
249
|
|-----------|------|----------|-------------|
|
|
@@ -254,11 +251,11 @@ AST-based structural outline: functions, classes, interfaces with line ranges.
|
|
|
254
251
|
|
|
255
252
|
Supported languages: JavaScript, TypeScript (JSX/TSX), Python, Go, Rust, Java, C, C++, C#, Ruby, PHP, Kotlin, Swift, Bash -- 15+ via tree-sitter WASM.
|
|
256
253
|
|
|
257
|
-
Not for `.
|
|
254
|
+
Not for `.json`, `.yaml`, `.txt` -- use `read_file` directly for those.
|
|
258
255
|
|
|
259
256
|
### verify
|
|
260
257
|
|
|
261
|
-
Check if range checksums from
|
|
258
|
+
Check if range checksums from prior read/search blocks are still valid, optionally relative to a prior `base_revision`. Returns a deterministic verification report with `status`, `summary`, and one line per checksum entry.
|
|
262
259
|
|
|
263
260
|
| Parameter | Type | Required | Description |
|
|
264
261
|
|-----------|------|----------|-------------|
|
|
@@ -266,7 +263,18 @@ Check if range checksums from a prior read are still valid, optionally relative
|
|
|
266
263
|
| `checksums` | string[] | yes | Array of checksum strings, e.g. `["1-50:f7e2a1b0"]` |
|
|
267
264
|
| `base_revision` | string | no | Prior revision to compare against latest state |
|
|
268
265
|
|
|
269
|
-
|
|
266
|
+
Example output:
|
|
267
|
+
|
|
268
|
+
```text
|
|
269
|
+
status: STALE
|
|
270
|
+
revision: rev-17-deadbeef
|
|
271
|
+
file: 1-120:abc123ef
|
|
272
|
+
summary: valid=0 stale=1 invalid=0
|
|
273
|
+
base_revision: rev-16-feedcafe
|
|
274
|
+
changed_ranges: 10-12(replace)
|
|
275
|
+
|
|
276
|
+
STALE 10-12 checksum: 10-12:oldc0de0 current=10-12:newc0de0
|
|
277
|
+
```
|
|
270
278
|
|
|
271
279
|
### directory_tree
|
|
272
280
|
|
|
@@ -398,7 +406,7 @@ The edit is rejected with an error showing which lines changed since the last re
|
|
|
398
406
|
<details>
|
|
399
407
|
<summary><b>Is outline available for all file types?</b></summary>
|
|
400
408
|
|
|
401
|
-
Outline works on code files
|
|
409
|
+
Outline works on code files (15+ languages via tree-sitter WASM) and markdown heading navigation (`.md`/`.mdx`, fenced code blocks ignored). For JSON, YAML, and text files use `read_file` directly. Each outline entry includes a hash anchor (`tag.line-range: symbol`) for direct use in `edit_file`.
|
|
402
410
|
|
|
403
411
|
</details>
|
|
404
412
|
|
package/dist/hook.mjs
CHANGED
|
@@ -262,6 +262,16 @@ function block(reason, context) {
|
|
|
262
262
|
process.stdout.write(JSON.stringify(output));
|
|
263
263
|
process.exit(2);
|
|
264
264
|
}
|
|
265
|
+
function advise(reason) {
|
|
266
|
+
process.stdout.write(JSON.stringify({
|
|
267
|
+
hookSpecificOutput: {
|
|
268
|
+
hookEventName: "PreToolUse",
|
|
269
|
+
permissionDecision: "approve",
|
|
270
|
+
permissionDecisionReason: reason
|
|
271
|
+
}
|
|
272
|
+
}));
|
|
273
|
+
process.exit(0);
|
|
274
|
+
}
|
|
265
275
|
function handlePreToolUse(data) {
|
|
266
276
|
const toolName = data.tool_name || "";
|
|
267
277
|
const toolInput = data.tool_input || {};
|
|
@@ -295,9 +305,12 @@ function handlePreToolUse(data) {
|
|
|
295
305
|
}
|
|
296
306
|
}
|
|
297
307
|
if (toolName === "Read") {
|
|
298
|
-
if (isPartialRead(toolInput)
|
|
308
|
+
if (isPartialRead(toolInput)) {
|
|
299
309
|
process.exit(0);
|
|
300
310
|
}
|
|
311
|
+
if (fileSize !== null && fileSize <= LARGE_FILE_BYTES) {
|
|
312
|
+
advise("hex-line read_file returns hash-annotated lines for verified edit workflow. For code files, outline gives a compact structural map first.");
|
|
313
|
+
}
|
|
301
314
|
const target = filePath ? `Use mcp__hex-line__outline or mcp__hex-line__read_file with path="${filePath}"` : "Use mcp__hex-line__directory_tree or mcp__hex-line__read_file";
|
|
302
315
|
block(target, "For large or unknown full reads: call outline first, then read_file with offset/limit or ranges. Do not use built-in Read here.");
|
|
303
316
|
}
|
|
@@ -424,7 +437,7 @@ function handleSessionStart() {
|
|
|
424
437
|
}
|
|
425
438
|
}
|
|
426
439
|
const prefix = styleActive ? "Hex-line MCP available. Output style active.\n" : "Hex-line MCP available.\n";
|
|
427
|
-
const msg = prefix + "Call hex-line tools directly. Do not use ToolSearch for hex-line tools.\nWorkflow:\n- Discovery: outline for
|
|
440
|
+
const msg = prefix + "Call hex-line tools directly. Do not use ToolSearch for hex-line tools.\nWorkflow:\n- Discovery: outline for code and markdown files, read_file for targeted reads, grep_search for symbol/text lookup\n- Read cheaply: prefer offset/limit or ranges; avoid full-file Read on large files\n- Edit safely: read/grep first, then one batched edit_file call per file with base_revision when available\n- Verify before reread: use verify to check checksums or revision freshness\n- Multi-file rename/refactor: use bulk_replace\n- New files: use write_file\nExceptions: images, PDFs, notebooks, .claude/settings.json, .claude/settings.local.json use built-in Read. Glob is always OK.";
|
|
428
441
|
process.stdout.write(JSON.stringify({ systemMessage: msg }));
|
|
429
442
|
process.exit(0);
|
|
430
443
|
}
|