README
¶
Taskrail
Turn goals into tracked work, kept aligned to one authoritative state file.
Taskrail is a deterministic execution harness for humans and AI agents. It turns goals into structured tasks, keeps every transition aligned to a single authoritative state file, and advances work through validation, verification, and explicit follow-up.
It is built on durable primitives — Git for history and review, plain Markdown with YAML frontmatter for specs, tasks, and state. No database. No hidden automation. No opaque dashboards. Your repo stays inspectable, and the same taskrail commands work whether a person or an agent is at the keyboard.
taskrail init # adopt Taskrail in an existing repo
taskrail next --json # pick the next eligible task, deterministically
taskrail start T-001
taskrail complete T-001 --note "implemented"
taskrail verify T-001 --result pass --summary "acceptance met"
Contents
- Why Taskrail
- What It Is
- What It Is Not
- Install
- Commands
- Quickstart
- What a Verification Leaves Behind
- State Contract
- Repository Layout
- Development
- Status
- License
- Read Next
Why Taskrail
- Deterministic: next-task selection follows status, dependencies, priority, and stable tie-breaking — same repo, same answer, every time.
- State-first: one authoritative
planning/STATE.mdis the continuity and control surface for all work. - Verification as a first-class concept: completing implementation and verifying it are distinct steps, and verification leaves durable artifacts.
- Retrofit-friendly:
taskrail init(orretrofit) drops the contract into an existing repository with no rewrite. - Agent-ready: every command has a
--jsonpath where it matters, so coding agents drive the same workflow humans do.
What It Is
- A CLI for tracking repo-native work as Markdown task files with an explicit, machine-checkable schema.
- A deterministic workflow:
validate → next → start → complete → verify. - One authoritative
planning/STATE.md— the continuity and control surface for all work. - Repo-native specs under
specs/and deterministic tracked work underplanning/. - Task validation (dependency checks, spec references), deterministic next-task selection, and explicit transitions.
- A verification model that records pass/fail outcomes, writes inspectable artifacts, and opens follow-up tasks as needed.
What It Is Not
- Not a built-in LLM provider integration — Taskrail is provider-agnostic and manual-first. (
importstructures notes; it never calls a model.) - Not a sandbox, container, or worktree orchestrator.
- Not a background daemon, distributed worker pool, or multi-lane scheduler.
- Not a semantic spec-to-task generator or drift detector —
importproduces structural drafts only; LLM-assisted generation is deferred.
Install
Homebrew (macOS and Linux):
brew install tessariq/tap/taskrail
taskrail --version
This pulls the release binary from the tessariq/homebrew-tap tap.
Build from source (needs Go 1.26):
git clone https://github.com/tessariq/taskrail.git
cd taskrail
go install ./cmd/taskrail
taskrail version
Plain go build/go install produce a development build that reports version
0.0.0-dev. To produce a release build that reports a real version, inject it at
build time:
go build -ldflags "-X main.version=v0.2.0" -o taskrail ./cmd/taskrail
# or, via Taskfile:
VERSION=v0.2.0 task release
./taskrail version # -> v0.2.0
Tagged releases are automated with GoReleaser: pushing a
v* tag builds linux/darwin binaries for amd64/arm64 and publishes archives
plus checksums to a GitHub Release, with notes taken from the matching ## v<version>
section of CHANGELOG.md. The Homebrew tap is bumped by hand afterward — see
docs/workflow/releasing.md for the full checklist.
Commands
Run taskrail <command> --help for full flag details.
| Command | Purpose |
|---|---|
taskrail init |
Version-aware, non-destructive init/upgrade for empty, existing, or non-standard repos. --with-skills installs the agent skills (add --force to reinstall over existing copies, backing up local edits first); --apply writes migrations/retrofits; --json. |
taskrail retrofit [notes] |
Guided bootstrap for a non-standard repo: detect layout, import notes into a reviewable draft, scaffold specs/ + planning/. Dry run by default; --apply, --emit-prompt, --json. |
taskrail validate |
Validate layout, task shape, dependency/spec references, and STATE.md consistency. Read-only. |
taskrail repair |
Reconcile mechanical STATE.md drift (stale current_task pointer or task counts). Dry run by default; --apply rewrites STATE.md only; --json. |
taskrail coverage |
Report advisory spec coverage for the active spec in two dimensions — decomposition (gating) and report-only implementation — plus a per-area reverse map of covering task id(s) (double-covered areas flagged), orphan tasks, and drift. Read-only; never fails validate. --min <pct> (0–100) opts into CI gating: exits non-zero when decomposition coverage is below the threshold (report unchanged; N/A never gates). --area <anchor> narrows the whole report — coverage figures, reverse map, orphan/drift — to a single coverable spec area for a focused "is this feature decomposed?" check (a non-coverable anchor is rejected). --json. |
taskrail status |
Print the current tracked-work snapshot: active spec, task counts, next eligible task (computed but not persisted), blocked tasks with reasons, last verification, a one-line coverage summary, and a one-line orphan/drift summary (orphan-task and uncovered-area counts) alongside it. Read-only. --json. |
taskrail stats |
Report aggregate statistics computed snapshot-only from current task files and STATE.md: counts and percentages by status, blocked ratio and recorded-blocker count, spec coverage with a per-area breakdown, and dependency shape (unmet dependencies, longest chain). Read-only. --json. --format dot|mermaid instead exports the task dependency DAG (nodes = tasks, edges = dependencies) as Graphviz DOT or Mermaid text. |
taskrail next |
Deterministically select the next eligible task. --json. |
taskrail start <task-id> |
Mark a task active and update STATE.md. |
taskrail complete <task-id> |
Mark a task implementation-complete. --note. |
taskrail block <task-id> |
Mark a task blocked and record a --reason. |
taskrail unblock <task-id> |
Return a blocked task to todo so it re-enters next selection; drops its STATE.md blocker entry. Optional --reason appends a note. --json. |
taskrail verify <task-id> |
Record a pass/fail outcome and write artifacts under planning/artifacts/verify/. --result, --summary, --create-followup, --json. |
taskrail spec activate <version> |
Repoint STATE.md's active spec to a versioned target (e.g. v0.3.0), re-render STATE.md, and re-validate. CLI-only writer of the active spec; rejects a missing or non-conforming version with no write. --json. |
taskrail spec list |
List the versioned specs under specs/ in version order and mark the active one. Read-only. --json. |
taskrail spec show <version> |
Print a versioned spec; with --anchors, list its spec_ref heading anchors exactly as validate accepts them (so task new --spec-ref <path>#<anchor> can target a real anchor). Read-only. --json. |
taskrail spec add <version> |
Scaffold specs/<version>.md with the standard section skeleton and add it to the specs/README.md reading order. Never writes STATE.md and does not activate the spec; rejects an existing or non-conforming version with no write. --json. |
taskrail task new |
Scaffold a task file with the next free id. Requires --title and --spec-ref; --priority, repeatable --dep, --follow-up <parent-id>, --json. |
taskrail import <source> |
Build spec/task drafts from a markdown source without an LLM. --to tasks|spec|planning, --emit-prompt, --apply <draft.json>, --json. |
taskrail version |
Print the CLI version (also --version). |
Shell completion
Taskrail ships shell completion via Cobra. Load it for your shell (or add the line to your shell profile):
source <(taskrail completion bash) # bash
taskrail completion zsh > "${fpath[1]}/_taskrail" # zsh
taskrail completion fish | source # fish
Run taskrail completion --help for per-shell install steps. Completion is
read-only: it never writes STATE.md or task files. Beyond every command and
flag, it completes spec versions for spec show/spec activate and real
<path>#<anchor> values for task new --spec-ref (the anchors it offers are
exactly the ones validate accepts, so a completed reference authors a task that
passes validate).
Quickstart
Initialize Taskrail inside an existing repository, then confirm it is sane:
taskrail init
taskrail validate
Tasks live under planning/tasks/ as Markdown with YAML frontmatter:
---
id: T-001
title: Bootstrap repository structure
status: pending
priority: high
spec_ref: specs/v0.1.0.md#summary
dependencies: []
---
# T-001 Bootstrap repository structure
## Description
Create the initial Taskrail structure, specs, and planning area.
## Acceptance
- `planning/STATE.md` exists.
- `taskrail validate` passes.
Let Taskrail pick the next eligible task, start it, and advance it:
taskrail next --json
taskrail start T-001
taskrail complete T-001 --note "implementation landed"
taskrail verify T-001 --result pass --summary "validate passes; acceptance met"
When verification reveals more work, spawn a follow-up task in the same step:
taskrail verify T-001 \
--result fail \
--summary "missing dependency check" \
--create-followup \
--followup-title "Add dependency validation" \
--followup-priority high
Bootstrap drafts from rough notes without any LLM — preview first, then apply:
taskrail import notes.md --to tasks # preview the structural task drafts
taskrail import notes.md --to tasks --emit-prompt # print an agent prompt for a richer draft
taskrail import --apply draft.json # validate an agent draft and write real files
Typical flow:
- Write a goal as a Markdown task inside
planning/tasks/. validatethe repository.nextto select deterministically, thenstart.completethe implementation.verifyto record the outcome and leave artifacts — opening follow-up tasks as needed.
What a Verification Leaves Behind
Every verification writes repo-local evidence under planning/artifacts/verify/<task-id>/<timestamp>/:
planning/
STATE.md # single authoritative state surface
tasks/
T-001.md # task with frontmatter schema
artifacts/
verify/
T-001/
20260619T113646Z/
plan.md # verification plan
report.json # machine-readable outcome
report.md # human-readable outcome
These are plain files — no proprietary formats, no database required. The
planning/artifacts/ tree is gitignored, reproducible local output: verify
creates it on demand, taskrail init never pre-creates it, and neither committed
state nor validate depends on it surviving a Git round-trip.
State Contract
planning/STATE.md is the authoritative execution state. It carries the active spec, current task, status summary, blockers, the next action, and the last verification result, plus pointers to relevant artifacts. Do not hand-edit machine-managed state fields — let the taskrail transitions update them.
Repository Layout
.
├── AGENTS.md # guidance for coding agents
├── CHANGELOG.md
├── README.md
├── cmd/taskrail/ # CLI entry point
├── internal/ # core packages
├── lefthook.yml # opt-in local git hooks (mirror CI)
├── mise.toml # optional pinned developer toolchain (mise)
├── planning/ # authoritative tracked work and STATE.md
├── scripts/
└── specs/ # versioned, normative product specs
The packaged skill set lives in internal/taskrail/skills/ (embedded; installed
by taskrail init --with-skills). This repository adopts it: committed copies in
.agents/skills/ and .claude/skills/ are kept byte-identical to the package by
task check:skills.
Development
mise can pin and provision the developer toolchain (Go,
task, lefthook) from the committed mise.toml. It is optional convenience —
direct go commands and the Taskfile.yml targets work without it:
mise install # provision the pinned toolchain on a fresh clone
mise run setup # provision, build taskrail onto PATH, wire the opt-in git hooks
mise run setup (and task taskrail:install) build the working-tree
./cmd/taskrail into ./bin and mise puts ./bin on PATH, so a bare taskrail
resolves to the current build with no TASKRAIL override. task taskrail:check
fails loudly if the on-PATH binary is stale versus the working tree.
The mise.toml pins are the single source of truth: the go pin matches go.mod
and the lefthook pin matches the hooks guidance below. CI provisions the same
toolchain via jdx/mise-action, so local and
CI builds share one set of pinned versions. The build/test job runs as an OS matrix
over Linux, Windows, and macOS, catching cross-platform regressions (path
separators, line endings, file modes) before merge.
Optional git hooks mirror the CI checks locally via
lefthook. mise run setup wires them;
to install by hand:
go install github.com/evilmartians/lefthook@v1.13.6 # or: brew install lefthook
task hooks:install
pre-commit:gofmt,go vet ./...,taskrail validate, skill package-parity check.commit-msg: Conventional Commit subject; rejects automated-attribution trailers.pre-push:go test ./....
Hooks are a convenience; CI (.github/workflows/ci.yml) remains the authoritative
gate. Do not bypass them with --no-verify.
See CONTRIBUTING.md for the PR checklist, the AI-assisted contribution policy, and tracked-work rules.
Status
Taskrail is an in-progress open-source project. The current release is v0.2.0.
v0.1.0established the repository contract: deterministic task progression, the authoritativeSTATE.md, and verification as a first-class concept.v0.2.0makes adoption in existing repositories easy — guidedretrofit, LLM-freeimportof rough notes into spec/task drafts, opt-in shippable agent skills, a version-aware non-destructiveinit, and conservativeSTATE.mdrepair — while keeping the core CLI provider- and tooling-independent.- Later work is tracked under
specs/v0.3.0.md.
This repository also dogfoods the Taskrail workflow style — using planning/, docs/workflow/, and the packaged skill set it adopts like any adopter — until the product itself fully replaces that scaffolding.
License
Apache-2.0. See LICENSE.
Read Next
specs/v0.2.0.md— current release scopespecs/README.md— spec reading order and versioningplanning/STATE.md— live execution stateAGENTS.md— guidance for coding agentsCHANGELOG.md
The versioned specs in specs/ remain the normative source of truth for release scope and behavior.
Directories
¶
| Path | Synopsis |
|---|---|
|
cmd
|
|
|
taskrail
command
|
|
|
internal
|
|
|
toolchain/cmd/freshcheck
command
Command freshcheck fails loud when the taskrail binary on PATH is stale versus a freshly built one, without relying on external coreutils (mktemp/cmp/trap) that are absent on a stock native Windows install.
|
Command freshcheck fails loud when the taskrail binary on PATH is stale versus a freshly built one, without relying on external coreutils (mktemp/cmp/trap) that are absent on a stock native Windows install. |