The basic configuration is to set tmux’s default-command
so that
your interactive shell ends up reattached to the user bootstrap
namespace:
set-option -g default-command 'reattach-to-user-namespace -l zsh'
Since the “attachment status” is inherited by child processes, this configuration will ensure that all the commands started from your shell will also be properly attached.
Some users like to share identical configuration files (including
.tmux.conf
) with systems where the wrapper program is not
available (e.g. same files on both OS X and Linux). Starting with
tmux 1.9, it is safe to use if-shell
to conditionally configure
the use of the wrapper program:
if-shell 'test "$(uname -s)" = Darwin' 'set-option -g default-command "exec reattach-to-user-namespace -l zsh"'
Or, if you have other platform specific configuration, you can conditionally source another file.
In .tmux.conf
:
if-shell 'test "$(uname -s)" = Darwin' 'source-file ~/.tmux-osx.conf'
Then in .tmux-osx.conf
, include the default-command
setting and
any other bits of OS X configuration (e.g. the buffer-to-pasteboard
bindings shown below):
set-option -g default-command 'exec reattach-to-user-namespace -l zsh'
With tmux 1.8 and earlier, the above configuration has a race
condition (the if-shell
command is run in the background) and/or
does not affect the initial session/window/pane. Instead, the basic
default-command
can be extended with a bit of shell code to
conditionally use the wrapper only where it is present:
set-option -g default-command 'command -v reattach-to-user-namespace >/dev/null && exec reattach-to-user-namespace -l "$SHELL" || exec "$SHELL"'
The default-command
will be run using your default-shell
(which
defaults to SHELL, your login shell, or /bin/sh
). This particular
code should work on most systems, but it may fail if the effective
shell is not POSIX compliant (old-style /bin/sh
, a csh variant,
fish, etc.). If one of your systems does not understand command -v
(or if it does something unrelated that returns the wrong exit
value), then you might try using which
instead. Exotic shells may
also require different syntax.
Instead of using default-command
to “wrap” your top-level shells,
you can instead use the wrapper on just the tools that need it (see
“Beyond Pasteboard Access” (below) for other commands that may also
need the wrapper).
You might want to adopt this approach if part of your shell
initialization takes a long time to run: the default-command
will
start your shell twice (once to process the default-command
, and
once more for the final, interactive shell that is started by the
default-command
). For example if your SHELL is zsh, then your
.zshenv
(if you have one) will be run twice (the other
initialization files will only be run once).
For example, you could leave your shell “detached” and run
reattach-to-user-namespace pbpaste
to read from the pasteboard. If
you take this approach, you may want to use a small script, shell
alias, or shell function to supply a shorter name for the wrapper
program (or wrap the individual commands—the
reattach-to-user-namespace
Homebrew recipe has some support for
this).
You will also need to apply this fine-grained “wrapping” if you want to have tmux directly run commands that need to be reattached.
For example, you might use bindings like the following to write a tmux buffer to the OS X pasteboard or to paste the OS X pasteboard into the current tmux pane.
bind-key C-c run-shell 'tmux save-buffer - | reattach-to-user-namespace pbcopy'
bind-key C-v run-shell 'reattach-to-user-namespace pbpaste | tmux load-buffer - \; paste-buffer -d'
Similarly, for the copy-pipe
command (new in tmux 1.8):
bind-key -t vi-copy y copy-pipe 'reattach-to-user-namespace pbcopy'
bind-key -t emacs-copy M-w copy-pipe 'reattach-to-user-namespace pbcopy'
Because the fix applied by the wrapper program is not limited to just pasteboard access, there are other bugs/issues/problems that come up when running under tmux that the wrapper can help alleviate.
-
nohup
The nohup program aborts if it cannot “detach from console”. Normally, processes running “inside” tmux (on the other side of a daemon(3) call) are already detached; the wrapper reattaches so that nohup can successfully detach itself.
nohup does generate an error message if it aborts due to failing to detach, but it happens after the output has been redirected so it ends up in the
nohup.out
file (or wherever you sent stdout):nohup: can't detach from console: Undefined error: 0
References: problem using nohup within tmux on OSX 10.6
-
The
export
,getenv
,setenv
subcommands oflaunchctl
Notably, the
setenv
subcommand will issue an error when it is run from a “detached” context:launch_msg("SetUserEnvironment"): Socket is not connected
The
getenv
andexport
commands will simply not have access to some variables that have otherwise been configured in the user’s launchd instance.References: tmux “Socket is not connected” error on OS X Lion
subl -w
subl --wait
The *subl* command from *Sublime Text* can be used to open files
in the GUI window from a shell command line. The `-w` (or
`--wait`) option tells it to wait for the file to be closed in
the editor before exiting the `subl` command.
Whatever mechanism *Sublime Text* uses to coordinate between the
`subl` instance and the main *Sublime Text* instance is affected
by being “detached”. The result is that `subl -w` commands
issued inside *tmux* will not exit after the file is closed in
the GUI. The wrapper lets the `subl` command successfully
synchronize with the GUI instance.
References: ['subl -w' doesn't ever un-block when running under tmux on OS X][su subl] and [subl --wait doesn't work within tmux][so subl]
-
Retina rendering of apps launched under tmux (10.9 Mavericks)
From feedback in issue #22:
> Under Mavericks, applications launched from inside a tmux
> session cannot enable retina rendering (for reasons I don't
> understand -- this worked under Mountain Lion). If the shell
> inside the tmux session is reattached to the user namespace,
> then applications launched from the reattached shell do enable
> retina rendering when appropriate.
-
ABAddressBook
(via custom program)Issue #43 mentions a custom Swift program using
ABAddressBook
that does not work under tmux unless run with the wrapper (tested on Yosemite).
-
MacVim using a font from ~/Library/Fonts for
guifont
Issue #54 mentions MacVim (8.0; possibly older versions, too) not being able to use a font from ~/Library/Fonts for its
guifont
setting when run under tmux unless run with the wrapper (tested under Sierra).
-
curl
using certificates in Keychain to verify peer--cacert
(iOS and macOS only) If curl is built against Secure Transport [...] then curl will use the certificates in the system and user Keychain to verify the peer, which is the preferred method of verifying the peer's certificate chain.As of macOS Sierra, under tmux without
reattach-to-user-namespace
,curl
will fail to verify peers against Keychain-stored certificates. -
ssh
- Keychain access for Secure ShellOn macOS Sierra tmux can only add your SSH keys to
ssh-agent
withreattach-to-user-namespace
, see "macOS Sierra without SSH-passphrase" on YouTube.
There may also be other contexts (aside from “inside tmux”) where these same problems occur, but I have not yet heard of any.