{"id":49694259,"url":"https://github.com/yorch/ccpod","last_synced_at":"2026-05-07T21:59:04.532Z","repository":{"id":354944106,"uuid":"1226105996","full_name":"yorch/ccpod","owner":"yorch","description":"Run Claude Code inside Docker containers with portable, composable configuration","archived":false,"fork":false,"pushed_at":"2026-05-06T13:30:59.000Z","size":450,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-05-07T21:58:41.600Z","etag":null,"topics":["claude","claude-ai","claude-code"],"latest_commit_sha":null,"homepage":"https://ccpod.brnby.com/","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/yorch.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":"AGENTS.md","dco":null,"cla":null}},"created_at":"2026-05-01T01:30:52.000Z","updated_at":"2026-05-06T13:31:38.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/yorch/ccpod","commit_stats":null,"previous_names":["yorch/ccpod"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/yorch/ccpod","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/yorch%2Fccpod","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/yorch%2Fccpod/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/yorch%2Fccpod/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/yorch%2Fccpod/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/yorch","download_url":"https://codeload.github.com/yorch/ccpod/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/yorch%2Fccpod/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":32757807,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-07T02:14:30.463Z","status":"ssl_error","status_checked_at":"2026-05-07T02:14:29.405Z","response_time":62,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.6:443 state=error: 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":["claude","claude-ai","claude-code"],"created_at":"2026-05-07T21:59:03.836Z","updated_at":"2026-05-07T21:59:04.505Z","avatar_url":"https://github.com/yorch.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# ccpod\n\nRun Claude Code inside Docker containers with portable, composable configuration.\n\n**Why:** Your Claude environment (settings, plugins, skills, CLAUDE.md, MCPs) is usually locked to one machine. ccpod wraps it in a **profile** — a versioned config that travels with you, your team, or your open-source project. Every `ccpod run` drops you into a clean, reproducible Claude session.\n\nWorks with Docker, Podman, OrbStack, and Colima — auto-detected.\n\n📖 **Docs:** https://ccpod.brnby.com\n\n---\n\n## Install\n\n```sh\n# macOS / Linux — one-liner installer\ncurl -fsSL https://ccpod.brnby.com/install.sh | sh\n\n# Or build from source (requires Bun)\nbun run build   # outputs dist/ccpod\n```\n\nThe installer places `ccpod` in `/usr/local/bin` by default. Override with `CCPOD_INSTALL_DIR=~/.local/bin` or pin a version with `CCPOD_VERSION=v0.2.0`.\n\n---\n\n## Quick start\n\n```sh\nccpod init          # first-run wizard: detect runtime, set up auth, create default profile\nccpod run           # interactive Claude session in the current directory\n```\n\nThe project directory is mounted at `/workspace` inside the container. Claude runs there.\n\n---\n\n## Profiles\n\nA profile defines the complete Claude environment for a session: Docker image, auth, settings, plugins, CLAUDE.md, SSH config, network policy, and sidecar services.\n\nProfiles live at `~/.ccpod/profiles/\u003cname\u003e/profile.yml`.\n\n### Profile config (`~/.ccpod/profiles/\u003cname\u003e/profile.yml`)\n\n```yaml\nname: personal\ndescription: My personal Claude environment\n\nconfig:\n  source: local               # \"local\" | \"git\"\n  path: ~/.my-claude-config   # local path to your ~/.claude config dir\n  # For git-based configs:\n  # source: git\n  # repo: https://github.com/org/claude-config\n  # sync: daily               # \"always\" | \"daily\" | \"pin\"\n  # ref: main\n\nimage:\n  use: ghcr.io/yorch/ccpod:latest   # pre-built image with Claude Code\n  # use: build                     # build locally using dockerfile:\n  # dockerfile: ./Dockerfile\n\nauth:\n  type: api-key              # \"api-key\" | \"oauth\"\n  keyEnv: ANTHROPIC_API_KEY  # env var to read key from\n  # keyFile: /run/secrets/api-key\n\nstate: ephemeral             # \"ephemeral\" (default) | \"persistent\"\n\nssh:\n  agentForward: true         # forward SSH_AUTH_SOCK\n  mountSshDir: false         # mount ~/.ssh read-only\n\nnetwork:\n  policy: full               # \"full\" (default) | \"restricted\"\n  allow: []                  # domains/IPs to allow in restricted mode\n\nports:\n  list:\n    - \"3000:3000\"            # host:container\n  autoDetectMcp: true        # expose HTTP/SSE MCP ports from .mcp.json\n\nplugins:\n  - mcp-server-brave-search  # delta-installed on first run; skipped if already present\n\nclaudeArgs:                  # extra flags passed to claude on every run\n  - \"--dangerously-skip-permissions\"\n\nenv:\n  - DATABASE_URL             # host env vars to forward into container\n\nservices:                    # optional sidecar containers\n  postgres:\n    image: postgres:17\n    env:\n      POSTGRES_PASSWORD: dev\n    volumes:\n      - ccpod-pg-data:/var/lib/postgresql/data\n```\n\n### Project config (`.ccpod.yml` in project root)\n\nOverrides the profile for a specific project. ccpod walks up from `$PWD` to find it.\n\n```yaml\nprofile: personal            # which profile to use\nmerge: deep                  # \"deep\" (default) | \"override\"\n\nconfig:\n  claudeMd: append           # \"append\" (default) | \"override\"\n\nnetwork:\n  policy: restricted\n  allow:\n    - api.github.com\n    - registry.npmjs.org\n\nports:\n  list:\n    - \"4000:4000\"\n\nenv:\n  - STRIPE_SECRET_KEY\n```\n\n**Merge strategies:**\n\n| Asset | Default behavior |\n|-------|-----------------|\n| `settings.json` | Deep merge; project wins on conflicts |\n| `CLAUDE.md` | Profile content first, project appended (or `override` to replace) |\n| plugins | Union — project adds, cannot remove profile plugins (unless `merge: override`) |\n| `services` | Merged by key; project adds sidecars |\n| `env` | Union of both lists |\n\n---\n\n## CLI reference\n\n```\nccpod run                        Interactive Claude session\nccpod run \"fix lint errors\"      Headless: inline prompt\nccpod run --file prompt.txt      Headless: prompt from file (exit with container code)\nccpod run --profile \u003cname\u003e       Use a specific profile\nccpod run --env KEY=VALUE        Pass/override env var for this run\nccpod run --rebuild              Force image rebuild or repull\nccpod run --no-state             Force ephemeral state for this run\n\nccpod init                       First-run setup wizard\nccpod init --profile \u003cname\u003e      Create a named profile\n\nccpod profile create \u003cname\u003e\nccpod profile list\nccpod profile update \u003cname\u003e      Force-pull git-based config\nccpod profile delete \u003cname\u003e\n\nccpod plugins list [--profile \u003cname\u003e]\nccpod plugins update [--profile \u003cname\u003e]   Flush and reinstall all plugins\n\nccpod image init [--profile \u003cname\u003e]       Download Dockerfile for local customization\nccpod image init --from \u003curl\u003e             Use a custom Dockerfile URL\nccpod image build [--profile \u003cname\u003e]      Build local Dockerfile image\nccpod image build --apply                 Also update profile image.use to the built tag\nccpod image pull [--profile \u003cname\u003e]       Pull latest base or declared image\n\nccpod ps                         List running ccpod containers\nccpod ps --all                   Include stopped containers\nccpod down                       Stop Claude container + sidecars for $PWD\n\nccpod state clear [--profile \u003cname\u003e]      Delete state directory (resets projects/todos)\n\nccpod config get \u003ckey\u003e           Get a global config value\nccpod config set \u003ckey\u003e \u003cvalue\u003e   Set a global config value\nccpod config show                Print resolved merged config\nccpod config validate            Validate .ccpod.yml\n\nccpod update                     Update ccpod to the latest release\n```\n\n---\n\n## State persistence\n\n| Mode | History \u0026 memory | Survives restart |\n|------|-----------------|-----------------|\n| `ephemeral` (default) | tmpfs — wiped on exit | No |\n| `persistent` | `~/.ccpod/state/\u003cprofile\u003e/` on host | Yes |\n\nSwitch for a single run: `ccpod run --no-state`\n\nReset: `ccpod state clear [profile]` — deletes `~/.ccpod/state/\u003cprofile\u003e/`\n\n---\n\n## Storage layout\n\n```\n~/.ccpod/\n  config.yml                # global ccpod config (autoCheckUpdates, etc.)\n  profiles/\u003cname\u003e/\n    profile.yml\n    .ccpod-sync-lock        # timestamp of last git sync\n    config/                 # cloned Claude config (only if source: git)\n  credentials/\u003cname\u003e/       # auth tokens — persist across container restarts\n  state/\u003cname\u003e/             # projects, todos, statsig (persistent mode only)\n\nDocker named volumes (managed by ccpod):\n  ccpod-plugins-\u003cprofile\u003e   # installed Claude plugins\n```\n\n---\n\n## Global config\n\n`~/.ccpod/config.yml` controls ccpod's own behaviour (not the container).\n\n| Key | Default | Description |\n|-----|---------|-------------|\n| `autoCheckUpdates` | `true` | Check for new ccpod releases on startup |\n\n```sh\nccpod config set autoCheckUpdates false   # disable startup update checks\nccpod config set autoCheckUpdates true    # re-enable\n```\n\n---\n\n## MCP auto-detection\n\nIf `.mcp.json` exists at the project root and `ports.autoDetectMcp: true` (default), ccpod reads HTTP/SSE MCP entries and automatically exposes their ports. No manual port config needed for most MCP setups.\n\n\u003e **Note:** stdio-based MCP servers require their runtime binaries inside the container. `npx`-based MCPs work automatically since the base image includes Node.js. Other runtimes need a custom `dockerfile:`.\n\n---\n\n## Shared team profile\n\nPoint your team at a shared git repo:\n\n```yaml\n# ~/.ccpod/profiles/team/profile.yml\nname: team\nconfig:\n  source: git\n  repo: https://github.com/your-org/claude-config\n  sync: daily\n  ref: main\n```\n\nEveryone gets the same CLAUDE.md, settings, and plugins. Updates flow in daily (or on demand with `ccpod profile update team`).\n\n---\n\n## Base image\n\nThe official base image is `ghcr.io/yorch/ccpod` — built from `docker/Dockerfile` and published automatically on every push to `main` (`:main`, `:latest`) and on version tags (`:1.2.3`, `:1.2`).\n\nTo use a custom image, set `image.use` in your profile. To build locally from a Dockerfile, set `image.use: build` and `image.dockerfile: ./Dockerfile`.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fyorch%2Fccpod","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fyorch%2Fccpod","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fyorch%2Fccpod/lists"}