Migrating
Coming from tmuxp
Translate a tmuxp YAML or JSON workspace into a glaze profile, block by block.
tmuxp has been at this for well over a decade. It has a freeze command that predates glaze save by years, a Python library underneath for the day a YAML file is not enough and a config format that has grown a key for nearly every situation. If it works for you, keep using it. I am not here to convince anyone. But if you want to try a .glaze file, and you already have a directory of workspaces, this page translates one into the other block by block, and it is honest about the places where the two tools simply do not line up.
A typical workspace
A tmuxp workspace with the usual parts:
session_name: daemon-run
start_directory: ~/runs/arasaka
before_script: ./bootstrap.sh
suppress_history: true
environment:
ICE_TARGET: arasaka-mainframe
options:
main-pane-height: 30
windows:
- window_name: editor
layout: main-vertical
focus: true
shell_command_before:
- nvm use 20
panes:
- shell_command:
- npm install
- npm run dev
- nvim .
- window_name: logs
layout: even-horizontal
panes:
- tail -f logs/dev.log
- htopThe same workspace as a profile:
locals {
setup = "nvm use 20"
}
session {
name = "daemon-run"
starting_directory = "~/runs/arasaka"
envs = {
ICE_TARGET = "arasaka-mainframe"
}
options = {
"main-pane-height" = "30"
}
window {
name = "editor"
layout = "main-vertical"
focus = true
pane {
commands = [local.setup, "npm install", "npm run dev"]
}
pane {
commands = [local.setup, "nvim ."]
}
}
window {
name = "logs"
layout = "even-horizontal"
pane {
commands = ["tail -f logs/dev.log"]
}
pane {
commands = ["htop"]
}
}
}before_script is not in the profile. It runs before glaze up instead. See below.
The translation table
| tmuxp | glaze | Notes |
|---|---|---|
session_name | session.name | Glazier replaces ., :, $ and a backslash with - and shows a warning. |
start_directory | starting_directory | On the session or the window, as in tmuxp. ~ expands. A relative path is relative to the directory of the profile. |
windows[].window_name | window.name | |
layout | window.layout | The same five tmux presets. A raw layout string also works in both tools. |
focus | focus = true | On a window or a pane, as in tmuxp. |
panes[] as a string | pane.commands | A list with one command. |
panes[].shell_command | pane.commands | A list, in order. Glazier waits for each command except the last. |
panes[] as null, pane or blank | pane {} | An empty pane block. |
environment | session.envs | Session only. See below. |
options | options | On the session or the window. Glazier sets each option where tmux keeps it. |
global_options | session.options | Not the same. See below. |
suppress_history | none | Glazier always does this. See below. |
shell_command_before | session.envs, or repeat the command | Not the same. See below. |
before_script | run it before glaze up | Not the same. See below. |
options_after | none | See below. |
window_index | none | Glazier has no index. It creates the windows in file order. |
sleep_before, sleep_after | none | Glazier waits for each command to complete. There are no sleeps. |
enter: false | none | |
tmuxp load daemon-run | glaze up | |
tmuxp freeze daemon-run | glaze save | save captures names, directories, focus and layout. It does not capture commands, envs, hooks or options. |
tmux kill-session -t daemon-run | glaze down | A session that is not running causes no error. |
The five layout presets are tmux presets in both tools: even-horizontal, even-vertical, main-horizontal, main-vertical and tiled. The default in Glazier is tiled.
What does not map one to one
shell_command_before. tmuxp runs these commands in every pane of the session or the window before the pane’s own commands. Glazier has no such hook. You have two options. When the command sets environment variables, put them in envs on the session: Glazier applies them before it creates any window or pane, so every shell inherits them. When the command does real work, for example nvm use 20, put it first in the commands of each pane. Yes, that means repeating it. The example above holds the string once in a locals block, so each pane reads local.setup. See Locals.
environment on a window or a pane. tmuxp sets a window or pane environment. Glazier accepts envs on the session only, because tmux gives a new variable only to the shells it starts after the variable is set, and a pane already has its shell by then. An earlier version of Glazier accepted envs on a window and a pane. It looked like it worked, and it did not. Put the variable on the session, or inline it in the command: EDITOR=nvim nvim .. See Environment.
global_options. tmuxp sets these globally, so they apply to the whole tmux server. Glazier never sets a global option. options on the session block goes to the session, and a window option in it goes to every window of the session. The option is in effect for this session only, which is what a project file usually means anyway. An option that must be global belongs in tmux.conf. See Hooks and options.
before_script. tmuxp runs this script before the session exists, and a non-zero exit stops the load. Glazier has commands on the session block, and they run in the active pane after Glazier creates all windows and panes. Nothing checks their exit status. For a script that must finish, and must succeed, before anything else, run it in your shell: ./bootstrap.sh && glaze up. See Session and Scripting.
suppress_history. You can drop this key. Glazier does not type the commands into the pane. It loads them into a tmux paste buffer and types one line that starts with a space, so a shell that ignores such lines does not keep it in the history. There is no switch to turn it off. See Run commands reliably.
options_after. tmuxp has this key for one job: synchronize-panes after the panes exist. Glazier applies window options before it runs the pane commands, and tmux then types each command line into every pane of the window. A command runs twice and a pane reports a missing buffer. So:
warning
Do not set synchronize-panes in options on a window whose panes have commands.
Set it on a window whose panes have no commands, or turn it on by hand after up with tmux set-option -w synchronize-panes on.
Differences in the workflow
- tmuxp keeps workspaces in
$TMUXP_CONFIGDIR,~/.config/tmuxp/or~/.tmuxp/, andloadalso takes a path. Glazier looks for.glazein the current directory, then in$GLAZE_PATH, or where--profile-pathpoints. A profile lives with the project, so it goes into the repository. See Profile resolution. - tmuxp reads YAML and JSON and converts between them. A profile is HCL only. There is no converter, which is why this page exists.
- tmuxp replaces
${VAR}in a few keys from the environment. Glazier hasenv.*fromGLAZE_ENV_*variables, typedvariableblocks and--varflags, so one profile serves many projects. See Variables and One profile for many projects. - Glazier waits for each pane command except the last with
tmux wait-for, sonpm installfinishes beforenpm run devstarts. There are no fixed sleeps. See Run commands reliably.
Check the translation
Run glaze format --validate before the first glaze up. It decodes the profile and reports each problem that it can find, with the file and the line, before tmux starts:
$ glaze format --validate --stdout > /dev/null
Error: Invalid layout specified
on /home/v/runs/arasaka/.glaze line 9, in session:
9: layout = "main-diagonal"
The layout value of "main-diagonal" is not a supported preset
(even-horizontal, even-vertical, main-horizontal, main-vertical, tiled) nor a
valid tmux layout string.
the glaze profile contains errors
Without --stdout, format also rewrites the profile into the canonical form, which is a fine first step for a file you just typed by hand. See glaze format.
Two files, same workspace. Keep the one you prefer.