Keyboard shortcuts

Press ← or → to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

sd update

Change one or more seeds. All the named seeds change in one transaction, or none do.

sd update sd-a3f --status in_progress --add-label parser
sd update sd-a3f --claim                 # atomically take it
sd update sd-a3f sd-b7c --priority 0
sd update sd-a3f --defer 2026-10-15      # hide from ready until then
flagmeaning
--title, -d, --description, --notes, --design, --acceptance-criteria (alias --acceptance)set the text (see below for replacing existing text)
--forceallow replacing a non-empty description, notes, design, acceptance criteria or agent context with different content
-s, --statusopen, in_progress, blocked, deferred, closed
-p, --priority0-4 or P0-P4
--assignee NAMEset the assignee ("" clears it)
--owner WHOset the owner ("" clears it)
--external-ref REFa reference to the same work elsewhere, br’s external_ref ("" clears it)
--agent-context JSONbr’s agent_context: inline JSON, @path or @path.yaml/.yml, stored as compact JSON. "" clears it; replacing or clearing a non-empty one needs --force
--due WHENdue date, the forms of --defer; a bare date or tomorrow is 09:00 local, stored as a UTC instant ("" clears it)
--estimate MINtime estimate in minutes, 0 to 525960
--check-acceptance ITEMStick acceptance checklist items in place: 1-based numbers (1,4,5) or a text selector matching exactly one item (case-insensitive; an exact match wins, else a unique substring). Repeatable; needs no --force; the rest of the field is kept byte for byte
--uncheck-acceptance ITEMSuntick items; the same selectors
--add-acceptance TEXTappend - [ ] TEXT to the checklist (repeatable). Checklist edits and --acceptance-criteria are not combined in one update
--claimset assignee to the actor and status to in_progress, only if the seed is open, unclaimed and unblocked
--add-label, --remove-labelrepeatable
--defer DATEhide from ready until this date or instant ("" clears it)
--workflow-run RUNthe shuttle run driving it ("" clears it); see Formulas

--claim is a compare-and-set. It succeeds for exactly one caller: a second claimer, or a claim on a blocked or non-open seed, exits 4 and writes nothing. Claiming your own claim again is a no-op. The actor is --actor, else SEEDS_ACTOR, else $USER.

Setting status to closed records closed_at; setting it back to anything else clears closed_at and close_reason. An update that changes nothing writes nothing.

Explicitly setting a status other than deferred (or using --claim) also clears an old defer date and retires resume_when: notes markers to historical resume condition: in that same transaction. The condition and surrounding evidence remain in the notes. This also repairs stale parking metadata when the requested status already matches. A non-empty --defer in the same request deliberately establishes a new hold and preserves its resume marker. Edits without a status or claim preserve existing holds.

Existing text is not replaced by accident. Setting a description, notes, design, acceptance criteria or agent context that already has text to different text (including "") is refused with exit 5, naming the field, and nothing is written, unless --force is given. This is br’s guard (br’s --force). Filling an empty field, or setting the same text again, needs no --force, so re-running an update is safe. The replaced text stays in the seed’s history (sd history). The check runs in the shared update path, so a local store and a quipu server refuse alike.

--json: an array of the updated seed objects, each with the tx.

Exit codes: 0; 2 for a bad value or --claim combined with --assignee or --status; 3 for an unknown id; 4 for a lost claim or a concurrent change; 5 for replacing existing text without --force.

sd update ID -a owner is the short form of --assignee owner.

Rank within a priority

sd update ID --rank 10 assigns an exact decimal ordering key; --rank "" clears it. --before OTHER and --after OTHER insert only ID beside a ranked, live item of the same priority, without editing neighbors or deadlines. Moves accept one ID and cannot change priority or claim work in the same command.

Ranks are canonical decimal strings in JSON (null when absent), with up to nine fractional digits and magnitude at most 9000000000000000000. No binary floating point is used. Tied anchors, exhausted precision and boundary exhaustion refuse without renumbering. Explicit rank assignments may tie; ordering then uses due date, creation time and ID. Moving is relative to the observed cohort: concurrent independent moves may receive the same rank. The moved item’s revision is checked atomically; neighbors are never rewritten.

sd ready defaults to priority,rank; sd list --sort priority,rank requests the same order. Unranked items sort last within their priority, oldest first. Due dates remain time limits and are never changed by ranking.

A reviewed bulk migration can use scripts/migrate-ranks.py. Its plan is a JSON object with quipu, graph and rows; each row names id, canonical rank (or null), and expected priority, revision, rank and due_at. The default is a read-only rehearsal. Execution requires --execute --plan-sha256 SHA; every edit uses --if-revision and touches only rank. The receipt records each completed edit and a revision-guarded rollback plan. A refusal or unknown outcome stops without retry or automatic rollback. Inspect pending_id before continuing. Rehearsal and execution need distinct receipt paths; an existing receipt is never overwritten. Do not derive ordering from current deadlines implicitly: review an explicit order and its current target preconditions first.