CLI
← Docs · Reference

CLI

Deploy, tail logs, run commands and manage apps from your terminal.

railyard is a single Go binary over the Railyard REST API: deploy, tail logs, run commands, manage env vars, domains, databases and servers from your terminal. No runtime required.

Install

One binary, no dependencies, for macOS and Linux on arm64 and amd64. Nothing is hardcoded — the CLI talks to whichever Railyard you sign in to.

brew install almokhtarbr/railyard/railyard           # Homebrew
curl -fsSL https://app.railyard.run/install.sh | sh   # one-line installer (verifies the sha256)

Or download railyard-<os>-<arch> from a cli-v* release at github.com/almokhtarbr/railyard-app/releases, chmod +x it and put it on your PATH.

Later, instead of brew upgrade:

railyard upgrade   # replaces this binary with the newest build your Railyard serves
railyard version   # prints the installed build

Sign in

railyard login https://app.railyard.run
Confirm code ABCD2345 in your browser: https://app.railyard.run/cli/auth/ABCD2345
Logged in to https://app.railyard.run

This is the device flow (same idea as gh auth login or fly auth login): the CLI opens that URL in your browser, you type the code shown in the terminal into the already-signed-in dashboard, and the CLI picks up a token minted for you — no password or token ever typed into the terminal. If you run railyard login with no URL it reuses whatever’s already configured.

railyard whoami    # team, token scope, limits (alias: me)
railyard logout    # forget the saved token

Config and CI

The token and API URL are saved to ~/.railyard/config.json (mode 0600). For CI or containers, skip login and set environment variables instead — they always win over the file:

VariableOverrides
RAILYARD_API (or RAILYARD_API_URL)the control plane URL
RAILYARD_TOKENthe bearer token
RAILYARD_CONFIGthe config file path (default ~/.railyard/config.json)

--json on any command prints the raw API response instead of a table.

Linking an app to a directory

cd my-app && railyard link my-app   # writes ./.railyard.json: {"app": "my-app"}
railyard deploy --follow            # app argument now optional in this directory
railyard unlink

Commands that take [app] fall back to the linked app, found by walking up from the current directory to the first .railyard.json. Everywhere else, <app> is an id or a name (an unambiguous prefix works too).

Shell completion

railyard completion zsh  > "${fpath[1]}/_railyard"
railyard completion bash > /etc/bash_completion.d/railyard
railyard completion fish > ~/.config/fish/completions/railyard.fish

Apps

railyard apps
railyard app [app]
railyard open [app]
railyard create <name> <git-url> [flags]
railyard templates [--verified]
railyard launch <template> [--server id]
railyard clone [app]
railyard promote [app]
  • apps — id · name · last deploy status · url, one per line.
  • app — full JSON for one app.
  • open — prints and opens the app’s URL in your browser.
  • create flags: --server <id|hostname>, --ref <branch>, --port <n> (detected from the repo when omitted), --addons postgres,redis,…, --db-extensions <ext,…>.
  • templates — the one-click catalog; launch deploys one now.
  • clone — copies the app into a staging copy; promote ships a staging app’s release to production (like Heroku pipelines).
railyard create my-app https://github.com/me/my-app --ref main --port 3000
railyard clone my-app && railyard promote my-app-staging

Deploys

railyard deploy [app] [flags]
railyard deploys [--app <app>] [--status <s>]
railyard deploy:logs <id> [--follow]
railyard deploy:approve|reject|cancel <deploy-id>
railyard releases [app]
railyard rollback <app> <version> [--code-only] [--message "note"]
railyard deploy-window <app> off | <mon,tue,...> <09:00> <17:00> [zone]

deploy flags: --ref <branch|tag|sha> deploys that ref once without changing the tracked branch, --message "note", --follow streams the build and release log, --force skips first-deploy checks, --at <ISO 8601> schedules it (cancel with deploy:cancel), --anyway deploys outside the deploy window.

deploy --local builds the current directory with your Docker instead of the team’s builder, pushes it, and deploys that image once — like fly deploy --local-only:

railyard deploy [app] --local [--image repo[:tag]]

--image pushes to your own registry (your docker login) instead of the team’s build registry; an untagged repo gets :local-<UTC timestamp>.

deploy-window — pushes and auto-deploys outside the window wait until it opens; deploy --anyway overrides it. rollback redeploys an earlier release’s commit and restores its env vars (--code-only keeps today’s).

railyard deploy --ref v1.4.2 --message "hotfix" --follow
railyard rollback my-app 112 --message "bad migration"
railyard deploy-window my-app mon,tue,wed,thu,fri 09:00 17:00 America/New_York

Git deploys

railyard git:remote [app] [--remote name]
railyard git:strict <app> on|off

