Workspace guide
LibTmuxWorkspace 0.1.0-alpha.1 · Source
LibTmuxWorkspace reads a documented tmuxp-style YAML/JSON subset. Validation, expansion and planning are pure. Applying a plan creates tmux resources and can execute shell input. Keep those stages explicit when reviewing an untrusted configuration.
From a consumer project directory, add the core and workspace package from the same public Git tag:
$ julia \ --startup-file=no \ -e 'using Pkg; Pkg.activate("."); repo="https://github.com/libtmux/libtmux-julia.git"; tag="v0.1.0-alpha.1"; Pkg.add([Pkg.PackageSpec(url=repo, rev=tag), Pkg.PackageSpec(url=repo, rev=tag, subdir="packages/LibTmuxWorkspace")])'The following executable source example needs a checkout and its own consumer environment. Clone the same tag, then enter the checkout:
$ git clone \ --branch v0.1.0-alpha.1 \ --depth 1 \ https://github.com/libtmux/libtmux-julia.git$ cd libtmux-juliaCreate a local environment for the example:
$ julia \ --startup-file=no \ -e 'using Pkg; Pkg.activate(".workspace-env"); repo="https://github.com/libtmux/libtmux-julia.git"; tag="v0.1.0-alpha.1"; Pkg.add([Pkg.PackageSpec(url=repo, rev=tag), Pkg.PackageSpec(url=repo, rev=tag, subdir="packages/LibTmuxWorkspace")])'It loads two panes, checks their layout and focus, freezes the supported reconstruction subset, and closes the private daemon:
$ julia \ --startup-file=no \ --project=.workspace-env \ packages/LibTmuxWorkspace/examples/owned_load.jlThe code below is included from that executable program:
using LibTmux, LibTmuxWorkspace
function main() endpoint = Ref{Server}() frozen = with_server(; tmux=get(ENV, "LIBTMUX_TEST_TMUX", "tmux")) do server endpoint[] = server config = validate( Dict( "session_name" => "workspace-example", "options" => Dict("default-shell" => "/bin/sh"), "windows" => [ Dict( "window_name" => "editor", "window_index" => 0, "layout" => "even-horizontal", "focus" => true, "panes" => [ Dict( "shell_command" => [ Dict("cmd" => "printf ready", "enter" => false), ], ), Dict("focus" => true), ], ), ], ), ) prepared = plan(expand(config; base_directory=dirname(server.socket_path))) result = apply(server, prepared; rollback=:created) @assert result.status == :complete observed = snapshot(server) @assert length(panes(observed)) == 2 link = only(windowlinks(observed)) @assert link.index == 0 && link.active editor = window(link) editor_panes = sort(collect(panes(editor)); by=p -> p.index) @assert [p.active for p in editor_panes] == [false, true] @assert all(p -> p.height == editor.height, editor_panes) @assert sum(p.width for p in editor_panes) + 1 == editor.width @assert abs(editor_panes[1].width - editor_panes[2].width) <= 1 document = freeze(server, result.session) @assert length(validate(document).windows[1].panes) == 2 frozen_editor = only(validate(document).windows) @assert frozen_editor.name == "editor" && frozen_editor.focus @assert [p.focus for p in frozen_editor.panes] == [false, true] @assert all( p -> p.start_directory == realpath(dirname(server.socket_path)), frozen_editor.panes, ) @assert frozen_editor.layout == only(read_formats(server, editor.ref, FormatField("window_layout"))).value println("Loaded 1 window and 2 panes; frozen names, layout, paths and focus") document end @assert !ispath(dirname(endpoint[].socket_path)) frozenend
main()Install the command¶
The launcher binds to that environment and performs no package resolution at startup:
$ julia \ --startup-file=no \ --project=.workspace-env \ -e 'using LibTmuxWorkspace; println(LibTmuxWorkspace.install_cli("bin"))'Inspect the shipped configuration without contacting tmux:
$ bin/libtmux-workspace plan packages/LibTmuxWorkspace/examples/workspace.yaml \ --env PROJECT=example \ --output jsonvalidate FILE checks syntax and schema. plan FILE expands only explicitly
supplied environment/home values and produces inert ordered steps.
load FILE and freeze SESSION require exactly one explicit --socket or
--socket-name. Loading is detached by default; an existing session name
fails unless reuse is explicit. Interactive --attach requires a terminal
and remains outside automated attachment evidence.
Human progress goes to stderr. --output json writes one final result;
--output ndjson writes ordered progress and one terminal record. Nonzero
exit codes distinguish usage, backend failure, partial effects, cancellation
and deadline. A requested rollback removes only provably created resources.
Shell input, scripts and changes to borrowed resources cannot be rolled back.
The default POSIX shell readiness handshake uses directory notifications and an exact owned marker. It does not poll cursor position or infer that later commands finished. Custom interactive launchers require the explicit readiness opt-out and caller-provided coordination.
Freeze preserves names, layouts, pane directories and focus. It cannot reconstruct commands, history, environment or options. Reloading shared windows creates independent windows. Snapshot acquisition is not atomic.
Library reference¶
Browse the LibTmuxWorkspace API reference.