Subsystem

subroutine commands

The 35 commands subroutine runs directly, each with its arguments and options.

subroutine add

subroutine add [OPTIONS] [words]...

Add something to your list.

Examples:

subroutine add "Call the dentist before Sunday"

subroutine add "Write the report by friday !3 ~2h #work"

subroutine add "Dates render as if this year" --type bug

subroutine add "Cache the roster" --description "Measured at 400ms a call."

subroutine add "Pay the rent" --repeat "every month on the 30th"

subroutine add "Water the plants tomorrow" --repeat "every 3 days" --repeat-from completion

Write the title as an instruction — 'Cache the roster', not 'The roster is cached'. A bug says what is wrong now instead, as the third example does, and a question ends in a question mark: three moods, so a list reads at a glance. '--description' is where the reasoning goes, which is what lets a title stay that short.

'--repeat-from schedule' keeps the rhythm whatever you do — rent is due on the 30th whether or not last month's was paid late. '--repeat-from completion' measures from when you finished, which is what "every three days" means about watering.

Arguments

Options

subroutine agenda

subroutine agenda [OPTIONS] [when]

Show what you are doing today, or what another day looks like.

Examples:

subroutine agenda

subroutine agenda tomorrow

subroutine agenda saturday --days 2

subroutine -w work agenda

subroutine -w work agenda --project acme

A named day is shown as it stands now, so anything already late appears under Overdue whether or not it was late on that day.

Arguments

Options

subroutine today

subroutine today [OPTIONS]

Not listed by subroutine --help.

Say where this went. It is not an alias and does not print an agenda.

'subroutine agenda' is the command now.

subroutine list

subroutine list [OPTIONS]

List everything still open — tasks and documents — newest first.

Examples:

subroutine list

subroutine list --limit 10

subroutine list --order -priority_score

subroutine list --project SR --order due_at

subroutine list --assignee si --status blocked

subroutine list --claimed-by claude --order claimed_at

subroutine list --filter created_at.gte=yesterday

subroutine list --filter completed_at.gte=2026-08-02 --filter completed_at.lt=today

Options

subroutine search [OPTIONS] [terms]

Find things by any of their words, wherever they were written.

Searches tasks and documents together, like 'subroutine list', because one number names either and a search that found only half of them would be lying about the rest.

A tag is found by writing it as you wrote it. Quote it, or the shell reads the '#' as the start of a comment. That finds what carries the tag and anything that mentions it in writing; '--tag' is the narrower question and answers with everything carrying it and nothing else.

Examples:

subroutine search "dentist"

subroutine search "#errand"

subroutine search "pagination" --project SR

subroutine search "boiler" --filter created_at.gte=yesterday

Arguments

Options

subroutine journal

subroutine journal [OPTIONS]

What happened over a period, with who did it and what they said.

'subroutine changes' says what *moved* and is what you resume from a number. This says what *happened* — the same events, with the comments people wrote, the names of who did each thing, and what a change moved between rather than which rows it touched.

Ask it for a period. It is the question to ask when somebody wants writing up.

Examples:

subroutine journal --filter created_at.gte=yesterday

subroutine journal --filter created_at.gte=2026-08-28 --filter created_at.lt=2026-08-29

subroutine journal --by claude --filter created_at.gte=start_of_week

subroutine journal --oldest --filter created_at.gte=today

Options

subroutine changes

subroutine changes [OPTIONS]

What has changed, oldest first — the question to ask after time away.

'subroutine list' says what is open now. This says what *moved*, which is the thing you cannot work out by looking at the current state.

'--by' is how you find out what somebody else has been doing, which is usually an agent you handed work to. '--mine' is the same question about this machine.

'--since' resumes where you left off; '--filter' asks about a period. They are different questions — you have no number to offer for 'what happened yesterday'.

Examples:

subroutine changes

subroutine changes --since 412

subroutine changes --filter created_at.gte=yesterday

subroutine changes --mine

subroutine changes --by claude

