{"record":{"id":"73e9c17bb3944688","repo":"JuliusBrussee/caveman","slug":"usage-invokedcommand-toon-encode-decode","errorCode":null,"errorMessage":"usage: ${invokedCommand(\"toon\")} encode|decode","messagePattern":"usage: (.+?) encode\\|decode","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/cli/src/index.ts","lineNumber":12989,"sourceCode":"    bytes_out: input.length,\n    ratio: 0,\n    basis: \"inferred\",\n    token_count_basis: \"unavailable\",\n    content_type: contentType || \"unknown\",\n    engine: \"missing\",\n    note: \"caveman-engine not installed — 0% compression, input passed through unchanged. Run `caveman setup` to see what's missing and how to install.\",\n  }));\n}\n\n// toonConvert shells out to `caveman-engine toon encode|decode` — the stateless,\n// CCR-free JSON⇄TOON converter (single source of truth in the engine, no JS\n// parser). It is the manual surface for the same transform the proxy applies at\n// the wire boundary; the converted output must not be fed back into the agent\n// that wrote the other form, or it would double the tokens it sees.\nasync function toonConvert(rest: string[]) {\n  const sub = rest[0];\n  if (sub !== \"encode\" && sub !== \"decode\") {\n    throw new Error(`usage: ${invokedCommand(\"toon\")} encode|decode`);\n  }\n  const input = await readStdin();\n  const bin = cavemanBin(\"caveman-engine\", \"CAVEMAN_ENGINE_BIN\");\n  let handled = false;\n  const child = spawn(bin, [\"toon\", sub], { stdio: [\"pipe\", \"inherit\", \"inherit\"] });\n  emitCommandRunOnce(\"ok\"); // exit handler below hard-exits; never returns to main()\n  child.on(\"error\", () => {\n    if (handled) return;\n    handled = true;\n    // encode degrades byte-safe: the input is still valid JSON, just not compacted.\n    // decode cannot be faked without the engine — emitting raw TOON as JSON would\n    // hand downstream a broken payload, so it fails loudly instead.\n    if (sub === \"encode\") {\n      // Not silent: the pass-through must announce itself so 0% can never be\n      // mistaken for \"TOON didn't help\".\n      console.error(`${mark(\"warn\")} caveman-engine not found — emitting input JSON unchanged (no TOON encoding); run \\`caveman setup\\` to see what's missing`);\n      process.stdout.write(input);\n      process.exit(0);","sourceCodeStart":12971,"sourceCodeEnd":13007,"githubUrl":"https://github.com/JuliusBrussee/caveman/blob/5184b3d11ac6a1acb7d44b9bfaa31698157cff97/packages/cli/src/index.ts#L12971-L13007","documentation":"Subcommand validation for `caveman toon`: the command requires exactly `encode` or `decode` as its first argument. Anything else — a typo, a missing subcommand, or an option in that position — throws this usage error before stdin is read. The same function then shells out to the stateless `caveman-engine toon` converter.","triggerScenarios":"`caveman toon` with no subcommand; `caveman toon enc` or `caveman toon json` (aliases that do not exist); piping a file but forgetting the direction, e.g. `cat x.toon | caveman toon`.","commonSituations":"Scripts written from memory instead of docs; assuming symmetric flags like `--encode` exist; CI steps migrated from an older command layout.","solutions":["Use `caveman toon encode < payload.json` to compact JSON into TOON","Use `caveman toon decode < payload.toon` for the reverse direction","Remember the converted output must not be fed back to the agent that produced the other form (it would double the tokens it sees)"],"exampleFix":"# before\ncat wire.toon | caveman toon\n# after\ncat wire.toon | caveman toon decode","handlingStrategy":"validation","validationCode":"const sub = rest[0];\nif (sub !== 'encode' && sub !== 'decode') {\n  console.error('usage: caveman toon encode|decode');\n  process.exit(2);\n}","typeGuard":"const isToonSubcommand = (v: unknown): v is 'encode' | 'decode' => v === 'encode' || v === 'decode';","tryCatchPattern":null,"preventionTips":["Whitelist subcommands before spawning the CLI from scripts","Treat exit code 2 (usage) differently from runtime failures in CI"],"tags":["cli","subcommand","usage-error","toon"],"backgroundTag":"missing-cli-subcommand","analyzedSha":"5184b3d11ac6a1acb7d44b9bfaa31698157cff97","analyzedAt":"2026-08-18T03:14:35.516Z","contentChangedAt":"2026-08-18T03:14:35.516Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}