TASKS.md

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

Quick Start

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.

Why TASKS.md?

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.

Zero setup

No accounts, no APIs, no tokens. Create a file and start writing.

In your editor

Add tasks without leaving your IDE. No browser tab, no context switch.

Version-controlled

In git, next to the code. Every change is tracked.

Agent-native

LLMs parse Markdown natively. No API client needed to read a file.

Vendor-neutral

Works with any agent, any IDE, any CI system, today.

Offline

Works on a plane. No server required.

How It Works

1

Plan

Write tasks under P0–P3 priority headings as ideas come to you. Even a one-liner is enough.

2

Delegate

Agent reads the file, claims a task with (@agent-name), and implements it.

3

Remove

Completed tasks are deleted from the file. History lives in git log.

4

Repeat

You keep adding tasks while agents keep working. No ideas get lost, agents never run out of work.

Writing Good Tasks

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

One session, one task

If it takes more than a sentence to describe, it might be two tasks.

Include file paths

Agents explore faster when they know where to look.

Define "done"

An Acceptance field turns a vague ask into a testable outcome.

Use IDs for dependencies

Give task A an ID, add Blocked by to task B. The agent will skip B until A is gone.

The Format

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

The /next-task Command

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

Install

Copy the command file into your project (commit it so your team gets it too):

AgentInstall
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/

What it does

When you type /next-task, the agent runs a 6-step loop:

1

Find

Discovers all TASKS.md files from the git root down.

2

Pick

Selects the highest-priority unblocked, unclaimed task. Prefers tasks that unblock others.

3

Claim

Appends (@agent-id) to the task line so other agents skip it.

4

Work

Reads the task's metadata, checks AGENTS.md for project conventions, makes changes, runs tests.

5

Complete

Removes the entire task block from TASKS.md, commits, pushes.

6

Loop

Reads TASKS.md again, picks the next task, continues until the queue is empty.

The workflow

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.

Tooling

MCP Server

tasks-mcp lets MCP-compatible agents (Claude Code, Cursor, Windsurf) manage TASKS.md files programmatically — list, claim, complete, and add tasks without file parsing.

Linter

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

From the Blog

Why Your AI Agent Needs a Backlog

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.

Read →

FAQ

Why not Jira / GitHub Issues / Linear?

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 trackersTASKS.md
AudienceProduct managers, teamsAgents, solo devs
GranularityFeatures, bugs, epicsImplementation steps
AccessAPI calls, auth tokensRead a file
SpeedBrowser/API round-tripEdit a line in your editor
Works offlineNoYes
Agent can writeNeeds API client + authAppend to a file
Git-nativeSeparate systemSame repo, same PR

Can I use TASKS.md alongside Jira / GitHub Issues?

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.

Why not TODO.md?

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

Do I need an orchestrator?

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.

Won't deleting tasks cause merge conflicts?

Each agent claims a unique task (different line). Git auto-merges deletions on non-adjacent lines. Conflicts are rare and trivial.

How detailed should my tasks be?

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.

Can I use TASKS.md without AI agents?

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.

How do I handle tasks that are too big?

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.

What happens when an agent gets stuck?

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.

Can multiple agents work on the same TASKS.md?

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.

Should I keep completed tasks in the file?

No. Remove them. Git log is your history. Keeping completed tasks adds noise and makes it harder for agents to scan the queue.

How does TASKS.md relate to AGENTS.md?

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.