tmda — Task Markdown for Agents
.tmda files are task ledgers: Markdown checkboxes with stable ids, a
machine-computed progress block, and a validated link to the detailed brief
that explains what the work is actually for.
Two rules define the format:
- Every task is addressable —
- [!] T-014 Register the callback URL, so an agent can reference, block on, and flip a specific piece of work instead of guessing which bullet was meant. - Progress is derived, never authored — the percentage and bar are recomputed from the checkboxes by tooling. A stale number is a validation error, not a convenience.
The prose — what the person wants to do, why, constraints, what "done" looks
like — lives in a linked .md brief. Every .tmda file is required to point
at one, and tmda check verifies the file and the anchor resolve.
project/
├── auth-flow-brief.md ← prose: what we want to do and why
└── auth-flow.tmda ← ledger: checkboxes, ids, progress
Full normative specification: SPEC.md.
Install
pipx install tmda # recommended: isolates the CLI
or, inside a project environment:
pip install tmda
with uv:
uv tool install tmda
PyYAML is optional — pip install "tmda[yaml]" widens front-matter support to
full YAML. Without it a documented YAML subset is parsed and anything outside
it is a clear E002 error.
Requires Python ≥ 3.9. Single module, standard library only.
From source:
git clone https://github.com/Gakpey/tmda.git && cd tmda
pip install -e .
Quickstart
$ tmda init auth-flow --title "Sign-in and session overhaul"
created auth-flow-brief.md
created auth-flow.tmda
progress inserted
next: edit auth-flow.tmda and run `tmda check`
Write the actual description in auth-flow-brief.md, then break the work down
in the ledger:
## 2. Implementation
- [ ] T-010 Scaffold the auth package
- [x] T-011 Add the provider SDK
- [~] T-012 Wire the callback route
- [!] T-014 Register the callback URL @blocked-by=T-015
- [ ] T-015 Ask infra for the production redirect URI @owner=agent:scout @due=2026-10-28
- [ ] T-016 Rate limit the token endpoint @detail=./auth-flow-brief.md#rate-limiting @weight=3
Five checkbox states: [ ] todo · [~] in progress · [x] done ·
[!] blocked · [-] cancelled (excluded from the total). Metadata after the
description is parsed right-to-left: @detail, @owner, @blocked-by,
@weight, @due.
$ tmda sync # (re)write the managed progress block
$ tmda check # validate everything; exit 1 on errors
tmda check: 2 file(s)
OK - 0 error(s), 0 warning(s)
Reading progress
$ tmda status examples/auth-flow.tmda
examples/auth-flow.tmda
Sign-in and session overhaul
brief ./auth-flow-brief.md ok
status ✖ active
progress `█████████░░░░░░░░░░░` **6/14 pts (43%)**
5 done - 1 in progress - 1 blocked - 6 todo - 1 cancelled
sections
▸ 4/5 (80%) 1. Research and design
✖ 1/7 (14%) 2. Implementation
▸ 1/2 (50%) 3. Verification
blocked
T-014 Register the callback URL with the provider blocked-by T-015
next up
T-005 Pick the rotation interval
T-012 Wire the callback route
...
For agents, tmda status --json returns the same thing as data: derived
status, per-section rollups, every task with its container/parent links, plus
the next (dependency-satisfied) and blocked id lists. The stable shape is
documented in SPEC.md §14.3.
The agent loop
tmda status --json tasks/ # 1. what stands, what is blocked, what is next
$ less tasks/auth-flow-brief.md # 2. read WHY before touching any checkbox
$ tmda mark T-015 done # 3. record the outcome by id
$ tmda check --strict tasks/ # 4. hand back only if this exits 0
Step 2 is not optional — the ledger says what, the brief says why, and why decides how the work gets done.
Commands
| Command | Purpose |
|---|---|
tmda init NAME |
Scaffold a ledger and its brief stub |
tmda check [PATH…] |
Validate syntax, ids, links and the progress block (--strict, --json) |
tmda status [PATH…] |
Progress report per file, section and project (--json, --totals-only, --limit N) |
tmda sync [PATH…] |
Rewrite the progress block in place; idempotent |
tmda list [PATH…] |
Flat task list with --state, --open, --owner, --blocked, --id, --limit N |
tmda mark T-014 done |
Change a task's state by id and refresh progress |
Exit codes: 0 ok · 1 validation errors · 2 usage error.
On a large repository, scope the path. A bare tmda status returns every
task in every ledger, which is tens of thousands of tokens on a monorepo. Ask a
small question instead:
$ tmda status --totals-only . # project rollup only
TOTAL 157 file(s)
progress `█████████░░░░░░░░░░░` **2251/4879 pts (46%)**
1768 done - 317 in progress - 308 blocked - 1443 todo - 263 cancelled
$ tmda status --limit 3 services/ # a few files; rollup still covers all
showing 3 of 157 file(s) - narrow the PATH or raise --limit
$ tmda list --open --limit 20 services/billing/
showing 20 of 144 task(s) - narrow the PATH or raise --limit
Task ids (T-004) are unique within one file, not across the project, so
list --id and mark both refuse when an id matches several files rather
than return a plausible-looking wrong row. Narrow the path to one ledger.
status also stays a report rather than a validator: it exits 0 for a file
check rejects, but it names it as stale and gives the tmda sync remedy.
Use it in your CI
A composite action that installs tmda and runs it over your ledgers:
# .github/workflows/tmda.yml
name: tmda
on: [push, pull_request]
jobs:
tmda:
runs-on: ubuntu-latest
permissions:
contents: read
steps:
- uses: actions/checkout@v7
- uses: Gakpey/tmda@v1
with:
path: tasks/ # default "."
strict: "true" # default - warnings fail the build
version: latest # or pin "1.1.0"
strict is on by default because that is where the value is: a stale progress
block, a broken link into a brief, or a duplicated task id all fail the build
instead of quietly rotting.
Design decisions worth knowing
Progress is computed, and only computed. There is no percent: key. The
single source of truth is the checkboxes, and tmda check fails if the
rendered block drifts from them (E040) — so the number in a diff is always
reconstructible.
Parents don't double-count. A task with nested children is a container: its state is derived from them and it is excluded from the denominator. Nesting therefore never inflates or deflates the percentage.
Cancelled work leaves the fraction. Dropping a task must not make progress
go backwards, so - [-] is excluded from both numerator and denominator.
The brief is mandatory. detail: is a required front-matter key, its
target must exist, and a #fragment must match a real heading. Task-level
@detail=./brief.md#rate-limiting gives one-hop access from any checkbox to
the paragraph that justifies it.
Links run both ways. A brief that doesn't mention its ledger warns (W066),
so a human reading the prose can always find the checkboxes.
Ids, not line numbers. T-014 survives edits; a line number does not.
Everything else in the tool — mark, @blocked-by, the JSON reports — is
built on that.
Repository layout
tmda/
├── SPEC.md normative format specification
├── README.md this file
├── tmda.py single-file, stdlib-only CLI
├── action.yml reusable GitHub Action
├── pyproject.toml packaging, lint config
├── .github/workflows/ CI + PyPI release
├── examples/ two ledger/brief pairs
└── tests/ 68 tests
Working on it:
$ pip install -e ".[dev,yaml]"
$ python3 -m unittest discover -s tests # 68 tests
$ ruff check .
$ tmda check --strict examples
See CONTRIBUTING.md for the ground rules — notably standard library only and the format is versioned, so spec version 1 does not change.
Status
Spec version 1, initial release. The format is deliberately conservative:
candidates for a future version are listed in
SPEC.md §16.
License
MIT © Joshua Gakpey.
Metadata
Release files for tmda 1.1.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | |
|---|---|---|---|---|
| tmda-1.1.0.tar.gz | 53.4 kB | With provenance | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| tmda-1.1.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 75.9 kB
Release files / tmda-1.1.0.tar.gz
| Download URL | tmda-1.1.0.tar.gz |
|---|---|
| Size | 53.4 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
990104defaddf4e4cb510ab2ac09baeab19475f348d52f00f4b8a37a8b77cfe5
|
|
BLAKE2b-256 checksum How to use checksums |
a6340bd3e886dfd0baa1393d858619c13e40a153285b7a7131e078978ac3748a
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.16
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 23, 2026.
Transparency logRelease files / tmda-1.1.0-py3-none-any.whl
| Download URL | tmda-1.1.0-py3-none-any.whl |
|---|---|
| Size | 22.6 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
2eaebc9e55cbebbeba754234281c77d3c829ccc70a4ea0e5725ef1e480066d86
|
|
BLAKE2b-256 checksum How to use checksums |
ce1d8449a512d01d547307728161ce823ccb83785a13f30e3e8115263151d91a
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.16
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 23, 2026.
Transparency logSecurity for tmda 1.1.0
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
Full provenance
All 2 files in this release have been uploaded with provenance metadata.
Attestation for tmda-1.1.0.tar.gz
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 23, 2026.
Transparency logA note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.