# How to Troubleshoot Common Caveman Errors: A Complete Diagnostic Guide

> Fix common Caveman errors by diagnosing flag-file permissions, stdin handling, and corrupted history files. This guide offers solutions for seamless operation.

- Repository: [Julius Brussee/caveman](https://github.com/JuliusBrussee/caveman)
- Tags: how-to-guide
- Published: 2026-07-05

---

**Most Caveman failures stem from three sources: flag-file permission issues in [`caveman-config.js`](https://github.com/JuliusBrussee/caveman/blob/main/caveman-config.js), stdin handling errors in [`caveman-mode-tracker.js`](https://github.com/JuliusBrussee/caveman/blob/main/caveman-mode-tracker.js), or corrupted history files affecting [`caveman-stats.js`](https://github.com/JuliusBrussee/caveman/blob/main/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`](https://github.com/JuliusBrussee/caveman/blob/main/src/hooks/caveman-config.js)** – Handles **configuration and flag handling**, including `safeWriteFlag` and `readFlag` functions that manage the active-mode flag file.
- **[`src/hooks/caveman-mode-tracker.js`](https://github.com/JuliusBrussee/caveman/blob/main/src/hooks/caveman-mode-tracker.js)** – Runs on every user prompt to parse `/caveman` commands, update the flag file, and emit the "CAVEMAN MODE ACTIVE" notice.
- **[`src/hooks/caveman-stats.js`](https://github.com/JuliusBrussee/caveman/blob/main/src/hooks/caveman-stats.js)** – Computes token savings, executes `/caveman-stats`, and processes auxiliary commands like `/caveman-commit` and `/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`](https://github.com/JuliusBrussee/caveman/blob/main/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:** `/caveman` commands 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).

- **Symptom:** Mode appears as `off` or `lite` when you requested `full`.
  - **Check:** Inspect the current value: `cat $HOME/.claude/.caveman-active` and verify it matches your intended mode.

- **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'))"`.

**Enable debug output** to see why writes fail silently:

```bash
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`](https://github.com/JuliusBrussee/caveman/blob/main/src/hooks/caveman-mode-tracker.js) (lines 23-27), the guard code is:

```javascript
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 `execFileSync` call (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:

```bash
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`](https://github.com/JuliusBrussee/caveman/blob/main/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:**

```bash

# 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`](https://github.com/JuliusBrussee/caveman/blob/main/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`](https://github.com/JuliusBrussee/caveman/blob/main/install.sh)) fetched from GitHub requires Node ≥ 18 and stable network access.

**Common failure points:**

- **Network errors:** `curl` returns non-200 status, throwing `new Error('curl failed …')` from the installer.
- **Node version:** The script checks Node version at the top of [`install.sh`](https://github.com/JuliusBrussee/caveman/blob/main/install.sh) and aborts if < 18.

**Verify installation integrity:**

```bash
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`](https://github.com/JuliusBrussee/caveman/blob/main/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:

1. **Flag file survival:** Confirm `$HOME/.claude/.caveman-active` persists after process termination.
2. **External interference:** Check for stale `caveman-shrink` wrappers or other tools that might delete the flag.
3. **Mode-transition log:** Verify `.caveman-mode-log.jsonl` exists in `$HOME/.claude`. This log is created by `recordModeChange` (lines 311-321 in [`caveman-config.js`](https://github.com/JuliusBrussee/caveman/blob/main/caveman-config.js)) and is essential for `caveman-stats` to 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 -l` and enable `CAVEMAN_DEBUG=1` for 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.jsonl` or missing history files—inspect the raw file and test [`caveman-stats.js`](https://github.com/JuliusBrussee/caveman/blob/main/caveman-stats.js) directly.
- **Installation failures** require Node ≥ 18 and stable network connectivity—use `bash -x` with 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`](https://github.com/JuliusBrussee/caveman/blob/main/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`](https://github.com/JuliusBrussee/caveman/blob/main/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`](https://github.com/JuliusBrussee/caveman/blob/main/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`](https://github.com/JuliusBrussee/caveman/blob/main/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.