JuliusBrussee/caveman · error
Cave Build is Pi-specific; refusing to attach its identity t
Error message
Cave Build is Pi-specific; refusing to attach its identity to Claude Code execution
What it means
After the lock validates, its JSON is parsed and harness.id must equal "claude". Cave Build locks carry a harness identity and the feature is currently Pi-specific; attaching a non-claude (e.g. "pi") lock identity to a Claude Code launch is refused to prevent misattributed execution and billing.
Source
Thrown at packages/cli/src/index.ts:5055
throw new Error("Cave Build lock exists but caveman-agent checker is unavailable; refusing Claude launch before model spend");
}
const invocation = portableInvocation(checker, ["check"]);
const checked = spawnSync(invocation.command, invocation.args, {
cwd: process.cwd(),
env: process.env,
encoding: "utf8",
});
if (checked.error || checked.status !== 0) {
const detail = String(checked.stderr || checked.error?.message || "lock check failed").trim();
throw new Error(`Cave Build lock is stale or invalid; refusing Claude launch before model spend: ${detail}`);
}
const rawAfterCheck = readFileSync(lockPath, "utf8");
if (rawAfterCheck !== rawBeforeCheck) {
throw new Error("Cave Build lock changed during validation; refusing Claude launch before model spend");
}
const lock = JSON.parse(rawAfterCheck) as { harness?: { id?: unknown } };
if (lock.harness?.id !== "claude") {
throw new Error(
"Cave Build is Pi-specific; refusing to attach its identity to Claude Code execution",
);
}
throw new Error(
"Claude-specific Cave Build execution is unavailable until model, reasoning, budget, recovery, and wire selectors are enforced",
);
}
function firstEnvSecret(env: NodeJS.ProcessEnv, keys: string[]): string | undefined {
for (const key of keys) {
const value = env[key];
if (typeof value === "string" && value.trim()) return value.trim();
}
return undefined;
}
function maybeWarnHermesMissingKey(agent: AgentProfile | undefined, gw = gatewayURL()) {
if (agent?.id !== "hermes") return;View on GitHub (pinned to 27d5a3981a)
Solutions
- Remove or archive .caveman/agent.lock.json from the Pi session before launching Claude
- Use a separate working directory for Claude vs Pi Cave Build sessions
- Regenerate the lock with harness.id "claude" if your workflow requires a lock for Claude
Example fix
# before
# .caveman/agent.lock.json: { "harness": { "id": "pi" } }
claude # Error: Cave Build is Pi-specific
# after
rm .caveman/agent.lock.json
claude Defensive patterns
Strategy: validation
Validate before calling
import { readFileSync } from "node:fs";
const lock = JSON.parse(readFileSync(".caveman/agent.lock.json", "utf8"));
if (lock.harness?.id !== "claude") {
throw new Error(`lock harness is ${lock.harness?.id ?? "unset"}; remove the lock before launching Claude`);
} Type guard
function isClaudeLock(v: unknown): v is { harness: { id: "claude" } } {
return !!v && typeof v === "object"
&& typeof (v as any).harness === "object" && (v as any).harness !== null
&& (v as any).harness.id === "claude";
} Try / catch
try {
claudeCaveBuildEnv();
} catch (error) {
if (/Pi-specific/.test((error as Error).message)) {
rmSync(".caveman/agent.lock.json"); // Pi lock does not belong to a Claude launch
claudeCaveBuildEnv();
} else throw error;
} Prevention
- Use separate project directories (or clean locks) when alternating Pi and Claude
- Check lock.harness.id before launching Claude in shared workspaces
- Add .caveman/agent.lock.json to per-machine ignore so it is not cloned around
When it happens
Trigger: Launching Claude via the caveman launcher in a project whose .caveman/agent.lock.json has harness.id set to anything other than "claude" (typically "pi" from a Cave Build run).
Common situations: Switching between Pi and Claude harnesses in the same project; reusing a project directory that previously ran Cave Build with Pi.
Related errors
- Cave Build lock exists but caveman-agent checker is unavaila
- Cave Build lock is stale or invalid; refusing Claude launch
- Cave Build lock changed during validation; refusing Claude l
- Claude-specific Cave Build execution is unavailable until mo
- lock disappeared during validation
AI-assisted analysis of JuliusBrussee/caveman@27d5a3981a (2026-08-15).
Data as JSON: /api/errors/8fbbc8df96c8651f.
Report an issue: GitHub.