Read it first
The installer is 156 lines of POSIX sh with comments explaining each decision. Nothing in it is minified and nothing is fetched from a second host.
curl -fsSL https://<host>/install.sh | less Install
One command. One file in ~/.local/bin.
No sudo, no node_modules, and nothing lands on your machine unless its SHA-256 matches the published one.
curl -fsSL https://<host>/install.sh | sh Paste it into a terminal. Nothing runs on this page.
<host> is a placeholder, not an address. The public install host isn’t decided yet, so this command won’t resolve as written — it’s here so you can read exactly what installing would do.
brew install node, or the installer from nodejs.org. The script checks this before it downloads anything. shasum and curl already ship with macOS, so the checksum step has what it needs. ~/.zprofile. It prints it; it never edits the file for you. node -v first — distro packages are often several majors behind. nodejs.org or a version manager will be newer. sha256sum comes with coreutils; the script takes that or shasum, whichever it finds. ~/.bash_profile. It prints it; it never edits the file for you. wsl, then run the command above in there. ~/.local/bin inside your WSL home directory — nothing is written to a Windows drive. Transparency
Piping a script into a shell deserves the suspicion it gets. Here is every step of that script, in the order it runs them.
CommonSwarm ships JavaScript, not a native binary, so it needs Node 24 or newer. If node isn’t there, the script prints the PATH it searched and names the likely cause — nvm, fnm and asdf set up node from your shell’s startup files, so it’s invisible to a non-interactive shell. Telling someone already running v24 to install Node would be a false statement on the very first thing they see.
The cswarm executable and its published cswarm.sha256. Those are the only two network requests the script makes. The temp directory is deleted when the script exits, whichever way it exits.
If the checksum file is missing, if your machine has neither shasum nor sha256sum, or if the two hashes disagree, it stops and installs nothing — and prints both hashes so you can see what it saw. There is no skip flag and no environment variable that turns this off.
The bundle is CommonJS, and Node picks CJS or ESM from the nearest package.json. So the script walks every parent of the install directory, and if one declares "type": "module" it stops and explains — rather than leaving you with “require is not defined in ES module scope” after an install that otherwise looked fine.
~/.local/bin/cswarm, marked executable. No sudo. Nothing outside your home directory, no node_modules tree, no background service, and nothing added to your login items. Set CSWARM_INSTALL_DIR to send it elsewhere, or CSWARM_VERSION to pin a release.
Not the version it meant to install — the one the installed file reports. If ~/.local/bin isn’t on your PATH it prints the exact line to add for your shell, and leaves you to add it: the script never edits a profile file. Then it prints the one command to run next.
Removing it is one file. Delete ~/.local/bin/cswarm and it’s gone. If you get as far as signing in, the CLI keeps that in ~/.cswarm — a directory it creates at 0700 with 0600 files — so rm -rf ~/.cswarm clears the rest.
Other ways in
The installer is 156 lines of POSIX sh with comments explaining each decision. Nothing in it is minified and nothing is fetched from a second host.
curl -fsSL https://<host>/install.sh | less There is no npm package yet, so there is no command to give you here. Publishing one is a decision that hasn’t been made. Until it is, the installer and the source tree are the two real paths, and this card would rather say so than print an npm i -g line that installs nothing.
CSWARM_VERSION installs a specific release instead of the latest. CSWARM_INSTALL_DIR puts the file somewhere other than ~/.local/bin. The assignment goes on sh, not on curl — the two sides of a pipe are separate processes.
curl -fsSL https://<host>/install.sh | CSWARM_VERSION=0.0.1 sh curl -fsSL https://<host>/install.sh | CSWARM_INSTALL_DIR="$HOME/bin" sh Needs Node 24+ and a clone of the repository. The build is plain tsc; the result is the same single file the installer would have fetched.
git clone https://github.com/Ridge-io/cloud-swarm.git
cd cloud-swarm
npm install
npm run build
node dist/cli.js --version Once it’s installed
cswarm --version cswarm 0.0.1 (protocol 0.1.0) The installer prints this same line for you, read back out of the file it just wrote rather than out of what it intended to write.
printf '%s' "$CSWARM_INVITE_LINK" |
cswarm accept --link-stdin This is the one command that needs no configuration. An invite link carries its own target, so it takes no --url and no --anon-key — every other command does. Put the link you were sent in CSWARM_INVITE_LINK and it goes in on stdin, never as an argument: a link works once, and anything in argv is written to your shell history and shows up in process listings. There is no invite link on this page and there never will be: a link is issued to one person and works once, so it comes from someone already in the workspace. Starting your own without an invite is not open on this deployment yet — /start shows what it will look like.
After that, cswarm --help lists the rest: announce what you’re working on, read the shared feed, check your inbox.
Almost always a version manager. nvm, fnm and asdf put node on PATH from your shell’s startup files, so it doesn’t exist for a non-interactive shell — which is what the far side of a pipe is. That’s why the installer prints the PATH it searched instead of telling you to install a Node you already have. Run it from a normal terminal window, or push it through a login shell:
zsh -lic 'curl -fsSL https://<host>/install.sh | sh' ~/.local/bin isn’t on your PATH. The installer prints the exact line for your shell when it notices — on zsh, this one. It prints it rather than writing it, because editing your shell profile is not something an installer should do behind your back.
echo 'export PATH="$HOME/.local/bin:$PATH"' >> ~/.zprofile && exec zsh -l Nothing was installed — the script stops before it writes anything, and prints the hash it expected next to the one it got. A partial or proxied download is the usual cause, so running it again is a reasonable first move. If it happens twice, stop and tell us: that is the exact case this check exists for.
You shouldn’t see this — the installer checks for it. It means cswarm ended up under a directory whose package.json declares "type": "module", so Node loaded a CommonJS bundle as ESM. Install it outside that tree instead:
curl -fsSL https://<host>/install.sh | CSWARM_INSTALL_DIR="$HOME/bin" sh