Skip to content

why

rigger why <PROJECT> <VERSION> [--json]
rigger why [PROJECT] --principle <NAME> [--json]
rigger why --principles [--json]

Shows the work that went into one release: what was decided, what was learnt, what was tripped over, and what changed - everything recorded between the release before it and itself.

Terminal window
$ rigger why sample v0.3.0
v0.3.0 — shipped 2026-09-04
the work after v0.2.0 (2026-09-04)
2026-09-04 decision The budget is a gate, not a suggestion.
2026-09-04 pitfall A wide window hides what the budget dropped.
2026-09-04 change feat: rank what a person wrote above a commit

No event carries a version of its own, and none needs to: a release is bounded by the release before it, so the record can answer this for versions that shipped long before the question was asked.

From the previous release to this one, by the moment each was tagged rather than the day. A day would not be enough - this line ships several versions in an afternoon, and a day-wide window would hand every one of them the whole day’s work.

The lower bound is exclusive and the upper inclusive. That asymmetry is the point: a tag points at a commit, so a release and its last commit share a moment. Inclusive at the top keeps that commit in the release it shipped; exclusive at the bottom keeps it out of the next one.

Two releases tagged in the same second have nothing between them, and why says so rather than showing an empty answer that looks like a missing record.

A version imported from a hub carries only the day it shipped, which still bounds the window - less precisely, but better than not at all. Run rigger sync and the tag supplies the moment.

The current stage has no upper bound, so its window runs to now:

Terminal window
$ rigger why sample v0.4.0
v0.4.0 · Search — being built
the work after v0.3.0 (2026-09-04)
2026-09-04 decision A bare word is searched as a prefix.

That is the work in progress, which is exactly what a session picking up the stage wants to see.

The number is matched by value, not by text, so v1.9, 1.9 and v1.9.0 all find the stage recorded as v1.9.0 - hubs spell a version several ways and nobody remembers which.

A version the record does not have is refused, with a pointer to what it does have.

Under --json a version prints its window: the project, the version, the version before it, then the events between them.

Field Type Meaning
project string The project’s name.
version object The version asked about.
version.name string The version, as the record spells it.
version.title string The stage’s title.
version.status string The version’s state, such as planned or shipped.
version.shipped_at string The day it shipped, YYYY-MM-DD.
version.shipped_ts string The moment it was tagged, RFC 3339 UTC.
after object The release before it, which bounds the window.
after.name string That version.
after.title string Its title.
after.status string Its state.
after.shipped_at string The day it shipped, YYYY-MM-DD.
after.shipped_ts string The moment it was tagged, RFC 3339 UTC.
events array The events recorded in the window.
events[] object One event.
events[].project string The project it belongs to.
events[].kind string decision, finding, pitfall, change, question or wish.
events[].date string The day it was recorded, YYYY-MM-DD.
events[].body string The event’s text.
events[].from_git boolean Whether it was read from a commit message.
events[].commit_hash string or null The commit it came from; null for what a person wrote.

With --principle it prints an array of the decisions standing on that principle, oldest first. With --principles it prints an array of pairs, each a principle’s name and the number of decisions on it.

Field Type Meaning
[] object A decision standing on the principle, with --principle; a principle, with --principles.
[].principle string With --principles: the principle’s name, as decisions spell it.
[].decisions integer With --principles: how many decisions stand on it.
[].project string The project the decision belongs to.
[].kind string The event’s kind; always decision.
[].at string When it was recorded, RFC 3339 UTC.
[].body string The decision’s text.
[].version string or null The version it was recorded against; null when it was against none.

A version is one window on the record. A principle is another, cut the other way: every decision that stands on one thing this line believes, from every project, oldest first.

Terminal window
$ rigger why --principle "no users, no compatibility"
no users, no compatibility
6 decisions across 5 projects
2026-08-30 · sample
Broke the format outright rather than reading both.
...

Read one project at a time, six such decisions look like six opinions. Read as one thread they are something the line learnt, with what it cost each time - which is what makes a principle arguable rather than a slogan.

Naming a project alongside narrows it to that project’s share.

--principles prints the vocabulary: every name used, with how often.

Terminal window
$ rigger why --principles
no users, no compatibility — 6 decisions
measure the screen — 3 decisions

A name nothing stands on is far likelier a misspelling than a new principle - these are typed by hand, months apart - so the answer lists the ones the record knows rather than an empty result.

Decisions carry a principle when they are recorded: see note --principle.

  • note - naming the principle a decision stands on.
  • find - searching by word rather than by version.
  • sync - what supplies the tags this window is drawn from.
  • context - the current stage and its open tasks.