Terminal multiplexer inspired by i3

3mux is a terminal multiplexer with out-of-the-box support for search, mouse-controlled scrollback, and i3-like keybindings. Imagine tmux with a smaller learning curve and more user-friendly defaults.

Features

  • batteries included
  • i3-like keybindings
  • session management
    • optionally interactive
    • self-documenting
  • search
  • scrollback
  • mouse support
    • drag to resize panes
    • click to select pane
    • scrollwheel

Key Bindings

Key(s) Description
Alt+Enter
Alt+N
Create a new pane
Alt+Shift+F Make the selected pane fullscreen. Useful for copying text
Alt+←/↓/↑/→
Alt+h/j/k/l
Select an adjacent pane
Alt+Shift+←/↓/↑/→
Alt+Shift+h/j/k/l
Move the selected pane
Alt+R Enter resize mode. Resize selected pane with arrow keys or h/j/k/l. Exit using any other key(s)
Alt+/ Enter search mode. Type query, navigate between results with arrow keys or n/N
Scroll Move through scrollback
Shift Many terminal emulators support selecting text while pressing this key

Supported tmux Bindings

Key(s) Description
Ctrl+b " Split horizontally
Ctrl+b % Split vertically
Ctrl+b { Move pane left
Ctrl+b } Move pane right

Supported screen Bindings

Key(s) Description
Ctrl+a | Split horizontally
Ctrl+a S Split vertically
Ctrl+a Tab Cycle forward through panes

Installation Instructions

Binary (recommended)
  1. Download the .tar.gz for your OS from the Releases tab
  2. tar -zxvf YOUR_FILE.tar.gz
  3. Add the now-extracted ./3mux to your $PATH
Using Nix flakes (requires Nix 2.4+)
nix run github:aaronjanse/3mux
Package manager

Packages for 3mux

Building from source
  1. Install Golang
  2. go get github.com/aaronjanse/3mux
  3. Run 3mux to launch the terminal multiplexer

To update 3mux, run go get -u github.com/aaronjanse/3mux

Terminal.app

Warning: Arrow-key-controlled pane management is currently unsupported on Terminal.app. Please use the default vim-like keybindings instead.
Preferences > Profiles > Keyboard > Use Option as Meta Key

iTerm2

Preferences > Profiles > Keys > Option Key > Esc+

Miscellaneous

3mux searches XDG_CONFIG_HOME to find its config. If it cannot, it writes a config to ~/.config/3mux/config.toml upon the first run. Modifiers in shortcuts (e.g. Alt) are case-insensitive.

You can detect if you're running a script inside 3mux by checking if THREEMUX is equal to 1.

Contributing

All help is welcome! You can help the project by filing issues recording what works well, what doesn't work well, and/or a feature you want. Pull Requests would be very much appreciated.

Related Projects

