xxh: bring your shell configuration to any SSH host without root or installs
🚀 Bring your favorite shell wherever you go through the ssh. Xonsh shell, fish, zsh, osquery and so on.
At a glance
- What is it?
- xxh packages a portable shell locally and uploads it over SSH, so your zsh, fish, bash, xonsh or osquery setup follows you to a remote host. It is for engineers who work on machines they cannot configure, and it trades a small amount of remote disk for that portability.
- Who is it for?
- Adopt xxh if you regularly SSH into hosts where you cannot install packages or edit system files, and you want your prompts, aliases and plugins to come along. Skip it if the remote host is ARM, since the README lists Linux on x86_64 as the supported target, or if you need a documented rollback, because the README does not document one.
- Can I use it commercially?
- Yes. BSD-2-Clause is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository last received commits 120 days ago.
- What is it written in?
- Mainly Python, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on September 29, 2026, and from our analysis. They are not legal advice.
Editorial analysis
The problem xxh solves for people who live in SSH sessions
You spend time on remote machines. Your local shell has aliases, a prompt theme, completion rules and plugins that you built up over years. The moment you type ssh, all of that disappears and you are back to a bare prompt with none of your habits. The usual fixes are worse than the problem: installing packages on the remote host needs root, copying dotfiles over is a blind overwrite that the README explicitly argues against, and asking an administrator to change the login shell is a request that often goes nowhere.
xxh takes a different route. It prepares the shell and its plugins locally, then uploads the result to the host over the existing SSH connection. The README describes the result as portable, meaning no installations and no root access on the host, and hermetic, meaning that deleting the ~/.xxh directory from the remote host makes the environment behave as if xxh was never there. That combination is the whole pitch: your environment arrives with you, and it leaves no trace you cannot remove with one directory deletion.
The audience is narrow but real. It is not for someone who administers a fleet of machines and can install whatever they want. It is for the consultant, the on-call engineer, the person debugging a customer's box, anyone who gets a login and nothing else.
How xxh works: local packaging, remote upload, entrypoint execution
The mechanism follows the description in the README and the repository layout. xxh is a Python package whose dependencies are pexpect and pyyaml, per pyproject.toml. pexpect is what lets a Python process drive an interactive SSH session, and pyyaml is what lets the shell and plugin definitions be declarative rather than hardcoded. The package installs a script named xxh plus three entrypoint files, xxh.zsh, xxh.xsh and xxh.bash, which are shipped as script files in the distribution.
Shell support is not built into the main package. Each shell lives in its own repository, for example xxh-shell-zsh, xxh-shell-fish, xxh-shell-bash, xxh-shell-xonsh and xxh-shell-osquery. When you run xxh against a host and name a shell, xxh fetches that shell repository, assembles it locally, and uploads the assembled directory to the remote host, where it runs as the session shell. Because the shell is a repository rather than a compiled artifact baked into xxh, you can fork it and point xxh at your fork. The README makes this explicit: every xxh repo could be forked, customized and reused without waiting for a package management system or an xxh release.
Plugins sit on top of that. Prerun plugins run before the shell starts and are how portable tools, dotfiles and aliases get into the session. The README names ohmyzsh, powerlevel10k, ohmyfish, fisher and ohmybash as existing plugin repositories, and notes that any type of tool could sit behind an entrypoint, including a portable browser. The README also states that xxh does not copy your local config files to the remote host by default, and recommends forking a plugin or shell example and packing your configs into it instead. That is a deliberate constraint, not an oversight: it keeps the remote environment reproducible and keeps your local files from being pushed somewhere you did not intend.
Installing xxh and running your first remote shell
The README lists several installation methods. The simplest is pip, which installs the package under the name xxh-xxh, not xxh. That naming detail matters because installing xxh from PyPI gets you something else.
pip install xxh-xxhIf you prefer isolated environments, pipx is listed as an alternative, and the README points to pipx's own comparison page for the reasoning.
pipx install xxh-xxhHomebrew, Macports, Conda-forge and xonsh's xpip are also listed as supported install routes. For a machine with no package manager at all, the README documents a portable musl Alpine tarball and an AppImage. The tarball route, copied from the README, looks like this.
mkdir ~/xxh && cd ~/xxh
wget https://github.com/xxh/xxh/releases/download/0.8.12/xxh-portable-musl-alpine-Linux-x86_64.tar.gz
tar -xzf xxh-portable-musl-alpine-Linux-x86_64.tar.gz
./xxhNote that the URL pins release 0.8.12 while the most recent releases listed for the project are 0.8.16 and 0.8.15. If you use the portable archive, check which version the link actually serves rather than assuming it matches the latest release.
Once installed, the first real use is a single command against a host you already have SSH access to. The README's example for choosing a shell is:
xxh anyhost +s xonshSubstitute anyhost for your host and xonsh for whichever shell you want. The README describes the choice as task-driven: xonsh when you want a Python environment, osquery for simple querying, fish for modern features, or zsh and bash for speed. If the shell you name is not already present locally, xxh fetches its repository, assembles it and uploads the result, so the first connection takes longer than later ones. What you should see is your prompt and your plugins inside the SSH session, with no packages installed on the host and no changes outside the ~/.xxh directory.
Where xxh stops being the right tool
The most concrete limitation is architecture. The README states that the currently supported OS for the target host is Linux on x86_64, and links to an open issue for ARM support that it attributes to the community. If your remote hosts are ARM machines, xxh is not a supported option today, and no amount of configuration changes that.
Support status varies by shell, and the README's own table is the honest source. xonsh, zsh, fish and bash are marked stable. osquery is beta. fish-appimage and elvish are alpha. Seamless mode, which the table tracks as a separate column, is listed for xonsh, zsh and bash, while fish shows a link to an open issue instead. If your workflow depends on seamless mode in fish, the README does not claim it works.
The hermetic design cuts both ways. Because your home is the .xxh directory by default, anything on the remote host that expects to read from your real home directory will not find what it expects unless you adjust the hermetic level, which the README points to a wiki page for. That is a real trade-off: you get a clean, removable environment, and you give up the assumption that the remote session looks like a normal login. The README also does not document rollback. There is no described procedure for reverting a session, which is consistent with the delete-the-directory approach but leaves nothing more granular.
Finally, xxh is the wrong tool when you control the host. If you can install packages and edit the login shell, doing that once is simpler than assembling and uploading a portable environment on every connection.
How xxh differs from copying dotfiles or using a config manager
The obvious alternative is scp-ing your dotfiles to the remote host and sourcing them. The difference is in what gets moved and who owns the result. Dotfile copying transfers your local files verbatim into a remote home directory, where they may conflict with whatever is already there and where they persist after you leave. The README argues against this directly, calling blindfolded copying a privacy and repeatability problem, and recommends packaging configs into a forked plugin instead. xxh uploads an assembled shell directory rather than your files, and by default that directory is the session's home, so removal is a single rm -rf ~/.xxh.
A configuration management tool such as Ansible or a dotfiles framework is the other comparison point, and here the difference is access. Those tools assume you can write to the host, install packages, or at least run a provisioning step with sufficient privileges. xxh assumes the opposite: you have an SSH login and nothing else. That assumption is what shapes every other decision in the project, including the fork-based customization model, which exists because there is no package manager on the remote side to distribute through.
The cost of that assumption is that xxh is not a configuration management system. It does not converge a host to a desired state, it does not run on a schedule, and it does not give you an inventory. It gives you one shell session that looks like yours, and it gives it to you on demand.
Editorial conclusion
Adopt xxh if you regularly SSH into hosts where you cannot install packages or edit system files, and you want your prompts, aliases and plugins to come along. Skip it if the remote host is ARM, since the README lists Linux on x86_64 as the supported target, or if you need a documented rollback, because the README does not document one. Before relying on it, check that the shell you want is listed as stable and that the release archive version you download matches the version you intend to run.
Frequently asked questions
What is xxh?
xxh is a tool that brings your shell and its plugins to a remote host over SSH without root access or a system installation. It prepares the shell locally, uploads it, and runs it as the session shell on the remote side.
How does xxh work?
xxh assembles a portable shell and its plugins locally, uploads the result to the host over the existing SSH connection, and runs it there. Your home in that session is the .xxh directory by default, so deleting that directory removes the environment.
Is xxh the same as the xxh-xxh package on PyPI?
The PyPI package for this project is named xxh-xxh, and the README's pip instructions are pip install xxh-xxh. The command you run after installing is xxh.
Which shells does xxh support?
The README lists xonsh, zsh, fish, bash, osquery, fish-appimage and elvish, each in its own repository. xonsh, zsh, fish and bash are marked stable, osquery is beta, and fish-appimage and elvish are alpha.
Which remote hosts can run xxh?
The README states that the currently supported OS for the target host is Linux on x86_64, with ARM support linked to an open issue and attributed to the community.
Can I remove xxh from a remote host?
The README describes the environment as hermetic: deleting the ~/.xxh directory from the remote host makes it function as if xxh was never there. The README does not document any other rollback procedure.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/xxh-xxh)