Task Management

ait create, ait ls, and ait update commands

ait create

Create new task files with YAML frontmatter metadata. Supports standalone and parent/child task hierarchies.

Interactive mode (default — requires fzf):

  1. Draft management — If drafts exist in aitasks/new/, a menu appears: select a draft to continue editing, finalize (assign real ID and commit), or delete — or create a new task
  2. Parent selection — Choose “None - create standalone task” or select an existing task as parent from a fzf list of all tasks (shown with status/priority/effort metadata)
  3. Priority — Select via fzf: high, medium, low
  4. Effort — Select via fzf: low, medium, high
  5. Issue type — Select via fzf from aitasks/metadata/task_types.txt (bug, chore, documentation, enhancement, feature, manual_verification, performance, refactor, style, test)
  6. Status — Select via fzf: Ready, Editing, Implementing, Postponed
  7. Labels — Iterative loop: pick from existing labels in aitasks/metadata/labels.txt, add a new label (auto-sanitized to lowercase alphanumeric + hyphens/underscores), or finish. New labels are persisted to the labels file for future use
  8. Dependencies — fzf multi-select from all open tasks. For child tasks, sibling tasks appear at the top of the list. Select “None” or press Enter with nothing selected to skip
  9. Sibling dependency (child tasks only, when child number > 1) — Prompted whether to depend on the previous sibling (e.g., t10_1). Defaults to suggesting “Yes”
  10. Task name — Free text entry, auto-sanitized: lowercase, spaces to underscores, special chars removed, max 60 characters. Preview shows draft_*_<name>.md (real ID is assigned during finalization)
  11. Description — Iterative loop: enter text blocks, optionally add file references (fzf file walker with preview of first 50 lines, can also remove previously added references), then choose “Add more description” or “Done - create task”
  12. Post-creation — Choose: “Finalize now” (claim real ID and commit), “Show draft”, “Open in editor” ($EDITOR), or “Save as draft” (finalize later via ait create or --batch --finalize)

Batch mode (for automation and scripting):

# Creates draft in aitasks/new/ (no network needed)
ait create --batch --name "fix_login_bug" --desc "Fix the login issue"

# Auto-finalize: claim real ID and commit immediately (requires network)
ait create --batch --name "add_feature" --desc "New feature" --commit

# Finalize a specific draft
ait create --batch --finalize draft_20260213_1423_fix_login.md

# Finalize all pending drafts
ait create --batch --finalize-all

# Child task (auto-finalized with --commit)
ait create --batch --parent 10 --name "subtask" --desc "First subtask" --commit

# Read description from stdin
echo "Long description" | ait create --batch --name "my_task" --desc-file -
OptionDescription
--batchEnable batch mode (non-interactive)
--name, -n NAMETask name (required, auto-sanitized)
--desc, -d DESCTask description text
--desc-file FILERead description from file (use - for stdin)
--priority, -p LEVELhigh, medium, low (default: medium)
--effort, -e LEVELlow, medium, high (default: medium)
--type, -t TYPEIssue type from task_types.txt (default: feature)
--status, -s STATUSReady, Editing, Implementing, Postponed (default: Ready)
--labels, -l LABELSComma-separated labels
--deps DEPSComma-separated dependency task numbers
--verifies IDSComma-separated task IDs this task verifies (usually a manual_verification task, but any issue type may carry it)
--also-blocks-dependents GATESComma-separated gates that must also pass before this task’s dependents unblock, beyond the registry defaults. Writes also_blocks_dependents
--file-ref REFAdd a file reference (path, path:N, or path:N-M; repeatable)
--parent, -P NUMCreate as child of parent task number
--no-sibling-depDon’t auto-add dependency on previous sibling
--assigned-to, -a EMAILAssignee email
--issue URLLinked issue tracker URL
--pull-request URLLinked pull request URL
--contributor NAMEExternal contributor name for Co-Authored-By
--contributor-email EMAILExternal contributor email
--commitClaim real ID and commit to git immediately (auto-finalize)
--finalize FILEFinalize a specific draft from aitasks/new/ (claim ID, move to aitasks/, commit)
--finalize-allFinalize all pending drafts in aitasks/new/
--silentOutput only filename (for scripting)