Owner
Aaron Janse
UC Berkeley '24
Aaron Janse
Comments
  • Binary release builds

    Binary release builds

    Hi,

    3mux looks really cool, and I would love to try it out. Unfortunately, I don't have a go toolchain setup, so I would rather download a single binary and run it. Would it be possible for you to upload the binary outputted by go into the github releases?

    Thanks!

  • Waiting for server to be online...

    Waiting for server to be online...

    I don’t use brew so I installed 3mux using

    > go get github.com/aaronjanse/3mux
    

    and when I try to run 3mux it asks me for a session name (I entered test) and I get this:

    > ./go/bin/3mux
    Waiting for server to be online... (/var/folders/d5/6_9wptzx0ml6ys098gqncydm0000gn/T/3mux/92c9afcc-e1f5-4d81-5821-fad5a3ffae1e/fd.sock)
    Although the server socket exists, connection to it failed: dial unix /var/folders/d5/6_9wptzx0ml6ys098gqncydm0000gn/T/3mux/92c9afcc-e1f5-4d81-5821-fad5a3ffae1e/fd.sock: connect: connection refused
    See server-side logs at /var/folders/d5/6_9wptzx0ml6ys098gqncydm0000gn/T/3mux/92c9afcc-e1f5-4d81-5821-fad5a3ffae1e/logs-server.txt
    To manually kill this session, run `3mux kill test`
    

    where the log contains:

    > sudo cat /var/folders/d5/6_9wptzx0ml6ys098gqncydm0000gn/T/3mux/92c9afcc-e1f5-4d81-5821-fad5a3ffae1e/logs-server.txt
    2021/03/26 11:17:45 Booting...
    2021/03/26 11:17:45 Detach error: listen unix /var/folders/d5/6_9wptzx0ml6ys098gqncydm0000gn/T/3mux/92c9afcc-e1f5-4d81-5821-fad5a3ffae1e/detach-server.sock: bind: invalid argument
    

    So, my question is: what server is expected to run here?

  • Not starting up

    Not starting up

    Error during: starting shell: fork/exec /usr/bin/zsh: invalid argument Tiling state: Universe0 goroutine 1 [running]: runtime/debug.Stack(0x585280, 0xc000128008, 0xc00008dda8) /usr/local/go/src/runtime/debug/stack.go:24 +0x9d main.fatalShutdownNow(0xc000166000, 0x38) /home/z003ejhw/src/github.com/aaronjanse/3mux/main.go:133 +0x17e main.newTerm(0x1, 0x562bd8) /home/z003ejhw/src/github.com/aaronjanse/3mux/pane.go:89 +0x270 main.main() /home/z003ejhw/src/github.com/aaronjanse/3mux/main.go:77 +0x2f9

  • Keybindings interfere with i3s default keybindings

    Keybindings interfere with i3s default keybindings

    Do you have any plans to add another set of keybindings, that doesn't interfere with the default i3 keybindings? Because this is pretty much unusable out of the box on i3....

  • connect: no such file or directory when trying to connect to an existing session

    connect: no such file or directory when trying to connect to an existing session

    Here's what happens:

    ~ 
    ➜ 3mux
    Attach to an existing session or create a new one:
    > 3mux
    + create new session
    

    I hit "Enter" and get this:

    panic: dial unix /tmp/3mux/0/fd.sock: connect: no such file or directory
    
    goroutine 1 [running]:
    main.attach(0xc00001848b, 0x1)
            /home/v1rtl/go/src/github.com/aaronjanse/3mux/attach.go:36 +0x7c8
    main.main()
            /home/v1rtl/go/src/github.com/aaronjanse/3mux/main.go:137 +0x695
    

    I use v1.0.0 of 3mux and go1.14

  • thanks for bring sanity to a terminal multiplexer - and a minor suggestion

    thanks for bring sanity to a terminal multiplexer - and a minor suggestion

    Very well done - you brought both functionality and usability to a next-generation terminal multiplexer, I was a long term tmux user, 3mux works far better out of the box!

    By the way, a minor suggestion - alt+b and alt+f are used by readline for moving cursor between words, they're very handy as many terminal emulators out there don't correctly handle ctrl+left/right for the same feature. Would you consider using a different default key for making a panel full screen?

    Another odd one, I'm using fish on Ubuntu 18.04, this happens to fish when I repeatedly press enter in 3mux:

    image

  • Error on macOS 10.14.6

    Error on macOS 10.14.6

    • Mac Pro (early 2009)
    • macOS 10.14.6
    • go version go1.14.1 darwin/amd64
    • Shell - Alacrity + ZSH (not with OhMyZSH!)
    • Same error occurs with iTerm and Terminal

    go get github.com/aaronjanse/3mux completes okay but 3mux [enter] gives the following...

    Stack trace...

    Error during: pane.go (shell death)
    runtime error: index out of range [0] with length 0
    Tiling state: Universe[0](Workspace(HSplit[0](Term[160x49]*)))
    goroutine 51 [running]:
    runtime/debug.Stack(0x1180c60, 0xc00000e018, 0xc0000a6cf8)
    	/usr/local/go/src/runtime/debug/stack.go:24 +0x9d
    main.fatalShutdownNow(0xc000016140, 0x49)
    	/Users/carlca/Code/go/src/github.com/aaronjanse/3mux/main.go:126 +0x16c
    main.newTerm.func2.1()
    	/Users/carlca/Code/go/src/github.com/aaronjanse/3mux/pane.go:68 +0xb3
    panic(0x1144500, 0xc0001a8040)
    	/usr/local/go/src/runtime/panic.go:967 +0x166
    main.newTerm.func2(0xc00007e000)
    	/Users/carlca/Code/go/src/github.com/aaronjanse/3mux/pane.go:74 +0x230
    created by main.newTerm
    	/Users/carlca/Code/go/src/github.com/aaronjanse/3mux/pane.go:65 +0x167
    
    
    Please submit a bug report with this stack trace to https://github.com/aaronjanse/3mux/issues
    
  • Error on mac os catalina

    Error on mac os catalina

      ~ go get github.com/aaronjanse/3mux
    # github.com/aaronjanse/3mux
    go/src/github.com/aaronjanse/3mux/shell.go:96:11: undefined: pty.Setsize
    go/src/github.com/aaronjanse/3mux/shell.go:96:32: undefined: pty.Winsize
    
  • index out of range when trying to split vertically

    index out of range when trying to split vertically

    When I hit ctrl + b + shift + ' (e.g. ctrl + b + ") I get this stacktrace:

    goroutine 1 [running]:                                                                                                                                                                        
    runtime/debug.Stack(0x642e00, 0xc000010020, 0xc0000a95e8)                                                                                                                                     
            /home/v1rtl/.go/src/runtime/debug/stack.go:24 +0x9d                                                                                                                                   
    main.main.func1(0xc0000a9dc8)                                                                                                                                                                 
            /home/v1rtl/go/src/github.com/aaronjanse/3mux/main.go:65 +0xd6                                                                                                                        
    panic(0x5eb200, 0xc000018420)                                                                                                                                                                 
            /home/v1rtl/.go/src/runtime/panic.go:975 +0x3e3                                                                                                                                       
    github.com/aaronjanse/3mux/wm.(*split).refreshRenderRect(0xc00009a300, 0x0)                                                                                                                   
            /home/v1rtl/go/src/github.com/aaronjanse/3mux/wm/split.go:126 +0x27c                                                                                                                  
    github.com/aaronjanse/3mux/wm.(*split).SetRenderRect(...)                                                                                                                                     
            /home/v1rtl/go/src/github.com/aaronjanse/3mux/wm/split.go:88                                                                                                                          
    github.com/aaronjanse/3mux/wm.(*workspace).setRenderRect(0xc00005a6c0, 0x0, 0x0, 0xbe, 0x28)                                                                                                  
            /home/v1rtl/go/src/github.com/aaronjanse/3mux/wm/workspace.go:42 +0xcb                                                                                                                
    github.com/aaronjanse/3mux/wm.(*Universe).refreshRenderRect(0xc00005a660)                                                                                                                     
            /home/v1rtl/go/src/github.com/aaronjanse/3mux/wm/universe.go:102 +0xcb                                                                                                                
    github.com/aaronjanse/3mux/wm.(*Universe).AddPaneTmux(0xc00005a660, 0xc0000a9900, 0xc000073380, 0x6032c7)                                                                                     
            /home/v1rtl/go/src/github.com/aaronjanse/3mux/wm/pane-add.go:62 +0xac                                                                                                                 
    github.com/aaronjanse/3mux/wm.glob..func3(0xc00005a660)                                                                                                                                       
            /home/v1rtl/go/src/github.com/aaronjanse/3mux/wm/tiling.go:69 +0x30                                                                                                                   
    main.seiveConfigEvents(0xc0000714d0, 0xc000071500, 0xc0000716b0, 0xc000071560, 0x100, 0xc00005a660, 0x771b62, 0x1, 0x60e400)                                                                  
            /home/v1rtl/go/src/github.com/aaronjanse/3mux/config.go:184 +0x2ed                                                                                                                    
    main.main()                                                                                                                                                                                   
            /home/v1rtl/go/src/github.com/aaronjanse/3mux/main.go:145 +0xcdf                                                                                                                      
                                                                                                                                                                                                  
                                                                                                                                                                                                  
    BEFORE `Universe[0](Workspace(VSplit[1](Term[0,0 190x40], Term[0,21 190x19]*)))`  
    

    It happens ocassionaly on vertical split

    here's my system info

    uname -r: 5.4.0-29-generic go version: go version go1.14.3 linux/amd64

  • Update golang.org/x/sys.

    Update golang.org/x/sys.

    This fixes the build on Darwin using Go 1.18.

    See https://stackoverflow.com/questions/71507321/go-1-18-build-error-on-mac-unix-syscall-darwin-1-13-go253-golinkname-mus

  • tmux bindings are buggy

    tmux bindings are buggy

    Error during: pane.go (vt.ProcessStream) runtime error: index out of range [-1] Tiling state: Universe[0](Workspace(HSplit[0](Term[181x48]*, Term[-1x48]))) goroutine 38 [running]: runtime/debug.Stack(0x1183000, 0xc00000e018, 0xc000144a88) /usr/local/Cellar/go/1.14/libexec/src/runtime/debug/stack.go:24 +0x9d main.fatalShutdownNow(0xc001c64140, 0x41) /Users/ghazni/go/src/github.com/aaronjanse/3mux/main.go:125 +0x16c main.newTerm.func4.1() /Users/ghazni/go/src/github.com/aaronjanse/3mux/pane.go:112 +0xb3 panic(0x11463e0, 0xc000ef2380) /usr/local/Cellar/go/1.14/libexec/src/runtime/panic.go:967 +0x15d github.com/aaronjanse/3mux/vterm.(*VTerm).handleEraseInDisplay(0xc0001b2000, 0x0, 0x0) /Users/ghazni/go/src/github.com/aaronjanse/3mux/vterm/csi.go:171 +0x38c github.com/aaronjanse/3mux/vterm.(*VTerm).handleCSISequence(0xc0001b2000) /Users/ghazni/go/src/github.com/aaronjanse/3mux/vterm/csi.go:87 +0x6e7 github.com/aaronjanse/3mux/vterm.(*VTerm).handleEscapeCode(0xc0001b2000) /Users/ghazni/go/src/github.com/aaronjanse/3mux/vterm/stream.go:130 +0x158 github.com/aaronjanse/3mux/vterm.(*VTerm).ProcessStream(0xc0001b2000) /Users/ghazni/go/src/github.com/aaronjanse/3mux/vterm/stream.go:80 +0x35f main.newTerm.func4(0xc0001b2000) /Users/ghazni/go/src/github.com/aaronjanse/3mux/pane.go:115 +0x4d created by main.newTerm /Users/ghazni/go/src/github.com/aaronjanse/3mux/pane.go:109 +0x1f5

  • [feature request]Could you add shortcut key

    [feature request]Could you add shortcut key "Ctrl-b d" for detach from session?

    Hi,

    Could you add shortcut key "Ctrl-b d" for detach from session? Right now I have to close the teminal for detach from session when I have a program running in the foreground.

    Thank you!

  • Unicode-based frames are misaligned

    Unicode-based frames are misaligned

    Very interesting project. I thought about writing something like this myself, but as you already wrote it, I can save some time :) Thank you very much for it.

    One minor issue that I immediately found (hopefully will find and report more in fuiture):

    Maybe this issue is already reported, but I didn't find anything at the first glance.

    Unicode-based frames look like:

    Selection_143

    Ncurses-based frames are displayed correctly:

    Selection_144

    What is even more interesting, the same output may be displayed differently (once well, once broken):

    (please ignore the emoji line above; it is a known issue; we are talking only about the frames)

    Selection_145

  • text can be selected across panes

    text can be selected across panes

    On 3mux 1.1.0 when selecting text using shift+mouse, it can be selected across vertical and horizontal splits. Just like you can without any multiplexer. It makes proper selecting multiple lines of t ext impossible.

  • Mac Terminal.app and vim wreak visual havoc

    Mac Terminal.app and vim wreak visual havoc

    With v1.1.0 on Mac using the Terminal app I get this:

    3mux

    This is a fresh start of 3mux and I didn’t resize the terminal window, a single pane with vim & YCM. Note vim’s two status lines too…

  • Optimize rendering in special cases

    Optimize rendering in special cases

    See https://github.com/aaronjanse/3mux/pull/117#pullrequestreview-609360835. Some cases to possibly optimize:

    • clearing a full-screen pane
    • clearing an entire line (e.g. the help bar)
    • maybe drawing window borders?
