The Railway CLI is npm i -g @railway/cli (or brew install railway), and the eight commands that cover 80% of day-to-day work are: login to authenticate, init to scaffold a new project, link to attach the local repo to an existing project, up to deploy, status to see the running services, logs to tail the runtime output, variables to set and read env vars, and run to execute one-off commands against a service. The other 22 commands are for the dashboard-only workflows: billing, team management, project creation with templates, and a handful of niche use cases. This post walks through the eight, the patterns teams hit on day one, and the cases where the dashboard is still the right answer.
Table of contents
- Install and login: the two-step setup
- The first project: init, link, and up
- The day-to-day trio: status, logs, variables
- The one-off command: railway run
- The three commands the CLI does not replace
- The shell-vs-CI consideration
- The right workflow for a team that uses Railway heavily
- FAQ
Install and login: the two-step setup
The install is the standard pattern for a Node.js-distributed CLI:
# npm
npm i -g @railway/cli
# Homebrew (macOS, Linux)
brew install railway
# Verify
railway --version
The login is a browser-based OAuth flow:
railway login
The command opens a browser window, the user authorizes the CLI, the CLI receives a token, and the session is stored locally. The session persists across commands until the user runs railway logout or the token expires.
The gotcha: the login requires a browser. A team that is on a headless server (a CI runner, a Docker container) cannot use the interactive login. The right answer for headless environments is the RAILWAY_TOKEN env var, which the team gets from the dashboard’s “Tokens” section. The token is used in place of the interactive login.
The first project: init, link, and up
The first project on a new repo is the init then up pattern:
cd my-project
railway init # creates a new Railway project
railway up # deploys the current directory
The init command creates a new Railway project, generates a railway.toml config file in the current directory, and links the local repo to the project. The up command detects the runtime (Node.js, Python, Go, etc.), builds the project, deploys it, and prints the URL.
The gotcha: the init command requires a Railway account. The team that has not created one is prompted to do so as part of the flow. The prompt is a one-time setup, not a per-command requirement.
The alternative pattern is the link command for an existing project:
cd my-project
railway link # links to an existing project by ID or name
The link command is the right answer when the team already has a project in the dashboard and wants to attach the local repo to it. The init command is the right answer when the team is starting fresh.
The second gotcha: the up command deploys to the linked project’s default environment. The team that has multiple environments (production, staging) uses the --environment flag:
railway up --environment staging
The flag is the difference between a deploy to production and a deploy to staging. The wrong environment is the most common first-day mistake.
The day-to-day trio: status, logs, variables
The three commands teams use every day are status, logs, and variables.
status shows the running services in the linked project:
railway status
The output is a table with the service name, the deployment status, the URL, and the recent deploy timestamp. The command is the dashboard’s “Deployments” view in CLI form.
logs tails the runtime output:
railway logs # tail all services
railway logs --service api # tail one service
The command is tail -f for the platform’s runtime logs. The output streams as the app generates it. The command is the dashboard’s “Logs” view in CLI form.
variables reads and sets env vars:
railway variables # list all
railway variables set KEY=value # set one
railway variables set KEY=value --service api # set on a specific service
railway variables delete KEY # delete one
The command is the dashboard’s “Variables” view in CLI form. The set/delete commands update the project’s env vars and trigger a redeploy.
The gotcha: variables set triggers a redeploy. A team that is setting a few related vars should batch the sets in a single command (or use the dashboard) to avoid multiple deploys. The pattern is railway variables set A=1 B=2 C=3, which sets all three in one redeploy.
The second gotcha: variables reads the linked environment’s vars, not the source-of-truth vars. The team that needs the source-of-truth view uses the dashboard, which shows the full var history including who set what and when.
The one-off command: railway run
The run command executes a one-off command against a service:
railway run python manage.py migrate
railway run --service api rails db:migrate
railway run --service api bash
The command is the standard way to run database migrations, one-off scripts, and interactive shells against a service. The command runs in the same environment as the service, with the same env vars and the same network access.
The gotcha: the run command is not a replacement for the dashboard’s “Shell” view for interactive debugging. The dashboard’s shell is faster to start and easier to use for ad-hoc queries. The CLI’s run is the right answer for scripts and migrations.
The second gotcha: the run command does not persist state. Each run starts a fresh container. The team that needs to keep a database connection open across multiple commands uses the dashboard’s “Shell” view, not the CLI.
The three commands the CLI does not replace
The three dashboard-only workflows that the CLI does not (yet) replace:
- Billing and invoices. The billing dashboard shows the current month-to-date spend, the projected month-end total, the invoice history, and the payment method. The CLI has
railway billingfor some of this, but the dashboard is more complete. - Team management. The team dashboard shows the team members, the role assignments, the pending invites, and the audit log. The CLI has
railway teamfor some of this, but the dashboard is more complete. - Project creation with templates. The dashboard’s “New Project” flow has a template gallery (Postgres + Redis + Next.js, Express + Postgres, etc.) that scaffolds a multi-service project. The CLI’s
initcreates a single-service project; the multi-service templates are dashboard-only.
The team’s pattern: the CLI covers the day-to-day engineering work, the dashboard covers the admin and provisioning work. Both are needed; neither replaces the other.
The shell-vs-CI consideration
The Railway CLI is the right answer for a developer’s shell. The right answer for CI is different.
In CI, the team does not use the interactive railway login. The team uses the RAILWAY_TOKEN env var, which is set in the CI’s secret store. The token is generated in the dashboard’s “Tokens” section.
The CI pattern:
# GitHub Actions
- name: Deploy to Railway
env:
RAILWAY_TOKEN: ${{ secrets.RAILWAY_TOKEN }}
run: |
npm i -g @railway/cli
railway up --service api --environment production
The pattern is the same for any CI (GitHub Actions, GitLab CI, CircleCI, Buildkite). The token is the auth, the up is the deploy, the --service and --environment flags are the targeting.
The gotcha: the CI token has the same permissions as the user who generated it. A token generated by a team member has team-scoped permissions. A token generated by a service account has the service account’s permissions. The team’s CI tokens should be generated by a service account, not by an individual.
The right workflow for a team that uses Railway heavily
The right workflow for a team that uses Railway heavily:
- The dashboard for the project setup. Create the project in the dashboard, add the team members, set the billing, choose the region. The dashboard is the right answer for the one-time setup.
- The CLI for the day-to-day engineering work. The team’s engineers use the CLI for the deploy, the logs, the env vars, and the one-off commands. The CLI is the right answer for the recurring work.
- The CI for the production deploy. The production deploy is automated in CI, not run from a developer’s shell. The CI is the right answer for the production path.
- The CLI for the staging deploy. The staging deploy can be either CI or CLI. The CLI is faster for an ad-hoc fix; CI is the right answer for a regular release.
- The dashboard for the monthly review. The team reviews the bill, the resource usage, and the team activity in the dashboard once a month. The dashboard is the right answer for the review.
The five-step pattern is the one most teams settle into after the first month. The first month is figuring out which is which; the second month is automating the recurring parts; the third month is reviewing the bill.
How this fits the rest of the stack
The platform decision is also a cost decision. The deploy minutes, the build minutes, the database, the storage, the bandwidth, the workers, and the secrets each show up as a line item on the platform bill, and the team’s mental model for the project cost is the sum of those numbers. The right answer is to know the line items before the project ships, not after. The RunxBuild hosting calculator is the right place to do that exercise — pick the runtime size, the database tier, the storage, the bandwidth, the build frequency, and the secrets, and the calculator shows what the platform actually costs at the team’s actual usage.
Useful related references:
FAQ
How do I install the Railway CLI?
npm i -g @railway/cli for the npm path, brew install railway for macOS/Linux via Homebrew. The command railway --version verifies the install.
How do I authenticate the Railway CLI from a headless environment?
The RAILWAY_TOKEN env var, generated in the dashboard’s “Tokens” section. The token replaces the interactive railway login. The token has the same permissions as the user who generated it.
What is the difference between railway init and railway link?
init creates a new Railway project and links the local repo. link attaches the local repo to an existing project by ID or name. The right one depends on whether the project is new (use init) or existing (use link).
Does railway up deploy to production or staging?
The linked environment. The team’s first deploy is to the default environment (usually production). The --environment flag overrides the default. The wrong environment is the most common first-day mistake.
How do I see the runtime logs from the CLI?
railway logs tails all services, railway logs --service api tails one. The output is the same as the dashboard’s “Logs” view.
How do I set environment variables from the CLI?
railway variables set KEY=value sets one. The set triggers a redeploy. Batch the sets (railway variables set A=1 B=2 C=3) to avoid multiple redeploys.
How do I run a database migration from the CLI?
railway run --service api <command>. The command runs in the same environment as the service, with the same env vars and the same network access. The pattern works for migrations, one-off scripts, and interactive shells.
When should I use the dashboard instead of the CLI?
Three workflows: billing and invoices, team management, and project creation with templates. The CLI covers the day-to-day engineering work; the dashboard covers the admin and provisioning work.