Skip to main content
@anthropic-ai/claude-code (v2.1.126+). Production-ready in Crewship since day one; the canonical reference for what every other adapter targets for parity.

Install

Pre-installed in every seeded crew via the ghcr.io/devcontainers-extra/features/claude-code:2 devcontainer feature. To pull manually:

Auth

Two modes, both supported: Crewship’s sidecar reverse-proxy injects the API key into api.anthropic.com requests so the agent container never sees the raw token. OAuth tokens flow through the HTTPS CONNECT tunnel directly (sidecar passes through, Claude Code sets Authorization: Bearer itself).

Models

Legacy claude-opus-4-6 / 4-5 / 4-1, claude-sonnet-4-5, claude-opus-4-5 still selectable. Claude 4 (claude-*-4-20250514) retires 2026-06-15.

Command shape

Crewship’s adapter builds:
--bare is deliberately not passed, on any auth path. It reads like the isolation flag for scripted calls, but it also replaces the built-in tool catalogue with {Bash, Edit, Read}, and --tools can only subtract from that set — never add back. Measured against 2.1.226 with the same --tools value in every row: --bare was previously appended for API-key credentials only — it was already dropped for OAuth, whose auth contract it breaks (it strictly requires ANTHROPIC_API_KEY or an apiKeyHelper via --settings, and never reads CLAUDE_CODE_OAUTH_TOKEN or the keychain). So every API-key run silently lost Write, Glob, Grep, WebFetch and WebSearch whatever its tool profile said. What --bare was covering is now covered explicitly, verified against 2.1.226 on a project carrying both a CLAUDE.md and a .claude/settings.json declaring a SessionStart hook:
  • --setting-sources "" — the hook did not fire, and the model answered NO when asked whether the repo’s CLAUDE.md marker was in its context (with and without --system-prompt). This flag is load-bearing: it is what stands between an agent and a cloned repository’s hooks. It also suppresses project-level skill discovery, which is why materialised SKILL.md files are not natively discovered today.
  • --strict-mcp-config — only the servers Crewship wrote in .mcp.json load.
  • --tools — keeps the harness catalogue out of the model’s context; that catalogue is present without --bare, so this flag is what does that work now.
See claudeCodeAdapter.BuildCommand in internal/orchestrator/adapter_claude.go. --tools is always passed with the agent’s per-profile built-in allowlist (MINIMALRead,Glob,Grep,ToolSearch; CODING+Write,Edit,Bash,WebFetch,WebSearch; FULL+NotebookEdit). This removes harness-internal tools (TaskCreate, Agent, Workflow, Cron*, …) that have no Crewship backing from the agent’s context. ToolSearch is kept so that large MCP catalogues stay reachable if the CLI defers them rather than listing them in context; MCP tools themselves are not affected by --tools (measured on 2.1.226: an 80-tool MCP server is listed in full even with no ToolSearch present). See Tool profiles & the built-in tool allowlist.

MCP

Configured at /crew/agents/<slug>/.mcp.json. Standard schema:
Env-var refs ${VAR} resolve from the agent container’s process env at MCP server spawn time. Crewship’s injectMCPCredentialEnvVars populates them from workspace credentials.
setupMCPConfig auto-injects two sidecar-hosted servers into .mcp.json: crewship-memory (http://127.0.0.1:9119/mcp/memory/<slug>) and crewship-routines (.../mcp/routines) — so the model gets native memory.* and routine-authoring tools even when no other MCP source is declared. This is why --mcp-config is always passed. A user-declared server of the same name wins.

Memory

Same canonical memory file set as every other adapter — AGENTS.md, CLAUDE.md, GEMINI.md, .cursor/rules/crewship.md, .factory/AGENTS.md — written to /output/<slug>/. Even though --setting-sources "" suppresses Claude Code’s own CLAUDE.md discovery (the system prompt arrives via --system-prompt), Crewship writes the file so a customer SSH-ing into the container sees the same context the agent operates on.

Output stream

JSONL events documented at code.claude.com/docs/en/cli-reference. Crewship parses every documented type:
  • system (subtype init / api_retry)
  • stream_event (text / thinking deltas)
  • assistant (tool_use, tool_result blocks)
  • tool / user (tool result blocks)
  • result (terminal envelope with usage + cost)
system/init also carries session provenance, all recorded on the event’s metadata: The result envelope adds terminal_reason, api_error_status, stop_reason, session_id and permission_denials. terminal_reason is not derivable from subtype: a hard authentication failure arrives as subtype: "success" with is_error: true and terminal_reason: "api_error", so in-band failures are labelled from terminal_reason when the subtype names nothing.

Where the provenance lands

Parsing a field is not the same as being able to reach it, so each of these has a surface: Two deliberate asymmetries in what gets stored:
  • api_key_source is never stored verbatim. It is an upstream field we do not control, and everything above is persisted, so only a member of a known set is kept; anything else is recorded as other.
  • mcp_server_errors[].message reaches the chat card but not the run record or the journal. It is CLI-supplied free text describing a config file, and the credential scrubber only rewrites an event’s Content — it never touches Metadata. The journal is hash-chained and cannot be redacted after the fact, so the durable copies carry the server name and the error category only. The message stays where it is bounded and ephemeral.

Troubleshooting

claude: not found — devcontainer feature didn’t install; check crew devcontainer_config for ghcr.io/devcontainers-extra/features/claude-code:2. 401 from Anthropic — credential not assigned to agent. Check crewship credential assign <name> <agent> and verify the credential has type=API_KEY or type=AI_CLI_TOKEN with provider=ANTHROPIC. Model retires 2026-06-15 — UI shows a badge on retiring models (claude-3.5-, claude--4-20250514). Migrate to claude-sonnet-4-6 or claude-opus-4-7.