tmux Window Juggling
Tags: tmux, productivity, debugging
Published: 2019-01-29 07:41:41

---
title: tmux Window Juggling
published: true
description: Ever wanted to turn a tmux Window into a Pane or vice-versa? In this article I'll show you how to juggle tmux Windows and Panes like a pro.
tags: tmux, productivity, debugging
canonical_url: https://davidlains.com/posts/tmux-window-juggling
---

I keep finding more and more depth to *tmux*. It really is a remarkable piece of software. In this article I will show you how to turn a *tmux* Window into a Pane and vice-versa.

Why would you want to move Panes and Windows around in a *tmux* session? I'll explain my scenario, and maybe that will give you some ideas of your own.

## Debugging Sessions

I create *tmux* scripts for all of my projects. This allows me to simply run the script to have the development environment for the given project up and running in a *tmux* session.

For a Rails project I generally have a *tmux* window named `server` that is running the Rails server. I make it the last window in the list because I don't need to look at it too often.

However, I also use Byebug for debugging Ruby. If you haven't used Byebug or a similar debugger before the way it works is you add a `byebug` statement in your code where you want a breakpoint. When you run the code the `byebug` statement will halt the process and transfer control to the debugger.

In a Rails project the server is running the code, so when Byebug hits a breakpoint the debugger stops in the server window. Then you can interact with the debugger as you normally would, inspecting variables, stepping through code, etc.

Now you can perhaps see where this is going. When debugging Rails it would be very handy to have the server window in a split pane next to my editor. That way I can see the relevant code and the debugger in the same *tmux* window.

## Window Becomes Pane

The first *tmux* command we need is `join-pane`. The `join-pane` command gives you the ability to attach a window or pane somewhere else in *tmux* to your current window. The `join-pane` command has the following form.

```
join-pane [-bdhv] [-l size | -p percent] [-s src-pane] [-t dest-pane]
```

We wont need all of those options thankfully. The `-s` option is used to specify the source pane or window to join into the current window.

A quick refresher for how to reference things in *tmux* may be in order.

```
[session]:[window].[pane]
```

For example, if your current *tmux* session is named `giggles` then a reference to the third pane in the second window would be `giggles:2.3`. You can omit the session name if you are currently in the session with the window you want to reference. And yes, that means you can use `join-pane` to move a window or pane from a different *tmux* session to your current session.

For my case I want to move a whole window, so I can just use `-s N`, where `N` is the window number I'm interested in. You can also move a window by its name, so `-s server` would work just as well.

The `-l` and `-p` arguments can be used to size the new pane appropriately. I'm fine with the default 50/50 split so there is no need to use either.

The `-t` argument can be used to move the source pane to someplace other than the current window. Also not an option I will need. The `-b` option works with `-t` to specify that the new pane should be placed to the left or above the target pane.

The joined pane will be active when you complete the `join-pane` command. If you don't want it to be you can use the `-d` option.

The `-h` and `-v` arguments make new pane a horizontal or vertical pane respectively.

Now I can put together the first command I need. I want to move my `server` window into my `editor` window for this debugging session. First I enter command mode with `<Prefix>:`. Now the `join-pane` command:

```
join-pane -h -s server
```

And there it is, my server window next to my editor window. One weird thing about *tmux* is how it deals with horizontal and vertical splits. The `-h` argument specified above produces what I would call a vertical split. There is a pane on the left and a pane on the right. The `-v` argument does the opposite, putting one pane on top and the other on the bottom.

## Pane Becomes Window

To reverse the `join-pane` operation and make a pane a window use the `break-pane` command. The `break-pane` command has the following format.

```
break-pane [-dP] [-F format] [-n window-name] [-s src-pane] [-t dest-window]
```

Again, we won't need all of these options. Just like with the `join-pane` command, if you specify the `-d` option the window will not become active after the move. The `-P` argument tells *tmux* to print information about the new window, and the `-F` argument provides the ability to format that information.

If you don't specify a source pane with `-s` then the currently active pane will be broken out to its own window. Otherwise you can specify the pane to move the same way you did for the `join-pane`.

Panes are not named like windows are, so when you move a pane to its own window *tmux* will use the default name for the window, which is the current command. If you would like to name the window use the `-n` argument and the window name.

The other option, if you have an existing window that you would like to move the pane to you can use the `-t` argument with the reference to the desired window.

For my case when I'm done with the debugging session I just want to move the pane back to its own window named `server`, and I don't need it to be active. I'd rather the `editor` window remain active. I can achieve this with the following command (remembering to activate command mode first with `<Prefix>:`).

```
break-pane -d -n server
```

That tells *tmux* to move the currently active pane to a new window at the end of the window list, do not make it active, and name it `server`.

## Create Key Bindings

The `join-pane` and `break-pane` commands aren't too hard to use in an ad-hoc manner to move panes around as necessary. It is a little bit of typing, but if the window to move is not named, or you need to move different windows around you are stuck having to use the commands themselves.

In my case I know the `server` window will always be available because it is in the *tmux* script that sets up the environment. Since I know the window name will not change I can create key bindings for those commands. As an added benefit, these key bindings are only available for this session because they are not in the main `.tmux.conf` file.

```
tmux bind-key u join-pane -h -s server
tmux bind-key U break-pane -d -n server
```

Now, whenever I want to see the `server` window next to my code I can just type `<Prefix>u` and to return it to its own window I can type `<Prefix>U`.

*Originally posted at [davidlains.com](https://davidlains.com).*