Clone a repo. Run one command. Get the full dev environment.
git clone github.com/yourorg/project
cd project
podspawn devThat's it. Podspawn reads the repo's podfile.yaml, builds a cached image, starts companion services (postgres, redis), mounts your code, and drops you into a shell. Works locally with Docker or remotely over SSH.
curl -sSfL https://podspawn.dev/up | bashA Podfile defines your dev environment:
extends: ubuntu-dev
packages:
- go@1.25
- nodejs@22
services:
- name: postgres
image: postgres:16
env: { POSTGRES_PASSWORD: devpass }
env:
DATABASE_URL: "postgres://postgres:devpass@postgres:5432/dev"
on_create: |
go mod download
npm installextends: ubuntu-dev inherits common tools (git, ripgrep, fzf, neovim, jq). Your Podfile adds what's specific to your project. Podfiles compose -- a child inherits from a base and overrides what it needs.
No SSH, no root, no daemon. Just Docker.
podspawn dev # shell into Podfile environment
podspawn dev -- make test # run a command and exit
podspawn down # stop everything
podspawn init # scaffold a Podfile for your projectYour code is bind-mounted into the container. Edits on your host appear instantly inside. Companion services are accessible by name (postgres:5432).
For longer-lived environments, including branch-specific project workspaces:
podspawn create backend # create a named machine
podspawn add-project api --repo https://github.com/acme/api
podspawn create auth-fix --project api --branch feat/auth-retry
podspawn shell auth-fix # attach or restart it
podspawn run scratch # one-shot throwaway
podspawn run review --project api --branch fix/flaky-test
podspawn list # see what's running
podspawn stop auth-fix # tear down container, keep checkoutProject-backed machines clone into ~/.podspawn/workspaces/<machine>/ in local mode. The checkout survives podspawn stop, so podspawn shell <machine> can recreate the container without recloning or rerunning on_create.
Hook into your existing sshd. Every SSH feature works.
ssh deploy@backend.pod
-> sshd calls podspawn auth-keys
-> container created from project Podfile
-> companion services start
-> you're in
SFTP, scp, rsync, port forwarding, agent forwarding, VS Code Remote, JetBrains Gateway, Cursor. Teammates need zero client-side install.
- Packages:
go@1.25,nodejs@22,python@3.13,rust@stable-- version-pinned installs - Services: postgres, redis, or any Docker image as a companion container
- Extends: inherit from base Podfiles, override what you need
- Bang-replace:
packages!:to fully replace instead of merge - Lifecycle hooks:
on_create(once) andon_start(every attach) - Port forwarding: auto-resolve conflicts, manual, or strict
- Mount modes: bind (live sync), copy (one-shot), or none
- Session modes: grace-period, destroy-on-disconnect, persistent
-
podspawn dev-- one-command setup from Podfile -
podspawn down-- teardown with--cleanfor volumes -
podspawn init-- scaffolding with project type detection -
podspawn prebuild-- pre-build images for CI - Podfile
extendswith deep merge and bang-replace -
mount: copyvia Docker CopyToContainer - Port forwarding (auto, manual, expose strategies)
- Embedded templates: go, node, python, rust, fullstack, minimal
- Template registry with
--updatefrom podspawn/podfiles - devcontainer.json fallback
- Named machines (
create,run,shell,list,stop) - Podfile environments (packages, services, env vars, hooks)
- Default Podfile at
~/.podspawn/podfile.yaml - Registered project workspaces via
create/run --project [--branch]
- Native sshd hook via
AuthorizedKeysCommand - Three session modes: grace-period, destroy-on-disconnect, persistent
- Persistent containers with bind-mounted home directories
- Per-user bridge network isolation
- Companion services on shared Docker network
- SFTP, scp, rsync, port forwarding, agent forwarding
- VS Code Remote, JetBrains Gateway, Cursor
- Non-root container users with passwordless sudo
- Project routing via
.podhostnames
- SQLite session state (WAL mode, crash recovery)
- Cleanup daemon (grace periods, max lifetimes, orphan reconciliation)
- Structured audit logging (JSON-lines)
- Prometheus metrics (
podspawn status --prometheus) - Security hardening (cap-drop ALL, no-new-privileges, PID limits, gVisor)
- Multi-arch releases (linux/darwin/windows, amd64/arm64, deb/rpm/Homebrew)
What's coming next, roughly in priority order:
| Feature | Status | Description |
|---|---|---|
| Dev integration tests | Planned | End-to-end tests for podspawn dev with real Docker |
| Image baking | Planned | Bake container user into image at build time for faster cold starts (~600ms) |
prebuild --push |
Planned | Push pre-built images to ghcr.io for CI |
podspawn sync |
Planned | Manual push/pull file sync between host and container |
| Warm container pool | Exploring | Pre-start containers in background for instant attach |
| Branch-based environments | In progress | local branch workspaces via create/run --project --branch |
| Shell completions | Exploring | bash, zsh, fish completions |
See project_next_phase.md for detailed design notes.
podspawn uses its own tool for development. See podfile.yaml in this repo:
git clone github.com/podspawn/podspawn
cd podspawn
podspawn dev
# Go 1.25, golangci-lint, delve, pre-commit hooks -- all ready# Dev environments
podspawn dev # Start from CWD Podfile
podspawn down # Stop dev environment
podspawn init # Scaffold a Podfile
podspawn prebuild # Pre-build image for CI
# Named machines
podspawn create # Create a named machine
podspawn run # Create + attach, ephemeral
podspawn shell # Attach to existing machine
podspawn list # Show machines
podspawn stop # Destroy a machine
# Server administration
podspawn server-setup # Configure sshd
podspawn add-user # Register SSH keys
podspawn add-project # Register a project with Podfile
podspawn doctor # Preflight checks
# Client
podspawn setup # Configure ~/.ssh/config
podspawn ssh # SSH wrapper with .pod routing
podspawn open # VS Code / Cursor launcher
| Codespaces | Coder | DevPod | podspawn | |
|---|---|---|---|---|
| Self-hosted | no | yes | yes | yes |
| One-command setup | yes | no | yes | yes |
| SSH server | custom | custom | custom | native sshd |
| Config format | devcontainer.json | Terraform | devcontainer.json | Podfile |
| Companion services | Docker Compose | manual | manual | first-class |
| Extends / composition | features system | no | features system | extends + merge |
| Local mode | no | no | yes | yes |
| Persistent + ephemeral | persistent only | persistent only | persistent only | both |
| Complexity | high | high | medium | low |
| Open source | no | yes (Apache) | yes (MPL) | yes (AGPL) |
Local mode: Docker (OrbStack, Docker Desktop, Colima, Podman) Server mode: Docker + OpenSSH 7.4+ on Linux Client mode: SSH client
Full docs at podspawn.dev:
- Getting Started
- Podfile Reference
- Real-World Examples
- Extending Podfiles
- CLI Reference
- Security Hardening
Alpha. Core features work and are tested (350+ unit tests, integration tests across 4 Linux distros). API may change between minor versions.
AGPL-3.0. If you run a modified version as a service, you share your changes.