Install
One binary, into ~/.local/bin.
Pick your platform
brew trust --tap sophonz-labs/tap
brew install sophonz-labs/tap/stHomebrew 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 | shIt 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.
curl -fsSL https://dl.sophonz.io/install.sh | shIt lands in ~/.local/bin/st, and if that is not on your PATH the script says
how to add it in the syntax of the shell you use.
curl -fsSL https://dl.sophonz.io/install.sh | shThe script picks the build from uname -m, so this is the same line as on
x86-64, and it lands in the same place: ~/.local/bin/st.
irm https://dl.sophonz.io/install.ps1 | iexNative, in Windows Terminal or anywhere else: st.exe lands in
%LOCALAPPDATA%\Programs\sophonz and that goes on your PATH. The shell it
shares is PowerShell, or whatever st --command cmd.exe names, kept alive by
psmux, a tmux for Windows that comes with it. See
Windows below for what differs there.
curl -fsSL https://dl.sophonz.io/install.sh | shInside WSL this is Linux: the linux-x64 build lands in ~/.local/bin/st, and
tmux is whatever your distribution ships — which is the one thing the native
build cannot have.
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 | |
|---|---|
| ttyd | inside the binary |
| tmux | yours if you have one, otherwise inside the binary |
| zellij | inside the binary |
| psmux (Windows) | yours if you have one, otherwise inside the binary |
| web assets and font | inside the binary |
| cloudflared | fetched 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 shWindows
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 upgradeRuns 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,ststarts the newest kept one that works instead.
st rollback # put the previous version back and move the share onto itWindows
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 binaryThat 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 restartSigned 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 binaryst upgradereplacesst.exewhile it runs. A runningst.execannot 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, andstill sharing on the old version — st restart moves it oversays so: runst restartnext.st restartis safe inside the share from v0.3.52. Before that, every terminal opened afterwards ended at once with "session ended". Runningst upgradefirst avoids it: thest restartthat follows is the new binary. If it has already happened, runst restartonce 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 exitorStop-Process -Name stinside 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 holdsst.exeopen (an st started as administrator, say); that is for someone sitting at the PC. - A share started with
--mux noneloses 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 withst --versionthat 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 runningst exit still means stopped: the service does not start it again until you run st. Its log is ~/.sophonz/keepalive.log.