hi.d

hi.d and the alternatives

An honest look at what else solves this problem, where hi.d is genuinely different, and where another tool is the better one. Written for someone deciding whether to use hi.d, not to sell it.

Contents

The problem being solved

You have a shell you have spent years tuning, and you spend your day on machines that are not yours: production boxes, a colleague’s server, a jump host, a container that will not exist in an hour. There you get sh-4.4$ and no ll.

There are two families of answer.

Install your config there. Dotfile managers — chezmoi, yadm, GNU Stow, dotbot, rcm, homeshick — or config management like Ansible. These are excellent, and hi.d does not compete with them: they assume the machine is yours, that you’ll be back, and that leaving files behind is fine. That fails for a shared production host, a box you touch once, or a container. The line blurs at the edge — chezmoi’s --one-shot applies dotfiles to an ephemeral machine then deletes chezmoi, and VS Code devcontainers can clone a dotfiles repo into every container — but both need the target to reach your repo over the network, both leave the files behind, and neither does anything per-session. hi.d pushes from the client, needs no network on the target, and cleans up.

Carry your config with you, per session. The tool ships your config over the connection, uses it for that session, and gets out. That is the family hi.d is in, and everything below is a member of it.

A third thing that looks similar but is not: terminal emulators that help with ssh, like kitty’s ssh kitten and wezterm’s ssh domains (which go further, with an optional persistent wezterm-mux-server on the remote). Those solve the adjacent and very real terminfo/shell-integration problem — kitty’s copies the xterm-kitty terminfo database, enables shell integration, and can copy files you list. If your pain is “backspace is broken over ssh”, that is the fix, and it composes with hi.d rather than competing. hi.d handles the terminfo half itself (_hi_remote_preamble probes the target’s terminfo tree, falling back to xterm-256color) precisely so it doesn’t depend on your terminal.

The direct alternatives, side by side

  hi.d sshrc xxh kyrat sshdot
Written in POSIX/bash shell shell Python bash shell
Client needs bash 3.2+, base64 bash, ssh a Python install (pip/pipx/conda) or the portable binary bash ≥ 4.0, GNU coreutils shell, ssh
Target needs base64; bash for the full session shell Linux x86_64 only shell shell
Target OS Linux (glibc + musl), macOS/BSD, Windows via WSL/Git Bash broad Linux x86_64 Linux, macOS broad
Installs on target nothing nothing a portable shell + plugins under ~/.xxh nothing nothing
Cleans up on exit yes, automatically leaves /tmp dir no — delete ~/.xxh yourself yes, automatically leaves files
Size ceiling ~40KB gzipped, enforced by CI ~64KB and the server may block you large — it uploads whole shells small none (that is its point)
Non-ssh targets docker, podman, nomad, k8s no no no no
Can give you a shell the host lacks no no yes no no
Maturity pre-1.0, not yet published to any channel original deleted from GitHub; cdown’s fork is the maintained line, argv ceiling inherited mature, active quiet quiet

Tool by tool

sshrc — the ancestor

hi.d is a fork of sshrc (via cdown’s and danrabinowitz’s lines), and the core idea is unchanged: tar your config, base64 it, hand it to the login shell, source it on the far side. Russell Stewart’s original repository was deleted from GitHub outright — not archived — so the links here point at cdown’s fork, the self-described maintained continuation, which carries the design (64KB argv ceiling included) unchanged.

Where sshrc still wins: it is smaller and simpler, and simplicity is a real feature in something that runs on every host you touch. If you just want your .bashrc and .vimrc over there, sshrc does it in a fraction of the code, and you can read all of it in one sitting.

Where hi.d went further, and why:

xxh — the one that solves a harder problem

xxh’s pitch is different and more ambitious: it uploads a portable build of the shell itself, so you can use fish or zsh on a host that has neither.

Where xxh wins outright: that capability. hi.d cannot give you a shell the target lacks — its no-bash ladder (fish > zsh > mksh > ksh > dash > ash > sh) picks the best of what is installed and says so. If you need your shell on a locked-down box that ships only sh, xxh is the answer and hi.d is not; its plugin model is also more principled than copying dotfiles blind.