Stonks is a terminal based stock visualizer and tracker that displays realtime stocks in graph format in a terminal.
Stonks is a terminal based stock visualizer and tracker that displays realtime stocks in graph format in a terminal.

Stonks is a terminal based stock visualizer and tracker. Installation Requirements: golang >= 1.13 Manual Clone the repo Run make && make install Pack

Dec 16, 2022
Pure Go line editor with history, inspired by linenoise

Liner Liner is a command line editor with history. It was inspired by linenoise; everything Unix-like is a VT100 (or is trying very hard to be). If yo

Jan 3, 2023
Building powerful interactive prompts in Go, inspired by python-prompt-toolkit.
Building powerful interactive prompts in Go, inspired by python-prompt-toolkit.

go-prompt A library for building powerful interactive prompts inspired by python-prompt-toolkit, making it easier to build cross-platform command line

Jan 3, 2023
One-line-at-a-time was a hobby project inspired by the character Dwight K. Schrute of 'The Office'
One-line-at-a-time was a hobby project inspired by the character Dwight K. Schrute of 'The Office'

One Line at a Time Introduction One-line-at-a-time was a hobby project inspired by the character Dwight K. Schrute of 'The Office'. His efficient usag

Dec 13, 2021
Washizator CLI inspired by @yablko.
Washizator CLI inspired by @yablko.

