How to Troubleshoot Common Caveman Errors: A Complete Diagnostic Guide
Most Caveman failures stem from three sources: flag-file permission issues in caveman-config.js, stdin handling errors in caveman-mode-tracker.js, or corrupted history files affecting caveman-stats.js.
Runtime issues in the JuliusBrussee/caveman repository typically trace back to its tightly-coupled three-piece architecture. Because the tool relies on a single flag file ($HOME/.claude/.caveman-active) as its source of truth, troubleshooting requires systematic verification of file I/O operations, process error handling, and installation integrity. This guide provides specific diagnostic commands and code references to resolve the most frequent failure modes.
Understanding Caveman's Three-Component Architecture
Caveman operates through three interconnected modules that share state via the filesystem:
src/hooks/caveman-config.js– Handles configuration and flag handling, includingsafeWriteFlagandreadFlagfunctions that manage the active-mode flag file.src/hooks/caveman-mode-tracker.js– Runs on every user prompt to parse/cavemancommands, update the flag file, and emit the "CAVEMAN MODE ACTIVE" notice.src/hooks/caveman-stats.js– Computes token savings, executes/caveman-stats, and processes auxiliary commands like/caveman-commitand/caveman-review.
Because these components communicate through the flag file, most errors manifest as permission denials, silent write failures, or stale mode states.
Diagnosing Flag-File Issues in caveman-config.js
The flag file at $HOME/.claude/.caveman-active must satisfy strict safety requirements enforced by safeWriteFlag in src/hooks/caveman-config.js. The file must never be a symlink, must reside in a user-owned directory, and must contain a valid mode string (lite, full, ultra, or wenyan).
Common symptoms and verification commands:
-
Symptom:
/cavemancommands produce no output and no "CAVEMAN MODE ACTIVE" line appears.- Check: Verify the file exists and is a regular file:
ls -l $HOME/.claude/.caveman-active(should show ≤ 64 bytes, not a symlink).
- Check: Verify the file exists and is a regular file:
-
Symptom: Mode appears as
offorlitewhen you requestedfull.- Check: Inspect the current value:
cat $HOME/.claude/.caveman-activeand verify it matches your intended mode.
- Check: Inspect the current value:
-
Symptom: Stats script reports "no active mode".
- Check: Test the reader directly:
node -e "console.log(require('./src/hooks/caveman-config').readFlag('$HOME/.claude/.caveman-active'))".
- Check: Test the reader directly:
Enable debug output to see why writes fail silently:
CAVEMAN_DEBUG=1 node -e "require('./src/hooks/caveman-config').safeWriteFlag('$HOME/.claude/.caveman-active','full')"
This prints [caveman] safeWriteFlag: … messages to stderr explaining rejection reasons, such as symlink detection or permission errors.
Fixing Mode-Tracker stdin Errors in caveman-mode-tracker.js
The mode-tracker reads JSON payloads from Claude Code via stdin. If the parent process crashes or pipes break, Node emits an 'error' event that aborts the hook unless handled properly.
According to src/hooks/caveman-mode-tracker.js (lines 23-27), the guard code is:
process.stdin.on('error', () => process.exit(0));
Symptom: Hooks exit with non-zero codes after IDE crashes or sudden terminations.
- Cause: The error listener is missing or overwritten by custom modifications.
- Fix: Verify the file contains the two lines above; removal reintroduces the failure.
Symptom: /caveman-stats returns "could not run stats script".
- Cause: The
execFileSynccall (lines 88-90) timed out after the default 5-second limit. - Fix: Ensure Node can spawn child processes:
node src/hooks/caveman-stats.js.
Test the mode-tracker manually with a sample payload:
echo '{"prompt":"/caveman"}' | node src/hooks/caveman-mode-tracker.js
Valid output includes a JSON line with "hookEventName":"UserPromptSubmit" and the active mode context.
Resolving Stats-Script Failures for /caveman-stats
caveman-stats.js aggregates token counts from session history stored in $CLAUDE_CONFIG_DIR/.caveman-history.jsonl. Failures occur when the history file is missing, corrupted, or contains malformed JSON lines.
Diagnostic steps:
# Inspect the raw history file
cat $HOME/.claude/.caveman-history.jsonl | head
# Run stats directly with verbose output
node src/hooks/caveman-stats.js --session-file ./tests/fixture-session.json --since 1d
If the script prints "could not run stats script", check the parsing logic around line 320 in src/hooks/caveman-stats.js for malformed JSON entries. The script catches parsing errors and returns the generic message to prevent crashes, but the underlying cause is usually a corrupted history line.
Handling Installation and Version Errors
The one-liner installer (install.sh) fetched from GitHub requires Node ≥ 18 and stable network access.
Common failure points:
- Network errors:
curlreturns non-200 status, throwingnew Error('curl failed …')from the installer. - Node version: The script checks Node version at the top of
install.shand aborts if < 18.
Verify installation integrity:
bash -x <(curl -fsSL https://raw.githubusercontent.com/JuliusBrussee/caveman/main/install.sh)
The -x flag shows execution line-by-line, revealing failures around line 110 in bin/install.js (referenced in the installer). Ensure your system has curl installed and Node 18+ available.
Ensuring Mode Persistence Across Sessions
If modes revert to default between sessions, verify persistence through three checkpoints:
- Flag file survival: Confirm
$HOME/.claude/.caveman-activepersists after process termination. - External interference: Check for stale
caveman-shrinkwrappers or other tools that might delete the flag. - Mode-transition log: Verify
.caveman-mode-log.jsonlexists in$HOME/.claude. This log is created byrecordModeChange(lines 311-321 incaveman-config.js) and is essential forcaveman-statsto attribute token savings correctly.
If the log is empty, Caveman may be running in a sandbox that blocks file writes. Check filesystem permissions on the $HOME/.claude directory.
Summary
- Flag-file issues are the root cause of most "Caveman not working" symptoms—verify permissions and symlink status with
ls -land enableCAVEMAN_DEBUG=1for detailed rejection reasons. - stdin errors in the mode-tracker require the specific error handler
process.stdin.on('error', () => process.exit(0))to prevent non-zero exits during IDE crashes. - Stats failures typically indicate corrupted JSON lines in
.caveman-history.jsonlor missing history files—inspect the raw file and testcaveman-stats.jsdirectly. - Installation failures require Node ≥ 18 and stable network connectivity—use
bash -xwith the installer to pinpoint exact failure lines. - Mode persistence depends on the flag file and mode-log surviving between sessions—ensure write permissions exist for
$HOME/.claude.
Frequently Asked Questions
Why does Caveman silently fail to change modes when I type /caveman ultra?
Silent failures occur when safeWriteFlag in src/hooks/caveman-config.js rejects the write operation due to safety checks. The function silently returns if the target file is a symlink, resides in an unsafe directory, or lacks proper permissions. Set CAVEMAN_DEBUG=1 before running the command to see the specific rejection reason printed to stderr.
How do I fix the "could not run stats script" error when running /caveman-stats?
This error typically indicates either a corrupted entry in $HOME/.claude/.caveman-history.jsonl or a timeout during the execFileSync call in caveman-mode-tracker.js. First, inspect the history file for malformed JSON lines using head and cat. If the file is valid, verify that node src/hooks/caveman-stats.js executes successfully when called directly, ensuring your Node environment can spawn child processes within the 5-second default timeout.
What causes Caveman to lose its mode setting between Claude Code sessions?
Mode persistence depends on the flag file at $HOME/.claude/.caveman-active surviving process termination. If the mode reverts to default, check that the file contains your intended mode string using cat, verify that no sandbox or cleanup script is deleting the file, and ensure the mode-transition log at .caveman-mode-log.jsonl exists and is writable. The recordModeChange function (lines 311-321 in caveman-config.js) writes this log, and its absence indicates filesystem permission issues.
Why does the Caveman installer fail with a curl error or Node version warning?
The install.sh script requires Node.js version 18 or higher and uses curl to fetch resources from GitHub. Network failures trigger new Error('curl failed …') within the installer script, while version checks abort execution early if Node is outdated. Run bash -x <(curl -fsSL ...) to see the exact execution line that fails, and upgrade Node to version 18+ before attempting installation.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →