Channel your daily todo list into a continuous runnel of achievement.
An agent-centric command-line TODO manager for everyday task management, built with Go and SQLite. runnel-todo is designed to be driven by AI coding agents (and humans too): capture the day's work, move it through a clear status workflow, and review what you accomplished — all through predictable commands, exact flag syntax, and deterministic output that turns the routine of planning, tracking, and reviewing daily tasks into a few terminal commands.
A bundled skill (skills/runnel-todo/SKILL.md) teaches any opencode-compatible agent every command, flag, due-date format, status transition, and exact error string, so it can drive runnel-todo correctly without scraping the README. Whether you're a human working from the shell or an agent invoking tools on your behalf, you get date-based IDs, tags, due dates, and completion metrics — all stored locally in SQLite and structured for reliable, parseable output.
Most TODO CLIs are built for humans typing at a prompt. runnel-todo is built for agents that invoke tools:
- Deterministic output —
plainformat (default) is line-oriented and easy to parse; IDs, statuses, and dates appear in fixed positions so an agent can extract them reliably. - Exact error strings — every error message is specified in
SPEC.mdand matched by tests, so an agent can branch onTODO item with ID <X> not foundwithout regex guesswork. - No interactive surprises — destructive commands accept
--yes/-yso agents can skip prompts without hanging on stdin. - A first-class skill —
skills/runnel-todo/SKILL.mdis shipped with the repo. Load it in any opencode session and the agent immediately knows every command, flag, due-date format, status transition, and exact error string — no need to scrape the README. - Local-first & isolated —
~/.runnel-todo/runnel-todo.dbby default, overridable per-invocation with--db. Agents can spin up a throwaway DB in a temp dir for sandboxed workflows. - Stable, documented invariants — the
SPEC.mdis the behavioral source of truth; gotchas (likelist --overdue≠metricsOverdue) are called out explicitly so agents don't "fix" them.
- Date-based IDs —
YYYYMMDDNNformat groups tasks by day (up to 99 per day). - Status workflow —
pending→in-progress→donewith constrained transitions. - Tags & due dates — categorize tasks and set deadlines with date or datetime precision.
- Filtering & sorting — multi-dimensional sort, filter by status / tag / due range / overdue.
- Two output formats — plain text (default, agent-friendly) and dynamic terminal-width-aware tables.
- Metrics — completion rate, average completion time, overdue count, and period-based stats.
- Local-first — all data lives in a SQLite file at
~/.runnel-todo/runnel-todo.db.
If you're an opencode agent (or driving one), load the bundled skill instead of reading this whole README — it's the authoritative, token-efficient reference:
# In an opencode session, the skill at skills/runnel-todo/SKILL.md is auto-discovered.
# Its frontmatter description tells the agent when to invoke it.The skill covers every command, flag, due-date format, status-transition rule, exact error string, and the known gotchas — everything an agent needs to drive runnel-todo correctly in one place.
npm install -g @runnel-ai/runnel-todoShips prebuilt binaries for darwin/arm64, darwin/amd64, linux/amd64, linux/arm64, and windows/amd64. A postinstall script selects the right one for your platform.
go install github.com/runnel-ai/runnel-todo/cmd/runnel-todo@latestRequires CGO (
mattn/go-sqlite3), so a C toolchain must be present.
Download a prebuilt archive from the Releases page.
git clone https://github.com/runnel-ai/runnel-todo.git
cd runnel-todo
make build # produces ./bin/runnel-todorunnel-todo add "Buy groceries" --desc "Milk, eggs, bread" --due 2024-12-01 --tags "shopping,personal"
runnel-todo add "Team standup" --due 2024-12-01T09:30
runnel-todo start 2024120102
runnel-todo list
runnel-todo list --all --format table
runnel-todo done 2024120102
runnel-todo metrics --period week# An agent can drive runnel-todo end-to-end without any stdin interaction
# and without touching the user's real database:
runnel-todo --db /tmp/agent-tasks.db add "Refactor parser" --tags work,refactor --due 2026-06-30
runnel-todo --db /tmp/agent-tasks.db start 2026062201
runnel-todo --db /tmp/agent-tasks.db done 2026062201 --yes 2>/dev/null || true
# ↑ --yes avoids the confirmation prompt; agents should always pass it
# when scripting deletes / state changes they've already decided on.| Command | Description |
|---|---|
add |
Create a new TODO (positional title required). |
list |
List TODOs with filters/sorting (done hidden by default). |
show |
Show full details of a single TODO. |
edit |
Edit title/description/due/tags of a TODO. |
delete |
Delete a TODO (prompts unless --yes). |
done |
Mark a TODO as done. |
start |
Mark a TODO as in-progress. |
reset |
Reset a TODO to pending. |
tags |
List all tags in use. |
metrics |
Display completion statistics. |
version |
Show version information (skips DB init). |
versiondeliberately does not open the database — agents can probe availability withrunnel-todo versionwithout side effects.
runnel-todo add "Buy groceries" --desc "Milk, eggs, bread" --due 2024-12-01 --tags "shopping,personal"| Flag | Short | Description |
|---|---|---|
| (title) | TODO title (required) | |
--desc |
-d |
Description |
--due |
Due date: YYYY-MM-DD (→ 23:59 local) or YYYY-MM-DDTHH:MM |
|
--tags |
-t |
Comma-separated tags |
runnel-todo list --status pending --tag work --sort -due_date,title --format table| Flag | Short | Description |
|---|---|---|
--all |
-a |
Include done items (hidden by default) |
--status |
-s |
Filter by status (pending, in-progress, done); overrides --all |
--tag |
-t |
Filter by exact tag match |
--due-before |
Due before a date/datetime | |
--due-after |
Due after a date/datetime | |
--overdue |
Only overdue items (due_date < now, time-level comparison) |
|
--sort |
Comma-separated fields: status, due_date, created_at, title, updated_at. Prefix - for descending. Default: status,due_date |
|
--format |
-f |
plain (default) or table |
Default sort order: in-progress > pending > done, then due_date ascending (items without a due date go last).
Plain output shape (default, easy for agents to parse):
[ID] [status] Title
[ID] [pending] Title (due: YYYY-MM-DDTHH:MM)
[ID] [done] Title (finished: YYYY-MM-DD)
runnel-todo edit 2024120101 --title "Buy more groceries" --due 2024-12-05T14:00
runnel-todo edit 2024120101 --due "" # clear the due dateAt least one of --title, --desc, --due, --tags is required.
runnel-todo delete 2024120101 # prompts for confirmation
runnel-todo delete 2024120101 --yes # skip confirmation (use this from agents)pending --start--> in-progress
pending --done----> done
in-progress --done----> done
in-progress --reset---> pending
done --reset---> pending
done --start--> in-progress
Same-status transitions are an error.
runnel-todo metrics
runnel-todo metrics --period week # or month / all (default)Reports total / pending / in-progress / done counts, completion rate, average completion time, overdue count, and items completed in the selected period.
Note:
list --overdueuses a time-level comparison (due_date < now), whilemetricsOverdue uses a date-level comparison (due_date < today). This is intentional.
- Prefer
--yes/-yondeletewhen the agent has already decided to delete — otherwise the process blocks on stdin. - Prefer
--format plain(the default) when parsing output programmatically;tableis for humans. - Probe with
runnel-todo version, notrunnel-todo list—versionskips DB init and has no side effects. - Isolate with
--db— agents running untrusted or ephemeral workflows should point--dbat a temp file rather than the user's~/.runnel-todo/runnel-todo.db. - Branch on exact error strings — see
SPEC.md§5 for the canonical list. Don't fuzzy-match. - For the full agent reference, read
skills/runnel-todo/SKILL.md(or load it as a skill in opencode). It's more complete and token-efficient than this README for programmatic use.
- Default database:
~/.runnel-todo/runnel-todo.db(directory auto-created). - Override with the global
--dbflag:runnel-todo --db /path/to/custom.db list. - All times are in the local timezone.
Requires Go 1.26+ and a C toolchain (CGO is needed for go-sqlite3).
make build # build to ./bin/runnel-todo (injects version via ldflags)
make run ARGS="list"
make test # go test -race ./...
make cover # coverage report -> coverage.out / coverage.html
make lint # golangci-lint run ./...
make fmt # gofmt -s -w .
make vet # go vet ./...
make install # go install (with version ldflags)
make clean # remove ./bin and ./distCross-compilation for releases:
make dist # build + archive all platforms into ./dist
make build-cross GOOS=darwin GOARCH=arm64runnel-todo/
cmd/runnel-todo/main.go # Entry point
internal/
cli/ # Cobra commands + sort/filter + date parsing
db/ # SQLite migrations, TodoStore CRUD, status-transition rules
model/ # Todo struct + status constants/validation
formatter/ # plain / table output formatters
npm/ # npm package (install.js, bin stub)
skills/ # Agent skill: runnel-todo/SKILL.md — authoritative CLI reference for AI agents
.github/workflows/ # Release CI (build, archive, GitHub Release, npm publish)
SPEC.md # Behavioral source of truth (commands, errors, data model)
TEST.md # Testing spec
AGENTS.md # Guide for opencode sessions working in this repo
Makefile
Push a tag matching v* (e.g. v0.1.0) to trigger .github/workflows/release.yml. The workflow cross-compiles for all supported platforms, archives them, creates a GitHub Release, and publishes to npm as @runnel-ai/runnel-todo.
