token-goat 2.9.6 → 2.9.8
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 +5 -2
- package/dist/{token-goat-chunk-J7LGMKF3.mjs → token-goat-chunk-2SBHUPBF.mjs} +44 -9
- package/dist/{token-goat-chunk-3ZAMYHQG.mjs → token-goat-chunk-3YANZKER.mjs} +5 -5
- package/dist/{token-goat-chunk-46VKOCUH.mjs → token-goat-chunk-6RAUVAKW.mjs} +2 -2
- package/dist/{token-goat-chunk-C7LLUVUT.mjs → token-goat-chunk-EZZ7IJYM.mjs} +3 -3
- package/dist/{token-goat-chunk-T2OE7MYM.mjs → token-goat-chunk-JZYJH76S.mjs} +2712 -2697
- package/dist/{token-goat-chunk-TX64YIIV.mjs → token-goat-chunk-Q4VCAIBR.mjs} +5 -5
- package/dist/{token-goat-chunk-LXIC7MTW.mjs → token-goat-chunk-REHUP2OE.mjs} +1 -1
- package/dist/{token-goat-chunk-3HJQR4OO.mjs → token-goat-chunk-TXZY7C24.mjs} +105 -19
- package/dist/{token-goat-chunk-7GJBID7S.mjs → token-goat-chunk-VEEHPNBV.mjs} +5 -3
- package/dist/{token-goat-chunk-UJORWTI4.mjs → token-goat-chunk-WT5OLTT6.mjs} +2 -2
- package/dist/{token-goat-chunk-EIZYCVBM.mjs → token-goat-chunk-XYLPMQ6I.mjs} +332 -82
- package/dist/token-goat-hook.mjs +5 -5
- package/dist/token-goat.core.mjs +5 -5
- package/docs/install.md +62 -0
- package/docs/security.md +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -129,7 +129,7 @@ The fastest way to reduce AI token costs is fixing these five, not writing short
|
|
|
129
129
|
| `claude-in-chrome`'s `computer`/`browser_batch` return a raw, full-resolution base64 screenshot in-band, with no destination-file option to redirect through image-shrink | Inline screenshot blocks are shrunk via the same image-shrink pipeline in place, and a repeated `Tab Context:` listing (appended to nearly every call, often unchanged) collapses to a placeholder once seen unchanged this session |
|
|
130
130
|
| Agent tool spawns a subagent with no orientation and no reuse hints | A `PreToolUse` handler appends a compact briefing pack to the prompt: a one-line project-map summary, 2-3 recent cached-output IDs, and a surgical-read reminder (~300 tokens) |
|
|
131
131
|
| Subagent's own final report runs long and gets discarded once the parent moves on | Agent tool results ≥8000 characters get a recall pointer appended (`token-goat recall`); the original report always reaches the parent untouched |
|
|
132
|
-
| Agent tool spawns with no `subagent_type` (or an explicit `general-purpose`), so the lane starts by paying for every tool and MCP schema on the machine | Once per session, a `PostToolUse` advisory names up to three `tools:`-restricted agent definitions found in `~/.claude/agents` and suggests passing one as `subagent_type` on a future spawn that fits. It fires only when at least one restricted definition exists, states outright that the observed spawn already ran and nothing was saved, and records a zero-credit stat |
|
|
132
|
+
| Agent tool spawns with no `subagent_type` (or an explicit `general-purpose`), so the lane starts by paying for every tool and MCP schema on the machine | Once per session, a `PostToolUse` advisory names up to three `tools:`-restricted agent definitions found in `~/.claude/agents` or the current project's `.claude/agents` and suggests passing one as `subagent_type` on a future spawn that fits. It fires only when at least one restricted definition exists, states outright that the observed spawn already ran and nothing was saved, and records a zero-credit stat |
|
|
133
133
|
| Large MCP tool result (≥2 KB) is a homogeneous array of objects, e.g. a list/search result | Deterministic structural compression: table-ified into one header row + tab-delimited rows, with columns constant across every row hoisted into a single `constant:` line instead of repeated per row; only applied when it saves ≥15%. Full original always recoverable via `token-goat bash-output <id>` (labeled `[token-goat: compressed, full via mcp-output <id>]`). Disable with `TOKEN_GOAT_MCP_COMPRESS=0` |
|
|
134
134
|
| Large MCP tool result (≥2 KB) doesn't table-ify (an object-rooted config dump, a single-resource response, a nested settings tree) but most of its bytes are `null`/`""`/`[]`/`{}` | Deterministic empty-value pruning: recursively drops those four empty shapes to a fixed point (a container left empty by its own dropped children is dropped too) and renders the remainder as compact JSON with a trailing `dropped N empty value(s) (null, "", [], {})` summary line; `0` and `false` are never dropped; only applied when it saves ≥15%. Same full-recovery-by-id guarantee and `TOKEN_GOAT_MCP_COMPRESS=0` opt-out as the table pass |
|
|
135
135
|
| GitHub MCP tool result (`list_pull_requests`, `list_issues`, `search_code`, `get_file_contents`, `pull_request_read`, …) carries dozens of boilerplate fields per object | GitHub compression pack strips `_links`, `node_id`, `gravatar_id`, `site_admin`, and every `*_url` field (`avatar_url`, `html_url`, `events_url`, `gists_url`, `followers_url`, …) except `download_url`/`git_url`/`clone_url`/`ssh_url`, before handing the shrunk JSON to the same table-ifying pass — same `TOKEN_GOAT_MCP_COMPRESS=0` opt-out and full-recovery-by-id guarantee |
|
|
@@ -169,6 +169,9 @@ The fastest way to reduce AI token costs is fixing these five, not writing short
|
|
|
169
169
|
| Fetched web content lands raw in model context | Always wrapped in an untrusted-content fence; scanned for attack patterns, and a matched pattern name is written to the log and into the fence's notice |
|
|
170
170
|
| Chatty log repeats the same error or event thousands of times | `token-goat logfold` collapses consecutive duplicates to `[Nx]` counts; same event logged with different timestamps or request IDs folds correctly — ~90–95% smaller on repetitive logs |
|
|
171
171
|
| Reading poetry.lock or package-lock.json to find a pinned version | `token-goat lockdeps` returns a name/version table of direct dependencies; optional packages and transitive entries excluded |
|
|
172
|
+
| Large SVG / diagram file (≥8 KB) read in full | Coordinate path flooding blocked; extracted layer/group IDs and title shown; redirects to `token-goat xml-outline` and `xml-query` |
|
|
173
|
+
| Broad recursive Glob sweep (`*`, `**/*`) on root directory | Pre-Glob hook warns against tree-dumping and points at `token-goat map --compact` for fast, lightweight structure inspection |
|
|
174
|
+
| Compound test/build pipeline (`npm run build && npm run typecheck && npm test`) | Post-Bash hook routes chained build/test/lint commands to `generic-ci` compression, dropping verbose passing steps and compiler noise |
|
|
172
175
|
|
|
173
176
|
On a per-token API plan, 100K wasted tokens per session runs about $0.30. Five sessions a week is ~$450/year. AI coding cost reduction at that scale comes from fixing the waste, not from using the product less. Token-goat is free. And on subscription plans, it can result in limits feeling 10x higher.
|
|
174
177
|
|
|
@@ -422,7 +425,7 @@ never drift on where `mcp.json` lives or what key name it looks for.
|
|
|
422
425
|
|
|
423
426
|
**What the index actually holds, in plain terms.** The point of a surgical read is returning a function body without the file around it, which means the database stores those bodies. `symbols.body` holds the source text of every indexed symbol, `symbols.docstring` its doc comment, `refs.context` the line around each reference, and `chunks.text` the passages that semantic search embeds. There is also a full-text index over the bodies and docstrings. So the database is not a list of names and line numbers: it is a substantial copy of your source, sitting in a plain unencrypted SQLite file outside the repository.
|
|
424
427
|
|
|
425
|
-
The file-by-file table for each harness, and the path that file sits at: **[What gets installed](docs/install.md#what-gets-installed)
|
|
428
|
+
The file-by-file table for each harness, and the path that file sits at: **[What gets installed](docs/install.md#what-gets-installed)** (see also **[Permissions & auto-approval](docs/install.md#command-auto-approval-and-permissions)**).
|
|
426
429
|
|
|
427
430
|
## Zero maintenance
|
|
428
431
|
|
|
@@ -86,7 +86,7 @@ import {
|
|
|
86
86
|
runZipRead,
|
|
87
87
|
symbolNamesInFile,
|
|
88
88
|
upsertNote
|
|
89
|
-
} from "./token-goat-chunk-
|
|
89
|
+
} from "./token-goat-chunk-6RAUVAKW.mjs";
|
|
90
90
|
import {
|
|
91
91
|
DEFAULT_RECONCILE_BUDGET_MS,
|
|
92
92
|
GEMINI_TOOL_NAME_MAP,
|
|
@@ -108,7 +108,7 @@ import {
|
|
|
108
108
|
runReconcile,
|
|
109
109
|
storeWebOutput,
|
|
110
110
|
summarizeResidentContext
|
|
111
|
-
} from "./token-goat-chunk-
|
|
111
|
+
} from "./token-goat-chunk-VEEHPNBV.mjs";
|
|
112
112
|
import {
|
|
113
113
|
AGENT_SALT_MARKER,
|
|
114
114
|
BASH_OUTPUT_SUBDIR,
|
|
@@ -190,6 +190,7 @@ import {
|
|
|
190
190
|
isParseSkipEligible,
|
|
191
191
|
isRecallCacheType,
|
|
192
192
|
isSuppressionCategory,
|
|
193
|
+
isTreeSitterAvailable,
|
|
193
194
|
isWorkerRunning,
|
|
194
195
|
listBlobs,
|
|
195
196
|
listOutputs,
|
|
@@ -230,12 +231,14 @@ import {
|
|
|
230
231
|
storeCompact,
|
|
231
232
|
storeOutput,
|
|
232
233
|
tokenGoatHome,
|
|
234
|
+
treeSitterCoreAvailable,
|
|
235
|
+
treeSitterCoreLoadError,
|
|
233
236
|
trimToBudget,
|
|
234
237
|
urlPolicyDenialReason,
|
|
235
238
|
visionTokensSavedByText,
|
|
236
239
|
walkProject,
|
|
237
240
|
writeCompact
|
|
238
|
-
} from "./token-goat-chunk-
|
|
241
|
+
} from "./token-goat-chunk-TXZY7C24.mjs";
|
|
239
242
|
import {
|
|
240
243
|
C,
|
|
241
244
|
CONFIG_KEY_ENV_OVERRIDES,
|
|
@@ -346,6 +349,7 @@ import {
|
|
|
346
349
|
savedTokensFromBytes,
|
|
347
350
|
sleepSync,
|
|
348
351
|
stripAnsi,
|
|
352
|
+
stripLower,
|
|
349
353
|
stripOwnHooksFromMap,
|
|
350
354
|
stripStaleGroupHooks,
|
|
351
355
|
suggestPackageNames,
|
|
@@ -368,7 +372,7 @@ import {
|
|
|
368
372
|
withFileLock,
|
|
369
373
|
withRetryOnLock,
|
|
370
374
|
writeJsonSettings
|
|
371
|
-
} from "./token-goat-chunk-
|
|
375
|
+
} from "./token-goat-chunk-JZYJH76S.mjs";
|
|
372
376
|
import {
|
|
373
377
|
__export,
|
|
374
378
|
init_define_import_meta_env
|
|
@@ -6313,6 +6317,29 @@ function checkTsCompiler() {
|
|
|
6313
6317
|
message: err2 !== null ? `unavailable: ${extractErrorMessage(err2)}` : "unavailable (not attempted)"
|
|
6314
6318
|
};
|
|
6315
6319
|
}
|
|
6320
|
+
var TREE_SITTER_LANGUAGES = ["typescript", "javascript", "python", "go", "rust", "ruby", "java", "c", "cpp"];
|
|
6321
|
+
function checkTreeSitter() {
|
|
6322
|
+
const name = "Tree-sitter";
|
|
6323
|
+
if (!treeSitterCoreAvailable()) {
|
|
6324
|
+
const err2 = treeSitterCoreLoadError();
|
|
6325
|
+
const cause = err2 !== null ? `: ${extractErrorMessage(err2)}` : " (not attempted)";
|
|
6326
|
+
return {
|
|
6327
|
+
name,
|
|
6328
|
+
status: "warn",
|
|
6329
|
+
message: "unavailable -- the source skeleton fold, the code body fold's disk-parse fallback, and tree-sitter indexing are all disabled; likely cause: the optional native dependency `tree-sitter` is not installed, or is not resolvable from the bundle's location" + cause
|
|
6330
|
+
};
|
|
6331
|
+
}
|
|
6332
|
+
const available = TREE_SITTER_LANGUAGES.filter((lang) => isTreeSitterAvailable(lang));
|
|
6333
|
+
if (available.length === TREE_SITTER_LANGUAGES.length) {
|
|
6334
|
+
return { name, status: "ok", message: `available (${available.length}/${TREE_SITTER_LANGUAGES.length} grammars)` };
|
|
6335
|
+
}
|
|
6336
|
+
const missing = TREE_SITTER_LANGUAGES.filter((lang) => !available.includes(lang));
|
|
6337
|
+
return {
|
|
6338
|
+
name,
|
|
6339
|
+
status: "warn",
|
|
6340
|
+
message: `partially available (${available.length}/${TREE_SITTER_LANGUAGES.length} grammars); missing: ${missing.join(", ")}`
|
|
6341
|
+
};
|
|
6342
|
+
}
|
|
6316
6343
|
function checkEmbeddings(config) {
|
|
6317
6344
|
const name = "Embeddings";
|
|
6318
6345
|
if ((config.indexing?.embeddings_enabled ?? true) === false) {
|
|
@@ -6688,6 +6715,7 @@ function runDoctor(dataDir2, configPath2, rootDir, processes) {
|
|
|
6688
6715
|
const actualDataDir = dataDir2 || dataDir();
|
|
6689
6716
|
results.push(checkInstall());
|
|
6690
6717
|
results.push(checkTsCompiler());
|
|
6718
|
+
results.push(checkTreeSitter());
|
|
6691
6719
|
results.push(checkStrayClaudeMdBlocks());
|
|
6692
6720
|
results.push(checkWorkerRunning(actualDataDir) ? { name: "Worker", status: "ok", message: "running" } : { name: "Worker", status: "warn", message: "not running" });
|
|
6693
6721
|
results.push(checkDbExists(actualDataDir));
|
|
@@ -14937,11 +14965,14 @@ function readClaudeJsonConfig(claudeJsonPath, projectRoot) {
|
|
|
14937
14965
|
function discoverMcpConfig(projectRoot, home) {
|
|
14938
14966
|
const mcpJsonPath = path28.join(projectRoot, ".mcp.json");
|
|
14939
14967
|
const claudeJsonPath = path28.join(home, ".claude.json");
|
|
14940
|
-
const
|
|
14968
|
+
const copilotJsonPath = path28.join(home, ".copilot", "mcp-config.json");
|
|
14969
|
+
const sourcesChecked = [mcpJsonPath, claudeJsonPath, copilotJsonPath];
|
|
14941
14970
|
const fromMcpJson = readMcpJsonFile(mcpJsonPath);
|
|
14942
14971
|
if (fromMcpJson !== null) return { servers: fromMcpJson, sourcePath: mcpJsonPath, sourcesChecked };
|
|
14943
14972
|
const fromClaudeJson = readClaudeJsonConfig(claudeJsonPath, projectRoot);
|
|
14944
14973
|
if (fromClaudeJson !== null) return { servers: fromClaudeJson, sourcePath: claudeJsonPath, sourcesChecked };
|
|
14974
|
+
const fromCopilotJson = readMcpJsonFile(copilotJsonPath);
|
|
14975
|
+
if (fromCopilotJson !== null) return { servers: fromCopilotJson, sourcePath: copilotJsonPath, sourcesChecked };
|
|
14945
14976
|
return { servers: null, sourcePath: null, sourcesChecked };
|
|
14946
14977
|
}
|
|
14947
14978
|
function analyzeMcpCache() {
|
|
@@ -15730,7 +15761,7 @@ async function cmdMcpServe() {
|
|
|
15730
15761
|
let StdioServerTransport;
|
|
15731
15762
|
try {
|
|
15732
15763
|
;
|
|
15733
|
-
({ createMcpServer } = await import("./token-goat-chunk-
|
|
15764
|
+
({ createMcpServer } = await import("./token-goat-chunk-EZZ7IJYM.mjs"));
|
|
15734
15765
|
({ StdioServerTransport } = await import("./token-goat-chunk-EVC4TOLE.mjs"));
|
|
15735
15766
|
} catch (err2) {
|
|
15736
15767
|
process.stderr.write(
|
|
@@ -15755,7 +15786,7 @@ async function cmdHook(event, opts) {
|
|
|
15755
15786
|
if (typeof opts.harness === "string" && opts.harness.length > 0) {
|
|
15756
15787
|
process.env[ENV_KEYS.HARNESS_OVERRIDE] = opts.harness;
|
|
15757
15788
|
}
|
|
15758
|
-
const { relay } = await import("./token-goat-chunk-
|
|
15789
|
+
const { relay } = await import("./token-goat-chunk-Q4VCAIBR.mjs");
|
|
15759
15790
|
await relay(event);
|
|
15760
15791
|
}
|
|
15761
15792
|
async function cmdInstall(opts) {
|
|
@@ -16688,7 +16719,7 @@ function emitExtraFileArgsNote(command, first, extras, opts = {}) {
|
|
|
16688
16719
|
}
|
|
16689
16720
|
async function cmdCompress(opts) {
|
|
16690
16721
|
try {
|
|
16691
|
-
const bashRunner = await import("./token-goat-chunk-
|
|
16722
|
+
const bashRunner = await import("./token-goat-chunk-WT5OLTT6.mjs");
|
|
16692
16723
|
if (opts.compress === false) {
|
|
16693
16724
|
process.exitCode = bashRunner.runRaw(opts.cmd, parseTimeout(opts.timeout, bashRunner.DEFAULT_TIMEOUT_SECONDS));
|
|
16694
16725
|
return;
|
|
@@ -16961,8 +16992,12 @@ async function cmdSkillSection(nameHeading, headingArg) {
|
|
|
16961
16992
|
const body = decodeSource(fs29.readFileSync(filePath));
|
|
16962
16993
|
const extracted = extractNamedSection(body, heading);
|
|
16963
16994
|
if (!extracted) {
|
|
16964
|
-
const messages = [`Section '${heading}' not found in skill '${skillName}'`];
|
|
16965
16995
|
const allHeadings = listSections(filePath);
|
|
16996
|
+
const wanted = stripLower(heading);
|
|
16997
|
+
if (allHeadings.some((h) => stripLower(h) === wanted)) {
|
|
16998
|
+
throw new CliError(`Section '${heading}' in skill '${skillName}' is present but empty`);
|
|
16999
|
+
}
|
|
17000
|
+
const messages = [`Section '${heading}' not found in skill '${skillName}'`];
|
|
16966
17001
|
const available = filterSimilarHeadings(allHeadings, heading);
|
|
16967
17002
|
if (available.length > 0) messages.push(didYouMean(available));
|
|
16968
17003
|
else if (allHeadings.length === 0) messages.push(`skill '${skillName}' has no headings`);
|
|
@@ -7,11 +7,11 @@ import {
|
|
|
7
7
|
expandGlobs,
|
|
8
8
|
leftoverIntegrations,
|
|
9
9
|
run
|
|
10
|
-
} from "./token-goat-chunk-
|
|
11
|
-
import "./token-goat-chunk-
|
|
12
|
-
import "./token-goat-chunk-
|
|
13
|
-
import "./token-goat-chunk-
|
|
14
|
-
import "./token-goat-chunk-
|
|
10
|
+
} from "./token-goat-chunk-2SBHUPBF.mjs";
|
|
11
|
+
import "./token-goat-chunk-6RAUVAKW.mjs";
|
|
12
|
+
import "./token-goat-chunk-VEEHPNBV.mjs";
|
|
13
|
+
import "./token-goat-chunk-TXZY7C24.mjs";
|
|
14
|
+
import "./token-goat-chunk-JZYJH76S.mjs";
|
|
15
15
|
import "./token-goat-chunk-EEIDFMEM.mjs";
|
|
16
16
|
import "./token-goat-chunk-A37V4PBF.mjs";
|
|
17
17
|
export {
|
|
@@ -67,7 +67,7 @@ import {
|
|
|
67
67
|
walkProject,
|
|
68
68
|
yamlLineClosesQuote,
|
|
69
69
|
yamlOpenQuoteAfter
|
|
70
|
-
} from "./token-goat-chunk-
|
|
70
|
+
} from "./token-goat-chunk-TXZY7C24.mjs";
|
|
71
71
|
import {
|
|
72
72
|
Database,
|
|
73
73
|
PER_FILE_COUNTERFACTUAL_CEILING,
|
|
@@ -125,7 +125,7 @@ import {
|
|
|
125
125
|
unsupportedLanguageName,
|
|
126
126
|
windowsCmdQuoteArg,
|
|
127
127
|
withExtension
|
|
128
|
-
} from "./token-goat-chunk-
|
|
128
|
+
} from "./token-goat-chunk-JZYJH76S.mjs";
|
|
129
129
|
import {
|
|
130
130
|
registerReset
|
|
131
131
|
} from "./token-goat-chunk-EEIDFMEM.mjs";
|
|
@@ -25,7 +25,7 @@ import {
|
|
|
25
25
|
runSkeleton,
|
|
26
26
|
runSymbol,
|
|
27
27
|
withPinnedReads
|
|
28
|
-
} from "./token-goat-chunk-
|
|
28
|
+
} from "./token-goat-chunk-6RAUVAKW.mjs";
|
|
29
29
|
import {
|
|
30
30
|
buildProjectMap,
|
|
31
31
|
embeddingsDepsAvailable,
|
|
@@ -34,7 +34,7 @@ import {
|
|
|
34
34
|
getProjectIndexCounts,
|
|
35
35
|
isWorkerRunning,
|
|
36
36
|
mapLookupBytesSaved
|
|
37
|
-
} from "./token-goat-chunk-
|
|
37
|
+
} from "./token-goat-chunk-TXZY7C24.mjs";
|
|
38
38
|
import {
|
|
39
39
|
ENV_KEYS,
|
|
40
40
|
VERSION,
|
|
@@ -48,7 +48,7 @@ import {
|
|
|
48
48
|
recordStat,
|
|
49
49
|
resolveProjectRoot,
|
|
50
50
|
savedTokensFromBytes
|
|
51
|
-
} from "./token-goat-chunk-
|
|
51
|
+
} from "./token-goat-chunk-JZYJH76S.mjs";
|
|
52
52
|
import "./token-goat-chunk-EEIDFMEM.mjs";
|
|
53
53
|
import {
|
|
54
54
|
init_define_import_meta_env
|