tli is a fast file-backed task tracker that keeps work state inside your repository instead of in a hosted service. It is designed to be comfortable in a terminal, cheap to query from hooks and agents, and reliable enough to use as local working memory during day-to-day development.
Use it when you want:
- repo-local task state under versioned project context
- compact terminal output for humans
- machine-readable JSON for hooks, scripts, and agents
- pause/resume and handoff flows without opening another app
Most task tools optimize for shared remote dashboards. tli optimizes for the working loop inside a codebase:
- capture work as soon as you notice it
- ask what is actionable now
- checkpoint or hand off without losing the thread
- resume cheaply from the terminal or an AI prompt
The store lives in .tli/, so it stays close to the repo and is easy to inspect, back up, or automate.
cargo install tlinpm install -g @slaveoftime/tliThe npm package ships the compiled tli binary for supported release targets and exposes the same tli command.
git clone git@github.com:slaveoftime/tasks-cli.git
cd tasks-cli
cargo install --path . --forceCreate a store in the repository you want to track:
mkdir .tliThen start using it:
tli add "Ship first public release" --summary "Finalize docs and publication flow" --label release
tli add "Nightly maintenance" --cron "0 22 * * *"
tli state
tli ready
tli start ship-first-public-release --note "Picking this up now"
tli checkpoint ship-first-public-release --next-step "Verify npm release assets"
tli next
tli server start --port 3030tli state
tli ready
tli nextThese commands are the fastest way to answer:
- what is ready right now
- what is due but blocked by dependencies
- what is already in flight
- what should continue after a checkpoint or handoff
tli ready keeps dependency-blocked tasks out of the list by default. The exception is a scheduled task whose due time has arrived: it still appears in ready, but with a warning when unfinished dependencies are preventing the current cycle from actually starting.
tli add "Implement parser cache" --summary "Cache parsed plans by workspace" --label rust
tli add "Nightly cleanup" --every-minutes 1440
tli list
tli show <task-id>
tli --verbose show <task-id>
tli --json show <task-id>Most commands that take a task id also accept a case-insensitive partial id match, so you usually do not need to type the full stored id.
tli server start --port 3030server start serves a compact dark Kanban board and JSON API at http://127.0.0.1:<port>. It binds to localhost only, uses the same .tli/ store and core Rust logic as the CLI commands, and embeds all frontend resources in the tli binary.
tli start <task-id> --note "Picked up after triage"
tli checkpoint <task-id> --note "Pause here" --next-step "Resume benchmark wiring"
tli block <task-id> --reason "Waiting on upstream API"
tli review <task-id> --note "Ready for review"
tli done <task-id> --note "Merged and verified"
tli note <task-id> "Need benchmark follow-up"
tli log <task-id> --limit 20tli dep add <task-id> <dependency-id>
tli dep remove <task-id> <dependency-id>- dependencies gate readiness
tli keeps the default terminal view compact, then expands only when you ask:
tli state
tli --verbose state
tli --json state --limit 6- default output is optimized for terminal scanning
--verboseadds richer human-readable detail--jsonkeeps the command contract stable for hooks, scripts, and agents
For automation, the recommended first call is:
tli --json state --limit 6That payload is meant to stay cheap and actionable. A good pattern for agents is:
- read
state - surface
ready,pending_dependencies, andactive - use aggregate
nextfor real unfinished continuation targets, then drill intoshow,next <task-id>, orlogonly for the task that actually needs detail
Useful follow-up commands:
tli --json show <task-id>
tli --json next <task-id>
tli --json log <task-id> --limit 20
tli skill
tli --json skillThe embedded skill guide is compiled into the binary so prompts and hooks can fetch current usage guidance without reading repository files directly.
--ready-at accepts RFC3339 timestamps and human-friendly local time: 2026-05-10 12:20:10, 12:20:10 for today, or 5-10 13:0:0 for the current year.
By default tli looks upward from the current working directory until it finds an existing .tli/ directory. You can also target one directly with --root.
.tli/
index.json
events.ndjson
task-events/
<task-id>.ndjson
tasks/
<task-id>.json
index.jsonis the cheap summary file used for fast state queriesevents.ndjsonis the append-only activity logtask-events/<id>.ndjsonspeeds up task-specific log readstasks/<id>.jsonstores the canonical task detail
git clone git@github.com:slaveoftime/tasks-cli.git
cd tasks-cli
cargo test
cargo fmt -- --check
cargo clippy --all-targets --all-features
cd e2e && npm install && npm testThe project is intentionally small and file-based. If you are changing behavior, prefer updating the Rust tests in src/store/tests.rs and tests/cli.rs alongside the implementation.
GitHub Actions publishes releases from version tags matching v*.
When you push a tag such as v0.2.0, the release workflow will:
- validate the repo with
cargo test,cargo fmt -- --check, andcargo clippy --all-targets --all-features - build release binaries for Linux x64, macOS arm64, and Windows x64
- upload zipped binaries to the GitHub Release
- publish the crate
tlito crates.io - publish the npm package
@slaveoftime/tli
Create a release like this:
git tag v0.2.0
git push origin v0.2.0Required repository secrets:
| Secret | Purpose |
|---|---|
CARGO_REGISTRY_TOKEN |
publish tli to crates.io |
NPM_TOKEN |
publish @slaveoftime/tli to npm |
The workflow copies the root README.md and LICENSE into the npm package during publication so the package page stays aligned with the repo.
| Need | Command |
|---|---|
| Print embedded usage help | tli skill |
| Create a task | tli add "Title" [--id id] [--summary text] [--ready-at time] [--cron expr | --every-minutes n] [--label tag] |
| Add, change, or clear a schedule | tli schedule <task-id> [--cron expr | --every-minutes n] [--ready-at time] [--clear] |
| List tasks | tli list [--status todo] [--ready] [--label tag] [--query text] [--limit n] [--all] |
| Show actionable work | tli ready [--query text] [--limit n] |
| Show compact repo state | tli state [--query text] [--limit n] |
| Show continuation hints | tli next [task-id] (tli next resolves done handoffs to unfinished targets; tli next <task-id> inspects one task's stored handoff) |
| Inspect a task | tli show <task-id> |
| Start work | tli start <task-id> |
| Save a checkpoint | tli checkpoint <task-id> |
| Block work | tli block <task-id> --reason "..." |
| Request review | tli review <task-id> |
| Finish work | tli done <task-id> [--clear-schedule] |
| Add note | tli note <task-id> "..." |
| View history | tli log [task-id] |
| Add dependency | tli dep add <task-id> <dependency-id> |
| Start local web UI/API | tli server start [--port 3030] |
MIT. See LICENSE.