GitHub - danshapiro/kilroy (original) (raw)

Kilroy is a local-first CLI for running StrongDM-style Attractor pipelines in a git repo.

High-level flow:

  1. Convert English requirements to a Graphviz DOT pipeline (attractor ingest).
  2. Validate graph structure and semantics (attractor validate).
  3. Execute node-by-node with coding agents in an isolated git worktree (attractor run).
  4. Resume interrupted runs from logs, CXDB, or run branch (attractor resume).

Installation

Homebrew (macOS and Linux)

brew tap danshapiro/kilroy brew install kilroy

Go Install

go install github.com/danshapiro/kilroy/cmd/kilroy@latest

Build from Source

go build -o kilroy ./cmd/kilroy

What Is CXDB?

CXDB is the execution database Kilroy uses for observability and recovery.

Short version: git branch is code history; CXDB is run history.

What Attractor Means Here

An Attractor pipeline is a digraph where:

In this repo, each completed node also creates a git checkpoint commit on a run branch.

StrongDM Attractor vs Kilroy Implementation

This implementation is based on the Attractor specification by StrongDM at https://github.com/strongdm/attractor. Here's how Kilroy differs

Area From StrongDM Attractor Specs Kilroy-Specific in This Repo
Graph DSL + engine semantics DOT schema, handler model, edge selection, retry, conditions, context fidelity Concrete Go engine implementation details and defaults
Coding-agent loop Session model, tool loop behavior, provider-aligned tool concepts Local tool execution wiring and CLI/API backend routing choices
Unified LLM model Provider-neutral request/response/tool/streaming contracts Concrete provider adapters and environment wiring
Provider support Conceptual provider abstraction Provider plug-in runtime with built-ins: OpenAI, Anthropic, Google, Kimi, ZAI, Minimax
Backend selection Spec allows flexible backend choices Backend is mandatory per provider (api/cli), no implicit defaults
Checkpointing + persistence Attractor/CXDB contracts Required git branch/worktree/commit-per-node and concrete artifact layout
Ingestion Ingestor behavior described in spec docs attractor ingest implementation: Claude CLI + create-dotfile skill

Prerequisites

Quickstart

1) Build

go build -o kilroy ./cmd/kilroy

2) Generate a pipeline from English

./kilroy attractor ingest -o pipeline.dot "Solitaire plz"

Notes:

3) Validate the pipeline

./kilroy attractor validate --graph pipeline.dot

If you want to author a graph manually instead of using ingest, this minimal example is valid:

digraph Simple { graph [ goal="Run tests and summarize results", model_stylesheet=" * { llm_provider: openai; llm_model: gpt-5.4; } " ]

start [shape=Mdiamond] exit [shape=Msquare] run_tests [shape=box, prompt="Run tests and write status.json"] summarize [shape=box, prompt="Summarize outcomes and write status.json"]

start -> run_tests -> summarize -> exit }

4) Create run.yaml

version: 1

repo: path: /absolute/path/to/target/repo

cxdb: binary_addr: 127.0.0.1:9009 http_base_url: http://127.0.0.1:9010 autostart: enabled: true # argv form; use an absolute path if you run kilroy outside repo root. command: ["/absolute/path/to/kilroy/scripts/start-cxdb.sh"] wait_timeout_ms: 20000 poll_interval_ms: 250 ui: enabled: true command: ["/absolute/path/to/kilroy/scripts/start-cxdb-ui.sh"] url: "http://127.0.0.1:9020"

llm: cli_profile: real providers: openai: backend: cli anthropic: backend: api google: backend: api kimi: backend: api api: protocol: anthropic_messages api_key_env: KIMI_API_KEY base_url: https://api.kimi.com/coding path: /v1/messages profile_family: openai zai: backend: api api: protocol: openai_chat_completions api_key_env: ZAI_API_KEY base_url: https://api.z.ai path: /api/coding/paas/v4/chat/completions profile_family: openai

modeldb: openrouter_model_info_path: /absolute/path/to/kilroy/internal/attractor/modeldb/pinned/openrouter_models.json openrouter_model_info_update_policy: on_run_start openrouter_model_info_url: https://openrouter.ai/api/v1/models openrouter_model_info_fetch_timeout_ms: 5000

git: require_clean: false run_branch_prefix: attractor/run commit_per_node: true

runtime_policy: stage_timeout_ms: 0 stall_timeout_ms: 600000 stall_check_interval_ms: 5000 max_llm_retries: 6

preflight: prompt_probes: enabled: true transports: [complete, stream] timeout_ms: 15000 retries: 1 base_delay_ms: 500 max_delay_ms: 5000

Important:

5) Run the pipeline

Real run (recommended/default profile):

unset KILROY_CODEX_PATH KILROY_CLAUDE_PATH KILROY_GEMINI_PATH ./kilroy attractor run --graph pipeline.dot --config run.yaml

