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

canon trail

Read the decision trail. Canon records every effectful action (decision provenance); trail is how you read that record back — as a timeline of what happened, with your notes interleaved as the thinking between the actions.

One command, two lenses:

  • The scope lens — standing in a folder: what did I do here? Decisions touching this place, as a timeline ending at now.
  • The time lens (--today, --since, --on) — what did I do today? The day’s decisions as a story, with a rollup of what was deleted, archived, and excluded.
# What happened here?
canon trail

# What happened in a specific folder?
canon trail /mnt/old-drive/photos

# Today's story, across all roots
canon trail --today --global

# Everything since Saturday
canon trail --since saturday

# One specific day
canon trail --on 2026-05-12

# One decision in full
canon trail show 61

trail is a pure query command — it never changes anything.

The scope lens

With no time flags, trail lists the decisions that touched the current scope — a timeline reading oldest to newest, ending at the most recent:

Decision trail: /mnt/old-drive/photos

#42   2026-05-12 14:03  .       Applied italy-2016: 47 copied, 0 errors
#57   2026-07-11 15:10  .       Scanned 4,120 files: 12 new, 1,350 missing · "verified duplicates"
#61   2026-07-11 16:42  misc    Excluded 210 duplicates (kept 105) · "redundant backup"
      2026-07-11 16:50  italy   ~ unsure about the RAW files — revisit

12 earlier decisions not shown (--limit N or --all; showing 20).
2 global decisions not shown (--global).

A decision touches the scope in either direction: a decision on a parent folder happened to this folder too, and a decision on a subfolder is activity here. Sibling folders’ decisions don’t appear.

Each line carries the decision id, timestamp, the scope it acted on, the completion summary, and your --reason (quoted). The scope column is relative to what you’re viewing (. is the viewed folder itself); in global views it shows the path, capped from the left. Decisions recorded without a scope show global. Decisions that did not complete cleanly are marked ([partial], [interrupted], [started]).

The listing is capped at the 20 most recent decisions; the footer tells you what’s beyond the cap (--limit N or --all to widen). Decisions recorded without a scope — global operations — can’t be attributed to any folder, so scoped views count them in a footer instead of silently hiding them.

The time lens

--today, --since <when>, or --on <when> switch to the day-grouped story view — chronological, so it reads forward:

Decision trail: all roots — today

Saturday 2026-07-12 — deleted 1,350 files (35.0 GB), archived 47 files (3.9 GB), excluded 210 files — and 2 other actions

#63   09:14  /mnt/kali             Scanned 4,120 files: 12 new, 1,350 missing · "verified duplicates"
      09:40  /mnt/kali/photos      ~ unsure about the RAW files — revisit
#64   11:02  ...ive/photos/italy   Applied italy-2016: 47 copied, 0 errors
#65   11:30  /mnt/kali/misc        Excluded 210 duplicates (kept 105) · "redundant backup"

<when> accepts today, yesterday, a weekday name (the most recent one, today included), or a date (YYYY-MM-DD). Days follow your local timezone.

Each day opens with a rollup by fate: deleted (deletions a scan observed), archived (apply), excluded, plus a count of other actions (scans that deleted nothing, manifest generation, imports, and so on). Sizes are computed from the index and shown when reliable — for older decisions whose files have since been touched by newer decisions, the size is omitted rather than guessed.

Scope still applies: canon trail --today inside a root shows that folder’s day; add --global for the whole story.

Notes in the timeline

Notes (canon note) interleave with decisions by default, marked with ~ and carrying no id, counts, or status — a thought never reads as an action. The two commands split one story: the trail holds actions (“what did I do?”), notes hold thoughts (“what did I think?”). Use --no-notes for decisions only.

Inspecting one decision: trail show

The id on every line drills down:

$ canon trail show 61
Decision #61 — exclude_duplicates
  when:     2026-07-11 16:42
  status:   completed
  counts:   attempted 315, completed 210, failed 0, skipped 105
  reason:   "redundant backup"
  command:  canon exclude duplicates /mnt/old-drive/photos --prefer /archive ...
  scope:    /mnt/old-drive/photos
  version:  0.5.2
  summary:  Excluded 210 duplicates (kept 105)
  receipts:
    /archive/.canon-ledger/000061-exclude_duplicates.toml

show lists where the decision’s receipts live on disk — including one receipt per source root for deletions. It does not print receipt contents; open the file to see the per-item record. When there is no receipt, the reason is stated (no receipt (--no-receipt) or no receipt recorded) — absence is never silent.

Machine output

--jsonl emits one JSON object per timeline event, with a type field ("decision" or "note"), the raw command identifier, timestamps, counts, reason, scope, summary, and receipt location. The scope header moves to stderr so stdout stays clean:

canon trail --today --global --jsonl | jq -r 'select(.type=="decision") | .summary'

Flags

FlagMeaning
--globalAll roots, ignoring current-directory scope
--todayTime lens: today (sugar for --since today)
--since <when>Time lens: from a day onward
--on <when>Time lens: one day
--limit NShow at most N decisions (default 20)
--allNo cap
--no-notesDecisions only
--jsonlMachine output (JSONL on stdout)