tmux-workspace 0.1.0-alpha.16

Build tmux workspaces from tmuxp-style YAML using libtmux (alpha)
Documentation

tmux-workspace

Load tmux sessions from YAML, and save running ones back to it. A native tmuxp: it reads tmuxp's workspace files, finds them where tmuxp does and takes tmuxp's flags, as one binary with no Python.

Alpha. Commands and flags can change between releases, and changes are listed in the changelog rather than flagged as breaking. cargo install skips prereleases unless asked, so the command below names the version.

Install

$ cargo install tmux-workspace \
    --version 0.1.0-alpha.16 \
    --locked

It needs tmux 3.3a or newer on PATH, and Rust 1.85 to build. cargo binstall fetches a prebuilt binary for Linux or macOS when the release carries one, and builds from source when it does not:

$ cargo binstall tmux-workspace --version 0.1.0-alpha.16

Load a session

Describe the session:

session_name: dev
windows:
  - window_name: editor
    layout: main-vertical
    panes:
      - vim
      - git status
  - window_name: monitor
    panes:
      - top

Save it as dev.yaml, and load it:

$ tmux-workspace load ./dev.yaml

That builds the session and attaches to it. Run inside tmux, it asks whether to switch to the new session, keep it in the background, or add its windows to the session you are in.

Loading

Build the .tmuxp.yaml in a project directory:

$ tmux-workspace load .

Keep workspaces in ~/.config/tmuxp/ and load them by name from anywhere:

$ tmux-workspace load dev

See what one would build -- sessions, windows, panes, directories and commands -- without touching tmux or running its before_script:

$ tmux-workspace load --dry-run dev

Load several, attaching to the last:

$ tmux-workspace load api web

Build without attaching:

$ tmux-workspace load -d dev

Build under a different session name:

$ tmux-workspace load -s scratch dev

Add the windows to the session you are in:

$ tmux-workspace load -a tools

Build on a separate tmux server, named or by socket path:

$ tmux-workspace load -L work dev

Saving and converting

Save a running session as a workspace:

$ tmux-workspace freeze dev -o dev.yaml

Freezing recovers windows, panes, layouts and working directories. It cannot recover the command someone typed to start a pane, only what the pane is running now, so read the file before relying on it.

Convert between YAML and JSON; it shows the destination and asks first:

$ tmux-workspace convert dev.yaml

Import a tmuxinator project or a teamocil layout. It asks, then saves it where load finds it by name -- here ~/.config/tmuxp/api.yaml, so tmux-workspace load api builds it next:

$ tmux-workspace import tmuxinator api
$ tmux-workspace import teamocil dev

Open a workspace in $EDITOR:

$ tmux-workspace edit dev

Finding workspaces

List every workspace it can find, grouped by directory:

$ tmux-workspace ls --tree

Search them; window:, session:, pane: and path: limit a pattern to one field:

$ tmux-workspace search window:logs

Shell setup

Completions and the manual page are generated by the binary. For zsh, with ~/.zfunc on fpath:

$ tmux-workspace --generate zsh > ~/.zfunc/_tmux-workspace
$ tmux-workspace --generate man > ~/.local/share/man/man1/tmux-workspace.1

bash, fish, PowerShell and elvish are in the command reference. Every command has examples under --help.

Attach this to a bug report:

$ tmux-workspace debug-info

Coming from tmuxp

Your workspace files load unchanged: the same keys, the same .tmuxp.yaml project files, the same directories ($TMUXP_CONFIGDIR, ~/.config/tmuxp, ~/.tmuxp) and the same load flags (-d, -s, -a, -L, -S, -f, -2, -y). Where it differs:

  • An unknown key is refused rather than ignored. Prefix a key with x- to carry your own fields; convert preserves them.
  • A window that names no layout is tiled rather than stacked.
  • A session_name containing : or . is refused: tmux reads those as window and pane separators.
  • $VAR in a command is expanded by the pane's shell, with your value passed to it, rather than pasted into the command text: a value holding ; stays a value.
  • freeze saves only where -o says, or prints with --json.
  • plugins and custom workspace_builders run through tmuxp itself, so they need tmuxp 1.74.x and Python libtmux declaring a hard tmux minimum of 3.3a or newer with per-command daemon version check. Runtime discovery and the builder child check this before importing extension hooks.

The Python bridge depends on the coordinated Python libtmux tmux-support change, which has not been released. CI qualifies its pinned source with tmux 3.3a. Released tmuxp 1.74.0 pins libtmux below 0.62; installing that release alone does not qualify the bridge. Use a compatible tmuxp environment carrying the updated Python library and select it with TMUX_WORKSPACE_PYTHON.

The command reference has the complete list.

It starts in about a millisecond where tmuxp takes about 125, and a cold two-window load takes about 150 ms against 205 (one Linux machine, tmux 3.7d, tmuxp 1.74.0, medians of 20 starts and 5 loads). To measure your own:

$ just bench-cli --binary target/release/tmux-workspace --tmuxp "$(command -v tmuxp)"

Scripting

--json prints one JSON document, and --ndjson streams one event per line as windows and panes are created. A load under either needs -d, because nothing is attached:

$ tmux-workspace --ndjson load -d api web

A failure writes {"schema_version":1,"code":"...","message":"..."} to stderr and exits 1, or 2 when the command line itself is wrong. The codes and events are in the command reference.

Let an agent watch it

tmux-mcp gives an MCP client typed, read-only access to the sessions a workspace builds. Load on a named server and point the server at the same one:

$ tmux-workspace load -d -L agents dev
$ LIBTMUX_TOOLSETS=inspect tmux-mcp -L agents

Configure your MCP client to launch that second command. The workspace keeps running after the client disconnects. The tmux-mcp README covers installing it and wiring clients.

Use it from Rust

The same package is a library: parse a workspace, preview the tmux commands it would run, build it, or freeze a session, through libtmux. It reads a document the way the command does, tmuxp's way; the command reference lists where the two differ.

$ cargo add tmux-workspace@0.1.0-alpha.16 --no-default-features

--no-default-features leaves the command and its dependencies out. Examples and the API are on docs.rs.

Development

The tests drive a real tmux on an isolated socket, so tmux must be on $PATH:

$ cargo test -p tmux-workspace --all-features

License

Licensed under either of Apache License, Version 2.0 or MIT license at your option.