EnerBrain Agency· Documentation
Adapters › Agent Adapters

Claude Code

Claude Code local adapter setup and configuration

The claude_local adapter runs Anthropic's Claude Code CLI locally. It supports session persistence, skills injection, and structured output parsing.

Quota waits

Claude ACP runs that end with a typed provider-quota error retain the quota classification and any parsed reset time. Recovery waits until that time, or uses its existing one-hour quota backoff when no reset time is available. This includes the Claude bridge's typed “The Claude account has no available quota.” fallback, which carries no reset timestamp. The adapter inspects the terminal provider message in memory; the run result and run log retain only the generic failure message, recovery labels, and reset timestamp. Context, turn, rate, and configured budget limits are not treated as subscription quota exhaustion merely because ACP labels them limit.

Prerequisites

Configuration Fields

Field Type Required Description
cwd string Yes Working directory for the agent process (absolute path; created automatically if missing when permissions allow)
model string No Claude model to use (default: claude-opus-5)
promptTemplate string No Prompt used for all runs
env object No Environment variables (supports secret refs)
timeoutSec number No Process timeout (0 = no timeout)
graceSec number No Grace period before force-kill
maxTurnsPerRun number No Max agentic turns per heartbeat (defaults to 300)
dangerouslySkipPermissions boolean No Skip permission prompts (default: true); required for headless runs where interactive approval is impossible

Default model

An omitted, empty, or whitespace-only model uses Claude Opus 5 (claude-opus-5) on both the CLI and ACP engines. This also applies to existing agents with an unset model, including agents created through the API and agents running in sandboxes. No database migration is needed. The editor shows the EnerBrain Agency default and leaves the setting unset until you select a model.

An explicit model takes precedence over ANTHROPIC_MODEL. When only ANTHROPIC_MODEL is configured, the adapter keeps that override. Bedrock and Vertex configurations without an explicit model keep their provider-specific default because those providers use different model IDs. Host environment settings apply only to local targets when resolving the model.

The default does not change explicitly configured agent models or the separate EnerBrain Agency Runner's qualified provider profiles.

Prompt Templates

Templates support {{variable}} substitution:

Variable Value
{{agentId}} Agent's ID
{{companyId}} Company ID
{{runId}} Current run ID
{{agent.name}} Agent's name
{{company.name}} Company name

Session Persistence

The adapter persists Claude Code session IDs between heartbeats. On the next wake, it resumes the existing conversation so the agent retains full context.

Session resume is cwd-aware: if the agent's working directory changed since the last run, a fresh session starts instead.

If resume fails with an unknown session error, the adapter automatically retries with a fresh session.

Poisoned previous_message_id (recovery)

Symptom in logs / issue thread:

API Error: 400 diagnostics.previous_message_id: must be the `id` from a prior /v1/messages response (starts with `msg_`)

What it means: the on-disk Claude Code transcript JSONL for that session contains a malformed (non-msg_-prefixed) previous_message_id. Anthropic's /v1/messages rejects every resume attempt against that transcript with a deterministic 400. Without guards, EnerBrain Agency would re-persist the same poisoned session id and the issue is stranded permanently — see RED-976 / RED-978.

What the adapter does automatically:

  1. Auto-rotate on resume. If a --resume attempt returns this 400, the adapter retries once with a fresh session, deletes the poisoned <session>.jsonl from the local Claude config dir (best effort), and uses the fresh session id going forward.
  2. Validate-before-persist. A result that carries this 400 never gets its session_id written back to the task session store, even if Claude Code emits one in the result event. The adapter returns sessionId: null, sessionParams: null, and errorCode: "claude_poisoned_previous_message_id".
  3. Clear-on-error. The adapter sets clearSession: true on the result, which causes the heartbeat service to drop any persisted session row for that issue (clearTaskSessions). The next continuation starts from a clean slate.

On-call checklist if you see this in production:

Skills Injection

The adapter creates a temporary directory with symlinks to EnerBrain Agency skills and passes it via --add-dir. This makes skills discoverable without polluting the agent's working directory.

Remote credential ownership

When no API key or CLAUDE_CODE_OAUTH_TOKEN is configured, claude_local uses a snapshot-owns-auth topology for managed sandbox execution targets. When the run uses a sandbox execution target and no explicit CLAUDE_CONFIG_DIR is configured, EnerBrain Agency creates a remote CLAUDE_CONFIG_DIR under the run's Claude runtime directory. It uploads sanitized host-side settings such as settings.json and CLAUDE.md, but the managed seed does not upload host Claude credential files.

After the seed is copied, the remote materialization command checks the execution target's own $HOME/.claude directory. For each missing credential file, it copies .credentials.json or credentials.json from that remote home into the managed CLAUDE_CONFIG_DIR. That means credentials baked into the sandbox image win for managed remote Claude runs.

Worked example: a sandbox image contains $HOME/.claude/.credentials.json from its own Claude Code login. EnerBrain Agency starts a managed remote claude_local run, uploads only the sanitized config seed, and sets CLAUDE_CONFIG_DIR to the remote runtime config path. Because the managed config has no credential file, the adapter copies the sandbox image's $HOME/.claude/.credentials.json into that path before invoking Claude. The sandbox snapshot owns the credential for the run.

This differs from codex_local, where an EnerBrain Agency-managed sandbox run uploads a host-owned CODEX_HOME/auth.json and therefore shadows any Codex login already present inside the sandbox image.

For manual local CLI usage outside heartbeat runs (for example running as claudecoder directly), use:

npx paperclipai agent local-cli claudecoder --company-id <company-id>

This installs EnerBrain Agency skills in ~/.claude/skills, creates an agent API key, and prints shell exports to run as that agent.

Environment Test

Use the "Test Environment" button in the UI to validate the adapter config. It checks:

The probe sees the same layered env as a real run: when an environment is selected, its environment variables (secret refs included) are resolved and merged under the adapter config's env, so environment-level auth is reflected in the test result. A secret binding that is missing surfaces as an environment_env_binding_missing failure instead of a silently passing probe.