How can I run a chain of command like in shells with tmux? I want to run multiple commands based on success of them. I want to echo out to terminal (or command bar)

E.g. I have a keybinding to reload config as follow. And I also want to output reloaded to tell use it happened. But this shows error for source-file when I trigger it.

bind r source-file ~/.tmux.conf   # works fine
bind r source-file ~/.tmux.conf && echo reloaded.   # doesn't work shows source-file help in command bar.
bind r source-file ~/.tmux.conf; echo reloaded.  # doesn't work, says not recognized 'echo'

And what shell will this command be called on? Default shell or current shell or foreground program running in tab/window/pane? My default shell is fish.

  • Note: the title says "pipe" but && you were trying to use does not build a pipe in a shell. Jul 1, 2020 at 21:51
  • @KamilMaciorowski Yeah it's difficult to convery everything in a few words so chose those words. I did try pipe ... | echo reloaded. but it also fails the say way as second one.
    – user14492
    Jul 2, 2020 at 7:13
  • Piping to echo makes no sense, even in a shell where it throws no error. Jul 2, 2020 at 7:15

1 Answer 1


What you specify after bind r should be one or more tmux commands (with or without arguments). source-file ~/.tmux.conf is a valid tmux command. source-file ~/.tmux.conf && echo reloaded. is not. To run more than one tmux command you need to use ; (sometimes in a form of \;, see Binding a tmux key to multiple commands for details). But echo is not a tmux command.

There is however the run-shell tmux command that allows you to run arbitrary code in a shell. My tests tell me the shell is sh (even if my command interpreter is not sh). The manual confirms:

shell-command arguments are sh(1) commands.

To run source-file from a shell you need to call tmux source-file …. This line in .tmux.conf should work:

bind-key r run-shell 'tmux source-file ~/.tmux.conf && echo reloaded'

The output from the shell (i.e. from echo in this case) will appear in view mode. Personally I would like the short message to appear in the status line, so I would rather use this variant:

bind-key r run-shell 'tmux source-file ~/.tmux.conf && tmux display-message reloaded'

It's quite educative to analyze what happens when you trigger this binding. You're in a tmux client that communicates with a tmux server. When the client receives a proper key sequence, prefixr, it informs the server and the server acts according to the binding: it runs a shell. The shell runs another tmux client that communicates with the same tmux server and makes it execute the source-file … command. Then the shell runs yet another tmux client that communicates with the server and tells it to run display-message ….

In other words the server runs some code that spawns clients that tell the same server to do something.

Your original working binding (bind r source-file ~/.tmux.conf) is a lot simpler, the server runs source-file … directly.

Since source-file and display-message are tmux commands, you can run them both upon a keystroke without spawning a shell:

bind-key r source-file ~/.tmux.conf \; display-message reloaded

One would expect \; here to work like ; in a shell, but in fact it's more like &&. The manual states:

Each command is terminated by a newline or a semicolon (;). Commands separated by semicolons together form a command sequence - if a command in the sequence encounters an error, no subsequent commands are executed.

So this last binding seems just right in your case, it doesn't spawn any unnecessary shell. Still it's good to know you can run anything via run-shell, even additional tmux clients.

You can mix the two approaches:

bind-key r source-file ~/.tmux.conf \; run-shell '#some complex logic here or whatever'

And there is if-shell. Example:

bind-key r if-shell 'tmux source-file ~/.tmux.conf' 'display-message reloaded' 'display-message "reload failed"'

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .