Skip to content

amulyavarshney/todo-cli

Repository files navigation

Todo CLI

CI Pages Python 3.9+ License: MIT GitHub stars

Turn messy “fix it later” notes — and in-code TODO/FIXME/XXX comments — into paste-ready briefs for Cursor, Claude, Codex, or any coding agent.

Todo CLI is a local, scriptable task queue with agent handoff built in — not another chat window. Capture work once, sync it from your codebase, reuse it forever, switch models freely.

Try it in the browser: amulyavarshney.github.io/todo-cli · Playground

If this saves you time, please ⭐ star the repo — it helps others discover it. Want to improve it? Fork and open a PR — see Contributing.


Why todo-cli?

flowchart LR
  You[You] --> Capture[Capture task]
  Capture --> Enrich[Add context + acceptance]
  Enrich --> Go["todo go"]
  Go --> Clipboard[Clipboard prompt]
  Clipboard --> Agent[Cursor / Claude / Codex]
  Agent --> Done[todo done]
  Done --> Recipe[Save as recipe]
  Recipe --> Capture
  Code[Code comments] --> Sync["todo sync / watch"]
  Sync --> Capture
Loading
Pain with chat-only agents What todo-cli gives you
Work disappears when the tab closes Durable queue on disk
Vague “fix auth” prompts Structured briefs with acceptance criteria
Locked into one product Same packet → any model
Repeating the same setup Recipes + .todo/ project packs
In-code TODO/FIXME/XXX rot todo sync / todo watch → queue + auto-close

5-minute interactive tour

Follow these steps in order. Copy each block as you go.

Step 1 — Install

Requirements: Python 3.9+

git clone https://github.com/amulyavarshney/todo-cli.git
cd todo-cli
python3 -m pip install -e .
todo --version   # → todo-cli 1.6.2

Optional but recommended — pin a stable data folder:

todo init
todo where

Step 2 — Your first todos (human mode)

todo add "water the plants"
todo add "change light bulb"
todo ls
todo done 1
todo report

You should see numbered items like [2] t_… change light bulb. Numbers are for quick picks; ids stay stable.

Step 3 — Prepare work for an AI agent

todo add "Implement Google OAuth" \
  --priority high \
  --tag auth \
  --for agent \
  --template feature \
  --accept "Users can sign in with Google" \
  --accept "Existing auth tests pass"

todo context 1 "Reuse src/auth.py session store. Do not commit secrets."
todo ls --agent-only

Step 4 — Hand off in one command

todo go --quiet

That copies a full agent prompt to your clipboard. Paste it into Cursor, Claude, ChatGPT, or Codex.

Prefer files instead of clipboard?

todo go --handoff
# → handoffs/<task-id>/NEXT_PROMPT.md

Preview without touching the clipboard:

todo go --dry-run

Step 5 — Pull TODOs out of the code

todo project init                  # seeds code-todo / code-fixme / code-xxx recipes
todo scan --include .py            # list hits
todo sync --include .py            # import as linked tasks
todo ls --tag code
todo go --quiet

When you delete a TODO comment and run sync again, the linked task auto-completes. If the comment returns, the task reopens.

Step 6 — Finish and reuse

todo done 1
todo recipe save oauth 1          # save before done if you still need the task
# or polish a task first, then:
todo recipe save oauth <task-id>
todo recipe use oauth "Add GitHub OAuth provider"
todo go --quiet

🎉 You’re in the loop: capture → sync → go → agent → done → recipe.


How the agent loop works

sequenceDiagram
  participant U as You
  participant T as todo-cli
  participant A as Cursor / Claude / Codex

  U->>T: todo add "... --for agent"  /  todo sync
  U->>T: todo go
  T-->>U: Prompt on clipboard (+ optional handoff files)
  U->>A: Paste NEXT_PROMPT / clipboard
  A-->>U: Code changes + summary
  U->>T: todo done <id>
  U->>T: todo recipe save name <id>
Loading

Optional live dispatch (Cursor SDK — not required for daily use):

python3 -m pip install 'todo-cli[agent]'
export CURSOR_API_KEY=...
todo go --run --cwd .
# Preview SDK payload without calling the API:
todo go --run --dry-run --cwd .

Share the workflow with your team

Rule of thumb: commit recipes and defaults; keep each person’s queue local.

flowchart TB
  subgraph repo [Git repo — shared]
    Pack[".todo/project.json"]
    Recipes[".todo/recipes/*.json"]
  end
  subgraph local [Per developer — private]
    DirA["TODO_DIR / --dir A"]
    DirB["TODO_DIR / --dir B"]
  end
  DevA[Developer A] --> Pack
  DevB[Developer B] --> Pack
  DevA --> DirA
  DevB --> DirB
  DirA --> GoA["todo go"]
  DirB --> GoB["todo go"]
  GoA --> AgentA[Any agent]
  GoB --> AgentB[Any agent]
Loading
# In your application repo (once):
todo project init --name my-app
git add .todo/project.json .todo/recipes .todo/.gitignore
git commit -m "Add todo-cli agent project pack"

# On each machine / clone (private queue — do NOT commit tasks.json):
export TODO_DIR="$HOME/.todo-cli/queues/my-app"
# or: todo --dir ~/.todo-cli/queues/my-app sync
todo sync --include .py
todo go --quiet

.todo/.gitignore (created by project init) already ignores tasks.json, undo.json, handoffs/, and the lock file so clones never fight over the same queue.

More detail: todo help team.


Bridge in-code TODOs into the queue

Scan the repo for single-line TODO / FIXME / XXX comments, import them as tasks (with recipes), and keep the queue in sync as comments appear or disappear:

todo scan                          # list hits (path:line + summary)
todo sync                          # create/update tasks; close when comment is gone
todo watch --interval 2            # re-sync when file mtimes change (Ctrl+C to stop)
todo go --quiet                    # hand the next imported task to an agent

Sync behavior

Event Result
New comment found Creates a linked task (source.kind=code_comment)
Comment moves (same text) Updates source.path / source.line
Comment removed Auto-completes the linked task (one undoable mutation)
Comment returns Reopens the task (clears claim + auto-complete notes)
You edited todo context Your context is kept on later syncs
Scan finds 0 comments (files still match) Auto-completes linked tasks that disappeared
Scan matches no source files Auto-close is skipped (use --force-close to override)

