Skip to content
v0.10.1

CLI

markdown

The CLI reads and updates the same tasks as the board. A running board picks up saved changes automatically.

Terminal window
tsk add -t "Fix login timeout"
tsk list

Install the skill with tsk setup pi, or use your agent’s setup target. tsk guide prints the workflow.

  1. Read the task with tsk list T12.
  2. Set its status with tsk status T12 started (or ready to pick it from the inbox).
  3. Update notes or steps as work progresses.
  4. Set review, blocked, open, or done explicitly.

The CLI can mark a task done with tsk status <task> done. Agent lifecycle does not change task status automatically.

Use --json on add or list for machine-readable output. Read the exit contract before retrying a write.

CommandAction
tskOpen the board
tsk captureOpen capture; save or discard exits
tsk addAdd a task or JSON plan
tsk listRead tasks
tsk statusSet task status
tsk editReplace title or notes
tsk stepsAdd, toggle, rename, or remove steps
tsk archive / tsk unarchiveHide or restore a task
tsk project archive / tsk project unarchiveHide or restore a project
tsk trash restoreRestore a task from trash
tsk setupConfigure Herdr or install an agent skill
tsk updateUpgrade an installer-managed copy, or print Homebrew guidance
tsk guidePrint the agent workflow
tsk help [<command>]Show the CLI reference or one command’s reference
tsk --helpShow the CLI reference
tsk --version / tsk -VPrint the installed version

tsk --help is the syntax reference. tsk help prints the same reference, and tsk help <command> is identical to tsk <command> --help. Help always wraps at 80 columns, including redirected output. Internal Herdr launcher flags are intentionally absent.

Data commands accept --state-dir <dir>. Setup, update, and guide do not use that flag.

StatusMeaning
openCaptured, not yet picked (inbox)
readyPicked, up next (on deck)
startedIn motion
blockedWaiting on something
reviewDone by the agent, waiting on you
doneClosed

T12, t12, 12, and a task UUID identify the same task. Direct lookup ignores the current project.

