Install

One binary, into ~/.local/bin.

Pick your platform

brew trust --tap sophonz-labs/tap
brew install sophonz-labs/tap/st

Homebrew asks before it loads a tap that is not its own, so brew trust comes first.

Or without Homebrew:

curl -fsSL https://dl.sophonz.io/install.sh | sh

It lands in ~/.local/bin/st — Homebrew puts it in its own prefix instead — and if ~/.local/bin is not on your PATH, the script says how to add it in the syntax of the shell you use.

It runs on macOS 13 or later, the tmux and ttyd it carries included.

Intel Macs have no published build. Building one needs an Intel Mac to build it on; from a checkout of the st source on that machine, make build writes dist/st.

Whichever route, what lands is one binary, and it carries what it needs: ttyd, a multiplexer, its own web assets and the font. There is nothing to install first.

Bundled components

where it comes from
ttydinside the binary
tmuxyours if you have one, otherwise inside the binary
zellijinside the binary
psmux (Windows)yours if you have one, otherwise inside the binary
web assets and fontinside the binary
cloudflaredfetched once, on the first run that asks for a tunnel

tmux is what st uses wherever there is one: it is the only backend where two browsers can be on different windows of one session at once. Your own comes first, so st can attach to the session your tmux is already running. The carried one is for the machine that has none. Windows is the exception: there is no native tmux, so psmux takes its place.

cloudflared is fetched once into ~/.sophonz/bin, pinned to a version and checked against a recorded SHA-256. st --no-tunnel never needs it.

Somewhere else, or some other version

curl -fsSL https://dl.sophonz.io/install.sh | ST_INSTALL_DIR=/usr/local/bin sh
curl -fsSL https://dl.sophonz.io/install.sh | ST_VERSION=v0.3.116 sh

Windows

st.exe lands in %LOCALAPPDATA%\Programs\sophonz and that directory is added to your PATH. It shares the shell you are in — PowerShell by default, or whatever st --command cmd.exe names — and the tunnel and the browser side are the same as everywhere else.

psmux, not tmux. Windows has no native tmux, so psmux — tmux for Windows, native on ConPTY and speaking tmux's commands — is what keeps the session alive when the browser goes away, with zellij as the fallback (--mux zellij). psmux has no session groups, so two browsers on one session see the same window.

A tmux on your PATH there is ignored: the ones packaged for Windows are Cygwin builds, which cannot run a native Windows console program.

WSL is the other way in, and the tab above has its line. Inside it this is Linux — the linux-x64 build, and your distribution's tmux — so a session started there is a Linux session, not a PowerShell one.

Upgrading

st upgrade

Runs the install script again against the directory this binary is already in, so installing elsewhere does not leave a second copy in ~/.local/bin.

Once the new version is in place it lists what's new since the one it replaced (st 0.3.78 and later): each release, newest first, with what it changed. A long jump shows the latest eight and points to Download for the rest.

Installed with Homebrew? Then Homebrew owns the file: brew upgrade st, then st restart to move the share onto it. st upgrade says so rather than write over Homebrew's copy.

From the phone. When a machine's st has an update, the app says "Update available" on the machine. Update st does exactly what st upgrade does, on the machine, and shows each step. The link stays the same and sessions keep running; if the new version does not answer through the same tunnel within a minute and a half, the version you had goes back in place and the share returns to it. It is not offered for a Homebrew install, or for a machine with a tunnel that is not signed in (its address is the only way in). Try it on a machine you can reach some other way first.

From the desktop app (0.1.32 and later). A machine whose st is behind gets ↑ v… on its row in the sidebar, this machine and the others alike; the row's right-click menu has Update st to v… too. It asks first and shows what changed since the machine's version, then the steps on the row. It does what Update st does on the phone, and is not offered in the same cases.

An upgrade cannot take a running share down:

  • The new binary checks itself first — its ttyd starts and serves a page — before the running agent is asked anything. If it fails, the version you had goes back in place and the share is not touched.
  • If the new agent still does not come up after the old one stepped aside, the version that was running takes the port and the tunnel back.
  • Every version that has run a share here is kept in ~/.sophonz/bin (the last three). If a start's self-check fails, st starts the newest kept one that works instead.