Where hi.d wins:

kyrat — closest in spirit

kyrat is the nearest neighbour: a bash ssh wrapper, base64+gzip through the command line, cleanup on exit, KYRAT_SHELL to pick bash/zsh/sh. If the table above looks like a description of hi.d, that is because it nearly is.

The differences are narrow and concrete. kyrat requires bash ≥ 4.0, ruling out macOS’s system bash — the exact constraint hi.d contorts itself to respect (no mapfile, no associative arrays, no namerefs, enforced by a lint grep and a real bash-3.2 container in CI). kyrat spawns bash, zsh or sh; hi.d styles bash, zsh and fish, and gives the POSIX tiers a colored prompt and — for ksh/mksh — a live git segment. And kyrat is ssh-only.

sshdot

sshdot is sshrc without the size limit, achieved by not squeezing through the command line. Narrower in scope than hi.d; the honest summary is that it solves the one problem it names.

homeshick — the same constraints, the opposite answer

homeshick is a git dotfiles synchronizer written in bash, and it is the tool whose constraints look most like hi.d’s: “provided that at least Bash 3 and Git 1.5 are available you can use homeshick” — no Ruby, no Python, no root, no package manager. hi.d holds the same bash 3.2 floor for the same reason. That is where the resemblance stops, because it answers the other half of the problem. You homeshick clone a repo — a castle — into ~/.homesick/repos/, and homeshick link symlinks that castle’s home/ directory into $HOME; a line in your rc file sources homeshick.sh (or .csh/.fish), and track/pull/refresh keep the castle and the machine in step. Several castles compose, which is how people run oh-my-zsh beside their own config.

So it is not a competitor, and it is not in the table above. It is the tool for a machine you own and will come back to: the checkout stays, the symlinks stay, and the next login is already configured with no client involved. hi.d is for the machine you will not come back to — it pushes from the client, needs no git and no network on the target, and takes the tree away when the session ends. The failure modes are mirror images: homeshick on a production box you touch once leaves a ~/.homesick and an edited rc file behind for the next person; hi.d on your own laptop re-sends a payload every session to give you what a symlink would have given you for free.

Where homeshick wins outright: the machine is yours; you want your config there when you arrive rather than when hi says so; you want your dotfiles under plain git with plain symlinks and nothing clever in between. The two compose, too — install hi.d permanently on that box (scripts/install.sh) and let homeshick manage everything else.

Adjacent tools, and how they compose

None of these are alternatives — they touch the same session from a different side. Listed because people conflate them with the family above, or because the composition has a wrinkle worth knowing.

What actually makes hi.d different

Two things, and it is worth being precise because the rest is degree, not kind.

1. It is not an ssh tool. Every alternative above is an ssh wrapper. hi resolves a name through a ladder — ssh host, docker container, podman, nomad allocation, kubernetes pod — and gives the same session on whichever it finds. hi web-1 is your shell whether web-1 is a Host in ~/.ssh/config or a pod in the namespace your kubectl points at. For anyone moving between a server and the containers on it that is the feature, and nothing else in this space does it.

2. It degrades in stated tiers rather than failing or lying. The compatibility tables answer three questions — can hi land a session here, what must your login shell survive, what do you end up in — and mark every cell proven-by-a-suite, expected, reduced, or unsupported. A target with no bash gets aliases, a colored prompt, and a warning saying so; a Windows OpenSSH host with no POSIX shell gets a plain PowerShell session rather than an error. That stance is why the honest cells (🟡 “nobody has proven it”) are in the table at all.

Secondary but real: a per-user config overlay (settings, colors, packages, aliases) that rides along without dirtying the tree, hi --doctor for when something is slow, --tmux so a dropped connection detaches instead of losing work, and detecting a permanent ~/hi.d on the target to use in place.

Where hi.d is the wrong choice

Sources