Skip to content

Feature request: nested zellij instances (e.g. over ssh) #387

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
alxhub opened this issue Apr 26, 2021 · 11 comments
Open

Feature request: nested zellij instances (e.g. over ssh) #387

alxhub opened this issue Apr 26, 2021 · 11 comments
Milestone

Comments

@alxhub
Copy link

alxhub commented Apr 26, 2021

Currently, running zellij inside zellij does work, but is not specially handled. A really good experience could be provided though, especially in combination with ssh:

  1. I'm inside a tab in zellij on my local machine.
  2. I ssh to a remote machine.
  3. I launch zellij on the remote machine.

Rather than running an independent instance of zellij that's tricky to control as it requires escape sequences to operate, zellij could instead recognize that it's running inside another instance and coordinate. It would be possible to:

  • distinguish local vs remote tabs/panes, e.g. through color or name prefixes
  • open new tabs/panes for the remote machine, coordinated by the inner zellij instance
  • navigate seamlessly between local and remote
@a-kenji
Copy link
Contributor

a-kenji commented Apr 27, 2021

Good idea! Thanks for taking the time in writing this out.

@Lillecarl
Copy link

There's a really cool thing that Zellij could do that'd "remove" the need for running Zellij on the remote machine.

The terminal emulator Wezterm supports running SSH through it, and then you can spawn new wezterm tabs they'll be in the same SSH session because of something called SSH channels, Wezterm is also written in rust and uses libssh2 for this so i guess quite a bit of code could be reused from that project (both WezTerm and Zellij are MIT licensed too so copypasta is cool)

This would kinda imply adding a command mode to zellij to be able to run the ssh command, or if there's a way for the zellij binary to know which pane it runs in, which then can be used to instruct the zellij server to initiate an ssh connection in that pane. Think zellij ssh user@host.

When i saw this feature in Wezterm my jaw dropped, it's such an obviously awesome feature.

ssh2 = {version="0.9.3", features=["openssl-on-win32"]}
libssh-rs = {version="0.1.1", features=["vendored"]}

https://wezfurlong.org/wezterm/ssh.html

@raphCode
Copy link
Contributor

There's a really cool thing that Zellij could do that'd "remove" the need for running Zellij on the remote machine.

Running zellij or any other terminal multiplexer provides session persistence, so that the programs continue to run after the ssh connection drops. To me, this is an important feature, especially for long running tasks.
If I understand correctly, multiplexed ssh sessions a la wezterm do not provide this?

@Lillecarl
Copy link

@raphCode true, my suggestion complements another issue regarding nested zellij instances.

@milanglacier
Copy link

milanglacier commented May 14, 2023

Both tmux and zellij treats nested session as is...

But most of the time, nested tmux works just fine because its keybinding scheme is centered around the prefix key. Say if you want to control the nesteed tmux session, you just need to press Control b twice to send the real Control b to the terminal which then forwards to the nesteed tmux session.

In zellij, you need to firstly lock the outer level session by C-g and then you are able to send keys like C-p, C-n into the inner level zellij session, which then controls the pane/tab/layout of the nested zellij session. But here comes the problem, you can never send a real C-p, C-n stuffs into the nested tmux session because you can never really lock the nested zellij session as you can never send a real C-g into the terminal.

Here's my workaround config to fix the problem (that is, tweaking the keymaps to have ability to send a real C-g into the terminal), note that I used Alt g as my lock mode key instead of Ctrl g but they should work the same.

    locked {
        bind "Alt g" { SwitchToMode "Normal"; }
    }

    normal {
        bind "Alt g" { SwitchToMode "Locked"; }
    }

    shared_except "locked" {
        bind "Ctrl a" { SwitchToMode "Tmux"; }
        bind "Alt p" { SwitchToMode "Pane"; }
        bind "Alt r" { SwitchToMode "Resize"; }
        bind "Alt s" { SwitchToMode "Scroll"; }
        bind "Alt o" { SwitchToMode "Session"; }
        bind "Alt t" { SwitchToMode "Tab"; }
        bind "Alt m" { SwitchToMode "Move"; }
        bind "Alt g" { Write 27 7015; SwitchToMode "Normal"; } // send a real Alt+g to the terminal
    }

In this way, you are able to send the real Alt g to the terminal and then you are able to lock the nested zellij session. In this setup, nested zellij works like nested tmux, controlling the nested session is a little verbose than controlling the outer level session, but it is doable, you just need to press one more keystroke (Ctrl a, Alt p, or whatever).