Explicit test-shim run (for local fake-provider testing only):

llm: cli_profile: test_shim providers: openai: backend: cli executable: /absolute/path/to/fake-codex

./kilroy attractor run --graph pipeline.dot --config run.yaml --allow-test-shim

Preflight-only run (validate everything, do not start execution):

./kilroy attractor run --graph pipeline.dot --config run.yaml --preflight ./kilroy attractor run --graph pipeline.dot --config run.yaml --test-run

Preflight-only mode contract:

On success, stdout includes:

If autostart is used, startup logs are written under {logs_root}:

Observe and intervene during long runs:

./kilroy attractor status --logs-root ./kilroy attractor stop --logs-root --grace-ms 30000 --force

CXDB Autostart Notes

Provider Setup

Provider runtime architecture:

CLI backend command mappings:

Execution policy:

API backend environment variables:

API prompt-probe tuning (preflight):

Run config policy takes precedence over env tuning:

Kimi compatibility note:

Node Attributes

Node attributes are DOT key=value pairs on [shape=box] nodes that control engine behaviour.

Output token limit (max_tokens)

Every provider adapter has a built-in default output token cap of 32768 tokens. This is the per-response limit — how many tokens the model may generate in a single API call. It is completely separate from the model's input context window.

Override it per-node with max_tokens:

implement [ shape=box, max_agent_turns=300, max_tokens=32768, // default; increase for very large file writes prompt="..." ]

Why this matters: If max_tokens is too small the model will silently hit the cap mid-generation (especially during large write_file tool calls), return an empty or truncated response, and Kilroy will interpret the session as cleanly ended. For nodes that write large files (full source modules, extensive spec documents), keep max_tokens at 32768 or higher.

Provider-specific behaviour:

Provider When max_tokens omitted Notes
Google (Gemini) 32768 Always sent; Google API requires the field
Anthropic 32768 Always sent; Anthropic API requires the field
OpenAI (Responses) omitted (API uses model default) Only sent when explicitly set
OpenAI-compat omitted (API uses model default) Only sent when explicitly set
Kimi max(32768, 16000) 16000 minimum enforced by provider policy

Turn budget (max_agent_turns)

Caps the number of agent turns (model calls) in a single session. Defaults to unlimited.

implement [shape=box, max_agent_turns=300, prompt="..."]

Reasoning effort (reasoning_effort)

Passed to the model as the reasoning effort parameter where supported (e.g. low|medium|high for Anthropic extended thinking, o1-family models).

review [shape=box, reasoning_effort=high, prompt="..."]

Run Artifacts

Typical run-level artifacts under {logs_root}:

Typical stage-level artifacts under {logs_root}/{node_id}:

Commands

kilroy attractor run [--preflight|--test-run] [--allow-test-shim] [--force-model <provider=model>] --graph <file.dot> --config <run.yaml> [--run-id <id>] [--logs-root <dir>]
kilroy attractor resume --logs-root <dir>
kilroy attractor resume --cxdb <http_base_url> --context-id <id>
kilroy attractor resume --run-branch <attractor/run/...> [--repo <path>]
kilroy attractor status --logs-root <dir> [--json]
kilroy attractor stop --logs-root <dir> [--grace-ms <ms>] [--force]
kilroy attractor validate --graph <file.dot>
kilroy attractor ingest [--output <file.dot>] [--model <model>] [--skill <skill.md>] <requirements>
kilroy attractor serve [--addr <host:port>]

--force-model can be passed multiple times (for example, --force-model openai=gpt-5.4 --force-model google=gemini-3-pro-preview) to override node model selection by provider. Supported providers are openai, anthropic, google, kimi, zai, and minimax (aliases accepted).

Additional ingest flags:

Exit codes:

HTTP Server Mode (Experimental)

This feature is experimental and subject to breaking changes.

kilroy attractor serve starts an HTTP server that exposes pipeline management via a REST API with Server-Sent Events (SSE) for real-time progress streaming. This enables remote pipeline submission, live observability dashboards, and web-based human-in-the-loop gates.

kilroy attractor serve # listens on 127.0.0.1:8080 kilroy attractor serve --addr :9090 # custom address

Endpoints:

Method Path Description
GET /health Server health and pipeline count
POST /pipelines Submit a pipeline run
GET /pipelines/{id} Pipeline status
GET /pipelines/{id}/events SSE event stream
POST /pipelines/{id}/cancel Cancel a running pipeline
GET /pipelines/{id}/context Engine runtime context
GET /pipelines/{id}/questions Pending human-gate questions
POST /pipelines/{id}/questions/{qid}/answer Answer a question

The server defaults to localhost-only binding and includes CSRF protection. There is no authentication — do not expose to untrusted networks.

Skills Included In This Repo

References

License

MIT. See LICENSE.