git:remote adds a railyard git remote pointing at this app and a git credential helper that answers with your token, so git push railyard main deploys that exact commit and streams the build log back. git:strict (on by default) rejects a push whose build fails, so the branch stays on its old commit; off accepts the push first and deploys after.

cd my-app && railyard git:remote
git push railyard main

Each push is capped at 1 GB. Pushed repositories also count against a per-team quota (5 GB by default); going over it rejects the push with the usage and a suggestion to delete apps you no longer push to. Railyard runs git gc on pushed repositories every night to keep them small.

Runtime

railyard logs [app] [--follow] [--process web] [--tail 200]
railyard logs:search <app> <text|/regex/> [--level error] [--range 24h] [--process web]
railyard ps [app]
railyard restart [app] [--process web]
railyard run <app> [--process worker] [--exec] -- <command...>
railyard scale <app> <process>=<n> …
railyard wake [app]
railyard sleep <app> <10|30|60|360|1440|off>

run starts a fresh one-off container from the current release (like heroku run), or execs inside the already-running container with --exec; it streams output and exits with the remote command’s own exit code. sleep stops the app’s containers after that many idle minutes and wake/the next request brings it back; off disables it.

railyard logs my-app --follow --process web
railyard run my-app -- bin/rails db:migrate
railyard scale my-app web=2 worker=1
railyard sleep my-app 30

Config vars and domains

railyard env [app] [--reveal[=KEY]]
railyard env:set <app> KEY=VALUE …
railyard env:unset <app> KEY
railyard configs
railyard domains [app]
railyard domain:add <app> <hostname> [--redirect]
railyard domain:rm <app> <domain-id>

env masks values unless --reveal (all) or --reveal KEY (one). configs lists team-wide config entries (read-only from the CLI).

railyard env my-app --reveal SECRET_KEY_BASE
railyard env:set my-app RAILS_ENV=production LOG_LEVEL=info
railyard domain:add my-app www.example.com --redirect

Database and volumes

railyard db:query <app> "<sql>" [--write]
railyard db:backups [app]
railyard db:backup [app]
railyard db:restore <backup-id>
railyard db:url <backup-id>
railyard volumes [app]
railyard volume:backup <app> <volume-name>
railyard volume:restore <backup-id>

db:query is read-only unless --write (needs a write-scoped token). db:url returns a signed download link for a backup.

railyard db:query my-app "select count(*) from users"
railyard db:backup my-app
railyard volume:backup my-app data

Manifest

railyard manifest:pull [app] [--secrets] [--out railyard.yml]
railyard manifest:apply [app] <file.yml>

manifest:pull prints the app as a railyard.yml (--secrets includes variable values); manifest:apply applies one to the app.

railyard manifest:pull my-app --out railyard.yml
railyard manifest:apply my-app railyard.yml

Observability

railyard metrics [app] [--range 1h|24h|7d|30d]
railyard autoscale <app> --max N [--min N] [--p95 ms] [--cpu %]
railyard autoscale <app> off

metrics prints requests, p95, error rate and slowest endpoints. autoscale scales web replicas between --min/--max once p95 latency or CPU crosses the given thresholds; off removes the bounds.

railyard metrics my-app --range 7d
railyard autoscale my-app --max 5 --min 1 --p95 300 --cpu 80

Notifications and webhooks

railyard notify
railyard webhooks

Team-wide listings of notification rules and webhook endpoints (read-only from the CLI; create and edit them from the dashboard).

Servers

railyard servers
railyard server <id>
railyard server:cordon <server-id>
railyard server:uncordon <server-id>
railyard server:reboot <server-id>
railyard server:power-cycle <server-id>
railyard server:prune <server-id>
railyard server:resize <server-id> <size>

cordon stops new apps from being placed on a server without moving what’s already there; prune clears unused Docker images and volumes.

railyard server:cordon srv-7
railyard server:resize srv-7 s-4vcpu-8gb

Networking

railyard tunnel [app] [web|db|postgres|redis|<process>] [-p local-port]

Alias: proxy. Forwards a local port to a container or database on the app’s server — like fly proxy / railway connect. Listens on localhost (the remote port by default); a database tunnel prints a ready postgres://…@localhost:<port>/… URL. Nothing is opened to the internet: bytes travel CLI → control plane (your token) → agent → container.

railyard tunnel my-app db -p 5433

Search and imports

railyard search:reindex [app]
railyard import

search:reindex runs the app’s reindex command in a fresh one-off container. import opens the Heroku/Render/Fly importer in your browser.

Exit codes

0 ok · 2 the API returned an error (message on stderr) · 3 not signed in or bad usage · 64 bad command usage. railyard run instead exits with the remote command’s own exit code.

See also