tmux client library for Elixir
Control tmux, navigate sessions, windows, and panes, watch for changes via control mode.
Guides
Task guides for Elixir.
Topics
Subject-by-subject, with Elixir in every code block.
Examples
Complete programs, sourced from the code each port tests.
API reference
Types and functions of the Elixir API.
Install
{:libtmux, "~> 0.1.0"}libtmux 0.1.0 is pre-1.0 and can change between minor versions. Pin to a range:
{:libtmux, "~> 0.1.0"}At a glance
Server → Session → Window → Pane. Each level of the tmux hierarchy has its own entry in the Elixir API, with the tmux object it wraps.
| Type | Wraps |
|---|---|
LibTmux.Server | A tmux server |
LibTmux.Session | A session, ID $n |
LibTmux.Window | A window in a session, ID @n |
LibTmux.Pane | A pane in a window, ID %n |
What it does
Start with Elixir
Mix.install([{:libtmux, "~> 0.1"}])
alias LibTmux.{Command, Selection, Server, Snapshot}
tmux = System.find_executable("tmux") || raise "tmux is not on PATH"id = Base.encode16(:crypto.strong_rand_bytes(8), case: :lower)dir = Path.join(System.tmp_dir!(), "libtmux-" <> id)socket = Path.join(dir, "tmux.sock")File.mkdir!(dir)File.chmod!(dir, 0o700)
# libtmux works on a running server, so tmux itself starts the private one.create = ["new-session", "-d", "-s", "demo", "/bin/cat"]{_, 0} = System.cmd(tmux, ["-S", socket, "-f", "/dev/null" | create])
server = Server.new(executable: tmux, socket: socket)split = Command.new("split-window", ["-t", "demo", "/bin/cat"])logs = Command.new("new-window", ["-t", "demo", "-n", "logs", "/bin/cat"]){:ok, _} = Server.run(server, split){:ok, _} = Server.run(server, logs)
snapshot = Server.snapshot!(server)session = snapshot |> Snapshot.sessions() |> Selection.one!()windows = snapshot |> Snapshot.windows() |> Selection.size()panes = snapshot |> Snapshot.panes() |> Selection.size()IO.puts("#{session.name}: #{windows} windows, #{panes} panes")Mix.install([{:libtmux, "~> 0.1"}])
alias LibTmux.{Command, Selection, Server, Snapshot}
tmux = System.find_executable("tmux") || raise "tmux is not on PATH"id = Base.encode16(:crypto.strong_rand_bytes(8), case: :lower)dir = Path.join(System.tmp_dir!(), "libtmux-" <> id)socket = Path.join(dir, "tmux.sock")File.mkdir!(dir)File.chmod!(dir, 0o700)
# libtmux works on a running server, so tmux itself starts the private one.create = ["new-session", "-d", "-s", "demo", "/bin/cat"]{_, 0} = System.cmd(tmux, ["-S", socket, "-f", "/dev/null" | create])
server = Server.new(executable: tmux, socket: socket)split = Command.new("split-window", ["-t", "demo", "/bin/cat"])logs = Command.new("new-window", ["-t", "demo", "-n", "logs", "/bin/cat"]){:ok, _} = Server.run(server, split){:ok, _} = Server.run(server, logs)
snapshot = Server.snapshot!(server)session = snapshot |> Snapshot.sessions() |> Selection.one!()windows = snapshot |> Snapshot.windows() |> Selection.size()panes = snapshot |> Snapshot.panes() |> Selection.size()IO.puts("#{session.name}: #{windows} windows, #{panes} panes")Mix.install([{:libtmux, "~> 0.1"}])
alias LibTmux.{Command, Selection, Server, Snapshot}
tmux = System.find_executable("tmux") || raise "tmux is not on PATH"id = Base.encode16(:crypto.strong_rand_bytes(8), case: :lower)dir = Path.join(System.tmp_dir!(), "libtmux-" <> id)socket = Path.join(dir, "tmux.sock")File.mkdir!(dir)File.chmod!(dir, 0o700)
try do # libtmux works on a running server, so tmux itself starts the private one. create = ["new-session", "-d", "-s", "demo", "/bin/cat"] {_, 0} = System.cmd(tmux, ["-S", socket, "-f", "/dev/null" | create])
server = Server.new(executable: tmux, socket: socket) split = Command.new("split-window", ["-t", "demo", "/bin/cat"]) logs = Command.new("new-window", ["-t", "demo", "-n", "logs", "/bin/cat"]) {:ok, _} = Server.run(server, split) {:ok, _} = Server.run(server, logs)
snapshot = Server.snapshot!(server) session = snapshot |> Snapshot.sessions() |> Selection.one!() windows = snapshot |> Snapshot.windows() |> Selection.size() panes = snapshot |> Snapshot.panes() |> Selection.size() IO.puts("#{session.name}: #{windows} windows, #{panes} panes")after System.cmd(tmux, ["-S", socket, "kill-server"], stderr_to_stdout: true) File.rm_rf(dir)endMix.install([{:libtmux, "~> 0.1"}])
alias LibTmux.{Command, Selection, Server, Snapshot}
tmux = System.find_executable("tmux") || raise "tmux is not on PATH"id = Base.encode16(:crypto.strong_rand_bytes(8), case: :lower)dir = Path.join(System.tmp_dir!(), "libtmux-" <> id)socket = Path.join(dir, "tmux.sock")File.mkdir!(dir)File.chmod!(dir, 0o700)
try do # libtmux works on a running server, so tmux itself starts the private one. create = ["new-session", "-d", "-s", "demo", "/bin/cat"] {_, 0} = System.cmd(tmux, ["-S", socket, "-f", "/dev/null" | create])
server = Server.new(executable: tmux, socket: socket) split = Command.new("split-window", ["-t", "demo", "/bin/cat"]) logs = Command.new("new-window", ["-t", "demo", "-n", "logs", "/bin/cat"]) {:ok, _} = Server.run(server, split) {:ok, _} = Server.run(server, logs)
snapshot = Server.snapshot!(server) session = snapshot |> Snapshot.sessions() |> Selection.one!() windows = snapshot |> Snapshot.windows() |> Selection.size() panes = snapshot |> Snapshot.panes() |> Selection.size() IO.puts("#{session.name}: #{windows} windows, #{panes} panes")after System.cmd(tmux, ["-S", socket, "kill-server"], stderr_to_stdout: true) File.rm_rf(dir)endRun this example
POSIX shell, tmux 3.3 or newer, Elixir 1.20.4 or newer, Erlang/OTP 29.1.2 or a newer 29.x release, access to hex.pm, and a C11 compiler on Linux.
Save the program above as quickstart.exs in a new directory, along with the files below.
Cleanup is omitted; the private tmux server and its temporary files may remain. Select Cleanup to remove them when the program finishes. The program stops its private tmux server and removes any temporary files it created when it finishes. An unmatched result or a raised error ends the script with its message and stack trace, so there is no separate error handling to add. Every version checks required results.
Setup and run
unset TMUX TMUX_PANEexport ENV=/dev/null BASH_ENV=/dev/null SHELL=/bin/shelixir quickstart.exsExpected output
demo: 2 windows, 3 panesLibrary revision: cac4252bfc52.
Typed API
- Typed objects instead of parsed format strings:
LibTmux.Pane - Filtering and queries over tmux objects:
LibTmux.Filter - Typed errors instead of exit codes and stderr:
LibTmux.Error
What you get over the tmux CLI
- Traversal from a server down to its panes:
LibTmux.Snapshot.panes/1 - Watch for changes through tmux control mode:
LibTmux.Control - Arguments passed as a list, with no shell quoting:
LibTmux.Command