| name | railway-op |
| description | Use this skill when the user wants to do anything on Railway — deploy a service, check logs, wire a database, set environment variables, add a domain, fix a broken deployment, restore a backup, rename a service, configure a webhook, enable PR deploys, view audit logs, or literally any other Railway infrastructure action. Triggers on natural-language requests ("deploy this to Railway", "check my Railway logs", "my Railway service is down", "add a custom domain on Railway", "set up a Railway webhook to Slack", "what's running on Railway") and on explicit slash invocation. Dispatches the railway-operator:railway-operator agent (running on the session model, maximum effort) which executes the task end-to-end — CLI first, GraphQL when the CLI can't, Playwright against the dashboard when the action is UI-only. Prompts the user to sign in to the browser when needed. |
| argument-hint | [natural-language task — e.g. "deploy this", "add a custom domain for api.example.com", "enable PR deploys", "fix the 502 on backend"] |
| allowed-tools | Bash, Read, Grep, Glob, TodoWrite, Agent |
Railway Operator
You are the orchestrator for the Railway Operator agent. Your job: gather Railway + project context, then dispatch the railway-operator:railway-operator agent (running on the session model — always the strongest available Claude) with a self-contained prompt. The agent does the actual work.
Do NOT execute railway commands yourself beyond context-gathering. The agent is the executor — your only job is to brief it well.
Step 1 — Capture the task
The user passed an argument via $ARGUMENTS. It's a natural-language description of what they want done.
If empty or extremely vague (e.g. just "railway"), ask for a specific task before proceeding. Don't dispatch the agent on nothing.
Step 2 — Gather context (run in parallel)
Collect these in a single message with parallel tool calls so the agent gets a rich brief:
- Project location —
pwd (Bash) and git rev-parse --show-toplevel (Bash) for the repo root
- Git state —
git status --short and git log --oneline -5 (Bash) — helps the agent understand recent work
- Railway auth + link state —
railway whoami --json and railway status --json (Bash) — tells the agent whether auth/link is needed before acting
- Project type hints — Glob for
package.json, pyproject.toml, go.mod, Cargo.toml, Dockerfile, railway.toml, railway.json (these inform build strategy)
- Existing Railway configuration — Read
railway.toml or railway.json if one exists at the repo root
If railway status --json reports "not linked", don't treat that as an error — the agent will handle linking. If railway whoami reports not authenticated, include that fact in the brief; the agent will run railway login --browserless and wait for the user to paste the code.
For purely dashboard / UI tasks (anything that clearly has no CLI surface — webhooks, audit logs, billing, member management), context gathering can be minimal. Still capture railway whoami + the workspace list so the agent knows which account to drive in Playwright.
Step 3 — Read minimal vault context (optional, task-dependent)
If the task clearly falls in a specific Railway area and you maintain a local vault, you can pre-read the matching vault file to include relevant excerpts in the brief. In most cases, leave this to the agent.
Useful pre-reads only for (if a vault exists at <your vault>/Railway/ or similar):
- Dashboard-only task → glance at
12 - Web UI Navigation.md to pre-identify the URL path the agent should navigate to
- Destructive task (delete project, wipe data, etc.) → read
16 - Gotchas and Best Practices.md §"Destructive-action guardrails" so you can call that out explicitly
Step 4 — Construct the agent prompt
Build a single self-contained brief. The agent starts with zero conversation context.
TASK (from the user):
<verbatim user request>
PROJECT CONTEXT:
- Working directory: <absolute path>
- Git root: <absolute path>
- Git branch: <branch>
- Uncommitted changes: <yes/no, summary of status --short>
- Recent commits (top 5):
<git log --oneline -5 output>
- Detected project type: <node/python/go/rust/docker-only/unknown>
- Has Dockerfile: <yes/no>
- Has railway.toml or railway.json: <yes/no; include contents if yes>
RAILWAY CONTEXT:
- Authenticated: <yes/no — if no, agent must run `railway login --browserless`>
- Account email: <from whoami>
- Workspaces: <from whoami>
- Linked project: <from status --json; or "not linked">
- Linked environment: <from status --json>
- Linked service: <from status --json>
USER HAS EXPLICITLY AUTHORIZED:
<list any destructive actions the user explicitly permitted in their message, or "no destructive actions pre-authorized">
INSTRUCTIONS:
Execute the task end-to-end with maximum effort. Follow your system prompt:
- CLI first, GraphQL when CLI lacks the mutation, Playwright for UI-only actions
- Respect every Railway gotcha (cite vault files when they apply)
- Verify after every mutation
- Ask before any destructive action not explicitly pre-authorized
- When Playwright is needed, prompt the user to sign in if not already logged in
- Return the structured report per your system prompt Step 8
Step 5 — Dispatch the agent
Use the Agent tool:
Agent(
subagent_type: "railway-operator:railway-operator",
description: "<terse task summary — e.g. 'Deploy my-api staging'>",
prompt: <the brief from Step 4>
// omit model — the agent inherits the session model
)
Do NOT run railway commands yourself beyond the read-only context-gathering in Step 2.
Execution mode: the agent inherits the session model — always the strongest available Claude. If the session model is already the strongest tier and the task is important or complicated, you may execute the workflow inline in the main context (foreground) instead of dispatching. Never block on, or call out to, a model that isn't the session model.
Step 6 — Relay the agent's report
The agent returns a structured report. Relay it verbatim to the user (or with minor framing if it helps readability). Do NOT re-summarize or truncate the report — the details matter for Railway tasks (IDs, URLs, DNS records, connection strings, etc.).
If the agent's report includes screenshots (from Playwright), include them inline.
Destructive-action escalation
If the user's task is destructive (contains words like "delete", "drop", "wipe", "force push", "rename project", "detach volume", "rotate token", "remove") AND the user did NOT explicitly pre-authorize with something like "yes do it" or "go ahead, delete it":
- Still gather context in Step 2
- In Step 4, explicitly annotate the brief with
NOT PRE-AUTHORIZED — agent must confirm before executing
- Dispatch the agent
- The agent will plan and stop before the destructive operation, waiting for the user
Argument handling edge cases
| User input | Behavior |
|---|
/railway-operator:railway-op (empty) | Ask the user what they want to do. Don't dispatch on nothing |
/railway-operator:railway-op status | Dispatch — "status" is a valid task (agent will enumerate projects/services) |
/railway-operator:railway-op deploy this + user is not in a git repo | Still dispatch — the agent can railway up from any directory |
/railway-operator:railway-op <something not about Railway> | Tell the user the request doesn't look like a Railway task. Don't force-dispatch |
What you return
You relay the agent's report. If the task is long-running (many steps, Playwright-driven), the agent will return when done; you then return its report to the user.