CLI Command Contract
Taskledger uses a task-first command grammar:
taskledger [--root PATH] [--json] <area> <verb> [RESOURCE_REF] [--task TASK_REF] [options]
Global Options
--root PATHselects the workspace root.--jsonis root-level only and must appear before the command group.Command-local
--jsonoptions are not part of the public contract.
--cwd remains accepted as a compatibility root alias, but docs and examples
should prefer --root.
Task Scoping
Task-scoped workflow commands default to the active task. Use
--task TASK_REF when explicitly targeting another task.
taskledger plan start
taskledger plan start --task task-0001
taskledger implement resume --task task-0001 --reason "Reacquire implementation lock."
taskledger implement restart --task task-0001 --summary "Fix validation findings."
taskledger implement finish --task task-0001 --summary "Implemented."
taskledger review record --task task-0001 --result pass --summary "No blocking issues."
taskledger validate status --task task-0001
Task-resource commands accept the task as their direct positional resource:
taskledger task show task-0001
taskledger task cancel task-0001 --reason "Duplicate"
taskledger task archive task-0001 --reason "Hide historical task"
taskledger task unarchive task-0001 --reason "Restore task"
taskledger task report task-0001
Root reporting commands render standalone HTML:
taskledger report html task-0040 --output task-0040.html
taskledger report html --active --output active-task.html
taskledger report site --output .taskledger-report/
Serve supports optional positional task selection and refresh in seconds:
taskledger serve --refresh-seconds 2
taskledger serve --task task-0040 --refresh-seconds 2
Optional positional task refs are not supported for workflow commands.
Plan guidance command
taskledger plan guidance is a read-only planning helper command:
taskledger plan guidance [--task TASK_REF] [--format markdown|json]
Rules:
defaults to the active task when
--taskis omitted;--formataccepts onlymarkdownorjson;when a planning run is active, it records a one-time guidance-view marker for that run and appends a
plan.guidance.viewedevent;root
--jsoncontinues to return the standard CLI success/error envelope.
The command payload shape is:
kindtask_idhas_project_guidanceguidanceprofilequestion_policy
Plan revision commands
taskledger plan export renders an editable plan draft outside durable
storage, and taskledger plan amend applies structured plan-review edits:
taskledger plan export [--task TASK_REF] [--version latest|N] [--file PATH] [--overwrite] [--stdout]
taskledger plan amend [--task TASK_REF] [--drop-criterion CRITERION_ID ...] [--drop-todo TODO_ID ...] [--remove-file PATH ...] --reason "..."
Plan proposal commands that accept --file reject file paths under
.taskledger/ because that directory is private durable ledger state.
Plan review command
taskledger plan review is a read-only approval-facing plan renderer:
taskledger plan review [--task TASK_REF] [--version N] [--format markdown|json] [-o PATH]
Rules:
defaults to the active task when
--taskis omitted;defaults to the latest proposed plan in
plan_reviewstage when--versionis omitted;renders Markdown by default and can emit JSON-formatted content with
--format json;when
-o/--outputis provided, writes rendered content to a file path.
Archive import lock policy
Archive imports support explicit lock handling:
taskledger import ./taskledger-transfer.tar.gz --replace [--lock-policy drop|quarantine|keep]
taskledger import ./taskledger-task-<project>-<ledger>-task-0040-<ts>.tar.gz [--id-policy preserve|renumber-on-conflict|fail-on-conflict]
The default is quarantine so imported source-machine runtime locks are not
restored as active lock.yaml files. keep is diagnostic-only behavior
for full-fidelity lock restoration.
Transfer archive manifest contract
Transfer archives include both machine identity and human-readable metadata:
manifest.project.name and manifest.project.slug are display metadata,
while manifest.project.uuid remains the safety identity.
{
"project": {
"uuid": "<project_uuid>",
"name": "<project_name>",
"slug": "<project_slug>",
"ledger_ref": "<ledger_ref>"
}
}
Import compatibility is backward-safe: older archives that only contain
project.uuid and project.ledger_ref remain valid. UUID comparison is
still authoritative for import safety.
taskledger import --dry-run must not mutate taskledger state for either
archive or JSON payload imports.
Export task selection
Taskledger export supports full-ledger and task-scoped archives:
taskledger export
taskledger export ./backup.tar.gz
taskledger export --task task-0040
taskledger export task-0040
taskledger export task-0040 -o ./task0040.tar.gz
Positional Resource Refs
Positional refs are reserved for the direct resource being changed or shown:
taskledger task create TITLE [options]
taskledger task record TITLE [options]
taskledger task activate TASK_REF
taskledger task follow-up PARENT_REF TITLE [options]
taskledger todo done TODO_ID --task TASK_REF --evidence "pytest -q"
taskledger question answer QUESTION_ID --task TASK_REF --text "Yes."
taskledger handoff show HANDOFF_ID --task TASK_REF
taskledger require add REQUIRED_TASK_REF --task TASK_REF
taskledger release show 0.4.1
Release commands
Release boundaries are durable project records, not task lifecycle states:
taskledger release tag 0.4.1 --at-task task-0030 --note "0.4.1 released"
taskledger release list
taskledger release show 0.4.1
taskledger release changelog 0.4.2 --since 0.4.1 --until-task task-0035 --output /tmp/taskledger-0.4.2-changelog-source.md
release tag writes a durable release record under the current ledger’s
releases/ directory.
release changelog is read-oriented: it renders Markdown or JSON changelog
context from done tasks and may write an external output file, but it does not
mutate ledger state.
Ledger commands
Branch-scoped ledgers isolate ignored local task state by the checked-in
ledger_ref stored in taskledger.toml:
taskledger ledger status
taskledger ledger list
taskledger ledger fork feature-a
taskledger ledger switch main
taskledger ledger adopt --from feature-a task-0030
taskledger ledger doctor
ledger fork creates a new local namespace under
.taskledger/ledgers/<ref>/ and updates only Taskledger-owned ledger keys in
taskledger.toml. ledger switch changes the checked-in pointer to an
existing local ledger. ledger adopt copies a task from another local ledger
into the current ledger and renumbers on collision.
Storage and sync helper commands
Taskledger also exposes local storage discovery and sync helpers:
taskledger storage where
taskledger storage move --to ../taskledger-state/project-a --mode copy|move [--adopt-existing] [--force]
taskledger sync preflight
taskledger sync status
taskledger sync commit --message "Sync project-a taskledger state"
taskledger sync export --output ./taskledger-transfer.tar.gz
taskledger sync import ./taskledger-transfer.tar.gz --dry-run
taskledger sync git status
taskledger sync git init --repo ../taskledger-state --project-path project-a
taskledger sync git commit --message "Sync project-a taskledger state"
cd "$(taskledger sync git cd)"
git pull --ff-only
git push
taskledger sync git hooks install
taskledger sync git hooks status
taskledger sync git hooks uninstall
Rules:
storage whereis read-only and reports the resolved workspace root, config path,taskledger_dir, project identity, ledger ref, Git detection, and active lock count.storage moveupdatestaskledger.tomlatomically after the target has been copied or explicitly adopted.sync preflightperforms only local checks. It must not perform network push/pull operations.sync statusandsync commitoperate only on the Git repository that contains the resolvedtaskledger_dir.sync exportandsync importare archive aliases for the rootexport/importcommands.sync gitcommands operate on a private external Git repository that stores full project taskledger state under<repo>/<project_path>.
Config commands
Project config inspection and edits are available under config:
taskledger config list
taskledger config show
taskledger config keys
taskledger config get prompt_profiles.planning.max_required_questions
taskledger config describe prompt_profiles.planning.plan_body_detail
taskledger config set prompt_profiles.planning.max_required_questions 3
taskledger config set prompt_profiles.planning.question_policy always_before_plan
Rules:
dotted keys target nested TOML tables (for example
prompt_profiles.planning.max_required_questions);config keyslists available key names and path patterns;config describeprovides key semantics, allowed values, defaults, and whether a key is explicitly set;config setaccepts TOML literals (numbers, booleans, arrays, inline tables); when TOML parsing fails, the value is treated as a plain string;invalid values are rejected using standard LaunchError JSON/human envelopes.
next-action result contract
taskledger next-action is the preferred fresh-context entrypoint for agents
and operators. It should identify the next concrete question, todo, criterion,
plan, dependency, or repair target instead of only naming a lifecycle bucket.
Human output should stay concise but actionable:
todo-work: Implementation is in progress; 1 todos remain.
Next todo: todo-0001 -- Update next-action JSON payload.
Command: taskledger todo show todo-0001
Worker step: tester
Worker context: taskledger pipeline context tester
Worker handoff: taskledger handoff create --worker tester --summary "..."
Mark todo done after evidence exists: taskledger todo done todo-0001 --evidence "..."
Progress: 0/1 todos done
JSON output preserves the existing fields:
kindtask_idstatus_stageactive_stageactionreasonblockingnext_command
and may also include:
next_itemfor the concrete targetcommandsfor ordered command hints with one primary commandprogressfor question, todo, or validation queuesworker_pipelinewhen an enabledguidedworker pipeline has a pending step; this object includesenabled,mode,next_step,context_command, andhandoff_commandtemplate_commandplusrequired_plan_fieldsandrecommended_plan_fieldswhen the next step is regenerating a plan from answered questionsguidance_commandwhen planning guidance should be reviewed before drafting or regenerating a plan
Agents should inspect next_item, prefer next_command when it is safe,
avoid inventing question answers, and never mark todos done without evidence.
When a task is in failed_validation, next-action should direct agents
back to implementation with taskledger implement restart --summary SUMMARY.
When a task persists planning, implementing, or validating as its
status but active_stage is missing, next-action must not report
The task is cancelled. For an orphaned implementation with a still-running
latest implementation run and no active lock, it should direct agents to
taskledger implement resume --task TASK_REF --reason "...".
For an approved task with a non-implementation run still marked running,
next-action must not direct agents to taskledger implement start.
It should report a repair-oriented action and point to taskledger doctor.
Truly cancelled tasks recover through
taskledger task uncancel --task TASK_REF --reason "..."
Compact mutation output
Mutation commands emit compact acknowledgements instead of full task or run records. This reduces LLM context consumption during implementation loops.
The following commands produce compact output:
todo add: emitstodo_addedresult with new todo, progress, and next command.todo done/todo undone: emitstodo_updateresult with todo id, status, progress, and next command.implement finish: emitstask_lifecycleresult with task id, run id, status, and next command.
Human mode shows a one-line summary:
added todo-0001 on task-0001 (0/3 done)
done todo-0001 on task-0001 (1/3 done)
finished implementation run-0001 task task-0001 -> implemented
JSON mode wraps the compact result in the standard success envelope with result_type.
For full task, run, or todo details after a mutation, use:
taskledger task showortaskledger statusfor task-level detail.taskledger todo show TODO_IDfor individual todo detail.taskledger next-actionfor the next concrete step.taskledger todo nextfor the next open todo.
to a durable non-active stage rather than directly re-entering an active stage.
Run and lock repair
Managed command wrappers
plan command and implement command mirror the inner command exit code by
default.
Use --allow-failure when you intentionally want to record a non-zero inner
exit code while returning wrapper exit code 0:
taskledger plan command -- pytest tests/ -q
taskledger plan command --allow-failure -- pytest tests/ -q
taskledger implement command -- ruff check --config=.ruff.toml .
taskledger implement command --allow-failure -- python -c "raise SystemExit(7)"
Transcript review modes
task transcript defaults to review mode, which groups wrapper +
managed-shell pairs, highlights failures and wrapper/managed mismatches, and
flags late lifecycle commands. Raw per-record audit table is available with
--raw.
taskledger task transcript --task TASK_REF
taskledger task transcript --task TASK_REF --raw
taskledger task transcript --task TASK_REF --failures
--review is the default (no flag needed). --raw shows every record
without collapsing. --failures renders only failed command rows and retry
detection. --raw, --review, and --failures are mutually exclusive.
task export writes a Markdown file with a deterministic body combining a curated
archive report, raw task-bundle record files, and optional source-file snapshots.
It is the recommended command for handing a task to an LLM/coding agent.
taskledger task export TASK_REF -o task.llm.md
taskledger task export --task TASK_REF --no-source-files -o task.records.md
taskledger --json task export TASK_REF -o task.llm.md
taskledger doctor and taskledger doctor locks report running runs without
matching active locks. Orphaned running planning runs can be finished only
through an explicit repair command with a reason:
taskledger repair run --task TASK_REF --run RUN_ID --reason "Planning was already completed."
The repair command refuses to finish non-planning runs, non-running runs, or runs that still have a matching active lock.
Post-completion follow-up deltas
taskledger task follow-up PARENT_REF TITLE is the supported path for small
post-completion changes. It requires a done parent task, creates a new draft
child task with parent_task_id and parent_relation=follow_up, and keeps
the parent task terminal.
Human monitoring UI
taskledger serve is a top-level human-oriented monitoring command:
taskledger serve [TASK_REF] [--host 127.0.0.1] [--port 8765] [--refresh-seconds 2] [--open/--no-open]
Rules:
the MVP binds only to localhost;
it serves read-only server-rendered HTML pages;
browser actions are not part of the MVP;
agents should continue to use
next-action,context,view, and--jsoncommands as the canonical automation interface.
Focused context and handoff options
Code review commands
review stores optional durable code-review evidence without adding a new
lifecycle stage. Review evidence may be recorded before validation or after a
task has reached done; storing the review remains append-only and does not
reopen the completed task:
taskledger review record [--task TASK_REF] --result pass|fail|blocked (--summary TEXT | --summary-file PATH) [--from-git] [--commit COMMIT] [--worker STEP_ID] [--handoff HANDOFF_ID] [--run RUN_ID]
taskledger review list [--task TASK_REF]
taskledger review show REVIEW_REF [--task TASK_REF]
JSON mode returns a stable payload with kind = "code_review_recorded" for
review record and includes review_id, task_id, result,
source, implementation_run, worker_step_id, and compact git
metadata fields when present.
Focused worker contexts keep lifecycle mode separate from worker-role
--for:
taskledger context --for planner|implementer|validator|spec-reviewer|code-reviewer|reviewer|full [--scope task|todo|run] [--todo TODO_ID] [--run RUN_ID] [--format markdown|json|text] [--task TASK_REF]
taskledger handoff create --mode planning|implementation|validation|review|full [--for planner|implementer|validator|spec-reviewer|code-reviewer|reviewer|full] [--scope task|todo|run] [--todo TODO_ID] [--run RUN_ID] [--task TASK_REF]
taskledger handoff create --worker STEP_ID [--scope task|todo|run] [--todo TODO_ID] [--run RUN_ID] [--task TASK_REF]
taskledger pipeline context STEP_ID [--scope task|todo|run] [--todo TODO_ID] [--run RUN_ID] [--format markdown|json|text] [--task TASK_REF]
taskledger handoff show HANDOFF_ID --format text|markdown|json [--task TASK_REF]
Rules:
--todoimplies--scope todo.--runimplies--scope run.--scope todorequires--todo.--scope runrequires--run.--for implementation|validation|planning|review|fullremain accepted as compatibility aliases.handoff create --workerderives mode and context from the configured worker step and storesworker_step_idin the handoff record.pipeline context STEP_IDis equivalent tocontext --worker STEP_ID.spec-reviewerandcode-reviewerworker contexts require--runor explicit--scope taskwhen they are not bound to a validation/review run.handoff show --format markdownprints the stored snapshot body.
Removed Pre-Release Aliases
These aliases are intentionally not registered:
task newtask clear-activeimplement add-changevalidate add-checkfile linkfile unlinklink linklink unlink
Use task create, task deactivate, implement change,
validate check, file add, file remove, link add, and
link remove instead.
Approval escape hatches
Plan approval escape hatches require --reason to prevent silent bypass:
Approval also requires --note for user approval. Agent approval additionally
requires --allow-agent-approval --reason "...".
Todo source inference
When todo add is called without an explicit --source, the source is
inferred from the active lock:
Active lock stage |
Inferred source |
|---|---|
|
|
|
|
No active lock |
|
Plan-materialized todos always use source=plan.
Storage Compatibility
Taskledger stores project-local configuration in taskledger.toml at the
workspace root. .taskledger.toml is also read as a local override file when
it exists.
The resolved taskledger_dir defaults to .taskledger/ beside that config
file, but taskledger init --taskledger-dir /path/to/state may point durable
state elsewhere. Commands resolve config files upward from the starting
directory and keep --root scoped to the source workspace, not the storage
root.
Taskledger uses:
a workspace storage layout version in
taskledger_dir/storage.yamlper-record
schema_versionper-record
object_typeper-file
file_versionfor durable Markdown/YAML/JSON record files
Storage layout version history:
Layout 2: Introduced branch-scoped ledgers under
taskledger_dir/ledgers/<ledger_ref>/Layout 3: Consolidates layout-2 root-level task state into branch-scoped ledgers; migrates legacy root
tasks/,events/,intros/,releases/, andactive-task.yamlinto the active ledger namespace
Taskledger does not silently rewrite storage during read-only commands.
If the installed taskledger version can read but not write an older workspace, it reports that migration is required.
To migrate:
taskledger migrate status
taskledger migrate plan
taskledger migrate apply --backup
After migration to layout 3, verify health with:
taskledger doctor
taskledger ledger doctor
Indexes under taskledger_dir/ledgers/<ledger_ref>/indexes/ are optional derived caches or
registries. Task, plan, and run commands must continue to work from canonical
Markdown/YAML records even when task/run/plan JSON cache files are absent. The
remaining derived caches may be plain JSON arrays with no version metadata and
can be rebuilt with:
taskledger reindex
A newer storage version than the installed taskledger supports is rejected with a clear error.
Lock recovery contract
Lock diagnostics are exposed through three surfaces:
taskledger lock show --task TASKreturns adiagnosticsobject and a structured human block. Theclassificationfield names the lock state:none,expired,active_dead_local_process,active_live_local_process,active_unverifiable_remote_or_unknown_process,active_no_pid,active_same_actor, oractive_other_actor.taskledger --json next-actionreturnslock_statuswhenever a lock exists, and setsaction=repair-lockwith a diagnostics blocker when the active implementation lock has a dead local holder PID.taskledger implement resume --repair-expired-lockreturns aLOCK_CONFLICTerror (exit code 4) with diagnostics and remediation commands when the existing lock is non-expired.
--repair-expired-lock is not a general stale-lock takeover flag. It only
applies to locks whose expires_at is in the past. For non-expired active
locks, follow the classification returned by lock show or next-action.
For non-expired active locks classified as active_dead_local_process, the
canonical recovery sequence is:
taskledger repair lock --task TASK --reason "Holder PID ... is no longer running."
taskledger implement resume --task TASK --reason "Reacquire implementation lock after stale holder repair."
For active_live_local_process or active_other_actor, do not repair;
use a handoff or wait for the holder to release. For
active_unverifiable_remote_or_unknown_process, do not infer staleness
from local process checks; inspect handoffs or ask the user before repairing.