TASKS.mdA task queue for AI agents. The companion to AGENTS.md.
AGENTS.md tells agents how to work. TASKS.md tells them what to work on.
Create a TASKS.md at your repo root:
# Tasks
## P0
- [ ] Fix authentication crash on token refresh
- **ID**: auth-fix
- **Tags**: backend, auth
- **Details**: JWT refresh returns 500 on expired tokens
- **Files**: `src/auth/refresh.ts`, `src/middleware/auth.ts`
- **Acceptance**: Refresh works, tests pass, regression test added
## P1
- [ ] Add rate limiting to public API endpoints (@cursor-1)
- **Tags**: backend
- **Details**: Use express-rate-limit, 100 req/min per IP
- **Blocked by**: auth-fix
## P2
- [ ] Update README with new API endpoints
## P3
- [ ] Support WebSocket connections
Most tasks are just checkboxes under priority headings. Add metadata only when needed.
You think faster than agents can code. Ideas come in bursts — while an agent implements one feature, you've already thought of three more. Without a queue, those ideas live in your head or scatter across chat windows. TASKS.md is your buffer: write tasks down as they come, and agents work through them at their own pace.
Planning first leads to better results. Writing a task down — even a one-liner — forces you to think about what you actually want before the agent starts coding. That small act of planning is the difference between an agent that builds the right thing and one that guesses.
Zero friction beats any tool. Opening Jira to write a task takes you out of flow — you switch context, fill in fields, pick a project, assign a sprint. With TASKS.md, you add a line to a file that's already open in your editor. The lower the friction, the more likely you are to actually write tasks down.
No accounts, no APIs, no tokens. Create a file and start writing.
Add tasks without leaving your IDE. No browser tab, no context switch.
In git, next to the code. Every change is tracked.
LLMs parse Markdown natively. No API client needed to read a file.
Works with any agent, any IDE, any CI system, today.
Works on a plane. No server required.
Write tasks under P0–P3 priority headings as ideas come to you. Even a one-liner is enough.
Agent reads the file, claims a task with (@agent-name), and implements it.
Completed tasks are deleted from the file. History lives in git log.
You keep adding tasks while agents keep working. No ideas get lost, agents never run out of work.
A task is a small contract between you and the agent — the more specific you are, the better the result.
A one-liner is fine for obvious work:
- [ ] Add input validation to the /users endpoint
Add metadata when the task needs context:
- [ ] Fix race condition in WebSocket reconnect
- **Details**: When the server restarts, clients reconnect but sometimes
miss messages sent during the reconnect window. Add a sequence number
to messages and request missed messages after reconnecting.
- **Files**: `src/ws/client.ts`, `src/ws/server.ts`
- **Acceptance**: No dropped messages during server restart in integration test
If it takes more than a sentence to describe, it might be two tasks.
Agents explore faster when they know where to look.
An Acceptance field turns a vague ask into a testable outcome.
Give task A an ID, add Blocked by to task B. The agent will skip B until A is gone.
| Field | Purpose | Example |
|---|---|---|
| Priority | P0–P3 headings (PagerDuty/SRE scale) | ## P1 |
| ID | Stable identifier for blocker references and cross-file linking | **ID**: auth-fix |
| Tags | Lowercase, comma-separated labels for filtering and orchestrator routing | **Tags**: backend, auth |
| Details | Implementation guidance, context, approach | **Details**: JWT returns 500 |
| Files | Relevant file paths (backtick-quoted, comma-separated) | **Files**: `src/auth.ts` |
| Acceptance | Definition of done | **Acceptance**: Tests pass |
| Blocked by | Task ID(s) of blocking tasks — comma-separated if multiple | **Blocked by**: auth-fix |
All metadata is optional. Most tasks are just a checkbox and a sentence.
/next-task CommandThe most useful thing about TASKS.md is a single command: "pick the next task and do it." Install it for your agent, then type /next-task to start an autonomous work loop.
Copy the command file into your project (commit it so your team gets it too):
| Agent | Install |
|---|---|
| Claude Code | cp -r commands/claude/skills/next-task .claude/skills/ |
| Codex | cp -r commands/codex/skills/next-task .agents/skills/ |
| Cursor | cp commands/cursor/next-task.md .cursor/commands/ |
| Gemini CLI | cp commands/gemini/next-task.toml .gemini/commands/ |
| Windsurf | cp commands/windsurf/next-task.md .windsurf/workflows/ |
When you type /next-task, the agent runs a 6-step loop:
Discovers all TASKS.md files from the git root down.
Selects the highest-priority unblocked, unclaimed task. Prefers tasks that unblock others.
Appends (@agent-id) to the task line so other agents skip it.
Reads the task's metadata, checks AGENTS.md for project conventions, makes changes, runs tests.
Removes the entire task block from TASKS.md, commits, pushes.
Reads TASKS.md again, picks the next task, continues until the queue is empty.
You Agent
────────────────── ──────────────────
Write tasks as ideas come → /next-task
Add more tasks → Claims P0 task, starts working
Add more tasks → Completes task, picks next one
Review agent's commits ← Commits, removes task, loops
Add more tasks → ...keeps draining the queue
You're always adding to the queue. The agent is always draining it. Planning is your job, execution is the agent's.
tasks-mcp lets MCP-compatible agents (Claude Code, Cursor, Windsurf) manage TASKS.md files programmatically — list, claim, complete, and add tasks without file parsing.
@tasks-md/lint validates TASKS.md files against the spec — checks structure, priority ordering, ID format, duplicate IDs, and dangling blocker references. Add it to CI.
You think faster than agents code. That's the fundamental mismatch nobody talks about. TASKS.md is the async buffer between your ideas and agent execution.
They solve a different problem. Issue trackers are for team coordination — sprints, assignments, reporting. TASKS.md is for agent execution — a local, fast, file-based queue that agents read and write without API calls. Use the tracker for what to build; use TASKS.md for how the agent builds it.
| Issue trackers | TASKS.md | |
|---|---|---|
| Audience | Product managers, teams | Agents, solo devs |
| Granularity | Features, bugs, epics | Implementation steps |
| Access | API calls, auth tokens | Read a file |
| Speed | Browser/API round-trip | Edit a line in your editor |
| Works offline | No | Yes |
| Agent can write | Needs API client + auth | Append to a file |
| Git-native | Separate system | Same repo, same PR |
Absolutely — that's the expected setup for teams. The issue tracker is your source of truth for product work. When you pick up an issue, break it into implementation steps in TASKS.md and let the agent execute them.
TODO.md has no spec and thousands of incompatible formats. A "task queue" is an active work queue for agents, not a human wish list. The naming fits: AGENTS.md (instructions) + TASKS.md (work queue).
No. A solo developer with one agent benefits from persistent context across sessions. An orchestrator helps with multiple agents, but it's not required. TASKS.md is intentionally simple enough that any agent can use it without special tooling.
Each agent claims a unique task (different line). Git auto-merges deletions on non-adjacent lines. Conflicts are rare and trivial.
As detailed as needed for the agent to succeed without asking you. A one-liner works for obvious changes. For anything ambiguous, add Details, Files, and Acceptance so the agent knows what to do, where to look, and when it's done.
Yes. It works as a personal backlog for any developer. The format is just prioritized Markdown checkboxes — you don't need an agent to benefit from writing tasks down before starting work.
Break them into sub-tasks or split them into separate tasks with dependencies. If a task takes more than one sentence to describe, it's probably two tasks. Use Blocked by to order them.
The agent should tell you it's stuck and move on to the next task. The stuck task stays in the queue with its claim. You can add more detail or remove the claim so another agent can try.
Yes — that's what the claiming mechanism is for. Each agent appends (@agent-id) to the task it picks up. Other agents see the claim and skip to the next unclaimed task.
No. Remove them. Git log is your history. Keeping completed tasks adds noise and makes it harder for agents to scan the queue.
They're companions. AGENTS.md tells agents how your project works (build commands, conventions, architecture). TASKS.md tells agents what to work on (prioritized queue). Together, an agent can start a session, read both files, and be immediately productive.