Skip to content

Latest commit

 

History

History

libtmux-workspace-cli

Folders and files

NameName
Last commit message
Last commit date

parent directory

..
 
 
 
 
 
 
 
 
 
 

README.md

libtmux for Java workspace

libtmux-workspace-cli

tmux-workspace loads, captures, converts and imports tmux workspaces.

libtmux.org libtmux-workspace-cli

Load a tmuxp-style file into a session, capture a session back into a file, convert it between YAML and JSON, or import a tmuxinator or Teamocil project. Flags follow tmuxp 1.74.0, and every command can answer in JSON or NDJSON.

io.github.libtmux:libtmux-workspace-cli — on Maven Central. Reference: the command manual on libtmux.org.

Releases are numbered 0.1.N, and each release increments N. The API is not settled: any release may change or remove exported identifiers, and the changelog marks each break. Pin an exact version to avoid one.

Commands, flags and output records are part of the API.

Contents — Quick start · Find, convert, and import · Inspect a loaded workspace through MCP · Commands · What it leaves out · Support and status · Documentation

Quick start

Build the launcher from the repository root and put its directory on PATH:

$ ./gradlew :libtmux-workspace-cli:installDist
$ export PATH="$PWD/libtmux-workspace-cli/build/install/tmux-workspace/bin:$PATH"

Check that it runs:

$ tmux-workspace --version

Save a workspace as workspace.yaml:

session_name: dev
windows:
  - window_name: editor
    window_index: 0
    layout: even-horizontal
    panes:
      - null
      - shell_command: echo ready

tmux-workspace load: build a session

load builds the workspace as a session. -d leaves it detached and -S selects the tmux socket. Choose an unused socket path for this example; an existing server on that path would receive the load:

$ mkdir -p /tmp/libtmux-java-dev
$ tmux-workspace load ./workspace.yaml \
    -S /tmp/libtmux-java-dev/workspace-example.sock \
    -d \
    --ndjson

It starts a tmux server on the unused socket and prints one JSON event per line. The last is a completed event with status ok, and the session dev now holds two panes.

Without -S or -L, LIBTMUX_SOCKET_PATH and then LIBTMUX_SOCKET choose the server. With neither set, no socket is passed and tmux picks: the server in TMUX from inside a pane, and its default socket otherwise.

Every layout is checked before any script runs or any session changes.

tmux-workspace freeze: capture a session

freeze writes a live session back out as a workspace:

$ tmux-workspace freeze dev \
    -S /tmp/libtmux-java-dev/workspace-example.sock \
    --json

It prints the workspace as one JSON document: session_name is dev, and the window lists two panes.

It recovers topology, directories, focus and options. It does not recover command history. Writing the capture to a file takes --save-to.

Find, convert, and import

tmux-workspace ls: what is saved

ls lists the workspaces in the current project and in the global configuration directory:

$ tmux-workspace ls

It prints one line for each workspace, its name and where it lives.

tmux-workspace search: find one by what is in it

search looks through names, paths, sessions, windows and pane commands. This finds the workspaces with editor in a window's name:

$ tmux-workspace search editor --field window

Every query must match unless you add --any.

tmux-workspace convert: YAML to JSON and back

convert rewrites a workspace file in the other format. It never runs the workspace:

$ tmux-workspace convert ./workspace.yaml --save-to ./workspace.json --yes

It asks before writing unless you pass --yes, and it keeps an existing file unless you pass --force.

tmux-workspace import: bring a tmuxinator or Teamocil file

import tmuxinator and import teamocil translate the other tool's file into a native workspace:

$ tmux-workspace import tmuxinator ./project.yml --save-to ./imported.yaml --yes

A field it cannot carry is rejected before anything is written.

Inspect a loaded workspace through MCP

A loaded workspace is an ordinary tmux session, so an agent can read it through libtmux-mcp. Build the launcher:

$ ./gradlew :libtmux-mcp:installDist \
    --max-workers=2 \
    --no-parallel

claude mcp add: read the socket load built

Register it on that socket, offering only the tools that read tmux:

$ claude mcp add tmux \
    -e LIBTMUX_TOOLSETS=inspect \
    -- libtmux-mcp/build/install/libtmux-mcp/bin/libtmux-mcp \
    --socket /tmp/libtmux-java-dev/workspace-example.sock

Another client launches the same program with the same arguments and environment variable. Use --socket-name when you loaded with -L.

Then the agent can:

Commands

command what it does reference
load builds workspaces in order, creating or reusing a session load
freeze captures a running session as a workspace file freeze
convert converts a workspace file between YAML and JSON convert
import tmuxinator, import teamocil translates another tool's file into a workspace import, tmuxinator, teamocil
ls lists the local project and global workspaces ls
search searches names, paths, sessions, windows and pane commands search
edit resolves a workspace and opens it in EDITOR edit
shell opens a Python shell on a session; needs Python with tmuxp 1.74.0 shell
debug-info reports runtime and configuration diagnostics debug-info
--generate writes the command schema or Bash, Zsh or Fish completion completion

What it leaves out

  • Rollback. A failed append reports what it kept and undoes nothing. Creating, reusing and appending has the rules.
  • tmuxp's layout and focus defaults. A window with no layout tiles its panes where tmuxp stacks them, and no focus keeps the first window active. Layouts and focus says why.
  • Unknown keys. Loading rejects a key it does not implement before it contacts tmux, except x- vendor extensions. Document rules has the rest.
  • Fields an import cannot carry. Hooks, project pre and post, endpoint overrides and the like are rejected. Imports lists them.
  • Python, unless you ask. Loading, capture, conversion, imports, discovery and search run on the JVM. Python covers the shell command, plugins and custom builders.

Support and status

  • JDK 25 or newer, and tmux 3.3a or newer.
  • Linux, including WSL. CI runs on Ubuntu. macOS is supported on a best-effort basis, and CI coverage for it is highly limited.
  • Releases. Releases are numbered 0.1.N, and each release increments N. The API is not settled: any release may change or remove exported identifiers, and the changelog marks each break. Pin an exact version to avoid one. Commands, flags and output records are part of the API.
  • Machine output. --json is one document and --ndjson one record per line. A failure names one code, and the exit status is 0, 1, 2 or 130. Output has the full contract.
  • Optional Python. Only shell, tmuxp plugins and custom builders need Python with tmuxp 1.74.0, named by TMUX_WORKSPACE_PYTHON, and a Python libtmux whose TMUX_OPTIONAL_FEATURE_POLICY_VERSION is 2 or more. No released libtmux has that yet; it comes with tmux-python/libtmux#780, so install libtmux from that source or skip those features.

Documentation