tasks
CLI reference

Commands

Every command, flag, exit code, and failure mode.

This page describes the reference implementation

It documents the @speekl/tasks CLI specifically. The parts that are contract — exit codes and --json shapes — are defined normatively in CLI contract; command names and flags are this tool's own surface.

Every command accepts --json. Under --json, successful output goes to stdout and errors go to stderr as {"error": {"code", "message", "details"}}. See the JSON contract for shapes and exit codes.

Global flags:

FlagEffect
-v, --versionPrint the CLI version and exit 0.
-h, --helpPrint help for the program or a subcommand and exit 0.
--jsonEmit machine-readable JSON, including for errors.

tasks init

Scaffold a .tasks/ directory in the current project.

tasks init [--force] [--no-skill] [--json]
FlagEffect
--forceReinitialize even if .tasks/ already exists. Existing files are not clobbered.
--no-skillSkip installing the agent skill into .claude/skills/tasks/.

Creates config.yml, README.md, .gitignore, and the .locks/ directory, then installs the agent skill.

Fails with exit 4 if .tasks/ already exists and --force was not passed.

Ask before running this

Creating .tasks/ is a project-level decision. An agent should ask rather than run init as a side effect of a question about work.

tasks new

Create a task from the template, in a given phase.

tasks new <phase> <name...> [--id <id>] [--json]
Argument / flagMeaning
<phase>Phase directory. Created if it does not exist.
<name...>Human-readable title. Unquoted words are joined.
--id <id>Explicit id. Defaults to a kebab-case slug of the name.
tasks new auth-rework "Design token schema"
tasks new auth-rework Design token schema --id token-schema

The body is scaffolded with ## Description, ## Acceptance criteria, and ## Notes. Fill it in with a normal file edit at the path returned under --json.

Fails with exit 2 if the id is not lowercase kebab-case, or the phase is not a valid slug. Fails with exit 4 if the id is already taken by a live or archived task — archived ids stay reserved so a new task can never silently inherit an archived one's inbound dependencies.

tasks list

List tasks, filterable.

tasks list [-p <phase>] [-a] [-s <status>] [--json]
FlagEffect
-p, --phase <phase>Restrict to one phase.
-a, --allSearch every phase, ignoring active_phase.
-s, --status <status>Restrict to one status.

Without -p or -a, output is scoped to active_phase from config.yml when it is set. If a task you expect is missing, retry with --all before concluding it does not exist.

Fails with exit 2 if --status names a status that is not in the configured list.

tasks show

Print one task's metadata, resolved dependencies, and body.

tasks show <id> [--json]

Under --json this is the richest single-task shape: it adds title, ready, dependencies[] (each with satisfied, status, reason), and body.

Fails with exit 3 if no such task exists.

tasks ready

List unblocked tasks — what can be worked on right now.

tasks ready [-p <phase>] [-a] [--json]

A task appears when its status is the ready role and every dependency is satisfied. An empty result is success: exit 0 with {"count": 0, "tasks": []}.

tasks ready --json | jq -r '.tasks[0].id // empty'

tasks claim

Take ownership of a task and mark it in progress.

tasks claim <id> [--as <who>] [--force] [--json]
FlagEffect
--as <who>Identity to record. Defaults to $TASKS_ACTOR, then $USER / $USERNAME, then unknown.
--forceClaim even if dependencies are unsatisfied.

Claim is legal from any status that can reach the claimed role — not just the ready one. That is what makes reopening a completed task work (DONE → IN_PROGRESS) while still recording who took it on.

Fails with exit 4 when the task is already claimed, when the transition to the claimed role is illegal from its current status, or when a dependency is unsatisfied and --force was not passed.

What --force does and does not override

--force overrides dependencies, not somebody else's claim. A CONFLICT saying a task is already claimed means someone else has it — pick a different task, do not reach for --force.

tasks release

Give up a claimed task and return it to the ready pool. Clears claimed_by and claimed_at.

tasks release <id> [--json]

Fails with exit 4 if the task is not currently in the claimed status, or if claimed → ready is not a legal transition under this project's rules.

tasks status

Move a task through its lifecycle, validating the transition.

tasks status <id> <STATUS> [--json]
tasks status token-schema DONE

Leaving the claimed status releases the claim automatically.

Fails with exit 2 if the status is unknown, or if the target is the claimed role — that case redirects to tasks claim so claim metadata can never be bypassed. Fails with exit 4 if the task already has that status, or the transition is illegal; the error's details.allowed lists what is legal from here.

{
  "error": {
    "code": "CONFLICT",
    "message": "Illegal transition PENDING -> DONE. Allowed from PENDING: IN_PROGRESS.",
    "details": {
      "id": "token-schema",
      "from": "PENDING",
      "to": "DONE",
      "allowed": ["IN_PROGRESS"]
    }
  }
}

tasks dep

Manage dependencies. See dependencies for reference syntax.

tasks dep add <id> <ref>... [--json]
tasks dep rm  <id> <ref>... [--json]
tasks dep list <id> [--json]

add validates before writing: it refuses a self-reference and a local ref to a task that does not exist (exit 2 / 3), and refuses to introduce a cycle (exit 4). Duplicates are silently ignored rather than appended twice.

rm fails with exit 3 if the task does not currently depend on one of the given refs — removing something that was never there is treated as a mistake, not a no-op.

list resolves each dependency and reports whether it is satisfied, plus a reason when it is not.

tasks move

Reassign a task's phase, relocating the file.

tasks move <id> <phase> [--json]

Always use this rather than mv: the directory determines the phase, and the move is ordered write-then-unlink so a crash leaves a duplicate that validate reports rather than losing the task. An emptied phase directory is cleaned up.

Fails with exit 4 if the task is already in that phase.

tasks delete

Archive a task, or permanently remove it.

tasks delete <id> [--force] [--purge] [--json]
FlagEffect
--forceDelete even if other tasks depend on it.
--purgePermanently remove the file instead of archiving it.

The default moves the task to .tasks/.archive/<id>.md, preserving the originating phase in frontmatter — the archive is flat, so the directory can no longer carry it. Archived tasks are excluded from every default query, never satisfy a dependency, and keep their id reserved.

Fails with exit 4 if live tasks depend on it and --force was not passed. With --force, those dependents are reported as orphaned_dependents and are now permanently blocked — run tasks validate.

tasks reindex

Regenerate _index.md from task frontmatter.

tasks reindex [--json]

_index.md is a generated overview. No command reads it, so drift is cosmetic — but it is committed, so a stale one misleads reviewers in a diff. Regenerate before committing.

tasks validate

Check tree integrity and report anything that has drifted.

tasks validate [--fix] [--json]
FindingSeverityFixable by --fix
filename-mismatcherroryes — file renamed to match id
phase-drifterroryes — phase rewritten to the containing directory
stale-indexwarningyes — _index.md regenerated
malformederrorno
duplicate-iderrorno
unknown-statuserrorno
malformed-referrorno
cycleerrorno
dependency-missing / dependency-archived / dependency-unresolved-projectwarningno

Errors exit 4, so CI can gate on them. Warnings do not — a stale _index.md is deliberately never a build failure, because the index is not a source of truth.

tasks validate --json | jq -e '.ok'

tasks skill install

Install the bundled agent skill into .claude/skills/tasks/.

tasks skill install [--force] [--json]

An existing install is left alone unless --force, so local edits survive. Use --force to refresh after upgrading the CLI. See working with agents.

On this page