How Kamui works
The connection
kamui foo hands foo to the system OpenSSH client as a single argument and
keeps that connection open in a background controller, so you don't run ssh
first. Anything ssh foo understands works: aliases, user@host, jump hosts,
keys, and Tailscale MagicDNS names. Kamui rejects destinations that start with
- so they can't be read as OpenSSH options.
One session exists per exact destination. Running kamui foo again reuses it
and applies the current port policy without reconnecting. kamui stop foo
closes the session, its OpenSSH process, and every mirrored port.
Mirroring ports
Kamui keeps one discovery command open over SSH. Every second it lists the
TCP ports listening on the remote machine with ss, lsof, or netstat,
whichever exists. Ports 1 through 1023 are skipped unless you include them
with --include-port, and --exclude-port skips more.
For each remaining port, Kamui listens on the same port on your laptop's
127.0.0.1 and ::1 and carries each connection through SSH to the remote
loopback, trying IPv4 first and IPv6 second. A port is mirrored only when both
local addresses are free.
Because discovery runs every second, short-lived ports work too. When a remote
agent starts an OAuth sign-in, such as for an MCP server, its callback port is
mirrored before you finish signing in, so the provider's redirect to
http://localhost:<port>/callback reaches the agent instead of your laptop.
When ports collide:
- A program already listening on your laptop keeps its port.
- If two Kamui sessions see the same port, the first one keeps it. The other
reports a conflict in
kamui statusand retries every five seconds. - A program that starts on your laptop after Kamui claimed a port gets
address already in use.
If discovery fails or goes quiet for ten seconds, Kamui keeps the current
ports, shows the error in kamui status, and restarts discovery five seconds
later. When a remote service stops, its local port goes away on the next pass.
Mirroring only opens unprivileged loopback listeners. It doesn't change proxy settings, firewall rules, or network extensions, and it doesn't carry UDP, QUIC, or HTTP/3.
Reconnecting
A dropped SSH connection breaks open TCP streams and WebSockets. Kamui
reconnects in the background, and new connections work once it succeeds.
Background reconnects never prompt. If one needs a passphrase or another
answer, kamui status shows authentication-required; run kamui foo in a
terminal and Kamui relays OpenSSH's prompts to it.
Port discovery opens its own SSH connection that can't prompt. Mirroring
therefore needs authentication that works without a prompt once you've
connected, such as an ssh-agent key (AddKeysToAgent yes helps), a key without
a passphrase, or a ControlMaster in your SSH config.
The dedicated browser
kamui browser foo starts an isolated browser profile that sends localhost,
*.localhost, 127.0.0.0/8, and ::1 to the remote machine through a local
proxy. Other addresses connect directly. It doesn't open ports for other
programs on your laptop; run kamui foo too if you want both. The browser and
mirroring share one session per destination.
With --browser-loopback local-first, the profile tries your laptop's
loopback first and falls back to the remote machine only when both local
addresses refuse the connection. HTTP errors, TLS errors, and timeouts don't
trigger the fallback, and open connections stay where they started.
Warning
Remote content in that profile gets the browser's localhost trust. In
local-first mode it can also reach real services on your laptop, and the same
origin can switch machines when a listener starts or stops. Keep the profile
for development and use it only with hosts you trust.
Safari isn't supported. On Linux, Kamui finds Chrome, Chromium, Brave, Edge,
Firefox, Firefox ESR, Firefox Developer Edition, Zen, LibreWolf, and Floorp on
your PATH, but not Flatpak or AppImage launchers. kamui browsers lists what
it found.
Starting from an SSH login
kamui print-ssh-config foo prints a LocalCommand snippet that starts
mirroring whenever you ssh foo. Review it and add it to your SSH config
yourself. Kamui's own SSH processes always run with PermitLocalCommand=no, so
the hook can't call itself. Set openBrowserOnSSH to true in the
configuration to open the dedicated browser as well.
Upgrades and state
After you upgrade kamui, the next command that connects notices the old
controller, replaces it, and retries. That destination comes back on its own;
start any other sessions again. kamui status reports the old controller
instead of replacing it, so polling never ends sessions.
OpenSSH diagnostics go to a private log that kamui logs prints. On macOS it's
~/Library/Application Support/kamui/logs/openssh.log; on Linux it's
$XDG_STATE_HOME/kamui/logs/openssh.log, by default
~/.local/state/kamui/logs/openssh.log. Run kamui stop --all before deleting
Kamui's state.
Why not something else
Exposing every dev server on a Tailscale network avoids SSH forwards, but it
means changing bind addresses, firewall rules, or project config. A browser
proxy avoids that, but only helps the browser, not curl or desktop apps.
Kamui keeps remote services on loopback, needs no list of ports, and works
with any destination plain ssh reaches.