Headless Mode β
Run CodeBuddy Code programmatically without an interactive UI
Overview β
Headless mode allows you to run CodeBuddy Code programmatically through command-line scripts and automation tools without any interactive UI.
Headless mode also supports scheduled task capabilities. In script, SDK, or server-side integration scenarios, you can use tools such as CronCreate, CronList, and CronDelete to create, view, and cancel scheduled tasks.
β οΈ Important Note:
-y(or--dangerously-skip-permissions) is a required parameter for non-interactive mode. When using the-p/--printparameter for non-interactive execution, this parameter must be added to perform operations that require authorization (file read/write, command execution, network requests, etc.), otherwise these operations will be blocked. Only use this parameter in trusted environments and explicit task scenarios. See CLI Reference for details.
Basic Usage β
The primary command-line interface for CodeBuddy Code is the codebuddy (or cbc) command. Use the --print (or -p) flag to run in non-interactive mode and print the final result:
bash
codebuddy -p "Stage my changes and write a set of commits for them" \
--allowedTools "Bash,Read" \
--permission-mode acceptEditsConfiguration Options β
Headless mode leverages all available CLI options in CodeBuddy Code. Here are key options for automation and scripting:
| Flag | Description | Example |
|---|---|---|
--print, -p | Run in non-interactive mode | codebuddy -p "query" |
--output-format | Specify output format (text, json, stream-json) | codebuddy -p --output-format json |
--resume, -r | Resume a conversation by session ID | codebuddy --resume abc123 |
--continue, -c | Continue the most recent conversation | codebuddy --continue |
--verbose | Enable verbose logging | codebuddy --verbose |
--append-system-prompt | Append to system prompt (only works with --print) | codebuddy --append-system-prompt "Custom instructions" |
--allowedTools | List of allowed tools, space-separated or comma-separated string | codebuddy --allowedTools mcp__slack mcp__filesystemcodebuddy --allowedTools "Bash(npm install),mcp__filesystem" |
--disallowedTools | List of disallowed tools, space-separated or comma-separated string | codebuddy --disallowedTools mcp__splunk mcp__githubcodebuddy --disallowedTools "Bash(git commit),mcp__github" |
--settings | Load additional settings configuration from a JSON file or JSON string | codebuddy -p --settings '{"model":"gpt-5"}' "query" |
--setting-sources | Specify which settings sources to load (options: user, project, local) | codebuddy -p --setting-sources project,local "query" |
--mcp-config | Load MCP servers from a JSON file | codebuddy --mcp-config servers.json |
--permission-prompt-tool | MCP tool for handling permission prompts (only works with --print) | β Not supported |
Note: The
--permission-prompt-toolfeature is currently not supported.
For a complete list of CLI options and features, please refer to the CLI Reference documentation.
Multi-turn Conversations β
For multi-turn conversations, you can resume a conversation or continue from the most recent session:
bash
# Continue the most recent conversation
codebuddy --continue "Now refactor for better performance"
# Resume a specific conversation by session ID
codebuddy --resume 550e8400-e29b-41d4-a716-446655440000 "Update tests"
# Resume in non-interactive mode
codebuddy --resume 550e8400-e29b-41d4-a716-446655440000 "Fix all linting issues" -pOutput Formats β
Text Output (Default) β
bash
codebuddy -p "Explain the file src/components/Header.tsx"
# Output: This is a React component that displays...JSON Output β
Returns structured data with metadata:
bash
codebuddy -p "How does the data layer work?" --output-format jsonResponse format:
json
{
...
}Stream JSON Output β
Streams as each message is received:
bash
codebuddy -p "Build an application" --output-format stream-jsonEach conversation begins with an initial init system message, followed by a list of user and assistant messages, and ends with a final result system message containing statistics. Each message is emitted as a separate JSON object.
Background Task Events (Async) β
When the model launches a background command (Bash / PowerShell), background workflow, or background Agent sub-task with run_in_background: true, the CLI emits a separate system event on the stream-json output stream for each task, carrying a unique task_id (used to distinguish concurrent tasks), with tool_use_id linking back to the tool_use that initiated the task:
- Task started β
system/subtype: "task_started" - Task progress (emitted per completed tool_use, sub-agent/workflow only) β
system/subtype: "task_progress"(withusage) - Task status change β
system/subtype: "task_updated"(withpatch) - Task completed/failed/stopped β
system/subtype: "task_notification"
jsonc
// Task started (pushed immediately when entering running state)
{"type":"system","subtype":"task_started","task_id":"agent-00f6","tool_use_id":"toolu_01","description":"bg agent","task_type":"Agent","uuid":"...","session_id":"..."}
// Progress (per completed tool_use, carries cumulative usage + last tool name; shell tasks do not emit)
{"type":"system","subtype":"task_progress","task_id":"agent-00f6","description":"bg agent","usage":{"total_tokens":320,"tool_uses":2,"duration_ms":157},"last_tool_name":"Bash","uuid":"...","session_id":"..."}
// Status change (patch carries changed fields; terminal state adds end_time)
{"type":"system","subtype":"task_updated","task_id":"agent-00f6","patch":{"status":"completed","end_time":1783945615966},"status":"completed","uuid":"...","session_id":"..."}
// Task completed (may arrive after the triggering turn's result; sub-agent carries usage)
{"type":"system","subtype":"task_notification","task_id":"agent-00f6","tool_use_id":"toolu_01","status":"completed","summary":"Background agent \"bg agent\" completed","output_file":"/.../bg-tasks/agent-00f6.stdout.log","usage":{"total_tokens":480,"tool_uses":2,"duration_ms":250},"session_id":"..."}Field descriptions:
| Field | Event | Description |
|---|---|---|
task_id | All | Unique ID for the background task, persists across started β progress β updated β notification; used to distinguish concurrent tasks and route to TaskOutput |
tool_use_id | Most (optional) | Links back to the model's tool_use |
description / task_type | started / progress | Task command description / tool type (Bash / PowerShell / Workflow / Agent) |
usage | progress (always present) / notification (present for sub-agent, omitted for shell) | { total_tokens, tool_uses, duration_ms } (aligns with CC's TaskUsage) |
last_tool_name | progress (optional) | Name of the most recently executed tool |
patch / status | updated | Changed fields in this update (at least status; terminal state adds end_time) |
status | notification | completed / failed / stopped (killed/cancelled normalized to stopped) |
summary | notification | Human-readable completion summary |
output_file / output_stderr_file | notification (optional) | On-disk output path for the background task (file mode); use this to read the full output |
Progress events (
task_progress) are event-driven (one emitted per completed tool_use), not polled on a timer; background shell tasks (Bash/PowerShell) do not emit progressβonly sub-agent / workflow tasks do.Terminal state may arrive only via
task_updated: Some background tasks reach their terminal state solely throughtask_updated(patch.statusset to a terminal value) without a correspondingtask_notification. Consumers tracking "active tasks" should treat the terminal status (completed/failed/stopped/killed) from both events equally when cleaning up.
Important (stdio long-lived connection scenario): Background tasks may complete after the
resultof the turn that triggered them. When using--input-format stream-json --output-format stream-json(a long-lived connection with stdin kept open), the CLI proactively pushestask_notificationback to the same output stream after the task truly finishesβno need to send new input. Consumers should therefore keep reading the output stream and must not stop after receiving the firstresult, or they will miss background completion events. Pure-psingle-shot mode (process exits after the firstresult) does not support background tasks and returns an explicit error.
Disabling background tasks: In scenarios that do not support or need background tasks, set the environment variable
CODEBUDDY_CODE_DISABLE_BACKGROUND_TASKS=1to disable themβtherun_in_backgroundparameter for Bash / PowerShell / Agent is hidden from the tool schema, and even if the model still sends it, it will be ignored/degraded to foreground execution, producing no background task events and no cross-turn push-back. The SDK'squery()single-shot usage automatically injects this variable (sincequery()stops at the firstresultand cannot receive cross-turn push-back events); continuously-reading SDK usage (JSunstable_v2_createSession/ PythonCodeBuddySDKClient) is unaffected.
Structured JSON Output β
To get output that conforms to a specific schema, use --output-format json with --json-schema and a JSON Schema definition. The response includes metadata about the request (session ID, usage, etc.), with the structured output in the structured_output field.
This example extracts function names from auth.py and returns them as an array of strings:
bash
codebuddy -p "Extract the main function names from auth.py" \
--output-format json \
--json-schema '{"type":"object","properties":{"functions":{"type":"array","items":{"type":"string"}}},"required":["functions"]}'Tip: Use tools like jq to parse the response and extract specific fields:
bash# Extract text result codebuddy -p "Summarize this project" --output-format json | jq -r '.result' # Extract structured output codebuddy -p "Extract function names from auth.py" \ --output-format json \ --json-schema '{"type":"object","properties":{"functions":{"type":"array","items":{"type":"string"}}},"required":["functions"]}' \ | jq '.structured_output'
Input Formats β
Text Input (Default) β
bash
# Direct argument
codebuddy -p "Explain this code"
# From stdin
echo "Explain this code" | codebuddy -pStream JSON Input β
A stream of messages provided via stdin, where each message represents a user turn. This allows for multi-turn conversations without restarting the codebuddy binary, and allows providing guidance to the model while it processes requests.
Each message is a JSON "user message" object following the same format as the output message schema. Messages are formatted using jsonl format, where each line of input is a complete JSON object. Stream JSON input requires -p and --output-format stream-json.
bash
echo '{"type":"user","message":{"role":"user","content":[{"type":"text","text":"Explain this code"}]}}' | \
codebuddy -p --output-format=stream-json --input-format=stream-json --verbose
# Single message (with image)
echo '{"type":"user","message":{"role":"user","content":[{"type":"text","text":"Text prompt, such as referring to the text in the following image"},{"type":"image","source":{"type":"base64","media_type":"image/png","data":"raw base64 (without protocol prefix)"}}]}}' \
| codebuddy -p --input-format stream-json --output-format stream-json
# Multi-turn conversation (multi-line JSON, continuously sent to the same process)
printf '%s\n' \
'{"type":"user","message":{"role":"user","content":[{"type":"text","text":"First question"}]}}' \
'{"type":"user","message":{"role":"user","content":[{"type":"text","text":"Second question"}]}}' \
| codebuddy -p --input-format stream-json --output-format stream-json --verboseAgent Integration Examples β
SRE Incident Response Bot β
bash
#!/bin/bash
# Automated incident response agent
investigate_incident() {
local incident_description="$1"
local severity="${2:-medium}"
codebuddy -p "Incident: $incident_description (Severity: $severity)" \
--append-system-prompt "You are an SRE expert. Diagnose the issue, assess impact, and provide immediate action items." \
--output-format json \
--allowedTools "Bash,Read,WebSearch,mcp__datadog" \
--mcp-config monitoring-tools.json
}
# Usage
investigate_incident "Payment API returning 500 errors" "high"Automated Security Review β
bash
# Security audit agent for PRs
audit_pr() {
local pr_number="$1"
gh pr diff "$pr_number" | codebuddy -p \
--append-system-prompt "You are a security engineer. Review this PR for vulnerabilities, unsafe patterns, and compliance issues." \
--output-format json \
--allowedTools "Read,Grep,WebSearch"
}
# Use and save to file
audit_pr 123 > security-report.jsonMulti-turn Legal Assistant β
bash
# Legal document review with session persistence
session_id=$(codebuddy -p "Start legal review session" --output-format json | jq -r '.session_id')
# Review contract in multiple steps
codebuddy -p --resume "$session_id" "Review liability clauses in contract.pdf"
codebuddy -p --resume "$session_id" "Check compliance with GDPR requirements"
codebuddy -p --resume "$session_id" "Generate executive summary of risks"Best Practices β
Use JSON output format for programmatically parsing responses:
bash# Parse JSON response using jq result=$(codebuddy -p "Generate code" --output-format json) code=$(echo "$result" | jq -r '.result') cost=$(echo "$result" | jq -r '.total_cost_usd')Handle errors gracefully - Check exit codes and stderr:
bashif ! codebuddy -p "$prompt" 2>error.log; then echo "An error occurred:" >&2 cat error.log >&2 exit 1 fiUse session management to maintain context across multi-turn conversations
Consider timeouts for long-running operations:
bashtimeout 300 codebuddy -p "$complex_prompt" || echo "Timed out after 5 minutes"Respect rate limits when making multiple requests, by adding delays between calls
Use
-yto perform operations requiring authorization in non-interactive mode:bash# Complete example in non-interactive mode codebuddy -p "Analyze code and run tests" \ --output-format json \ -y \ --allowedTools "Bash,Read,Grep"β οΈ Important Note:
-y(or--dangerously-skip-permissions) is a required parameter for non-interactive mode. When using the-p/--printparameter for non-interactive execution, this parameter must be added to perform operations that require authorization (file read/write, command execution, network requests, etc.), otherwise these operations will be blocked. Only use this parameter in trusted environments and explicit task scenarios. See CLI Reference for details.
Related Resources β
- CLI Reference - Complete CLI documentation
- Common Workflows - Step-by-step guides for common use cases
- Interactive Mode - Interactive session features
- IAM Permissions - Tool permissions and access control
Tip: Headless mode is ideal for CI/CD pipelines, automation scripts, and agent integrations. Combine it with MCP servers to extend functionality.