HomeDocs › Headless Mode

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

The three ways to invoke headless mode:

# Positional prompt — the simplest invocation
kosmokrator "fix the off-by-one error in src/Math.php"

# Explicit -p flag
kosmokrator -p "list all TODO comments in the codebase"

# Stdin pipe
echo "explain this error" | kosmokrator

All 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=$(kosmokrator -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.

Tip: Combine stdin with a positional prompt — stdin is appended after the prompt. Great for injecting file contents into a task:

cat error.log | kosmokrator -p "explain this error and suggest a fix"

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 providers
kosmokrator integrations:status --json

# Read the schema for one integration function
kosmokrator integrations:schema plane.list_issues

# Call an integration directly
kosmokrator integrations:call plane.list_issues \
  --workspace-slug=kosmokrator \
  --project-id=PROJECT_UUID \
  --json

# Run a multi-step Lua workflow against configured integrations
kosmokrator integrations:lua workflow.lua --json

This 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

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 server
kosmokrator mcp:add github --project --type=stdio \
  --command=github-mcp-server --env GITHUB_TOKEN --json

# Review and trust project server command before discovery/execution
kosmokrator mcp:list --json
kosmokrator mcp:trust github --project --json
kosmokrator mcp:tools github --json
kosmokrator mcp:schema github.search_repositories --json

# Call directly or through a per-server shortcut
kosmokrator mcp:call github.search_repositories --query="kosmokrator" --json
kosmokrator mcp:github search_repositories --query="kosmokrator" --json

# Run a Lua workflow against MCP servers
kosmokrator mcp:lua workflow.lua --json

Headless 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 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

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 configuration
kosmokrator web:providers --json
kosmokrator web:doctor --json

# Configure provider keys from environment variables
kosmokrator web:configure tavily --api-key-env=TAVILY_API_KEY \
  --enable --search --global --json
kosmokrator web:configure firecrawl --api-key-env=FIRECRAWL_API_KEY \
  --enable --fetch --crawl --project --json

# Call providers directly from scripts
kosmokrator web:search "latest Symfony TUI changes" --provider=tavily --json
kosmokrator web:fetch https://symfony.com/blog/ --provider=firecrawl --json
kosmokrator web:crawl https://docs.example.com --provider=tavily --max-pages=10 --json

Supported 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

You can bootstrap KosmoKrator itself without opening the setup wizard or settings TUI:

# Configure an LLM provider and credentials
printf %s "$OPENAI_API_KEY" | \
  kosmokrator providers:configure openai --model gpt-5.4-mini \
  --api-key-stdin --global --json

# Discover and set normal settings
kosmokrator settings:list --json
kosmokrator settings:set tools.default_permission_mode guardian --global --json

# Batch apply settings from JSON
jq -n '{settings:{"agent.mode":"plan","context.max_output_lines":1200}}' | \
  kosmokrator settings:apply --stdin-json --global --json

# Store managed secrets without echoing raw values
printf %s "$OPENAI_API_KEY" | \
  kosmokrator secrets:set provider.openai.api_key --stdin --json

# Store MCP server secrets without committing tokens to .mcp.json
printf %s "$GITHUB_TOKEN" | \
  kosmokrator mcp:secret:set github env.GITHUB_TOKEN --stdin --json

# Configure Telegram gateway without the TUI
printf %s "$TELEGRAM_BOT_TOKEN" | \
  kosmokrator gateway:telegram:configure --token-stdin \
  --enabled on --session-mode thread_user --global --json

Use 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

Control the output format with -o / --output-format:

# Human-readable text (default)
kosmokrator -p "list the files in src/"

# Single JSON blob at completion
kosmokrator -p -o json "what does the AgentLoop class do?"

# Streaming NDJSON events as they happen
kosmokrator -p -o stream-json "refactor the auth module"

Text

The default. Final response on stdout, progress on stderr:

$ kosmokrator -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.              ← stdout

Tip: Only stdout contains the result. Stderr is for human eyes only. This makes text mode ideal for scripting:

# Capture just the result
result=$(kosmokrator -p "generate a migration for users table")

# Show progress live, capture result
kosmokrator -p "run the test suite" 2>/dev/null

JSON

A single structured JSON blob written to stdout when the agent finishes. Useful for programmatic consumption:

$ kosmokrator -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

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:

$ kosmokrator -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:

EventDescription
user_messageThe prompt sent to the agent
phaseAgent phase transition (thinking, working, idle)
text_deltaIncremental text from the LLM response
reasoningExtended thinking content (if supported by model)
tool_callA tool is being invoked with name and arguments
tool_resultTool execution result with success status
subagent_spawnA child agent was spawned
subagent_batchChild agent(s) completed
stream_endThe current text stream completed
errorAn error occurred during execution
resultFinal result with usage stats and duration

CLI Reference

All headless-related flags. Combine freely:

FlagAliasDescription
[prompt]Positional task prompt (enables headless mode)
--print-pExplicit headless mode
--output-format-oOutput format: text, json, stream-json
--model-mOverride model for this run
--modeAgent mode: edit, plan, ask
--yoloAuto-approve governed permission prompts (alias for --permission-mode prometheus)
--permission-modePermission mode: guardian, argus, prometheus
--max-turns-tMaximum agentic turns (LLM call cycles)
--timeoutMaximum runtime in seconds
--continue-cContinue the most recent session
--resumeResume last session (same as --continue)
--sessionResume a specific session by ID
--system-promptReplace the system prompt entirely
--append-system-promptAppend to the default system prompt
--no-sessionDon't persist the session to disk

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 prompts
kosmokrator -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)
kosmokrator -p --permission-mode guardian "add type hints to src/Utils.php"

