Kontora is an agent orchestration tool. You write tickets as markdown files, it runs AI agents through multi-step pipelines, each in its own git worktree and tmux session.
tmux session view
Features
Multi-stage pipelines with per-stage retry and failure policies (implement, review, fix, commit)
Git worktree isolation per ticket, so agents never conflict
The wizard walks you through agent selection, directories, and settings, then writes ~/.config/kontora/config.yaml.
To have a coding agent write the config instead, run kontora setup --agent. It prints a brief for the agent to follow and writes nothing itself. The brief is embedded in the binary, so it describes the schema the installed version accepts. Use the same command later to add agents, stages, pipelines, or projects.
Start the daemon:
kontora start
Create a ticket:
cd ~/projects/myproject
kontora new "Add a health check endpoint"
Kontora picks it up, creates a git worktree, runs the agent, and marks the ticket done on success (or pauses it on failure).
The CLI can drive a daemon running on another machine over the same HTTP API the web UI uses. This is meant for a trusted network such as a Tailscale tailnet.
On the daemon host, bind the web server to the tailnet IP and set a shared token:
Instead of writing the token into the config file, you can pass it to kontora start through the KONTORA_WEB_TOKEN environment variable, which overrides web.token. This lets a deployment inject it from a secret. It is a daemon-side setting, unrelated to the CLI's own KONTORA_TOKEN.
When web.token is set, the daemon requires it on every /api/* and /ws/* request. GET /health and the static UI stay public. The browser UI keeps working: open http://<host>:8080/?token=<secret> once and it stores a kontora_token cookie for subsequent API, SSE, and WebSocket calls.
From another host, point the CLI at the daemon with KONTORA_URL and KONTORA_TOKEN (or --url/--token):
export KONTORA_URL=http://100.x.y.z:8080
export KONTORA_TOKEN=<the-same-secret>
kontora ls
kontora run <id>
kontora logs <id>
kontora attach <id> # live terminal over WebSocket
Remote mode needs no local config file. It supports ls, view, new, init, update, delete, run, pause, retry, cancel, done, skip, set-stage, note, summary, logs, config, and attach. Verbs that act on local files (edit, archive, fmt, doctor, start, setup, completion) are rejected in remote mode. Configure the daemon host by running kontora setup there. Paths passed to kontora new --path refer to the daemon host's filesystem, not the caller's.
[!WARNING]
The token is the only thing gating remote access, and the default config runs agents with --dangerously-skip-permissions (effectively remote code execution). On a tailnet the transport is already encrypted, so plain HTTP is acceptable. On any untrusted network, put the daemon behind TLS (e.g. a reverse proxy) — the token alone is sent in clear over plain HTTP.
Tickets
Tickets are markdown files with YAML frontmatter, inspired by wedow/ticket:
---
id: kon-q88f
kontora: true
status: todo
pipeline: default
path: ~/projects/kontora
---
# Add GoReleaser to kontora
Automate GitHub Releases with zig cc cross-compilation.
Create them with kontora new or write them by hand. Kontora lists any valid ticket with an id, but kontora: true is required before the daemon will execute it; otherwise the UI marks it as not a kontora ticket. Full reference: docs/tickets.md
Package stats aggregates ticket history into the figures the Stats page shows: throughput over time, per-stage and per-agent quality, and per-project output.
Package stats aggregates ticket history into the figures the Stats page shows: throughput over time, per-stage and per-agent quality, and per-project output.