How to Template Agent Runners for Headless CI Execution Across Claude Code, Codex, OpenCode, and CodeLayer
The humanlayer/skills repository standardizes headless CI execution through a single YAML template file that configures runtime setup, API key injection, headless CLI invocation, output capture, and model-specific response extraction for each supported AI coding agent.
The humanlayer/skills repository provides a unified approach to running AI coding agents in headless CI environments. By defining model-specific templates in plugins/design-control-loop/skills/design-control-loop/references/agent-runner-templates.md, teams can drop ready-made configurations into GitHub Actions workflows. This eliminates environment drift and ensures consistent behavior across Claude Code, Codex CLI, OpenCode, and CodeLayer runners.
The 5-Step Headless Execution Pattern
Every agent runner template in the repository follows an identical five-step choreography to ensure deterministic, debuggable CI runs:
- Set up the runtime – Install Node.js (or Bun) and the global CLI package for the chosen agent.
- Export the secret – Inject the required API key from repository secrets (
ANTHROPIC_API_KEY,OPENAI_API_KEY, etc.) into the environment. - Run the agent headlessly – Read the prompt from
/tmp/agent-prompt.mdand pass it to the CLI with flags that suppress interactive prompts and force deterministic output formats. - Capture raw output – Tee every command's full console output to
/tmp/agent-output.txtfor artifact upload and debugging. - Extract the final response – Use model-specific extraction logic (often
jqorsed) to write the agent's final answer to/tmp/pr-body.mdfor downstream PR creation.
Model-Specific Runner Configurations
While the orchestration pattern remains constant, each AI model requires distinct CLI flags, output formats, and extraction logic as defined in the templates file.
Claude Code
Claude Code requires the ANTHROPIC_API_KEY secret and produces stream-JSON output that must be parsed with jq.
The installation uses npm install -g @anthropic-ai/claude-code. The headless invocation (lines 41-48 in the templates file) uses:
claude -p "$PROMPT" \
--permission-mode bypassPermissions \
--output-format stream-json \
--verbose \
2>&1 | tee /tmp/agent-output.txt
Extraction requires filtering the final assistant message from newline-delimited JSON objects:
cat /tmp/agent-output.txt \
| grep '^{' \
| jq -s '[.[] | select(.type == "assistant" and .message.content)] | last | .message.content[] | select(.type == "text") | .text' -r \
> /tmp/pr-body.md
Codex CLI
Codex CLI consumes the OPENAI_API_KEY secret and offers built-in extraction support, eliminating the need for manual parsing.
Installation via npm install -g @openai/codex. The run command (lines 73-78) includes a direct output flag:
codex exec "$PROMPT" \
--json \
--output-last-message /tmp/pr-body.md
Because --output-last-message handles extraction internally, no secondary jq step is required.
OpenCode
OpenCode supports multiple providers (accepting either ANTHROPIC_API_KEY or OPENAI_API_KEY) and uses Bun as its runtime.
Installation: bun install -g opencode-ai. The invocation (lines 5-11) specifies JSON formatting:
opencode run "$PROMPT" --format json
Extraction traverses the messages array:
jq -r '.messages | ... | .content' /tmp/agent-output.txt > /tmp/pr-body.md
CodeLayer
CodeLayer typically requires both ANTHROPIC_API_KEY and GH_TOKEN, utilizing Bun's executable runner.
Installation uses bunx @humanlayer/cli@latest codelayer. The command (lines 42-46) outputs plain text with ANSI color codes:
bunx @humanlayer/cli@latest codelayer \
--provider anthropic \
--model claude-opus-4-8 \
--thinking high \
--prompt "$PROMPT" \
2>&1 | tee /tmp/agent-output.txt
Extraction strips ANSI escape sequences using sed:
cat /tmp/agent-output.txt | sed 's/\x1b\[[0-9;]*m//g' > /tmp/pr-body.md
Complete CI Workflow Examples
Claude Code in GitHub Actions
# .github/workflows/ci.yml
steps:
- uses: actions/setup-node@v4
with:
node-version: 24
- run: npm install -g @anthropic-ai/claude-code
- name: Run Claude Code
env:
ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }}
run: |
claude -p "$PROMPT" \
--permission-mode bypassPermissions \
--output-format stream-json \
--verbose \
2>&1 | tee /tmp/agent-output.txt
- name: Extract PR body
run: |
cat /tmp/agent-output.txt \
| grep '^{' \
| jq -s '[.[] | select(.type == "assistant" and .message.content)] | last | .message.content[] | select(.type == "text") | .text' -r \
> /tmp/pr-body.md
CodeLayer in GitHub Actions
steps:
- uses: oven-sh/setup-bun@v2
- name: Run CodeLayer
env:
ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }}
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
FORCE_COLOR: "3"
run: |
bunx @humanlayer/cli@latest codelayer \
--provider anthropic \
--model claude-opus-4-8 \
--thinking high \
--prompt "$PROMPT" \
2>&1 | tee /tmp/agent-output.txt
- name: Extract PR body
run: |
cat /tmp/agent-output.txt | sed 's/\x1b\[[0-9;]*m//g' > /tmp/pr-body.md
Critical Implementation Details
All templates in agent-runner-templates.md include a mandatory pre-flight check: run the actuator locally first (lines 7-13). This verification step ensures the command syntax and prompt formatting work correctly before committing to a long-running CI pipeline.
The output format differences drive the extraction complexity:
- Stream-JSON (Claude Code): Requires
jqto filter the last assistant message from potentially hundreds of incremental updates. - Structured JSON (Codex, OpenCode): Allows direct property access or built-in extraction flags.
- ANSI Text (CodeLayer): Requires regex-based stripping of color codes to produce clean markdown.
Key Files and Architecture
| File | Role |
|---|---|
plugins/design-control-loop/skills/design-control-loop/references/agent-runner-templates.md |
Central source of all headless CLI snippets and extraction steps. |
plugins/design-control-loop/skills/design-control-loop/SKILL.md |
Explains how the templates integrate within the design-control-loop workflow. |
plugins/build-iterated-agentic-loop/skills/build-iterated-agentic-loop/SKILL.md |
Demonstrates template application for iterative loop construction. |
Summary
- The
humanlayer/skillsrepository provides a single source of truth for agent runner templates located atplugins/design-control-loop/skills/design-control-loop/references/agent-runner-templates.md. - Each supported model follows a 5-step pattern: runtime setup, secret export, headless execution, output capture, and response extraction.
- Claude Code and OpenCode require
jqparsing of JSON outputs, while Codex CLI offers built-in extraction and CodeLayer requires ANSI stripping. - All templates mandate local actuator verification (lines 7-13) before CI deployment to prevent workflow failures.
Frequently Asked Questions
Where are the agent runner templates defined in the repository?
The canonical definitions reside in plugins/design-control-loop/skills/design-control-loop/references/agent-runner-templates.md. This file contains the exact CLI invocations, environment variable requirements, and extraction scripts for Claude Code, Codex CLI, OpenCode, and CodeLayer.
How does output extraction differ between Claude Code and Codex CLI?
Claude Code outputs stream-JSON lines that require jq to filter the final assistant message from the incremental stream (lines 41-48). Codex CLI provides a --output-last-message flag that writes the final response directly to disk (lines 73-78), eliminating the need for post-processing.
Why should I run the actuator locally before committing to CI?
Lines 7-13 of the templates file explicitly remind developers to verify commands locally first. This catches prompt formatting errors, permission issues, or CLI flag changes that would otherwise fail silently or consume unnecessary CI minutes during the debugging cycle.
What runtime dependencies are required for different agents?
Claude Code and Codex CLI require Node.js and npm for global installation, while OpenCode and CodeLayer rely on Bun (bun install or bunx). The templates specify the exact setup action (actions/setup-node@v4 vs oven-sh/setup-bun@v2) for each runtime environment.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →