Git-backed markdown authorative todos with a local sqlite for indexes and queries.
  • Go 90.4%
  • Just 4.9%
  • Shell 4.7%
Find a file
Viktor Varland 0e4a59eba9
All checks were successful
ci/woodpecker/push/build Pipeline was successful
ci/woodpecker/tag/release Pipeline was successful
docs: changelog for v1.0.0
2026-06-24 14:12:32 +02:00
.woodpecker ci: add Woodpecker build + release pipelines and changelog tooling 2026-06-24 13:50:57 +02:00
internal feat: unified gout presentation for list and stats 2026-06-24 13:04:52 +02:00
scripts ci: add Woodpecker build + release pipelines and changelog tooling 2026-06-24 13:50:57 +02:00
CHANGELOG.md docs: changelog for v1.0.0 2026-06-24 14:12:32 +02:00
go.mod refactor: migrate to the gout/cli command framework 2026-06-24 12:46:44 +02:00
go.sum refactor: migrate to the gout/cli command framework 2026-06-24 12:46:44 +02:00
justfile ci: add Woodpecker build + release pipelines and changelog tooling 2026-06-24 13:50:57 +02:00
main.go refactor: migrate to the gout/cli command framework 2026-06-24 12:46:44 +02:00
README.md feat: add revamp 2026-02-27 20:33:57 +01:00

todo

Minimal sqlite-backed task manager with local markdown notes.

Usage

todo add "follow up with payroll"
todo edit 1
todo list
todo search "payroll"
todo done 1
todo show 1
todo import
todo import git@github.com:you/plan.git
todo export
todo sync /path/to/todo-notes

Storage

  • Database: ~/.local/share/todo/todo.db
  • Notes repo: ~/.local/share/todo/notes (sparse checkout of tasks/)
  • Tasks path: ~/.local/share/todo/notes/tasks/<uid>-<slug>.md

Notes are the source of truth. Each note includes metadata lines:

  • Status: open|done
  • Created: <RFC3339>
  • Updated: <RFC3339>
  • Completed: <RFC3339> (only when done)

Import expects notes named like <uid>-<slug>.md (slug = lowercase, 20 chars max). Each task has a stable uid used for filenames and cross-machine sync. Local numeric IDs are per-machine shortcuts.

Override paths with --db and --notes (repo root).

Commands

  • add [--edit] TITLE... add a task and optionally open the note
  • edit ID|UID open the task note in $EDITOR
  • list [--all] [--limit N] list tasks
  • search [--all] QUERY... search task titles
  • show ID|UID show details
  • done ID|UID mark a task done
  • import [GIT_URL] import notes into sqlite, optionally cloning into the notes repo first
  • export [--all] export sqlite tasks to notes
  • sync [DIR] [--all] export to DIR, git pull/push, import back

sync stores DIR in sqlite and reuses it when omitted. Tasks live under tasks in the repo. The repo is kept in sparse mode with tasks/ checked out.