tmux and tmuxp session configuration, management, and troubleshooting. Use when creating, editing, debugging, or optimizing tmuxp YAML configs, designing tmux workspace layouts, fixing tmux session errors, managing multi-environment terminal setups, or working with tmux panes, windows, and sessions. Also use when the user mentions tmuxp, .tmuxp, tmux layouts, session_name, or terminal workspace organization.

GitHub
Install command
npx skhub add julianobarbosa/tmux
Markdown
SKILL.md

tmux & tmuxp Skill

Create, edit, debug, and optimize tmux sessions via tmuxp YAML configurations.

Quick Decisions

TaskApproach
New project workspaceCreate tmuxp YAML from template
Fix session load errorCheck session_name, YAML syntax, tool availability
Multi-environment K8sUse environment vars + per-env windows with safety guards
Simple dev setup2-3 windows: editor, server, terminal
Complex infrabefore_script validation + helper scripts + monitoring windows
Capture existing layouttmuxp freeze then clean up the output

Session Name Rules

tmux session names cannot contain periods (.) or colons (:).

Common pitfall: using ${USER} in session_name when the username contains periods (e.g., first.last). Always use a static name or sanitize:

# BAD - breaks if USER contains periods
session_name: ${USER}-project

# GOOD - static name
session_name: project-dev

# GOOD - sanitized
session_name: project-${USER//\./-}

Configuration Structure

session_name: project-name          # Required. No periods or colons.
start_directory: ~/Projects/foo     # Default working dir for all windows
environment:                        # Session-wide env vars
  PROJECT_ROOT: ~/Projects/foo
suppress_history: false             # Whether to hide commands from shell history

before_script: |                    # Runs before session creation. Exit 1 = abort.
  echo "Validating..."

after_script: |                     # Runs after session is destroyed
  echo "Cleaning up..."

windows:
  - window_name: editor             # Window identifier
    focus: true                     # Make this the active window on load
    layout: main-vertical           # Pane layout
    start_directory: ~/Projects/foo/src
    options:
      main-pane-width: 70%          # Layout-specific options
    shell_command_before:            # Runs in ALL panes before pane commands
      - source ~/.zshrc
    panes:
      - focus: true                 # Active pane within window
        shell_command:
          - vim .
      - shell_command:
          - npm test -- --watch

Layouts

LayoutUse ForPane Arrangement
main-verticalEditor + sidebarsLarge left, stacked right
main-horizontalLogs + statusLarge top, split bottom
even-horizontalEqual side-by-sideEqual horizontal splits
even-verticalEqual stackedEqual vertical splits
tiledMonitoring dashboardsGrid of equal panes

Control main pane size via options:

options:
  main-pane-width: 70%    # For main-vertical
  main-pane-height: 65%   # For main-horizontal

Capture a custom layout from a running session:

tmux display-message -p '#{window_layout}'
# Returns: "bb62,159x48,0,0{79x48,0,0,79x48,80,0}"

Pane Definitions

panes:
  # Simple command
  - vim README.md

  # Multiple commands
  - shell_command:
      - cd ~/project
      - source .venv/bin/activate
      - python app.py

  # Empty pane
  - null     # or: blank, pane

  # With focus
  - focus: true
    shell_command:
      - k9s

Environment Variables

environment:
  # Static values
  PROJECT_NAME: my-app

  # Reference existing vars (expanded at load time)
  HOME_DIR: ${HOME}

  # Multi-environment pattern
  K8S_CTX_DEV: aks-myapp-dev
  K8S_CTX_STG: aks-myapp-stg
  K8S_CTX_PRD: aks-myapp-prd

  # Defaults
  EDITOR: ${EDITOR:-vim}

Never hardcode secrets. Reference env vars from the shell: ${AZURE_SUBSCRIPTION_ID}.

before_script Validation

Use before_script to validate prerequisites. Exit 1 aborts session creation:

before_script: |
  # Check project exists
  [ -d "$PROJECT_ROOT" ] || { echo "Project not found"; exit 1; }

  # Check required tools
  for tool in kubectl terraform docker; do
    command -v $tool >/dev/null || echo "Warning: $tool not found"
  done

  # Check connectivity
  kubectl cluster-info >/dev/null 2>&1 || echo "Warning: Cannot reach cluster"

Production Safety Patterns

Protect production environments with read-only access and warnings:

- window_name: k8s-prod
  panes:
    - shell_command:
        - echo "PRODUCTION - READ-ONLY ACCESS"
        - echo "DO NOT use: apply, delete, edit, patch"
        - kubectl config use-context $K8S_CTX_PRD
        - k9s --readonly

CLI Commands

tmuxp load config-name          # Load from ~/.tmuxp/
tmuxp load ./path/to/file.yaml  # Load from path
tmuxp load -y config-name       # Skip confirmation prompt
tmuxp load -d config-name       # Load detached (background)
tmuxp ls                        # List available configs
tmuxp freeze session-name       # Capture running session to YAML
tmuxp convert file.json         # Convert JSON config to YAML
tmuxp edit config-name          # Edit config in $EDITOR
tmuxp debug-info                # Show environment info

Troubleshooting

ErrorCauseFix
BadSessionName: contains periodssession_name has . (often from ${USER})Remove ${USER} prefix or sanitize
BadSessionName: contains colonssession_name has :Remove colons from name
Session already existsDuplicate session_nameKill old: tmux kill-session -t name
Commands not executingShell compatibilityTest commands manually first
Layout brokenTerminal too small for layoutUse predefined layouts or test with tmuxp load -d
Env vars not expandingWrong syntaxUse ${VAR} not $VAR in YAML values

Debug: tmuxp -v load config.yaml for verbose output.

References

Workflow: Create New Config

  1. Identify the project type (dev, infra, monitoring, mixed)
  2. Choose a template from templates/
  3. Set session_name (no periods/colons), start_directory, environment vars
  4. Design windows by function (editor, server, logs, k8s, etc.)
  5. Pick layouts matching each window's purpose
  6. Add before_script validation if the project has external dependencies
  7. Add production safety guards for any prod-access windows
  8. Test: tmuxp load -d config.yaml then tmux attach -t session-name

Gotchas

  • Session names with periods break the unix-socket path: ${USER} containing . (e.g. first.last) produces BadSessionName because tmux uses the name in /tmp/tmux-UID/ socket path. Use a static name or ${USER//\./-} sanitization.
  • before_script runs in a fresh shell, not your interactive zsh: Aliases, functions, and .zshrc-sourced env vars are absent. command -v works but myalias does not. Source ~/.zshrc explicitly if you depend on it.
  • shell_command_before runs in EVERY pane of the window: Heavy commands (sourcing 500ms+ of zsh config, activating venvs) multiply latency — a 4-pane window adds ~2s to session load. Use per-pane shell_command instead when only one pane needs it.
  • tmuxp freeze captures live state, not intent: Output includes the random working directories, history-expanded commands, and the literal pane sizes — review and clean before committing. Frozen YAML is a starting point, not a finished config.
  • Env var expansion happens at YAML load, not pane start: environment: FOO: ${BAR} resolves $BAR from the shell that invoked tmuxp load. If $BAR is unset there, it stays empty even if a later pane defines it.
  • focus: true on multiple panes silently picks the last one: No error, no warning — the file just looks misconfigured at runtime. Validate with grep -c "focus: true" per window before debugging.
Discovery
Tags

No tags published for this skill.

Version
Latest version metadata

Version

v2026.09.24

Published

Sep 24, 2026

Category

Uncategorized

License

MIT

Source path

skills/tmux

Default branch

main

Latest commit

515755d

Tree SHA

fca30ca