JuliusBrussee/caveman · error · Error

native integration postflight is

Error message

${agent} native integration postflight is ${status.state}

What it means

Thrown by verifyAgentNativeBundle during `caveman setup --agent-native` postflight when the native integration status for the agent (claude or codex) is anything other than "installed" after setup supposedly completed. The CLI verifies that the native integration actually took hold; if it didn't, the bundle verification fails loudly rather than leaving a half-configured agent.

Solutions

  1. Run `caveman setup --agent-native <agent>` again after fixing any write-permission issues so the install step can complete.
  2. Verify the agent binary/config exists (e.g. `claude --version`, check ~/.claude or ~/.codex) and install/update the agent if missing.
  3. Check nativeIntegrationStatus output for the agent to see the failing state and address the underlying cause (permissions, missing binary, unsupported agent version).
  4. Use `caveman setup --agent-native <agent> --remove` to clear partial state, then re-run setup.

Example fix

// before: setup proceeds even though agent binary absent
$ caveman setup --agent-native claude
// after: ensure agent is installed first
$ claude --version || npm install -g @anthropic-ai/claude-code
$ caveman setup --agent-native claude
Defensive patterns

Strategy: validation

Validate before calling

import { nativeIntegrationStatus } from "caveman/cli";
const status = nativeIntegrationStatus("claude");
if (status.state !== "installed") {
  console.error(`native integration not ready: ${status.state}`);
  process.exit(1);
}

Try / catch

try {
  verifyAgentNativeBundle(agent, journal, cloudMcp);
} catch (err) {
  console.error(`postflight failed: ${(err as Error).message}. Re-run: caveman setup --agent-native ${agent}`);
  process.exitCode = 1;
}

Prevention

When it happens

Trigger: Running `caveman setup --agent-native claude` (or codex) where nativeIntegrationStatus(agent) returns a state like "not-installed", "partial", or "error" immediately after the install step — e.g. the agent's config file was not written or the native marker is missing.

Common situations: Agent CLI not installed or upgraded to an incompatible version that moved its config location; read-only home directory preventing config writes; a prior failed setup left partial state; running as a different user than the one whose config was modified.

Understand the failure class

Background: "Invalid state transition" errors: "status must be X, actually Y", "already rejected/charging/uninstalled", "cannot ... while running" — what they mean when a library rejects your call — this error's family across 31 libraries.

Related errors


AI-assisted analysis of JuliusBrussee/caveman@3ee70a1026 (2026-09-20). Data as JSON: /api/errors/308c7d07d03af8f9. Report an issue: GitHub.

Appendix: source

Thrown at packages/cli/src/index.ts:2906

  }
}

function installAgentNativeBundleSkills(agent: "claude" | "codex", journal: AgentNativeBundleJournal): void {
  const originals = new Map(journal.skills.map((skill) => [skill.file, skill.before_base64]));
  journal.skills = agentNativeSkillFiles(agent).map(({ file, body }) => {
    mkdirSync(dirname(file), { recursive: true });
    atomicWriteFile(file, Buffer.from(body));
    return {
      file,
      before_base64: originals.get(file) ?? null,
      after_sha256: bytesHash(Buffer.from(body)),
    };
  });
}

function verifyAgentNativeBundle(agent: "claude" | "codex", journal: AgentNativeBundleJournal, cloudMcp: { command: string; args: string[] }): void {
  const status = nativeIntegrationStatus(agent);
  if (status.state !== "installed") throw new Error(`${agent} native integration postflight is ${status.state}`);
  const marker = readMcpServerMarker(agent, "caveman-cloud");
  if (!marker || marker.command !== cloudMcp.command || JSON.stringify(marker.args) !== JSON.stringify(cloudMcp.args)) {
    throw new Error(`${agent} caveman-cloud MCP postflight mismatch`);
  }
  if (!agentNativeCloudMcpMatches(agent, cloudMcp)) {
    throw new Error(`${agent} caveman-cloud MCP registration failed exact postflight`);
  }
  for (const skill of journal.skills) {
    const current = fileBytes(skill.file);
    if (!current || bytesHash(current) !== skill.after_sha256) throw new Error(`${skill.file} failed skill postflight`);
  }
}

function removeAgentNativeBundle(agent: "claude" | "codex"): void {
  recoverPendingAgentNativeRemoval(agent);
  recoverPendingAgentNativeBundle(agent);
  const journal = readAgentNativeBundleJournal(agent);
  if (!journal) {

View on GitHub (pinned to 3ee70a1026)