A powerful CLI for project-local task tracking
Markdown-native · Agent-friendly · JSON-first · CI-ready
This project is in public beta. The core task lifecycle is implemented and tested end-to-end, but the format and command ergonomics may still evolve before
v1.0. If you hit rough edges, open an issue.
Stop scattering tasks across chats, notes, and ad-hoc scratch files. Start tracking work where the code lives.
| 🧠 Agent-first by design | Deterministic commands, stable IDs, --json output, and JSON bulk mutations |
| 📝 Markdown as source of truth | Tasks live in docs/Task.md, readable by humans and writable by tools |
| 📦 Single-file workflow | No database, no background daemon, no account signup |
| 🔒 Safe concurrent writes | File lock + temp write + atomic rename |
| ⚡ Fast local triage | taskmd next picks the next highest-priority todo deterministically |
Option 1 — Homebrew (recommended)
brew tap FerdiKT/tap
brew install taskmdOption 2 — Go install
go install github.com/ferdikt/taskmd-cli@latestOption 3 — Build from source
git clone https://github.com/FerdiKT/taskmd-cli.git
cd taskmd-cli
make tidy
make build VERSION=0.1.0
./bin/taskmd versionOption 4 — Multi-arch release binaries
make dist VERSION=0.1.0
ls dist/See docs/RELEASE.md for the release flow.
Get up and running in 2 minutes.
taskmd initThis creates docs/Task.md in the repo root if you're inside a Git repository. Otherwise it creates it in the current directory.
taskmd add "Initialize parser" --priority p1 --assignee main-agent --labels cli,v1
taskmd add "Write README" --priority p2 --assignee docs-agenttaskmd list
taskmd list --assignee main-agent
taskmd nexttaskmd start T001
taskmd done T001
taskmd reopen T001cat <<'JSON' | taskmd bulk add --file -
[
{"title":"Ship binary", "priority":"p1", "assignee":"release-agent", "labels":["release"]},
{"title":"Write docs", "priority":"p2", "assignee":"docs-agent"}
]
JSON💡 Tip: Use
taskmd list --jsonandtaskmd next --jsonwhen another CLI agent needs to consume the output.
| Area | Commands | Highlights |
|---|---|---|
core |
init · list · show · version |
Project bootstrap and inspection |
lifecycle |
add · edit · start · done · reopen · remove |
Stable IDs and explicit status changes |
bulk |
bulk add · bulk edit · bulk remove |
JSON array input from file or stdin |
preview |
preview |
Local web UI for the live Task.md state |
maintenance |
next · fmt · validate |
Deterministic prioritization and file normalization |
Full reference:
taskmd --help·taskmd <command> --help
taskmd is optimized for local AI agents that are already comfortable with terminal workflows.
taskmd list --json
taskmd show T001 --json
taskmd next --jsontaskmd add "Investigate flaky tests" --priority p1 --assignee qa-agent --labels testing
taskmd edit T004 --assignee release-agent --notes "Repro found on macOS only"
taskmd bulk edit --file ./patches/tasks.jsontaskmd fmt
taskmd validateThe canonical file format is strict enough for safe machine updates, but still readable enough for manual editing.
taskmd preview
taskmd preview --port 4783This starts a local web server, opens your browser, and renders the current docs/Task.md in a Jira-style preview with List and Board views. Search, assignee, and label filters are preserved in the URL, issue detail opens in a side drawer, and the page auto-refreshes every 30 seconds.
taskmd owns a stable Markdown layout:
# Task
<!-- taskmd:version 1 -->
## Todo
### T001 - Initialize parser
- priority: p1
- assignee: main-agent
- labels: cli, v1
- created: 2026-04-09T14:30:00+03:00
- updated: 2026-04-09T14:30:00+03:00
#### Notes
Create the Markdown parser and renderer.
## In Progress
## DoneRules:
- IDs are stable and never renumbered.
- Status is derived from the section, not duplicated in metadata.
Assigneeis optional and can be cleared with an empty string patch.Notesis optional and accepts raw Markdown.taskmd fmtrewrites the file back into canonical form.
Bulk commands accept JSON arrays.
cat <<'JSON' | taskmd bulk edit --file -
[
{"id":"T001","assignee":"main-agent","notes":"Parser skeleton ready"},
{"id":"T002","labels":[]},
{"id":"T003","priority":"p1","assignee":""}
]
JSONPatch semantics:
- Missing fields are left unchanged.
""clears string fields such asassigneeornotes.[]clears labels.
Every write operation follows the same flow:
- Acquire a file lock on
docs/Task.md.lock - Parse the current Markdown document
- Apply the mutation in memory
- Write to a temp file
- Atomically rename into place
This keeps local multi-agent workflows from trampling each other.
make tidy
make test
make build VERSION=0.1.0
make dist VERSION=0.1.0MIT
