Agent skill
railway-doctor
Install this agent skill to your Project
npx add-skill https://github.com/stars-end/agent-skills/tree/master/railway-doctor
SKILL.md
railway-doctor
Description
Pre-flight checks for Railway deployments to catch failures BEFORE deploying.
Use when:
- About to deploy to Railway ("deploy to railway", "railway up")
- Railway deployment fails (imports break, env issues, lockfile errors)
- Debugging Railway 500 errors
- User says "check railway", "railway pre-flight", "why did railway fail"
Problem solved: Eliminates "Deploy to Railway β Imports break β Iterate" pattern (12/69 toil commits, 17% of analyzed toil).
Auto-Activation
This skill activates when:
- User mentions Railway deployment ("railway", "deploy", "railway up")
- CI deployment step fails
- Railway shows 500 errors or build failures
- Before important deployments (staging, production)
Implementation
The skill performs comprehensive pre-flight checks to catch Railway deployment issues early.
Check Script
#!/bin/bash
# ~/.agent/skills/railway-doctor/check.sh
set -e
echo "π Railway Doctor - Pre-flight Check"
ISSUES_FOUND=0
# Check 1: Critical Python imports (Backend)
if [[ -f "backend/pyproject.toml" ]]; then
echo ""
echo "π Checking Python imports (backend)..."
cd backend
# Ensure poetry env exists
if ! poetry env info &>/dev/null; then
echo "Installing Poetry environment..."
poetry install --no-root
fi
# Test critical imports
if poetry run python -c "
import sys
from pathlib import Path
sys.path.insert(0, str(Path.cwd()))
# Test critical imports that commonly break in Railway
try:
from services.plaid_adapter import PlaidAdapter
from brokers.security_resolver import SecurityResolver
from api.routers import health
print('β
All critical imports valid')
except ImportError as e:
print(f'β Import will fail in Railway: {e}')
sys.exit(1)
" 2>&1; then
echo "β
Backend imports validated"
else
echo "β ERROR: Backend imports will fail in Railway"
echo " Fix import paths or missing dependencies"
ISSUES_FOUND=$((ISSUES_FOUND + 1))
fi
cd ..
fi
# Check 2: Lockfiles in sync
echo ""
echo "π¦ Checking lockfiles..."
# Poetry lockfile
if [[ -f "backend/pyproject.toml" ]]; then
cd backend
if poetry check --lock 2>/dev/null; then
echo "β
backend/poetry.lock in sync"
else
echo "β ERROR: backend/poetry.lock out of sync"
echo " Run: cd backend && poetry lock --no-update"
ISSUES_FOUND=$((ISSUES_FOUND + 1))
fi
cd ..
elif [[ -f "pyproject.toml" ]]; then
if poetry check --lock 2>/dev/null; then
echo "β
poetry.lock in sync"
else
echo "β ERROR: poetry.lock out of sync"
echo " Run: poetry lock --no-update"
ISSUES_FOUND=$((ISSUES_FOUND + 1))
fi
fi
# pnpm lockfile
if [[ -f "frontend/package.json" ]]; then
cd frontend
if pnpm install --frozen-lockfile 2>/dev/null; then
echo "β
frontend/pnpm-lock.yaml in sync"
else
echo "β ERROR: frontend/pnpm-lock.yaml out of sync"
echo " Run: cd frontend && pnpm install"
ISSUES_FOUND=$((ISSUES_FOUND + 1))
fi
cd ..
elif [[ -f "package.json" ]]; then
if pnpm install --frozen-lockfile 2>/dev/null; then
echo "β
pnpm-lock.yaml in sync"
else
echo "β ERROR: pnpm-lock.yaml out of sync"
echo " Run: pnpm install"
ISSUES_FOUND=$((ISSUES_FOUND + 1))
fi
fi
# Check 3: Required environment variables (if Railway CLI available)
if command -v railway &>/dev/null; then
echo ""
echo "π Checking Railway environment variables..."
REQUIRED_VARS=(
"DATABASE_URL"
"SUPABASE_URL"
"CLERK_SECRET_KEY"
)
for VAR in "${REQUIRED_VARS[@]}"; do
if railway variables 2>/dev/null | grep -q "^$VAR"; then
echo "β
$VAR set"
else
echo "β οΈ WARNING: $VAR not set in Railway environment"
echo " Set via: railway variables set $VAR=<value>"
ISSUES_FOUND=$((ISSUES_FOUND + 1))
fi
done
else
echo ""
echo "βΉοΈ Railway CLI not installed (skipping env var check)"
echo " Install: npm install -g @railway/cli"
fi
# Check 4: Railway configuration file
echo ""
echo "βοΈ Checking Railway configuration..."
if [[ -f "railway.toml" ]] || [[ -f "railway.json" ]]; then
echo "β
Railway config file found"
else
echo "β οΈ No railway.toml or railway.json found"
echo " Consider adding for build configuration"
fi
echo ""
echo "βββββββββββββββββββββββββββββββββββββββ"
if [[ $ISSUES_FOUND -eq 0 ]]; then
echo "β
All pre-flight checks passed!"
echo " Safe to deploy to Railway"
exit 0
else
echo "β Found $ISSUES_FOUND issue(s) - deployment will likely fail"
echo ""
echo "Fix issues before deploying to Railway"
exit 1
fi
Fix Script
#!/bin/bash
# ~/.agent/skills/railway-doctor/fix.sh
set -e
echo "π§ Railway Doctor - Fixing issues..."
FIXED=0
# Fix 1: Regenerate lockfiles
echo ""
echo "π¦ Fixing lockfiles..."
# Poetry
if [[ -f "backend/pyproject.toml" ]]; then
cd backend
if ! poetry check --lock 2>/dev/null; then
echo "Regenerating backend/poetry.lock..."
poetry lock --no-update
git add poetry.lock
echo "β
backend/poetry.lock fixed"
FIXED=$((FIXED + 1))
fi
cd ..
elif [[ -f "pyproject.toml" ]]; then
if ! poetry check --lock 2>/dev/null; then
echo "Regenerating poetry.lock..."
poetry lock --no-update
git add poetry.lock
echo "β
poetry.lock fixed"
FIXED=$((FIXED + 1))
fi
fi
# pnpm
if [[ -f "frontend/package.json" ]]; then
cd frontend
if ! pnpm install --frozen-lockfile 2>/dev/null; then
echo "Regenerating frontend/pnpm-lock.yaml..."
pnpm install
git add pnpm-lock.yaml
echo "β
frontend/pnpm-lock.yaml fixed"
FIXED=$((FIXED + 1))
fi
cd ..
elif [[ -f "package.json" ]]; then
if ! pnpm install --frozen-lockfile 2>/dev/null; then
echo "Regenerating pnpm-lock.yaml..."
pnpm install
git add pnpm-lock.yaml
echo "β
pnpm-lock.yaml fixed"
FIXED=$((FIXED + 1))
fi
fi
# Fix 2: Import issues - can't auto-fix, only provide guidance
if [[ -f "backend/pyproject.toml" ]]; then
cd backend
if ! poetry run python -c "
import sys
from pathlib import Path
sys.path.insert(0, str(Path.cwd()))
from services.plaid_adapter import PlaidAdapter
" 2>/dev/null; then
echo ""
echo "β οΈ Cannot auto-fix: Import errors detected"
echo " Manual fixes needed:"
echo " - Check import paths in Railway match local"
echo " - Verify all dependencies in pyproject.toml"
echo " - Test with: cd backend && poetry run python -c 'from services.plaid_adapter import PlaidAdapter'"
fi
cd ..
fi
# Fix 3: Environment variables - can't auto-fix, only guide
if command -v railway &>/dev/null; then
echo ""
echo "β οΈ Environment variable issues require manual setup in Railway dashboard"
echo " Or use: railway variables set VARIABLE_NAME=value"
fi
echo ""
echo "βββββββββββββββββββββββββββββββββββββββ"
if [[ $FIXED -eq 0 ]]; then
echo "βΉοΈ No auto-fixable issues found"
echo " Check error messages above for manual fixes"
else
echo "β
Fixed $FIXED issue(s)"
echo ""
echo "Re-run railway-doctor check to verify all issues resolved"
fi
Usage Examples
Pre-flight check before deployment
railway-doctor check
Auto-fix lockfile issues
railway-doctor fix
CI Integration
# .github/workflows/deploy.yml
- name: Railway Pre-flight Check
run: ~/.agent/skills/railway-doctor/check.sh
- name: Deploy to Railway
if: success()
run: railway up
Agent workflow
1. User: "deploy to railway"
2. Agent: Run railway-doctor check
3. If passes: railway up
4. If fails: railway-doctor fix, then re-check
Common Issues & Fixes
Issue 1: Import errors in Railway
Symptom: Works locally, fails in Railway with ModuleNotFoundError
Cause: Import paths different in Railway vs local
Check: railway-doctor validates critical imports
Fix: Adjust sys.path or restructure imports
Issue 2: Lockfile out of sync
Symptom: Railway build fails with "dependency mismatch" Cause: pyproject.toml changed without poetry lock Check: railway-doctor validates lockfiles Fix: Auto-fixed with railway-doctor fix
Issue 3: Missing environment variables
Symptom: Railway 500 errors, missing DATABASE_URL etc. Cause: Env vars not set in Railway project Check: railway-doctor checks required vars (if Railway CLI installed) Fix: Manual setup via Railway dashboard or CLI
Issue 4: Railpack version breaking changes
Symptom: Build works locally, fails in Railway after Railpack update Cause: Railpack breaking change (e.g., 0.0.70 packageManager field) Prevention: Pin Railpack version in railway.toml
Monorepo Root Pattern (Python + llm-common)
Symptom: Works locally with ../packages/llm-common or a vendored copy, but Railway deploy fails with missing modules or broken imports.
Root Cause: Railway βisolated monorepoβ deploys only the configured Root Directory (e.g., backend/). Anything outside that directory (../packages/llm-common) is invisible inside the container.
Best Practice Pattern:
- Set Root Directory for Python services to
backend/. - Use a standard dependency for shared libraries like
llm-common, never a relative path:toml# backend/pyproject.toml [tool.poetry.dependencies] llm-common = { git = "https://github.com/stars-end/llm-common.git", tag = "v0.4.0", extras = ["pgvector"] } - Avoid
path = "../llm-common"orpackages/llm-commonfor runtime; those are fine for local dev only if the service is not deployed from that folder. - Start command should assume
backend/as CWD:bashpoetry run uvicorn main:app --host 0.0.0.0 --port "$PORT"
Heuristic for Agents:
- If a Railway deploy fails only in one repo (e.g., Affordabot) but works in another (Prime Radiant), first check:
- Is the service using
Root Directory = backend/? - Is
llm-common(or any shared lib) installed as a normal dependency instead of via../paths?
- Is the service using
Cross-Repo Deployment
This skill deploys to ~/.agent/skills/ and works across:
- β All repos (prime-radiant-ai, affordabot, any Railway project)
- β All AI agents (Claude Code, Codex CLI, Antigravity)
- β All VMs (shared via Universal Skills MCP)
Success Metrics
Baseline: 12 commits (17% of toil) wasted on Railway deployment failures Target: <2 commits per 60-commit cycle Impact: ~2-3 hours/month saved, fewer deployment iterations
Notes
Design Philosophy:
- Fail fast locally (before pushing to Railway)
- Validate critical imports (catches 80% of issues)
- Clear guidance for non-auto-fixable issues
- Agent-friendly (railway-doctor check β fix β deploy)
Why not full Railway simulator?
- Over-engineering: Pre-flight + better logging gets 80% value
- Complexity: Full simulator may still diverge from actual Railway
- ROI: 2-3 days vs 1 day for similar impact
Complementary with:
- Enhanced Railway logging (bd-vs87) - for debugging deployed errors
- lockfile-doctor skill (bd-heb9) - for dependency management
Recommended Agent Skills
Expand your agent's capabilities with these related and highly-rated skills.
toolchain-health
Validate Python toolchain alignment between mise, Poetry, and pyproject. Use when changing Python versions, editing pyproject.toml, or seeing Poetry/mise version solver errors. Invokes /toolchain-health to check: - .mise.toml python tool version - pyproject.toml python constraint - Poetry env python interpreter Keywords: python version, mise, poetry, toolchain, env use, lock, install
parallelize-cloud-work
Delegate independent work to Claude Code Web cloud sessions for parallel execution. Generates comprehensive session prompts with context exploration guidance, verifies Beads state, provides tracking commands. Use when user says "parallelize work to cloud", "start cloud sessions", or needs to execute multiple independent tasks simultaneously, or when user mentions cloud sessions, cloud prompts, delegate to cloud, Claude Code Web, generate session prompts, parallel execution, or asks "how do I use cloud sessions".
docs-create
Create epic-specific documentation skill with external reference docs. MUST BE USED for caching external docs. Fetches URLs, caches full content, uses documentation-engineer to generate cohesive summaries, and creates auto-activating skill. Use when starting work on epic that requires external documentation context (API docs, tool guides, reference materials), or when user mentions "cache docs", "external docs", "API documentation", URLs for docs, documentation needs, reference materials, knowledge caching, or epic context documentation.
git-safety-guard
Installs a Git safety guard hook for Claude Code to prevent destructive Git and filesystem commands. Blocks accidental data loss from commands like 'git checkout --', 'git reset --hard', 'git clean -f', 'git push --force', and 'rm -rf'. Use this skill to set up safety rails in a new or existing repository, or globally for the agent.
beads-guard
Safe Beads workflow helper (warning-only). Use before bd sync/close/create to avoid JSONL conflicts. Ensures you are on a feature branch, up to date with origin/master, and stages Beads files cleanly with Feature-Key commits.
vm-bootstrap
Linux VM bootstrap verification skill. MUST BE USED when setting up new VMs or verifying environment. Supports modes: check (warn-only), install (operator-confirmed), strict (CI-ready). Enforces Linux-only + mise as canonical; honors preference brewβnpm (with apt fallback). Verifies required tools: mise, node, pnpm, python, poetry, gh, railway, bd, tmux, jq, rg. Handles optional tools as warnings: tailscale, playwright, docker, bv. Never prints/seeds secrets; never stores tokens in repo/YAML; Railway vars only for app runtime env. Safe on dirty repos (refuses and points to dirty-repo-bootstrap skill, or snapshots WIP branch). Keywords: vm, bootstrap, setup, mise, toolchain, linux, environment, provision, verify, new vm
Didn't find tool you were looking for?