Economy of Effort

Twitter LinkedIn GitHub Mail RSS

Reattach-to-user-namespace: The Fix for Your Tmux in OS X Woes

tl;dr: Things not behaving right in tmux on OS X? Install reattach-to-user-namespace

Are you a tmux + Mac OS X user? Have you had any of the following problems?

  • Running launchctl to start services fails with a message like launch_msg(): Socket is not connected
  • Using the OS X Pasteboard commands pbcopy and pbpaste and having them not work
  • Launching a GUI app from the terminal and getting a “ghost window”: the app window loads in the background, with no dock icon, cannot be Command-Tab’d to, and the app’s menu does not populate the top bar when the window gains focus

Why does this happen? Chris Johnsen has some details

tmux uses the daemon(3) library function when starting its server process. In Mac OS X 10.5, Apple changed daemon(3) to move the resulting process from its original bootstrap namespace to the root bootstrap namespace. This means that the tmux server, and its children, will automatically and uncontrollably lose access to what would have been their original bootstrap namespace (i.e. the one that has access to the pasteboard service).

It turns out that Apple has patched the version of GNU screen that they distribute with OS X to avoid this problem. But this is 2013, and we UNIX geeks have moved on to tmux, right? Chris goes on in that README to explain why porting Apple’s screen patch to tmux would be tricky.

So, instead, he provides the reattach-to-user-namespace wrapper program. This allows us to launch a process and have that process be attached to the per-user bootstrap namespace, which, to put it simply, makes the program behave as we are expecting.

The “trick” is to configure tmux to launch its shells with the reattach-to-user-namespace wrapper. By doing that, the shells tmux launches, as well as everything those shells launch, will be attached to the user namespace, and the problems listed at the top of this post will no longer be issues. We can use the default-command option in ~/.tmux.conf to wrap our shell launching command.

First, we need to install reattach-to-user-namespace. If you use Homebrew or MacPorts, this is as easy as:

; with Homebrew
$ brew install reattach-to-user-namespace

; with MacPorts
$ port install tmux-pasteboard

I use the same dotfiles for Linux as well as OS X, so I only want to do this in the OS X environment. I accomplish this with the following:

" at the end of the file
if-shell 'test "$(uname)" = "Darwin"' 'source ~/.tmux-osx.conf'
set-option -g default-command "reattach-to-user-namespace -l zsh"

If you only use OS X, you can skip creating an external file, and just put the set-option line directly in your ~/.tmux.conf. Also, I am using zsh, so my command to reattach-to-user-namespace is zsh. If you’re using a different shell, change that to your shell’s name.

With this configuration in place, kill and re-launch tmux. The shells that tmux launches should now get attached to the user namespace, and namespace-related issues should be resolved.