Railform is a TypeScript config layer for Railway. It previews, stages, and
applies Railway projects, services, databases, variables, domain references, and
deploy settings from railform.config.ts.
It is designed to be usable by humans and agents:
railform planis read-only.railform apply --request-approvalcan hand changes to a human for review.railform apply --approval <id>lets an agent continue after approval without getting stuck on prompts.RAILFORM_DANGEROUSLY_SKIP_PERMISSIONS=1exists for explicit no-review automation.
npm install -g railformRailform uses your existing Railway auth. Log in with Railway before applying:
railway loginCreate a project:
mkdir my-app
cd my-app
npm init -yCreate a config. railform init installs @railform/core in the project if it
is not already present:
railform initIf your Railway account has multiple workspaces, init asks which one to use
and saves it in .railform/state.json.
Edit railform.config.ts:
import { Postgres, Project, Redis, Service, randomSecret } from "@railform/core";
export default new Project({
name: "my-app",
environment: "production",
databases: [new Postgres({ name: "postgres" }), new Redis({ name: "redis" })],
services: [
new Service({
name: "api",
databases: ["postgres", "redis"],
variables: {
NODE_ENV: "production",
SESSION_SECRET: randomSecret(48),
},
deploy: {
startCommand: "bun run start",
healthcheckPath: "/health",
},
}),
],
});Preview changes:
railform planApply directly:
railform applyAsk for human review and exit:
railform apply --request-approval --format jsonThe human reviews and approves:
railform review <approval-id>
railform approve <approval-id>The agent continues without prompts:
railform apply --approval <approval-id> --wait --format jsonFor automation where the human already chose to skip review:
RAILFORM_DANGEROUSLY_SKIP_PERMISSIONS=1 railform apply --request-approval --wait --format jsonimport {
promptVariable,
railwayPrivateUrl,
railwayPublicUrl,
railwayRef,
randomSecret,
} from "@railform/core";randomSecret(48)creates${{secret(48)}}.promptVariable("API token")asks at apply time or via--var.railwayRef("api", "RAILWAY_PRIVATE_DOMAIN")creates Railway references.railwayPublicUrl("web")andrailwayPrivateUrl("api")create service URLs.
Prompt variables can be passed non-interactively:
railform apply --request-approval --var api.API_TOKEN=secret --format jsonRailform ships agent instructions in the package:
node_modules/@railform/core/agent-skills/railway-stack/SKILL.md