Getting Started with Tmux
ittavern.com
ittavern.com
It's possible to achieve "command as tmux key" with iTerm which I did do for years but I don't recommend it. It's very hacky.
Considering your comment (and many others like it), I don't think that has quite worked out.
Still, kitty is one of my favorite terminal emulators and I'd urge anyone who hasn't tried it to give it a shot.
Running remote tmux inside a local tmux is just to error prone and forces you to remember different bindings.
bind -T root F3 \
set prefix None \;\
set key-table off \;\
set status-left '#[bg=#C678DD,fg=#2C323C](pass-#S)' \;\
set status-style bg=#E06C75 \;\
set window-status-current-style bg=magenta,fg=black \;\
refresh-client -S;
bind -T off F3 \
set -u prefix \;\
set -u key-table \;\
set -u status-left \;\
set -u status-style \;\
set -u window-status-current-style \;\
refresh-client -S;
This way, pressing F3 in local machine disables the prefix and I can use remote tmux as if it is local. When I want to get to local tmux, I press F3 once and I am back to local tmux. I use highlighting to easily show that local prefix is disabled.For example, `bind -n M-1 select-window -t 1` means Alt-1 goes to Window 1 for me.
I use Alt-h, Alt-j, Alt-k, Alt-l for vim-aware pane switching (with some vim config too), e.g. via `bind -n 'M-h' if-shell "$is_vim" 'send-keys M-h' 'select-pane -L'`. I have a load of Alt-<X> mappings.
I use iTerm and Windows Terminal primarily, but it works on everything, really. Though sometimes you need to adjust what 'alt' means; in iTerm, you need to make Alt be Esc+ (I think).
And actually, I didn't mention that my VinTmuxNav commands are bound to `alt-j` and the like so that I can still use `ctrl-h` and `ctrl-l` on the command line. [EDIT: ...and then alacritty binds `cmd-j` and friends to the meta version when inside vim]
And yes, can confirm you do need to make Alt be Esc+ in iTerm!
For example, to jump to specific windows within a tab, instead of number keys, I use `cmd-a`, `cmd-s`, `cmd-d`, `cmd-f`, `cmd-q`, `cmd-w`, `cmd-e`, and `cmd-r` for windows 1-8 respectively (I don't have one for 9 since if I ever get past 8 windows, they are usually throwaways).
A few months ago however, I bought a moonlander keyboard. Now, I've got one of it's keys that, when held, maps the right side to a full traditional numpad. Typing numbers is much more seamless now. Besides numbers, other keys that always broke my flow (looking at you right curly brace) are much easier to type.
Just thought I'd share as it really elevated my overall typing/vim experience.
Another comment in here made think about using Karabiner to give myself a keypad with uiojklnm,. (or something). I actually did this when I used to use a flash-able mechanical keyboard, but I like working on my couch too much so I've been all-in on the short-scale apple keyboards for several years now.
[0] https://sw.kovidgoyal.net/kitty/faq/#i-am-using-tmux-and-hav...
I believe I used this article when I switched over from iTerm to Alacritty: https://arslan.io/2018/02/05/gpu-accelerated-terminal-alacri...
Otherwise, here's my alacritty config: https://github.com/sodapopcan/dotfiles/blob/f9eba86bf292aa3b.... Line 57 is where the keybindings start (They are annoying to read since they use escape sequences). I make my tmux prefix `ctrl-space` (because `ctrl-b` is useful), then in Alacritty pressing `cmd` sends `ctrl-space` to tmux.
bind-key | split-window -h
bind-key - split-window -v
More on my wiki: https://wiki.rsapkf.org/notes/unix/tmux/What tmux calls horizontal and vertical splits is inverse of those in Vim - hence -h flag for what most would call as vertical split. I suspect one of the authors was Australian!
In Sway and i3 if I make a vertical split and open a new window, it appears below (thus vertical), but the split was like a cut horizontally across. I've seen some people use the - and | keys for tmux splits which kind of avoids the language issues and turns it into which way the new line is drawn.
PS comment is in spirit of knowlege-sharing not pedantry. :)
[to be limpid, I just meant that a reboot could kill that server-in-tmux strategy ;P ]
The main page suggests -CC, but the best practices wiki[0] says to use `-CC new -A -s main`, but this causes iterm to warn that a session is already started and doesn't actually create or reattach like I expected. I also had trouble getting the tmux select-layout to work: when I tried it all my panes just exited with an error. I would like to have iterm behave similarly to Kitty's tall layout[1] which I think is the same thing as tmux's main layout, but haven't figured out how to make it work. Anybody have tips on making these wek?
[0]: https://gitlab.com/gnachman/iterm2/-/wikis/tmux-Integration-... [1]: https://sw.kovidgoyal.net/kitty/layouts/#the-tall-layout
I started doing this last week along with tmuxp for managing window sets. It works great.
I thought there was another one, but searching for "tmux" in the issues of the major terminal emulators is worthless since there are so many pages
The main reason to do this (for me) is to use (tmuxp)[https://tmuxp.git-pull.com] to configure window sets for different projects / clients and start them up quickly.
If you dig this and want a whole book that goes into more depth, check out Getting Started with tmux (the book, not the ittavern.com blog post :P)
Could anyone using these explain what it provides that you find useful in practice? I rarely ever need persistence of shell when I close the console, is that a common need? Familiarity/muscle memory of shortcuts is a valid answer, but I'm wondering if there's more to it than that.
Now say you will be moving between home, office, and traveling. If the tmux session is hosted at work you can connect from anywhere and be in the same workspace with the same command history. If you have a dozen other projects happening at once this system can also be a big help as far as organization.
tmux preserves everything for you unless you explicitly kill it, or you have to reboot.
I started using Screen like 20 years ago (and later moved to tmux) and I can't go back to doing real work in a "bare" terminal window. It would feel like walking on a thin layer of ice on a lake; as soon as something goes wrong, it's a minor disaster.
In the unlikely event everything locks up and dies then mostly I'll just lose vim sessions, and I can vim -r to recover the data. This is rare, and vim complains at you when you start it up on a file after it has crashed.
You'd lose the window layouts, but I don't use crazy window layouts, generally no more than two panes for code+tests (running tests I let it flip to fullscreen and scroll and I've got that bound to a key combo in .vimrc). If I had crazy window layouts I'd probably setup a command alias to make it easy to pop them up.
When it comes to commands and such, I just use the command history which is my memory. When it comes to running daemon process I would detach them if I cared (and generally I've got command history so I don't care, I'll just restart it, no matter how arbitrarily complicated it was to get the command running).
Similarly, though, I don't horde tabs and I HATE it when the O/S starts popping open all the windows I had open after a reboot to upgrade the O/S or whatever. I try to run pretty much "statelessly" so that I can wipe everything and start over from nothing easily enough (obviously not really "statelessly" since e.g. slack remembers all kinds of state about what I've done in the past, but I don't have to remember any of that)
And my memory does suck, but I know how to pull things out of command history, internet search, google history, etc. If I need to track stuff, then I use a tool to track it so that it becomes persistent (Zotero has now replaced my folder full of PDFs, I take notes in Obsidian). I don't know what I would ever lose in a terminal window that I fundamentally couldn't get back (and if I ever really needed something such as some unique failure I'd probably take a quick screen shot or copypasta into a note file somewhere -- I'll commonly copy test failures into code comments temporarily while I'm working on them -- sometimes these get promoted to documentation in particularly hairy edge cases).
So I literally just pulled up iTerm in activity window and force killed it and I have no idea what disappeared, but I don't care... Based on the saved command history I can see I likely didn't lose anything at all...
For those who switched from screen what was the biggest benefit?
https://github.com/jftuga/universe/blob/master/tmux.conf
What I like about this config is the "mouse mode". When you split a windows into multiple panes, you can press ctrl-m to go into mouse mode. Within mouse mode, you can use the mouse to resize panes. Outside of mouse mode, copy/paste works better.
Overall, I’m still comfortable switching back and forth, but it seems like tmux is the new hotness, so I’m using that most of the time. It’s a bit easier to style, etc.
tl;dr tmux has much easier configuration, it is more actively developed and maintained, and now (this isn't in my post) a richer add-on/plugin ecosystem
* Clear and discard all scrollback history: Ctrl+Shift+K
* Start a program run
* Select all output: Ctrl+Shift+A
* Copy it: Ctrl+Shift+C
* Paste it somewhere else
A total of 3 key combinations, that are now second nature.
When I installed Tmux and tried to replicate this, I only found a sea of gotchas. No key binding by default for clearing the scroll; similarly, no way to select all text with one single keypress; no way to copy the selected text so I can paste it in other applications.
Given enough time, of course, all of these can be solved one by one, assuming enough motivation and free time (use custom configs, configure xclip, etc) but the default onboarding experience was a bit poor, to be honest.
This is not a fault specifically of Tmux, but more of the typical lack of cohesion between different components that are considered independent tools albeit from the user pow they are arguably part of the same thing.
I might have to revisit Tmux by means of Byobu [0] and see if this time it clicks.
Then, the copy-paste is not done always, but it's done a lot when analyzing logs or debugging some issue. I prefer to read that output with the much more advanced filtering and searching tools that I have installed in my VSCode editor.
One of my favorite scripts to run is a tmux script that creates a new session with about 7 windows of running my company's project (one window for notes, 3 windows for the backend (runner, code, tests), and 3 windows for the client (runner, code, tests). It's even tweaked further to open up the code in vim, and when used in conjunction with something like harpoon.nvim I have access to my most used files with a few keystrokes. I now create similar scripts for all projects I work on for lengthy periods.
One script builds and runs the environment in the way I prefer to work. Tailored to my taste, for me.
Probably the best advice that I always took to heart was a co worker telling me to "just learn the command line." He really took the phrase "learn your tools" seriously. Now, after some decent experience, I finally feel like I have a decent box of specialty tools when heading to any job site.
Tmux comes with the ability to script it, intentionally and by design, and it’s very straightforward and simple to open several windows that launch commands in them. Tmuxinator doesn’t reinvent that, and it does add another dependency, and another layer of options and flags and project syntax to learn.
The suggestion to check it out is great, but saying that people who don’t use it are reinventing it is a tad heavy handed. There are good reasons and legitimate scenarios to keep it simple with tmux scripting alone.
Single binary, too, so no Ruby dependency. I really should get it into Homebrew one of these days...
It's amazing how well tmux works as a project setup tool.
[1]: https://gavinhoward.com/2020/12/my-development-environment-a...
I don't know if you've heard of charmbracelet [1] but they are a company that makes a lot of cool go libraries to assist creating CLTs and TUIs. One of which was on HN recently, VHS [2].
#!/usr/bin/env bash
tmux new-session -d -s sessionname
tmux rename-window todo
tmux send-keys -t todo "vim todo" Enter
tmux new-window -d -n dot
tmux send-keys -t dot "cd " Enter
tmux new-window -d -n windowname
tmux send-keys -t windowname "cd ~/reponame" Enter
tmux send-keys -t windowname "commands to run" Enter
tmux attach-session -d -t sessionname
Config doesn't have to be very complicated, I've used this for a while.
set -g mouse on # allow mouse
set -g history-limit 999999999 # unlimited history
set -sg escape-time 0 # vim esc response faster bind h select-pane -L
bind l select-pane -R
bind k select-pane -U
bind j select-pane -D
bind -r C-h select-window -t :-
bind -r C-l select-window -t :+
bind -r H resize-pane -L 5
bind -r J resize-pane -D 5
bind -r K resize-pane -U 5
bind -r L resize-pane -R 5
I read Brian Hogan's 2012 edition of "tmux: Productive Mouse-Free Development". It was short and made me comfortable enough with tmux that since then I rarely ever use the terminal without starting a tmux session first. I see now that the book has been revised in 2016 for tmux 2 and perhaps I'll re-read it to see what I've missed.I use a function for the local tmux session and an alias for remote ssh tmux sessions, with a different bindings (MOD+x & MOD+w).
Like that I am always in tmux localy and remotely just by launching URxvt.
# open a new tmux session named ssh_tmux or attach to it
alias tmuxs='tmux new-session -A -s ssh_tmux && exit'
# open a new default tmux session with a named default or attach if it exist
tmuxa () {
systemd-run -q --scope --user tmux new-session -A -s default "$@"
exit
}
# run tmux if TMUX variable is null
if [[ "${TERM-}" != tmux* ]] && [[ -z "${TMUX}" ]] && [[ -z "${SSH_CONNECTION}" ]]; then
tmuxa
elif [[ -z "${TMUX}" ]] && [[ -n "${SSH_CONNECTION}" ]]; then
tmuxs
fiI found a plugin called tmux-resurrect but it would be nice as a base feature.
Are the primary usecases of this for SSH, or for non-tiling desktop environments? People say a lot of good stuff about it, but I struggle to figure out what it can do for me when I'm just doing stuff on a local computer, where I can just create new terminal windows.
And if I cannot install, then it is likely that tmux is not available either. So I use lsyncd to edit locally and transfer the edits to the remote system. For running commands I just run ssh host command then.
That's fine, right up until the point you're running a command (or a series of commands) that change things on the machine and your connection gets broken. When that happens there's a very good chance the command being executed will fail in some fashion. If you're very lucky it won't be a big deal, but depending on what you're doing it could be dangerous.
I would strongly advocate for using either screen or tmux as a matter of course on any remote server when you're executing commands on it. You don't need to do anything more with them other than just have a single window in it. You just don't want the command execution to be specifically tied to your SSH session.
At the very least, screen or tmux enables you to get right back to what you were doing with no loss of output, and at the most it enables whatever commands you were executing to finish executing without risk of broken pipes killing them mid-flow or whatever else might end up being catastrophic.
I spent 5 years at Amazon (back a long time ago) being incredibly aggressive with command line root-trust from the old bastion host they had there, working up to regularly executing ssh commands to all 30,000 servers (like I said it was a long time ago, but that's still a considerable stack) every single day. It is the kind of idea that gives a lot of people the vapours to think about, and I wouldn't recommend it if you had good alternatives. But Amazon never turned into a smoking hole, and I never once saw this kind of problem. I certainly had to deal with network issues, and the scripts I used were pretty robust against problems. Most often servers would be crashed and fail to ping, packets would get lost but retransmissions would succeed, or the kernel would be hung only responding to interrupts and userspace was all deadlocked, but sometimes the servers had some resource starvation issues and it would just be very slow and the command would timeout. Nothing bad every happened. I occupy some weird space though where I'm stupid enough to try these kinds of things and just careful enough to not get bitten by them. I've also been a trained cave diver for over a decade now as well (if you get the training and follow the rules, it is safer than driving on the roads in Mexico).
And really you should always be using configuration management to change the state of servers and should have some kind of agent doing that automatically for you (although I've broken that rule probably a thousand times myself), and you should also ensure that what you're doing is 'idempotent', so that if it fails due to some transient error then you can just keep on hammering on the server and the next time or the time after that or whatever it will fix itself. This is the "self-healing" or "computer immunology" concept of configuration management that Mark Burgess came up with back in 1998 or so. If the process gets interrupted just run the process again. That may require some care taken around intermediate states and recovery from intermediate states, but that is just config management 101.
set -g prefix `
bind-key e send-prefix
Then, all your tmux controls are one left pinky press away (` is beside z on uk Mac keyboards).(`e sends a ` for when you need it, rare though, $() is better for sub shells :})
But then again those types of users are also likely already hyper aware of hotkey modifications and optimizations.
For some reason I kept getting extreme slowdowns/laggy behaviour when using neovim.
I’ve seen this thread: https://github.com/tmux/tmux/issues/353
I tried everything in the thread and still end up with a laggy terminal. For now I just use iterm2 with tabs but I miss my tmux.
On my personal Linux laptop, I never encounter the same lag with the same setup.
# split in pane cwd
bind '"' split-window -c "#{pane_current_path}"
bind % split-window -h -c "#{pane_current_path}"
bind c new-window -c "#{pane_current_path}""|" -- for vertical split
"-" -- for horizontal split
Great tool
I just wish that eg windows' (os) terminal was smarter when you have eg two windows in tmux next to eachother and try to select line or text with mouse then it was just selecting from one window, not many or all
You still need to learn the basics but this lowers the learning curve a lot.
enter copy mode: LEADER [
highlight text to copy: press space and then arrow w and b to highlight words (like vi editor)
exit copy mode: press enter key or Q
paste copied text: LEADER ] OR cmd+V
My TL;DR: sure, use Tmux if you're directly accessing remote resources often, otherwise there's probably simpler solutions that might get you 95% of the way there.
Annoys the hell out of me every time I used it on new machine.
set -g default-terminal "screen-256color"
# Use C-a for outer sessions, and C-x for nested sessions.
unbind-key C-b
set-option -g prefix C-a
bind-key -n C-x send-prefix