A spec is a single Markdown file.
Your app's behavior sits on top.
Planned tasks live as checkboxes below.
Ideal for an agent loop. On each pass your agent picks an unblocked task, builds it, and closes it in one commit — code, checkbox, and updated spec.
Plain files in your repo, with tracker features from the CLI.
One commit carries the code, the task closure, and the spec update.
Agents follow a predefined skill-based workflow. A task is not complete until the implementation, task state, and documentation are updated together.
J**A SUCKS!!!
Each spec is one file. Together they are your backlog.
Each file shows what already works and what tasks are planned.
No boards. No database. No workspace. Just files in your repo.
Query your Markdown specs like a task tracker.
A checkbox, stable ID, title, and optional description make a task. Priority, tags, and custom fields can be added when needed.
@blocked_by is a custom field mdtask understands out of the box.
The task shows up as blocked.
Most tools split specs and tasks into different places. mdtask keeps them in one Markdown file.
OpenSpec and Spec Kit spin up their own multi-step workflow: each feature gets a separate folder of generated files — spec, plan, tasks — and a set of slash commands to drive them. A second set of documents to keep in line with your code.
mdtask skips all of that. The task is a checkbox in the same file as the spec. Mark it done and update the spec to describe how the feature works now — one commit. No second set of files, no separate workflow to keep in sync.
GitHub Issues, Jira, and Linear make you check a board to understand what changed and why.
mdtask puts the task in the same diff as the code and spec. Reviewers see the whole change in git.
A plain checklist works until you need to find owners, blockers, related work, or everything for one area.
mdtask makes that checklist queryable without turning it into a database.
Your agent does this from one instruction — not you by hand.