Install Core
Two commands, and the first one prints the second. install.sh from main installs the latest release. Installing is not activating: the script places the bundle and stops. Nothing is running until you run setup.
curl -fsSL https://raw.githubusercontent.com/actana/control/main/install.sh | bash
actana setup
Run the actana setup line it printed. On a machine where ~/.local/bin was not on PATH when the shell started, that line is an absolute path rather than a bare actana.
The one-liner detects OS and CPU, downloads the matching Core tarball from the latest GitHub Release, checks it against that release's SHA256SUMS before extracting or running anything, copies the bundle to ~/.local/share/actana/versions/<version>, points ~/.local/share/actana/current at it, and links ~/.local/bin/actana — unless something else already answers to actana, in which case it leaves that one alone and says so.
The checksum catches a corrupted or truncated download: it proves the tarball is the one that release's own checksum file describes. Releases are not signed, so it is not a proof of origin — use https URLs, which the defaults do. A failed check leaves nothing installed.
Re-running both commands upgrades in place — same identity, one unit, every paired client stays paired. It is always safe to paste again.
Already have Node?
If the machine already has Node 22 or newer, you do not need the shell script:
npm i -g @actana/cli
actana install
actana install fetches the same release tarball, verifies it against SHA256SUMS, and runs setup — both halves in one go. install.sh stays the door for a machine with no Node: the tarball carries its own pinned runtime.
Installer flags, not setup flags
Piped, the run is non-interactive. The options install.sh takes are its own:
| Flag | Meaning |
|---|---|
--version <v> |
Install this exact version. A release (x.y.z) or a beta (x.y.z-beta). |
--repo <slug> |
Install from another GitHub repository. |
--base-url <url> |
Fetch releases from somewhere else. |
--help |
What this copy installs from, and the options it owns. |
curl -fsSL https://raw.githubusercontent.com/actana/control/main/install.sh | bash -s -- --version x.y.z
actana setup
ACTANA_VERSION, ACTANA_REPO and ACTANA_BASE_URL set the same three options. Anything else is refused, not ignored. --yes, --port, --public-host, --label, --with-<harness> and --no-harnesses belong on setup:
curl -fsSL https://raw.githubusercontent.com/actana/control/main/install.sh | bash
~/.local/bin/actana setup --public-host core1.example.com --yes
Platforms
A release publishes three Core builds: linux-x64, linux-arm64, and mac-arm64. The same two commands install either platform; what differs is the auto-start mechanism. Everything runs as your user, without sudo — the one exception is Linux lingering, below. The bundle carries its own Node runtime; the machine's system Node does not matter.
Linux
The auto-start unit is a systemd user unit (actana-core.service); systemctl --user must work. Lingering (loginctl enable-linger) makes the daemon survive logout, so a Core keeps running on a machine nobody is logged into. actana setup prompts for linger and tries it without sudo. If your distribution refuses that for a normal user, run it once with an administrator:
sudo loginctl enable-linger "$(whoami)"
WSL2 counts as Linux, with systemd enabled.
macOS
The auto-start unit is a LaunchAgent at ~/Library/LaunchAgents/com.actana.core.plist. It is tied to your login session:
- It starts when you log in, not when the machine boots.
- It stops when you log out. Locking the screen is fine; logging out is not.
- There is no linger equivalent that stays sudo-less — surviving logout would mean a root-owned LaunchDaemon, and this install does not do that.
A Mac Core wants to stay logged in: enable automatic login (System Settings → Users & Groups) if the Core has to be reachable after a reboot. The first time the daemon binds its port, macOS may ask whether to allow incoming connections — allow it, or the Panel cannot dial the Core. actana logs -f tails ~/Library/Logs/Actana/core.log.
On macOS, the piped bash line can fail on the stock bash 3.2 (asset…: unbound variable) — workaround in Troubleshooting.
Intel Mac
An Intel Mac has no on-device build and will not get one. The installer refuses at detection — before it downloads anything — and points you at the container image: run the core service from the Compose file on that machine instead.
Windows
Windows cannot host a Core natively, and the Panel has no native Windows install either. The Core is a daemon built around PTYs, POSIX paths, and user-unit supervision; on Windows those live in WSL2 or in Docker Desktop, and both already run the Core well:
- WSL2 — the one-liner above runs unchanged inside WSL2 with systemd enabled; the Windows-side CLI then dials it like any remote Core.
- Docker Desktop — the Docker Compose quickstart runs as-is in PowerShell.
The actana CLI itself is native on Windows, as a client of Cores elsewhere. The full mapping: Windows.
The port
The Panel dials the Core, never the reverse. The port you choose (default 8443) must be reachable from the Panel's machine:
sudo ufw allow 8443/tcp
Check from the Panel host with nc -zv <public-host> 8443. If the machine's address changed since setup, re-run actana setup --public-host <new-address> so the certificate covers it, then pair again.