Create Railway projects, services, and databases with proper configuration...
Create Railway projects, services, and databases with proper configuration.
Check CLI installed:
command -v railway
If not installed:
Install Railway CLI:
npm install -g @railway/clior
brew install railway
Check authenticated:
railway whoami --json
If not authenticated:
Run
railway loginto authenticate.
railway status --json (in current dir)
ā
āāāāāā“āāāāā
Linked Not Linked
ā ā
ā Check parent: cd .. && railway status --json
ā ā
ā āāāāāā“āāāāā
ā Parent Not linked
ā Linked anywhere
ā ā ā
ā Add service railway list
ā Set rootDir ā
ā Deploy āāāāā“āāāā
ā ā Match? No match
ā ā ā ā
ā ā Link Init new
āāāāāāāāā“āāāāāāāāā“āāāāāāāāā
ā
User wants service?
ā
āāāāāāā“āāāāāā
Yes No
ā ā
Scaffold code Done
ā
railway add --service
ā
Configure if needed
ā
Ready to deploy
railway status --json
Default behavior: "deploy to railway" = add a service to the linked project.
Do NOT create a new project unless user EXPLICITLY says:
App names like "flappy-bird" or "my-api" are SERVICE names, not project names.
User: "create a vite app called foo and deploy to railway"
Project: Already linked to "my-project"
WRONG: railway init -n foo
RIGHT: railway add --service foo
Railway CLI walks up the directory tree to find a linked project. If you're in a subdirectory:
cd .. && railway status --json
If parent is linked, you don't need to init/link the subdirectory. Instead:
railway add --service <name>rootDirectory to subdirectory path via environment skillrailway upIf no parent is linked, proceed with init or link flow.
Skip this section if already linked - just add a service instead.
Only use this section when NO project is linked (directly or via parent).
The output can be large. Run in a subagent and extract only:
id and nameid and namerailway list --json
railway initrailway linkrailway initrailway init -n <name>
Options:
-n, --name - Project name (auto-generated if omitted in non-interactive mode)-w, --workspace - Workspace name or ID (required if multiple workspaces exist)If the user has multiple workspaces, railway init requires the --workspace flag.
Get workspace IDs from:
railway whoami --json
The workspaces array contains { id, name } for each workspace.
Inferring workspace from user input: If user says "deploy into xxx workspace" or "create project in my-team", match the name against the workspaces array and use the corresponding ID:
# User says: "create a project in my personal workspace"
railway whoami --json | jq '.workspaces[] | select(.name | test("personal"; "i"))'
# Use the matched ID: railway init -n myapp --workspace <matched-id>
railway link -p <project>
Options:
-p, --project - Project name or ID-e, --environment - Environment (default: production)-s, --service - Service to link-t, --team - Team/workspaceAfter project is linked, create a service:
railway add --service <name>
For GitHub repo sources: Create an empty service, then invoke the railway-environment skill to configure the source via staged changes API. Do NOT use railway add --repo - it requires GitHub app integration which often fails.
Flow:
railway add --service my-apisource.repo and source.branchReference railpack.md for build configuration. Reference monorepo.md for monorepo patterns.
Static site (Vite, CRA, Astro static):
RAILPACK_STATIC_FILE_ROOTrailway variables CLI - always use the environment skillNode.js SSR (Next.js, Nuxt, Express):
start script exists in package.jsonstartCommandPython (FastAPI, Django, Flask):
requirements.txt or pyproject.toml existsGo:
go.mod existsCritical decision: Root directory vs custom commands.
Isolated monorepo (apps don't share code):
/frontend)Shared monorepo (TypeScript workspaces, shared packages):
pnpm --filter <package> buildnpm run build --workspace=packages/<package>yarn workspace <package> buildturbo run build --filter=<package>See monorepo.md for detailed patterns.
Analyze the codebase to ensure Railway compatibility.
Check for existing project files:
package.json ā Node.js projectrequirements.txt, pyproject.toml ā Python projectgo.mod ā Go projectCargo.toml ā Rust projectindex.html ā Static siteMonorepo detection:
pnpm-workspace.yaml ā pnpm workspace (shared monorepo)package.json with workspaces field ā npm/yarn workspace (shared monorepo)turbo.json ā Turborepo (shared monorepo)package.json but no workspace config ā isolated monorepoIf no code exists, suggest minimal patterns from railpack.md:
Static site:
Create an
index.htmlfile in the root directory.
Vite React:
npm create vite@latest . -- --template react
Astro:
npm create astro@latest
Python FastAPI:
Create
main.pywith FastAPI app andrequirements.txtwith dependencies.
Go:
Create
main.gowith HTTP server listening onPORTenv var.
For adding databases (Postgres, Redis, MySQL, MongoDB), use the railway-railway-database skill.
The railway-railway-database skill handles:
Railway CLI not installed. Install with:
npm install -g @railway/cli
or
brew install railway
Not logged in to Railway. Run: railway login
No workspaces found. Create one at railway.com or verify authentication.
Project name already exists. Either:
- Link to existing: railway link -p <name>
- Use different name: railway init -n <other-name>
Service name already exists in this project. Use a different name:
railway add --service <other-name>
User: "create a simple html site and deploy to railway"
1. Check status ā not linked
2. railway init -n my-site
3. Guide: create index.html
4. railway add --service my-site
5. No config needed (index.html in root auto-detected)
6. Use deploy skill: railway up
7. Use domain skill for public URL
User: "create a vite react service"
1. Check status ā linked (or init/link first)
2. Scaffold: npm create vite@latest frontend -- --template react
3. railway add --service frontend
4. No config needed (Vite dist output auto-detected)
5. Use deploy skill: railway up
User: "add a python api to my project"
1. Check status ā linked
2. Guide: create main.py with FastAPI, requirements.txt
3. railway add --service api
4. No config needed (FastAPI auto-detected)
5. Use deploy skill
User: "connect to my backend project and add a worker service"
1. railway list --json ā find "backend"
2. railway link -p backend
3. railway add --service worker
4. Guide setup based on worker type
User: "deploy to railway"
1. railway status ā not linked
2. railway list ā has projects
3. Directory is "my-app", found project "my-app"
4. Ask: "Found existing project 'my-app'. Link to it or create new?"
5. User: "link"
6. railway link -p my-app
7. Ask: "Create a service for this code?"
User: "create a static site in the frontend directory"
1. Check: /frontend has its own package.json, no workspace config
2. This is isolated monorepo ā use root directory
3. railway add --service frontend
4. Invoke environment skill to set rootDirectory: /frontend
5. Set watch paths: /frontend/**
User: "add a new api package to this turborepo"
1. Check: turbo.json exists, pnpm-workspace.yaml exists
2. This is shared monorepo ā use custom commands, NOT root directory
3. Guide: create packages/api with package.json
4. railway add --service api
5. Invoke environment skill to set buildCommand and startCommand (do NOT set rootDirectory)
6. Set watch paths: /packages/api/**, /packages/shared/**
User: "deploy the backend package to railway"
1. Check: pnpm-workspace.yaml exists ā shared monorepo
2. railway add --service backend
3. Invoke environment skill to set buildCommand and startCommand
4. Set watch paths for backend + any shared deps
User: "create a vite app in my-app directory and deploy to railway"
CWD: ~/projects/my-project/my-app (parent already linked to "my-project")
1. Check status in my-app ā not linked
2. Check parent: cd .. && railway status ā IS linked to "my-project"
3. DON'T init/link the subdirectory
4. Scaffold: bun create vite my-app --template react-ts
5. cd my-app && bun install
6. railway add --service my-app
7. Invoke environment skill to set rootDirectory: /my-app
8. Deploy from root: railway up