tsk is about tasks. Big and small. From working out your next sequence of moves in the codebase to planning large scale cross team initiatives.
It is also designed from the ground up to work in the world of agentic engineering. With a native MCP you can have tsk running alongside your agent and keep track of where you both are, or where youre teams of agents are for that matter. Or even where you, your human colleagues and their agents are!
It's your "sat nav" for work. Keep your human cognitive context and that of your agents clear and keep track of all the work threads you are context switching to.
At the core of the domain of tsk are four dimensions which are facets of any software engineering delivery. Where tsk is different is that it models all four of these dimensions explicitly. Other tools you might be used to like linear or jira only model some parts of these dimensions, and end up being a little too abstract (in the wrong direction) to really give a holistic abstraction.
tsk is very opinionated but within a very specific abstraction. It has a lot of flexibility but in the right dimensions.
The four dimensions are:
- Navigation
- Deltas
- Product
- Scale
tsk is written in Rust. You need the Rust toolchain installed before building or installing.
rustup (recommended — official installer, works everywhere):
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | shHomebrew (macOS):
brew install rustmise (if you use mise for toolchain management):
mise use -g rust@latestOnce installed, verify with:
rustc --version
cargo --versioncargo install tsk-bin tskdSame command — cargo install replaces the existing binaries:
cargo install tsk-bin tskdThis installs two binaries: tsk (CLI + TUI) and tskd (daemon).
1. Start the daemon in your project root:
tskd &The daemon creates a tsk/ directory in the current folder (committed to source control) and a socket at /tmp/tsk-{project-hash}.sock.
2. Create a thread:
tsk thread create fix-login PRIO "Fix the login bug"Priorities: BG (background), PRIO (priority), INC (incident).
Output is JSON — useful for agents and scripting:
{
"id": 1,
"slug": "fix-login",
"state": "paused",
"priority": "PRIO",
"description": "Fix the login bug",
"dir": "/your/project/tsk/threads/0001-fix-login"
}New threads start paused. Use switch-to to activate one.
3. Switch to a thread:
tsk thread switch-to 1 # by id
tsk thread switch-to fix-login # by slug4. Update a thread:
tsk thread update fix-login --description "New description"
tsk thread update fix-login --slug new-slug
tsk thread update fix-login --priority BGAll flags are optional — only the fields you pass are changed. If you change the slug, the thread directory is renamed automatically.
5. List threads:
tsk thread list6. Launch the TUI (no arguments):
tskDisplays threads grouped by section (Active / Priority & Incidents / Background). Updates live when the CLI makes changes. Use j/k to scroll, ctrl-d/ctrl-u to page, gg/G to jump to top/bottom, ? for keybindings, q to quit.
Everything under tsk/ is committed to source control:
tsk/
event-log/
events.ndjson # append-only audit trail of all events
threads/
index.json # authoritative thread state
0001-fix-login/ # per-thread context directory
# Unit tests only
cargo test -p tsk-core
# All tests including e2e (requires cargo build --workspace first)
cargo test --workspacecargo build --workspace --releaseBinaries land in target/release/: tsk and tskd.
Or install locally with just:
just build-install # builds and installs to ~/.cargo/bin
just test # run all tests
just publish # publish all crates to crates.ioBump the version with just bump, commit, then publish:
just bump 0.1.7 # requires cargo-edit: cargo install cargo-edit
git add -p && git commit -m "Bumping version to 0.1.7"
just publishThis publishes tsk-core first, waits 30 seconds for crates.io to index it, then publishes tsk-bin and tskd. The published crate name for the CLI is tsk-bin (it installs the tsk binary).
create
│
▼
┌───────────┐ start ┌─────────────┐
│ not-started│────────────▶│ in-progress │
└───────────┘ └─────────────┘
│ │ ▲
│ cancel block│ │ (unblock?)
│ ▼ │
▼ ┌─────────┐
┌───────────┐ │ blocked │
│ cancelled │◀────────────└─────────┘
└───────────┘ cancel │
▲ │ complete
│ cancel ▼
└─────────────────── ┌──────────┐
│ done │
└──────────┘
Commands: task create, task start, task block, task complete, task cancel, task update, task list.
Tasks live in tsk/threads/{id}-{slug}/tasks.json — one file per thread.
Task fields: id (TSK-{thread-id}-{seq} e.g. TSK-0001-0001), description, state, due_by (ISO 8601, optional), seq (integer, for manual ordering).
All task commands default to the currently active thread. Use --thread <id> to target a different thread explicitly.
A diversion is when something comes up while you are working on one thread that needs recording against a different thread — without switching context. The agent language for this is:
"Diversion: add a task to thread 0004 — follow up with Alice about the API contract"
The --thread flag makes this explicit in the CLI:
tsk task create "follow up with Alice about the API contract" --thread 0004
The active thread does not change. You record the thought and get back to what you were doing.
create
│
▼
┌────────┐
┌─────▶│ PAUSED │◀──────────────────────────┐
│ └────────┘ │
│ │ ▲ │
│ wait resume │ switch-to
│ │ │ │ (another)
│ ▼ │ │
│ ┌─────────┐ ┌────────┐
│ │ WAITING │◀────── wait ──────────│ ACTIVE │
│ └─────────┘ └────────┘
│ ▲
└──────────────── switch-to ─────────────────┘
create→ always starts pausedswitch-to→ target becomes active; previously active thread becomes pausedwait→ marks a thread waiting (blocked on external dependency); works from active or pausedresume→ returns a waiting thread to paused; useswitch-toto make it active again
tskd is a headless daemon that owns all state. tsk is a thin client — in CLI mode it sends a JSON-RPC request over a Unix socket and exits; in TUI mode it watches tsk/threads/index.json for changes and re-renders instantly. Multiple clients (CLI, TUI, agents) can talk to the daemon concurrently. See doc/arch/ and doc/adr/ for the full architecture.
CodeQL static analysis runs on every push to main and weekly. Rust requires an advanced setup (.github/workflows/codeql.yml) because CodeQL must compile the code to analyse it — the default GitHub setup does not support Rust.
- Configuration file (
tsk.tomlor.tskrc) — per-project and per-user settings. First planned setting:show_status_bar = true/falseto toggle the TUI status bar.