Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -88,3 +88,7 @@ docs/_static/css/fonts.css
**/CLAUDE.local.md
**/CLAUDE.*.md
**/.claude/settings.local.json
.claude/commands/

# Development notes
notes/
1 change: 1 addition & 0 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -201,6 +201,7 @@ Pass structured data on every log call where useful for filtering, searching, or
| `tmux_pane` | `str` | pane identifier |
| `tmux_config_path` | `str` | workspace config file path |
| `tmux_layout` | `str` | window layout string |
| `tmux_hook_cmd` | `str` | lifecycle hook shell command line |

**Heavy/optional keys** (DEBUG only, potentially large):

Expand Down
77 changes: 77 additions & 0 deletions CHANGES
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,83 @@ $ tmuxp@next load yoursession
_Notes on the upcoming release will go here._
<!-- END PLACEHOLDER - ADD NEW CHANGELOG ENTRIES BELOW THIS LINE -->

tmuxp 1.71.0 brings tmuxp to feature parity with tmuxinator and
teamocil. Sessions can be managed end to end from the CLI (`stop`,
`new`, `copy`, `delete`), workspace configs gain lifecycle hooks,
`{{ variable }}` templating, and pane titles, and `tmuxp load` learns
`--here` and friends. Imports from tmuxinator and teamocil now convert
much more of an existing config. See {doc}`comparison` for a
side-by-side of all three tools.

### What's new

#### `tmuxp stop` — kill a session with cleanup (#1025)

Stop a running session by name. The `on_project_stop` lifecycle hook
runs before the session is killed, giving your project a chance to
clean up. See {ref}`cli-stop`.

```console
$ tmuxp stop mysession
```

#### `tmuxp new`, `tmuxp copy`, `tmuxp delete` — manage workspace configs (#1025)

Create a workspace config from a starter template and open it in
`$EDITOR`, duplicate an existing config under a new name, or delete
configs (with a confirmation prompt unless `-y` is passed).

```console
$ tmuxp new myproject
```

#### Lifecycle hooks (#1025)

Workspace configs support four hooks, modeled on tmuxinator's:

- `on_project_start` — before a new session is built
- `on_project_restart` — after you confirm reattaching to an existing session
- `on_project_exit` — when the last client detaches
- `on_project_stop` — before `tmuxp stop` kills the session

See {ref}`top-level` for examples.

#### Config templating with `--set` (#1025)

Workspace configs may contain `{{ variable }}` placeholders, filled at
load time:

```console
$ tmuxp load --set project=myapp mytemplate.yaml
```

#### Pane titles (#1025)

Session-level `enable_pane_titles`, `pane_title_position`, and
`pane_title_format` keys turn on tmux pane border titles; a pane-level
`title` key names individual panes.

#### New window keys: `synchronize`, `shell_command_after`, `clear` (#1025)

`synchronize: before/after/true` mirrors keystrokes across a window's
panes; `shell_command_after` runs commands in every pane after the
window is built; `clear: true` clears each pane once its commands
complete.

#### New `tmuxp load` flags (#1025)

- `--here` — build the workspace in your current tmux window instead of a new session
- `--no-shell-command-before` — skip all `shell_command_before` entries
- `--debug` — show each tmux command as it executes
- `--set KEY=VALUE` — fill config template variables

#### Broader tmuxinator and teamocil imports (#1025)

`tmuxp import` now converts lifecycle hooks, named panes, startup
window/pane focus, synchronized windows, and tmux CLI arguments from
tmuxinator configs, and recognizes teamocil's v1.x format. See
{ref}`cli-import` for the full key mappings.

## tmuxp 1.70.0 (2026-05-23)

tmuxp 1.70.0 bumps libtmux to 0.58.0, fixing session and window listing on systems whose locale is not UTF-8.
Expand Down
3 changes: 3 additions & 0 deletions conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,9 @@ def socket_name(request: pytest.FixtureRequest) -> str:

# Modules that actually need tmux fixtures in their doctests
DOCTEST_NEEDS_TMUX = {
"tmuxp.cli.load",
"tmuxp.cli.stop",
"tmuxp.util",
"tmuxp.workspace.builder",
}

Expand Down
25 changes: 25 additions & 0 deletions docs/cli/copy.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
(cli-copy)=

(cli-copy-reference)=

# tmuxp copy

Copy an existing workspace config to a new name. Source is resolved using the same logic as `tmuxp load` (supports names, paths, and extensions).

## Command

```{eval-rst}
.. argparse::
:module: tmuxp.cli
:func: create_parser
:prog: tmuxp
:path: copy
```

## Basic usage

Copy a workspace:

```console
$ tmuxp copy myproject myproject-backup
```
41 changes: 41 additions & 0 deletions docs/cli/delete.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
(cli-delete)=

(cli-delete-reference)=

# tmuxp delete

Delete one or more workspace config files. Prompts for confirmation unless `-y` is passed.

## Command

```{eval-rst}
.. argparse::
:module: tmuxp.cli
:func: create_parser
:prog: tmuxp
:path: delete
```

## Basic usage

Delete a workspace:

```console
$ tmuxp delete old-project
```

Delete without confirmation:

```console
$ tmuxp delete -y old-project
```

