Skip to content

calendar

rigger calendar [--weeks <N>] [--from <WEEK>] [--json]
rigger calendar [--weeks <N>] [--from <WEEK>] --ics <FILE>

The release calendar as a grid: weeks across, projects down. What a version was aimed at comes from version plan; what actually happened comes from the tags sync reads. Nothing here is a status anyone sets - slippage is the difference between the two, and it appears the moment a tag does.

Terminal window
$ rigger calendar --from 2026-W37 --weeks 5
2026-W37 2026-W38 2026-W39 2026-W40 2026-W41
sample *v0.1.0 >v0.2.0 ·v0.3.0 A
widget +v0.1.0 ·v0.2.0 B
+ shipped as planned < early > slipped ! overdue * unplanned · planned
sample v0.2.0 — aimed at 2026-W37, 2 weeks late

The trailing column is the project’s tier, when it has one.

Mark Meaning
+ shipped in the week it was aimed at
> shipped, but not in that week
! the planned week has passed and there is no tag
* shipped without ever being planned
· planned, still to come

A release that slipped is shown in the week its tag is in, not the week it was aimed at. Showing it in its planned week would leave the grid claiming a release happened in a week that has none; the aim is not lost, it is named underneath with the distance in weeks.

A version that was never aimed at a week still appears once it ships. Hiding it would let the calendar disagree with the tags, which is the failure it exists to prevent.

Two releases in a week are named; more than two are counted, as a span:

Terminal window
$ rigger calendar --from 2026-W33 --weeks 3
2026-W33 2026-W34 2026-W35
sample *v0.1.0..v0.14.0 (14) *v0.15.0 *v0.16.0 >v0.17.0..v0.19.0 (3) B

This is not tidiness. A week of a real record can hold dozens of releases, and naming them all stretches the column past three hundred characters - every row wraps, the heading stops lining up, and the grid cannot be read at all.

The mark on a counted cell is the worst standing inside it, so one release that slipped into a busy week is not hidden by the ones that landed on time beside it. The names are in why either way.

Weeks are ISO-8601: 2026-W37 is the week of Monday 7 September, and it releases on Friday 11 September. ISO is used because it is the same everywhere, needs no locale to read, and starts on the Monday this line already works to.

--weeks is how many to show, starting from this week; --from reads a different span. The current week is marked * in the heading, so a grid read on a Wednesday says where the reader is standing.

A version that is neither aimed at a week nor shipped is in the plan and not on the calendar - digest is the screen for that.

The same weeks as a calendar file (iCalendar), for the calendar on the phone - where Friday’s release and Monday’s focus show before anyone opens a terminal.

Terminal window
$ rigger calendar --weeks 6 --ics rigger.ics
Wrote 3 release Fridays and 2 weeks of focus, 2026-W39 to 2026-W44, to rigger.ics
Import it into the phone's calendar; importing again updates the events rather than doubling them.
  • A release Friday is a whole-day event on the Friday of the week a version is aimed at: sample v0.3.0 · Third.
  • A week’s focus is one event from Monday to Friday naming what is aimed at that week: Focus: sample v0.3.0, widget v0.2.0.

Only what is still ahead goes in: a version already shipped has no Friday left to be reminded of. Every event is transparent - a release day is a marker, not a meeting, and does not show anyone as busy.

Each event’s UID is made of what it is about - release-sample-v0.3.0@rigger, focus-2026-W40@rigger - so importing a newer file updates the events it already made instead of adding copies. - prints the file instead of writing it. There is no server and no network: the file goes where it is told, and getting it to the phone - a synced folder, a mail to oneself - is left to the owner.

With --json, the grid as data.

Field Type Meaning
from string The first week of the span, as 2026-W37.
to string The last week of the span, as 2026-W41.
now string The current week, as 2026-W41.
weeks array Every week of the span.
weeks[] string One week, as 2026-W37.
projects array One row per project.
projects[] object One project’s row.
projects[].project string The project.
projects[].tier string or null Its tier: A, B, C or out; null when it has none.
projects[].rhythm_weeks integer or null How many weeks between releases its tier asks for, or null.
projects[].cells array The versions that fall in the span.
projects[].cells[] object One version in one week.
projects[].cells[].week string The week it is shown in: the week of its tag once shipped, else the week it is aimed at.
projects[].cells[].version string The version’s number.
projects[].cells[].standing string How it reads: planned, shipped, early (shipped before the week aimed at), slipped (after it), overdue or unplanned.

With --ics and --json, what was written.

Field Type Meaning
from string The first week written, as 2026-W37.
to string The last week written, as 2026-W42.
releases integer How many release Fridays the file holds.
focus_weeks integer How many weeks of focus the file holds.
written string or null The file written; null when the file went to standard output.
ics string or null The file’s text when the target was -; otherwise null.
  • version plan - aim a version at a week.
  • next - one week of this, in full.
  • project tier - the tier and rhythm shown here.
  • sync - what reads the tags this compares against.