Install
One command. Ten seconds. Done.
Works on macOS (Apple Silicon & Intel) and Linux (x86_64 & ARM). Installs a single ~8MB binary to /usr/local/bin. No runtime dependencies.
Authenticate
Sign in with GitHub. Takes 5 seconds.
Opens your browser, you click authorize, and you're in. Session lasts 30 days.
Deploy
Ship it.
Build & Ship detects your framework, builds a Docker image, starts it with zero-downtime blue-green deployment, and assigns you a public URL. The whole thing takes about 30 seconds.
Your URL
Share it with the world. It's live right now.
Every project gets a permanent .buildandship.it subdomain. It stays the same across every redeploy. Push new code, the URL updates instantly.
After a reboot, run bs restart to reconnect your secure connection and your URL is back up.
Link Your Repo
Auto-deploy on every push. Run this after your first deploy.
This auto-detects your GitHub remote, starts a webhook agent daemon, stores deploy secrets in GitHub Actions, and commits a workflow file. It also sets your project’s .buildandship.it URL in the repo’s About section on GitHub, and syncs your local repo so you’re never out of date.
From now on, every push to your branch triggers an automatic deploy via webhook. No SSH, no open ports — works behind any firewall.
bs deploy at least once before bs link so your subdomain and container are ready. Then every git push auto-deploys.Custom Domain
Optional. Bring your own domain with automatic TLS.
You'll be shown a DNS record to add. Once DNS propagates, SSL activates automatically via Cloudflare. Check progress anytime:
bs up
Your projects stay running. Forever. Like Kubernetes, but for humans.
When you run bs up, your project becomes self-sustaining. It survives reboots, crashes, Docker restarts, and code updates. One command replaces an entire Kubernetes stack.
What happens:
- Detects your framework and builds a Docker image (if no container exists)
- Starts the container with health checks enabled
- Registers the project for desired state — it should always be running
- Installs the Guardian daemon (auto-starts on boot)
- Sets up health monitoring, metrics collection, and local DNS
- Enables GitOps auto-deploy (watches your git repo for changes)
After bs up, try killing the container — the Guardian brings it back within 15 seconds. Reboot your machine — everything comes back automatically.
bs up --status
The kubectl get pods of Build & Ship. See every managed project at a glance.
bs up --status reads your local database — works offline, no login required.Flags
| --status | Show all managed projects (no deploy) |
| --no-auto-deploy | Skip GitOps watcher for this project |
bs down
Gracefully stop a project. The Guardian stops watching it.
This stops the container, sets desired state to “stopped”, and the Guardian won’t restart it. Run bs up again to bring it back.
bs down stops the container but doesn’t remove images or volumes. Your project is one bs up away from running again.The Guardian Daemon
Your machine’s control plane. Runs in the background, keeps everything alive.
The Guardian is a background service that manages desired state for all your projects. It’s the equivalent of the Kubernetes kubelet — a daemon that runs on your machine and ensures reality matches intent.
How it works:
Every 15 seconds, the Guardian runs a reconciliation loop:
Daemon lifecycle:
- macOS: Runs as a Launch Agent (
~/Library/LaunchAgents/com.buildandship.guardian.plist) - Linux: Runs as a systemd user service (
~/.config/systemd/user/bs-guardian.service) - Auto-starts on boot (
RunAtLoad/WantedBy=default.target) - Auto-restarts on crash (
KeepAlive/Restart=always) - Logs:
~/.buildandship/guardian/guardian.log
Guardian commands (usually you don’t need these — bs up handles it):
Self-Healing
Crashes happen. The Guardian handles them automatically.
The Guardian monitors two things per project:
- Liveness: Is the container process alive? (checks Docker container state)
- Readiness: Is the app actually serving traffic? (HTTP GET to health endpoint)
What happens when something breaks:
| Scenario | Guardian Response |
|---|---|
| Container exits or crashes | Restarts immediately |
Container removed (docker rm) | Re-creates from saved image |
| Health check fails 3 times | Restarts with exponential backoff |
| 10+ restarts without recovery | Marks as CrashLoopBackOff, stops retrying |
| Docker daemon not ready (reboot) | Waits up to 90 seconds, then reconciles |
Exponential backoff: 10s → 20s → 40s → 80s → 160s → 300s (5 min max). If the project stays healthy for 5 minutes, the backoff counter resets.
GitOps
Push code, get a new deploy. Automatically.
For projects registered with bs up, the Guardian watches the local git repository for new commits every 60 seconds. When it detects changes:
- Checks if build-related files changed (Dockerfile, package.json, go.mod, etc.)
- Rebuilds the Docker image from the updated source
- Stops the old container
- Starts the new container
- Updates the database with the new container ID and commit SHA
bs up --no-auto-deploy registers the project without GitOps. The Guardian still keeps it alive, just won’t auto-redeploy on code changes.Metrics
CPU, memory, network, and response latency for every project.
The Guardian collects metrics every 15 seconds for each managed project:
| Metric | Source | Shown in |
|---|---|---|
| CPU % | docker stats | bs up --status |
| Memory usage | docker stats | bs up --status |
| Network I/O | docker stats | Stored in DB |
| Response latency | Health check HTTP request | Stored in DB |
| Container restarts | Guardian reconcile loop | bs up --status |
| Uptime | Container start time | bs up --status |
Metrics are stored in SQLite with 24-hour retention (auto-pruned to keep the database lean).
Commands — Auth
bs login
Opens your browser for GitHub OAuth. Creates a local session.
bs logout
Signs out and clears your session.
bs whoami
Shows the currently logged-in user.
Commands — Deploy & Lifecycle
bs init
Detects your framework and generates buildandship.toml.
bs deploy
Build, deploy with zero downtime, set up a B&S secure connection, and register your public URL. Run in your project directory.
bs list
See all your deployed projects at a glance — status, public URL, and whether auto-deploy is connected. Alias: bs ls.
bs status
Detailed project info with resource usage, deploy history, and domain mappings.
bs logs
Stream container logs in real-time.
bs stop
Stops containers and the secure connection. Data and images are preserved.
bs restart
Restarts containers and re-establishes the secure connection. Your public URL is automatically updated.
bs rollback
Reverts to a previous deploy using zero-downtime blue-green swap.
bs up
Register a project for always-on management. Builds, deploys, and starts the Guardian daemon. See Always On for full details.
bs down
Stop a project and remove it from Guardian management. Data and images are preserved.
bs destroy
Full teardown. Stops containers, closes the secure connection, removes your subdomain and custom domains, cleans up the database. Data volumes are preserved.
Commands — Environment
Manage environment variables. Sensitive values (containing SECRET, TOKEN, PASSWORD, etc.) are automatically encrypted with AES-256-GCM.
bs env set
bs env list
bs env rm
Commands — Services
One-command managed databases. Connection strings are auto-injected into your .env file.
| Service | Image | Port | Env Variable |
|---|---|---|---|
| postgres | postgres:16-alpine | 5432 | DATABASE_URL |
| mysql | mysql:8 | 3306 | MYSQL_URL |
| redis | redis:7-alpine | 6379 | REDIS_URL |
| mongo | mongo:7 | 27017 | MONGODB_URI |
Commands — Domains
bs domain add
Map a custom domain (auto-TLS) or local domain (.local, .test, .dev via /etc/hosts).
bs domain ls
List all domain mappings.
bs domain rm
bs domain status
Check SSL and DNS propagation status.
Commands — CI/CD
bs link
Connects your GitHub repo for automatic deploys on every push. Run after bs deploy.
| --repo | GitHub repo as owner/name (auto-detected from git remote) |
| --branch | Branch to deploy on push (default: repo's default branch) |
What it does:
- Starts a webhook agent daemon (auto-restarts on reboot)
- Stores deploy secrets in GitHub Actions
- Commits a workflow file to your repo
- Syncs your local repo (so you’re not behind after the remote commit)
- Sets your
.buildandship.itURL in the repo’s About section on GitHub
How deploys work:
bs deploy at least once before bs link. The link command needs your subdomain to exist.bs unlink
Removes the CI/CD connection. Cleans up GitHub Actions secrets, workflow file, and subdomain route.
Commands — System
bs doctor
Health check. Verifies Docker, BuildKit, cloudflared, disk, memory, Git, and ports.
bs update
Self-update to the latest version.
bs cleanup
Remove stopped containers, dangling images, and old build cache.
bs version
Show current version, Go version, and OS/Arch.
bs uninstall
Completely remove Build & Ship from your machine. Stops all daemons, removes config/data, cleans shell profile, and deletes the binary. Requires typing “uninstall” to confirm.
bs destroy and bs unlink per-project first if needed.Global Flags
| -v, --verbose | Show detailed output |
| -q, --quiet | Suppress all output except errors |
Configuration
Project config lives in buildandship.toml at your project root. Auto-generated by bs init.
Config priority (highest wins):
| Variable | Description | Default |
|---|---|---|
BS_PORT | Override deploy port | 3000 |
BS_FRAMEWORK | Override detected framework | auto |
BS_MEMORY | Override memory allocation | 512MB |
BS_WORKER_URL | Custom Worker proxy URL | https://proxy.buildandship.it |
Supported Frameworks
Auto-detected by inspecting config files, dependencies, and project structure.
| Framework | Language | Detection | Port |
|---|---|---|---|
| Next.js | JavaScript | next.config.js/ts/mjs | 3000 |
| Remix | JavaScript | remix.config.js | 3000 |
| Nuxt | JavaScript | nuxt.config.js/ts | 3000 |
| SvelteKit | JavaScript | svelte.config.js | 3000 |
| Astro | JavaScript | astro.config.mjs | 4321 |
| Vite | JavaScript | vite.config.js/ts | 80 |
| Express | JavaScript | express dep | 3000 |
| FastAPI | Python | fastapi in imports | 8000 |
| Django | Python | manage.py | 8000 |
| Flask | Python | flask in imports | 8000 |
| Go | Go | go.mod | 8080 |
| Rust | Rust | Cargo.toml | 8080 |
| Static Site | HTML | index.html | 80 |
| Dockerfile | Any | Dockerfile | — |
| Docker Compose | Any | docker-compose.yml | — |
Package manager detection: package-lock.json → npm, yarn.lock → yarn, pnpm-lock.yaml → pnpm, bun.lockb → bun.
Node.js version: reads from .nvmrc, .node-version, or engines in package.json.
Blue-Green Deploys
Every deploy is a zero-downtime swap. No dropped requests.
Health Checks
After starting the green container, Build & Ship polls a health endpoint until it's consistently healthy.
| Setting | Default | Description |
|---|---|---|
| Endpoint | / | HTTP GET path to check |
| Interval | 2s | Time between checks |
| Timeout | 120s | Max time waiting for health |
| Min healthy | 10s | Must stay healthy for this long |
| Success codes | 2xx, 3xx | HTTP codes considered healthy |
Customize in buildandship.toml:
DNS Guide
Point your domain to Build & Ship with a CNAME record:
| Provider | Steps |
|---|---|
| GoDaddy | DNS → Add Record → CNAME → proxy.buildandship.it |
| Namecheap | Advanced DNS → Add Record → CNAME → proxy.buildandship.it |
| Cloudflare | DNS → Add Record → CNAME → proxy.buildandship.it |
myapp.com vs www.myapp.com). Use www, transfer DNS to Cloudflare, or use a provider that supports ALIAS/ANAME records.