# Caveman Configuration Resolution Order: How Default Modes Are Determined

> Understand Caveman configuration resolution order. Discover how environment variables, repo-local, and user-level configs determine default modes, with a built-in fallback.

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

---

**Caveman resolves its default mode through a four-tier priority chain: environment variables override repo-local configs, which override user-level configs, with a built-in fallback to "full" mode.**

The JuliusBrussee/caveman project implements a deterministic configuration system that determines which operation mode (`off`, `lite`, `full`, `ultra`, etc.) the tool uses at startup. Understanding the Caveman configuration resolution order is essential for managing different behaviors across local development, CI/CD pipelines, and personal workstations.

## The Four-Tier Resolution Hierarchy

### 1. Environment Variable (Highest Priority)

Caveman checks the `CAVEMAN_DEFAULT_MODE` environment variable first. If set to a valid mode—such as `off`, `lite`, `full`, or `ultra`—this value wins outright regardless of any configuration files present.

### 2. Repository-Local Configuration

If no environment variable is set, Caveman searches for repo-local settings by walking up the directory tree from the current working directory. It looks for [`.caveman/config.json`](https://github.com/JuliusBrussee/caveman/blob/main/.caveman/config.json) or [`.caveman.json`](https://github.com/JuliusBrussee/caveman/blob/main/.caveman.json) in each directory until reaching the filesystem root. The first file found containing a valid `defaultMode` field determines the behavior.

### 3. User-Level Configuration File

When neither environment variables nor repo-local configs are present, Caveman checks per-user defaults. On Unix-like systems, it reads `$XDG_CONFIG_HOME/caveman/config.json` (or `~/.config/caveman/config.json` if `XDG_CONFIG_HOME` is unset). On Windows, it checks `%APPDATA%\caveman\config.json`.

### 4. Built-in Fallback Default

If all preceding sources fail to yield a valid mode, Caveman defaults to `"full"` mode as the safe baseline.

## Core Implementation in src/hooks/caveman-config.js

The resolution logic is implemented in [`src/hooks/caveman-config.js`](https://github.com/JuliusBrussee/caveman/blob/main/src/hooks/caveman-config.js), specifically within the `getDefaultMode()` function. This module also defines `VALID_MODES` to ensure only accepted strings are recognized:

```javascript
function getDefaultMode() {
  // 1️⃣ env var
  const envMode = process.env.CAVEMAN_DEFAULT_MODE;
  if (envMode && VALID_MODES.includes(envMode.toLowerCase())) {
    return envMode.toLowerCase();
  }

  // 2️⃣ repo‑local config
  const repoConfigPath = findRepoConfigPath(process.cwd());
  if (repoConfigPath) {
    const repoMode = readModeFromConfigFile(repoConfigPath);
    if (repoMode) return repoMode;
  }

  // 3️⃣ user config
  const userMode = readModeFromConfigFile(getConfigPath());
  if (userMode) return userMode;

  // 4️⃣ fallback
  return 'full';
}

```

The helper functions `findRepoConfigPath()` and `readModeFromConfigFile()` handle the directory traversal and JSON parsing, while `getConfigPath()` determines the appropriate user-level directory based on platform conventions. The test suite in [`tests/test_repo_local_config.js`](https://github.com/JuliusBrussee/caveman/blob/main/tests/test_repo_local_config.js) verifies this hierarchy, ensuring that environment variables correctly override file-based configurations.

## Practical Configuration Examples

### Override with Environment Variable

Set the mode for a single invocation without modifying any files:

```bash
CAVEMAN_DEFAULT_MODE=lite caveman run

```

### Project-Specific Defaults

Create [`.caveman/config.json`](https://github.com/JuliusBrussee/caveman/blob/main/.caveman/config.json) in your project root to ensure all team members use the same mode:

```json
{
  "defaultMode": "commit"
}

```

Running `caveman` from anywhere inside the project directory tree will start in **commit** mode unless overridden by the environment variable.

### Personal Defaults

Configure your user-level file at `~/.config/caveman/config.json` (Linux/macOS) or `%APPDATA%\caveman\config.json` (Windows):

```json
{
  "defaultMode": "review"
}

```

### Fallback Behavior

Without any configuration, Caveman automatically uses `"full"` mode:

```bash
caveman status  # Executes in "full" mode

```

## Summary

- **Environment variables take precedence**: `CAVEMAN_DEFAULT_MODE` overrides all other sources.
- **Repo-local configs are priority two**: Files named [`.caveman/config.json`](https://github.com/JuliusBrussee/caveman/blob/main/.caveman/config.json) or [`.caveman.json`](https://github.com/JuliusBrussee/caveman/blob/main/.caveman.json) in the project hierarchy apply next.
- **User-level configs provide personal defaults**: Located in XDG config directories or Windows AppData.
- **Safe fallback**: The built-in default is `"full"` mode when no other configuration exists.
- **Source location**: The `getDefaultMode()` function in [`src/hooks/caveman-config.js`](https://github.com/JuliusBrussee/caveman/blob/main/src/hooks/caveman-config.js) implements this hierarchy.

## Frequently Asked Questions

### What is the Caveman configuration resolution order?

Caveman resolves configuration through a strict four-level hierarchy: environment variables (`CAVEMAN_DEFAULT_MODE`) are checked first, followed by repository-local config files ([`.caveman/config.json`](https://github.com/JuliusBrussee/caveman/blob/main/.caveman/config.json) or [`.caveman.json`](https://github.com/JuliusBrussee/caveman/blob/main/.caveman.json)), then user-level config files (`~/.config/caveman/config.json` or `%APPDATA%\caveman\config.json`), and finally falls back to the built-in default of `"full"` mode.

### Where does Caveman look for repository-local configuration?

Caveman searches for [`.caveman/config.json`](https://github.com/JuliusBrussee/caveman/blob/main/.caveman/config.json) or [`.caveman.json`](https://github.com/JuliusBrussee/caveman/blob/main/.caveman.json) starting from the current working directory and walking upward through parent directories until reaching the filesystem root. The first valid file encountered in this traversal determines the configuration.

### How do I set a system-wide default mode for Caveman?

Set the `CAVEMAN_DEFAULT_MODE` environment variable in your shell profile or system environment settings. Alternatively, create a user-level config file at `~/.config/caveman/config.json` on Unix systems or `%APPDATA%\caveman\config.json` on Windows to apply defaults across all projects that lack repo-specific configurations.

### What happens if I specify an invalid mode in my config file?

Invalid mode values are ignored during the resolution process. If a config file contains an invalid `defaultMode`, Caveman continues to the next level in the hierarchy. If no valid mode is found throughout the entire chain, the tool defaults to `"full"` mode.