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:

  1. Set up the runtime – Install Node.js (or Bun) and the global CLI package for the chosen agent.
  2. Export the secret – Inject the required API key from repository secrets (ANTHROPIC_API_KEY, OPENAI_API_KEY, etc.) into the environment.
  3. Run the agent headlessly – Read the prompt from /tmp/agent-prompt.md and pass it to the CLI with flags that suppress interactive prompts and force deterministic output formats.
  4. Capture raw output – Tee every command's full console output to /tmp/agent-output.txt for artifact upload and debugging.
  5. Extract the final response – Use model-specific extraction logic (often jq or sed) to write the agent's final answer to /tmp/pr-body.md for 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 jq to 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/skills repository provides a single source of truth for agent runner templates located at plugins/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 jq parsing 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:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →