# libtmux.core/snapshot!

- **Module:** libtmux.core
- **Package:** io.github.libtmux:libtmux-clojure
- **Language:** Clojure
- **Kind:** function
- **Source:** https://github.com/libtmux/libtmux-java/blob/5f88402151ff08fc0390dd438b90963692ec3fe4/libtmux-clojure/src/main/clojure/libtmux/core.clj#L147
- **Public owner:** libtmux.core
- **Page:** https://libtmux.org/en/clojure/latest/reference/libtmux-core-snapshot/

```
(snapshot! server)
```

Acquires an eager captured graph from an explicit server.

Traverse one observation with [[libtmux.data/windows]] and [[libtmux.data/panes]].

## Examples

Connect to a private tmux server. Use JDK 25 or newer, the Clojure CLI, Git and tmux on Linux or macOS, with /bin/cat and /bin/sh available. These packages are unpublished. In an empty directory, install this exact source into the consumer's isolated Maven repository:

```console
$ git clone https://github.com/libtmux/libtmux-java libtmux-source && \
  git -C libtmux-source checkout --detach 5f88402151ff08fc0390dd438b90963692ec3fe4 && \
  (cd libtmux-source && ./gradlew \
    :libtmux:publishToMavenLocal \
    :libtmux-clojure:publishToMavenLocal \
    --console=plain \
    "-Dmaven.repo.local=$PWD/../m2")
```

Save this file as `deps.edn`. Dependencies resolve from the isolated m2 directory; the core.async dependency is only enabled by its alias.