# Use Argus mode (deny tools that would normally ask)
kosmokrator -p --permission-mode argus "what files are in the project?"

# Bypass integration read/write policy for this direct call only
kosmokrator integrations:call plane.create_issue --force --json

See Permissions for details on each mode.

Guardrails

For autonomous runs, protect against runaway agents with --max-turns and --timeout:

# Maximum 10 LLM call cycles
kosmokrator -p --max-turns 10 "refactor the database layer"

# Maximum 5 minutes
kosmokrator -p --timeout 300 "implement user authentication"

# Combine both
kosmokrator -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

Headless runs create sessions by default, just like interactive mode. This means you can resume them later:

# Run a task (creates a session)
kosmokrator -p "analyze the authentication flow"

# Continue that session later
kosmokrator -p -c "now implement the suggested improvements"

# Resume a specific session by ID
kosmokrator -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 persisted
kosmokrator -p --no-session "what does this regex do? /([A-Z])\w+/"

Model Selection

Override the configured model for a single run:

# Use a specific model
kosmokrator -p -m sonnet "quick code review of src/Http/"

# Use a cheaper model for simple tasks
kosmokrator -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

Control which tools the agent can use:

# Full access (default) — all tools available
kosmokrator -p --mode edit "fix the login bug"

# Read-only — analyze without modifying files
kosmokrator -p --mode plan "design a caching strategy for the API"

# Ask mode — read files and run bash, but no file writes
kosmokrator -p --mode ask "what does the QueueWorker do?"
ModeFile ReadFile WriteBashSubagents
edit (default)
plan×
ask××

System Prompt Control

Customize the agent's behavior by modifying the system prompt:

# Append instructions to the default prompt
kosmokrator -p --append-system-prompt "Always use PSR-12 coding style" "refactor src/"

# Replace the entire system prompt
kosmokrator -p --system-prompt "You are a security auditor. Find vulnerabilities." "audit src/Auth/"

Exit Codes

CodeMeaning
0Success — agent completed the task
1Error — agent encountered an error or returned an error response
2Limit exceeded — max turns or timeout reached
130Cancelled — interrupted by SIGINT (Ctrl+C)
143Cancelled — interrupted by SIGTERM
# Use in shell scripts
kosmokrator -p "run tests" 
if [ $? -eq 0 ]; then
    echo "Tests passed!"
elif [ $? -eq 2 ]; then
    echo "Agent hit a guardrail limit"
fi

CI/CD Integration

GitHub Actions

name: AI Code Review
on: [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 }}" | \
            kosmokrator setup --provider anthropic --api-key-stdin --global --json

      - name: Run AI Review
        run: |
          kosmokrator -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

#!/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=$(kosmokrator -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 1
fi

Makefile Integration

# Makefile
.PHONY: ai-review ai-docs ai-test

ai-review:
	@kosmokrator -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:
	@kosmokrator -p --mode plan \
		"Generate API documentation for all public methods in src/. \
		 Output markdown suitable for a docs site."

ai-test:
	@kosmokrator -p --yolo \
		"Run the test suite. If any tests fail, fix them and re-run."

Scripting Patterns

Batch Processing

Process multiple files or tasks sequentially:

#!/bin/bash
# Add type hints to all PHP files in a directory
for file in src/Service/*.php; do
  echo "Processing $file..."
  kosmokrator -p --no-session --max-turns 3 \
    "Add strict type declarations and parameter type hints to $file. \
     Only modify the file if types are missing."
done

JSON Output Parsing

#!/bin/bash
# Get structured results with jq
result=$(kosmokrator -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

#!/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

FeatureInteractiveHeadless
Input methodREPL promptCLI arg, stdin, or -p
OutputTUI / ANSI rendererstdout (text, JSON, stream-json)
Tool permissionsInteractive promptsPolicy evaluated; use --yolo for agent auto-approval
Plan approvalInteractive dialogPlans output but not auto-implemented
Ask user/choiceInteractive promptsReturns empty/dismissed
Slash commandsAvailableNot available
Session persistenceYesYes (disable with --no-session)
Session resume--resume--continue, --resume, --session
SubagentsFull supportFull support
Stuck detectionNoYes (auto-nudge and force-return)
Max turns / timeoutNot available--max-turns, --timeout

Migrating from Other Agents

If you're coming from another coding agent, here's how the headless flags map:

You're used toKosmoKrator equivalent
Claude Code -pkosmokrator -p (identical)
Claude Code --output-format jsonkosmokrator -o json
Claude Code --output-format stream-jsonkosmokrator -o stream-json
Claude Code --dangerously-skip-permissionskosmokrator --yolo
Claude Code --continuekosmokrator -c (identical)
Claude Code --max-turnskosmokrator --max-turns (identical)
Claude Code --modelkosmokrator -m
Codex CLI codex exec "task"kosmokrator "task"
Codex CLI --full-autokosmokrator --yolo
Codex CLI -qkosmokrator -p
Aider --message "task"kosmokrator -p "task"
Aider --yes-alwayskosmokrator --yolo
Goose goose run -t "task"kosmokrator "task"
OpenCode opencode run "task"kosmokrator "task"