# LibTmux-Workspace
LibTmux-Workspace validates, plans, and loads JSON workspaces through public
[LibTmux core APIs](https://github.com/libtmux/libtmux-perl/tree/master/packages/core).
Describe sessions, windows, pane commands, layout, working directories, and
environment; inspect the plan before applying it.
[CLI example](#validate-plan-and-load-a-workspace) ·
[Perl example](#load-and-inspect-from-perl) ·
[Guide](https://libtmux.org/en/perl/latest/workspace/source-guide/) ·
[API reference](https://libtmux.org/en/perl/latest/workspace/reference/libtmux-workspace/)
## Install from source
Install core first. From the workspace distribution directory:
```console
$ cpm install \
--global \
.
```
Requires Perl 5.44, the versioned core distribution, and its Linux x86_64 LP64
and tmux 3.3a–3.8 environment. It adds no non-core runtime dependency and does
not require async. This development distribution is not published on CPAN.
Read the [source installation guide](https://github.com/libtmux/libtmux-perl/blob/master/docs/installation.md)
for interpreter and installer setup.
## Validate, plan, and load a workspace
The packaged [examples/workspace.json](examples/workspace.json) creates two
windows and three panes. Its commands run Perl directly:
```json
{
"schema": "libtmux.workspace/v1",
"environment": {"PROJECT": "api"},
"sessions": [{
"name": "perl-workspace",
"windows": [{
"name": "editor",
"layout": "even-horizontal",
"panes": [
{"command": ["perl", "-e", "while () { print }"]},
{"command": ["perl", "-e", "while () { print }"], "horizontal": true}
]
}, {
"name": "logs",
"panes": [{"command": ["perl", "-e", "while () { print }" ]}]
}]
}]
}
```
From this distribution directory, validate the file and inspect its plan:
```console
$ libtmux-workspace validate examples/workspace.json
```
```console
$ libtmux-workspace plan examples/workspace.json
```
Load it on an explicit socket. An unused path starts a new server:
```console
$ libtmux-workspace load examples/workspace.json \
--socket-path "${TMPDIR:-/tmp}/libtmux-perl-workspace-$$.sock" \
--existing skip
```
Validation and planning perform no tmux I/O. Loading leaves the workspace
running. Repeating the command with the same socket and `skip` preserves the
entire existing session. The default policy reports a conflict; it never
silently replaces another session.
## Load and inspect from Perl
Run [examples/load.pl](examples/load.pl) to plan, load, inspect the graph,
repeat with `skip`, and remove the session it created:
```console
$ perl examples/load.pl "${TMPDIR:-/tmp}/libtmux-perl-workspace-$$.sock"
```
```perl
use v5.44;
use FindBin;
use LibTmux::Server;
use LibTmux::Workspace;
my $socket = shift @ARGV // die "Usage: $0 SOCKET_PATH [TMUX]\n";
my $tmux = shift @ARGV // 'tmux';
my $server = LibTmux::Server->new(
socket_path => $socket,
executable => $tmux,
config_file => '/dev/null',
);
# example: begin plan
open my $in, '<:raw', "$FindBin::Bin/workspace.json" or die $!;
my $json = do { local $/; <$in> };
close $in or die $!;
my $workspace = LibTmux::Workspace->from_json($json);
my $plan = $workspace->plan;
say 'planned sessions: ', scalar $plan->{sessions}->@*;
die 'plan must not mutate' if $plan->{mutates};
# example: end plan
my ($session, $failure);
try {
# example: begin load
my $report = $workspace->load(server => $server);
my $snapshot = $server->snapshot;
$session = $snapshot->sessions->one({name => 'perl-workspace'});
my $windows = $session->window_links;
say 'loaded windows: ', $windows->count;
my $editor = $windows->one({window => {-is => {name => 'editor'}}})->window;
say 'editor panes: ', $editor->panes->count;
# example: end load
die 'workspace structure differs'
unless $windows->count == 2 && $editor->panes->count == 2;
# example: begin repeat
my $again = $workspace->load(server => $server, existing => 'skip');
say 'skipped existing sessions: ', scalar $again->{skipped}->@*;
# example: end repeat
die 'repeat did not skip' unless $again->{skipped}->@* == 1;
die 'environment was not inherited'
unless $server->get_environment(session => $session, name => 'PROJECT')
eq 'api';
}
catch ($error) { $failure = $error }
if ($session) {
try { $server->kill_session(session => $session) }
catch ($cleanup) {
warn "session cleanup failed: $cleanup\n";
$failure //= $cleanup;
}
}
die $failure if defined $failure;
say 'workspace plan, load, repeat: ok';
```
The program reports one planned session, two loaded windows, two editor panes,
and one skipped session. It uses installed modules and its adjacent JSON file;
it needs no Python or author fixture.
## Handle conflicts and partial effects
The [`Workspace`](https://libtmux.org/en/perl/latest/workspace/reference/libtmux-workspace/)
library checks all session-name conflicts before creating anything. `skip`
preserves whole existing sessions; it does not reconcile their pane count or
layout. Working directories and environment inherit through the configured
levels, and layout is applied after splitting.
A failed load records completed steps, the failed step, dispatch uncertainty,
and the original typed cause. Rollback can affect only sessions proven created
by that load. `report` preserves typed cleanup failures with target identities;
`report_data` makes a detached JSON-safe diagnostic export.
The CLI exits with 0 for success, 2 for usage/configuration, 3 for load failure,
and 4 for conflict. Pane commands use literal `command` arrays or an explicit
`shell_command`. The versioned `libtmux.workspace/v1` format is not tmuxp's
schema; tmuxp catalog import is separate work.
Read the [workspace guide](https://libtmux.org/en/perl/latest/workspace/source-guide/)
and installed `perldoc LibTmux::Workspace` documentation. Each native archive
includes this README, its logo assets, and the complete examples.