<!-- Generated by crates/swarmops-cli/src/reference.rs from the code: do not edit. Change the code, then run SWARMOPS_REGEN_REFERENCE=1 with the regen_reference test. -->

# swarmops show

Show one changeset.

```yaml
title: "swarmops show"
description: "Show one changeset."
group: "read"
since: "0.1.0"
mutates: false
identity_required: false
mcp_tool: "show"
envelope_op: "show"
exit_codes: [0, 2, 6]
errors: [E_NOT_A_REPO, E_REV_NOT_FOUND, E_INVALID_ARG]
syntax: "swarmops show [OPTIONS] <REV>"
```

## Syntax

```text
swarmops show [OPTIONS] <REV>
```

## Required arguments

### `REV`

Syntax: `<REV>`.

The changeset.

## Optional arguments

The command also takes the [global options](../cli.md#global-options).

### `--max-changes`

Syntax: `--max-changes <N>`.
Default: `400`.

The most changes to list.

## Examples

### CLI

```sh
swarmops --repo [tmp]/store show main
```

```json
{
  "ok": true,
  "op": "show",
  "api": 1,
  "result": {
    "id": "[c2]",
    "seq": 1,
    "parents": [
      "[c1]"
    ],
    "root": "[root2]",
    "author": {
      "agent": "agent/worker-17"
    },
    "created_at": "[created_at]",
    "message": "second",
    "changes": [
      {
        "path": "README.md",
        "op": "put",
        "kind": "file",
        "blob": "[id1]"
      },
      {
        "path": "notes.txt",
        "op": "delete"
      }
    ],
    "files_changed": 2,
    "changes_truncated": false,
    "metadata": {
      "agent": "agent/worker-17"
    },
    "signatures": {
      "author": {
        "name": "agent/worker-17",
        "email": "worker-17@agent.swarmops.local",
        "secs": "[secs]",
        "offset_secs": 0
      },
      "committer": {
        "name": "agent/worker-17",
        "email": "worker-17@agent.swarmops.local",
        "secs": "[secs]",
        "offset_secs": 0
      }
    }
  },
  "meta": {
    "repo": "[tmp]/store",
    "elapsed_ms": "[elapsed_ms]",
    "resolved": {
      "main": "[c2]"
    },
    "auth": "trust"
  }
}
```

Exit code 0. Recorded by the CLI tests. A name in square brackets, such as `[tmp]` or `[c1]`, stands for what differs from run to run: the test's temporary directory, an id, a time.

### MCP

No recorded example yet.

## Details

`show` prints one changeset whole: its place in the store, its parents and root tree, who wrote
it and who landed it, its message, the files it changed against its first parent, its metadata
and its git signatures. Use it to inspect a change before you land it, after it landed, or when
an error names one.

### Any changeset, on a ref or not

REV is any revision, so `show` reads changesets that no ref names: an agent's commit that has not
landed yet, or the `actual` of an `E_CAS_MISMATCH`. `seq` is the changeset's place in the store's
index, in commit order, counting every changeset the store holds; it is not a position on
`main`, and the `seq` values along `main` can skip numbers.

### Who and when

| Field | Holds |
| --- | --- |
| `author.agent` | The agent that wrote the change: the `agent` metadata, or `unknown/unknown` when there is none (as for a changeset `git import` made). `author.run_id` is the `run_id` metadata, when present. |
| `lander` | Only on a changeset a `land` made: the agent that landed it. |
| `created_at` | The committer signature's time, in Unix milliseconds. For a landed changeset that is when the land published it, not when its author committed. |
| `signatures` | The git author and committer, kept for git round trips; `secs` in Unix seconds. |

A land squashes the change it publishes into one changeset whose parent is the ref's head. Its
`author` is the change's author, `squashed_from` lists the changesets it squashed (oldest first,
ending at the head that was landed), and `land_key` is the `--key` of the land, when it had one.

### The changes

