Zellij: A terminal workspace with batteries included
zellij.dev
zellij.dev
(No affiliation, I just want to be like them when I grow up.)
Unfortunately, it's missing one key feature that keeps me from using it as a daily-driver: it doesn't appear to be possible to attach to an existing session by automatically creating a new tab or pane. iTerm2 has fantastic integration with tmux that allows it to directly create a new tmux tab for every native iTerm2 split or tab, and I was hoping to recreate that with Zellij, outside of iTerm2.
It _is_ possible to open a new tab with the `new-tab` action (or whatever it's called), but unfortunately, there's no way to do that "in the background": one of your open sessions always switches to that new tab when it opens. I don't know if this is a limitation of the session/tab system, but when I dug through the source, I couldn't for the life of me figure out why this was happening.
I did spend some time trying to contribute a flag to allow attaching to existing sessions with a new tab/pane, but the actual architecture in place back then made this very difficult to support without non-trivial refactoring (and at least at the time, Zellij wasn't accepting any major contributions that weren't directly aligned with the roadmap, which I respect: there's only enough time in the day to review random PRs).
I check back periodically; if this is made possible at some point, I'd love to switch to it.
But also, native splits/panes and tabs cover 90% of what I really want from a multiplexer, so it's easier for me personally to stick with familiar behavior than to integrate another tool into my workflow just to recreate it.
Use the 'clear-defaults=true' option for each mode and build the config.
E.g.resize mode for me looks like this
resize clear-defaults=true {
bind "Esc" { SwitchToMode "Normal"; }
bind "h" { Resize "Increase Left"; }
bind "j" { Resize "Increase Down"; }
bind "k" { Resize "Increase Up"; }
bind "l" { Resize "Increase Right"; }
}
Normal mode: normal clear-defaults=true {
// Quit/detach
bind "Alt x" { Quit; }
bind "Alt d" { Detach; }
// Switch modes
bind "Alt p" { SwitchToMode "pane"; }
bind "Alt r" { SwitchToMode "resize"; }
bind "Alt t" { SwitchToMode "tab"; }
bind "Alt s" { SwitchToMode "scroll"; }
bind "Alt m" { SwitchToMode "move"; }
// new pane or resize pane
bind "Alt n" { NewPane; }
bind "Alt >" { Resize "Increase"; }
bind "Alt <" { Resize "Decrease"; }
// move between panes (moves tabs if at the last pane)
bind "Alt h" { MoveFocusOrTab "Left"; }
bind "Alt j" { MoveFocus "Down"; }
bind "Alt k" { MoveFocus "Up"; }
bind "Alt l" { MoveFocusOrTab "Right"; }
// swap layouts
bind "Alt {" { PreviousSwapLayout; }
bind "Alt }" { NextSwapLayout; }
bind "Alt 1" { GoToTab 1; }
bind "Alt 2" { GoToTab 2; }
bind "Alt 3" { GoToTab 3; }
bind "Alt 4" { GoToTab 4; }
bind "Alt 5" { GoToTab 5; }
}Most people's first experience with a new tool will be to launch it with the default configuration and get a feel for it. That is an abysmal experience with far too many tools, so people go back to what they were already comfortable with even if its potential is more limited.
There's some nuance here when distributions change the default config. For example, some distributions made vim act like vi by default, while others enabled a reasonable set of modern features. People can form completely different opinions of the vim experience based entirely on what distribution they happened to try it on first, and you can't exactly blame the users for that.
One list is found here:
https://github.com/zellij-org/awesome-zellij
It also has tutorial links on how to write your own plugins.
I’d like to know which ones people like.
- https://github.com/dj95/zjstatus
- https://github.com/vdbulcke/ghost
And I've also defined some helper functions:
~ cat ~/dotfiles/custom/modules/public/zellij.zsh
# zellij alias
alias ze=zellij
# zellij attach [container]
function za() {
zellij attach "$*"
}
# zellij run [command]
function zr() {
zellij run --name "$*" -- zsh -ic "$*"
}
# zellij run floating [command]
function zrf() {
zellij run --name "$*" --floating -- zsh -ic "$*"
}
# zellij edit file [file]
function zed() {
zellij edit "$@"
}
# zellij attach
function zs() {
sessions=$(zellij list-sessions --no-formatting | awk '{printf "\033[1;36m%-20s\033[0m %s\n", $1, $3}')
selected_session=$(echo "$sessions" | fzf --height ${FZF_TMUX_HEIGHT:-20%} --ansi)
if [ -n "$selected_session" ]; then
za $selected_session | awk '{print $1}'
fi
}
--I'm currently working to write a plugin which will dynamically name zellij workspaces based on their context, with an easier way to rename them as well. The automatic naming scheme is annoying to remember as it chooses two words and stitches them together, e.g "brave-piano", "lucky-iguanadon".
One thing I needed to do in iTerm2 to get some of the Alt- commands to work was to change the option keys from "Normal" to "Esc+". (Settings -> "Profiles" tab -> "Keys" sub-tab -> Click "Esc+" radio for Option Keys.
Projects such as nushell aim to add a bit more but I think that is too conservative. Something like the jupyter or the slime/sly repl are much better. Something with a real language instead of bash and where all the little programs that make a currently terminal work are libraries that can be used as a function or as a standalone program.
Something like that would be much nicer to work with.
For better or for worse, composable commands composed together with pipes is really effective. See [1] as a good example.
It’s not clear that a new “real” language would be able to have the same effectiveness if it didn’t make some of the same choices and trade-offs. Nushell (and powershell) definitely falls into the “real language without bash” category.
By this I mean: what parts of a “real” language would help with the problem linked in [1]? A imperative language would hinder this greatly, and a fully declarative one is too constraining. So you end up with a mix of both.
1. http://www.leancrew.com/all-this/2011/12/more-shell-less-egg...
But they’re not.
My colleagues and I use them every single day. My favourite shell still wasn’t written.
Besides a web browser, there simply isn’t yet as powerful a piece of software for making a computer do anything.
> Something with a real language instead of bash
sh is a real language. It’s command-based programming. An example of a more programmy variant of this paradigm is TCL (Toolkit Command Language) with its tclsh: command languages are excellent for short, frequently used stuff, and then they get worse fast.
So maybe I could qualify “real” a bit: something that is just as ergonomic for frequent stuff, but which does not get progressively worse as it veers into actual programming.
> and where all the little programs that make a currently terminal work are libraries that can be used as a function or as a standalone program.
Have you tried UNIX? It’s literally that!
I do agree it could be improved; for example, piping around structured data is not trivial; it got better with jq, but it’s not native to POSIX.