Delete multiple workspaces:

```console
$ tmuxp delete proj1 proj2
```

```{note}
Only workspace files are deletable: the resolved path must end in `.yaml`, `.yml`, or `.json`. Any other file is refused and the command exits with code 1.
```
18 changes: 18 additions & 0 deletions docs/cli/import.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,14 @@ $ tmuxp import teamocil /path/to/file.json

````

### Supported teamocil features

The teamocil importer handles:

- **v1.x format** — `windows` at top level with `commands` key in panes
- **Focus** — `focus: true` on windows and panes is preserved
- **Window options** — `options` on windows are passed through

(import-tmuxinator)=

## From tmuxinator
Expand Down Expand Up @@ -71,3 +79,13 @@ $ tmuxp import tmuxinator /path/to/file.json
```

````

### Supported tmuxinator features

The tmuxinator importer maps:

- **Hook mapping** — `pre` maps to `on_project_start`, `pre_window` maps to `shell_command_before`
- **CLI args** — `cli_args` values (`-f`, `-S`, `-L`) are parsed into tmuxp config equivalents
- **Synchronize** — `synchronize` window key is converted
- **Startup focus** — `startup_window` / `startup_pane` convert to `focus: true`
- **Named panes** — hash-key pane syntax converts to `title` on the pane
4 changes: 4 additions & 0 deletions docs/cli/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ load
shell
ls
search
stop
```

```{toctree}
Expand All @@ -63,6 +64,9 @@ edit
import
convert
freeze
new
copy
delete
```

```{toctree}
Expand Down
64 changes: 64 additions & 0 deletions docs/cli/load.md
Original file line number Diff line number Diff line change
Expand Up @@ -253,3 +253,67 @@ When progress is disabled, logging flows normally to the terminal and no spinner
### Before-script behavior

During `before_script` execution, the progress bar shows a marching animation and a ⏸ status icon, indicating that tmuxp is waiting for the script to finish before continuing with pane creation.

## Here mode

The `--here` flag reuses the current tmux window instead of creating a new session. This is similar to teamocil's `--here` flag.

```console
$ tmuxp load --here .
```

When used, tmuxp builds the workspace panes inside the current window rather than spawning a new session.

`--here` only supports a single workspace file per invocation.

```{note}
When `--here` needs to provision a directory, environment, or shell, tmuxp uses tmux primitives instead of typing `cd` / `export` into the pane. The pane tmuxp itself runs in is never respawned (that would kill the build mid-flight): there the directory is provisioned with a quoted `cd`, environment variables land in the tmux session environment (inherited by the panes the build creates, not the already-running shell), and `window_shell` is skipped with a warning. Any other reused pane is provisioned with `respawn-pane`, which replaces the pane's process before the workspace commands run — long-running child processes in that pane will be terminated.
```

## Skipping shell_command_before

The `--no-shell-command-before` flag skips all `shell_command_before` entries at every level (session, window, pane). This is useful for quick reloads when the setup commands (virtualenv activation, etc.) are already active.

```console
$ tmuxp load --no-shell-command-before myproject
```

```{note}
This flag is intentionally broader than tmuxinator's `--no-pre-window`, which only disables the window-level `pre_window` chain. tmuxp's flag strips `shell_command_before` at all levels for a clean reload experience.
```

## Debug mode

The `--debug` flag shows tmux commands as they execute. This disables the progress spinner and attaches a debug handler to libtmux's logger, printing each tmux command to stdout.

```console
$ tmuxp load --debug myproject
```

## Config templating

Workspace configs support simple `{{ variable }}` placeholders for variable substitution. Pass values via `--set KEY=VALUE`:

```console
$ tmuxp load --set project=myapp mytemplate.yaml
```

Multiple variables can be passed:

```console
$ tmuxp load --set project=myapp --set env=staging mytemplate.yaml
```

In the config file, use double-brace syntax:

```yaml
session_name: "{{ project }}"
windows:
- window_name: "{{ project }}-main"
panes:
- echo "Working on {{ project }}"
```

```{note}
Values containing `{{ }}` must be quoted in YAML to avoid parse errors.
```
25 changes: 25 additions & 0 deletions docs/cli/new.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
(cli-new)=

(cli-new-reference)=

# tmuxp new

Create a new workspace configuration file from a minimal template and open it in `$EDITOR`. If the workspace already exists, it opens for editing.

## Command

```{eval-rst}
.. argparse::
:module: tmuxp.cli
:func: create_parser
:prog: tmuxp
:path: new
```

## Basic usage

Create a new workspace:

```console
$ tmuxp new myproject
```
37 changes: 37 additions & 0 deletions docs/cli/stop.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
(cli-stop)=

(cli-stop-reference)=

# tmuxp stop

Stop (kill) a running tmux session. If `on_project_stop` is defined in the workspace config, that hook runs before the session is killed.

## Command

```{eval-rst}
.. argparse::
:module: tmuxp.cli
:func: create_parser
:prog: tmuxp
:path: stop
```

## Basic usage

Stop a session by name:

```console
$ tmuxp stop mysession
```

Stop the currently attached session:

```console
$ tmuxp stop
```

Use a custom socket:

```console
$ tmuxp stop -L mysocket mysession
```
Loading
Loading