Hand the Task Runner a spec in markdown and it decomposes it into ordered steps, runs each one in its own session, tests the result, retries on failure, and checkpoints progress. Designed for 10+ hours of unattended operation.
Spec → LLM decomposes → Tasks → Execute → Test → Self-review → Commit or retry
For each task:
taskrunner:{task_id}:task{N}) with full memory injectiongit diff and validatesOpen the Projects panel, describe what you want in the Compose area, optionally refine it into a structured spec (✨ Refine), then click Run. The task appears in the sidebar with live progress, step status, and pause/cancel controls.
You can also upload an existing spec file (From Spec tab) or ask in chat: "run this task spec."
kirocrew run TASK.md # auto-resume from checkpoint on restart kirocrew run TASK.md --fresh # ignore checkpoint, start over kirocrew run TASK.md --timeout 3600 kirocrew run TASK.md --no-test # skip test verification
Also available via Slack (run <path>) and the task_run MCP tool.
Any markdown file. The Task Runner isn't picky — it decomposes what's there:
# Migrate user service to Go ## Goal Rewrite the Node.js user service in Go, preserving all behavior. ## Requirements - Every existing endpoint must continue to work - Existing tests must pass - The new implementation must handle the same load ## Acceptance criteria - `curl` smoke tests pass against a local instance - All unit tests pass with `go test ./...` - No behavior change observable from the client
The LLM decomposes this into ordered tasks with dependencies, acceptance criteria, and approval gates.
If you have a rough idea rather than a spec, use ✨ Compose in the dashboard:
Refine is a single-shot LLM call — no tools, no clarifying questions.
Up to 3 concurrent task runs are allowed (_MAX_CONCURRENT_TASKS). Each gets its own:
task_id — collision-resistant ID{work_dir}/{spec_stem}/taskrunner:{task_id}:task{N} sessionkirocrew/task/{task_id} (in a worktree if a repo exists)Cancel a specific task with kirocrew run cancel <task_id>, or all with kirocrew run cancel.
Tasks can be paused mid-run and resumed later without losing progress:
# In the dashboard Tasks panel: Pause button # In Slack: run pause <task_id> # REST: POST /api/taskrunner/{task_id}/pause
Resume by calling execute with fresh=false:
PENDINGWith fresh=true, all tasks reset — you re-run from the beginning.
On gateway restart, any task with status == "running" is automatically transitioned to "paused". This prevents zombie tasks that appear running but have no backing asyncio task. Resume manually from the dashboard.
Runs are persisted to ~/.kiro/crew/tasks/runs.json and reload on startup.
Steps can be marked with force_approval: true in the spec. These gates block execution even in YOLO mode:
Use force-approval for destructive operations (deploy, delete, publish, rm -rf).
Each task runs on its own isolated git branch:
git worktree add creates an isolated working directory; your checkout is untouchedgit init in the work directory, then checkout kirocrew/task/{task_id}Per-step:
git add -A && git commit after each passed stepgit reset --hard HEAD~1 when review fails, before retrygit log --oneline + git diff --stat injected into the next step's promptgit diff HEAD~1 fed to the independent reviewerGit init failure is non-fatal — the task continues without git coordination.
Each step passes through an independent reviewer using a separate session (taskrunner:{task_id}:review):
git diff HEAD~1 (not the LLM's self-report)Set the step's status transitions through REVIEWING (visible in the UI as 🔍) before promoting to PASSED.
| Layer | Cap | Purpose |
|---|---|---|
MAX_RETRIES | 3 | Logic/test failure retries per step |
MAX_RECOVERIES | 2 | Process crash recovery budget per step |
MAX_REPLAN | 2 | Plan revisions after a step exhausts retries |
MAX_TOTAL_TASKS | 50 | Hard cap on total tasks (including replans) |
When a step exhausts its retries, the task runner asks the LLM to revise the plan. Up to 2 replans before failing the run.
Cycle detection: 2 identical errors → warning; 3 identical errors → step marked FAILED with "Loop detected". Process crashes don't count toward this.
Tasks in the spec can declare dependencies. Tasks without cross-dependencies run in parallel batches of 3 (_MAX_PARALLEL_TASKS):
asyncio.gather(..., return_exceptions=True)This prevents 5N MCP-server-process cold-start bursts (N parallel tasks = ~5N processes if not batched).
Every step gets:
is_new=True on the first message so injection fires once, then follow-ups reuse contextActivity-aware stall detection tracks run.last_task_time, bumped on every stream chunk, tool approval, or recovery:
| Threshold | Action |
|---|---|
| 60 min no activity | ⚠️ Warning notification |
| 2 h no activity | 🔧 Session reset → recovery retry |
Reset cancels the current step session; the retry can fire again if it also stalls.
Every event gets a notification prefixed with [spec_name]:
Once a task completes, you can open its result inline in a new chat slot:
POST /api/taskrunner/{task_id}/to-chat
This creates a new chat session pre-loaded with the task's spec, plan, and per-step results. From there you can ask follow-up questions or iterate.
Task state is projected into ~/.kiro/crew/tasks/runs.json with:
Deleting a run via DELETE /api/taskrunner/{task_id} removes it from memory and disk.
The dashboard exposes an auto_approve toggle per-run:
The trust is TTL-bounded (dashboard window, 6h max, 24h hard ceiling). Each auto-approved tool call slides the grant forward — an actively-progressing run won't lose trust mid-flight, but an abandoned idle run lapses.
Force-approval gates still block. Hook deny-lists and sensitive-path blocks still apply. auto_approve is scoped tightly and never leaks to cron or MCP-launched runs (those are headless by construction).
A task step can spawn subagents:
parent_session_key = taskrunner:{task_id}:task{N}This composes cleanly for tasks like "run this analysis against every package in the repo" — the step fans out to subagents, waits for the digest, then continues.
Task-runner-related settings:
| Constant / config | Default | Purpose |
|---|---|---|
MAX_RETRIES | 3 | Retries per step |
MAX_RECOVERIES | 2 | Crash recoveries per step |
MAX_REPLAN | 2 | Replans per run |
MAX_TOTAL_TASKS | 50 | Total task cap including replans |
_MAX_PARALLEL_TASKS | 3 | Parallel batch size |
_MAX_CONCURRENT_TASKS | 3 | Concurrent runs |
CONTEXT_COMPACT_PCT | 80.0 | Session compact threshold |
TEST_TIMEOUT | 5400 | 90 min for test command |
STALL_TIMEOUT | 3600 | 60 min → warn |
STALL_CANCEL_TIMEOUT | 7200 | 2 h → reset session |
PROGRESS_FILE | TASK_PROGRESS.md | Written next to spec file |
Task Runner