Durable project-state storage and CLI for coding workflows
Project description
taskledger
taskledger is a task-first durable state layer for staged coding work. It keeps
project-local configuration in taskledger.toml at the workspace root and stores
plans, approval state, implementation logs, validation results, locks, and
fresh-context handoffs under a configurable taskledger_dir (default:
.taskledger/ beside that config file).
Canonical workflow
task -> plan -> approval -> implement -> validate -> done
The supported command surface is organized as:
Core workflow:
task,plan,question,implement,validate,todo
Context and decision-making:
intro,file,link,require,handoff
Operations:
context,next-action,can,search,grep,symbols,deps,actor,view,serve
Repair and inspection:
lock,doctor,repair,reindex
Project lifecycle:
init,status,export,import,snapshot,release
Which read command to use
| Need | Command |
|---|---|
| Next step | next-action |
| Next implementation item | todo next |
| Active task summary | task show |
| Specific task summary | task show TASK_REF or task show --task TASK_REF |
| Project/ledger overview | status, tree |
| Human dashboard | serve |
| Reviewable markdown report | task report |
| Fresh worker context | context or durable handoff show |
| Command audit | task transcript |
Planning guidance profiles
Taskledger supports project-local advisory planning guidance under
[prompt_profiles.planning] in the active project config file (taskledger.toml
or .taskledger.toml when legacy config is still present).
[prompt_profiles.planning]
profile = "strict"
question_policy = "always_before_plan"
max_required_questions = 3
min_acceptance_criteria = 2
todo_granularity = "atomic"
require_files = true
require_test_commands = true
require_expected_outputs = true
require_validation_hints = true
plan_body_detail = "detailed"
required_question_topics = ["scope", "compatibility", "test strategy"]
extra_guidance = "Every plan must mention docs, tests, and rollback or repair behavior."
Inspect guidance for the active task:
taskledger plan guidance
taskledger --json plan guidance
This guidance is advisory and cannot override lifecycle gates, user approval,
validation requirements, lock rules, or higher-priority harness instructions.
See docs/usage.rst for the full key reference and workflow details.
Install
python -m pip install -e .
python -m pip install -e ".[dev]"
Quick start
Initialize durable state in the current workspace:
taskledger init
# or keep storage outside the source repo
taskledger init --taskledger-dir /mnt/cloud/taskledger/my-repo
# or point at another workspace explicitly
taskledger --root /path/to/repo init
init writes taskledger.toml in the workspace root. By default that config
points at .taskledger/, but --taskledger-dir can move durable state to an
external directory without nesting another .taskledger inside it.
Create and activate a task, ask required planning questions, regenerate the plan from answers, approve it, implement todos with evidence, and validate it:
taskledger task create "Rewrite V2" --slug rewrite-v2 --description "Migrate to the task-first design."
taskledger task activate rewrite-v2 --reason "Start planning"
taskledger plan start
taskledger question add-many --required-for-plan --text $'Should exports include the new state?\nShould snapshots include implementation artifacts?'
taskledger question answer-many --text $'q-0001: Yes.\nq-0002: No.'
taskledger question status
taskledger plan template --from-answers --file ./plan.md
taskledger plan upsert --from-answers --file ./plan.md
taskledger plan lint --version 1
taskledger plan accept --version 1 --note "Ready."
taskledger next-action
taskledger --json next-action
taskledger context --for implementation --format markdown
taskledger implement start
taskledger implement checklist
taskledger implement change --path taskledger/storage/task_store.py --kind edit --summary "Normalized v2 markdown storage."
taskledger todo done todo-0001 --evidence "Updated taskledger/storage/task_store.py"
taskledger implement finish --summary "Implemented the approved plan."
taskledger context --for validation --format markdown
taskledger validate start
taskledger validate status
taskledger validate check --criterion ac-0001 --status pass --evidence "pytest -q tests/test_taskledger_v2_cli.py"
taskledger validate finish --result passed --summary "Validated the rewrite."
To revise a proposed plan, re-enter planning and edit an exported workspace
copy. Never edit .taskledger/ files directly:
taskledger plan revise
taskledger plan export --version latest --file ./plan.md
# edit ./plan.md
taskledger plan upsert --file ./plan.md
For manually completed work (e.g., manual testing, operations tasks, or work
completed outside the task-first lifecycle), use task record to create a
done task directly without acquiring lifecycle locks. Note: task record
does not replace the normal task lifecycle; it is for recording work already
completed, not as a shortcut for active task management.
taskledger task record "Deploy to production" --summary "Deployed v0.4.1 to prod" --change "infra/deploy.sh:run:Updated prod config" --evidence "Monitoring shows no errors"
taskledger task record "Manual API testing" --summary "Tested new endpoints" --allow-empty-record --reason "Exploratory testing, no formal changes tracked"
Archive is a visibility operation: it hides tasks from default list/tree/dashboard views without deleting history. Task ids stay monotonic and are never reused. Slugs can be reused after archive.
taskledger task archive task-0030 --reason "Hide historical task"
taskledger task list --archived
taskledger task unarchive task-0030 --reason "Need to continue work" --slug task-0030-reopened
taskledger tree --include-archived
If validation finds an implementation bug, keep the accepted plan and restart implementation explicitly:
taskledger validate finish --result failed --summary "Parser edge case still fails."
taskledger next-action
taskledger context --for implementation --format markdown
taskledger implement restart --summary "Fix failed validation findings."
Release tagging and changelog context
Use durable release tags to mark completed task boundaries and generate provider-neutral changelog source packs from finished tasks:
taskledger release tag 0.4.1 --at-task task-0030 --note "0.4.1 released"
taskledger release changelog 0.4.2 --since 0.4.1 --until-task task-0035 --output /tmp/taskledger-0.4.2-changelog-source.md
taskledger release show 0.4.1
taskledger release list
release changelog does not call an LLM API. It renders compact Markdown or JSON
from done tasks, implementation logs, code changes, and validation evidence so a
separate coding harness can draft the final human changelog.
taskledger next-action is the preferred fresh-context entrypoint. It stays
read-only and points at the next concrete question, todo, criterion, or repair
step.
Human output example:
todo-work: Implementation is in progress; 1 todos remain.
Next todo: todo-0001 -- Update next-action JSON payload.
Command: taskledger todo show todo-0001
Mark todo done after evidence exists: taskledger todo done todo-0001 --evidence "..."
Progress: 0/1 todos done
JSON result example:
{
"kind": "task_next_action",
"action": "todo-work",
"next_command": "taskledger todo show todo-0001",
"next_item": {
"kind": "todo",
"id": "todo-0001",
"text": "Update next-action JSON payload.",
"validation_hint": "Run: pytest tests/test_todo_implementation_gate.py -q; Expected: pass",
"done_command_hint": "taskledger todo done todo-0001 --evidence \"...\""
},
"commands": [
{
"kind": "inspect",
"label": "Show next todo",
"command": "taskledger todo show todo-0001",
"primary": true
},
{
"kind": "complete",
"label": "Mark todo done after evidence exists",
"command": "taskledger todo done todo-0001 --evidence \"...\"",
"primary": false
}
],
"progress": {
"todos": {
"total": 1,
"done": 0,
"open": 1,
"open_ids": ["todo-0001"]
}
},
"blocking": []
}
Compact implementation loop
For routine same-session implementation, prefer next-action and the single next
todo over broad generated context:
taskledger --json next-action
taskledger --json todo next
taskledger todo show todo-0003
# implement only that todo
pytest tests/...
taskledger todo done todo-0003 --evidence "pytest tests/... passed"
taskledger --json next-action
Rules for agents:
- Prefer
next-actionandtodo nextover generated context during normal work. - Use the todo
validation_hintbefore marking a todo done. - Record concise evidence with
todo done. - Do not create handoffs or context bundles unless the user asked to switch harness or session.
Human monitoring UI
taskledger serve starts a read-only local dashboard for humans monitoring task
state. It now emphasizes the active task, next action, progress, blockers, and
compact task browsing while staying local-only, read-only, and dependency-free.
The MVP still binds to localhost only, refreshes with read-only JSON polling,
and exposes no browser mutation endpoints.
taskledger serve
taskledger serve --open
taskledger serve --task rewrite-v2 --refresh-ms 2000
Agents should keep using taskledger next-action, taskledger todo next, and
--json commands as the canonical automation interface for routine same-session
work. Reach for context or handoffs when the task actually needs a broader
fresh-context transfer.
Storage layout
taskledger keeps project-local configuration in the workspace root and durable
records under the configured storage root. The checked-in .taskledger.toml
stores only a branch-scoped ledger pointer and next task number. Operational task
state remains ignored under .taskledger/ledgers/<ledger_ref>/:
.taskledger.toml
.taskledger/
storage.yaml
ledgers/
main/
intros/
releases/
tasks/
events/
indexes/ # optional derived caches and registries
Markdown files are canonical. Task, plan, and run listings scan only the current
ledger by default. JSON files under the current ledger's indexes/ directory are
optional derived caches or registries and are not required for task correctness.
Branch-scoped ledgers
.taskledger/ stays ignored and local. .taskledger.toml is safe to commit and
contains the current ledger_ref, optional parent ref, and the next logical task
number for the checked-out source branch.
When starting long-lived branch-local work, fork the ledger pointer after creating the Git branch:
git checkout -b feature-a
taskledger ledger fork feature-a
git add .taskledger.toml
Returning to a branch whose .taskledger.toml points back to main hides the
feature branch's active task and task list. Two ledgers may both contain a logical
task-0030; this is expected because task IDs are scoped by ledger_ref. Use
taskledger ledger adopt --from REF TASK_REF when branch-local task history
should be copied into the current ledger.
You can also point taskledger.toml at an external storage root:
taskledger init --taskledger-dir /mnt/cloud/taskledger/project-a
/home/me/src/project-a/taskledger.toml
/mnt/cloud/taskledger/project-a/storage.yaml
/mnt/cloud/taskledger/project-a/releases/
/mnt/cloud/taskledger/project-a/tasks/
/mnt/cloud/taskledger/project-a/events/
/mnt/cloud/taskledger/project-a/indexes/
Use one taskledger_dir per source project. Do not share one storage directory
across unrelated repositories.
JSON output
Use --json for machine-readable payloads:
taskledger --json status --full
taskledger --json task active
taskledger --json task show
taskledger --json task show task-0001
taskledger --json context --for validation --format json
Example status payload:
{
"ok": true,
"command": "status",
"result": {
"kind": "taskledger_status",
"workspace_root": "/home/me/src/project-a",
"config_path": "/home/me/src/project-a/taskledger.toml",
"taskledger_dir": "/home/me/src/project-a/.taskledger",
"project_dir": "/home/me/src/project-a/.taskledger",
"counts": {
"tasks": 1,
"introductions": 0,
"plans": 1,
"questions": 1,
"runs": 2,
"changes": 1,
"locks": 0
},
"active_task": null,
"healthy": true
},
"events": []
}
Handoff-driven work
Fresh-context handoff is a primary feature:
taskledger context --for planning --format markdown
taskledger context --for implementation --format markdown
taskledger context --for validation --format json
taskledger task dossier --format markdown
taskledger task report --task task-0030 -o task30.md
taskledger handoff create --mode implementation --intended-actor agent --intended-harness codex
taskledger handoff claim handoff-0001
taskledger handoff close handoff-0001 --reason "Implementation started."
Fresh-worker contexts
Use focused contexts when handing one todo or one review run to a fresh worker:
taskledger context --for implementer --todo todo-0003
taskledger context --for spec-reviewer --run run-0008
taskledger context --for code-reviewer --run run-0008
taskledger handoff create --mode implementation --todo todo-0003
taskledger handoff show handoff-0001 --format markdown
handoff create now stores the generated Markdown context snapshot in the handoff
record so another harness can continue from the exact same input.
Multi-Actor Handoff Protocol
The handoff protocol enables safe work transitions between human and agent actors across different harnesses:
Features
- Actor Identity: Track WHO performs each stage (human, agent, system)
- Harness Tracking: Record FROM WHERE each stage ran (manual, Codex, OpenCode, etc.)
- Handoff Records: Explicitly hand off work with context and intent
- Claim Protocol: New actors claim handoffs before starting work
- Lock Management: Transfer or release locks during handoffs
- Event Trail: Full audit trail recording all state changes
- Durable Records: Markdown-first storage with YAML metadata
Quick Start
# See your current identity
$ taskledger actor whoami
# Create a handoff
$ taskledger handoff create --task task-0001 --mode implementation --todo todo-0003
# Claim it
$ taskledger handoff claim handoff-0001 --task task-0001
# Show details
$ taskledger handoff show handoff-0001 --task task-0001 --format text
# Close when done
$ taskledger handoff close handoff-0001 --task task-0001 --reason "Continued."
See docs/usage.rst and skills/taskledger/SKILL.md for task-first handoff guidance.
Export, import, and snapshots
taskledger init --project-name "Taskledger"
taskledger export
taskledger import ./taskledger-transfer.tar.gz --dry-run
taskledger import ./taskledger-transfer.tar.gz --replace
taskledger snapshot ./artifacts
Default export filenames use this policy:
taskledger-export-{project_slug}-{ledger_ref}-{timestamp}.tar.gz
project_slug is derived from project_name in taskledger.toml. If
project_name is missing, taskledger falls back to the workspace directory name.
Import safety still relies on project_uuid, not the name/slug.
--include-bodies and --include-run-artifacts now change archive content:
--no-include-bodiesstrips record body text (body/context_body) from exported payloads.--include-run-artifactsembeds task and agent-log artifact files underartifacts/in the archive.
Cross-machine imports preserve durable task/run data, but imported runtime locks are quarantined by default. After importing an in-progress implementation, run:
taskledger next-action
taskledger implement resume --reason "Continue imported implementation."
Use --lock-policy keep only for diagnostic full-fidelity lock restoration.
Skill packaging
Agent workflows work best when the taskledger skill is installed in the
coding harness. The CLI has a task-first lifecycle with explicit planning,
approval, implementation, validation, locks, and handoff gates; without the
skill, an agent may not know the intended command sequence or gate semantics.
The canonical skill file lives at:
skills/taskledger/SKILL.md
Keep this skill outside the Python package. No additional
skills/taskledger/examples/ directory is required.
Development
python -m pytest -m "not slow"
python -m pytest -m "not slow" -n auto
python -m pytest -n auto
python -m pytest
ruff check .
Full release-readiness sweep:
make release-check
Project details
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file taskledger-0.3.0.tar.gz.
File metadata
- Download URL: taskledger-0.3.0.tar.gz
- Upload date:
- Size: 394.0 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
08424841438617a824c9cfeda4bf3b6a02e2ea5a68028ea14d9371cff7d6a169
|
|
| MD5 |
d0a86b994422bfea40a890c20ef3206d
|
|
| BLAKE2b-256 |
d3cce986ca2873255e3a83ab02a0de45ad4b26e56c4031ed02441f10dc897031
|
File details
Details for the file taskledger-0.3.0-py3-none-any.whl.
File metadata
- Download URL: taskledger-0.3.0-py3-none-any.whl
- Upload date:
- Size: 292.7 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
59b11d3c1afd6197dcf1f8e47be21a00e9f4d8b986e65c43ba65f4c287915efe
|
|
| MD5 |
07e4cf9599c647d9435044243dd75a09
|
|
| BLAKE2b-256 |
c03fad44821b8b83dcdc80f25b1efb23f730a3db50f713ff6c64a44b86ece43f
|