token-goat 2.3.0 → 2.4.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
@@ -356,7 +356,7 @@ To upgrade cleanly:
356
356
  | Command | What it does |
357
357
  |---------|-------------|
358
358
  | `token-goat symbol <name>` | Jump to a symbol definition. Add `--all-projects` to search across every indexed repo. |
359
- | `token-goat read "file::symbol"` | Pull one function or class, not the whole file. Supports qualified lookups: `read "file.py::Class.method"`. |
359
+ | `token-goat read "file::symbol"` | Pull one function or class, not the whole file. Supports qualified lookups (`read "file.py::Class.method"`) and line ranges: `read "file.py@10-40"` for lines 10 to 40 inclusive, or `read "file.py@42"` for one line. Line ranges read straight from disk, so they work on any file, including paths outside an indexed project. |
360
360
  | `token-goat section "doc.md::Heading"` | Pull one Markdown section by heading. Near-miss headings auto-redirect (difflib ratio ≥ 0.75) with a `(redirected from: …)` marker. Disambiguate duplicates with `"doc.md::Heading#2"`. |
361
361
  | `token-goat skill-section "<name>::<heading>"` | Extract a named section from an installed skill without reading the full skill file. |
362
362
  | `token-goat skeleton "file"` | Show all signatures in a file without bodies — typically 70–90% fewer tokens than a full read. |
@@ -9493,7 +9493,7 @@ init_define_import_meta_env();
9493
9493
  import { createRequire } from "node:module";
9494
9494
  function resolveVersion() {
9495
9495
  if (true) {
9496
- return "2.3.0";
9496
+ return "2.4.0";
9497
9497
  }
9498
9498
  const require2 = createRequire(import.meta.url);
9499
9499
  const pkg = require2("../package.json");
@@ -31060,7 +31060,47 @@ function parseReadSpec(spec) {
31060
31060
  if (colonIdx === -1) return { file: spec };
31061
31061
  return { file: spec.slice(0, colonIdx), symbol: spec.slice(colonIdx + 2) };
31062
31062
  }
31063
+ function parseLineRange(spec) {
31064
+ const m = /^(.+)@(\d+)(?:-(\d+))?$/.exec(spec);
31065
+ if (m === null) return null;
31066
+ const start = parseInt(m[2], 10);
31067
+ const end = m[3] !== void 0 ? parseInt(m[3], 10) : start;
31068
+ return { file: m[1], start, end };
31069
+ }
31070
+ function runLineRange(range, opts) {
31071
+ const { file, start, end } = range;
31072
+ if (start < 1) {
31073
+ emitErr(`Invalid line range: start must be >= 1 (got ${start})`);
31074
+ return 1;
31075
+ }
31076
+ if (end < start) {
31077
+ emitErr(`Invalid line range: end (${end}) is before start (${start})`);
31078
+ return 1;
31079
+ }
31080
+ const text = readFileText(file);
31081
+ if (text === null) {
31082
+ emitErr(`Could not read: ${file}`);
31083
+ return 1;
31084
+ }
31085
+ const allLines = text.split(/\r?\n/);
31086
+ if (allLines.length > 1 && allLines[allLines.length - 1] === "") allLines.pop();
31087
+ if (start > allLines.length) {
31088
+ emitErr(`Line ${start} is past end of file (${allLines.length} lines): ${file}`);
31089
+ return 1;
31090
+ }
31091
+ const clampedEnd = Math.min(end, allLines.length);
31092
+ const slice = allLines.slice(start - 1, clampedEnd);
31093
+ if (opts.json === true) {
31094
+ emit(JSON.stringify({ file, start, end: clampedEnd, lines: slice }, null, 2));
31095
+ return 0;
31096
+ }
31097
+ const tok = Math.ceil(slice.join("\n").length / 4);
31098
+ emit([`# lines ${start}-${clampedEnd} of ${allLines.length} (~${tok} tok)`, slice.join("\n")].join("\n"));
31099
+ return 0;
31100
+ }
31063
31101
  function runRead(opts) {
31102
+ const range = parseLineRange(opts.spec);
31103
+ if (range !== null) return runLineRange(range, opts);
31064
31104
  const { file, symbol } = parseReadSpec(opts.spec);
31065
31105
  if (symbol === void 0 || symbol === "") {
31066
31106
  const text = readFileText(file);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "token-goat",
3
- "version": "2.3.0",
3
+ "version": "2.4.0",
4
4
  "description": "Surgical token-reduction companion for Claude Code and other AI coding agents",
5
5
  "type": "module",
6
6
  "main": "./dist/token-goat.mjs",