Skip to content

Adapters Reference ​

Adapters wrap LLM CLI tools for subprocess invocation. Wave ships with support for Claude Code, OpenCode, Gemini Code, and Codex.

Adapter Selection ​

Wave uses a 4-tier precedence system to determine which adapter a step runs with (strongest to weakest):

  1. CLI --adapter flag — e.g., wave run my-pipeline --adapter opencode overrides all steps
  2. Step-level adapter: — specified per step in pipeline YAML
  3. Persona-level adapter: — set on the persona in wave.yaml
  4. Adapter default — from the adapter definition in wave.yaml

This means you can set a project-wide default via persona configuration, override individual steps in the pipeline, and still force a specific adapter at the CLI for one-off runs.

Claude Code Adapter ​

The primary adapter for the claude CLI.

yaml
adapters:
  claude:
    binary: claude
    mode: headless
    output_format: json
    project_files:
      - CLAUDE.md
      - .claude/settings.json
    default_permissions:
      allowed_tools: ["Read", "Write", "Edit", "Bash", "Glob", "Grep"]
      deny: []
FieldTypeDefaultDescription
binarystring—CLI binary name. Must resolve via $PATH.
modestring—Always headless for subprocess execution.
output_formatstringjsonOutput format. Only json supported.
project_files[]string[]Files copied to workspace. Supports globs.
default_permissionsPermissionsallow allDefault tool permissions for personas.

Workspace Setup ​

When the Claude adapter runs, it generates two configuration files in the workspace:

  1. .claude/settings.json — Claude Code reads this for permissions, model, and sandbox config
  2. CLAUDE.md — Claude Code reads this as a system prompt with restriction directives

Both are derived from the manifest's persona and runtime configuration.

Generated settings.json Structure ​

json
{
  "model": "opus",
  "temperature": 0.7,
  "output_format": "stream-json",
  "permissions": {
    "allow": ["Read", "Write", "Edit", "Bash", "Glob", "Grep"],
    "deny": ["Bash(rm -rf /*)"]
  },
  "sandbox": {
    "enabled": true,
    "allowUnsandboxedCommands": false,
    "autoAllowBashIfSandboxed": true,
    "network": {
      "allowedDomains": ["api.anthropic.com", "github.com"]
    }
  }
}
FieldSourceDescription
permissions.allowpersona.permissions.allowed_toolsTools the persona can use
permissions.denypersona.permissions.denyTools explicitly denied
sandbox.enabledPresent when allowed_domains configuredEnables Claude Code's built-in sandbox
sandbox.network.allowedDomainspersona.sandbox.allowed_domains or runtime.sandbox.default_allowed_domainsNetwork domain allowlist

Generated CLAUDE.md Structure ​

The adapter writes the persona's system prompt followed by a restriction section:

markdown
# Navigator

You are the navigator persona...

---

## Restrictions

The following restrictions are enforced by the pipeline orchestrator.

### Denied Tools

- `Write(*)`
- `Edit(*)`

### Allowed Tools

You may ONLY use the following tools:

- `Read`
- `Glob`
- `Grep`

### Network Access

Network requests are restricted to:

- `api.anthropic.com`

Environment Hygiene ​

The adapter passes a curated environment to subprocesses instead of the full host environment. Only these variables are included:

  • HOME, PATH, TERM, TMPDIR (base)
  • DISABLE_TELEMETRY, DISABLE_ERROR_REPORTING (telemetry suppression)
  • Variables listed in runtime.sandbox.env_passthrough (explicit passthrough)
  • Step-specific env vars from pipeline config

This prevents credential leakage from unrelated host environment variables (e.g., AWS_SECRET_ACCESS_KEY).

CLI Invocation ​

bash
claude -p --model opus --allowedTools "Read,Write" --output-format stream-json \
  --verbose --dangerously-skip-permissions --no-session-persistence "prompt"

Gemini Code Adapter ​

Adapter for Google's Gemini Code CLI (gemini), v0.34.0+.

yaml
adapters:
  gemini:
    binary: gemini
    mode: headless
    output_format: json
    project_files:
      - GEMINI.md
    default_permissions:
      allowed_tools:
        - Read
        - Bash
      deny: []
FieldTypeDefaultDescription
binarystring—CLI binary name. Must resolve via $PATH.
modestring—Always headless for subprocess execution.
output_formatstringjsonOutput format. Only json supported.
project_files[]string[]Files copied to workspace. Supports globs.
default_permissionsPermissionsallow allDefault tool permissions for personas.

Model Format ​

Gemini uses plain model names — no provider prefix:

