I run Claude Code on a remote desktop over ssh, inside a zellij session so it keeps working if my connection drops. Two things annoyed me about that:
- Every dropped connection meant
ssh ...again, thenzellij attach -c ...again. - When the link died mid-session, my local terminal was often left in a mess — stray escape codes, mouse reporting stuck on — because the remote never got to clean up after itself.
zc is a small wrapper that fixes both. It's ssh + zellij attach with a
reconnect loop and proper terminal cleanup around it.
zc shells out to your system ssh, so keyboard, mouse, resize, and paste all
pass through exactly as they would over a normal ssh session. It just owns the
loop around that:
- On a dropped connection it restores your terminal, clears the screen, and reconnects with backoff. Your zellij session is still running on the remote, so you pick up where you left off.
- When you detach (
Ctrl+o dby default) or the session ends,zcexits cleanly instead of reconnecting. - If it can't connect in the first place — expired credentials, wrong host — it shows you ssh's actual error and gives up after a few tries, rather than looping forever.
zc setup # configure hosts (name, hostname, user, default session)
zc session work # ssh to your host and attach the "work" session
zc session # uses the host's default session
zc session --host desktop work
zc setup writes ~/.config/zc/config.toml. You can edit it by hand too:
default_host = "desktop"
[[host]]
name = "desktop"
hostname = "desktop.example.com"
user = "me"
default_session = "work"cargo install --git https://github.com/marcbowes/zc
The remote needs zellij on its PATH (or set zellij_path for that host in
the config). Set up your ssh keys / config so plain ssh yourhost works before
pointing zc at it.
Works for what I use it for. It wraps the ssh binary today; the connection
logic sits behind a small trait so other transports can slot in later.