CLI
The ruust command line: sign in, hatch an Egg from a repo, list your Eggs, read logs, open a shell in a container, and drive the rest over the versioned /api/v1 REST API.
The ruust command line is a small Go binary that talks to the Ruust control plane over the versioned /api/v1 REST API. It is deliberately focused: sign in, hatch an Egg from a Git repo, list the Eggs you own, read their logs, open an interactive shell in a container, and open an Egg in your browser. Running ruust with no subcommand opens an interactive dashboard of your Eggs when you are signed in, where pressing s on a selected Egg opens its shell. Anything the CLI does not yet have a command for (setting environment variables, adding a custom domain) is done in the dashboard or by calling the same REST API directly, which this page shows.
Install it
The CLI is open source at [github.com/RuustRun/cli](https://github.com/RuustRun/cli). The quickest way to install it on macOS or Linux is Homebrew. You can also grab a prebuilt binary for your platform from the latest release, or build it yourself with Go 1.24 or later.
brew install ruustrun/tap/ruust
ruust versiongit clone https://github.com/RuustRun/cli.git
cd cli
go build -o ruust .
mv ruust /usr/local/bin/ruust
ruust versionSign in
Run ruust login. It opens your browser, you sign in on the website and approve this computer, and no password is ever typed into the terminal. The returned session token is written to ~/.config/ruust/config.json with owner-only permissions, and every other command reads it from there. Use ruust whoami to confirm who you are signed in as, and ruust logout to forget the token on this machine (your Eggs keep running). For CI, pass --email and --password to sign in without a browser, or set RUUST_TOKEN directly (see Configuration).
ruust login
# --no-browser prints the sign-in link instead of opening it.
# For CI, sign in without a browser:
ruust login --email [email protected] --password "$RUUST_PASSWORD"Deploy it
- Push your app to a Git repository Ruust can reach.
- Run
ruust loginif you have not signed in on this machine. - Run
ruust create --repo <git url>to hatch a new Egg, adding--regionand--tierif you want something other than the defaults. - Watch it go from incubating to hatched with
ruust logs <name>. - Open the live Egg with
ruust open <name>.
ruust create \
--repo https://github.com/you/app.git \
--branch main \
--region eu-west \
--tier standardThe --repo flag is the only required one. --branch defaults to main, --region to eu-west (London; us-east is Virginia), and --tier to standard. ruust deploy is an alias of ruust create, so either name works.
List and inspect Eggs
Run ruust ls (aliases ruust eggs and ruust list) to see every Egg you own as a table of name, region, tier, lifecycle state, and URL, with the flat monthly total in GBP. Read an Egg's recent log lines with ruust logs <name>, narrow the output with --lines N, and jump straight to a hatched Egg in your browser with ruust open <name>.
ruust ls
ruust logs my-egg --lines 100
ruust open my-egg
ruust statusShell into a container
Run ruust shell <name> to open an interactive shell inside an Egg's running container, like docker exec -it but to a container on a Ruust host. It is a real terminal, so tab completion, colours, and resizing work, and you land as the container's user (usually root) in its working directory. Type exit or press Ctrl-D to leave. The first connection can pause for up to about ten seconds while the host picks the session up on its next poll, which is normal, not a hang. The dashboard has the same thing behind a Shell tab on the Egg page. See [Shell access](/docs/shell) for the full picture.
ruust shell my-egg
# root@36cb0f65a247:/app# ls
# root@36cb0f65a247:/app# exitThe port
The CLI hatches the Egg, but the same port contract still decides whether it comes to life. Ruust sets a PORT environment variable, and your app must listen on it and bind to 0.0.0.0, not localhost. Binding to localhost or a hard-coded port is the top reason an Egg builds cleanly but never hatches, and it will show up as a stuck hatching state in ruust logs.
const port = process.env.PORT || 3000;
app.listen(port, '0.0.0.0');Environment variables and domains
The CLI does not yet have commands to set environment variables or add a custom domain. Set both in the dashboard, or drive the same versioned REST API the CLI uses. Every endpoint sits under /api/v1/ and takes your session token as a Bearer header. Variables set on an Egg are available at build and run time, are encrypted at rest, and are never printed in logs.
HOST="${RUUST_HOST:-http://localhost:3939}"
TOKEN="$RUUST_TOKEN"
# Read an Egg, including its env keys and domains
curl -sS "$HOST/api/v1/eggs/$EGG_ID" \
-H "Authorization: Bearer $TOKEN"Configuration and scripting
Config lives at ~/.config/ruust/config.json (honouring XDG_CONFIG_HOME) and holds the API host, session token, and email. For scripts and CI, two environment variables override the file without touching it: RUUST_HOST sets the API host (also settable per run with the global --host flag) and RUUST_TOKEN supplies the session token. The environment variables win over the stored config, so a CI job can point at a host and authenticate without ever running ruust login.
export RUUST_HOST=https://api.eu-west.ruust.run
export RUUST_TOKEN="$RUUST_CI_TOKEN"
ruust ls
ruust create --repo "$CI_REPO_URL" --tier small