ModelDescription
gemini-2.0-proGemini 2.0 Pro
gemini-3-flash-previewGemini 3 Flash (preview)

If no model is specified, the Gemini binary uses its own default.

Workspace Setup ​

When the Gemini adapter runs, it generates a GEMINI.md file in the workspace containing the persona's system prompt and restriction directives. Gemini Code reads this file for context.

Output Format ​

The adapter parses an NDJSON stream with these event types:

Event typeDescription
tool_useTool invocation with name and input
textText content delta
resultFinal result with content and usage stats (input_tokens, output_tokens)

CLI Invocation ​

bash
gemini --yolo --output-format stream-json -p "prompt"
gemini --model gemini-2.0-pro --yolo --output-format stream-json -p "prompt"

Codex Adapter ​

Adapter for the OpenAI Codex CLI (codex).

yaml
adapters:
  codex:
    binary: codex
    mode: headless
    output_format: json
    project_files:
      - AGENTS.md
    default_permissions:
      allowed_tools:
        - Read
        - Bash
      deny: []
FieldTypeDefaultDescription
binarystring—CLI binary name. Must resolve via $PATH.
modestring—Always headless for subprocess execution.
output_formatstringjsonOutput format. Only json supported.
project_files[]string[]Files copied to workspace. Supports globs.
default_permissionsPermissionsallow allDefault tool permissions for personas.

Model Format ​

Codex supports both plain model names for OpenAI models and provider/model format for other providers:

ModelDescription
openai/gpt-4oOpenAI GPT-4o (explicit provider)
gpt-4oOpenAI GPT-4o (plain, inferred as OpenAI)

Workspace Setup ​

When the Codex adapter runs, it generates an AGENTS.md file in the workspace containing the persona's system prompt. The Codex CLI reads this file for agent instructions.


OpenCode Adapter ​

Alternative adapter for the opencode CLI, supporting multiple model providers.

yaml
adapters:
  opencode:
    binary: opencode
    mode: headless
    output_format: json
    default_permissions:
      allowed_tools: ["Read", "Write", "Edit"]
      deny: ["Bash(rm *)"]

Model Configuration ​

OpenCode uses a provider/model format to select which LLM backend to use. Specify the model on the persona:

yaml
personas:
  openai-coder:
    adapter: opencode
    model: openai/gpt-4o

The model string is split on the first / only:

model valueProviderModel
openai/gpt-4oopenaigpt-4o
anthropic/claude-sonnet-4-20250514anthropicclaude-sonnet-4-20250514
google/gemini-2.0-flashgooglegemini-2.0-flash
openai/org/gpt-4oopenaiorg/gpt-4o (multi-slash: splits on first / only)
(not set)anthropicclaude-sonnet-4-20250514 (default)

If no model is configured, OpenCode defaults to anthropic/claude-sonnet-4-20250514.

Environment Passthrough ​

OpenCode uses the same curated environment as the Claude adapter. Only base variables and those explicitly listed in runtime.sandbox.env_passthrough are passed to the subprocess. Configure API keys for your chosen provider:

yaml
runtime:
  sandbox:
    env_passthrough:
      - OPENAI_API_KEY
      - GOOGLE_API_KEY
      - ANTHROPIC_API_KEY

Variables not listed here are not visible to the OpenCode subprocess, preventing credential leakage from unrelated host environment variables.

Workspace Setup ​

When the OpenCode adapter runs:

  1. Creates .opencode/config.json with provider and model settings derived from the persona's model field
  2. Projects the persona system prompt to AGENTS.md

Complete Persona Example ​

yaml
adapters:
  opencode:
    binary: opencode
    mode: headless
    output_format: json
    default_permissions:
      allowed_tools: ["Read", "Write", "Edit", "Bash"]
      deny: []

personas:
  openai-coder:
    adapter: opencode
    model: openai/gpt-4o
    system_prompt: |
      You are a senior software engineer focused on clean implementation.

runtime:
  sandbox:
    env_passthrough:
      - OPENAI_API_KEY

CLI Invocation ​

bash
opencode --prompt "prompt" --output-format json --non-interactive

GitHub Adapter ​

The GitHub adapter wraps the GitHub API for direct repository operations. Unlike the Claude and OpenCode adapters, it does not invoke a subprocess CLI — it makes GitHub API calls directly using the GITHUB_TOKEN or GH_TOKEN environment variable.

Purpose ​

The GitHub adapter enables pipelines to perform GitHub API operations:

  • Issue management — list, analyze, retrieve, and update issues
  • Pull request creation — create PRs from pipeline-generated branches
  • Repository queries — retrieve repository metadata
  • Branch creation — create feature branches for pipeline workflows

