Core Library0.xHome

Choose documentation 1

latest

Current version

latest
English

Early release libtmux is released, and its APIs may still change between releases. This site's structure and URLs may change too.

Edit this page on GitHub

tmux client library for Raku

Control tmux, connect to and create servers, navigate sessions, windows, and panes, send keys, watch for changes via control mode, capture pane contents.

Install

zef install 'LibTmux:auth<zef:libtmux>'

At a glance

Server → Session → LibTmux::Model::WindowLink → Window → Pane. Each level of the tmux hierarchy has its own entry in the Raku API, with the tmux object it wraps.

TypeWraps
LibTmux::Server A tmux server
LibTmux::Model::Session A session, ID $n
LibTmux::Model::Window A physical window linked into sessions, ID @n
LibTmux::Model::Pane A pane in a window, ID %n
LibTmux::Model::WindowLink A session-window association, with its index and active state

What it does

use LibTmux;
my $server = Server.start(:name<work>, :shell-command('exec cat'));
LEAVE $server.close if $server.defined;
my $before = $server.snapshot;
my $left = $before.panes.single.ref;
my $right = $left.split(:horizontal, :shell-command('exec cat'));
$left.set-title('editor');
$right.set-title('logs');
my $after = $server.snapshot;
my $editor = $after.panes.filter(*.title eq 'editor').single;
say "{$editor.title}: {$after.panes.elems} panes";
No tmux server yet

tmux before the first call: no server is running.

%0 cat
[work]

tmux after Server.start: added session work.

%0 cat
[work]

tmux after Server.snapshot: unchanged.

%0 cat
[work]

tmux after PaneSelection.single: unchanged, the call sent no command.

%0 cat
%1 cat
[work]

tmux after PaneRef.split: added pane %1 to window 0:sh.

%0 cat
%1 cat
[work]

tmux after PaneRef.set-title: unchanged.

%0 cat
%1 cat
[work]

tmux after PaneRef.set-title: unchanged.

%0 cat
%1 cat
[work]

tmux after Server.snapshot: unchanged.

%0 cat
%1 cat
[work]

tmux after PaneSelection.single: unchanged, the call sent no command.

No sessions

tmux after Server.close: the server has exited; the call sent no command.

Before the first call

No tmux server is running yet.

Server.start returned Server

{
"socket": "libtmux-owned-AbC123"
}
1 tmux command, 1 that changes tmux
  1. new-session -d -P -F LTM1-session-#{session_id} -s work -x 80 -y 24 -- 'exec cat' LTM1-session-$0

Before these, the library asked tmux about itself 4 times (its version, its daemon, how a control client reads escapes).

Server.snapshot returned Snapshot

