@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 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 (10 lines instead of 500) |
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
- ## Benchmarking
91
+ ## Validation
92
92
 
93
- Two benchmark layers:
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 run benchmark -- --repo /path/to/repo
100
- npm run benchmark:diagnostic -- --repo /path/to/repo
96
+ npm test
97
+ npm run lint
98
+ npm run check
101
99
  ```
102
100
 
103
- Current standalone workflow metrics on the `hex-line-mcp` repo (all real library calls):
101
+ Maintainers can also run the internal scenario harness when they want reproducible repo-local workflow regressions:
104
102
 
105
- | # | Workflow | Hex-line output | Ops |
106
- |---|----------|---------:|----:|
107
- | W1 | Debug hook file-listing redirect | 882 chars | 2 |
108
- | W2 | Adjust `setup_hooks` guidance and verify | 1,719 chars | 3 |
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
- Workflow total: `6,403` chars across `12` ops. Run `/benchmark-compare` for the balanced scenario suite with activation checks and diff-based correctness.
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 with FNV-1a hash-annotated lines, range checksums, file checksum, and revision. Supports batch reads, multi-range reads, and directory listing.
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 1-20 of 282
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-50:f7e2a1b0
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` (hash-annotated with checksums), `files` (plain path list), `count` (plain `file:count` list).
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 `file:line:content` |
240
+ | `plain` | boolean | no | Omit hash tags inside block entries, return `lineNum\|content` |
244
241
 
245
- `content` mode returns per-group checksums enabling direct `replace_lines` from grep results without intermediate `read_file`.
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: functions, classes, interfaces with line ranges.
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 `.md`, `.json`, `.yaml`, `.txt` -- use `read_file` directly for those.
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 a prior read are still valid, optionally relative to a prior `base_revision`.
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
- Returns a single-line confirmation or lists changed ranges.
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 only (15+ languages via tree-sitter WASM). For markdown, JSON, YAML, and text files use `read_file` directly -- these formats don't benefit from structural outline.
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) || fileSize !== null && fileSize <= LARGE_FILE_BYTES) {
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 large code 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.";
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
  }