claude

package
v0.2.21 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Oct 13, 2026 License: Apache-2.0 Imports: 24 Imported by: 0

Documentation

Overview

Package claude adapts headless Claude Code to the runner harness.

One Run is one `claude --print` invocation: one turn, one process, one session. The process speaks `--output-format stream-json`, which this adapter parses line by line into bounded harness.Events and one terminal harness.Result. There is no long-lived server as there is for Codex.

Credentials

Headless Claude Code authenticates through ONE environment variable, and this adapter is the only thing that ever sets it. The value is read from a runner-owned 0600 file named by Config.CredentialFile — never from the runner's own environment, which is why blockedEnvKey strips every inherited ANTHROPIC_*/CLAUDE_* variable before the child is started. Two kinds are supported:

oauth-token -> CLAUDE_CODE_OAUTH_TOKEN (produced by `claude setup-token`)
api-key     -> ANTHROPIC_API_KEY

The value never appears in an event, a blocker, a log line, an error or the capabilities response: every string that leaves this package goes through redact() first.

Isolation: what is enforced by a flag, and what is not

Enforced by flags (verified against `claude --help`, 2.1.273):

--print                       non-interactive; the workspace trust dialog is skipped
--output-format stream-json   machine-readable events instead of prose
--verbose                     required for stream-json to emit per-turn records
--permission-mode <mode>      Config.PermissionMode: acceptEdits (default) lets the
                              model edit files inside the worktree without asking;
                              bypassPermissions additionally allows every tool,
                              including arbitrary shell, and is for sandboxed hosts
--permission-prompts none     nobody to ask: anything that would still prompt is
                              DENIED. Used when Launch.Permissions is nil.
--permission-prompts host     somebody CAN be asked, and the request goes to the
                              --permission-prompt-tool below. The permission mode
                              still decides everything else; this widens nothing,
                              it only replaces a silent denial with a question.
--permission-prompt-tool      the one-tool MCP server this adapter hosts on
                              loopback for the child; see permission.go
--allowedTools <list>         Config.AllowedTools: tool patterns granted up front
                              (e.g. "Bash(git *)") so acceptEdits can run tests
--safe-mode                   disables CLAUDE.md, skills, plugins, hooks, MCP servers,
                              custom commands/agents, output styles, workflows — i.e.
                              every project-controlled code and config path. Auth,
                              model selection, built-in tools and permissions still work.
                              It is passed ONLY when there is nobody to ask: measured
                              against 2.1.281, --safe-mode disables --mcp-config
                              servers too, so it and a permission prompt tool cannot
                              both exist. See the trade documented on args().
--strict-mcp-config           no MCP server but the permission prompt one, and with
                              no --mcp-config at all, none whatsoever
--disable-slash-commands      no skills
--no-chrome                   no browser integration
--setting-sources ""          no user, project or local settings files
--session-id / --resume       the session identity is ours, never discovered

Enforced by environment (variable names verified present in the 2.1.273 binary): CLAUDE_CONFIG_DIR pins the config directory to the runner-owned home; DISABLE_AUTOUPDATER, DISABLE_TELEMETRY, DISABLE_ERROR_REPORTING, DISABLE_BUG_COMMAND, DISABLE_COST_WARNINGS and CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC turn off self-update and non-essential network traffic. The IDE integration is opt-in (--ide), so not passing it is the disabled state.

NOT available, and therefore NOT enforced:

  • No max-turns flag exists in this release, so a turn is bounded by the runner's own execution limits and by context cancellation, not by the harness.
  • No network sandbox. Unlike the Codex adapter's workspace-write sandbox, Claude Code has no flag that disables network access for the turn. Tools that reach the network are reachable unless removed with --restricted, which also removes Bash and would make a coding runner useless.
  • No filesystem sandbox beyond the working directory: file tools are confined to the cwd and --add-dir entries (we pass none), but Bash can still reach anything the runner account can.

The privilege boundary for an add-on-managed runner is therefore the dedicated non-root account the agent supervises it under, not this adapter. See docs/edge-harness.md.

Index

Constants

View Source
const (
	// HarnessName is what the runner advertises in its capabilities response.
	HarnessName = "claude-code"
)

Variables

This section is empty.

Functions

func New

func New(cfg Config) harness.Adapter

New constructs a Claude Code harness adapter. The returned adapter starts no process and reads no credential until Probe or Run is called.

Types

type Adapter

type Adapter struct {
	// contains filtered or unexported fields
}

Adapter is the Claude Code implementation of harness.Adapter.

func (*Adapter) Probe

func (a *Adapter) Probe(ctx context.Context) (harness.Info, error)

Probe checks the executable and its version without making a model call.

It deliberately does NOT check authentication: the credential arrives with each launch, so there is nothing to check here, and a runner that reported itself unready until one showed up would never accept the attempt that carries it. An unusable credential is a per-attempt needs_input outcome.

func (*Adapter) Run

func (a *Adapter) Run(ctx context.Context, launch harness.Launch, emit harness.Emit) (harness.Result, error)

Run executes exactly one headless turn. A Launch that carries a SessionID resumes that session; one that does not starts a new one. The session id is returned in every outcome — including failures — so a caller can always resume rather than silently starting a second conversation.

type Config

type Config struct {
	Binary string
	// Home is a runner-owned CLAUDE_CONFIG_DIR. It must be dedicated to the
	// worker and is created 0700.
	Home string
	// WorktreeRoot is the managed checkout root; Launch.Workdir must be a task
	// directory beneath it. Shares the Codex adapter's rule.
	WorktreeRoot string
	// Model is passed as --model when set; empty leaves the account default.
	Model string
	// ExpectedVersion, when set, produces a readiness Reason on mismatch.
	ExpectedVersion string
	// PermissionMode is what the model may do without asking. Empty means
	// PermissionAcceptEdits. A coding runner cannot work under "dontAsk": with
	// prompts denied, every file edit is refused and each turn ends with no
	// changes.
	PermissionMode PermissionMode
	// AllowedTools are Claude Code tool patterns granted for the session, e.g.
	// "Bash(git *)" or "Bash(npm test)". They matter under PermissionAcceptEdits,
	// where shell commands are otherwise denied.
	AllowedTools []string
}

Config selects the Claude Code executable and its isolated home. The credential is NOT configuration: it arrives with each launch.

type PermissionMode

type PermissionMode string

PermissionMode names a Claude Code --permission-mode value the runner supports.

const (
	// PermissionAcceptEdits auto-approves file edits within the working
	// directory; anything else that would prompt is denied.
	PermissionAcceptEdits PermissionMode = "acceptEdits"
	// PermissionBypass approves every tool call. The dedicated runner account
	// and the worktree are then the only isolation; Claude Code documents it
	// as suitable only for sandboxes.
	PermissionBypass PermissionMode = "bypassPermissions"
)

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL