JuliusBrussee/caveman · error · Error

usage: ${invokedCommand("compress")} [--type <content-type>]

Error message

usage: ${invokedCommand("compress")} [--type <content-type>] [--toon]

What it means

Argument validation for `caveman compress`: when `--type` is present, the next argv element must exist and must not start with '--'. The CLI throws this usage error when `--type` is the last argument or is immediately followed by another flag — i.e. the content-type value is missing.

Source

Thrown at packages/cli/src/index.ts:12926

  const path = mcpServerMarkerPath(agentId, serverName);
  durableAtomicWriteFile(path, mcpMarkerBytes(mcp, tool));
}

// compress streams stdin through the caveman-engine binary (resolved via
// CAVEMAN_ENGINE_BIN, default `caveman-engine` on PATH) and writes the compressed
// payload to stdout, forwarding the engine's JSON ratio report to stderr. The
// engine is fail-closed; if its binary is unavailable the CLI falls back to a
// pass-through that claims a 0 ratio, so `compress` never breaks a pipe.
async function compress(argv: string[]) {
  if (argv[0] === "catalog") return compressCatalog(argv.slice(1));
  if (argv.includes("--toon-stats")) {
    throw new Error("caveman compress --toon-stats is unavailable; use --toon to force TOON compression");
  }
  const input = await readStdin();
  const bin = cavemanBin("caveman-engine", "CAVEMAN_ENGINE_BIN");
  const typeIndex = argv.indexOf("--type");
  if (typeIndex >= 0 && (argv[typeIndex + 1] === undefined || argv[typeIndex + 1]!.startsWith("--"))) {
    throw new Error(`usage: ${invokedCommand("compress")} [--type <content-type>] [--toon]`);
  }
  let forcedType = argv.includes("--toon") ? "toon" : flagFrom(argv, "--type", "");
  if (forcedType === "auto") forcedType = "";
  const engineArgs = ["compress"];
  if (forcedType) engineArgs.push("--type", forcedType);
  let handled = false;
  const child = spawn(bin, engineArgs, { stdio: ["pipe", "inherit", "inherit"] });
  emitCommandRunOnce("ok"); // exit handler below hard-exits; never returns to main()
  child.on("error", () => { if (!handled) { handled = true; compressFallback(input, forcedType); } });
  child.on("exit", (code) => { if (!handled) { handled = true; process.exit(code ?? 0); } });
  if (child.stdin) {
    child.stdin.on("error", () => {}); // ignore broken pipe; the child 'error' drives the fallback
    child.stdin.end(input);
  }
}

// compressCatalog is explicit bridge to dedicated tool-catalog product. It
// preserves caveman-shrink's stdin/stdout/report contract and forwards lint /

View on GitHub (pinned to 5184b3d11a)

Solutions

  1. Pass a concrete value: `caveman compress --type application/json`
  2. Omit `--type` entirely to let the engine auto-detect the content type
  3. Use `--toon` alone when TOON compression is the goal
  4. In scripts, append the pair conditionally so a bare `--type` is never emitted

Example fix

# before
CTYPE=""
cat f.json | caveman compress --type "$CTYPE"
# after
if [ -n "$CTYPE" ]; then cat f.json | caveman compress --type "$CTYPE"; else cat f.json | caveman compress; fi
Defensive patterns

Strategy: validation

Validate before calling

// Build argv so --type is only ever appended together with its value.
const args: string[] = [];
if (contentType) args.push('--type', contentType);
if (forceToon) args.push('--toon');
// args can never end with a bare --type or have a flag in its value slot

Prevention

When it happens

Trigger: `caveman compress --type` with nothing after it; `caveman compress --type --toon < file` (value position occupied by a flag); shell scripts interpolating an empty or unset variable so the value token disappears.

Common situations: Unset environment variables in scripts (CTYPE="" making the token vanish), argument reordering during refactors, typos like `--type=--toon` when the CLI expects space-separated `--type <value>`.

Related errors


AI-assisted analysis of JuliusBrussee/caveman@5184b3d11a (2026-08-18). Data as JSON: /api/errors/ab425c5dbe9b13b7. Report an issue: GitHub.