<!-- 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 ls

List one directory at a revision (the root without a PATH), and with --depth the directories below it.

```yaml
title: "swarmops ls"
description: "List one directory at a revision (the root without a PATH), and with --depth the directories below it."
group: "read"
since: "0.1.0"
mutates: false
identity_required: false
mcp_tool: "read_tree"
envelope_op: "read_tree"
exit_codes: [0]
errors: []
syntax: "swarmops ls [OPTIONS] <REV[:PATH]>"
```

## Syntax

```text
swarmops ls [OPTIONS] <REV[:PATH]>
```

## Required arguments

### `REV[:PATH]`

Syntax: `<REV[:PATH]>`.

The revision, and the directory's path after the first ':'.

## Optional arguments

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

### `--depth`

Syntax: `--depth <N>`.
Default: `1`.

How many levels to list: 1 for the directory's own entries, 2 for theirs too, and so on, up to 64.

### `--limit`

Syntax: `--limit <N>`.
Default: `250`.

The most entries to list.

### `--cursor`

Syntax: `--cursor <CURSOR>`.

Resume a listing: the previous page's cursor, exactly as it was returned.

## Examples

### CLI

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

```json
{
  "ok": true,
  "op": "read_tree",
  "api": 1,
  "result": {
    "entries": [
      {
        "name": "README.md",
        "kind": "file",
        "size": 18,
        "id": "[id1]"
      },
      {
        "name": "bin",
        "kind": "dir",
        "id": "[id6]"
      },
      {
        "name": "latest",
        "kind": "symlink",
        "size": 9,
        "id": "[id4]"
      },
      {
        "name": "logo.bin",
        "kind": "file",
        "size": 4,
        "id": "[id2]"
      },
      {
        "name": "src",
        "kind": "dir",
        "id": "[id7]"
      }
    ],
    "truncated": false
  },
  "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

`ls` lists a directory at any revision without a checkout: names, kinds, sizes and object ids,
one page at a time. With `--depth` it walks the directories below as well, so one call can map a
whole subtree.

### What the target names

`REV` alone, or `REV:` with an empty path, lists the root. `REV:PATH` lists the directory at
PATH, and one trailing `/` is taken (`main:src/` is `main:src`); a second one is
`E_INVALID_ARG`. The target splits at the first `:`, as `cat`'s does.

A file at PATH is `E_PATH_NOT_FOUND` (exit 6), with the message "is a file at REV, not a
directory" and the hint `swarmops cat REV:PATH`; nothing at PATH is `E_PATH_NOT_FOUND` with the
hint of the `ls` one level up.

### What each entry says

| Field | File, executable or symlink | Directory |
| --- | --- | --- |
| `name` | Its last path component. | Its last path component. |
| `path` | With `--depth` 2 or more: its path below the listed directory. | The same. |
| `kind` | `file`, `exec` or `symlink`. | `dir`. |
| `size` | The content's size in bytes; for a symlink, the length of its target. | Omitted. |
| `id` | The blob id, which `cat` and `diff` show too. | The tree id. |

A size comes from the object's header, so a listing reads no file content.

### Order, depth and pages

Entries come in pre-order: a directory, then the entries below it, down to `--depth` levels
(1, the default, lists the directory's own entries; 2 adds theirs; at most 64). Each directory's
entries are sorted by the bytes of their names, so `README.md` and `Zeta.txt` come before `bin`.

`--limit` (250 by default, at least 1) cuts the page. A cut page says `truncated: true` and gives
`cursor`, the `path` of its last entry; `--cursor` with that value starts the next page after it.
The cursor is a path relative to the listed directory, so the next call must name the same
target and the same `--depth`. A cursor that names no entry still works: the page starts after
where it would sort, so a cursor past every name gives an empty page. A cursor that is not a
repository path is `E_INVALID_ARG`.

`--depth 0`, `--depth 65` and `--limit 0` are `E_INVALID_ARG`.

### Patterns

- **Map a subtree.** `ls REV:src --depth 64` lists everything below `src`, a page at a
  time; each entry's `path` is ready to pass to `cat REV:src/<path>`.
- **Find what changed by id.** Two listings of the same directory at two revisions share every
  entry whose `id` did not change; a directory with an unchanged tree id holds nothing new below
  it. `diff` does this comparison for you, file by file.
- **Pin the revision for paging.** Resolve `main` to a full id first and list that: the cursor
  does not pin a revision, so pages listed at `main` can come from two revisions if another
  agent lands in between.
- **Through MCP**, the tool is `read_tree`, with `rev`, `path` (omitted for the root), `depth`,
  `limit` and `cursor`. Ask for 100 entries or fewer a call: see
  [Result size limits](../../develop/mcp.md#result-size-limits).

### Caveats

- Paging limits what is returned, not what is read: a page decodes the whole tree object of the
  listed directory, and with `--depth` of every directory it enters. A very wide directory costs
  its whole tree on every page. See
  [known limitations](../../known-limitations.md#reads-and-response-sizes).
- A directory exists only while something is below it: there are no empty directories to list.
  A file that becomes a directory, or the other way, shows as a new `kind` at the same name.

### Guides

- [Reading and repairing history: List a directory](../../guides/history-and-undo.md#list-a-directory)
- [MCP integration: Result size limits](../../develop/mcp.md#result-size-limits)

## Return information

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

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `cursor` | `string or null` | no | When `truncated`: where the next page starts. Opaque: pass it back as given, as the next request's `cursor`. |
| `entries` | `array of TreeEntryOut` | yes | The entries. |
| `truncated` | `boolean` | yes | Whether more entries follow this page. |

Envelope `op`: `read_tree`.

Exit codes:

- `0`: Success.

## Errors

No golden step shows this command failing yet.

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 show`](show.md)
- [`swarmops log`](log.md)
- [`swarmops history`](history.md)
- [`swarmops diff`](diff.md)
- [CLI reference](../cli.md)
- [Error codes](../errors.md)