I also have the following keymaps to make things easier:

    tab {
        bind "Alt t" { Write 27 7028; SwitchToMode "Normal"; } // send a real Alt+t to the terminal
    }

    session {
        bind "Alt o" { Write 27 7023; SwitchToMode "Normal"; } // send a real Alt+o to the terminal
    }

    pane {
        bind "Alt p" { Write 27 7024; SwitchToMode "Normal"; } // send a real Alt+p to the terminal
    }

In this way, pressing Alt t twice will activate the tab mode in the nested zellij session, so you do not need to lock the outer level zellij session for entering the tab mode of the nested zellij session. To send a real A-t into the nested zellij session, firstly press A-g to lock the outlevel session, and then press A-t twice.

@bruno-robert
Copy link

@milanglacier In your example you are using Alt as a modfier, so sending Alt+t would be Write 27 7028.
How would one come up with the bytes to send for an arbitrary keypress, say Ctrl+t for example?

@adriangalilea
Copy link

adriangalilea commented Jul 25, 2024

My ideal scenario would be:

Instead of having a zellij inside a zellij, with conflicting keybinds and so on, I would love to be able to directly let my main zellij instance wormhole into the remote zellij instance in a way that I would simply experience the remote zellij instance until I close it and then I would be back up in the main zellij instance.

Commands:
zellij
ssh bob@foo
zellij

Then I'd see only a zellij instance in the remote machine but zellij notes that this is indeed a wormholed instance.

This may not be feasible or be very complex, just sharing my thoughts :)

P.S.: I love zellij

@rsniezek
Copy link

My ideal scenario would be:

Instead of having a zellij inside a zellij, with conflicting keybinds and so on, I would love to be able to directly let my main zellij instance wormhole into the remote zellij instance in a way that I would simply experience the remote zellij instance until I close it and then I would be back up in the main zellij instance.

Commands: zellij ssh bob@foo zellij

Then I'd see only a zellij instance in the remote machine but zellij notes that this is indeed a wormholed instance.

This may not be feasible or be very complex, just sharing my thoughts :)

P.S.: I love zellij

I'd also love to be able to simply connect my local zellij to a remote session. E.g. via session manager, simply selecting remote session would switch to it like to a local one so that the usage is identical to working locally. I'm willing to pay for having the session be local only or remote only if I can avoid nesting and have great UX thanks to the session manager. With this one could still pretty much use current nesting with lock mode or any improvements that are to come but remote session attach would work independently of that

@yocoldle
Copy link

yocoldle commented Dec 7, 2024

@milanglacier In your example you are using Alt as a modfier, so sending Alt+t would be Write 27 7028. How would one come up with the bytes to send for an arbitrary keypress, say Ctrl+t for example?

https://en.wiktionary.org/wiki/Appendix:Control_characters
For ones who wanna Write sth with Ctrl, there you go

@EvanEdwards
Copy link

EvanEdwards commented Feb 24, 2025

A real world use case that is semi-complex (aren't they all?), but works well for me. I am dumping this here just as a workaround and functioning example of nesting zellij. If somebody is planning on working on this, feel free to reach out and I'll provide feedback or testing. I'm typing this quickly just to share and mixing terminology. Hopefully it's clear enough to understand.

I am using zellij heavily with a prefix key, as I came in from screen to tmux to byobu to zellij, and I use emacs... so I'm all about the strange combos. I use ^A as the primary (and use z-tab-bar), and have it essentially paneless (meaning one full pane per tab, no splits). The bottom status bar thus has the host I am on (or a temporary secondary profile). The config.kdl is stripped down so it basically only uses ^A and is entirely focused only on creating and navigates those full screen tabs that connect to nested zellij session. I also have a za script that launches a command in a new pane in the current tab, or takes hostname: and launches a new tab with an ssh to that host with a nested zellij session.

In each host I have a "second level" config that uses ^Q as the prefix and maxes it out to various combos that do everything with that prefix, splitting, moving and otherwise managing panes. That said, it could be more typical with keybindings, but there's a logical reason: it has its own second level z-tab-bar that is the next to last line. ^A controls the bottom one for host, and ^Q -- being one line up, same as the status bar -- controlling the remote session is easy to use. Although it sometimes conflicts, most console applications generally have work around for terminals with flow control.

Yes, this means that I always have two status bars and often have four status lines at the bottom of the screen in emacs and three in flow or fzy. I don't see an easy way to do it better without a different plugin, and since I am on various hosts all day, I like the instant clarity of having the secondary status having a different color for different contexts.

@dominz88
Copy link

Others have mentioned wezterm ssh feature, but those sessions die when network connexion goes down. Instead wezterm has another feature called ssh domains in which the rendering is done locally and the remote wezterm instance keeps track of the tabs and panes, thats such a nice feature.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests