Documentation
¶
Overview ¶
Package claude implements adapters.HarnessAdapter for Claude Code.
Package placement: internal/adapters/claude/ (internal/adapters/ hosts the shared interface; each harness sub-package hosts its implementation).
Stopping convention (Phase 3-b): SIGUSR1 is delivered to the runtime process group by api.JobLifecycle.SignalJobRuntime. Run()'s signal.Notify(SIGUSR1) handler intercepts it and forwards SIGTERM to the claude child only, normalising the resulting exit status into Result.StoppedByDaemon=true. There is no separate "stop agent" entry on the adapter — the daemon owns the signal, the adapter owns the response.
Index ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
This section is empty.
Types ¶
type Adapter ¶
type Adapter struct{}
Adapter implements adapters.HarnessAdapter for Claude Code.
func (*Adapter) Bindings ¶
Bindings declares the host bind-mounts claude.Adapter.Run() needs inside the sandbox.
Phase 4 PR3 (docs/plans/home-workspace-volume.md) retires every entry this method used to return: ~/.local/bin (ro, CLI dir + PATH), ~/.local/share/claude (ro), ~/.claude (rw), ~/.claude.json (rw file), and the per-embedded-skill ~/.local/share/boid/skills/<name> -> ~/.claude/skills/<name> binds. All of that state now lives directly in the sandbox's $HOME, which Runner.Dispatch (internal/dispatcher/workspace_home.go) bind-mounts from a persistent per-workspace home directory instead of a fresh tmpfs — so ~/.claude, ~/.claude.json etc. simply already exist at those paths without any adapter-declared bind. The claude CLI binary itself is expected to be installed into that same workspace home by the workspace's init.sh (see the plan doc's init.sh 契約 section); a missing binary now fails fast with an explicit message from Run() (run.go) instead of silently falling back to a bind that no longer exists.
Embedded skills are synced into the workspace home's ~/.claude/skills/ by skills.DeployAll (internal/skills/deploy.go), called from Runner.Dispatch right after the workspace home is resolved — copy-based distribution replaces the bind-mount this method used to declare per skill.
The HarnessAdapter interface still requires this method; returning an empty slice keeps the contract satisfied for any future $HOME-independent bind a harness might need.
func (*Adapter) Run ¶
Run is the agent-process entry point. See RunContext / Result in package adapters for the I/O contract. Run owns:
- generating a fresh session id and persisting it to payload_patch.json up front so the jsonl transcript path is recorded in the task artifact even when the child terminates abnormally (SIGKILL, OOM)
- prompt selection (UserAnswer → bootstrap, otherwise /boid-task or "")
- claude argv construction (always --session-id, never --resume)
- signal.Notify(SIGUSR1 / SIGWINCH) and forwarding to the child
- exit code normalisation (StoppedByDaemon → 0)
- IS_SANDBOX=1 env injection (Claude CLI 2.1.181+ uid 0 bypass)
Session-id resume was removed: reopen and Q&A both start a fresh claude process. The agent (via the /boid-task skill) recovers general task/instructions/environment context via the `boid task current` / `instructions` / `env` broker RPCs on cold start (Phase 5b — the dispatch-time $HOME/.boid/context/*.yaml file distribution these replaced was retired by the Phase 5b PR6 cutover; PR3, which predates PR6, only cut over the one payload field Run() itself needs directly: the prior artifact.claude_code.sessions[] entries it merges the fresh session id into, which come from the `boid task payload` broker RPC — see readSessionsFromRPC below).