[Source example](https://github.com/libtmux/libtmux-java/blob/5f88402151ff08fc0390dd438b90963692ec3fe4/examples/api/clojure/deps.edn).

```clojure
{:paths ["src/main/clojure"]
 :mvn/local-repo "m2"
 :deps {org.clojure/clojure {:mvn/version "1.12.6"}
        io.github.libtmux/libtmux-clojure {:mvn/version "0.1.2-SNAPSHOT"}}
 :aliases
 {:core-async
  {:extra-deps
   {io.github.libtmux/libtmux-clojure-core-async {:mvn/version "0.1.2-SNAPSHOT"}}}}}
```

Save this file as `run.sh`. The launcher creates and stops a private server, including after program failure, and reports leaked servers as errors.

[Source example](https://github.com/libtmux/libtmux-java/blob/5f88402151ff08fc0390dd438b90963692ec3fe4/examples/api/run.sh).

```sh
#!/bin/sh
set -eu

if [ "$#" -eq 0 ]; then
    printf 'Usage: sh run.sh program [arguments...]\n' >&2
    exit 2
fi
binary=$(command -v "${TMUX_BIN:-tmux}")
root=${API_RUN_ROOT:-/tmp/libtmux-java-dev}

# A client that names no socket follows TMUX or LIBTMUX_SOCKET*, and otherwise lands on the default
# socket under TMUX_TMPDIR. The program gets none of them, and a TMUX_TMPDIR of its own below.
unset TMUX TMUX_PANE
for name in $(env | sed -n 's/^\(LIBTMUX_SOCKET[A-Za-z0-9_]*\)=.*/\1/p'); do
    unset "$name"
done

mkdir -p "$root"
directory=$(mktemp -d "$root/api.XXXXXX")
tmpdir=$(mktemp -d "$root/tmpdir.XXXXXX")
socket="$directory/tmux.sock"
config="$directory/tmux.conf"

serves() {
    "$binary" -S "$1" display-message -p '#{pid}' >/dev/null 2>&1
}

# Stops the server on the socket, then waits for it to stop answering.
stop() {
    "$binary" -S "$1" kill-server || return 1
    attempts=0
    while serves "$1" && [ "$attempts" -lt 60 ]; do
        sleep 0.05
        attempts=$((attempts + 1))
    done
    ! serves "$1"
}

cleanup() {
    status=$?
    trap - 0 HUP INT TERM PIPE
    # A closed output must not end the cleanup, whose messages are the only thing left to write.
    trap '' PIPE
    set +e
    stuck=
    left=
    if [ -S "$socket" ] && serves "$socket" && ! stop "$socket"; then
        stuck="$stuck tmux.sock"
    fi
    # Every socket anywhere under either directory, without following links. Only one a server answers
    # on is a leak; the runner's own is expected to be there.
    old_ifs=$IFS
    IFS='
'
    set -f
    for candidate in $(find "$tmpdir" "$directory" -type s 2>/dev/null); do
        [ "$candidate" = "$socket" ] && continue
        serves "$candidate" || continue
        case "$candidate" in
            "$tmpdir"/*) name=${candidate#"$tmpdir"/} ;;
            *) name=${candidate#"$directory"/} ;;
        esac
        left="$left $name"
        stop "$candidate" || stuck="$stuck $name"
    done
    set +f
    IFS=$old_ifs
    if [ -n "$stuck" ]; then
        printf 'tmux still answers on%s after kill-server; kept %s and %s under the runner root\n' \
            "$stuck" "${directory##*/}" "${tmpdir##*/}" >&2
        exit 1
    fi
    rm -rf "$directory" "$tmpdir" || exit 1
    if [ -n "$left" ]; then
        printf 'The program left a tmux server running:%s\n' "$left" >&2
        exit 1
    fi
    exit "$status"
}
trap cleanup 0
trap 'exit 1' HUP INT TERM PIPE

# A default socket path longer than this does not fit in sun_path.
default_socket="$tmpdir/tmux-$(id -u)/default"
if [ "$(printf '%s' "$default_socket" | wc -c)" -gt 100 ]; then
    printf 'API_RUN_ROOT is too long for a tmux socket\n' >&2
    exit 1
fi
TMUX_TMPDIR=$tmpdir
export TMUX_TMPDIR

printf 'set-option -g default-shell /bin/sh\n' > "$config"
"$binary" -S "$socket" -f "$config" new-session -d -s work-one -n editor /bin/cat
"$binary" -S "$socket" split-window -h -t '=work-one:editor' /bin/cat
"$binary" -S "$socket" new-window -d -t '=work-one' -n logs /bin/cat
"$binary" -S "$socket" new-session -d -s work-two -n editor /bin/cat
"$@" "$binary" "$socket" "$config"
"$binary" -S "$socket" has-session -t '=work-one'
"$binary" -S "$socket" has-session -t '=work-two'
```

Save the complete program as `src/main/clojure/libtmux/examples/api/connect.clj`, creating its parent directories. Closing its client leaves the launcher's server running.

[Source example](https://github.com/libtmux/libtmux-java/blob/5f88402151ff08fc0390dd438b90963692ec3fe4/examples/src/main/clojure/libtmux/examples/api/connect.clj).

```clojure
(ns libtmux.examples.api.connect
  "Connect to the private server supplied by run.sh."
  (:require [libtmux.core :as tm]))

(defn -main [& args]
  (when-not (= 3 (count args))
    (throw (IllegalArgumentException. "expected: tmux-binary socket-path config-file")))
  (let [[binary socket config] args]
    (with-open [server (tm/open! {:binary binary :socket-path socket
                                 :config-file config})]
      (let [snapshot (tm/snapshot! server)]
        (assert (seq (:tmux/sessions snapshot)))
        (println "connected=true")))))
```

Run it with the private fixture. Set TMUX_BIN to select another tmux binary:

```console
$ sh run.sh clojure \
  -J-Dclojure.main.report=stderr \
  -M \
  -m libtmux.examples.api.connect
```

Expected output:

```text
connected=true
```

Traverse root and session windows in one captured graph. Use JDK 25 or newer, the Clojure CLI, Git and tmux on Linux or macOS, with /bin/cat and /bin/sh available. These packages are unpublished. In an empty directory, install this exact source into the consumer's isolated Maven repository:

```console
$ git clone https://github.com/libtmux/libtmux-java libtmux-source && \
  git -C libtmux-source checkout --detach 5f88402151ff08fc0390dd438b90963692ec3fe4 && \
  (cd libtmux-source && ./gradlew \
    :libtmux:publishToMavenLocal \
    :libtmux-clojure:publishToMavenLocal \
    --console=plain \
    "-Dmaven.repo.local=$PWD/../m2")
```

Save this file as `deps.edn`. Dependencies resolve from the isolated m2 directory; the core.async dependency is only enabled by its alias.

[Source example](https://github.com/libtmux/libtmux-java/blob/5f88402151ff08fc0390dd438b90963692ec3fe4/examples/api/clojure/deps.edn).

```clojure
{:paths ["src/main/clojure"]
 :mvn/local-repo "m2"
 :deps {org.clojure/clojure {:mvn/version "1.12.6"}
        io.github.libtmux/libtmux-clojure {:mvn/version "0.1.2-SNAPSHOT"}}
 :aliases
 {:core-async
  {:extra-deps
   {io.github.libtmux/libtmux-clojure-core-async {:mvn/version "0.1.2-SNAPSHOT"}}}}}
```

Save this file as `run.sh`. The launcher creates and stops a private server, including after program failure, and reports leaked servers as errors.

[Source example](https://github.com/libtmux/libtmux-java/blob/5f88402151ff08fc0390dd438b90963692ec3fe4/examples/api/run.sh).

```sh
#!/bin/sh
set -eu

if [ "$#" -eq 0 ]; then
    printf 'Usage: sh run.sh program [arguments...]\n' >&2
    exit 2
fi
binary=$(command -v "${TMUX_BIN:-tmux}")
root=${API_RUN_ROOT:-/tmp/libtmux-java-dev}

# A client that names no socket follows TMUX or LIBTMUX_SOCKET*, and otherwise lands on the default
# socket under TMUX_TMPDIR. The program gets none of them, and a TMUX_TMPDIR of its own below.
unset TMUX TMUX_PANE
for name in $(env | sed -n 's/^\(LIBTMUX_SOCKET[A-Za-z0-9_]*\)=.*/\1/p'); do
    unset "$name"
done

mkdir -p "$root"
directory=$(mktemp -d "$root/api.XXXXXX")
tmpdir=$(mktemp -d "$root/tmpdir.XXXXXX")
socket="$directory/tmux.sock"
config="$directory/tmux.conf"

serves() {
    "$binary" -S "$1" display-message -p '#{pid}' >/dev/null 2>&1
}

# Stops the server on the socket, then waits for it to stop answering.
stop() {
    "$binary" -S "$1" kill-server || return 1
    attempts=0
    while serves "$1" && [ "$attempts" -lt 60 ]; do
        sleep 0.05
        attempts=$((attempts + 1))
    done
    ! serves "$1"
}

cleanup() {
    status=$?
    trap - 0 HUP INT TERM PIPE
    # A closed output must not end the cleanup, whose messages are the only thing left to write.
    trap '' PIPE
    set +e
    stuck=
    left=
    if [ -S "$socket" ] && serves "$socket" && ! stop "$socket"; then
        stuck="$stuck tmux.sock"
    fi
    # Every socket anywhere under either directory, without following links. Only one a server answers
    # on is a leak; the runner's own is expected to be there.
    old_ifs=$IFS
    IFS='
'
    set -f
    for candidate in $(find "$tmpdir" "$directory" -type s 2>/dev/null); do
        [ "$candidate" = "$socket" ] && continue
        serves "$candidate" || continue
        case "$candidate" in
            "$tmpdir"/*) name=${candidate#"$tmpdir"/} ;;
            *) name=${candidate#"$directory"/} ;;
        esac
        left="$left $name"
        stop "$candidate" || stuck="$stuck $name"
    done
    set +f
    IFS=$old_ifs
    if [ -n "$stuck" ]; then
        printf 'tmux still answers on%s after kill-server; kept %s and %s under the runner root\n' \
            "$stuck" "${directory##*/}" "${tmpdir##*/}" >&2
        exit 1
    fi
    rm -rf "$directory" "$tmpdir" || exit 1
    if [ -n "$left" ]; then
        printf 'The program left a tmux server running:%s\n' "$left" >&2
        exit 1
    fi
    exit "$status"
}
trap cleanup 0
trap 'exit 1' HUP INT TERM PIPE

# A default socket path longer than this does not fit in sun_path.
default_socket="$tmpdir/tmux-$(id -u)/default"
if [ "$(printf '%s' "$default_socket" | wc -c)" -gt 100 ]; then
    printf 'API_RUN_ROOT is too long for a tmux socket\n' >&2
    exit 1
fi
TMUX_TMPDIR=$tmpdir
export TMUX_TMPDIR

printf 'set-option -g default-shell /bin/sh\n' > "$config"
"$binary" -S "$socket" -f "$config" new-session -d -s work-one -n editor /bin/cat
"$binary" -S "$socket" split-window -h -t '=work-one:editor' /bin/cat
"$binary" -S "$socket" new-window -d -t '=work-one' -n logs /bin/cat
"$binary" -S "$socket" new-session -d -s work-two -n editor /bin/cat
"$@" "$binary" "$socket" "$config"
"$binary" -S "$socket" has-session -t '=work-one'
"$binary" -S "$socket" has-session -t '=work-two'
```

Save the complete program as `src/main/clojure/libtmux/examples/api/list_windows.clj`, creating its parent directories. Closing its client leaves the launcher's server running.

[Source example](https://github.com/libtmux/libtmux-java/blob/5f88402151ff08fc0390dd438b90963692ec3fe4/examples/src/main/clojure/libtmux/examples/api/list_windows.clj).

```clojure
(ns libtmux.examples.api.list-windows
  "Traverse root and session windows from the same captured graph."
  (:require [clojure.string :as str]
            [libtmux.core :as tm]
            [libtmux.data :as data]))

(defn -main [& args]
  (when-not (= 3 (count args))
    (throw (IllegalArgumentException. "expected: tmux-binary socket-path config-file")))
  (let [[binary socket config] args]
    (with-open [server (tm/open! {:binary binary :socket-path socket
                                 :config-file config})]
      (let [snapshot (tm/snapshot! server)
            session (data/exactly-one
                     (filter #(= "work-one" (:session/name %))
                             (:tmux/sessions snapshot)))]
        (println (str "windows="
                      (str/join "," (sort (map :window/name (data/windows snapshot))))))
        (println (str "session-windows="
                      (str/join "," (sort (map :window/name (data/windows session))))))))))
```

Run it with the private fixture. Set TMUX_BIN to select another tmux binary:

```console
$ sh run.sh clojure \
  -J-Dclojure.main.report=stderr \
  -M \
  -m libtmux.examples.api.list-windows
```

Expected output:

```text
windows=editor,editor,logs
session-windows=editor,logs
```

Traverse root, session, window and pane observations. Use JDK 25 or newer, the Clojure CLI, Git and tmux on Linux or macOS, with /bin/cat and /bin/sh available. These packages are unpublished. In an empty directory, install this exact source into the consumer's isolated Maven repository:

```console
$ git clone https://github.com/libtmux/libtmux-java libtmux-source && \
  git -C libtmux-source checkout --detach 5f88402151ff08fc0390dd438b90963692ec3fe4 && \
  (cd libtmux-source && ./gradlew \
    :libtmux:publishToMavenLocal \
    :libtmux-clojure:publishToMavenLocal \
    --console=plain \
    "-Dmaven.repo.local=$PWD/../m2")
```

Save this file as `deps.edn`. Dependencies resolve from the isolated m2 directory; the core.async dependency is only enabled by its alias.

[Source example](https://github.com/libtmux/libtmux-java/blob/5f88402151ff08fc0390dd438b90963692ec3fe4/examples/api/clojure/deps.edn).

```clojure
{:paths ["src/main/clojure"]
 :mvn/local-repo "m2"
 :deps {org.clojure/clojure {:mvn/version "1.12.6"}
        io.github.libtmux/libtmux-clojure {:mvn/version "0.1.2-SNAPSHOT"}}
 :aliases
 {:core-async
  {:extra-deps
   {io.github.libtmux/libtmux-clojure-core-async {:mvn/version "0.1.2-SNAPSHOT"}}}}}
```

Save this file as `run.sh`. The launcher creates and stops a private server, including after program failure, and reports leaked servers as errors.

[Source example](https://github.com/libtmux/libtmux-java/blob/5f88402151ff08fc0390dd438b90963692ec3fe4/examples/api/run.sh).

```sh
#!/bin/sh
set -eu

if [ "$#" -eq 0 ]; then
    printf 'Usage: sh run.sh program [arguments...]\n' >&2
    exit 2
fi
binary=$(command -v "${TMUX_BIN:-tmux}")
root=${API_RUN_ROOT:-/tmp/libtmux-java-dev}

# A client that names no socket follows TMUX or LIBTMUX_SOCKET*, and otherwise lands on the default
# socket under TMUX_TMPDIR. The program gets none of them, and a TMUX_TMPDIR of its own below.
unset TMUX TMUX_PANE
for name in $(env | sed -n 's/^\(LIBTMUX_SOCKET[A-Za-z0-9_]*\)=.*/\1/p'); do
    unset "$name"
done

mkdir -p "$root"
directory=$(mktemp -d "$root/api.XXXXXX")
tmpdir=$(mktemp -d "$root/tmpdir.XXXXXX")
socket="$directory/tmux.sock"
config="$directory/tmux.conf"

serves() {
    "$binary" -S "$1" display-message -p '#{pid}' >/dev/null 2>&1
}

# Stops the server on the socket, then waits for it to stop answering.
stop() {
    "$binary" -S "$1" kill-server || return 1
    attempts=0
    while serves "$1" && [ "$attempts" -lt 60 ]; do
        sleep 0.05
        attempts=$((attempts + 1))
    done
    ! serves "$1"
}

cleanup() {
    status=$?
    trap - 0 HUP INT TERM PIPE
    # A closed output must not end the cleanup, whose messages are the only thing left to write.
    trap '' PIPE
    set +e
    stuck=
    left=
    if [ -S "$socket" ] && serves "$socket" && ! stop "$socket"; then
        stuck="$stuck tmux.sock"
    fi
    # Every socket anywhere under either directory, without following links. Only one a server answers
    # on is a leak; the runner's own is expected to be there.
    old_ifs=$IFS
    IFS='
'
    set -f
    for candidate in $(find "$tmpdir" "$directory" -type s 2>/dev/null); do
        [ "$candidate" = "$socket" ] && continue
        serves "$candidate" || continue
        case "$candidate" in
            "$tmpdir"/*) name=${candidate#"$tmpdir"/} ;;
            *) name=${candidate#"$directory"/} ;;
        esac
        left="$left $name"
        stop "$candidate" || stuck="$stuck $name"
    done
    set +f
    IFS=$old_ifs
    if [ -n "$stuck" ]; then
        printf 'tmux still answers on%s after kill-server; kept %s and %s under the runner root\n' \
            "$stuck" "${directory##*/}" "${tmpdir##*/}" >&2
        exit 1
    fi
    rm -rf "$directory" "$tmpdir" || exit 1
    if [ -n "$left" ]; then
        printf 'The program left a tmux server running:%s\n' "$left" >&2
        exit 1
    fi
    exit "$status"
}
trap cleanup 0
trap 'exit 1' HUP INT TERM PIPE

# A default socket path longer than this does not fit in sun_path.
default_socket="$tmpdir/tmux-$(id -u)/default"
if [ "$(printf '%s' "$default_socket" | wc -c)" -gt 100 ]; then
    printf 'API_RUN_ROOT is too long for a tmux socket\n' >&2
    exit 1
fi
TMUX_TMPDIR=$tmpdir
export TMUX_TMPDIR

printf 'set-option -g default-shell /bin/sh\n' > "$config"
"$binary" -S "$socket" -f "$config" new-session -d -s work-one -n editor /bin/cat
"$binary" -S "$socket" split-window -h -t '=work-one:editor' /bin/cat
"$binary" -S "$socket" new-window -d -t '=work-one' -n logs /bin/cat
"$binary" -S "$socket" new-session -d -s work-two -n editor /bin/cat
"$@" "$binary" "$socket" "$config"
"$binary" -S "$socket" has-session -t '=work-one'
"$binary" -S "$socket" has-session -t '=work-two'
```

Save the complete program as `src/main/clojure/libtmux/examples/api/list_panes.clj`, creating its parent directories. Closing its client leaves the launcher's server running.

[Source example](https://github.com/libtmux/libtmux-java/blob/5f88402151ff08fc0390dd438b90963692ec3fe4/examples/src/main/clojure/libtmux/examples/api/list_panes.clj).

```clojure
(ns libtmux.examples.api.list-panes
  "Traverse session, window and pane observations without another acquisition."
  (:require [libtmux.core :as tm]
            [libtmux.data :as data]))

(defn -main [& args]
  (when-not (= 3 (count args))
    (throw (IllegalArgumentException. "expected: tmux-binary socket-path config-file")))
  (let [[binary socket config] args]
    (with-open [server (tm/open! {:binary binary :socket-path socket
                                 :config-file config})]
      (let [snapshot (tm/snapshot! server)
            session (data/exactly-one
                     (filter #(= "work-one" (:session/name %))
                             (:tmux/sessions snapshot)))
            window (data/exactly-one
                    (filter #(= "editor" (:window/name %)) (data/windows session)))]
        (println (str "panes=" (count (data/panes snapshot))))
        (println (str "window-panes=" (count (data/panes window))))))))
```

Run it with the private fixture. Set TMUX_BIN to select another tmux binary:

```console
$ sh run.sh clojure \
  -J-Dclojure.main.report=stderr \
  -M \
  -m libtmux.examples.api.list-panes
```

Expected output:

```text
panes=4
window-panes=2
```

## Parameters

- `server`

## tmux command

The tmux commands behind `snapshot!`.

- [`list-clients`](/en/tmux/latest/manual/list-clients/)
- [`list-panes`](/en/tmux/latest/manual/list-panes/) `-a` server scope, [`cmd_list_panes_server`](/en/tmux/latest/reference/c-function-cmd-list-panes-c-cmd_list_panes_server/) (source: `libtmux/src/main/java/io/github/libtmux/SnapshotCapture.java:163`)
- [`list-sessions`](/en/tmux/latest/manual/list-sessions/)
- [`list-windows`](/en/tmux/latest/manual/list-windows/) `-a` server scope, [`cmd_list_windows_exec`](/en/tmux/latest/reference/c-function-cmd-list-windows-c-cmd_list_windows_exec/) (source: `libtmux/src/main/java/io/github/libtmux/SnapshotCapture.java:162`)

## tmux C API

The C declarations in tmux that implement these commands.

- [`cmd_list_clients_entry`](/en/tmux/latest/reference/c-variable-cmd_list_clients_entry/) (attribute)
- [`cmd_list_clients_exec`](/en/tmux/latest/reference/c-function-cmd-list-clients-c-cmd_list_clients_exec/) (function)
- [`cmd_list_panes_entry`](/en/tmux/latest/reference/c-variable-cmd_list_panes_entry/) (attribute)
- [`cmd_list_panes_server`](/en/tmux/latest/reference/c-function-cmd-list-panes-c-cmd_list_panes_server/) (function)
- [`cmd_list_sessions_entry`](/en/tmux/latest/reference/c-variable-cmd_list_sessions_entry/) (attribute)
- [`cmd_list_sessions_exec`](/en/tmux/latest/reference/c-function-cmd-list-sessions-c-cmd_list_sessions_exec/) (function)
- [`cmd_list_windows_entry`](/en/tmux/latest/reference/c-variable-cmd_list_windows_entry/) (attribute)
- [`cmd_list_windows_exec`](/en/tmux/latest/reference/c-function-cmd-list-windows-c-cmd_list_windows_exec/) (function)

## Guides

Pages that discuss `snapshot!`.

### Concepts

- [Server, session, window, pane](/en/clojure/latest/concepts/server-session-window-pane/)

### Guides

- [Captured values](/en/clojure/latest/guides/captured-values/)
- [Getting started](/en/clojure/latest/guides/getting-started/)

## In other ports

Capture the tmux hierarchy

| Language | Equivalent |
| --- | --- |
| Python | no equivalent on `Server` |
| Ruby | [`LibTmux::Server#snapshot`](/en/ruby/latest/reference/libtmux-server-snapshot/) (method) |
| Lua | [`libtmux.Server:snapshot`](/en/lua/latest/reference/libtmux-server-snapshot/) (method) |
| PowerShell | [`LibTmux\Get-TmuxSnapshot`](/en/powershell/latest/reference/libtmux-get-tmuxsnapshot/) (cmdlet). Acquires a replacement `LibTmux.Server` to [`-Depth`](/en/powershell/latest/reference/libtmux-get-tmuxsnapshot/#LibTmux%5CGet-TmuxSnapshot.parameter.Depth) (panes by default). Acquisition is not atomic; retained handles do not refresh. |
| Julia | [`LibTmux.snapshot`](/en/julia/latest/reference/libtmux-snapshot-1gv6/) (function). Acquires a new `Snapshot` over an observation interval. Topology checks do not make it a transaction; earlier snapshots do not refresh. |
| Erlang | [`tmux_server:snapshot/1`](/en/erlang/latest/reference/tmux_server-snapshot-1/) (function). Captures a new graph over an observation interval. Retained snapshots never refresh. |
| Elixir | [`LibTmux.Server.snapshot/2`](/en/elixir/latest/reference/libtmux-server-snapshot-2/) (function). Captures a new graph over an observation interval. A retained `Snapshot` never refreshes. |
| Haskell | No public Haskell equivalent is implemented; the current modules expose scalar values and version parsing. |
| Common Lisp | [`libtmux:fetch-snapshot`](/en/lisp/latest/reference/libtmux-fetch-snapshot/) (function). `fetch-snapshot` acquires a new interval observation. Retained snapshots never refresh in place. |
| TypeScript | [`server.Server.snapshot`](/en/ts/latest/reference/server-server-snapshot/) (method) |
| Rust | [`server.Server.hierarchy`](/en/rs/latest/reference/server-server-hierarchy/) (method). Fetches the whole hierarchy with `list-sessions`, `list-windows -a` and `list-panes -a`, and stitches the rows by winlink. The three listings are separate commands, so the capture is not an atomic transaction. |
| Go | [`tmux.Server.Snapshot`](/en/go/latest/reference/tmux-server-snapshot/) (method) |
| Java | [`io.github.libtmux.Server.snapshot`](/en/java/latest/reference/io-github-libtmux-server-server-snapshot/) (method) |
| Kotlin | [`io.github.libtmux.kotlin.Server.snapshot`](/en/kotlin/latest/reference/io-github-libtmux-kotlin-server-snapshot/) (method) |
| Scala | [`io.github.libtmux.scaladsl.Server.snapshot`](/en/scala/latest/reference/io-github-libtmux-scaladsl-server-snapshot/) (method) |
| C# | [`LibTmux.Server.CaptureSnapshotAsync`](/en/csharp/latest/reference/libtmux-server-capturesnapshotasync/) (method) |
| F# | [`LibTmux.FSharp.Server.capture`](/en/fsharp/latest/reference/libtmux-fsharp-server-capture/) (function). Acquires a replacement shared .NET `LibTmux.Server` to the requested depth. Acquisition is not atomic; retained handles do not refresh. |
| C++ | no equivalent on `Server`: `sessions`, `windows`, `panes` and `clients` each take a snapshot of one listing, and `Snapshot::take` needs the internal `detail::Backend`, so no public call reads the whole hierarchy at once |
| Swift | [`Server.snapshot()`](/en/swift/latest/reference/server-snapshot()/) (method) |
| OCaml | [`Libtmux_unix.Client.capture`](/en/ocaml/latest/reference/libtmux_unix-client-capture/) (function). Acquires a complete immutable graph over an interval. Earlier observations remain readable without refreshing. |
| Perl | [`LibTmux::Server::snapshot`](/en/perl/latest/reference/libtmux-server-snapshot/) (method). Strict acquisition observes an interval, not an atomic transaction; retained handles do not refresh. |