Options

subroutine ls

subroutine ls [OPTIONS]

Not listed by subroutine --help.

The short name for 'subroutine list'. Both do the same thing.

Examples:

subroutine ls

Options

subroutine show

subroutine show [OPTIONS] [which]

Read one item — what it is, what it is joined to, and what happened to it.

Works on a task or on a document, because one counter per workspace serves both and a number on a command line does not say which it is.

Examples:

subroutine show 42

subroutine show 42 --json

subroutine show 42 --history

subroutine show 42 --tree

'--tree' walks what has to happen before this can, indented by how deep it sits. On a milestone that is its contents, since a milestone is an item whose blockers are its parts — so it is how you read a plan without opening every item in it.

Arguments

Options

subroutine claim

subroutine claim [OPTIONS] [which]

Not listed by subroutine --help.

Take something, so nobody else starts it too.

Examples:

subroutine claim 42

subroutine release 42

For when more than one person or agent works from the same list. A claim expires on its own, so nothing is stranded if whoever took it never comes back — say it again to hold it for longer.

Work somebody else has claimed disappears from 'subroutine list --ready' until their claim runs out. Your own never disappears from your own.

Arguments

Options

subroutine release

subroutine release [OPTIONS] [which]

Not listed by subroutine --help.

Put something back, so somebody else can pick it up.

Examples:

subroutine release 42

subroutine release --all

Releasing something nobody had claimed is not an error, so this is safe to run when you are not sure. Anybody who can change the task can release it — which is what makes an agent that died mid-task somebody else's problem to solve rather than nobody's.

'--all' is what a session-end hook runs. It says nothing when there is nothing to give back, which is the ordinary case once work has been finished.

Arguments

Options

subroutine verify

subroutine verify [OPTIONS] [which]

Not listed by subroutine --help.

Record what you checked against something, so the next person can see it.

Examples:

subroutine verify 42 --summary "5,610 passed, 41 skipped"

subroutine verify 42 --failed --summary "3 failed in test_agenda"

This is a record, not a proof — anybody can say a check passed without running one. What it is worth is being kept, attributed, and able to go out of date: it carries the state of the code it ran against, so somebody reading it later can tell whether the code has moved since.

In a git checkout the tree is read from git unless you name one. Outside one there is nothing to read, and the record is kept without it — it simply cannot go out of date.

Arguments

Options

subroutine start

subroutine start [OPTIONS] [which]

Say you have started something.

Examples:

subroutine start 42

subroutine stop 42

A person could finish work and put work off and never say they were doing it. The one state that answers "what am I in the middle of" was reachable only over the API.

Arguments

subroutine stop

subroutine stop [OPTIONS] [which]

Say you have put something down again, without finishing it.

Examples:

subroutine stop 42

A state you can enter and not leave is worse than no state, which is why this exists beside 'start' rather than after somebody has asked for it. Picking something up and putting it down is ordinary; having to finish it to stop showing as busy is not.

Arguments

subroutine done

subroutine done [OPTIONS] [which]

Tick something off.

Examples:

subroutine done 42

subroutine done 42 --because "superseded by #99"

Arguments

Options

subroutine skip

subroutine skip [OPTIONS] [which]

Let one of a repeating task go by, and bring the next.

Examples:

subroutine skip 42

subroutine skip 42 --because "away that week"

Arguments

Options

subroutine plan

subroutine plan [OPTIONS] [which] [when]

Say which day you will do something.

'--until' is for something that lasts — a holiday, a conference, a code freeze.

Examples:

subroutine plan 1 tomorrow

subroutine plan 7 "14 august" --until "28 august"

subroutine plan 42 friday --because "the review is on monday"

Arguments

Options

subroutine defer

subroutine defer [OPTIONS] [which] [when]

Hide something until later.

A day on its own hides it until that morning. Write a time as well and it comes back at that time — your agenda still waits for the day to turn.

Examples:

subroutine defer 1 monday