{
"panes": 1,
"sessions": 1,
"windows": 1
}
7 tmux commands
  1. list-sessions -F 'LTM1\011libtmux.format/v1:session:session:qa:none:id,name,windows-count,attached-count,created,activity,path,grouped,group-name\011qa\011#{session_id}\011#{q/a:session_name}\011#{session_windows}\011#{session_attached}\011#{session_created}\011#{session_activity}\011#{q/a:session_path}\011#{session_grouped}\011#{q/a:session_group}\011END' LTM1 libtmux.format/v1:session:session:qa:none:id,name,windows-count,attached-count,created,activity,path,grouped,group-name qa $0 work 1 0 1794634589 1794634589 /tmp/marked 0 END
  2. list-windows -a -F 'LTM1\011libtmux.format/v1:window-link:window-link:qa:none:session-id,window-id,index,active,last,activity,bell,silence\011qa\011#{session_id}\011#{window_id}\011#{window_index}\011#{window_active}\011#{window_last_flag}\011#{window_activity_flag}\011#{window_bell_flag}\011#{window_silence_flag}\011END' LTM1 libtmux.format/v1:window-link:window-link:qa:none:session-id,window-id,index,active,last,activity,bell,silence qa $0 @0 0 1 0 0 0 0 END
  3. list-windows -a -F 'LTM1\011libtmux.format/v1:window:window:qa:none:id,name,width,height,panes-count,layout,visible-layout,zoomed,modal-pane-id\011qa\011#{window_id}\011#{q/a:window_name}\011#{window_width}\011#{window_height}\011#{window_panes}\011#{q/a:window_layout}\011#{q/a:window_visible_layout}\011#{window_zoomed_flag}\011#{window_modal_pane}\011END' LTM1 libtmux.format/v1:window:window:qa:none:id,name,width,height,panes-count,layout,visible-layout,zoomed,modal-pane-id qa @0 sh 80 24 1 "{\"V\":2,\"L\":{\"t\":\"p\",\"w\":80,\"h\":24,\"x\":0,\"y\":0,\"a\":true,\"i\":0,\"I\":\"%0\"}}" "{\"V\":2,\"L\":{\"t\":\"p\",\"w\":80,\"h\":24,\"x\":0,\"y\":0,\"a\":true,\"i\":0,\"I\":\"%0\"}}" 0 END
  4. list-panes -a -F 'LTM1\011libtmux.format/v1:pane:pane:qa:none:id,window-id,index,active,width,height,left,top,pid,tty,title,current-command,current-path,start-command,start-path,dead,dead-status,dead-signal,dead-time,in-mode,mode,pipe,synchronized,floating,modal,x,y,z,command-running,command-status,at-top,at-bottom,at-left,at-right\011qa\011#{pane_id}\011#{window_id}\011#{pane_index}\011#{pane_act… LTM1 libtmux.format/v1:pane:pane:qa:none:id,window-id,index,active,width,height,left,top,pid,tty,title,current-command,current-path,start-command,start-path,dead,dead-status,dead-signal,dead-time,in-mode,mode,pipe,synchronized,floating,modal,x,y,z,command-running,command-status,at-top,at-bottom,at-left,at-right qa %0 @0 0 1 80 24 0 0 2005202 /dev/pts/19 host cat /tmp/marked "\"exe…
  5. list-clients -F 'LTM1\011libtmux.format/v1:client:client:qa:none:name,session-id,session-name,tty,pid,width,height,created,activity,control-mode,read-only,terminal-name,key-table\011qa\011#{q/a:client_name}\011#{session_id}\011#{q/a:client_session}\011#{q/a:client_tty}\011#{client_pid}\011#{client_width}\011#{client_height}\011#{client_created}\011#{client_activity}\011#{client_control_mode}\011#{… no output
  6. list-sessions -f #{session_grouped} -F 'LTM1\011libtmux.format/v1:session-group:grouped-session:qa:none:name,size,attached-count\011qa\011#{q/a:session_group}\011#{session_group_size}\011#{session_group_attached}\011END' no output
  7. list-buffers -F 'LTM1\011libtmux.format/v1:buffer:buffer:qa:none:name,size,created,sample\011qa\011#{q/a:buffer_name}\011#{buffer_size}\011#{buffer_created}\011#{q/a:buffer_sample}\011END' no output

Before these, the library asked tmux about itself 6 times (its version, its daemon, how a control client reads escapes).

PaneSelection.single returned PaneRef

{
"id": "%0"
}

The call sent no tmux command.

PaneRef.split returned PaneRef

{
"id": "%1"
}
1 tmux command, 1 that changes tmux
  1. split-window -P -F LTM1-pane-#{pane_id} -t %0 -h -d -- 'exec cat' LTM1-pane-%1

PaneRef.set-title returned void

null
1 tmux command, 1 that changes tmux
  1. select-pane -t %0 -T editor no output

PaneRef.set-title returned void

null
1 tmux command, 1 that changes tmux
  1. select-pane -t %1 -T logs no output

Server.snapshot returned Snapshot