Board notice tasks paint as N1… (starter tasks and What's new in tsk). Those ids are board-only: the CLI does not accept N1, and default tsk list omits them. Agents ignore them.

Without a scope flag, add and filtered list use the launch repository inside Git, or desk outside Git. Commands addressed to a task ignore that default. The outside-Git current directory remains available through -p /full/path.

FlagScope
--deskDesk
-p name / --project nameExisting project uniquely matching that basename, ignoring case
-p /pathExisting absolute directory, creating a project there if needed
--all on listAll scopes

For adds, a bare project name must match exactly one project the board already knows: a project with tasks, an archived project, or the repository you launched from. Missing and ambiguous names refuse with unknown-project, for example tsk add: unknown-project: project atlss is not on the board. A new project destination requires an existing absolute directory (/… or ~/…); relative and nonexistent paths refuse. Project-filtered reads remain permissive, so tsk list -p typo returns an empty list.

Terminal window
tsk add -t "Fix login timeout" -n "Reproduce on a slow connection" --thread auth
# new tasks start open; use `tsk status T<n> ready` when picked
tsk add -t "Buy coffee" --desk
tsk add -t "Draft release notes" -p atlas --json
OptionPurpose
-t, --titleRequired task title
-n, --notesOptional notes
-p, --project or --deskDestination
--threadThread name
--jsonOne result object
--file <path> or --file -Read a JSON plan
--state-dir <dir>Alternate state directory

Duplicate detection compares the trimmed title, resolved project, and normalized thread. A matching non-deleted task succeeds without changing the task (outcome: existing in JSON), even if done or individually archived. Adding into an archived project refuses.

Plain output: added <title> or task already exists.

JSON output: outcome (created or existing), id, number, title, and project (null for desk).

Values starting with - use equals syntax: --title="-fix parser", --notes="-5 degrees", --project="-maintenance", --file=..., or --state-dir=....

Blank notes are omitted. C0 control characters in titles are rejected before trimming.

[
{"title": "Reproduce login timeout", "project": "atlas", "thread": "auth"},
{"title": "Draft release notes", "notes": "Include migration instructions"}
]
Terminal window
tsk add --file plan.json
cat plan.json | tsk add
FieldMeaning
titleRequired string
notesOptional notes
project omittedInvocation default
project: nullDesk
project stringProject name or path
thread omitted or nullNo thread
thread stringNormalized thread

Output contains created, existing, and failed arrays. Items carry their input index i; failures include code and error. Successful entries include task ID, number, and title. Notes are not echoed.

Valid items persist even if another item fails. Retry only failed or confirmed-missing items.

Do not mix item flags with --file. Piped input is ignored when item flags are present.

Terminal window
tsk list
tsk list T12
tsk list --all --json
tsk list -p atlas --thread auth
tsk list --done --all
tsk list --open --all
tsk list --ready --all
tsk list --archived --all
tsk list --deleted --all
tsk list [<task>] [-p <project> | --desk | --all] [--thread <name>] [--open | --ready | --done | --deleted | --archived] [--json] [--state-dir <dir>]
FilterResult
DefaultOpen, ready, started, blocked, and review tasks; excludes archived, deleted, and notice (N) tasks
--openInbox tasks with status open
--readyPicked on-deck tasks with status ready
--doneCompleted tasks
--archivedIndividually archived tasks and tasks in archived projects, across statuses
--deletedLive soft-deleted tasks and trash.jsonl entries, deduped by task with the live copy winning, newest deletion first. Trash is retained for 30 days, see storage.
--threadFilter within the selected scope

Scope flags are mutually exclusive. So are --open, --ready, --done, --deleted, and --archived.

A direct task address searches the main store, including done, archived, and recently deleted tasks. It cannot be combined with scope, thread, or status filters. A missing task exits 2. A task already moved to trash.jsonl is not addressable; find it with tsk list --deleted (optionally -p), or restore it with tsk trash restore.

Human output groups by status in STARTED, READY, OPEN, BLOCKED, REVIEW order; filtered rows include the task number and thread, and --all adds scope labels using a unique concise trailing path or desk. List output and errors wrap to the attached terminal width with hanging indentation. Task rows, scope labels, notes, steps, archived marks, and threads use the same wrapping behavior, supported from 50 columns. Redirected output keeps stored logical lines. Command help is reference text and instead always wraps at 80 columns.

Single-task output removes the thread from the title row and presents notes, steps, then #thread as separate blocks. A blank line separates adjacent blocks that exist. Human step rows show state and text without machine-oriented short IDs.

JSON returns an array with id, number, title, status, project, and thread. Direct lookup returns the complete task, including notes (null when absent) and steps (an empty array when absent). Its fields are ordered id, number, project, status, title, notes, steps, thread; each JSON step retains its short_id for step commands. Archived listings include an archived mark: archived or project archived.

Terminal window
tsk status T12 open
tsk status T12 ready
tsk status T12 started
tsk status T12 review

Accepts open, ready, started (or start), blocked, review, and done.

Unlike keyboard toggles, this command sets the requested status directly. Repeating the same value is safe.

Output: status T12 <status> <title>. The output uses started, even when the input was start.

Terminal window
tsk edit T12 --title "Fix timeout on slow connections"
tsk edit T12 --notes "Reproduced with a delayed response"

Requires --title, --notes, or both. Scope and thread stay unchanged.

Blank notes clear the field. Notes preserve newlines and tabs. Use --title=... or --notes=... for values starting with -.

Output: edited T12 <title>. Repeating the same values is safe.

tsk steps <task> add <text> [--state-dir <dir>]
tsk steps <task> toggle <step-short-id> [--state-dir <dir>]
tsk steps <task> rename <step-short-id> <text> [--state-dir <dir>]
tsk steps <task> remove <step-short-id> [--state-dir <dir>]

Read short IDs with tsk list T12 --json. Full step UUIDs also work.

ActionOutput prefixSafe to repeat unchanged?
Addadded <short-id> <text>No; creates another step
Toggletoggled <short-id> [x] <text>No; flips the value again
Renamerenamed <short-id> <text>Yes
Removeremoved <short-id> <text>No; refuses after removal

Read back with tsk list T12 --json before retrying an uncertain result. Using steps on the board.

Terminal window
tsk archive T12
tsk unarchive T12

Keep the task’s status and number. Archiving removes it from working views, and it remains available through tsk list --archived until tsk unarchive returns it. Repeating either command is safe.

Output: archived T12 <title> or unarchived T12 <title>.

Unknown tasks refuse with T12 is not on the board; deleted tasks with T12 is deleted.

Terminal window
tsk project archive atlas
tsk project unarchive atlas

Accepts a project basename or path. Archiving removes the whole project from working views, while unarchiving returns its tasks in their existing statuses. Repeating an action is safe. An unknown project refuses with no project named <name> has tasks.

Restoring a project preserves task statuses and leaves individually archived tasks archived.

Output: archived project <name> or unarchived project <name>.

Terminal window
tsk list --deleted --all
tsk trash restore T12

Restore returns a task from trash with its original number, no soft-delete flag, a restored event, and a new revision. A task absent from trash, or already live, refuses with T12 is not in trash.

Recent deletions may still be in the main store; use board undo until they move to trash. Retention and storage.

Terminal window
tsk --help
tsk help list
tsk list --help
tsk --version

Use top-level help to find a command, then use either one-command form for its flags, examples, refusals, and exit contract. --version and -V print tsk <version>. They are global flags, so place them before a command.

Terminal window
tsk update

For an installer-managed copy, immediately downloads and runs the official installer to install the latest published release, then refreshes an already registered Herdr plugin and any outdated installed agent skills (details). For a Homebrew copy, it prints brew update && brew upgrade tsk; Homebrew remains responsible for its own upgrades. Reopen a running board after an upgrade.

Terminal window
tsk setup
tsk setup herdr
tsk setup agents --yes
tsk setup pi
tsk setup --skill-dir /path/to/skills
tsk setup --detected-ids
tsk setup --skill-states
tsk setup herdr --check

On a TTY, bare tsk setup detects global agent skill roots and asks once to install or update the embedded skill for every detected agent. Without a TTY it prints guidance (and the list of named targets) and does not hang. tsk setup --json prints a detection report. Two plain probes exist for installers: tsk setup --detected-ids prints space-separated detected agent ids, and tsk setup --skill-states prints an embedded <version> line followed by one tab-separated id state version path line per detected agent (missing, current, outdated, blocked-symlink).

Requires Herdr 0.9+ on PATH. Registers the installed binary and adds prefix+t and prefix+a. A plugin command you already bound to another key is left alone; setup never adds the default chord beside it. Shortcut conflicts require confirmation; noninteractive conflicts stop before writes. tsk setup herdr --check prints bound when both plugin commands are already in the config (on any keys), otherwise unbound, and changes nothing. It uses HERDR_CONFIG_PATH, then XDG_CONFIG_HOME/herdr/config.toml, then ~/.config/herdr/config.toml.

Reload, upgrades, and removal.

TargetSkills directory
pi~/.pi/agent/skills/
ompActive OMP profile’s user skills directory (normally ~/.omp/agent/skills/)
claude~/.claude/skills/
cursor~/.cursor/skills/
grok~/.grok/skills/
codex~/.agents/skills/
opencode~/.config/opencode/skills/
--skill-dir <path>The supplied directory

Setup writes tsk-cli/SKILL.md under the selected directory. OMP follows OMP_PROFILE, using legacy PI_PROFILE only when OMP_PROFILE is unset; an empty, whitespace, or default value explicitly selects the default profile. It also follows PI_CONFIG_DIR and the default profile’s PI_CODING_AGENT_DIR; invalid profile names are refused. Skill version: is independent of the crate version. A matching installed version exits 1 with skill-exists; a missing or different version updates without --force. --force always overwrites. tsk setup agents --yes installs or updates every detected agent without asking; tsk setup agents --yes --force also rewrites copies whose version already matches. --force without --yes is a usage error for agents. Only global skill roots are offered (project-local roots are out of scope).

OptionAction
--yesWith agents, install/update detected agents without asking
--forceReplace an existing skill even when versions match
--jsonMachine-readable outcome
--detected-idsPrint detected agent ids (installer use)
--skill-statesPrint each detected agent’s skill state (installer use)

Symlinks at the skills root, skill directory, or file are refused. Herdr setup does not accept these agent options.

Setup exits 0 for success/help/list/detection, 1 for setup failure or skill-exists, or 2 for invalid arguments.

Terminal window
tsk guide

Prints the embedded agent skill without YAML frontmatter. Exits 0. It is the same workflow installed by agent setup.

For data commands:

ExitMeaningNext step
0Success, including an already-existing task or unchanged valueContinue
1Refusal; a plan may have saved other itemsCorrect refusals; retry only failed items
2Invalid arguments or input; nothing savedFix the invocation
3Storage error; a write may have committedRead back before retrying

After an uncertain add, inspect tsk list --all --json. Also check --done and --archived when a duplicate could be hidden there. If you know the task number, use direct lookup.

CommandRefusal codes
Addempty-title, invalid-title, invalid-thread, invalid-item, unknown-project, project-archived
Stepsempty-step-text, invalid-step-text, unknown-task, soft-deleted-task, unknown-step, ambiguous-step
Statusunknown-task, soft-deleted-task
Editunknown-task, soft-deleted-task, empty-title, invalid-title
Archive / unarchiveunknown-task, soft-deleted-task

A refusal prints as tsk <command>: <code>: <message> on stderr, for example tsk status: unknown-task: T99 is not on the board. Branch on the code; the message is for people and may change.

Invalid thread flags fail argument parsing with exit 2; an invalid thread in a JSON plan is an item refusal with exit 1. Unknown or archived project refusals save nothing for that item; other valid plan items can still save.

Human-readable output escapes stored terminal control characters. JSON retains the underlying text.

tsk --find-board-pane reads Herdr pane list JSON from stdin and prints the ID of the pane labelled tsk. It exits 1 if none matches.