Documentation

tmuxinator has been doing this job well for far longer than Glazier has existed. 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 stack of .yml projects, this page translates one into the other block by block, and it is honest about the three places where the two tools simply do not line up.

A typical project

A tmuxinator project with the usual parts:

~/.config/tmuxinator/daemon-run.yml YAML
name: daemon-run
root: ~/runs/arasaka

on_project_start: docker compose up -d
pre_window: export ICE_TARGET=arasaka-mainframe
startup_window: editor

windows:
  - editor:
      layout: main-vertical
      panes:
        - nvim .
        - npm run dev
  - logs:
      layout: even-horizontal
      panes:
        - tail -f logs/dev.log
        - htop

The same workspace as a profile:

.glaze HCL
session {
  name               = "daemon-run"
  starting_directory = "~/runs/arasaka"
  commands           = ["docker compose up -d"]

  envs = {
    ICE_TARGET = "arasaka-mainframe"
  }

  window {
    name   = "editor"
    layout = "main-vertical"
    focus  = true

    pane {
      commands = ["nvim ."]
    }

    pane {
      commands = ["npm run dev"]
    }
  }

  window {
    name   = "logs"
    layout = "even-horizontal"

    pane {
      commands = ["tail -f logs/dev.log"]
    }

    pane {
      commands = ["htop"]
    }
  }
}

The translation table

tmuxinatorglazeNotes
namesession.nameGlazier replaces ., :, $ and a backslash with - and shows a warning.
rootsession.starting_directory~ expands. A relative path is relative to the directory of the profile.
windows[].<name>window.nameA window has no label. The name is an attribute.
layoutwindow.layoutThe same five tmux presets. A raw layout string also works in both tools.
panes[] as a stringpane.commandsA list, so one pane can run several commands in order.
startup_windowfocus = true on the windowGlazier has no index. Set the flag on the window block.
startup_panefocus = true on the pane
on_project_startsession.commandsNot the same. See below.
pre_windowsession.envs, or repeat the commandNot the same. See below.
synchronizenoneSee below.
tmuxinator start daemon-runglaze up
tmuxinator stop daemon-runglaze downA 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

pre_window. tmuxinator runs this command in every pane 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. That is what the example above does. 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. A locals block can hold the string once, so each pane reads local.setup. See Locals.

on_project_start. tmuxinator runs this before the session exists. Glazier has commands on the session block, and they run in the active pane after Glazier creates all windows and panes. The command runs, but later, and in a pane that you can see. tmux hooks are the other candidate, but a hook is a tmux command bound to a tmux event, not a shell command, and a session-created hook that Glazier sets fires only for sessions that tmux creates later. For a command that must finish before anything else, run it before glaze up in your shell. See Session and Hooks and options.

synchronize. Glazier has no synchronised panes. The tmux window option synchronize-panes exists, and options can set it, but 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

  • tmuxinator keeps projects in ~/.config/tmuxinator/. Glazier looks for .glaze in the current directory, then in $GLAZE_PATH, or where --profile-path points. A profile lives with the project, so it goes into the repository. See Profile resolution.
  • Glazier has typed variable blocks and --var flags, so one profile serves many projects. See One profile for many projects.
  • Glazier waits for each pane command except the last with tmux wait-for, so npm install finishes before npm run dev starts. 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:

Console
$ 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.