Optimal, opinionated, batteries-included TMUX that's neat and easy for any project.
A tmuxp wrapper that creates per-project tmux config directories with TPM and plugins pre-configured.
# run optmux anywhere (installs on first use via uv)
uvx optmux
# strongly recommended: install wtcode + lazygit for the full experience
brew install netj/tap/optmuxTry the included example:
git clone https://github.com/netj/optmux.git && cd optmux
./example.optmux.yamlOn first run, optmux will:
- Create
.example.optmux.d/tmux/next to the YAML file - Seed a default
tmux.confwith TPM and plugins - Install TPM and all plugins (visible in window 0)
- Launch tmuxp with an isolated tmux server
Supports .optmux.yaml, .tmuxp.yaml, and .optmuxp.yaml extensions:
optmux myproject.optmux.yaml
optmux myproject.tmuxp.yamloptmuxOpens plain tmux using .optmux.d/ in the current directory — useful for a quick, isolated tmux session with the bundled config.
Write a tmuxp YAML config with the optmux shebang line and make it executable:
#!/usr/bin/env -S uvx optmux
session_name: myproject
windows:
- window_name: editor
panes:
- vim .
- window_name: shell
panes:
- ""chmod +x myproject.optmux.yaml
./myproject.optmux.yamlHere's the included example.optmux.yaml showing shortcuts, tmux config, and window layout:
#!/usr/bin/env -S uvx optmux
session_name: example
start_directory: .
optmux:
shortcuts:
C-M-b: gh browse .
C-M-e:
command: ${VISUAL:-${EDITOR:-vim}} README.md # exec directly (default for str, no latency)
window: true # in a new-window
E:
send-keys: ${VISUAL:-${EDITOR:-vim}} . # send-keys (given command is run in a new shell)
zoom: false # do not zoom (defaults to zoom when split-window)
tmux_config:
project-settings: |
set -g status-style bg=blue
windows:
- window_name: editor
panes:
- vim .
- window_name: shell
panes:
- ""
- window_name: logs
panes:
- tail -f /var/log/system.logEach project gets its own .$NAME.optmux.d/ directory:
| Path | Purpose |
|---|---|
tmux/tmux.conf |
Main tmux config (editable after creation) |
tmux/tmux.*.conf |
Additional config files you can add |
tmux/tmux.sock |
Tmux server socket (isolates this project) |
tmux/plugins/ |
TPM plugin directory |
tmux/plugins-update.sh |
Run manually to update all plugins |
Add an optmux: section to your tmuxp YAML to configure shortcuts and tmux settings:
optmux:
shortcuts:
C-M-b: gh browse . # Ctrl-Alt-b: run command directly
C-M-e:
command: ${VISUAL:-${EDITOR:-vim}} README.md # exec directly (no shell)
window: true # open in a new-window
E:
send-keys: ${VISUAL:-${EDITOR:-vim}} . # send-keys (runs in a new shell)
zoom: false # do not zoom (default: true for splits)
tmux_config:
project-settings: |
set -g status-style bg=blueShortcuts bind tmux keys to commands:
C-M-*keys are bound globally (no prefix needed)- Other keys require the tmux prefix (
C-t) command:executes directly (default for string values)send-keys:sends the command to a new shell (supports shell expansion)window: trueopens in a new window instead of a splitzoom: falsedisables auto-zoom on splits (default: true)
Entries under tmux_config: are written as tmux.optmux-extras.{name}.conf files and auto-sourced by tmux.
Create ~/.optmux.yaml to define personal defaults that apply to all optmux sessions:
optmux:
shortcuts:
C-M-g: lazygit
tmux_config:
my-defaults: |
set -g status-style bg=greenPersonal config is merged with per-project config. When both define the same key, personal settings take precedence.
- Edit
tmux/tmux.confto change tmux settings - Drop
tmux/tmux.mysetup.conffiles for additional config (auto-sourced) - Run
tmux/plugins-update.shfrom inside tmux to update plugins - Press
prefix + Rto reload the config
optmux sets these before launching tmux/tmuxp:
| Variable | Value |
|---|---|
OPTMUX_DIR |
Absolute path to the .$NAME.optmux.d/ directory |
OPTMUX_NAME |
Name derived from YAML filename or cwd (e.g., myproject) |
TMUX_PLUGIN_MANAGER_PATH |
$OPTMUX_DIR/tmux/plugins |
# install the latest main branch
uvx git+https://github.com/netj/optmux.git
# local editable install for development
uv tool install -e .
# test any local changes directly (best for testing branches)
uv run optmux ./example.optmux.yaml
# run tests
uv run pytest # all tests
uv run pytest -m "not e2e" # skip E2E tests (no tmux needed)
uv run pytest -m e2e # E2E only (requires tmux)