Just another tmux session manager. Tmux 3.0+ is required.
If you have cargo
installed on your system:
console
$ cargo install airmux
console
$ AIRMUX_TARGET="x86_64-unknown-linux-gnu" # Check the list of available targets on the releases page
$ curl -o airmux -fsSL "https://github.com/dermoumi/airmux/releases/latest/download/airmux-$AIRMUX_TARGET"
$ chmod +x airmux
$ sudo mv airmux /usr/local/bin/
You can check the list of available targets in the releases page.
```
USAGE:
airmux [OPTIONS]
FLAGS: -h, --help Prints help information -V, --version Prints version information
OPTIONS: -c, --config-dir
SUBCOMMANDS: debug Print tmux source without actually running tmux edit Create or edit a project freeze Save current tmux session as a project file (commands not included) help Prints this message or the help of the given subcommand(s) kill Kill tmux session that matches the project list List all configured projects remove Remove a project (does not affect loaded tmux sessions) start Start a project as a tmux session ```
```yaml
workingdir: ~/projects/djangoproject/
oncreate: - >- # yaml-multiline.info docker run -itd --name r-redis --publish 16379:6379 redis || docker start r-redis - >- docker run -itd --name r-postgresql --publish 15432:5432 --env POSTGRESPASSWORD=hunter2 --volume $HOME/.postgresql:/var/lib/postgresql/13 postgresql:13 || docker start r-postgresql
on_stop: docker stop r-redis r-postgresql
pane_commands: source .venv/bin/activate
windows: # First window contains 3 panes: an empty shell, the dev server output and the worker output - main: panes: - - split: v # Split previous pane by half, vertically command: python manage.py runserver - split: h # split previous pane by half, horizontally command: python celery --app django_project worker # Second window contains logs of the previously run docker containers - container-logs: panes: - docker logs -f r-postgresql - docker logs -f r-redis ```
console
$ airmux start my_project [param1 [param2...]]
Parameters are accessible in the project file as $1
, $2
, etc...
Create or edit projects using:
console
$ airmux edit <my_project>
The default editor ($EDITOR
) is used to open the file.
You can use the --editor
option to specify which editor to use:
console
$ airmux edit --editor="code -w" my_project
All the fields are optional, but at least one is required.
```yaml
session_name:
--command
when running airmuxtmux_command: tmux
tmux_options:
-L <socket_name>
to tmux_options
tmux_socket:
working_dir:
windowbaseindex: 1
panebaseindex: 1
startup_window:
startup_pane:
on_start:
onfirststart:
on_restart:
on_exit:
on_stop:
post_create:
onpanecreate:
postpanecreate:
pane_commands:
attach: true detached: false
windows:
Commands can be written either as a string or as a list of strings:
```yaml
on_start: echo command1
on_stop: - echo command2 - echo command3 - echo command4 ```
Note: Airmux will always remove \r
characters and replace \n
with a space character (),
even if you don't use the correct yaml multiline syntax.
All commands are executed regardless of the exit status of the previous command.
All the fields are optional, but at least one is required.
```yaml
windows:
# Window names should not contain dots (.) and colons (:)
# You can have multiple windows with the same name
# It can also have a null (~) name, in which case it'll use default tmux behavior
- window1name:
# Working directory for the window (alias: root)
# If declared and left empty or set to ~ (null in Json), defaults to $HOME instead.
working_dir:
# Layout, can be: even-horizontal, even-vertical, main-horizontal, main-vertical, tiled
# Or a custom layout, see `Layouts` section for details. Can't use with custom pane splits.
layout: <no_layout>
# Shell commands to execute when a window is created (before child pane panes are configured)
# Available substitutions: __TMUX__, __SESSION__, __WINDOW__
on_create:
# Shell commands to execute after a window is created (after all child panes are configured)
# Available substitutions: __TMUX__, __SESSION__, __WINDOW__
post_create:
# Shell commands to execute when a pane is created (before pane_commands are typed in)
# Available substitutions: __TMUX__, __SESSION__, __WINDOW__, __PANE__
on_pane_create:
# Shell commands to execute after a pane is created (after pane_commands are typed in)
# Available substitutions: __TMUX__, __SESSION__, __WINDOW__, __PANE__
post_pane_create:
# Commands that are executed in the shell of each pane (alias: pre, pane_command)
pane_commands:
# List of panes
panes: <default empty pane>
```
Windows can also be defined as a single command or multiple commands (one for each pane):
yaml
windows:
- echo "single pane nameless window"
- single_pane: "single pane named window"
- ~:
- echo "pane 1 of a nameless window"
- echo "pane 2 of a nameless window"
- multiple_panes:
- echo "pane 1 of a named window"
- echo "pane 2 of a named window"
Also, window definition fields can be at the same level as the name, as long as it is the first key:
yaml:
windows:
- window_name:
layout: main-vertical
panes:
- echo cmd1
- echo cmd2
You can also override the window name with the name
(alias: title
) field:
yaml:
windows:
- layout: main-vertical
name: ~
panes:
- echo cmd1
- echo cmd2
```yaml
panes:
- # Working directory for the pane (alias: root)
# If declared and left empty or set to ~ (null in Json), defaults to $HOME instead.
working_dir:
# The pane to split from when creating this one. Does not apply to the first pane.
# These indexes follow the same order as in the project file and always start with pane_base_index
split_from: <previous pane>
# How to split when creating this pane (v, vertical, h, horizontal)
split: horizontal
# Size of this pane (number of columns/rows or a percentage)
split_size: 50%
# Whether or not to send a clear combination (Ctrl+L) after typing the pane commands
clear: false
# Shell commands to execute when a pane is created (before pane_commands are typed in)
# Available substitutions: __TMUX__, __SESSION__, __WINDOW__
on_create:
# Shell commands to execute after a pane is created (before pane_commands are typed in)
# Available substitutions: __TMUX__, __SESSION__, __WINDOW__
post_create:
# Commands to type and run in this pane's shell (alias: command)
commands:
```
Aside from the 5 default layouts, you can also supply a custom layout:
yaml
windows:
- layout: 'fc16,277x30,0,0{137x30,0,0,2,139x30,138,0,3}'
You can read more about custom layouts on the Tao of tmux
When using a layout on a window, all split
and split_size
cannot be used on the underlying panes.
The project file supports expansion of variables (anywhere, not just string values)
yaml
windows:
# Expanding the User environment variable
- $USER:
# Alternative syntax, allows you to use mid-words
- ${EDITOR}_window:
# Expansion with a fallback value for when the variable is not set
- ${SOME_VAR:-fallback_value}:
This also means that whenever you need to write $
you'll need to escape as $$
.
Furthermore, any extra values passed to airmux start
or airmux kill
are available as $1
, $2
, etc...
yaml
windows:
- pipenv run server ${1:-8000}
```bash
$ airmux start my_project 8080 ```
Commands that accept a project name can be called without it to use a local .airmux.(yml|yaml|json)
project file
instead.
If no local project file exists, Airmux will look into each ancestor to the current working directory until it finds one.
Otherwise, it will default to .airmux.yml
on the current directory.
You can specify the extension of the local project file when creating it:
console
$ airmux edit --ext json
console
$ airmux list
console
$ airmux kill my_project
console
$ airmux remove my_project
console
$ airmux debug my_project
Prints all the commands that are passed to tmux source
to create the session, complete with hooks and everything.
You can save the output and use it directly without passing through airmux
.
As long as the tmux server is already running. Also, it never attaches the session.
console
$ airmux debug my_project | tmux source
console
$ airmux freeze my_project
It will prompt you for confirmation before overriding an existing project, unless --no-input
flag is passed.
You can also print the project file to stdout instead of opening a text editor:
console
$ airmux freeze --stdout