Skip to main content

tmda — Task Markdown for Agents

CI PyPI Python License: MIT

.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:

  1. 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.
  2. 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)

Source distribution for tmda 1.1.0
File Size Uploaded Provenance
tmda-1.1.0.tar.gz 53.4 kB With provenance Details

Built distribution (wheel)

Table of built distributions (wheels) for tmda 1.1.0
File Interpreter ABI Platform
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 log

Release 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 log

Security 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.

Select from 2 files

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 log

A 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.

Release history Release notifications | RSS feed

This release

1.1.0 This release

2 release files Full provenance

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page