# Commit tours

> A guided walkthrough of a commit's diff, written by the agent, stored as a git note, and shown in Shelley's diff viewer.

A commit tour is an annotated reading of one commit. Instead of files in
alphabetical order, you get the diff in the order it makes sense: data model
first, then the core logic, then tests, with a sentence or two on why each
piece looks the way it does. Generated files, renames, and whitespace
collapse out of the way. A tour can also list the key design decisions, ask
you questions, and include screenshots or short recordings of a UI change.

Tours cover the whole diff, every hunk exactly once. Shelley checks this by
replaying the tour onto the commit's parent and requiring the exact commit
tree, so a tour can reorder the change but can't leave anything out or
quietly alter it.

## Asking for one

Any of these starts a tour for a commit:

- Type `/tour` in a conversation for `HEAD` of its working directory, or
  `/tour <hash>` for another commit. It takes a commit hash (abbreviated is
  fine), not a ref like `HEAD~1` or a branch name.
- Click **request tour** on the "now at `<hash>`" line that appears after
  the agent commits.
- Select a commit in the git graph and click **Build tour**. The diff
  viewer shows the same button when it's showing a single commit with no tour.

These run a separate worker conversation with the built-in `commit-tour`
skill, using the current conversation's model and reasoning level. While
it works, a *building* link next to the commit opens it. The worker is told not to
touch tracked files, commits, branches, or remotes, and it has 30 minutes.
Tours can be requested from top-level conversations only, and not from an
unsent draft. If the commit already has a valid tour, it just opens.

You can also ask in plain words ("write a commit tour for that") and the
agent follows the same skill itself. To get one for every commit, say so in
your [AGENTS.md](/docs/agents-md).

## Reading a tour

A toured commit is marked **tour** in the git graph and in the diff viewer's
commit picker, and the "now at" line gets a **tour** link. Opening it in the
[diff viewer](/docs/conversations#diffs-git-graph-and-terminal) shows a
**Tour** tab next to **Files**: title and intro, *Key design decisions*,
*Questions for you*, then the diff as titled sections with commentary.
Trivial changes are collapsed. Each question has an **Answer** button that
puts a quoted reply in your composer; decisions and diff lines take comments
the same way. Comments on screenshots work like comments on any image.

Shelley only shows a tour that still verifies against its commit. A note that
no longer matches won't open (the **tour** badge only checks that a note
exists), and requesting a tour for that commit builds a new one.

## Where tours live

Tours are [git notes](https://git-scm.com/docs/git-notes) on the ref
`refs/notes/shelley-tour`, one JSON note per commit, in the repository
itself rather than Shelley's database. Screenshots and recordings are stored
as git blobs pinned by that ref, so the note is self-contained.

```sh
git notes --ref=shelley-tour list
git notes --ref=shelley-tour show HEAD
```

Git doesn't push or fetch notes unless you ask:

```sh
git push origin refs/notes/shelley-tour
git fetch origin refs/notes/shelley-tour:refs/notes/shelley-tour
```

Pushing the ref pushes its pinned media too, and notes history keeps it.
Notes are attached to a commit hash, so amending or rebasing leaves the tour
behind. Git can carry it over if you tell it to:

```sh
git config notes.rewriteRef refs/notes/shelley-tour
```

The copied tour still has to verify against the new commit, so this helps
with reworded messages more than with changed code.

## The `shelley tour` command

This is what the agent runs, and you can too. Every subcommand takes
`-C <dir>` for the repository (default: the current directory); put flags
before the commit. Run `shelley tour` alone for the usage summary.

| Subcommand | Does |
|---|---|
| `chunks <commit>` | Print the commit's diff split into numbered chunks (JSON) |
| `scaffold <commit>` | Print a starting tour that references every chunk in diff order |
| `verify <commit> <tour.json>` | Check that the tour reproduces the commit exactly |
| `attach <commit> <tour.json>` | Verify, then store the tour as the commit's note |
| `show <commit>` | Print the stored tour |

`chunks` has three views: the default JSON (hash, subject, and each chunk's
`id`, `file`, and `patch`), `-index` for one line per chunk with no patch
bodies, and `-text` for raw patches. `-only` narrows it to chunk IDs and
ranges (`0,3-5`) or a single file path:

```sh
shelley tour chunks -index HEAD
shelley tour chunks -text -only 4,7-9 HEAD
shelley tour chunks -text -only server/model.go HEAD
```

The index marks chunks that are provably mechanical (generated files,
whitespace-only hunks, renames, binaries) as `[trivial: reason]`, and
`scaffold` pre-marks them trivial. A typical run:

```sh
shelley tour scaffold HEAD > /tmp/tour.json
# reorder entries, add headers and comments
shelley tour verify HEAD /tmp/tour.json
shelley tour attach HEAD /tmp/tour.json
```

`verify` prints `tour for HEAD verifies`, or an error and exits nonzero. A
tour that leaves something out fails with `tour produces tree <x>, want
<y>`. `attach` re-verifies, replaces any existing note, and is safe to run
concurrently. It stores chunk references resolved to their patch text, so
`show` prints patches rather than IDs.

## The tour format

```json
{
  "version": 1,
  "title": "Short plain-text title",
  "intro": "Markdown: what changed and why.",
  "decisions": [{"title": "One-line decision", "body": "Why, and what was rejected."}],
  "questions": [{"title": "Something for you to decide?"}],
  "chunks": [
    {"header": "## The data model"},
    {"ref": 4, "comment": "Why this shape matters."},
    {"media": "/tmp/after.png", "name": "Settings, after", "comment": "The new screen."},
    {"ref": 0, "trivial": true}
  ]
}
```

Each entry in `chunks` has exactly one of `header` (a Markdown heading),
`ref` (a chunk ID from `chunks`), `patch` (literal patch text, for splitting a
hunk by hand), or `media`. Patch and ref entries may carry `comment` and
`trivial`. Media must be PNG, JPEG, GIF, WebP, MP4, or WebM, 10 MiB at most;
relative media paths resolve against the current directory, not `-C`.
`decisions` and `questions` are optional. The full guidance the agent
follows is the skill itself:

```sh
shelley skill cat commit-tour
```