Identical comments in the same file get distinct keys (code:abc, code:abc#2, …).

Useful options

Flag Meaning
--root PATH Directory to scan (default: cwd)
--include .py Limit to suffixes (repeatable)
--marker FIXME Limit markers (repeatable; default TODO,FIXME,XXX)
--no-close Do not auto-complete when comments disappear
--no-reopen Do not reopen when comments return
--no-agent Do not assign imported tasks to an agent
--force-close Allow auto-close even when no source files match
--no-ignore Do not respect .gitignore / .todoignore
--json Machine-readable report (scan / sync)
--once watch: run one sync and exit
--interval N watch: poll every N seconds (default 2)

Tip: always pass a sensible --root / --include in large monorepos. If the filter matches no files, auto-close is skipped so a bad flag cannot wipe the queue — override with --force-close only when you mean it.


Everyday cheat sheet

I want to… Run
Add a quick task todo add "buy milk"
Add a bug for an agent todo add "Login 500" --template bug --for agent
List / import code TODOs todo scan / todo sync
Watch comments live todo watch
See what’s next todo next or todo go --quiet
Preview a go prompt todo go --dry-run
Filter the queue todo ls --tag auth --unblocked
Block task 3 on task 2 todo block 3 --on 2
Undo a mistake todo undo
Check install health todo doctor
Backup my queue todo backup
Find my data files todo where
Export prompts todo export -f prompt --agent-only

Command reference

Command Description
todo / todo help Show usage
todo help COMMAND Per-command help (also team)
todo add "text" Add a todo
todo add "text" --template bug|feature|refactor|chore Add from built-in template
todo add "text" --recipe NAME Add from a saved recipe
todo ls / todo ls --json List pending todos
todo edit REF ["text"] Edit text / metadata
todo del REF Delete
todo done REF Complete
todo undo Revert last change
todo go [REF] Next task → clipboard (+ --run / --handoff / --dry-run)
todo next Show best unblocked task
todo prompt [REF] Print agent prompt
todo handoff [REF] Write Markdown + JSON package
todo run [REF] Optional Cursor SDK dispatch
todo recipe list|save|use|show|delete Manage recipes
todo scan List TODO/FIXME/XXX comments
todo sync Import/sync comments → tasks (auto-close)
todo watch Poll file mtimes and re-sync
todo doctor Health checks for data dir / config
todo backup Zip the data directory
todo completion bash|zsh|fish Print shell completion script
todo project init Create .todo/ pack (+ comment recipes)
todo context REF "..." Attach context
todo accept REF "..." Add acceptance criterion
todo block REF --on DEP Add dependency
todo unblock REF Clear dependency
todo claim REF --as cursor Mark claimed
todo export -f json|md|prompt Export
todo report / todo report --all Counts
todo clear Clear completed history
todo where / todo init Data dir + config
todo --version Version

REF can be a display number (1) or a stable id (t_abc12345).

Useful flags

Flag Where Meaning
-p / --priority add, edit low, medium, high, critical
-t / --tag add, edit Repeatable tags
--for AGENT add Assignee (agent, cursor, …)
--accept add Acceptance criterion (repeatable)
--agent-only / --all go, ls, next, … Prefer agent-assigned work / include all
--quiet go Copy without reprinting the full prompt
--handoff go Also write handoff files
--run go Dispatch via Cursor SDK
--dry-run go Preview prompt (no clipboard); with --run, preview SDK call
--dry-run / --print-only run Preview without API calls
--no-copy go Print prompt without clipboard

Where your data lives

flowchart TD
  Dir["--dir flag"] --> Store
  Env["TODO_DIR env"] --> Store
  Cfg["config data_dir"] --> Store
  Cwd["current directory"] --> Store
  Store[(tasks.json + mirrors)]
  Store --> Handoffs[handoffs/]
  Store --> Undo[undo.json]
Loading
File Purpose
tasks.json Source of truth
todo.txt / done.txt Plain-text mirrors
handoffs/ Agent packages + run results
undo.json Last mutation for todo undo
.todo/project.json Repo-shared defaults + comment_recipes
.todo/recipes/*.json Shared / comment recipes
todo where    # show active data directory
todo init     # default data_dir → ~/.todo-cli

Exit codes: 0 success, 1 error (messages on stderr).


Privacy & network

todo-cli is local-first:

  • No telemetry, no analytics, no phone-home.
  • Task data stays in your data directory (todo where).
  • The only optional network path is the Cursor SDK when you explicitly install todo-cli[agent], set CURSOR_API_KEY, and run todo run / todo go --run.

Production checklist

todo init
todo doctor                      # verify data dir + tasks.json
todo backup -o ~/Backups         # zip before risky experiments
todo help sync                   # per-command help
eval "$(todo completion zsh)"    # bash | zsh | fish
# fish: todo completion fish > ~/.config/fish/completions/todo.fish
  • Scan ignores .gitignore and .todoignore by default (--no-ignore to override).
  • Team layout: shared .todo/recipes + private TODO_DIR — see Share the workflow / todo help team.
  • Security: SECURITY.md · Conduct: CODE_OF_CONDUCT.md
  • Install: from source today; PyPI publish is wired via GitHub Releases. After release: pipx install todo-cli. Packaging notes: docs/packaging.md.
  • Website: GitHub Actions deploys web/amulyavarshney.github.io/todo-cli on every push to main (workflow: .github/workflows/pages.yml). One-time setup: Settings → Pages → Source: GitHub Actions.

Support the project

Todo CLI is free and open source (MIT). A little visibility goes a long way:

  1. Star on GitHub — signals the project is useful
  2. 🍴 Fork the repo — experiment safely, then contribute back
  3. 💬 Open an issue — bugs, ideas, and questions welcome
  4. 🔀 Send a pull request — even small docs/tests PRs help
Star → Fork → Branch → Commit → PR → Review → Merge

Contributing

We love contributions of all sizes — docs, tests, UX polish, and features.

Fork workflow (recommended)

# 1) Fork on GitHub, then clone YOUR fork
git clone https://github.com/<your-username>/todo-cli.git
cd todo-cli

# 2) Add upstream
git remote add upstream https://github.com/amulyavarshney/todo-cli.git

# 3) Create a branch
git checkout -b feat/my-improvement

# 4) Install + test
python3 -m venv .venv
source .venv/bin/activate   # Windows: .venv\Scripts\activate
python3 -m pip install -e ".[dev]"
pytest

# 5) Push and open a PR against amulyavarshney/todo-cli
git push -u origin HEAD

Full guidelines: CONTRIBUTING.md.


License

MIT © Amulya Varshney


Ready? todo sync && todo go — then paste into your favorite agent.

If it helped, leave a star so more people can find it. Thank you!

About

Turn messy “fix it later” notes and in-code TODO/FIXME/XXX comments into paste-ready briefs for Cursor, Claude, Codex, or any coding agent.

Topics

Resources

License

Code of conduct

Contributing

Security policy

Stars

0 stars

Watchers

1 watching

Forks

Releases

No releases published

Packages

 
 
 

Contributors