Headless Mode
Run KosmoKrator non-interactively for CI/CD pipelines, shell scripts, git hooks, and automated workflows. Pass a prompt, get output, exit. No TTY required.
Quick Start
Section titled “Quick Start”The three ways to invoke headless mode:
# Positional prompt — the simplest invocationkosmokrator "fix the off-by-one error in src/Math.php"
# Explicit -p flagkosmo -p "list all TODO comments in the codebase"
# Stdin pipeecho "explain this error" | kosmoAll three produce the same result: the agent runs to completion, writes the final response to stdout, and exits with code 0 on success. Progress and diagnostics go to stderr, so result=$(kosmo -p "task") captures only the response.
This CLI path is backed by the same Agent SDK runtime exposed to PHP applications through Kosmokrator\Sdk\AgentBuilder. Use the SDK when you want headless execution inside a web app, worker, daemon, or another PHP automation surface.
For the complete command matrix used by wrappers and other coding CLIs, see CLI Reference. For every configurable setting and effect timing, see Settings Reference.
Tip: Combine stdin with a positional prompt — stdin is appended after the prompt. Great for injecting file contents into a task:
cat error.log | kosmo -p "explain this error and suggest a fix"Headless Integrations
Section titled “Headless Integrations”If you do not need an agent turn and only want to call external tools such as Plane, ClickUp, or other OpenCompany integration packages, use the dedicated integrations CLI instead:
# Discover configured providerskosmo integrations:status --json
# Read the schema for one integration functionkosmo integrations:schema plane.list_issues
# Call an integration directlykosmo integrations:call plane.list_issues \ --workspace-slug=kosmokrator \ --project-id=PROJECT_UUID \ --json
# Run a multi-step Lua workflow against configured integrationskosmo integrations:lua workflow.lua --jsonThis integration surface is designed for scripts and other coding CLIs. It is documented in detail in Integrations CLI.
Integration calls remain governed in headless mode. Read/write permissions configured with integrations:configure --read=..., --write=..., or integrations.permissions_default are checked before execution. A trusted automation job can pass --force to bypass only that integration read/write policy.
Headless MCP
Section titled “Headless MCP”MCP servers can also be used without an agent turn. KosmoKrator reads the common project .mcp.json shape, plus VS Code/Cursor servers files, then exposes the servers through mcp:* commands and Lua as app.mcp.*.
# Add a portable project serverkosmo mcp:add github --project --type=stdio \ --command=github-mcp-server --env GITHUB_TOKEN --json
# Review and trust project server command before discovery/executionkosmo mcp:list --jsonkosmo mcp:trust github --project --jsonkosmo mcp:tools github --jsonkosmo mcp:schema github.search_repositories --json
# Call directly or through a per-server shortcutkosmo mcp:call github.search_repositories --query="kosmokrator" --jsonkosmo mcp:github search_repositories --query="kosmokrator" --json
# Run a Lua workflow against MCP serverskosmo mcp:lua workflow.lua --jsonHeadless MCP keeps project trust and read/write policy checks. Project MCP config can start local processes, so normal execution requires mcp:trust. Tool calls also check kosmo.mcp.servers.SERVER.permissions.read or .write; ask fails in pure headless mode because there is no approval modal. Use --force only for trusted automation that should bypass both MCP trust and MCP read/write policy for that single invocation.
See MCP for config compatibility, secrets, resources, prompts, Lua helpers, and the full command reference.
Headless Web Providers
Section titled “Headless Web Providers”External web providers can be configured and tested without opening a TUI. They are opt-in and do not replace native web_fetch; external fetch and crawl remain separate provider-backed tools.
# Inspect available providers and effective configurationkosmokrator web:providers --jsonkosmokrator web:doctor --json
# Configure provider keys from environment variableskosmokrator web:configure tavily --api-key-env=TAVILY_API_KEY \ --enable --search --global --jsonkosmokrator web:configure firecrawl --api-key-env=FIRECRAWL_API_KEY \ --enable --fetch --crawl --project --json
# Call providers directly from scriptskosmokrator web:search "latest Symfony TUI changes" --provider=tavily --jsonkosmokrator web:fetch https://symfony.com/blog/ --provider=firecrawl --jsonkosmokrator web:crawl https://docs.example.com --provider=tavily --max-pages=10 --jsonSupported providers are Tavily, Firecrawl, Exa, Brave Search, Parallel, Jina Reader/Search, SearXNG, Perplexity, OpenAI native web search, and Anthropic native web search. Provider API keys can also be stored with web:configure --api-key-stdin or secrets:set provider.PROVIDER.api_key.
Headless Configuration
Section titled “Headless Configuration”You can bootstrap KosmoKrator itself without opening the setup wizard or settings TUI:
# Configure an LLM provider and credentialsprintf %s "$OPENAI_API_KEY" | \ kosmo providers:configure openai --model gpt-5.4-mini \ --api-key-stdin --global --json
# Discover and set normal settingskosmo settings:list --jsonkosmo settings:set tools.default_permission_mode guardian --global --json
# Batch apply settings from JSONjq -n '{settings:{"agent.mode":"plan","context.max_output_lines":1200}}' | \ kosmo settings:apply --stdin-json --global --json
# Store managed secrets without echoing raw valuesprintf %s "$OPENAI_API_KEY" | \ kosmo secrets:set provider.openai.api_key --stdin --json
# Store MCP server secrets without committing tokens to .mcp.jsonprintf %s "$GITHUB_TOKEN" | \ kosmo mcp:secret:set github env.GITHUB_TOKEN --stdin --json
# Configure Telegram gateway without the TUIprintf %s "$TELEGRAM_BOT_TOKEN" | \ kosmo gateway:telegram:configure --token-stdin \ --enabled on --session-mode thread_user --global --jsonUse settings:doctor --json, providers:list --json, and secrets:list --json as the agent-friendly discovery path. See Configuration and Providers for the full command reference.
Output Formats
Section titled “Output Formats”Control the output format with -o / --output-format:
# Human-readable text (default)kosmo -p "list the files in src/"
# Single JSON blob at completionkosmo -p -o json "what does the AgentLoop class do?"
# Streaming NDJSON events as they happenkosmo -p -o stream-json "refactor the auth module"The default. Final response on stdout, progress on stderr:
$ kosmo -p "how many PHP files are in src/?"
[Working] ← stderr (dimmed) → bash(command: find src/ -name "*.php" | wc -l) ← stderr ✓ bash: 142 ← stderr tokens: 1234→567 cost: $0.03 ← stderr
There are 142 PHP files in the src/ directory. ← stdoutTip: Only stdout contains the result. Stderr is for human eyes only. This makes text mode ideal for scripting:
# Capture just the resultresult=$(kosmo -p "generate a migration for users table")
# Show progress live, capture resultkosmo -p "run the test suite" 2>/dev/nullA single structured JSON blob written to stdout when the agent finishes. Useful for programmatic consumption:
$ kosmo -p -o json "list the routes"{ "type": "result", "text": "The application defines these routes:\n1. GET / ...", "duration_ms": 4500, "turns": 0, "usage": { "tokens_in": 1234, "tokens_out": 567 }, "errors": [], "tool_calls": [ {"name": "bash", "args": {"command": "php artisan route:list"}, "output": "...", "success": true} ]}Stream JSON
Section titled “Stream JSON”Emits NDJSON events to stdout as they happen. Each line is a complete JSON object. Designed for IDE integrations, real-time dashboards, and long-running agent monitoring:
$ kosmo -p -o stream-json "analyze the codebase"{"type":"user_message","text":"analyze the codebase","timestamp":1712570000000}{"type":"phase","phase":"thinking","timestamp":1712570000100}{"type":"text_delta","delta":"I'll start by ","timestamp":1712570005000}{"type":"text_delta","delta":"examining the directory structure.","timestamp":1712570005100}{"type":"tool_call","name":"bash","args":{"command":"find src/ -type f | head -30"},"timestamp":1712570006000}{"type":"tool_result","name":"bash","output":"src/Agent/AgentLoop.php\n...","success":true,"timestamp":1712570007000}{"type":"result","text":"The codebase follows...","duration_ms":8000,"turns":3,"usage":{"tokens_in":2345,"tokens_out":890},"timestamp":1712570010000}Event types:
| Event | Description |
|---|---|
user_message | The prompt sent to the agent |
phase | Agent phase transition (thinking, working, idle) |
text_delta | Incremental text from the LLM response |
reasoning | Extended thinking content (if supported by model) |
tool_call | A tool is being invoked with name and arguments |
tool_result | Tool execution result with success status |
subagent_spawn | A child agent was spawned |
subagent_batch | Child agent(s) completed |
stream_end | The current text stream completed |
error | An error occurred during execution |
result | Final result with usage stats and duration |
CLI Reference
Section titled “CLI Reference”All headless-related flags. Combine freely:
| Flag | Alias | Description |
|---|---|---|
[prompt] | — | Positional task prompt (enables headless mode) |
--print | -p | Explicit headless mode |
--output-format | -o | Output format: text, json, stream-json |
--model | -m | Override model for this run |
--mode | — | Agent mode: edit, plan, ask |
--yolo | — | Auto-approve governed permission prompts (alias for --permission-mode prometheus) |
--permission-mode | — | Permission mode: guardian, argus, prometheus |
--max-turns | -t | Maximum agentic turns (LLM call cycles) |
--timeout | — | Maximum runtime in seconds |
--continue | -c | Continue the most recent session |
--resume | — | Resume last session (same as --continue) |
--session | — | Resume a specific session by ID |
--system-prompt | — | Replace the system prompt entirely |
--append-system-prompt | — | Append to the default system prompt |
--no-session | — | Don’t persist the session to disk |
Permissions in Headless Mode
Section titled “Permissions in Headless Mode”In headless mode, there is no terminal dialog for approval. KosmoKrator still evaluates the configured permission mode, denied tools, blocked paths, agent mode, integration read/write policy, and file path validation before executing work. Calls that would require an unavailable prompt fail with a structured error unless you explicitly choose an auto-approval policy.
Use --yolo to explicitly opt into Prometheus-style auto-approval for agent tool calls:
# Auto-approve governed permission promptskosmo -p --yolo "run the full test suite and fix any failures"Or use --permission-mode for explicit control. For direct integration commands, use --force when a trusted automation job should bypass integration read/write policy:
# Use Guardian mode (auto-approve safe tools, deny risky ones)kosmo -p --permission-mode guardian "add type hints to src/Utils.php"
# Use Argus mode (deny tools that would normally ask)kosmo -p --permission-mode argus "what files are in the project?"
# Bypass integration read/write policy for this direct call onlykosmo integrations:call plane.create_issue --force --jsonSee Permissions for details on each mode.
Guardrails
Section titled “Guardrails”For autonomous runs, protect against runaway agents with --max-turns and --timeout:
# Maximum 10 LLM call cycleskosmo -p --max-turns 10 "refactor the database layer"
# Maximum 5 minuteskosmo -p --timeout 300 "implement user authentication"
# Combine bothkosmo -p --max-turns 20 --timeout 600 "rewrite the API module"Tip: One “turn” is one LLM call cycle. A turn that triggers tool calls counts as one turn — the tool execution and follow-up LLM call is the next turn.
Session Management
Section titled “Session Management”Headless runs create sessions by default, just like interactive mode. This means you can resume them later:
# Run a task (creates a session)kosmo -p "analyze the authentication flow"
# Continue that session laterkosmo -p -c "now implement the suggested improvements"
# Resume a specific session by IDkosmo -p --session abc123 "what was my last question about?"Use --no-session for ephemeral runs where you don’t need session history:
# Quick one-off question, no session persistedkosmo -p --no-session "what does this regex do? /([A-Z])\w+/"Model Selection
Section titled “Model Selection”Override the configured model for a single run:
# Use a specific modelkosmo -p -m sonnet "quick code review of src/Http/"
# Use a cheaper model for simple taskskosmo -p -m haiku "generate a .gitignore for a PHP project"The model name matches your provider’s model identifier. See Providers for available models.
Agent Modes
Section titled “Agent Modes”Control which tools the agent can use:
# Full access (default) — all tools availablekosmo -p --mode edit "fix the login bug"
# Read-only — analyze without modifying fileskosmo -p --mode plan "design a caching strategy for the API"
# Ask mode — read files and run bash, but no file writeskosmo -p --mode ask "what does the QueueWorker do?"| Mode | File Read | File Write | Bash | Subagents |
|---|---|---|---|---|
edit (default) | ✓ | ✓ | ✓ | ✓ |
plan | ✓ | × | ✓ | ✓ |
ask | ✓ | × | ✓ | × |
System Prompt Control
Section titled “System Prompt Control”Customize the agent’s behavior by modifying the system prompt:
# Append instructions to the default promptkosmo -p --append-system-prompt "Always use PSR-12 coding style" "refactor src/"
# Replace the entire system promptkosmo -p --system-prompt "You are a security auditor. Find vulnerabilities." "audit src/Auth/"Exit Codes
Section titled “Exit Codes”| Code | Meaning |
|---|---|
0 | Success — agent completed the task |
1 | Error — agent encountered an error or returned an error response |
2 | Limit exceeded — max turns or timeout reached |
130 | Cancelled — interrupted by SIGINT (Ctrl+C) |
143 | Cancelled — interrupted by SIGTERM |
# Use in shell scriptskosmo -p "run tests"if [ $? -eq 0 ]; then echo "Tests passed!"elif [ $? -eq 2 ]; then echo "Agent hit a guardrail limit"fiCI/CD Integration
Section titled “CI/CD Integration”GitHub Actions
Section titled “GitHub Actions”name: AI Code Reviewon: [pull_request]jobs: review: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4
- name: Setup KosmoKrator run: | curl -sSL https://kosmokrator.dev/install.sh | bash printf %s "${{ secrets.ANTHROPIC_API_KEY }}" | \ kosmo setup --provider anthropic --api-key-stdin --global --json
- name: Run AI Review run: | kosmo -p --no-session --max-turns 5 \ "Review the changed files in this PR. Focus on security, performance, and code style. Output a summary." \ 2>review-progress.txt >review-result.txt
- name: Post Review Comment if: success() uses: actions/github-script@v7 with: script: | const fs = require('fs'); const review = fs.readFileSync('review-result.txt', 'utf8'); github.rest.issues.createComment({ ...context.repo, issue_number: context.issue.number, body: review });Git Hooks
Section titled “Git Hooks”#!/bin/bash# .git/hooks/pre-commit — AI-assisted commit message validation# Requires: kosmokrator in PATH
staged=$(git diff --cached --name-only)if [ -z "$staged" ]; then exit 0; fi
issues=$(kosmo -p --no-session --max-turns 3 --timeout 30 \ "Check these staged files for obvious bugs, debugging leftovers (dd, dump, console.log), and TODO comments that should block commit. Files: $staged Output ONLY 'PASS' if everything looks good, or list the issues." \ 2>/dev/null)
if [ "$issues" != "PASS" ]; then echo "AI pre-commit check found issues:" echo "$issues" exit 1fiMakefile Integration
Section titled “Makefile Integration”# Makefile.PHONY: ai-review ai-docs ai-test
ai-review: @kosmo -p --max-turns 10 --timeout 300 \ "Review the codebase for security issues, performance problems, \ and code style violations. Prioritize actual bugs over style nits."
ai-docs: @kosmo -p --mode plan \ "Generate API documentation for all public methods in src/. \ Output markdown suitable for a docs site."
ai-test: @kosmo -p --yolo \ "Run the test suite. If any tests fail, fix them and re-run."Scripting Patterns
Section titled “Scripting Patterns”Batch Processing
Section titled “Batch Processing”Process multiple files or tasks sequentially:
#!/bin/bash# Add type hints to all PHP files in a directoryfor file in src/Service/*.php; do echo "Processing $file..." kosmo -p --no-session --max-turns 3 \ "Add strict type declarations and parameter type hints to $file. \ Only modify the file if types are missing."doneJSON Output Parsing
Section titled “JSON Output Parsing”#!/bin/bash# Get structured results with jqresult=$(kosmo -p -o json --no-session "list all PHP classes in src/")echo "Tokens used: $(echo "$result" | jq '.usage.tokens_in') in, $(echo "$result" | jq '.usage.tokens_out') out"echo "Duration: $(echo "$result" | jq '.duration_ms')ms"echo "Tool calls: $(echo "$result" | jq '.tool_calls | length')"echo "Response:"echo "$result" | jq -r '.text'Streaming Pipeline
Section titled “Streaming Pipeline”#!/usr/bin/env python3"""Real-time agent monitoring via stream-json."""import sys, json, subprocess
proc = subprocess.Popen( ['kosmokrator', '-p', '-o', 'stream-json', 'refactor the auth module'], stdout=subprocess.PIPE, stderr=subprocess.DEVNULL, text=True)
for line in proc.stdout: event = json.loads(line) match event['type']: case 'tool_call': print(f" → {event['name']}({list(event['args'].keys())[0]}: ...)") case 'tool_result': status = '✓' if event['success'] else '✗' print(f" {status} {event['name']}") case 'result': print(f"\nDone in {event['duration_ms']}ms") print(event['text'])
proc.wait()sys.exit(proc.returncode)Comparison with Interactive Mode
Section titled “Comparison with Interactive Mode”| Feature | Interactive | Headless |
|---|---|---|
| Input method | REPL prompt | CLI arg, stdin, or -p |
| Output | TUI / ANSI renderer | stdout (text, JSON, stream-json) |
| Tool permissions | Interactive prompts | Policy evaluated; use --yolo for agent auto-approval |
| Plan approval | Interactive dialog | Plans output but not auto-implemented |
| Ask user/choice | Interactive prompts | Returns empty/dismissed |
| Slash commands | Available | Not available |
| Session persistence | Yes | Yes (disable with --no-session) |
| Session resume | --resume | --continue, --resume, --session |
| Subagents | Full support | Full support |
| Stuck detection | No | Yes (auto-nudge and force-return) |
| Max turns / timeout | Not available | --max-turns, --timeout |
Migrating from Other Agents
Section titled “Migrating from Other Agents”If you’re coming from another coding agent, here’s how the headless flags map:
| You’re used to | KosmoKrator equivalent |
|---|---|
Claude Code -p | kosmo -p (identical) |
Claude Code --output-format json | kosmo -o json |
Claude Code --output-format stream-json | kosmo -o stream-json |
Claude Code --dangerously-skip-permissions | kosmo --yolo |
Claude Code --continue | kosmo -c (identical) |
Claude Code --max-turns | kosmo --max-turns (identical) |
Claude Code --model | kosmo -m |
Codex CLI codex exec "task" | kosmo "task" |
Codex CLI --full-auto | kosmo --yolo |
Codex CLI -q | kosmo -p |
Aider --message "task" | kosmo -p "task" |
Aider --yes-always | kosmo --yolo |
Goose goose run -t "task" | kosmo "task" |
OpenCode opencode run "task" | kosmo "task" |