Ships & Fleet
Ships are traditional processes that bind to a port or Unix socket. Mothership launches them, monitors them, and proxies HTTP and WebSocket traffic to them.
Ships are declared in named groups under [[fleet.GROUP]] — the group name (web, workers, jobs, …) is yours to choose and shows up in metrics and the TUI.
# Web ships[[fleet.web]]name = "app"command = "ruby"args = ["app.rb"]cwd = "./apps/web"bind = "tcp://127.0.0.1:3000"healthcheck = "/health"healthcheck_initial_delay = 10routes = [{ bind = "http", pattern = "/.*" }]
# Background workers[[fleet.workers]]name = "sidekiq"command = "bundle"args = ["exec", "sidekiq"]critical = false
# One-shot jobs[[fleet.jobs]]name = "migrate"command = "rails"args = ["db:migrate"]oneshot = trueShip configuration
Section titled “Ship configuration”| Field | Type | Default | Description |
|---|---|---|---|
name |
string | required | Unique identifier (ASCII only, no spaces) |
command |
string | required | Command to execute |
args |
string[] | [] |
Command arguments |
cwd |
string | inherited | Working directory for process launch |
bind |
string | – | Internal bind address (tcp://host:port or unix:///path), with $ENV_VAR expansion |
healthcheck |
string | – | Health check endpoint path |
healthcheck_initial_delay |
u64 | 30 |
Seconds to wait before the first health check |
routes |
array | [] |
HTTP routes (see Routing) |
depends_on |
string[] | [] |
Ships/bays to wait for before starting |
env |
table | {} |
Environment variables |
critical |
bool | true |
Crash kills the entire fleet |
oneshot |
bool | false |
Run once and exit |
tags |
string[] | [] |
Tags for filtering (--only, --except) |
healthcheck_initial_delay is useful for slow starters — apps that need to warm caches or establish upstream connections before /health can succeed.
Bind formats
Section titled “Bind formats”bind = "tcp://127.0.0.1:3000" # TCP with explicit prefixbind = "0.0.0.0:8080" # TCP without prefixbind = "3000" # port only (defaults to 127.0.0.1)bind = "unix:///tmp/app.sock" # Unix socketbind = "0.0.0.0:$PORT" # env-expandedOn the same machine, Unix sockets skip the network stack entirely — prefer them when the backend supports it.
Critical vs non-critical
Section titled “Critical vs non-critical”A critical ship (the default) that crashes takes the whole fleet down. Set critical = false for processes the fleet can live without — background workers, non-essential sidecars. Crashing ships get exponential-backoff restarts (crash-loop protection) instead of hot restart loops.
Health checks & circuit breakers
Section titled “Health checks & circuit breakers”When healthcheck is set, mothership probes the ship over HTTP with retries and circuit breakers. Health state is exported in Prometheus metrics and shown in the TUI.
Environment variables
Section titled “Environment variables”Ships inherit mothership’s environment; per-ship env entries override inherited values:
MASTER_KEY=secret DATABASE_URL=postgres://... mothership run[[fleet.web]]name = "app"command = "ruby"env = { RAILS_ENV = "production" }When loading ship-manifest.toml, mothership also loads a .env file from the manifest directory first. Existing process environment variables are preserved and never overridden by .env.
Tag filtering
Section titled “Tag filtering”mothership --only web # only ships tagged "web"mothership --only web,api # OR logicmothership --except workers # everything except "workers"Base templates
Section titled “Base templates”Reduce duplication with [base.ship] — every ship inherits its values, and list fields like tags are combined:
[base.ship]env = { RAILS_ENV = "production" }critical = truehealthcheck_initial_delay = 15tags = ["ruby"]
[[fleet.web]]name = "app"command = "ruby"tags = ["web"] # effective tags: ["ruby", "web"][base.bay] and [base.module] do the same for bays and WASM payloads.