Key features:

  • Tasks are created as drafts in aitasks/new/ by default (no network required). Finalization claims a globally unique ID from an atomic counter on the aitask-ids git branch
  • Drafts use timestamp-based filenames (draft_YYYYMMDD_HHMM_<name>.md) and are local-only (gitignored)
  • Child task IDs are assigned via local scan (safe because the parent’s unique ID acts as a namespace)
  • Atomic counter fallback: in interactive mode, warns and asks for consent to use local scan; in batch mode, fails hard if counter is unavailable
  • Child tasks stored in aitasks/t<parent>/ with naming t<parent>_<child>_<name>.md
  • Updates parent’s children_to_implement list when creating child tasks
  • Name sanitization: lowercase, underscores, no special characters, max 60 chars
  • Duplicate ID detection: ait ls warns if duplicate task IDs are found; ait update fails with a suggestion to run ait setup

ait ls

List and filter tasks sorted by priority, effort, and blocked status.

ait ls -v 15                    # Top 15 tasks, verbose
ait ls -v -l ui,backend 10     # Filter by labels
ait ls -v -s all --tree 99     # Tree view, all statuses
ait ls -v --children 10 99     # List children of task t10
ait ls -v --no-followup-kind 15 # Genuine new work only (no auto-spawned follow-ups)
ait ls --plan-approved 15       # Tasks with an approved plan awaiting implementation
ait ls --boardcol now 15        # Tasks in the board's "now" column
OptionDescription
[NUMBER]Limit output to top N tasks
-vVerbose: show status, priority, effort, issue type, follow-up kind, deferred-plan marker, assigned, issue
-s, --status STATUSFilter by status: Ready (default), Editing, Implementing, Postponed, Done, all
-l, --labels LABELSFilter by labels (comma-separated, matches any)
--type TYPEFilter by issue type. A task with no issue_type: field counts as feature
--boardcol COLFilter by board column id, exactly as the board groups tasks. Validated against the project’s configured columns (plus unordered); an unknown id is rejected
--followup-kind KINDFilter to auto-spawned follow-ups of one kind (e.g. risk_mitigation)
--no-followup-kindOnly tasks that are not auto-spawned follow-ups. Mutually exclusive with --followup-kind
--plan-approvedOnly tasks carrying plan_approved_at — an approved plan whose implementation was deliberately deferred, ready to be picked up without re-planning
--no-plan-approvedOnly tasks without that marker. Mutually exclusive with --plan-approved
-c, --children PARENTList only children of specified parent task number
--all-levelsShow all tasks including children (flat list)
--treeHierarchical tree view with children indented under parents

Sort order (unblocked tasks first, then): priority (high > medium > low) → effort (low > medium > high). Issue type, follow-up kind and the deferred-plan marker are shown in -v output but are not sort dimensions.

Deferred approved plans. A task stopped at the planning checkpoint with “Approve and stop here” keeps its plan and returns to Ready, so it otherwise looks untouched. -v renders it as Plan: approved <YYYY-MM-DD HH:MM>; the plain listing stays filename-only, so --plan-approved is how you find these without -v. The marker is cleared as soon as it stops being true — implementation starts, the plan is replanned or aborted, the task is decomposed into children, or a remote-drift stop requires re-verification. The board surfaces the same state as a · Planned card qualifier and a dedicated In-Flight lane — see In-Flight Lanes and Workflow Phases.

Board column. --boardcol answers “what is in this column?” from the CLI, resolving each task’s column through the same rule the board renders with — so its result matches a board lane exactly, including a project whose columns have been renamed.

--boardcol unordered selects the Unsorted / Inbox lane, which is two on-disk states: tasks with no boardcol field at all, and tasks explicitly moved there, which ait board and ait update --boardcol unordered both record as boardcol: unordered. Both are one lane on the board, so both match here.

An unknown column id is rejected, naming the configured ids. That matters because the alternative — returning zero rows — is indistinguishable from “that column is empty”, which is exactly what a typo or a renamed column would produce.

Follow-up kind marks a task as auto-spawned by the workflow rather than as new work. -v shows it as a Follow-up: <kind> field, present only when the task carries one — its absence means genuine new work. --followup-kind and --type both reject an unrecognised value rather than silently matching nothing.

View modes:

  • Normal (default) — Parent tasks only. Parents with pending children show “Has children” status
  • Children (--children N) — Only child tasks of parent N
  • All levels (--all-levels) — Flat list of all parents and children
  • Tree (--tree) — Parents with children indented using └─ prefix

Unnumbered task files. A listing candidate whose name carries no task id — t_something.md, where a number should follow the t — is skipped, and a warning naming the path is written to stderr. A listing row has to be addressable: everything downstream of ait ls maps a row back to a task id, and a row with no id yields an empty one, which then asks about a task that cannot exist. Skipping it silently would be no better, because the file is usually a real task nobody can reach, so the warning is what makes the defect visible. Rename the file to the naming convention to bring it back into the listing.