Configuration ​

The GitHub adapter is configured internally and does not require an entry in the adapters: section of wave.yaml. It is used automatically by GitHub-related pipelines.

Required Environment Variables ​

VariableDescription
GITHUB_TOKENGitHub personal access token. The adapter reads this via os.Getenv("GITHUB_TOKEN").
GH_TOKENAlternative token variable. Pass through via runtime.sandbox.env_passthrough.

At least one of these must be set for the adapter to authenticate with the GitHub API.

Supported Operations ​

OperationDescription
list_issuesList open issues for a repository
analyze_issuesAnalyze issues for quality (below a configurable threshold)
get_issueRetrieve a single issue by number
update_issueUpdate an issue's title, body, state, or labels
create_prCreate a pull request
get_repoRetrieve repository metadata
create_branchCreate a new branch from a reference

How It Differs from LLM Adapters ​

AspectLLM Adapters (Claude, OpenCode)GitHub Adapter
ExecutionSubprocess CLI invocationDirect API calls
OutputLLM-generated textStructured JSON data
WorkspaceGenerates config files (.claude/settings.json, CLAUDE.md)No workspace setup
PermissionsTool allow/deny listsGitHub API token scope

Usage Context ​

The GitHub adapter is used by pipelines that interact with GitHub repositories:

  • plan-research — scan and analyze issue quality
  • ops-rewrite — enhance poorly written issues
  • impl-issue — implement features from GitHub issues

Multiple Adapters ​

A project can define multiple adapters in wave.yaml and switch between them at runtime via the 4-tier precedence system.

yaml
adapters:
  claude:
    binary: claude
    mode: headless
  opencode:
    binary: opencode
    mode: headless
  gemini:
    binary: gemini
    mode: headless
  codex:
    binary: codex
    mode: headless

personas:
  navigator:
    adapter: claude
  reviewer:
    adapter: gemini
    model: gemini-2.0-pro

Mixing Adapters in a Pipeline ​

Each step can specify its own adapter, enabling different steps to use different LLM backends:

yaml
steps:
  - id: analyze
    persona: navigator
    adapter: opencode
    model: "zai-coding-plan/glm-5-turbo"
  - id: implement
    persona: craftsman
    # Uses persona's adapter (claude) by default
  - id: review
    persona: reviewer
    adapter: gemini
    model: "gemini-2.0-pro"

CLI Overrides ​

bash
wave run my-pipeline --adapter opencode                    # Override all steps to use opencode
wave run my-pipeline --adapter opencode --model "zai-coding-plan/glm-5-turbo"  # Override adapter + model
wave run my-pipeline --model "gemini-2.0-pro"              # Override model only (persona's adapter stays)

Environment and Credentials ​

Adapters receive a curated environment — not the full host environment. Only explicitly allowed variables are passed through.

VariableSourcePurpose
HOME, PATH, TERM, TMPDIRAlways includedBase operation
ANTHROPIC_API_KEYVia runtime.sandbox.env_passthroughClaude API authentication
GH_TOKENVia runtime.sandbox.env_passthroughGitHub CLI authentication

Configure which variables are passed to adapter subprocesses:

yaml
runtime:
  sandbox:
    env_passthrough:
      - ANTHROPIC_API_KEY
      - GH_TOKEN

WARNING

Credentials are never written to disk. They flow via curated process environment only. Variables not in env_passthrough are not visible to adapter subprocesses.


Timeout Handling ​

  • Default timeout: 5 minutes per step
  • Override via runtime.default_timeout_minutes or --timeout flag
  • On timeout, entire process group receives SIGKILL
  • Timeout counts as step failure, triggering retry logic
yaml
runtime:
  default_timeout_minutes: 30

Model Format ​

Model format varies by adapter:

AdapterModel FormatExample
claudeShort names or full IDssonnet, haiku, claude-opus-4-5-20251101
opencodeprovider/model for multi-provider, or short nameszai-coding-plan/glm-5-turbo, openai/gpt-4o, anthropic/claude-sonnet-4-20250514
geminiPlain model namesgemini-2.0-pro, gemini-3-flash-preview
codexprovider/model or plain namesopenai/gpt-4o

Validation ​

bash
$ wave validate --verbose
  Adapter 'claude' binary found: /usr/local/bin/claude
  Adapter 'opencode' binary found: /usr/local/bin/opencode
  Adapter 'gemini' binary found: /usr/local/bin/gemini
  Adapter 'codex' binary not found on PATH  # Warning only

Binary warnings do not block validation - the binary may be available at runtime.

Released under the MIT License.