Documentation

Every other tmux session manager I have used types your commands into the pane and hopes the shell does what you meant. Glazier used to do that too. It was fine right up until a command contained a ! or started with a - or ran longer than the line editor felt like accepting. This page is the terse reference for what Glazier does instead. The walkthrough with the war stories is Run commands reliably.

Where commands run

BlockWhere the commands run
paneIn the shell of that pane, in order.
sessionIn the active pane of the session, after Glazier creates all windows and panes.

Both lists follow the same rules.

Order and waiting

  1. Glazier creates every pane of a window before it runs any command in that window.
  2. Glazier runs the commands of a pane in file order.
  3. Each command completes before Glazier sends the next one. tmux wait-for sequences them. There are no fixed sleeps.
  4. Glazier does not wait for the final command in a list. Thus a long-running or interactive final command, for example nvim or a dev server, does not block the creation of the session.
  5. Glazier configures the next pane after the wait for the current pane ends.

By default, Glazier waits with no time limit, because a setup command such as npm install can be slow. If the shell of the pane exits, Glazier stops the wait. Use --command-timeout <duration> on glaze up, for example 5m, to set a limit. The default value 0 waits with no limit. In both cases Glazier shows a warning and continues with the next pane.

tip

Put the command that must keep running last. Everything before it must exit, or the wait does not end.

Delivery

Glazier does not type the commands into the pane. It loads them into a tmux paste buffer. Then it types one line that tells the shell of the pane to run the buffer:

Shell
eval "$('/usr/bin/tmux' -S '/tmp/tmux-1000/default' show-buffer -b glaze-3f9c0e1a7b2d4c68)"

The rules that follow from this:

  • The shell runs each command exactly as you wrote it. The line editor of the shell does not see the commands, so !, a tab, a leading - and a long line do not change.
  • The commands run in the shell of the pane, so cd and export stay in effect for the commands after them.
  • Each command runs in its own eval. A command with a syntax error fails alone, and the commands after it still run.
  • The line starts with a space, so a shell that ignores such lines does not keep it in the history.
  • The tmux path and the socket path in the line are absolute. A PATH or a TMUX value in your environment cannot break the sequence.
  • Glazier sends the buffer to tmux on stdin, so the commands do not appear in the process list. The first line of the buffer deletes the buffer. Each buffer has a random name.

Shell detection

Glazier finds the shell of the pane from the tmux options default-command and default-shell, in that order.

ShellForm
sh, bash, dash, ash, ksh, mksh, yash, busyboxThe POSIX form above.
zshThe POSIX form above.
fish`eval (…
Any other shellThe POSIX form, with one warning.

Glazier tests the sequence on bash, zsh, dash, busybox ash and fish. An exotic shell is out of scope by decision.

Logging

At the default log level, up shows only how many commands it runs in each pane. With --debug, it also shows the text of each command. A command can contain a secret from a variable, so check --debug output before you share it. See Environment for how env values are handled.

note

The eval runs only the commands from your profile. Earlier versions of Glazier typed the same commands into the pane. Thus the trust model does not change: a person who can change your profile can run commands in your panes. Only a client with access to your tmux socket can read or change a buffer, and such a client can already type into your panes.

Why a paste buffer and not a temp file or a straight send-keys? Typed keys go through the line editor, and five shells have five opinions about what !, a tab or a trailing ; means. A file on disk would work but leaves your commands lying around. The buffer lives inside tmux, deletes itself on first use and never touches the line editor. It took a spike of thirty five test cases across five shells to settle on it ( typed delivery failed nine, the buffer failed none ), which is a lot of effort to make echo hi! work. Worth it.