subroutine defer 7 "2026-08-18 06:00"

subroutine defer 42 2026-09-01 --because "waiting on the provider's reply"

Arguments

Options

subroutine move

subroutine move [OPTIONS] [which]

Make something part of another item, or a top-level item again.

Examples:

subroutine move 42 --under 7

subroutine move 42 --top

Arguments

Options

subroutine update

subroutine update [OPTIONS] [which]

Change what a task says about itself.

Everything you do not name is left alone.

Examples:

subroutine update 42 --importance 4 --urgency 3

subroutine update 42 --estimate 2h --type bug

subroutine update 42 --assignee jo --due friday

subroutine update 42 --title "Fix the parser, not the tokeniser"

subroutine update 42 --repeat "every other tuesday"

subroutine update 42 --repeat ""

A repeat belongs to the series rather than to the one in front of you, so changing it changes every occurrence after this one. '--repeat ""' stops it: the work in hand keeps its number and its history, and nothing follows it.

'--expected-version' turns the change down if somebody has saved since. The number comes from 'subroutine show 42 --json', which is where a script reads it; the plain command does not print it, because a version is machinery rather than something you set. Without it the last save wins and the other person's edit goes with no record that it happened.

Arguments

Options

subroutine comment

subroutine comment [OPTIONS] [which] [body]

Record what happened against an item.

A comment is what you *did*; a document is what you concluded. If the next session would need to read it, write it down properly instead.

Examples:

subroutine comment 42 "ran the suite, two failures in the date parser"

Arguments

subroutine uncomment

subroutine uncomment [OPTIONS] [which] [words]

Take a comment back out of an item's record.

Examples:

subroutine uncomment 42 "two failures in the date parser"

Named by what it says, because that is what you are looking at. A comment has no number of its own and its id is a UUID that appears in nothing a person reads — so asking for one would make this a command only a script could run.

Matching more than one is refused rather than guessed at: say more of the sentence. Deleting rather than editing is deliberate. A comment is attributed prose, and rewriting somebody's words under their name is not a thing to be able to do.

Arguments

subroutine link [OPTIONS] [which] [relation] [other]

Say how two items are related.

Examples:

subroutine link 42 blocks 43

subroutine link 42 blocks 43,44,45

subroutine link 43,44,45 blocks 42

subroutine link 42 relates-to 12

subroutine link 7 documents 42

'blocks' is the one that changes what you see: 'subroutine list --ready' leaves out anything blocked by unfinished work, so this is how that filter learns anything.

'documents' is the one that says a decision governs a piece of work, so that whoever picks #42 up can be shown what they have to read before starting it.

Those are the five a new workspace is given. A workspace can rename them or add its own, and naming one this workspace does not have lists the ones it does.

Several numbers separated by commas make one link each, all of the same kind. Either side takes them, and both sides at once means every one of the first joined to every one of the second — which is what 'each of these blocks each of those' says and is the only thing it could say.

Both sides matter because a plan is written from both ends: 'these six make up the roadmap' is six things blocking one, and 'this has to happen before those three' is one blocking three. Laying out a plan is the moment this is most heavily used, and it is the moment one link per command costs most.

Arguments

subroutine unlink [OPTIONS] [which] [other]

Undo a link between two items.

Examples:

subroutine unlink 42 43

subroutine unlink 42 43,44,45

subroutine unlink 42 43 --type blocks

Worth having beside 'link' rather than later. A link added by mistake blocks work that is not blocked, and --ready then hides it — so an unwanted link is worse than a missing one, because it narrows what looks startable and says nothing about doing so.

You do not have to say which kind, because usually there is only one and having to remember the relation is what leaves a wrong link in place. Where two items are joined more than one way, this says so and lists them rather than removing both.

Several numbers separated by commas undo one link each, which is what a plan laid out the wrong way round needs.

Arguments

Options

subroutine delete

subroutine delete [OPTIONS] [which]

Take something off the list that should not have been on it.

Examples:

subroutine delete 42

