What’s New

caveman

AI

caveman release notes.

Latest v1.9.1 · by cavemanWebsiteJuliusBrussee/caveman

Changelog

v1.9.1

v1.9.1 — 65%, honestly

Added
  • New limit-headroom meter in /caveman-stats for subscription users to view session budget saved at a glance
  • Documentation in docs/HONEST-NUMBERS.md explaining exactly when caveman saves tokens and when it costs them
  • Hermes Agent support with symmetric install/uninstall operations verified against real Hermes installs
  • Per-agent Cavecrew model overrides to pin each cavecrew subagent to the desired model
  • Claude Code now discovers slash commands via shipped commands/*.md and caveman-stats.toml files
Changed
  • Headline savings is now a flat 65% everywhere, measured as average output-token reduction vs default verbose replies across a 10-prompt benchmark
  • Output-reduction line in /caveman-stats is now labeled as output reduction instead of as a share of usage/quota
Fixed
  • Session token stats in /caveman-stats are now attributed to the mode that was active when each message happened, preventing mid-session mode changes from rewriting historical session math
  • Natural-language triggers no longer misfire and one-shot modes stay one-shot
  • mode-tracker now survives a broken stdin instead of hanging or crashing
  • SessionStart SKILL.md path off-by-one error fixed so the ruleset injects reliably
  • spawn ENOENT is now treated as a failure instead of reporting a fake successful install
  • No more EXDEV crash installing the Claude plugin across devices/filesystems by falling back to copy when rename cannot cross a mount
  • JSONC settings.json reader is now string-aware and no longer mangles trailing commas inside string values
  • install.ps1 now works when piped to iex
  • Uninstall now matches managed hook basenames instead of a loose substring to prevent stripping the wrong entry
  • caveman-init no longer requires a caveman checkout and runs standalone
  • opencode --force now migrates a legacy AGENTS.md instead of wiping it
  • OpenClaw SOUL.md data-loss issue fixed where a stray or half-present caveman marker could delete user content on next install/uninstall
  • caveman-shrink spawn-options.js now ships in the published tarball

A maintenance + honesty release. 50 changes since v1.9.0, mostly hook, installer, and integration hardening, plus a full pass on how caveman states its savings number. Installs stay pinned + integrity-checked; this tag now ships cavecrew-model-overrides.js in the hook manifest so the curl|bash fallback path installs cleanly.

Honest numbers, one number
  • Headline savings is now a flat 65% everywhere (#234). We retired the ~50-65% range and the ~75% claim that still lived on the docs site. 65% is the measured average output-token reduction vs default verbose replies across the committed 10-prompt benchmark (range 22–87%) — output tokens only. README, all plugin/extension manifests, the skill descriptions, the per-repo rule frontmatter, and the GitHub Pages site now agree.
  • /caveman-stats stops mislabeling savings (#601, and the budget-% fix). Session token stats are now attributed to the mode that was active when each message happened, so a mid-session /caveman ultra no longer rewrites the whole session's math. The output-reduction line is labeled as output reduction — not as a share of your usage/quota.
  • New limit-headroom meter in /caveman-stats for subscription users — session budget saved at a glance.
  • docs/HONEST-NUMBERS.md documents exactly when caveman saves tokens and when it costs them (#145, #550, #506). If caveman is net-negative for your workload, that page tells you to turn it off.
Hooks
  • Natural-language triggers stop misfiring and one-shot modes stay one-shot (#598, #599). /caveman-commit / -review / -compress no longer stick as a persistent mode.
  • mode-tracker survives a broken stdin — an error on the stdin stream no longer hangs or crashes the hook (#538).
  • SessionStart SKILL.md path off-by-one fixed (#587, #589) so the ruleset injects reliably.
Installer
  • Hermes Agent support — install/uninstall are symmetric and verified against a real Hermes install (#524).
  • Per-agent Cavecrew model overrides (#521) — pin each cavecrew subagent to the model you want.
  • spawn ENOENT is now treated as a failure, not a success (#592) — a missing binary no longer reports a fake successful install.
  • No more EXDEV crash installing the Claude plugin across devices/filesystems — falls back to copy when rename can't cross a mount (#585).
  • JSONC settings.json reader is string-aware (#595) — a trailing comma inside a string value is no longer mangled during the merge.
  • install.ps1 works when piped to iex (#565), and uninstall matches managed hook basenames instead of a loose substring so it can't strip the wrong entry (#593).
  • Claude Code discovers the slash commandscommands/*.md and caveman-stats.toml now ship so /caveman, /caveman-stats, etc. register (#571, #470).
  • caveman-init no longer needs a caveman checkout — the per-repo rule writer runs standalone (#603).
Integrations
  • opencode --force migrates a legacy AGENTS.md instead of wiping it (#594).
  • OpenClaw SOUL.md data-loss fixed — a stray or half-present caveman marker can no longer chain into deleting user content on the next install/uninstall (#596).
caveman-shrink (npm MCP middleware)
  • spawn-options.js now ships in the published tarball (#597) — the package was importing a file it didn't include.
  • Nested protected-segment sentinels restored (#444) — documents with adjacent/nested protected regions round-trip through compress without losing or duplicating content.
/caveman-compress
  • Build files and scripts are never classified as prose (#600) — package.json, Makefile, and shebang scripts won't get rewritten into caveman prose.
Repo standards & docs
  • Added SECURITY.md, CODE_OF_CONDUCT.md, .editorconfig.
  • Security/privacy docs: an explicit no-telemetry statement and notes on scanner warnings (#347, #504, #383, #28).
  • benchmarks/run.py reads only ANTHROPIC_API_KEY from .env.local (#528).

Known follow-ups (non-blocking, tracked for a later release)
  • NL activation: a negated phrase like "I don't want caveman" can still toggle the mode on; self-correcting with "stop caveman."
  • /caveman-stats savings estimate can skew when two Claude Code sessions run in different modes under the same config dir (shared mode log).
  • /caveman-compress shebang guard doesn't catch a shebang script that also carries a .txt/.rst extension.
  • The ultra-mode examples in skills/caveman/README.md still show abbreviations/arrows that the current ultra rule drops — cosmetic doc drift.

Full changelog: https://github.com/JuliusBrussee/caveman/compare/v1.9.0...v1.9.1

v1.9.0

v1.9.0 — Rock pinned. Rock verified. opencode rock work now.

Added
  • Repo-local config via .caveman/config.json or .caveman.json to pin per-project default mode
  • Natural-language brevity triggers for caveman mode including "less tokens", "be brief", and "be terse"
Fixed
  • opencode plugin now loads correctly by evaluating shared config as CommonJS by hand
  • Real lifecycle hooks implemented for opencode including event dispatcher for session init, chat.message for mode parsing, and experimental.chat.system.transform for per-turn reinforcement
  • Session-init flag write no longer misses one-shot opencode run sessions
  • caveman command works through both TUI command template expansion and quoted non-interactive run path
  • caveman-compress command file now ships
  • Copilot detection via extension directories
  • npx skills add honors the agent profile
  • Orphaned managed hooks pruned from settings.json
  • No double hook-wiring when plugin manifest already wires them
  • MCP-shrink is opt-in and requires an upstream
  • opencode config directory corrected to ~/.config/opencode on Windows
  • PowerShell $Args collision resolved
  • cavecrew agent copies strip tools: prefix for opencode
  • caveman-compress UTF-8 pinned subprocess to fix Windows cp1252 crash
  • caveman-compress claude.cmd resolution on Windows
  • caveman-compress YAML frontmatter preserved
Security
  • Installs now pinned and integrity-checked against the immutable v1.9.0 tag with SHA-256 verification of all hooks before execution
  • Fixed reflected DOM XSS in docs site demo by building nodes with textContent instead of innerHTML
Security
  • Installs now pinned + integrity-checked (#261, #262) curl|bash and detached installs no longer fetch hook files from the moving main branch — they download from the immutable v1.9.0 tag and verify every hook against src/hooks/checksums.sha256 (SHA-256) before anything executes. Mismatch aborts the install. This is the first tag shipping the manifest, so enforcement is fully active as of this release.

  • fix(docs): escape user input in the demo terminal (#438) The docs site demo interpolated user input via innerHTML — a real reflected DOM XSS. Nodes are built with textContent now.

opencode actually works now

Smoke-tested against a real opencode runtime for the first time — and the plugin turned out to never load: opencode runs plugins inside a compiled Bun binary where both require() of on-disk files and await import() of CJS silently fail. Fixed by evaluating the shared config as CommonJS by hand. Also fixed in the same pass, all verified end-to-end against opencode 1.4.0:

  • Real lifecycle hooks: event dispatcher for session init, chat.message for mode parsing, experimental.chat.system.transform for per-turn reinforcement — the old hook keys never existed and were silently ignored (#418, #421)
  • Session-init flag write no longer misses one-shot opencode run sessions
  • /caveman <level> works both through the TUI command template expansion and the quoted non-interactive run path
  • /caveman-compress command file now ships (was gitignored) (#398, #426, #451, #464)
Features
  • Repo-local config (#429) — check in .caveman/config.json (or .caveman.json) to pin a per-project default mode for the whole team. Resolution order: env var → repo config → user config → full.
  • Natural-language brevity triggers (#248) — "less tokens", "be brief", "be terse" now activate caveman mode.
Fixes
  • Installer: Copilot detection via extension dirs (#437), npx skills add honors the agent profile again (#395), orphaned managed hooks pruned from settings.json (#472), no double hook-wiring when the plugin manifest already wires them (#393), MCP-shrink is opt-in and requires an upstream (#380), opencode config dir corrected to ~/.config/opencode on Windows (#376), PowerShell $Args collision (#414), cavecrew agent copies strip tools: for opencode (#443)
  • caveman-compress: UTF-8 pinned subprocess (fixes Windows cp1252 crash, #388/#152), claude.cmd resolution on Windows (#435), YAML frontmatter preserved (#424), backups written outside the source tree (#420)
  • Skill: replies preserve the user's language (#446), no self-reference (#469), full-mode output guardrails (#322), fixed corrupted wenyan example
  • Stats: Opus 4.5+ output price corrected $75 → $25/M (#466), statusline pickaxe renders on Windows (#459)
  • MCP-shrink: npx/.cmd upstream resolution on Windows (#387)
Maintenance
  • Sponsors section (welcome, Atlas Cloud), caveman-code + cavegemma in the ecosystem table, stale pre-cleanup dotdir mirrors removed, init tests no longer touch the developer's real ~/.openclaw workspace.
Upgrade
curl -fsSL https://raw.githubusercontent.com/JuliusBrussee/caveman/main/install.sh | bash

Existing installs: re-run the same one-liner — idempotent. opencode users should re-run with --force to pick up the fixed plugin: npx -y github:JuliusBrussee/caveman -- --only opencode --force

🤖 Generated with Claude Code

v1.8.2

v1.8.2 — installer bug fixes

Fixed
  • curl|bash one-liner now installs skills by passing --yes --all to both the per-provider call and the auto-detect fallback
  • strip stray YAML fences from commands/caveman-init.toml so Gemini CLI extension loads cleanly
  • rename codex_hooks to hooks in .codex/config.toml to use the canonical key
Fixes
  • fix(install): curl|bash one-liner now actually installs skills (#370) Upstream skills CLI rendered its interactive skill-picker TUI under curl|bash (stdin not a TTY), got no selection, exited 0, and installed nothing — while our installer cheerfully reported done. Now passes --yes --all to both the per-provider call and the auto-detect fallback so every detected agent gets all 7 caveman skills, no prompt required.

  • fix(gemini): strip stray YAML fences from commands/caveman-init.toml (#372, dup #326) Gemini CLI's FileCommandLoader rejected the file with Failed to parse TOML on extension install. Fences gone — extension loads cleanly.

  • fix(codex): rename codex_hookshooks in .codex/config.toml (#350) Codex source confirms hooks is the canonical key; codex_hooks is a legacy alias that emits a deprecation log on every session.

Upgrade
curl -fsSL https://raw.githubusercontent.com/JuliusBrussee/caveman/main/install.sh | bash

Existing installs: re-run the same one-liner — idempotent, picks up the new flags.

🤖 Generated with Claude Code

v1.8.1

v1.8.1 — Hotfix: curl|bash one-liner

Added
  • New regression test asserts -- is accepted
Fixed
  • install.sh defaults BASH_SOURCE[0] to empty to prevent unbound variable error under curl|bash with set -u
  • install.sh and install.ps1 no longer pass -- between npx and the package to avoid unknown flag rejection
  • bin/install.js parseArgs now accepts a bare -- as a no-op POSIX end-of-options marker
Hotfix for v1.8.0 — curl|bash one-liner

The headline install command in v1.8.0 was broken at first contact:

$ curl -fsSL https://raw.githubusercontent.com/JuliusBrussee/caveman/main/install.sh | bash -s -- --only openclaw
bash: line 39: BASH_SOURCE[0]: unbound variable
error: unknown flag: --

Two regressions — neither caught by CI because both are stdin-pipe-only.

What broke
  1. set -u + ${BASH_SOURCE[0]} is fatal under curl|bash. When bash reads from stdin, BASH_SOURCE is unset; the strict-mode shell trapped on the first reference.
  2. -- separator survived npx. install.sh and install.ps1 passed npx -y "github:..." -- "$@" and modern npx forwards the literal -- to the package, which parseArgs rejected as unknown flag: --.
What this release fixes
  • install.sh defaults BASH_SOURCE[0] to empty so the curl-pipe path falls through cleanly under set -u.
  • install.sh + install.ps1 no longer pass -- between npx and the package — npm 7+ npx forwards trailing args correctly without it.
  • bin/install.js parseArgs now accepts a bare -- as a no-op (POSIX end-of-options marker). Future shim drift can't re-break this.
  • New regression test asserts -- is accepted.
Upgrade
curl -fsSL https://raw.githubusercontent.com/JuliusBrussee/caveman/main/install.sh | bash -s -- --only openclaw

If you tried v1.8.0 and got the error above, just re-run this command. No state was written on the failed install.

What's unchanged from v1.8.0

Everything else — OpenClaw, opencode, the installer fixes, the test bump (now 51 tests). See v1.8.0 release notes for the full feature list.

v1.8.0

v1.8.0 — Lobster grunt. Opencode grunt. Brain still big.

Added
  • Add OpenClaw (lobster) as a first-class always-on agent target via skill drop at ~/.openclaw/workspace/skills/caveman/SKILL.md and SOUL.md marker-fenced bootstrap block
  • Add opencode native plugin as always-on replacement for npx-skills fallback, with session.created and tui.prompt.append lifecycle hooks
  • Add six opencode slash-command prompt templates (/caveman, /caveman-commit, /caveman-review, /caveman-compress, /caveman-stats, /caveman-help)
  • Add three cavecrew subagents for opencode plugin
  • Add seven skill folders for opencode (caveman, caveman-commit, caveman-review, caveman-help, caveman-stats, caveman-compress, cavecrew)
  • Add Tier-3 always-on ruleset in opencode AGENTS.md fenced with <!-- caveman-begin --> / <!-- caveman-end --> markers
  • Add caveman-shrink MCP server to opencode.json (enabled by default via --with-mcp-shrink)
  • Add seven new tests covering --only typo validation, --config-dir ~ expansion, --help scope disclosure, malformed-input safety, AGENTS.md fence assertion, plugin.js hand-edit survival, and fenced uninstall preservation
Changed
  • Consolidate repository layout by moving hooks/, rules/, tools/, mcp-servers/ under src/
  • Change opencode plugin payload to no longer overwrite on reinstall, requiring --force flag to update user edits
  • Change opencode AGENTS.md to use fence markers for uninstall, preserving legacy un-fenced blocks by default unless --force is passed
  • Update --config-dir help text to disclose that it does not sandbox claude plugin install, gemini extensions install, opencode (XDG_CONFIG_HOME), or openclaw (OPENCLAW_WORKSPACE)
Fixed
  • Fix downloadTo Promise that was unawaited on https fallback path, causing silent partial install when curl was missing
  • Fix --only <typo> to validate against provider matrix and exit with code 2 instead of silently exiting 0
  • Fix .bak files being silently overwritten on every reinstall by preserving them on first install only
  • Fix opencode plugin payload (plugin.js, package.json, caveman-config.cjs) being rewritten on every reinstall by honoring --force flag
  • Fix uninstall to probe claude plugin list and gemini extensions list before firing uninstaller to eliminate stderr noise on cold uninstalls
  • Fix uninstall to also run claude mcp remove caveman-shrink when the subcommand exists
  • Fix removeCavemanHooks to no longer crash on malformed pre-existing settings.hooks
  • Fix --config-dir value to be ~-expanded

⚠️ v1.8.0's curl|bash one-liner was broken (BASH_SOURCE unbound + stray -- to parseArgs). Use v1.8.1 instead — same release contents plus the hotfix.

Brain still big. Two more mouths now small.

This release teaches caveman to two new agents: OpenClaw (the lobster) and opencode (the TUI). Both now grunt fluent caveman from message one — no /caveman per session, no setup nag.

Plus a stack of installer fixes from a top-to-bottom review of bin/install.js.

What's new
🦞 OpenClaw — first-class always-on target

npx -y github:JuliusBrussee/caveman -- --only openclaw and the lobster talks like a caveman every turn.

Two tiny writes do the work:

  • Skill drop at ~/.openclaw/workspace/skills/caveman/SKILL.md — spec-correct frontmatter (version, always: true), discoverable by openclaw skills list.
  • SOUL.md nudge — marker-fenced bootstrap block at ~/.openclaw/workspace/SOUL.md, auto-injected each turn under "Project Context". Stays well under OpenClaw's 12K-per-file cap.

Idempotent on both writes. Uninstall strips the skill folder + the marker block, leaves your other workspace content alone. Custom workspace via OPENCLAW_WORKSPACE.

See README's Lobster, Meet Rock section for the longer pitch.

🤖 opencode — native plugin replaces npx-skills fallback

opencode goes from "manual /caveman per session" to always-on. The installer drops:

  • A real opencode plugin (~/.config/opencode/plugins/caveman/) using session.created and tui.prompt.append lifecycle hooks
  • Six slash-command prompt templates (/caveman, /caveman-{commit,review,compress,stats,help})
  • Three cavecrew subagents
  • Seven skill folders (caveman, caveman-commit/review/help/stats/compress, cavecrew)
  • A Tier-3 always-on ruleset in AGENTS.md, fenced with <!-- caveman-begin --> / <!-- caveman-end --> markers (clean uninstall later)

opencode.json gets patched with the plugin entry plus the caveman-shrink MCP server (when --with-mcp-shrink is on, which is the default).

opencode reaches Tier-1 minus the statusline (opencode's TUI exposes no plugin-writable badge).

🛠️ Installer rewrite + correctness fixes

The unified bin/install.js got reviewed end-to-end. What changed in this release:

Bug fixes (high-severity)

  • downloadTo Promise was unawaited on the https fallback path — silent partial install if curl was missing. Now properly awaited.
  • --only <typo> used to exit 0 with no work done. Now validates against the provider matrix and exits 2 with error: unknown agent: <id>.
  • .bak files were silently overwritten on every reinstall, destroying recovery. Now preserved on first install only.
  • opencode plugin payload (plugin.js, package.json, caveman-config.cjs) used to be rewritten on every reinstall, wiping user edits. Now honors the same !--force skip the rest of the payload uses.
  • --config-dir help text now discloses scope honestly: it does not sandbox claude plugin install, gemini extensions install, opencode (XDG_CONFIG_HOME), or openclaw (OPENCLAW_WORKSPACE).

Idempotency / hygiene

  • Uninstall now probes claude plugin list / gemini extensions list before firing the uninstaller — no more "Plugin not installed" stderr noise on cold uninstalls.
  • Uninstall now also runs claude mcp remove caveman-shrink (when the subcommand exists).
  • opencode AGENTS.md is now fenced with <!-- caveman-begin --> / <!-- caveman-end -->. Uninstall strips just the fenced block, preserving any user content above and below it.
  • --config-dir value is now ~-expanded.
  • removeCavemanHooks no longer crashes on malformed pre-existing settings.hooks (e.g. when a user hand-edited and broke things).
🧹 Repo layout consolidated

hooks/, rules/, tools/, mcp-servers/ all moved under src/. Sources of truth are at the top of the tree; distribution mirrors live below. See CLAUDE.md for the new map.

Tests

50/50 passing (npm test). Up from 43 in v1.7.0 — seven new tests cover:

  • --only typo validation
  • --config-dir ~ expansion
  • --help discloses --config-dir scope
  • removeCavemanHooks malformed-input safety
  • AGENTS.md fence assertion
  • opencode plugin.js hand-edit survives reinstall (without --force)
  • AGENTS.md fenced uninstall preserves user prefix and suffix
Verify after upgrade
node bin/install.js --list      # 34 providers; OpenClaw + opencode visible
node bin/install.js --help      # --config-dir scope is now spelled out

For the lobster: npx -y github:JuliusBrussee/caveman -- --only openclaw.

For opencode: npx -y github:JuliusBrussee/caveman -- --only opencode (needs a local clone or npx-extracted repo for the native plugin payload).

Upgrade

Existing users:

npx -y github:JuliusBrussee/caveman

Auto-detects everything you already had + picks up OpenClaw and opencode if present. Safe to re-run.

Behavior changes worth knowing
  • opencode plugin payload no longer overwrites on reinstall. If you've edited ~/.config/opencode/plugins/caveman/plugin.js and want the new version, pass --force. Without --force, your edits stay.
  • opencode AGENTS.md from v1.7.x and earlier was un-fenced. Reinstall won't replace a legacy block by default; pass --force to rewrite with the fenced version. Uninstall still removes legacy blocks correctly.
Caveman ecosystem
  • caveman (you here) — output compression
  • cavemem — cross-agent memory
  • cavekit — spec-driven build loop

One rock. Two rock. Three rock. That it.

v1.7.0

v1.7.0 — Stats receipts, smart installer, cavecrew, MCP-shrink

Added
  • Add /caveman-stats command to display real token receipts including output tokens, cache-read tokens, estimated tokens saved, and cost savings with support for lifetime aggregation via --all and time windows via --since
  • Add statusline savings badge showing lifetime tokens saved, enabled by default and configurable via CAVEMAN_STATUSLINE_SAVINGS environment variable
  • Publish caveman-shrink as npm package, an MCP middleware that compresses description fields in tools/list, prompts/list, and resources/list responses while preserving code, URLs, paths, and identifiers
  • Add cavecrew, three caveman-mode subagents for Claude Code that emit approximately 60% fewer handoff tokens than vanilla agents: cavecrew-investigator for read-only code location queries, cavecrew-builder for surgical 1-2 file edits, and cavecrew-reviewer for diff and file review
  • Add smart multi-agent installer that detects 33 AI coding agents on the machine and runs each one's native installation with flags for --minimal, --with-hooks, --with-mcp-shrink, --with-init, --list, --only, and --dry-run options
  • Add caveman-init tool to drop rule files for supported agents into any repository
Fixed
  • Fix critical macOS installer bug that was silently breaking detection for all compound-spec providers including Cursor, Windsurf, Continue, and 28 others
v1.7.0 — Stats receipts, smart installer, cavecrew, MCP-shrink

The biggest release since v1.0. Caveman now has measurement (real token receipts, not vibes), an installer that detects 30+ agents and runs each one's native install, three caveman-mode subagents that emit ~60% fewer handoff tokens than vanilla, an MCP middleware that shrinks tool descriptions in flight, and a one-command rule-file dropper for any repo.

Plus a critical macOS installer fix that was silently breaking detection for every compound-spec provider (cursor / windsurf / continue / 28 others).


🆕 New: /caveman-stats — real receipts, not vibes
Caveman Stats
──────────────────────────────────
Session:  ...projects/my-app/abc123.jsonl
Turns:    47
──────────────────────────────────
Output tokens:         3,210
Cache-read tokens:     128,400
──────────────────────────────────
Est. tokens saved:     5,961 (~65%)
Est. saved (USD):      ~$0.089
──────────────────────────────────
Memory compressed:     2 files, ~1,920 tokens saved per session start

Reads the active Claude Code session JSONL directly — no model-side guessing. Pricing matches by model-id prefix (claude-sonnet-4-* → $15/M, etc.) so it stays correct across point releases. Lifetime aggregation via --all, time window via --since 7d / --since 24h, tweetable one-liner via --share.

Statusline savings badge — on by default. After your first /caveman-stats run the bar shows [CAVEMAN] ⛏ 12.4k (lifetime tokens saved) and updates every run. Opt out with CAVEMAN_STATUSLINE_SAVINGS=0. Suffix file is absent until stats has run, so fresh installs render no fake number.

29 tests cover: pricing prefix-match, lifetime aggregation latest-per-session semantics, --since parsing, malformed-duration rejection, compressed-memory pair detection, statusline default-on / opt-out / fresh-install behaviors, ANSI-escape stripping in the suffix file, and symlink-safe history append.

🆕 New: caveman-shrink — MCP middleware (published to npm)

caveman-shrink@0.1.0 is a stdio proxy that wraps any MCP server, intercepts tools/list / prompts/list / resources/list responses, and compresses the description fields. Same boundaries as the parent skill — code, URLs, paths, and identifiers stay byte-for-byte identical.

{
  "mcpServers": {
    "fs-shrunk": {
      "command": "npx",
      "args": ["caveman-shrink", "npx", "@modelcontextprotocol/server-filesystem", "/path/to/dir"]
    }
  }
}

V1 deliberately does not touch tool-call response bodies or request payloads — only prose-y description fields. Configurable extra fields via CAVEMAN_SHRINK_FIELDS, debug deltas via CAVEMAN_SHRINK_DEBUG=1. Auto-registered by install.sh (use --minimal to skip). 12 tests cover: article/filler/hedge stripping, fenced code preservation, inline code preservation, URL preservation, filesystem-path preservation, identifier preservation, real MCP-style descriptions, nested-object walking.

🆕 New: cavecrew — three caveman subagents for Claude Code

Subagent tool-output gets injected back into the main thread context. Vanilla Explore / reviewer agents return verbose prose that eats main-context fast. Cavecrew agents emit caveman-ultra by default, ~60% fewer handoff tokens.

SubagentModelJobOutput
cavecrew-investigatorhaikuRead-only locator. "Where is X defined?" / "what calls Y?" / "map this dir"path:line — \symbol` — note`, grouped headers when 3+
cavecrew-buildersonnet1-2 file surgical edits. Refuses 3+ file scope.path:line-range — change ≤10 words. + verified: re-read OK
cavecrew-reviewerhaikuDiff/branch/file review. One line per finding.path:line: 🔴 bug: problem. fix. + severity totals

Builder has no Bash tool — can't shell out, can't push, can't delete. Refusals are terminal one-liners (too-big. split: ..., needs-confirm. op: ..., regressed. revert path:line).

🆕 New: smart multi-agent installer
# macOS / Linux / WSL
curl -fsSL https://raw.githubusercontent.com/JuliusBrussee/caveman/main/install.sh | bash

# Windows
irm https://raw.githubusercontent.com/JuliusBrussee/caveman/main/install.ps1 | iex

Detects which AI coding agents are on your machine and runs each one's native install (plugin / extension / skill / rule file). Skips what you don't have. Safe to re-run.

Coverage: 33 agents. Native: Claude Code, Gemini CLI, Codex. IDE/VS Code-family: Cursor, Windsurf, Cline, Copilot, Continue, Kilo, Roo, Augment. CLI: Aider Desk, Amp, Bob, Crush, Devin, Droid, ForgeCode, Goose, iFlow, JetBrains Junie, Kiro CLI, Mistral Vibe, OpenHands, opencode, Qwen Code, Qoder, Rovo Dev, Tabnine, Trae, Warp, Replit Agent, Antigravity. Plus universal AGENTS.md / IDE rule files for everything else via npx skills.

FlagWhat
--allPlugin + hooks + statusline + MCP shrink + per-repo rule files. The full ride.
--minimalPlugin/extension only.
--with-hooksStandalone hooks + statusline + stats badge. On by default.
--with-mcp-shrinkRegister caveman-shrink MCP proxy. On by default.
--with-initDrop per-repo rule files for Cursor/Windsurf/Cline/Copilot/AGENTS.md.
--listPrint full agent matrix and exit.
--only <agent>One target only (repeatable).
--dry-runPreview, write nothing.

install.sh --help for full reference.

🆕 New: caveman-init (cavepack) — drop rule files into any repo
node tools/caveman-init.js              # writes rule files for all targets
node tools/caveman-init.js --dry-run    # preview
node tools/caveman-init.js --only cline # one target only

Idempotent — uses a sentinel string to detect prior installs and skip them. Existing rule files are preserved unless --force is passed. Appendable targets (AGENTS.md, .github/copilot-instructions.md) get the caveman block appended below your existing content; replace-mode targets (.cursor/rules/caveman.mdc, .windsurf/rules/caveman.md, .clinerules/caveman.md) get fresh files. 8 tests cover: greenfield create, idempotent skip, append-vs-replace semantics, sentinel detection, --force, --dry-run, --only.

🛠 Critical fixes
  • macOS installer detection was silently broken. detect_match() used awk -v RS='||' to split compound detection specs. BSD awk on macOS rejects || as a regex (illegal primary in regular expression), the awk silently failed, the fallback re-ran the whole spec as a single clause, and every compound-spec provider (cursor, windsurf, continue, kilo, roo, augment, aider-desk, bob, crush, devin, droid, forgecode, goose, iflow, kiro, mistral, openhands, opencode, qwen, rovodev, tabnine, trae, warp, replit) was undetectable on macOS. Replaced with bash parameter expansion (${rest%%||*} / ${rest#*||}) — works on bash 3.2+, no awk dependency. Verified with reproducer: compound match, fallback match, all-miss compound, single-clause all behave correctly.

  • --with-mcp-shrink registered a config that 404'd on first spawn. Pre-publish, claude mcp add caveman-shrink -- npx -y caveman-shrink would store an entry that failed every time Claude tried to spawn it. Now the installer probes npm view caveman-shrink first — package missing or registry unreachable degrades to a clean manual-config skip with a print-the-snippet fallback. Default-on restored after caveman-shrink@0.1.0 shipped to npm.

  • Windows install.ps1 syntax error from node -e. Powershell tokenizer truncated the embedded JS at double-quotes, breaking standalone hook install. Fix writes the script to a temp file, runs node script.js, and removes it. (Thanks @scottconverse — #250, fixes #249/#199/#72)

  • /caveman argument whitelist + symlinked-parent ~/.claude support. ~/.claude symlinked to another drive (legitimate pattern) was previously refused as a "symlink attack." Now: lstat parent, resolve, verify uid match (Unix) or home-dir prefix (Windows), then allow. The flag file itself still must never be a symlink — that's the actual clobber vector. Plus argument validation: only known mode tokens reach the flag write.

  • caveman-compress reliability. UTF-8 stdout enforced (Windows console no longer corrupts compressed output), empty/identical-input guards prevent silently writing zero-byte files, inline-code validation now matches the fenced-code rule, frontmatter cleanup preserves YAML.

🛡 Security
  • safeWriteFlag() extended to all flag-file writes. Adds: safeWriteFlag for the active-mode flag, appendFlag (with O_APPEND) for the lifetime stats log, and readFlag (with size cap + whitelist) for the per-turn reinforcement read. The whitelist (VALID_MODES) is the load-bearing part — without it, a flag pointing at ~/.ssh/id_rsa could exfiltrate via stdout.

  • Statusline scripts no longer trust the flag file blindly. Both caveman-statusline.sh and .ps1 now refuse symlinked flag/suffix files and strip control bytes (tr -d '\000-\037') so a hostile flag can't render terminal escape sequences in your status bar.

📊 Skill changes
  • Ultra-mode code-symbol guard. Previously the rule "abbreviate everything" was over-aggressive — symbols like useMemo or getUserById would get truncated. Now: ultra abbreviates prose, never code/symbols/error strings.
  • Auto-clarity expanded. Drop caveman for: security warnings, irreversible action confirmations, multi-step sequences where fragment ambiguity risks misread, compression itself creating ambiguity, user repeating a question.
  • Typst + LaTeX added to the protected-content list — math/markup blocks pass through untouched.
📚 Docs
  • README cleanup: install table now shows the smart installer first, manual install second, "What You Get" matrix collapsed to one table with footnotes, no more 4 nested <details> walls. Voice preserved (60-second readability check). Benchmark table re-anchored to real benchmarks/results/*.json runs (mean 65%, range 22-87%).
  • Codex install clarified — repo-local .codex/hooks.json makes auto-activation work for this repo on macOS/Linux; for other repos, copy the hook or use $caveman manually. Codex hooks currently disabled on Windows.
  • New: docs/install-windows.md — manual fallback for stubborn Windows envs (PR-merged plugin install path, symlink config for Codex).
  • CLAUDE.md heavily expanded: hook system, distribution matrix, skill-system, "adding a new agent" checklist (profile slug must exist in upstream vercel-labs/skills, install.ps1 is hand-kept-in-sync with install.sh), caveman-shrink integration notes, cavecrew canonical-vs-synced layout.
🧪 Tests
  • 73 tests now ship: 29 stats + 12 mcp-shrink + 8 init + 12 symlink-flag + 4 hooks (py) + 8 verify_repo + Python compress safety + inline-validate.
  • All tests run on every CI push.
Upgrade

Plugin users:

claude plugin update caveman

Standalone hook users (re-run for the new statusline, MCP-shrink registration, and crash fixes):

bash hooks/install.sh --force

Curl-pipe / fresh install:

curl -fsSL https://raw.githubusercontent.com/JuliusBrussee/caveman/main/install.sh | bash

Other agents:

npx skills add JuliusBrussee/caveman

Don't want the MCP shrink or per-repo init? --minimal skips them. Want everything? --all.

Thanks

@scottconverse (#250 Windows fix), @ikattur-ota (#199 Windows hook reports), @confluencepoint (#72 module-loader report), and everyone who hammered the installer until the awk-on-macOS bug fell out.

v1.6.0

v1.6.0 — Hardening release: hook crash fixes + symlink-safe flag writes

Added
  • Per-turn caveman reinforcement via hookSpecificOutput reminder on every UserPromptSubmit to maintain caveman style across context drift
Changed
  • CLAUDE_CONFIG_DIR env var is now respected across all hooks, statusline scripts, and install/uninstall scripts
  • Natural-language activation now matches "talk like caveman", "caveman mode", "stop caveman", and "normal mode" phrases in addition to /caveman slash commands
  • Consolidated all flag file writes through safeWriteFlag() helper
Fixed
  • Hooks no longer crash when an ancestor package.json declares "type": "module" by shipping hooks/package.json with {"type": "commonjs"}
  • ${CLAUDE_PLUGIN_ROOT} is now quoted in plugin.json to fix plugin install paths containing spaces
  • Codex hook config shape updated to the current spec with matcher + nested hooks array
  • skills/compress/scripts/ is now real Python files instead of broken Git symlinks on Windows and non-symlink-following platforms
  • README link fixes for several broken anchors
Security
  • safeWriteFlag() helper hardens all flag file writes against symlink attacks by refusing symlink parent directories, refusing symlink targets, opening with O_NOFOLLOW where supported, writing atomically via temp file + rename(), and setting 0600 permissions on creation
v1.6.0 — Hardening release

11 community PRs merged plus a hardened security model for the flag file. This release fixes two real crash bugs that were silently breaking installs, two local-file-clobber vulnerabilities, and several portability gaps.

Critical fixes
  • Hooks no longer crash when an ancestor package.json declares "type": "module". Before this fix, any user with ~/.claude/package.json set to ESM (common with several Claude Code plugins) hit ReferenceError: require is not defined in ES module scope on every session. SessionStart and UserPromptSubmit hooks both silently failed, the flag file was never written, and the statusline badge disappeared. Fixed by shipping hooks/package.json with {"type": "commonjs"} so the hooks pin themselves to CJS regardless of ancestor settings. (Thanks @malakhov-dmitrii — #174)

  • ${CLAUDE_PLUGIN_ROOT} is now quoted in plugin.json. Plugin install paths containing spaces (e.g. ~/Library/Application Support/... on macOS, C:\Users\Some Name\... on Windows) used to break the node invocation entirely. (Thanks @MukundaKatta — #171)

  • Codex hook config shape updated to the current spec. The old shape silently no-op'd on Codex with hooks enabled. New shape uses the matcher + nested hooks array. Repo also now ships .codex/config.toml with codex_hooks = true so auto-activation actually works inside this repo on macOS/Linux. (Thanks @davidbits — #148)

Security fixes
  • safeWriteFlag() helper hardens all flag file writes against symlink attacks. The flag file at ~/.claude/.caveman-active is at a predictable path. Before this fix, a local attacker (or any sibling process running as the same user but with a smaller blast radius — sandboxed extension, container with a ~/.claude bind mount, etc.) could replace the flag with a symlink to any user-writable file (~/.ssh/authorized_keys, ~/.bashrc) and the next hook write would clobber the symlink target. The new helper, defined once in hooks/caveman-config.js and used by every write site:

    • Refuses if the flag's parent directory is itself a symlink
    • Refuses if the existing flag target is a symlink
    • Opens with O_NOFOLLOW where supported (Linux/macOS)
    • Writes atomically via temp file + rename()
    • Sets 0600 permissions on creation

    Verified against a real symlink-redirect attack: the target file is left untouched. (Thanks @tuanaiseo — #70 + #71, consolidated into one shared helper)

Quality of life
  • CLAUDE_CONFIG_DIR env var is now respected across all hooks, statusline scripts, and install/uninstall scripts. Users with non-default Claude Code config locations no longer have to symlink things into ~/.claude/. (Thanks @BrendanIzu — #146)

  • Natural-language activation actually works now. The README has long claimed talk like caveman and caveman mode activate caveman, and stop caveman / normal mode deactivate it. The mode tracker hook only ever matched /caveman slash commands, so the natural-language phrasings were a lie. Now they're not. (Thanks @hummat — #120)

  • Per-turn caveman reinforcement. SessionStart injects the full ruleset once, but other plugins inject competing style instructions every turn. The mode tracker now emits a small hookSpecificOutput reminder on every UserPromptSubmit so the model keeps caveman style even after context drift. Skipped for independent modes (commit, review, compress) which have their own behavior. (Thanks @hummat — #119)

  • skills/compress/scripts/ is now real Python files instead of broken Git symlinks. Previously symlinks inside the skills directory broke on Windows and on platforms that don't follow them. The compress sub-skill now ships as proper modules: compress.py, detect.py, validate.py, benchmark.py, plus cli.py and __main__.py. (Thanks @gladkia — #153)

  • README link fixes — several broken anchors corrected. (Thanks @nervana21 — #169)

Internal
  • Consolidated all flag file writes through safeWriteFlag(). Direct fs.writeFileSync on predictable user-owned paths is now an anti-pattern documented in CLAUDE.md.
  • CLAUDE.md updated to document the new helper, CLAUDE_CONFIG_DIR support, the hooks/package.json CJS marker, natural-language activation, and per-turn reinforcement.
Known gaps (tracked for v1.6.1)

The flag file read path in the new per-turn reinforcement still trusts whatever's in the file, so a sibling process that can write the flag could inject arbitrary content into the model's context as a "mode name." Real exploit precondition is narrow (attacker needs write access to ~/.claude/ but no read on other user files — i.e. a sandboxed sibling process), but the fix is cheap and will land in a follow-up patch: lstat + length cap + VALID_MODES whitelist on the read.

The statusline scripts (caveman-statusline.sh/.ps1) read the flag without validation either, which on a hostile flag could render terminal escape sequences. Same fix pattern, same patch.

Upgrade

Plugin users:

claude plugin update caveman

Standalone hook users:

bash hooks/install.sh --force

Other agents (Cursor/Windsurf/Cline/Copilot/etc.):

npx skills add JuliusBrussee/caveman

v1.5.1

Added
  • Standalone installs fall back to a built-in minimal ruleset when no skills directory is present
Changed
  • Activation hook now reads skills/caveman/SKILL.md at runtime instead of hardcoding rules inline
  • Plugin installs resolve SKILL.md relative to the plugin root
  • commit/review/compress modes skip SKILL.md machinery entirely and use their own independent skill files
  • Consolidate install details for Cursor, Windsurf, Cline, and Copilot into one block
Fixed
  • Fix bash statusline badge example to use ANSI-C quoting so escape sequences render correctly
  • Fix /caveman with off default writing "off" to flag file by guarding against off and deleting the flag file
Runtime SKILL.md loading

Activation hook now reads skills/caveman/SKILL.md at runtime instead of hardcoding rules inline. Edits to the source of truth propagate automatically — no duplication to go stale.

  • Plugin installs resolve SKILL.md relative to the plugin root
  • Standalone installs (hooks only, no skills dir) fall back to a built-in minimal ruleset
  • commit/review/compress modes skip SKILL.md machinery entirely — they have their own independent skill files
Docs
  • Consolidate install details — Cursor, Windsurf, Cline, and Copilot install instructions merged into one block (#106)
  • Fix bash statusline badge example — use ANSI-C quoting so escape sequences render correctly (#57)
Bug fixes
  • Fix /caveman with off default writing "off" to flag file — mode tracker now guards against off and deletes the flag file, matching the activate hook behavior

v1.5.0

Added
  • Make default mode configurable via CAVEMAN_DEFAULT_MODE environment variable or config file at ~/.config/caveman/config.json, with fallback to 'full'
  • Add 'off' mode to skip session-start activation entirely
  • Add /caveman-help command to display a quick-reference card covering all modes, skills, triggers, configuration, and deactivation
Changed
  • Update all install/uninstall scripts (bash and PowerShell) to support configurable default mode
Fixed
  • Fix /caveman with 'off' default writing 'off' to flag file by guarding against 'off' mode and deleting flag file
  • Fix swapped step comments in uninstall.sh where steps 3 and 4 were numbered out of order
  • Update CLAUDE.md documentation to reference configurable default mode instead of hardcoded 'full' default
Configurable default mode

Default mode is now configurable instead of always starting at full. Resolution order:

  1. CAVEMAN_DEFAULT_MODE environment variable (highest priority)
  2. Config file at ~/.config/caveman/config.json (XDG-compliant, cross-platform)
  3. 'full' (unchanged default — fully backward compatible)
export CAVEMAN_DEFAULT_MODE=ultra
{ "defaultMode": "lite" }

All install/uninstall scripts (bash + PowerShell) updated. Invalid modes silently fall through to default.

Closes #86

"off" mode — disable auto-activation

Set CAVEMAN_DEFAULT_MODE=off or {"defaultMode": "off"} in config to skip session-start activation entirely. No flag file written, no rules injected. User can still manually activate with /caveman during the session.

/caveman-help quick-reference card

New skill — type /caveman-help to display a terse reference card covering all modes, skills, triggers, configuration, and deactivation. One-shot display, no mode change.

Works in: Claude Code, Gemini CLI, Cursor, Windsurf, Cline, Copilot, and all agents via npx skills.

Bug fixes
  • Fix /caveman with off default writing "off" to flag file — mode tracker now guards against off and deletes the flag file, matching the activate hook behavior
  • Add test coverage for off mode — both activate hook and mode tracker paths now tested
  • Fix swapped step comments in uninstall.sh — steps 3 and 4 were numbered out of order
  • Update stale CLAUDE.md/caveman default now references configurable default instead of hardcoded full

v1.4.1

Added
  • Add configurable default caveman mode via CAVEMAN_DEFAULT_MODE environment variable or ~/.config/caveman/config.json with fallback to 'full'
  • Add /caveman-help skill to display a quick-reference card covering all modes, skills, triggers, configuration, and deactivation
Fixed
  • Fix Codex plugin compress skill on Windows by replacing symlinks with real file copies and adding CI sync step for future propagation
Fix: Codex plugin compress skill broken on Windows

The compress skill in the Codex plugin shipped as symlinks (plugins/caveman/skills/compress/SKILL.md and scripts). On Windows and any git setup with core.symlinks=false, these checked out as plain text files containing the target path — causing Codex to reject the skill with "missing YAML frontmatter."

Changes
  • Replaced symlinks with real file copies (scripts identical to source, SKILL.md adapted for plugin context)
  • Added CI sync step so future edits to caveman-compress/ auto-propagate to the plugin copy

Closes #92


Feature: Configurable default caveman mode

Default mode is now configurable instead of always starting at full. Resolution order:

  1. CAVEMAN_DEFAULT_MODE environment variable (highest priority)
  2. Config file at ~/.config/caveman/config.json (XDG-compliant, cross-platform)
  3. 'full' (unchanged default — fully backward compatible)

Example — env var:

export CAVEMAN_DEFAULT_MODE=ultra

Example — config file:

{ "defaultMode": "lite" }

All install/uninstall scripts (bash + PowerShell) updated. Invalid modes silently fall through to default.

Closes #86


Feature: /caveman-help quick-reference card

New skill — type /caveman-help to display a terse reference card covering all modes, skills, triggers, configuration, and deactivation. One-shot display, no mode change.

Works in: Claude Code, Gemini CLI, Cursor, Windsurf, Cline, Copilot, and all agents via npx skills.