# Capture and navigate

Source: https://libtmux.org/en/haskell/latest/guides/capture/

> Use withServer to adopt an existing endpoint and capture to obtain a detached Snapshot.

Use [`withServer`](https://libtmux.org/en/haskell/latest/reference/libtmux-server-v-withserver/) to adopt an existing endpoint and
[`capture`](https://libtmux.org/en/haskell/latest/reference/libtmux-server-v-capture/) to obtain a detached
[`Snapshot`](https://libtmux.org/en/haskell/latest/reference/libtmux-snapshot-t-snapshot/). The complete program in the
[README](https://github.com/libtmux/libtmux-haskell/blob/663e212622a02aa74a9bdc8ff71e2b45fcb1d4d5/README.md) filters ordinary pane records, traverses relationships
and prints its result after the handle closes. Its
[source](https://github.com/libtmux/libtmux-haskell/blob/663e212622a02aa74a9bdc8ff71e2b45fcb1d4d5/examples/capture-graph/Main.hs) and
[owned fixture verification](https://github.com/libtmux/libtmux-haskell/blob/663e212622a02aa74a9bdc8ff71e2b45fcb1d4d5/scripts/check_sdist.py) are checked from the
source archive, with output asserted and owned process exits observed.

Create the [private demonstration server](https://github.com/libtmux/libtmux-haskell/blob/663e212622a02aa74a9bdc8ff71e2b45fcb1d4d5/README.md) from the README, then
run the Haskell executable from a provisioned checkout:

```console
$ cabal run --verbose=0 capture-graph -- \
    "$LIBTMUX_DEMO_DIR/s" \
    "$(command -v tmux)"
```

To inspect your own running server, pass its actual socket and executable
paths instead. The program observes that daemon; it does not create or stop it.

The library requires a trusted absolute socket path and a writable pin
directory on that socket's filesystem. The default pin directory is the
socket's parent. [Installation](https://libtmux.org/en/haskell/latest/guides/installation/#native-backend-host-requirements)
describes the Linux host requirements.

## Physical entities and appearances

A session links windows at numeric indices. The same physical window can
appear at two indices in one session or in several sessions. A pane belongs
to its physical window, while a pane occurrence retains the window-link
context:

```mermaid
flowchart LR
    S["Session demo"] --> L0["WindowLink index 0"]
    S --> L4["WindowLink index 4"]
    L0 --> W["Window @0"]
    L4 --> W
    W --> P["Pane %0"]
```

`windows` and `panes` return each physical entity once. `windowLinks` and
`paneOccurrences` retain both appearances in this fixture. Lists use numeric
ID order; links use session ID and window index; occurrences use link and
pane index. Indexed lookups avoid rescanning those lists.

References compare targeting identity within one Server generation. A lookup
returns the observation from the supplied snapshot, including a later capture
from that same Server. Independent Server scopes have distinct generations.
Resolving a native ID with [`lookupPaneId`](<https://libtmux.org/en/haskell/latest/reference/libtmux-snapshot-v-lookuppaneid/>) deliberately selects its observation
in the supplied snapshot; it does not restore an earlier targeting guarantee.

Record updates create local values. They do not update the snapshot's indexes,
validate a caller-edited graph or send a tmux command. Use
`dimensionValue pane.width` for numeric comparisons; checked dimensions have
no [`Num`](https://hackage-content.haskell.org/package/base-4.22.0.0/docs/Prelude.html#t:Num)
instance. Paths and current process names preserve POSIX bytes;
window labels use [`TmuxText`](<https://libtmux.org/en/haskell/latest/reference/libtmux-snapshot-t-tmuxtext/>) with explicit, fallible text conversion.

## Errors and recovery

Acquisition fails in [`IO`](<https://hackage-content.haskell.org/package/base-4.22.0.0/docs/System-IO.html#t:IO>) with [`TmuxException`](<https://libtmux.org/en/haskell/latest/reference/libtmux-server-t-tmuxexception/>). Pure navigation returns
`Either LookupError`; missing or foreign references never become empty results.
The snapshot records a monotonic capture interval. It does not claim a
transaction over tmux and operating-system state.

[`withServer`](<https://libtmux.org/en/haskell/latest/reference/libtmux-server-v-withserver/>) preserves a callback's original exception, including cancellation.
If bounded cleanup remains incomplete, its exception context retains a
[`CleanupRecovery`](<https://libtmux.org/en/haskell/latest/reference/libtmux-server-t-cleanuprecovery/>). After a successful callback, incomplete cleanup raises
[`CleanupFailed`](<https://libtmux.org/en/haskell/latest/reference/libtmux-server-v-cleanupfailed/>) instead of returning success.

Use [`tryTmux`](<https://libtmux.org/en/haskell/latest/reference/libtmux-server-v-trytmux/>) to catch library failures with their
[`ExceptionWithContext`](https://hackage-content.haskell.org/package/base-4.22.0.0/docs/Control-Exception.html#t:ExceptionWithContext),
or [`Control.Exception.tryWithContext`](https://hackage-content.haskell.org/package/base-4.22.0.0/docs/Control-Exception.html#v:tryWithContext)
when handling application exceptions and
cancellation too. Ordinary typed `try` loses this context when returning the
concrete exception. Keep the context while recovering ownership.

[`cleanupRecoveries`](<https://libtmux.org/en/haskell/latest/reference/libtmux-server-v-cleanuprecoveries/>) and [`captureRecoveries`](<https://libtmux.org/en/haskell/latest/reference/libtmux-server-v-capturerecoveries/>) retrieve correlated owners from
that context. Inspect them locally, resume existing cleanup, or explicitly
detach logical uncertainty. Resuming never dispatches a second capture;
detachment does not terminate native resources or prove daemon-side completion.
The [process contract](https://github.com/libtmux/libtmux-haskell/blob/663e212622a02aa74a9bdc8ff71e2b45fcb1d4d5/docs/contracts/process.md) defines these outcomes in detail.

Use [validated offline fixtures](https://libtmux.org/en/haskell/latest/guides/offline-fixtures/) to exercise application graph
logic without tmux. Their references belong to a separate offline origin.

The [capture baseline](https://libtmux.org/en/haskell/latest/guides/performance/) covers controlled graph sizes. The
[shared Runtime guide](https://libtmux.org/en/haskell/latest/guides/shared-runtime/) covers independent handle lifetimes.
Broader performance cases remain qualification work for the public observation
milestone. The
[status page](https://libtmux.org/en/haskell/latest/guides/status/) records the broader implementation scope.

The example fixture verifies daemon exit after setup failure before session
dispatch, and both daemon and pane exit after callback failure or cancellation.
The runner joins interrupted session clients. When creation was dispatched but
the pane receipt is unavailable, it reports that incomplete ownership explicitly.
