{"id":13580105,"url":"https://github.com/shell-pool/shpool","last_synced_at":"2026-05-01T03:01:49.493Z","repository":{"id":225002192,"uuid":"764840732","full_name":"shell-pool/shpool","owner":"shell-pool","description":"Think tmux, then aim... lower","archived":false,"fork":false,"pushed_at":"2025-05-09T15:04:00.000Z","size":43027,"stargazers_count":1300,"open_issues_count":25,"forks_count":23,"subscribers_count":9,"default_branch":"master","last_synced_at":"2025-05-09T16:23:24.377Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Rust","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/shell-pool.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2024-02-28T20:03:59.000Z","updated_at":"2025-05-08T06:47:24.000Z","dependencies_parsed_at":"2024-04-11T15:38:57.297Z","dependency_job_id":"3e8273f3-e1d2-492a-aa63-3b5e64b65fd6","html_url":"https://github.com/shell-pool/shpool","commit_stats":null,"previous_names":["shell-pool/shpool"],"tags_count":28,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/shell-pool%2Fshpool","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/shell-pool%2Fshpool/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/shell-pool%2Fshpool/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/shell-pool%2Fshpool/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/shell-pool","download_url":"https://codeload.github.com/shell-pool/shpool/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":254043961,"owners_count":22005042,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-08-01T15:01:47.316Z","updated_at":"2026-05-01T03:01:49.481Z","avatar_url":"https://github.com/shell-pool.png","language":"Rust","funding_links":[],"categories":["Rust"],"sub_categories":[],"readme":"# shpool\n\n`shpool` is a service that enables session persistence by allowing the\ncreation of named shell sessions owned by `shpool` so that the session\nis not lost if the connection drops. `shpool` can be thought of as a lighter\nweight alternative to `tmux` or GNU `screen`. While `tmux` and `screen` take over\nthe whole terminal and provide window splitting and tiling features, `shpool`\nonly provides persistent sessions. The biggest advantage of this approach is\nthat `shpool` does not break native scrollback or copy-paste.\n\n## Platform Support\n\n`shpool` runs on linux and mac. Linux is the primary supported platform\nand mac currently still has a few tests which don't pass. HACKING.md\nhas more info on the state of mac support. You may want to examine the\ntest tree to see which tests are currently disabled to see the current\nstate of mac support.\n\n## Installation\n\n### Installing from crates.io\n\n#### Using systemd to run the daemon\n\nRun\n\n```\ncargo install shpool\ncurl -fLo \"${XDG_CONFIG_HOME:-$HOME/.config}/systemd/user/shpool.service\" --create-dirs https://raw.githubusercontent.com/shell-pool/shpool/master/systemd/shpool.service\nsed -i \"s|/usr|$HOME/.cargo|\" \"${XDG_CONFIG_HOME:-$HOME/.config}/systemd/user/shpool.service\"\ncurl -fLo \"${XDG_CONFIG_HOME:-$HOME/.config}/systemd/user/shpool.socket\" --create-dirs https://raw.githubusercontent.com/shell-pool/shpool/master/systemd/shpool.socket\nsystemctl --user enable shpool\nsystemctl --user start shpool\nloginctl enable-linger\n```\n\n#### Without systemd\n\nTo install without setting up systemd, run\n\n```\ncargo install shpool\n```\n\nIf you don't use systemd, you can either port the `systemd/shpool.service`\nfile to your own init system and use that, or you can use autodaemonization\nmode to tell shpool to just fork a daemon process on the fly if it notices\none is missing. Autodaemonization is enabled by default, so you don't\nneed to do anything special to use it, though you can control its behavior\nwith the `nodaemonize` config option and the `-d/-D` command line switches.\n\n### Installing with Homebrew\n\nOn macOS, `shpool` can be installed via the project's [Homebrew tap](https://github.com/shell-pool/homebrew-shpool):\n\n```\nbrew tap shell-pool/shpool\nbrew install shpool\n```\n\nTo have the daemon start automatically at login:\n\n```\nbrew services start shpool\n```\n\n## Usage\n\nGenerally `shpool` is used to provide persistent sessions when\nsshing in to a remote host. To do so, `shpool` must be installed\non the remote host. No extra software is required on the client.\nAfter installing and setting up, the typical usage pattern\nis to ssh into the host you have installed shpool on, then create\na new named session by running `shpool attach main`. Here `main`\nis the name of the session. You'll want a separate named session\nfor each terminal you use to connect to your remote host. If your\nconnection drops or becomes stuck, you can ssh back into the remote\nhost and re-attach to the same named session by running `shpool attach main`\nagain.\n\nIf your terminal gets stuck and you forcibly close the window, you\nmight find that `shpool` still think a terminal is connected to\nyour session when you attempt to reattach. This is likely because\nan ssh proxy is holding the connection open in the vain hope that\nit will get some traffic again. You can just run `shpool detach main`\nto force the session to detach and allow you to attach.\n\nThis README covers basic usage, but you can also check out\n[the wiki](https://github.com/shell-pool/shpool/wiki) for\nmore tips and tricks.\n\n### [Troubleshooting](https://github.com/shell-pool/shpool/wiki/Troubleshooting)\n\nThe [troubleshooting](https://github.com/shell-pool/shpool/wiki/Troubleshooting)\nwiki page contains some information about known pitfalls.\n\n### [Configuration](./CONFIG.md)\n\nYou can customize some of `shpool`s behavior by editing your\n`~/.config/shpool/config.toml` file. For an in depth discussion\nof configuration options see [CONFIG.md](./CONFIG.md).\n\n### Keybindings\n\n`shpool` supports keybindings (well really for the moment it\nsupports keybinding, but in principle we could add more).\nFor the moment, the only binding is `Ctrl-Space Ctrl-q`\nto detach from the current session. If you wish, you can\n[configure](./CONFIG.md#detach-keybinding) this to use\na different keybinding. The full list of supported binding\nactions is defined by the `Action` enum in [`keybindings.rs`](./libshpool/src/daemon/keybindings.rs).\n\n### Shell Config\n\n##### bash\n\nIf you use bash, you may want to ensure that the `huponexit` option\nis set to make sure that child processes exit when you leave a\nshell. Without this setting, background processes you have\nspawned over the course of your shell session will stick around\nin the `shpool` daemon's process tree and eat up memory. To set\nthis option add\n\n```\nshopt -s huponexit\n```\n\nto your `~/.bashrc`.\n\n### Subcommands\n\n#### shpool daemon\n\nThe `daemon` subcommand causes `shpool` to run in daemon mode. When running in\nthis mode, `shpool` listens for incoming connections and opens up subshells,\nretaining ownership of them in a table. In general, this subcommand will not\nbe invoked directly by users, but will instead be called from a systemd unit\nfile.\n\n#### shpool attach\n\nThe `attach` subcommand connects to the `shpool daemon` instance, passing in a\nname. If the name is new, a new shell is created, and if it already exists it\njust attaches to the existing session so long as no other terminal is currently\nconnected to that session. The `--ttl` flag can be used to limit how long the\nsession will last.\n\n#### shpool list\n\nLists all the current shell sessions.\n\n#### shpool detach\n\nDetach from a one or more sessions without stopping them.\nWill detach the current session if run from inside a `shpool`\nsession with no session name arguments.\n\n#### shpool kill\n\nKills a named shell session.\n\n### (Optional) Automatically Connect to shpool\n\n#### Explicitly named sessions\n\nSpecifying session names yourself lets you assign logical\nroles such as text editing to each session.\n\n##### ssh config\n\nIf you typically connect to a small number of sessions with\nthe same jobs on a particular machine, custom ssh config\nblocks on your client machine are probably the best\nfit.\n\nTo do this, you can define \"hosts\" for sessions named `main` and `edit`\nin a config block in `~/.ssh/config` on your client machine, like so\n\n```\nHost = main edit\n    Hostname remote.host.example.com\n\n    RemoteCommand shpool attach -f %k\n    RequestTTY yes\n```\n\nYou can then attach to these sessions with `ssh main` or `ssh edit`.\n`%k` expands to the \"host\" named on the command line.\n\n##### shell function\n\nIf you would rather have a little more flexibility in\nspecifying the session name and machine you are targeting,\nyou can make a custom shell function to let you specify\nboth at invocation time. Add\n\n```\nfunction shpool-ssh () {\n    if [ $# -ne 2 ] ; then\n        echo \"usage: shpool-ssh \u003cremote-machine\u003e \u003csession-name\u003e\" \u003e\u00262\n        return 1\n    fi\n    ssh -t \"-oRemoteCommand=shpool attach -f $2\" \"$1\"\n}\n```\n\nto your `.bashrc` then invoke it like\n`shpool-ssh remote.host.example.com main`.\n\n#### Local tty based\n\nRather than specify an explicit name when you connect, you\ncan set up your system to automatically generate a `shpool`\nsession name based on your local terminal emulator's tty\nnumber. To do so, you can add a block of custom ssh config\nin the `~/.ssh/config` of your local machine like\n\n```\nHost = by-tty\n    User remoteuser\n    Hostname remote.host.example.com\n\n    RemoteCommand shpool attach -f \"ssh-$(basename $(tty))\"\n    RequestTTY yes\n```\n\nwhich you then invoke with `ssh by-tty`. You can apply the same principle\nof using `$(basename $(tty))` to get a unique id for your local terminal\nto the custom shell function approach as well.\n\nThe local-tty based approach has the advantage that you don't\nneed to specify a session name, but it can run into problems\nif you have to close the local window and open a new terminal,\nwhich can come up if your connection freezes rather than drops.\n\n## Comparison with other tools\n\n### `tmux` and GNU `screen`\n\n`tmux` is probably the best known session persistence tool, and\nGNU `screen` has a similar feature set, so in comparison to `shpool`\nit can be thought of as belonging to the same category.\n\nThe main way that `shpool` differs from `tmux` is that `tmux` is a\nterminal multiplexer which necessarily means that it offers session\npersistence features, while `shpool` only aims to be a session\npersistence tool. In contrast to `tmux` the philosophy of `shpool`\nis that managing different terminals is the job of your display or\nwindow manager, not your session persistence tool. Every operating\nsystem has its own idioms for switching between applications, and\nthere is no reason to switch to different idioms when switching\nbetween terminals. Especially for users of tiling window managers\nsuch as `i3`, `sway` or `xmonad`, tmux's multiplexing features are\nredundant.\n\nWhile `tmux` renders terminal contents remotely and only paints\nthe current view to the screen, `shpool` just directly sends\nall shell output back to the user's local terminal. This means\nthat all rendering is handled by a single terminal state machine\nrather than going through `tmux`s internal in-memory terminal\nbefore getting formatted and re-rendered by the local terminal.\nThis has performance implications, and probably most\nimportantly means that a terminal using `shpool` will feel\ncompletely native. Scrollback and copy-paste will work exactly\nas they do in your native terminal, while they can behave differently\nwhen using `tmux`.\n\n### [`mosh`](https://github.com/mobile-shell/mosh)\n\n`mosh` is another tool focused on providing persistent remote shell\nsessions. It differs from the other tools discussed here in that it\nhas its own network protocol, which it bootstraps off of regular\nssh. Like `tmux`, it renders the screen contents remotely and sends\njust the current view back. It is somewhat unique in trying to\npredicatively guess the right output to display to the user if\nthere is a network lag.\n\n`shpool` differs from `mosh` in that it has nothing to do with\nthe network, remaining confined to a single machine like most of\nthese other tools. Just like in the case of `tmux`, `mosh` will\nimpact the way scrollback and copy-paste work, while `shpool`\nkeeps them feeling entirely native.\n\n### [`dtach`](https://github.com/crigler/dtach), [`abduco`](https://github.com/martanne/abduco), and [`diss`](https://github.com/yazgoo/diss)\n\nThese tools have the most in common with `shpool`. Just like `shpool`, they\neschew multiplexing and just send the raw bytes back to you for your local\nterminal to render. While you could say that `shpool` aims to be a\nsimpler version of `tmux`, these tools follow the same philosophy with\nan even greater laser focus on simplicity and doing one thing well.\n\n`shpool` aims to be an easy and pleasant experience for people\nwho just want session persistence without having to care about\nit too much, so it has a few more \"cushy\" features that would\nnot be as good a fit for the focus on simplicity of these\ntools.\n\nThe most obvious of these features is the difference between\nhow `shpool` and these programs handle re-attaches. Though under normal operation,\n`shpool` does not do any rendering and subsetting of the shell\noutput, it continually maintains an in-memory render of the\nterminal state via the [`shpool_vt100`](https://crates.io/crates/shpool_vt100)\ncrate. On reattach, `shpool` will use this in-memory render to\nre-draw the screen, so you can easily see where you were when\nyour connection dropped. This even allows you to see output\ngenerated after your connection dropped.\n\nAnother such feature is the automatic prompt prefix. `shpool`\nwill detect when you are using a known shell (currently\n`bash`, `zsh`, or `fish`) and automatically inject a prefix\ninto your prompt to let you know the name of the `shpool` session\nyou are in. This adds some nice context so you don't lose\ntrack of your terminals and have some hint about the current\nterminal state.\n\nThere are also some features `shpool` is missing which these\nprograms have. In particular, it seems that `dtach` and `abduco`\nsupport shared sessions, while `shpool` only allows a single\nclient to be connected to a particular session at a time.\nThere may be more since I don't know these tools as well\nas `shpool`.\n\n## Hacking\n\nFor information on how to develop shpool, see [HACKING.md](./HACKING.md).\n\n## Release Notes\n\n...can be found in [debian/changelog](./debian/changelog).\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fshell-pool%2Fshpool","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fshell-pool%2Fshpool","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fshell-pool%2Fshpool/lists"}