{"id":47590094,"url":"https://github.com/podspawn/podspawn","last_synced_at":"2026-04-01T17:15:11.235Z","repository":{"id":340744724,"uuid":"1167400645","full_name":"podspawn/podspawn","owner":"podspawn","description":"Dev containers, locally or over SSH. One binary. Podfile config. Every SSH feature works.","archived":false,"fork":false,"pushed_at":"2026-03-26T21:42:35.000Z","size":2368,"stargazers_count":0,"open_issues_count":1,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-03-27T08:20:26.542Z","etag":null,"topics":["containers","dev-environments","devcontainer","docker","ephemeral","golang","ssh","sshd"],"latest_commit_sha":null,"homepage":"https://podspawn.dev","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"agpl-3.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/podspawn.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":"SECURITY.md","support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-02-26T08:55:27.000Z","updated_at":"2026-03-26T19:48:12.000Z","dependencies_parsed_at":"2026-02-26T15:03:22.455Z","dependency_job_id":null,"html_url":"https://github.com/podspawn/podspawn","commit_stats":null,"previous_names":["o1x3/podspawn","podspawn/podspawn"],"tags_count":12,"template":false,"template_full_name":null,"purl":"pkg:github/podspawn/podspawn","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/podspawn%2Fpodspawn","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/podspawn%2Fpodspawn/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/podspawn%2Fpodspawn/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/podspawn%2Fpodspawn/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/podspawn","download_url":"https://codeload.github.com/podspawn/podspawn/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/podspawn%2Fpodspawn/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":31290537,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-01T13:12:26.723Z","status":"ssl_error","status_checked_at":"2026-04-01T13:12:25.102Z","response_time":53,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["containers","dev-environments","devcontainer","docker","ephemeral","golang","ssh","sshd"],"created_at":"2026-04-01T17:15:10.524Z","updated_at":"2026-04-01T17:15:11.223Z","avatar_url":"https://github.com/podspawn.png","language":"Go","funding_links":[],"categories":[],"sub_categories":[],"readme":"# podspawn\n\n[![CI](https://github.com/podspawn/podspawn/actions/workflows/ci.yml/badge.svg)](https://github.com/podspawn/podspawn/actions/workflows/ci.yml)\n[![Release](https://img.shields.io/github/v/release/podspawn/podspawn)](https://github.com/podspawn/podspawn/releases/latest)\n[![License: AGPL-3.0](https://img.shields.io/badge/license-AGPL--3.0-blue)](LICENSE)\n\nClone a repo. Run one command. Get the full dev environment.\n\n```bash\ngit clone github.com/yourorg/project\ncd project\npodspawn dev\n```\n\nThat'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.\n\n## Install\n\n```bash\ncurl -sSfL https://podspawn.dev/up | bash\n```\n\n## How it works\n\nA Podfile defines your dev environment:\n\n```yaml\nextends: ubuntu-dev\npackages:\n  - go@1.25\n  - nodejs@22\nservices:\n  - name: postgres\n    image: postgres:16\n    env: { POSTGRES_PASSWORD: devpass }\nenv:\n  DATABASE_URL: \"postgres://postgres:devpass@postgres:5432/dev\"\non_create: |\n  go mod download\n  npm install\n```\n\n`extends: 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.\n\n## Three ways to use it\n\n### podspawn dev (local, one command)\n\nNo SSH, no root, no daemon. Just Docker.\n\n```bash\npodspawn dev                    # shell into Podfile environment\npodspawn dev -- make test       # run a command and exit\npodspawn down                   # stop everything\npodspawn init                   # scaffold a Podfile for your project\n```\n\nYour code is bind-mounted into the container. Edits on your host appear instantly inside. Companion services are accessible by name (`postgres:5432`).\n\n### Named machines (local, persistent)\n\nFor longer-lived environments that aren't tied to a specific repo:\n\n```bash\npodspawn create backend         # create a named machine\npodspawn shell backend          # attach to it\npodspawn run scratch            # one-shot throwaway\npodspawn list                   # see what's running\npodspawn stop backend           # tear it down\n```\n\n### Server mode (remote, over SSH)\n\nHook into your existing sshd. Every SSH feature works.\n\n```\nssh deploy@backend.pod\n  -\u003e sshd calls podspawn auth-keys\n  -\u003e container created from project Podfile\n  -\u003e companion services start\n  -\u003e you're in\n```\n\nSFTP, scp, rsync, port forwarding, agent forwarding, VS Code Remote, JetBrains Gateway, Cursor. Teammates need zero client-side install.\n\n## Podfile features\n\n- **Packages**: `go@1.25`, `nodejs@22`, `python@3.13`, `rust@stable` -- version-pinned installs\n- **Services**: postgres, redis, or any Docker image as a companion container\n- **Extends**: inherit from base Podfiles, override what you need\n- **Bang-replace**: `packages!:` to fully replace instead of merge\n- **Lifecycle hooks**: `on_create` (once) and `on_start` (every attach)\n- **Port forwarding**: auto-resolve conflicts, manual, or strict\n- **Mount modes**: bind (live sync), copy (one-shot), or none\n- **Session modes**: grace-period, destroy-on-disconnect, persistent\n\n## What's working\n\n### Dev environments\n- [x] `podspawn dev` -- one-command setup from Podfile\n- [x] `podspawn down` -- teardown with `--clean` for volumes\n- [x] `podspawn init` -- scaffolding with project type detection\n- [x] `podspawn prebuild` -- pre-build images for CI\n- [x] Podfile `extends` with deep merge and bang-replace\n- [x] `mount: copy` via Docker CopyToContainer\n- [x] Port forwarding (auto, manual, expose strategies)\n- [x] Embedded templates: go, node, python, rust, fullstack, minimal\n- [x] Template registry with `--update` from [podspawn/podfiles](https://github.com/podspawn/podfiles)\n- [x] devcontainer.json fallback\n\n### Local mode\n- [x] Named machines (`create`, `run`, `shell`, `list`, `stop`)\n- [x] Podfile environments (packages, services, env vars, hooks)\n- [x] Default Podfile at `~/.podspawn/podfile.yaml`\n\n### Server mode\n- [x] Native sshd hook via `AuthorizedKeysCommand`\n- [x] Three session modes: grace-period, destroy-on-disconnect, persistent\n- [x] Persistent containers with bind-mounted home directories\n- [x] Per-user bridge network isolation\n- [x] Companion services on shared Docker network\n- [x] SFTP, scp, rsync, port forwarding, agent forwarding\n- [x] VS Code Remote, JetBrains Gateway, Cursor\n- [x] Non-root container users with passwordless sudo\n- [x] Project routing via `.pod` hostnames\n\n### Infrastructure\n- [x] SQLite session state (WAL mode, crash recovery)\n- [x] Cleanup daemon (grace periods, max lifetimes, orphan reconciliation)\n- [x] Structured audit logging (JSON-lines)\n- [x] Prometheus metrics (`podspawn status --prometheus`)\n- [x] Security hardening (cap-drop ALL, no-new-privileges, PID limits, gVisor)\n- [x] Multi-arch releases (linux/darwin/windows, amd64/arm64, deb/rpm/Homebrew)\n\n## Roadmap\n\nWhat's coming next, roughly in priority order:\n\n| Feature | Status | Description |\n|---------|--------|-------------|\n| Dev integration tests | Planned | End-to-end tests for `podspawn dev` with real Docker |\n| Image baking | Planned | Bake container user into image at build time for faster cold starts (~600ms) |\n| `prebuild --push` | Planned | Push pre-built images to ghcr.io for CI |\n| `podspawn sync` | Planned | Manual push/pull file sync between host and container |\n| Warm container pool | Exploring | Pre-start containers in background for instant attach |\n| Branch-based environments | Exploring | `podspawn dev -b feat/auth` for per-branch containers |\n| Shell completions | Exploring | bash, zsh, fish completions |\n\nSee [project_next_phase.md](https://github.com/podspawn/podspawn) for detailed design notes.\n\n## Dogfooding\n\npodspawn uses its own tool for development. See [`podfile.yaml`](podfile.yaml) in this repo:\n\n```bash\ngit clone github.com/podspawn/podspawn\ncd podspawn\npodspawn dev\n# Go 1.25, golangci-lint, delve, pre-commit hooks -- all ready\n```\n\n## Commands\n\n```\n# Dev environments\npodspawn dev               # Start from CWD Podfile\npodspawn down              # Stop dev environment\npodspawn init              # Scaffold a Podfile\npodspawn prebuild          # Pre-build image for CI\n\n# Named machines\npodspawn create            # Create a named machine\npodspawn run               # Create + attach, ephemeral\npodspawn shell             # Attach to existing machine\npodspawn list              # Show machines\npodspawn stop              # Destroy a machine\n\n# Server administration\npodspawn server-setup      # Configure sshd\npodspawn add-user          # Register SSH keys\npodspawn add-project       # Register a project with Podfile\npodspawn doctor            # Preflight checks\n\n# Client\npodspawn setup             # Configure ~/.ssh/config\npodspawn ssh               # SSH wrapper with .pod routing\npodspawn open              # VS Code / Cursor launcher\n```\n\n## Comparison\n\n| | Codespaces | Coder | DevPod | podspawn |\n|---|---|---|---|---|\n| Self-hosted | no | yes | yes | yes |\n| One-command setup | yes | no | yes | yes |\n| SSH server | custom | custom | custom | native sshd |\n| Config format | devcontainer.json | Terraform | devcontainer.json | Podfile |\n| Companion services | Docker Compose | manual | manual | first-class |\n| Extends / composition | features system | no | features system | `extends` + merge |\n| Local mode | no | no | yes | yes |\n| Persistent + ephemeral | persistent only | persistent only | persistent only | both |\n| Complexity | high | high | medium | low |\n| Open source | no | yes (Apache) | yes (MPL) | yes (AGPL) |\n\n## Requirements\n\n**Local mode**: Docker (OrbStack, Docker Desktop, Colima, Podman)\n**Server mode**: Docker + OpenSSH 7.4+ on Linux\n**Client mode**: SSH client\n\n## Documentation\n\nFull docs at [podspawn.dev](https://podspawn.dev):\n- [Getting Started](https://podspawn.dev/docs/dev-environments/quickstart)\n- [Podfile Reference](https://podspawn.dev/docs/dev-environments/reference)\n- [Real-World Examples](https://podspawn.dev/docs/dev-environments/examples)\n- [Extending Podfiles](https://podspawn.dev/docs/dev-environments/extending)\n- [CLI Reference](https://podspawn.dev/docs/cli/server-commands)\n- [Security Hardening](https://podspawn.dev/docs/guides/security-hardening)\n\n## Status\n\n**Alpha.** Core features work and are tested (350+ unit tests, integration tests across 4 Linux distros). API may change between minor versions.\n\n## License\n\nAGPL-3.0. If you run a modified version as a service, you share your changes.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpodspawn%2Fpodspawn","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fpodspawn%2Fpodspawn","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpodspawn%2Fpodspawn/lists"}