Washizator [CLI] Are you feeling a bit overwhelmed or saddened? Well, Washizator fixes that for you. It, 'vashizasizes your (coding) experience' @yabl

Jan 16, 2022
A tiny command-line orientated PKM tool inspired by Taskwarrior and daily logging.

eden eden is a command line tool for creating and manipulating daily log notes. It started life as a series of different bash script that did various

Jan 20, 2022
Feb 12, 2022
Terminal client for SimpleNote

GoNote - Terminal client for SimpleNote GoNote is a simple utility for managing notes in your SimpleNote account. It allows basic operations like crea

Nov 22, 2022
gomerge is a tool to quickly bulk merge several pull requests from your terminal.
gomerge is a tool to quickly bulk merge several pull requests from your terminal.

Gomerge is a tool to quickly enable you to bulk merge Github pull requests from your terminal. The intention of this tool is to simplfy, and eventually automate the merging of github pull requests. This tool should be able to run on most systems.

Dec 28, 2022
`tmax` is a powerful tool to help you get terminal cmd directly.
`tmax`  is a powerful tool to help you get terminal cmd directly.

The positioning of tmax is a command line tool with a little artificial intelligence. If you frequently deal with the terminal daily, tmax will greatly improve your work efficiency.

Oct 15, 2022
YouTube client on your terminal