This covers the files ait ls actually looks at — those matching t<...>_<...>.md. A name further from the convention, such as tbroken.md, is not a listing candidate in the first place: it is absent from the listing with no warning, because nothing ever visits it. Neither shape is reachable through ait create, which always assigns an id.

Metadata format: Supports both YAML frontmatter (primary) and legacy single-line format (--- priority:high effort:low depends:1,4).


ait update

Update task metadata fields interactively or in batch mode. Supports parent and child tasks.

Interactive mode (default — requires fzf):

  1. Task selection — If no task number argument given, select from fzf list of all tasks (shown with metadata). Can also pass task number directly: ait update 25
  2. Field selection loop — fzf menu showing all editable fields with current values:
    • priority [current: medium]
    • effort [current: low]
    • status [current: Ready]
    • issue_type [current: feature]
    • dependencies [current: None]
    • labels [current: ui,backend]
    • description [edit in editor]
    • rename [change filename]
    • Done - save changes
    • Exit - discard changes
  3. Per-field editing:
    • priority/effort/status/issue_type — fzf selection from valid values
    • dependencies — fzf multi-select from all tasks (excluding current), with “Clear all dependencies” option
    • labels — Iterative fzf loop: select existing label, add new label (sanitized), clear all, or done
    • description — Shows current text, then offers “Open in editor” ($EDITOR with GUI editor support for VS Code, Sublime, etc.) or “Skip”
    • rename — Text entry for new name (sanitized), displays preview of new filename
  4. Save — Select “Done” to write changes. “Exit” discards all changes
  5. Git commit — Prompted Y/n to commit

Batch mode (for automation):

ait update --batch 25 --priority high --status Implementing
ait update --batch 25 --add-label "urgent" --remove-label "low-priority"
ait update --batch 25 --name "new_task_name" --commit
ait update --batch 10_1 --status Done           # Update child task
ait update --batch 10 --remove-child t10_1      # Remove child from parent
OptionDescription
--batchEnable batch mode
--priority, -p LEVELhigh, medium, low
--effort, -e LEVELlow, medium, high
--status, -s STATUSReady, Editing, Implementing, Postponed, Done
--type TYPEIssue type from task_types.txt
--deps DEPSDependencies (comma-separated, replaces all)
--labels, -l LABELSLabels (comma-separated, replaces all)
--add-label LABELAdd a single label (repeatable)
--remove-label LABELRemove a single label (repeatable)
--description, -d DESCReplace description text
--desc-file FILERead description from file (use - for stdin)
--name, -n NAMERename task (changes filename)
--assigned-to, -a EMAILAssignee email (use "" to clear)
--issue URLIssue tracker URL (use "" to clear)
--add-child CHILD_IDAdd child to children_to_implement
--remove-child CHILD_IDRemove child from children_to_implement
--children CHILDRENSet all children (replaces list)
--verifies IDSSet verifies list (comma-separated task IDs, replaces all)
--add-verifies IDAdd one verified task ID (repeatable)
--remove-verifies IDRemove one verified task ID (repeatable)
--also-blocks-dependents GATESSet the extra dependent-unblocking gates (comma-separated, replaces all; use "" to clear)
--file-ref REFAdd a file reference (path, path:N, or path:N-M; repeatable)
--remove-file-ref REFRemove a file reference (exact-string match; repeatable)
--boardcol COLBoard column ID. Validated against the project’s configured columns (plus unordered); an unknown id is rejected. Use "" to clear
--boardidx IDXBoard sort index
--pull-request URLLinked pull request URL (use "" to clear)
--contributor NAMEExternal contributor name for Co-Authored-By (use "" to clear)
--contributor-email EMAILExternal contributor email (use "" to clear)
--folded-tasks IDSComma-separated task IDs merged into this task
--folded-into NUMPrimary task number this was merged into
--implemented-with STRINGAgent/model attribution (e.g., claudecode/opus4_7_1m)
--commitAuto-commit to git
--silentOutput only filename

Key features:

  • Auto-updates updated_at timestamp on every write
  • Child task format: use 10_1 or t10_1 to target child tasks
  • When a child task is set to Done, automatically removes it from parent’s children_to_implement and warns when all children are complete
  • Parent tasks cannot be set to Done while children_to_implement is non-empty

Next: Board, Code Browser & Stats