# Getting started

Source: https://libtmux.org/en/erlang/latest/guides/getting-started/

> Getting started: libtmux_erlang documentation.

Create tmux sessions, windows and panes from Erlang. Capture their object graph,
filter it as immutable data, and execute source queries and owned operations
explicitly.

## Install

Use Erlang/OTP **29.1.2**, Rebar3 **3.28.0**, Linux, tmux **3.3a–3.8**, and
`make` with a C11 compiler. Native records are experimental in OTP 29. The core
uses OTP libraries and a compiled external helper, with no NIF or third-party
runtime packages.

This checkout is unreleased. Add its core application to your `rebar.config`:

<!-- erlang-term -->

```erlang
{deps, [
    {libtmux_erlang, {git_subdir,
        "https://github.com/libtmux/libtmux-erlang.git",
        {branch, "master"}, "apps/libtmux_erlang"}}
]}.
```

Commit `rebar.lock` to keep the resolved commit. The
[installation guide](https://libtmux.org/en/erlang/latest/guides/installation/) covers application startup and
building a consumer. No Hex release is advertised.

## Create, capture and query

From this checkout, compile with the pinned tools:

```console
$ mise exec -- rebar3 compile
```

Run the complete program below on a private tmux server:

```console
$ mise exec -- escript tools/run_examples.escript readme
```

The program starts an empty daemon on a unique private socket, verifies its
assertions, and retires the owned server and clients. It leaves your existing
tmux sessions alone. It uses only public core APIs and OTP runtime libraries;
the archive check also runs it outside this checkout.
Save it as `readme_demo.erl` when reusing it in an application.

<!-- example: examples/readme_demo.erl -->

```erlang
-module(readme_demo).
-moduledoc "Create a workspace, query its graph and preserve captured values.".
-export([run/1]).
-import_record(tmux_model, [pane]).

-spec run(binary()) -> map().
run(Executable) ->
    Options = #{executable => Executable},
    {ok, Result} = tmux_server:with_owned(Options, fun(Server) ->
        {ok, Session} = tmux_session:create(Server, #{name => <<"workspace">>,
            window_name => <<"editor">>, width => 120, height => 30,
            launch => #{argv => [<<"/bin/cat">>]}}),
        {ok, Worker} = tmux_window:create(Session,
            #{name => <<"workers">>,
              launch => #{argv => [<<"/bin/cat">>]}}),
        {ok, Right} = tmux_pane:split(Worker, #{direction => horizontal,
            launch => #{argv => [<<"/bin/cat">>]}}),
        {ok, _} = tmux_window:select_layout(Worker, even_horizontal),
        {ok, _} = tmux_pane:resize(Right, #{width => 40}),
        {ok, Snapshot} = tmux_server:snapshot(Server),
        Windows = tmux_select:windows(Snapshot),
        Workers = #{name => <<"workers">>, panes => #{count => 2,
            every => #{current_command => <<"cat">>}}},
        {ok, Captured} = tmux_select:one(Workers, Windows),
        {ok, Children} = tmux_snapshot:related(panes, Captured, Snapshot),
        Ids = [Id || #pane{id = Id} <:- Children],
        2 = length(Ids),
        Criteria = #{width => #{gte => 20},
            window => #{is => #{name => <<"workers">>}}},
        Query = tmux_query:where(Criteria, tmux_query:panes(Server)),
        {ok, Fetched} = tmux_query:fetch(Query),
        2 = tmux_select:size(Fetched),
        {ok, _} = tmux_window:rename(Worker, <<"finished">>),
        <<"workers">> = tmux_model:get(name, Captured),
        {ok, Fresh} = tmux_query:fetch(tmux_query:where(
            #{name => <<"finished">>}, tmux_query:windows(Server))),
        {ok, Renamed} = tmux_select:one(Fresh),
        <<"finished">> = tmux_model:get(name, Renamed),
        1 = length(tmux_snapshot:sessions(Snapshot)),
        2 = length(tmux_snapshot:windows(Snapshot)),
        3 = length(tmux_snapshot:panes(Snapshot)),
        #{sessions => 1, windows => 2, panes => 3, matched_panes => 2,
          captured_name => <<"workers">>, immutable => true}
    end),
    Result.
```

The result includes this checked output. Captured rows keep their original
values after a rename; actions and `fetch` perform explicit I/O.
[`tmux_server:with_owned/2`](<https://libtmux.org/en/erlang/latest/reference/tmux_server-with_owned-2/>) returns success after verified daemon cleanup. If cleanup fails,
its error preserves the callback outcome and ownership token for recovery.

<!-- example-output: readme_demo -->

```json
{
  "sessions": 1,
  "windows": 2,
  "panes": 3,
  "matched_panes": 2,
  "captured_name": "workers",
  "immutable": true
}
```

## Follow the graph

A window can have several links in one session and belong to more than one
session. Physical windows and panes remain unique; window links retain each
session/index membership.

- [Linked windows and relationship queries](https://libtmux.org/en/erlang/latest/concepts/object-graph/): build two sessions,
  link a shared window twice, and verify physical and membership counts.
- [Daemon ownership](https://libtmux.org/en/erlang/latest/topics/ownership/): choose private startup or a borrowed
  socket, keep their lifetimes explicit and handle incomplete cleanup.
- [Build command values](https://libtmux.org/en/erlang/latest/guides/commands/): prepare a rename and resize, submit
  them explicitly and inspect fresh state without changing captured rows.
- [Control attachments](https://libtmux.org/en/erlang/latest/topics/control/): verify connection identity, inspect
  attachment effects and retire the client explicitly.
- [Plan and apply a workspace](https://libtmux.org/en/erlang/latest/guides/workspace-json/): validate desired sessions,
  windows and panes, review saved operations, and handle drift or cancellation.
- [Run a job and capture its result](https://libtmux.org/en/erlang/latest/guides/operations/): wait for a pane's completion
  event, check its exit status, capture bytes, and cancel a separate operation.
- [Local filters and source queries](https://libtmux.org/en/erlang/latest/concepts/queries/): Boolean criteria,
  quantifiers, portable JSON, cardinality, coverage and execution plans.
- [Fields and operators](https://libtmux.org/en/erlang/latest/reference/fields/): generated from the runtime schema.
- [Scoped options](https://libtmux.org/en/erlang/latest/guides/options/): local ownership markers, explicit
  inheritance and sparse arrays, with a source-pinned option catalogue.
- [Buffers and paste](https://libtmux.org/en/erlang/latest/guides/buffers/): preserve binary artifacts, inspect
  names and control terminal delivery.
- [Rearrange panes](https://libtmux.org/en/erlang/latest/guides/panes/): isolate a running job in a window and join
  it back, preserving its process and the original snapshot.
- [Apply configuration and await a signal](https://libtmux.org/en/erlang/latest/guides/configuration/): load settings
  from stdin, observe the event and verify parse-only behavior.
- [Pipe terminal output](https://libtmux.org/en/erlang/latest/guides/piping/): save a job's bytes, await its consumer
  acknowledgement and verify the resulting log.
- [Hooks and completion](https://libtmux.org/en/erlang/latest/guides/hooks/): register a split callback, await its
  acknowledgement and remove the local hook.
- [Key tables](https://libtmux.org/en/erlang/latest/guides/keys/): register application bindings, inspect native
  listings and remove the owned table.
- [Native commands](https://libtmux.org/en/erlang/latest/reference/commands/): source-derived parser metadata
  and feature minimums, separate from library API and runtime qualification.
- [API browser and source docs](https://libtmux.org/en/erlang/latest/guides/api-documentation/): build searchable native reference
  pages with specs, types and links to the exact source revision.

## Decide whether it fits

The current path uses bounded one-shot tmux clients. Operations support
non-blocking submission, explicit waits, cancellation and ownership transfer.
An await timeout abandons that wait; it does not cancel the operation.
Cancellation after dispatch can leave the tmux outcome unknown.

An explicit control attachment verifies identity on its persistent connection
and owns its client cleanup. The workspace application plans and applies JSON
files through a standalone escript. Control command submission and output
streams remain implementation work. The
[support and gaps](https://libtmux.org/en/erlang/latest/guides/compatibility/) page lists
what is exercised, what remains open, and the required Linux/tmux matrix.
There is no control-versus-streaming performance claim.

The [project policy](https://libtmux.org/en/erlang/latest/topics/project-policy/) keeps core and workspace in
separate OTP applications with OTP runtime dependencies. MCP is excluded from
this port's scope.

## Verify and contribute

```console
$ time python3 tools/check.py mid
```

```console
$ time python3 tools/check.py outer
```

The outer check owns its tmux fixtures and tests installed consumers. See
[contributor setup](https://github.com/libtmux/libtmux-erlang/blob/d1b6308440cf9eb8f6647e7ae434bce60e849368/.github/CONTRIBUTING.md) for prerequisites and test budgets,
[CI](https://github.com/libtmux/libtmux-erlang/actions/workflows/ci.yml) for
individual release/architecture results, and the [MIT license](https://github.com/libtmux/libtmux-erlang/blob/d1b6308440cf9eb8f6647e7ae434bce60e849368/LICENSE).

[Branding assets](https://github.com/libtmux/libtmux-erlang/blob/d1b6308440cf9eb8f6647e7ae434bce60e849368/docs/branding.md) include the logo, icons, and social cards.