MeowTube YouTube client on your terminal Table of Contents About Getting Started Usage Contributing About MeowTube is a CLI (Command Line Interface) t

Jul 29, 2022
🎄 A Christmas tree right from your terminal!
🎄 A Christmas tree right from your terminal!

ctree ?? A Christmas tree right from your terminal! ?? Demo ⌛ No Refresh Don't want the tree to refresh every 2 seconds? Easy! Just add the --no-refre

Dec 20, 2022
progress_bar creates a single customizable progress bar for Linux terminal.
progress_bar creates a single customizable progress bar for Linux terminal.

progress_bar Go Progress Bar Features progress_bar creates a single customizable progress bar for Linux terminal. Installation go get -u github.com/er

Aug 12, 2022
A terminal based typing test.
A terminal based typing test.

What A terminal based typing test. Installation Linux sudo curl -L https://github.com/lemnos/tt/releases/download/v0.4.0/tt-linux -o /usr/local/bin/tt

Dec 28, 2022
Raspberry Pi terminal based activity monitor
Raspberry Pi terminal based activity monitor

pitop Raspberry Pi terminal based activity monitor Yes I know there are plenty of solutions already available, but I wanted to build my own terminal b

Dec 11, 2022
❓🖼 Find the anime scene by image using your terminal
❓🖼 Find the anime scene by image using your terminal

What Anime CLI ❓ ?? > This application is basically a ?? wrapper around trace.moe PREVIEW Usage ?? Get Anime By Image File ?? what-anime file anime.jp

Jan 2, 2023
Terminal stock ticker with live updates and position tracking
Terminal stock ticker with live updates and position tracking

Ticker Terminal stock watcher and stock position tracker Features Live stock price quotes Track value of your stock positions Support for multiple cos

Jan 8, 2023
lazyhub - Terminal UI Client for GitHub using gocui.
lazyhub - Terminal UI Client for GitHub using gocui.

lazyhub - Terminal UI Client for GitHub using gocui.

Dec 14, 2022
A modern and intuitive terminal-based text editor
A modern and intuitive terminal-based text editor

micro is a terminal-based text editor that aims to be easy to use and intuitive, while also taking advantage of the capabilities of modern terminals

Jan 7, 2023