`changes` lists what changed against the first parent, sorted by path: `op` is `put` (with the
file's `kind` and `blob`) or `delete`. A change of an executable bit alone is a `put` whose
`blob` did not change. `--max-changes` (400 by default, at least 1) caps the list; `files_changed`
still counts every path, and `changes_truncated` says the list was cut. There is no cursor: to see
every file of a large changeset, `diff` it against its first parent (`diff REV~1 REV`) and page
the diff. A changeset made with `commit --allow-empty` has `changes: []` and `files_changed: 0`.

`metadata` holds the changeset's SwarmOps metadata as text, such as `agent`, `run_id`,
`commit_key`, `land_key`, `lander` and `squashed_from`; a value that is not UTF-8 comes in base64
under its key with `:b64` appended.

### Patterns

- **Review before landing.** `show <changeset>` of a commit an agent reports gives its files and
  blob ids, `cat <changeset>:<path>` reads any of them, and `diff <base> <changeset>` shows what
  the change did since the base it started from.
- **Trace a landed change back.** On `main`, `show` gives `lander`, `land_key` and
  `squashed_from`; `show` of each id in `squashed_from` gives the original commits.
- **Check a retry.** After an `E_CAS_MISMATCH`, `show <actual>` gives the winner's `agent` and
  `run_id` metadata: the way to tell another agent's change from your own earlier attempt.
- **Through MCP**, the tool is `show`, with `rev` and `max_changes`. Ask for 100 changes or fewer
  a call: see [Result size limits](../../develop/mcp.md#result-size-limits).

### Caveats

- The changes of a merge are those against its first parent: what it brought in from its other
  parents shows as its own change. Native histories have no merges; histories brought in by
  `git import` can.
- `show` lists no renames: a moved file is a `delete` and a `put`.
- `--max-changes 0` is `E_INVALID_ARG`.

### Performance

`show` makes its reads in one snapshot. In the v0.1.0 measurement `show main` took 59.1 µs p50
with no ref but `main`, 149 µs with 16 more refs and 1.55 ms with 256: a snapshot reads every
ref file. See
[the performance ledger](../../perf.md#v010--just-perf-in-a-quiet-window-2026-10-21).

### Guides

- [Reading and repairing history: Look at one changeset](../../guides/history-and-undo.md#look-at-one-changeset)
- [Concepts: Land](../../concepts.md#land)
- [Known limitations: Commits, refs and history](../../known-limitations.md#commits-refs-and-history)

## Return information

`result` is a `ChangesetDetail` (`swarmops schema ChangesetDetail` prints its JSON Schema).

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `author` | `Attribution` | yes | Who wrote the change. |
| `changes` | `array of ChangeOut` | yes | What changed relative to the first parent, ordered by path: at most `max_changes` entries. |
| `changes_truncated` | `boolean` | yes | Whether `changes` stops before the changeset's last change. |
| `created_at` | `integer` | yes | When it was recorded: the committer signature's time, in Unix milliseconds. |
| `files_changed` | `integer` | yes | How many paths the changeset changes in all, also when `changes` is truncated. |
| `id` | `string` | yes | The changeset's id. |
| `land_key` | `string or null` | no | The idempotency key of the land that made it (its `land_key` metadata), when it had one. |
| `lander` | `Attribution or null` | no | Who landed it, for a changeset a `land` made: its `lander` and `lander_run_id` metadata. Omitted for any other changeset. |
| `message` | `string` | yes | The message. |
| `metadata` | `object` | yes | SwarmOps metadata, such as `agent` and `run_id`. A value that is not UTF-8 is given in standard, padded base64, under its key with `:b64` appended. A commit refuses a key that ends in `:b64`, so `k:b64` is always the base64 of `k`'s value, which is not UTF-8. |
| `parents` | `array of string` | yes | The parents' ids; the first is the mainline parent that `changes` are relative to. |
| `root` | `string` | yes | The root tree's id. |
| `seq` | `integer` | yes | Its position in the store's changeset index, in commit order. |
| `signatures` | `Signatures` | yes | The git author and committer signatures, kept for git fidelity. |
| `squashed_from` | `array of string` | no | The changesets a land squashed into it, oldest first: the landed head's first-parent chain after the land's base, ending at that head (its `squashed_from` metadata). Omitted for a changeset no land made. |

Envelope `op`: `show`.

Exit codes:

- `0`: Success.
- `2`: The request or the command line is malformed.
- `6`: Something the request names does not exist.

## Errors

- [`E_NOT_A_REPO`](../errors.md#e_not_a_repo) (exit 6): No store at the given path, or no store was named.
- [`E_REV_NOT_FOUND`](../errors.md#e_rev_not_found) (exit 6): A revision names no changeset.
- [`E_INVALID_ARG`](../errors.md#e_invalid_arg) (exit 2): A malformed argument or request, including a command-line usage error.

Any command that opens a store may also fail with a store error, such as [`E_NOT_A_REPO`](../errors.md#e_not_a_repo), [`E_IO`](../errors.md#e_io) or [`E_STORE_CORRUPT`](../errors.md#e_store_corrupt); a command line the grammar refuses is [`E_INVALID_ARG`](../errors.md#e_invalid_arg) (exit 2).

## See also

- [Quick start: How do I read it back?](../../guides/quick-start.md#4-how-do-i-read-it-back)
- [`swarmops resolve`](resolve.md)
- [`swarmops cat`](cat.md)
- [`swarmops ls`](ls.md)
- [`swarmops log`](log.md)
- [`swarmops history`](history.md)
- [`swarmops diff`](diff.md)
- [CLI reference](../cli.md)
- [Error codes](../errors.md)
