taskr

Getting started

taskr in ten minutes

taskr is a record your agents read before they start and write before they stop. There is nothing to orchestrate and no runtime to adopt: install a CLI, mint a key, and the loop below is the whole integration. The key is the only part that has to be you — the agent can do the rest of the setup itself.

Install

macOS and Linux. The installer puts the binary in ~/.local/bin — set TASKR_INSTALL_DIR to send it somewhere else.

curl -fsSL https://aitaskr.com/install.sh | sh
taskr: downloading v0.7.0 for linux/amd64
taskr: installed v0.7.0 to /home/you/.local/bin/taskr
installed /home/you/.agents/skills/taskr/SKILL.md
installed /home/you/.claude/skills/taskr/SKILL.md
Restart your agent session to pick them up.
taskr: next, run taskr auth login

With a Go toolchain instead: go install github.com/thomas-cabral/taskr-cli/cmd/taskr@latest, then taskr skill install once by hand. On Windows, take the zip from the releases page.

The installer also writes the agent skills — the file that teaches Claude Code, Codex, Cursor and opencode that taskr exists. They ship inside the binary, so taskr skill install after an upgrade rewrites them in step with the verbs the binary actually has. TASKR_SKILLS=0 skips them.

Get a key

A key carries the identity of whoever holds it, and that is where authorship comes from: a write authenticated by a key is recorded as that key's actor, whatever the request claims. Mint one key for yourself and one per agent, and label the agent's as an agent.

taskr auth login
Open: https://api.aitaskr.com/activate
Code: WDJB-MJHT
Or go straight there: https://api.aitaskr.com/activate?code=WDJB-MJHT
Waiting for approval...
Logged in. This machine writes as agent.
taskr auth status
host https://api.aitaskr.com
writes as agent
scopes read, write, agent_context

taskr auth login prints a code and a URL, then waits — approve it in a browser and the key lands the moment you do. It never opens the browser for you: RFC 8628 is browserless by construction, so the same command works unchanged on a laptop, over SSH and inside a container. Piping a key still works exactly as before (echo $TASKR_KEY | taskr auth login) and remains the right way to hand one to CI or a container. taskr auth status tells you which name your writes will carry before you make one.

Where the key comes from

Approving at /activate is what mints it: enter the code your terminal printed, or follow the link that already carries it, then confirm with a second press of Approve. It is shown once and never again — the server keeps a hash, so a lost secret costs a new key, never an account.

settings → keys is where you mint one by hand instead — a key that writes as you rather than as an agent, one scoped narrower than everything, or one to hand to CI or a container rather than approve in a browser. Every key lists and revokes there regardless of how it was minted, and revoking one also signs out every browser session it opened. That is the answer to a laptop you no longer have.

From here the agent can take over

The key was the one step that had to be you. Everything below you can still run yourself — but you mostly will not have to. The first time an agent runs taskr in a project it does not recognise, the taskr-onboarding skill the installer wrote does this setup on its own: it reads what already exists before creating anything, registers the repo, and proves the registration took before carrying on.

What follows is that same sequence, spelled out. Worth reading either way — it is three commands, and knowing what your agent did is cheaper now than the first time something looks off.

Register the repo

A project is the thing issues belong to; a repo is attached to it. taskr refuses a write from a repo it has never seen rather than filing it into whatever project happened to be active, so this is the one piece of setup per checkout.

This is the step taskr-onboarding exists for — "onboard this repo to taskr" is the whole instruction. What follows is what it does.

Run these from inside the checkout — taskr reads .git itself for the origin, the worktree root, the head and the branch, which is what resolves your project on every later command.

cd ~/code/billing
taskr project init billing --key PAY --pr-target main
Initialized billing (PAY).
taskr project attach
Attached github.com/acme/billing to billing.

Two steps, because they answer different questions: project init creates the project and its ref prefix, project attach says that this checkout is one of its repos. Attach defaults both arguments to what it reads from .git, which is why it takes none here.

Conventions are optional and worth setting: --branch-format (a shape like tc/{key}-{n}--{slug}), --commit-style and --pr-target are printed by taskr project ls and beside the project in taskr context, so an agent reads them instead of guessing your house style. Naming one later re-runs project init safely — it upserts on the slug, and a convention you do not name is left exactly as it was. In a monorepo, taskr project attach --project billing --dir services/billing registers a directory inside the repo as its own project's territory.

Writes are refused against an unregistered repo, on purpose: an issue filed against a checkout nobody has claimed cannot be ranked, scoped or resumed.

The first loop

Four verbs carry a whole day. This is all of it:

taskr new "Stripe webhook retries double-charge" -k bug -p high
Created PAY-31 — Stripe webhook retries double-charge
taskr start PAY-31
PAY-31 — Stripe webhook retries double-charge
status: in_progress priority: high kind: bug
This is a fresh start — no prior park on this issue.
taskr comment PAY-31 -m "one invoice per event id, unique index on event_id"
Commented on PAY-31.
taskr close PAY-31 -r "unique index on event_id; retries are no-ops now"
Closed PAY-31.

taskr next ranks what is ready rather than listing everything, and taskr context answers "where am I, what was I doing" — the first thing to run in a fresh terminal or a fresh agent turn.

The verb that earns its keep is the one you reach for when you stop. A session that ends without parking leaves the next reader nothing:

taskr park -m "add the replay case to webhook_test.go, next to TestChargeOnce" -r context_exhausted
Parked PAY-31 (context_exhausted).

Name the next concrete action, not a summary of what happened — the timeline already has that. -r says which kind of stop it was: done_for_now, blocked, interrupted, context_exhausted or handoff, which is how next tells "pick this up any time" apart from "actually stuck".

Hand it to an agent

Nothing else to wire. The skills the installer wrote are read by your harness at the start of a session, and the agent shells out to the same binary you just used. What changes is the shape of a turn: read the record before starting, write to it before stopping.

  • taskr context at the top of a turn, so a cold agent lands somewhere real.
  • taskr offload the moment it notices something that is not the task — filing is nearly free, losing the thread is not.
  • taskr park -m … before the session grows past the point of continuing, which is the difference between a handoff and a restart.

One environment variable is worth knowing about: TASKR_SESSION names the invocation context, so a terminal and an agent on one machine do not share a work session. taskr reads it from the harness when there is one to read (CLAUDE_CODE_SESSION_ID, OPENCODE_PID) and falls back to the parent process id. Export it yourself under a harness that publishes neither and spawns a fresh shell per tool call.

Where to go next