{
"panes": 2,
"sessions": 1,
"windows": 1
}
7 tmux commands
  1. list-sessions -F 'LTM1\011libtmux.format/v1:session:session:qa:none:id,name,windows-count,attached-count,created,activity,path,grouped,group-name\011qa\011#{session_id}\011#{q/a:session_name}\011#{session_windows}\011#{session_attached}\011#{session_created}\011#{session_activity}\011#{q/a:session_path}\011#{session_grouped}\011#{q/a:session_group}\011END' LTM1 libtmux.format/v1:session:session:qa:none:id,name,windows-count,attached-count,created,activity,path,grouped,group-name qa $0 work 1 0 1794634589 1794634589 /tmp/marked 0 END
  2. list-windows -a -F 'LTM1\011libtmux.format/v1:window-link:window-link:qa:none:session-id,window-id,index,active,last,activity,bell,silence\011qa\011#{session_id}\011#{window_id}\011#{window_index}\011#{window_active}\011#{window_last_flag}\011#{window_activity_flag}\011#{window_bell_flag}\011#{window_silence_flag}\011END' LTM1 libtmux.format/v1:window-link:window-link:qa:none:session-id,window-id,index,active,last,activity,bell,silence qa $0 @0 0 1 0 0 0 0 END
  3. list-windows -a -F 'LTM1\011libtmux.format/v1:window:window:qa:none:id,name,width,height,panes-count,layout,visible-layout,zoomed,modal-pane-id\011qa\011#{window_id}\011#{q/a:window_name}\011#{window_width}\011#{window_height}\011#{window_panes}\011#{q/a:window_layout}\011#{q/a:window_visible_layout}\011#{window_zoomed_flag}\011#{window_modal_pane}\011END' LTM1 libtmux.format/v1:window:window:qa:none:id,name,width,height,panes-count,layout,visible-layout,zoomed,modal-pane-id qa @0 sh 80 24 2 "{\"V\":2,\"L\":{\"t\":\"h\",\"w\":80,\"h\":24,\"x\":0,\"y\":0,\"c\":[{\"t\":\"p\",\"w\":40,\"h\":24,\"x\":0,\"y\":0,\"a\":true,\"i\":0,\"I\":\"%0\"},{\"t\":\"p\",\"w\":39,\"h\":24,\"x\":41,\"y\":0,\"i\":1,\"I\":\"%1\"}]}}" "{\"V\":2,\"L\":{\"t\":\"h\",\"w\":80,…
  4. list-panes -a -F 'LTM1\011libtmux.format/v1:pane:pane:qa:none:id,window-id,index,active,width,height,left,top,pid,tty,title,current-command,current-path,start-command,start-path,dead,dead-status,dead-signal,dead-time,in-mode,mode,pipe,synchronized,floating,modal,x,y,z,command-running,command-status,at-top,at-bottom,at-left,at-right\011qa\011#{pane_id}\011#{window_id}\011#{pane_index}\011#{pane_act… LTM1 libtmux.format/v1:pane:pane:qa:none:id,window-id,index,active,width,height,left,top,pid,tty,title,current-command,current-path,start-command,start-path,dead,dead-status,dead-signal,dead-time,in-mode,mode,pipe,synchronized,floating,modal,x,y,z,command-running,command-status,at-top,at-bottom,at-left,at-right qa %0 @0 0 1 40 24 0 0 2005202 /dev/pts/19 editor cat /tmp/marked "…
  5. list-clients -F 'LTM1\011libtmux.format/v1:client:client:qa:none:name,session-id,session-name,tty,pid,width,height,created,activity,control-mode,read-only,terminal-name,key-table\011qa\011#{q/a:client_name}\011#{session_id}\011#{q/a:client_session}\011#{q/a:client_tty}\011#{client_pid}\011#{client_width}\011#{client_height}\011#{client_created}\011#{client_activity}\011#{client_control_mode}\011#{… no output
  6. list-sessions -f #{session_grouped} -F 'LTM1\011libtmux.format/v1:session-group:grouped-session:qa:none:name,size,attached-count\011qa\011#{q/a:session_group}\011#{session_group_size}\011#{session_group_attached}\011END' no output
  7. list-buffers -F 'LTM1\011libtmux.format/v1:buffer:buffer:qa:none:name,size,created,sample\011qa\011#{q/a:buffer_name}\011#{buffer_size}\011#{buffer_created}\011#{q/a:buffer_sample}\011END' no output

Before these, the library asked tmux about itself 6 times (its version, its daemon, how a control client reads escapes).

PaneSelection.single returned Pane

{
"id": "%0",
"title": "editor"
}

The call sent no tmux command.

Server.close returned void

null

The call sent no tmux command.

0/9
Run this example

Linux, Raku 6.d with zef, and tmux 3.3a through 3.8 on PATH. The first command installs the published LibTmux distribution from Raku Land, so it needs network access to the zef ecosystem. The program starts its own private tmux server.

Save the program above as quickstart.raku in a new directory, along with the files below.

This complete program owns a private tmux server and closes it with LEAVE when the program exits, including on an exception.

Setup and run

zef install 'LibTmux:ver<0.0.1+>:auth<zef:libtmux>'
raku quickstart.raku

Expected output

editor: 2 panes

Typed API

What you get over the tmux CLI

LibTmux gives Raku programs typed snapshots of a tmux server, ordinary predicates over them, and explicit commands that change tmux. Reading a snapshot makes no further tmux calls; an operation through a reference does.

The LibTmux distribution from the zef:libtmux authority is published on Raku Land. Its API is experimental and may change between 0.x releases. CI qualifies Rakudo 2026.09 on Linux with tmux 3.3a and 3.8; other platforms and compiler versions are unverified. The library has no workspace manager or MCP server.

Esc

Type to search.

Reference previewOpen reference