# How the `/caveman` Command Persists Mode Across Session Turns

> Discover how the /caveman command persists its mode across Claude session turns by atomically writing to a hidden flag file and restoring it via the mode-tracker hook. Learn more now.

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

---

**TLDR:** The `/caveman` command persists its intensity mode across Claude session turns by atomically writing the selected mode to a hidden flag file at `~/.claude/.caveman-active` and restoring it via the mode-tracker hook on every subsequent request.

The JuliusBrussee/caveman repository implements a file-based persistence layer that allows the caveman intensity level to survive across multiple turns of a Claude conversation. Unlike ephemeral in-memory storage, this mechanism ensures your selected mode—whether `lite`, `full`, or `ultra`—remains active until explicitly changed.

## Where the Mode Is Stored

### The Flag File Location and Format

Persistence relies on a single hidden flag file located at `$CLAUDE_CONFIG_DIR/.caveman-active`, which typically resolves to `~/.claude/.caveman-active` on Unix systems. This file contains only the raw mode string (for example, `full` or `wenyan-ultra`) with no additional metadata or JSON wrapping.

### Core I/O Functions in [`caveman-config.js`](https://github.com/JuliusBrussee/caveman/blob/main/caveman-config.js)

All read and write operations are centralized in [`src/hooks/caveman-config.js`](https://github.com/JuliusBrussee/caveman/blob/main/src/hooks/caveman-config.js). The **`safeWriteFlag`** function handles atomic writes with restrictive permissions, while **`readFlag`** performs symlink-safe reads with validation.

```javascript
// From src/hooks/caveman-config.js
function safeWriteFlag(flagPath, content) {
  // Writes atomically, refuses symlinks, sets 0600 permissions
}

function readFlag(flagPath) {
  // Symlink-safe, size-capped at 64 bytes, validates against VALID_MODES
}

```

The write operation uses atomic file operations to prevent corruption during concurrent access, and the read operation enforces a 64-byte size limit—sufficient for the longest valid mode string (`wenyan-ultra`) while preventing buffer overflow attacks.

## How `/caveman` Updates the Persisted State

When you issue `/caveman <mode>` in the Claude interface, the caveman skill (documented in [`skills/caveman/README.md`](https://github.com/JuliusBrussee/caveman/blob/main/skills/caveman/README.md)) invokes `safeWriteFlag` with the requested mode. If you omit the argument, the system calls `getDefaultMode()` to resolve the default from environment variables, repository configuration, or user settings, ultimately falling back to `'full'`.

```javascript
// Internally triggered by: /caveman ultra
safeWriteFlag(path.join(claudeDir, '.caveman-active'), 'ultra');

```

This write occurs immediately upon command execution, ensuring the flag file always reflects the most recent user preference regardless of how the session terminates.

## Restoring Mode Across Session Turns

### The Mode-Tracker Hook Implementation

Every request flowing through the Claude tooling passes through the **mode-tracker** hook defined in [`src/hooks/caveman-mode-tracker.js`](https://github.com/JuliusBrussee/caveman/blob/main/src/hooks/caveman-mode-tracker.js). This hook executes automatically at the start of each turn, reading the flag file and injecting the mode into the request object.

```javascript
// From src/hooks/caveman-mode-tracker.js
const flagPath = path.join(claudeDir, '.caveman-active');
const mode = readFlag(flagPath);

if (mode) {
    request.cavemanMode = mode;   // Accessible to downstream hooks
}

// If changed during this turn, log the transition
recordModeChange(claudeDir, newMode);

```

Because the flag file lives on the local filesystem, the same value persists across process restarts, containerized environments, and multi-day sessions. The hook essentially rehydrates the session state from disk on every interaction.

## Security Safeguards for File-Based Persistence

The persistence mechanism implements multiple hardening measures to prevent privilege escalation or data exfiltration:

- **Symlink protection**: Both `safeWriteFlag` and `readFlag` reject symbolic links, preventing attackers from redirecting reads to sensitive files like `/etc/shadow` or writes to system directories.
- **Size enforcement**: The 64-byte cap in `readFlag` prevents reading arbitrary large files if a symlink bypass were ever successful.
- **Ownership verification**: When the parent directory is a symlink, the code verifies the real path's ownership matches the current user (via Unix uid or Windows home-directory checks).
- **Permission restrictions**: `safeWriteFlag` creates files with `0600` permissions, ensuring only the owner can read the current mode setting.

These safeguards ensure that **caveman command persistence** cannot be hijacked to access unauthorized system resources.

## Statistics and Mode Change Tracking

The system maintains an audit trail of mode transitions. Whenever `recordModeChange` detects a mode switch, it appends a JSON line to `$CLAUDE_CONFIG_DIR/.caveman-mode-log.jsonl`. The stats hook ([`src/hooks/caveman-stats.js`](https://github.com/JuliusBrussee/caveman/blob/main/src/hooks/caveman-stats.js)) later consumes this log to attribute token usage statistics to the correct mode, even if the active flag has been overwritten multiple times during the session.

```javascript
// Mode changes are logged for analytics
recordModeChange(claudeDir, newMode); // Writes to .caveman-mode-log.jsonl

```

This separation of concerns—current state in `.caveman-active` and historical data in `.caveman-mode-log.jsonl`—allows accurate reporting without interfering with the lightweight persistence mechanism.

## Summary

- The `/caveman` command writes the selected mode to `$CLAUDE_CONFIG_DIR/.caveman-active` using the atomic `safeWriteFlag` function.
- Each session turn restores the mode via `readFlag` in [`src/hooks/caveman-mode-tracker.js`](https://github.com/JuliusBrussee/caveman/blob/main/src/hooks/caveman-mode-tracker.js), injecting the value into `request.cavemanMode`.
- Security measures include symlink rejection, 64-byte size caps, and `0600` file permissions.
- Mode transitions are logged to `.caveman-mode-log.jsonl` for statistical analysis by [`src/hooks/caveman-stats.js`](https://github.com/JuliusBrussee/caveman/blob/main/src/hooks/caveman-stats.js).
- The persistence works across process restarts because state is maintained on the filesystem, not in memory.

## Frequently Asked Questions

### Where is the caveman mode stored between session turns?

The mode is stored in a hidden flag file at `$CLAUDE_CONFIG_DIR/.caveman-active` (typically `~/.claude/.caveman-active`). This file contains only the raw mode string and is read by the mode-tracker hook at the start of every turn to restore the previous session state.

### How does the mode-tracker hook restore the caveman setting?

The hook located in [`src/hooks/caveman-mode-tracker.js`](https://github.com/JuliusBrussee/caveman/blob/main/src/hooks/caveman-mode-tracker.js) calls `readFlag` to check the flag file on disk. If a valid mode is present, it assigns the value to `request.cavemanMode`, making it available to downstream processing hooks like compression and statistics.

### What happens if I switch modes mid-session?

When you issue a new `/caveman` command, `safeWriteFlag` immediately overwrites `.caveman-active` with the new mode. The `recordModeChange` function also appends the transition to `.caveman-mode-log.jsonl`, allowing the stats hook to accurately attribute token usage to the correct mode for that specific turn.

### Is the persistence mechanism secure against symlink attacks?

Yes. Both `safeWriteFlag` and `readFlag` in [`src/hooks/caveman-config.js`](https://github.com/JuliusBrussee/caveman/blob/main/src/hooks/caveman-config.js) explicitly reject symbolic links. Additionally, the read operation enforces a 64-byte size limit and verifies directory ownership when symlinks are present in the path, preventing unauthorized file access or data exfiltration.