st rollback           # put the previous version back and move the share onto it

Windows

Windows hands the share over the same way since st 0.3.73: st upgrade moves it onto the new binary and the address stays. Only a share that an older st started cannot be handed over, because its tunnel closes with it. For that one, st upgrade installs the new binary, leaves the share on the old version and says still sharing on the old version — st restart moves it over.

st restart            # stop the share and start it again, on this binary

That is what st restart is for, and it is the only thing to run, not st exit and then st, which needs a second way into the machine to run its second half, and on a machine reached only through this share there is none.

What it keeps:

  • The session. The session and everything running in it is still there afterwards.
  • The port and the token, so a token link opens the new address with the same token.
  • The link on your account, for a machine that is signed in: the slug is the machine's, not the tunnel's.

What it does not keep, for a share from before st 0.3.73, is the trycloudflare.com address: a new cloudflared means a new one, and st restart prints it. From 0.3.73, and on macOS and Linux, there is nothing to lose: the tunnel is handed over and the address stays.

Sign in first, or the address is all you have

With the link on your account, the address can be thrown away. Without an account there is no such link, and restarting a Windows share from before st 0.3.73 leaves you unable to get back into a machine you can only reach through the share:

  • the old address stops working the moment the agent goes,
  • the new one is printed into the session — which the browser on the old address can no longer reach,
  • and nothing else knows where the machine went.

st restart says so and asks before going ahead when it is certain to happen. Answer it with st login instead: the machine then keeps a stable link, and the address underneath it can change as often as it likes.

st login              # once per machine
st restart

Signed in, none of this applies anywhere — the link is the same afterwards.

Upgrading from PowerShell inside the share

st upgrade and st restart can both be run from the shared PowerShell itself. On a machine reached only through this share, that is the usual place. In this order:

st upgrade            # installs the new binary; the share keeps running the old one
st restart            # moves the share onto the new binary
  • st upgrade replaces st.exe while it runs. A running st.exe cannot be overwritten, so the install script renames the old file and puts the new one in its place. A share from st 0.3.73 or later is then handed over to it. A share from an older st goes on running the old version, and still sharing on the old version — st restart moves it over says so: run st restart next.
  • st restart is safe inside the share from v0.3.52. Before that, every terminal opened afterwards ended at once with "session ended". Running st upgrade first avoids it: the st restart that follows is the new binary. If it has already happened, run st restart once more from a terminal outside the share — a PowerShell opened on that PC, or Remote Desktop.
  • After restarting an older share, open tabs have to be opened again. The address changes, so a browser tab on the old one does not reconnect. Opening the link on your account again (from the dashboard or the app too) goes to the new address. The session and everything running in it is still there.
  • Do not run st exit or Stop-Process -Name st inside the share. Once the share is down there is no way back in to start it. The install script suggests both when it stops because something holds st.exe open (an st started as administrator, say); that is for someone sitting at the PC.
  • A share started with --mux none loses its shell. There is no psmux holding it, so the shell ends with the restart. The share itself does come back.
  • PowerShell 7 (pwsh) works too, from v0.3.51. If an older st was upgraded from pwsh, check with st --version that the version really changed.
  • On Windows the new binary's ttyd is checked first too (from v0.3.53). The self-check above starts ttyd there as well and asks it for its page. A version that fails it is not moved onto, and the share is left alone. The new binary runs the check, so it applies to any upgrade to v0.3.53 or later, whatever version it starts from.

Keep the share running

Opt-in. Registers st with launchd (macOS) or systemd --user (Linux), so the share starts at login and again whenever it is not running — after a crash, a reboot, or a broken upgrade (three failed starts in ten minutes and it starts a kept earlier version).

st service install [--session name] [--no-tunnel]
st service status
st service uninstall  # the share itself keeps running

st exit still means stopped: the service does not start it again until you run st. Its log is ~/.sophonz/keepalive.log.