Minimal, delightful CLI to manage todos from your terminal. Batteries included: JSON persistence, human-friendly UX, and optional Git commit gate to prevent shipping unfinished work.
π Killer feature: Gate your commits. Block commits when there are unfinished todos (with a simple
--forcebypass when you really need it).Built because I was tired of ticking markdown checkboxes in PR templates - this keeps the discipline in your terminal, close to your actual workflow.
- Fast workflows for solo makers and teams
- JSON-backed storage for simplicity and portability
- Optional βgateβ to block commits when todos are unfinished (with an easy bypass)
Block commits when todos are unfinished. Bypass with --force if you must.
- β add/list/delete/done commands
- πΎ JSON persistence at a configurable path (default:
./.todoctl/todos.json) - π« Git commit gate (per-repo enable/disable, commit-msg hook)
- π¨ Clean, colored output and friendly errors
go install github.com/5iing/todoctl@latestbrew install 5iing/tap/todoctlgit clone https://github.com/5iing/todoctl
cd todoctl
go build -o todoctl .Dependencies:
- jq (for the Git hook checks)
- macOS:
brew install jq - Ubuntu:
sudo apt-get install -y jq
- macOS:
# Real developer workflow
todoctl add "Implement JWT auth"
todoctl add "Write unit tests"
todoctl add "Update API docs"
todoctl list
# 1 β Implement JWT auth
# 2 β Write unit tests
# 3 β Update API docs
# ... work work work ...
git commit -m "feat: add authentication"
# β [todoctl gate] 3 unfinished todos
# Add '--force' to bypass
todoctl done 1
todoctl done 2
git commit -m "feat: add authentication"
# β
Committed successfully- Default path:
./.todoctl/todos.json - File is created automatically on first save.
- You can move or version it as part of your repo.
Prevent committing when there are unfinished todos in your project. Per-repository and easy to override.
Install the hook:
todoctl gate installEnable/disable per repo:
todoctl gate enable
todoctl gate disable
todoctl gate statusBypass on demand:
git commit -m "wip --force" # bypass via message flag
git commit --no-verify # bypass all hooks (not recommended)Customize file path used by the gate:
git config todoctl.gate.file ./.todoctl/todos.jsontodoctl add <title> # create a new todo
todoctl list # show todos
todoctl delete <id> # delete a todo by id
todoctl done <id> # mark a todo as done
todoctl gate install # install commit-msg hook
todoctl gate enable # enable gating for this repo
todoctl gate disable # disable gating for this repo
todoctl gate status # show gating status
You can inject version info at build time (for todoctl version, when added):
go build -ldflags "-X main.version=v0.1.0 -X main.commit=$(git rev-parse --short HEAD) -X main.date=$(date -u +%Y-%m-%d)" -o todoctl .Requirements:
- Go >= 1.25
- jq (for the Git hook checks) β
brew install jq
Project layout:
cmd/β Cobra commandsinternal/repo/β JSON repository for todosinternal/gate/β Git gate service (OOP style:Serviceinterface +GateService)
Issues and PRs are welcome! Please:
- Keep public APIs simple and documented
- Add tests for new behavior when possible
- Update the README for user-facing changes
MIT Β© 5iing. See LICENSE.
- Replace
github.com/5iing/todoctlin badge links once the repository is public. - Consider adding Homebrew tap and release automation (e.g., Goreleaser) when you cut versions.