It goes to the trash rather than vanishing, so it can be put back — the wrong number is the commonest mistake anybody makes here, and the second commonest is making it twice.

Arguments

subroutine restore

subroutine restore [OPTIONS] [which]

Put something back that was deleted.

Examples:

subroutine restore 42

subroutine list --trash

Arguments

subroutine use

subroutine use [OPTIONS] [where]

Not listed by subroutine --help.

Choose what a bare task number means.

It changes what a number means. It never changes what you can see — every listing still spans everything you can reach.

Examples:

subroutine use

subroutine use acme

subroutine use work/acme

subroutine use --here --project SR

subroutine use --reset

'--here' writes a .subroutine file in the current directory, and is what a checkout of a repository wants: it answers "which project is this work" for everything started from here, including an agent, which cannot be asked. Without it the choice is machine-wide, which cannot be right for two repositories at once.

Arguments

Options

subroutine whoami

subroutine whoami [OPTIONS]

Which account this machine is acting as, and what it is allowed to do.

Examples:

subroutine whoami

subroutine whoami --json

Worth asking before the first change of a session. One machine can hold more than one credential — yours in the credentials file, an agent's in the environment — and the one that answers here is the one your next command will act under.

Options

subroutine init

subroutine init [OPTIONS]

Set up Subroutine: create the database and everything a first task needs.

Options

subroutine mcp

subroutine mcp [OPTIONS]

Serve this instance to an AI agent over MCP, on stdin and stdout.

Examples:

subroutine mcp

subroutine mcp --connection work

subroutine mcp --connection work --workspace acme

Speaks the Model Context Protocol over stdio, so a client starts this as a child process rather than connecting to a port. There is nothing to expose and no listener: if the client is not running it, nothing is serving.

One connection, chosen here. Unlike 'agenda', which merges every configured instance because a person has one day, a tool call writes somewhere — and where it writes has to be a decision you can see rather than one this process takes for you.

'--workspace' is the same argument one level down, and it matters as soon as an instance holds two: without it every read is refused as ambiguous, and the agent has no way to learn a name it was never told. It is a default rather than a limit — a call naming a workspace still goes there, and a token pinned to one narrows it for real.

Options

subroutine serve

subroutine serve [OPTIONS]

Serve the HTTP API.

Examples:

subroutine serve

subroutine serve --host 0.0.0.0 --insecure

There is no setting that turns the API on or off, deliberately: if this process is not running there is no socket, and a configuration key that made 'serve' refuse to start would be a confusing way of saying "do not run it". The control that actually controls anything is the bind address, and its default is loopback.

Options

subroutine upgrade

subroutine upgrade [OPTIONS]

Not listed by subroutine --help.

Say where this went. It is not an alias and does not upgrade anything.

'subroutine db upgrade' is the command now.

subroutine help

subroutine help [OPTIONS]

Show what this can do — the same as 'subroutine --help'.

The same answer, deliberately. This used to explain concepts while '--help' listed commands, so one question had two answers and the reader had to learn which was which before learning either. 'help' is what everybody types first, so it answers the commonest question; the concepts moved to 'explain', whose name says what it is for in a way 'help <topic>' never did.

subroutine explain

subroutine explain [OPTIONS] [topic]

Explain a concept — refs, dates, the capture grammar, scripting.

Examples:

subroutine explain

subroutine explain dates

Arguments

subroutine doctor

subroutine doctor [OPTIONS]

Say whether this machine's installation is coherent, and change nothing.

Examples:

subroutine doctor

What is running and where it came from, which configuration it is reading, what each connection answers, and when a backup was last taken. One command because getting it wrong is nearly always the same mistake: running something without the environment the service uses, which acts on a different database and looks exactly like success.

It exits non-zero if anything needs attention, so it can be the last line of an update script rather than something a person reads and forgets.

It talks to the instances you have configured and to nothing else. Whether a newer release exists is a different question, asked with 'subroutine db upgrade --check'.