{"id":35761723,"url":"https://github.com/griffithind/dcx","last_synced_at":"2026-01-12T06:32:43.202Z","repository":{"id":331960199,"uuid":"1129226833","full_name":"griffithind/dcx","owner":"griffithind","description":"A single-binary CLI for running devcontainers with built-in SSH support","archived":false,"fork":false,"pushed_at":"2026-01-11T22:52:49.000Z","size":1145,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-01-11T23:36:05.708Z","etag":null,"topics":["cli","devcontainer","devcontainer-features","docker","docker-compose","ssh"],"latest_commit_sha":null,"homepage":"","language":"Go","has_issues":false,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/griffithind.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","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":null,"dco":null,"cla":null}},"created_at":"2026-01-06T19:40:16.000Z","updated_at":"2026-01-11T22:58:35.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/griffithind/dcx","commit_stats":null,"previous_names":["griffithind/dcx"],"tags_count":28,"template":false,"template_full_name":null,"purl":"pkg:github/griffithind/dcx","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/griffithind%2Fdcx","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/griffithind%2Fdcx/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/griffithind%2Fdcx/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/griffithind%2Fdcx/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/griffithind","download_url":"https://codeload.github.com/griffithind/dcx/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/griffithind%2Fdcx/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28336316,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-12T06:09:07.588Z","status":"ssl_error","status_checked_at":"2026-01-12T06:05:18.301Z","response_time":98,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.5: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":["cli","devcontainer","devcontainer-features","docker","docker-compose","ssh"],"created_at":"2026-01-06T23:19:11.213Z","updated_at":"2026-01-12T06:32:43.183Z","avatar_url":"https://github.com/griffithind.png","language":"Go","funding_links":[],"categories":[],"sub_categories":[],"readme":"# dcx\n\n[![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](LICENSE)\n[![Go 1.24+](https://img.shields.io/badge/Go-1.24+-00ADD8.svg)](https://go.dev/)\n\nA single-binary CLI for running [devcontainers](https://containers.dev/) with built-in SSH support. No Node.js required. Works with any editor.\n\n## Highlights\n\n- **Single binary** - Download and run, no runtime dependencies\n- **Built-in SSH server** - Connect with VSCode, Zed, Cursor, Neovim, or any SSH client\n- **SSH agent forwarding** - Git operations inside containers use your local keys\n- **Native secrets** - Fetch secrets from 1Password and other CLIs on-demand\n- **Smart rebuilds** - Only rebuilds when configuration actually changes\n- **Reproducible builds** - Lock feature versions with `dcx lock`\n- **Docker Compose** - Full support for compose-based devcontainers\n- **Command shortcuts** - Define project-specific aliases in devcontainer.json\n\n## Quick Start\n\n```bash\n# Install dcx\ncurl -fsSL https://raw.githubusercontent.com/griffithind/dcx/main/install.sh | sh\n\n# Navigate to a project with devcontainer.json\ncd myproject\n\n# Preview what will happen\ndcx plan\n\n# Start the devcontainer\ndcx up\n\n# Connect via SSH (auto-configured)\nssh myproject.dcx\n\n# Or run commands directly\ndcx exec -- npm install\ndcx shell\n```\n\n## Editor Integration\n\ndcx includes a built-in SSH server that works with any editor supporting remote development.\n\n### Setup\n\n```bash\ndcx up\n```\n\nThis starts your devcontainer and automatically configures SSH access. Your project name becomes the SSH host:\n\n```bash\nssh myproject.dcx\n```\n\n### VSCode\n\n1. Install the [Remote - SSH](https://marketplace.visualstudio.com/items?itemName=ms-vscode-remote.remote-ssh) extension\n2. `Cmd/Ctrl+Shift+P` → \"Remote-SSH: Connect to Host\"\n3. Select your project name\n\n### Zed\n\n1. `Cmd+Shift+P` → \"projects: Open Remote\"\n2. Connect via SSH to your project name\n\n### Cursor\n\nWorks the same as VSCode with Remote SSH.\n\n### Other Editors\n\nAny editor or tool that supports SSH will work. The SSH host is `\u003cproject-name\u003e.dcx`.\n\n## Installation\n\n### Quick Install (Recommended)\n\n```bash\ncurl -fsSL https://raw.githubusercontent.com/griffithind/dcx/main/install.sh | sh\n```\n\nInstalls to `~/.local/bin/dcx`.\n\n### Using Go\n\n```bash\ngo install github.com/griffithind/dcx/cmd/dcx@latest\n```\n\n### From Source\n\n```bash\ngit clone https://github.com/griffithind/dcx.git\ncd dcx\nmake build\n```\n\n## Commands\n\n### Lifecycle\n\n| Command | Description |\n|---------|-------------|\n| `dcx up` | Start the devcontainer, building if necessary |\n| `dcx down` | Stop and remove containers |\n| `dcx stop` | Stop containers without removing |\n| `dcx restart` | Restart containers without rebuilding |\n\n**`dcx up` flags:**\n- `--rebuild` - Force rebuild images\n- `--recreate` - Force recreate containers\n- `--pull` - Re-fetch remote features (useful when `:latest` tags update)\n\n### Execution\n\n| Command | Description |\n|---------|-------------|\n| `dcx exec -- \u003ccmd\u003e` | Run a command in the container |\n| `dcx shell` | Open an interactive shell |\n| `dcx run \u003cshortcut\u003e` | Run a command shortcut defined in devcontainer.json |\n\n### Information\n\n| Command | Description |\n|---------|-------------|\n| `dcx status` | Show devcontainer status |\n| `dcx plan` | Preview execution plan without making changes |\n| `dcx list` | List all managed devcontainers |\n| `dcx logs` | View container logs |\n| `dcx config` | Show resolved configuration |\n\n### Utilities\n\n| Command | Description |\n|---------|-------------|\n| `dcx build` | Build images without starting |\n| `dcx lock` | Generate or verify lockfile for reproducible builds |\n| `dcx clean` | Remove orphaned dcx images |\n| `dcx doctor` | Check system requirements |\n| `dcx debug` | Show detailed debugging information |\n| `dcx upgrade` | Update dcx to latest version |\n| `dcx ssh` | SSH connection info |\n\n### Global Flags\n\n```\n-w, --workspace   Workspace directory (default: current directory)\n-c, --config      Path to devcontainer.json\n-v, --verbose     Enable verbose output\n-q, --quiet       Minimal output (errors only)\n    --no-color    Disable colored output\n```\n\n## Configuration\n\n### DCX Customizations\n\nDCX-specific settings are defined in your `devcontainer.json` under `customizations.dcx`:\n\n```json\n{\n  \"name\": \"myproject\",\n  \"image\": \"node:20\",\n  \"customizations\": {\n    \"dcx\": {\n      \"shortcuts\": {\n        \"test\": \"npm test\",\n        \"dev\": { \"prefix\": \"npm run\", \"passArgs\": true },\n        \"lint\": { \"command\": \"npm run lint\", \"description\": \"Run linter\" }\n      }\n    }\n  }\n}\n```\n\n### Project Naming\n\nProject name resolution order:\n1. **Compose projects**: `name` field in compose.yaml (preferred)\n2. `name` field in devcontainer.json\n3. Workspace directory name (fallback)\n\nThe resolved name is used for container naming, SSH host (`myproject.dcx`), and display in `dcx status`.\n\n### Shortcuts\n\nShortcuts can be defined as:\n\n- **Simple string**: `\"test\": \"npm test\"`\n- **Object with prefix**: `\"dev\": { \"prefix\": \"npm run\", \"passArgs\": true }` - runs `npm run \u003cargs\u003e`\n- **Object with command**: `\"lint\": { \"command\": \"npm run lint\" }`\n\nRun shortcuts with:\n\n```bash\ndcx run test\ndcx run dev start    # runs: npm run start\ndcx run --list       # show available shortcuts\n```\n\n### Secrets\n\nDCX takes a different approach to secrets than the reference devcontainer CLI:\n\n- **Reference CLI**: Requires a pre-populated JSON file via `--secrets-file`, injects secrets as environment variables to lifecycle hooks\n- **DCX**: Executes commands on your host to fetch secrets on-demand, mounts them as files at `/run/secrets/\u003cname\u003e`\n\n#### Runtime Secrets\n\nSecrets are mounted as files at `/run/secrets/\u003cname\u003e` after container starts:\n\n```json\n{\n  \"name\": \"myapp\",\n  \"image\": \"node:20\",\n  \"customizations\": {\n    \"dcx\": {\n      \"secrets\": {\n        \"DATABASE_URL\": \"op read op://Development/database/connection-string\",\n        \"API_KEY\": \"op read op://Development/api/key\"\n      }\n    }\n  }\n}\n```\n\nAccess in container:\n```bash\ncat /run/secrets/DATABASE_URL\n```\n\n**Security:**\n- Stored in tmpfs (in-memory, never written to disk)\n- Owned by `remoteUser` (accessible to non-root users)\n- File permissions: 0400 (read-only by owner)\n\n#### Using Secrets as Environment Variables\n\nTo use secrets as environment variables, add them to your shell profile in a lifecycle hook:\n\n```json\n{\n  \"name\": \"myapp\",\n  \"image\": \"node:20\",\n  \"postCreateCommand\": \"echo '[ -f /run/secrets/DATABASE_URL ] \u0026\u0026 export DATABASE_URL=$(cat /run/secrets/DATABASE_URL)' \u003e\u003e ~/.bashrc\",\n  \"customizations\": {\n    \"dcx\": {\n      \"secrets\": {\n        \"DATABASE_URL\": \"op read op://Development/database/url\"\n      }\n    }\n  }\n}\n```\n\nOr load all secrets into the shell profile:\n\n```json\n{\n  \"postCreateCommand\": \"echo 'for f in /run/secrets/*; do export $(basename $f)=$(cat $f); done' \u003e\u003e ~/.bashrc\"\n}\n```\n\n#### Build Secrets\n\nAvailable during `docker build` via BuildKit's `--mount=type=secret`. Works with both Dockerfile and Docker Compose builds:\n\n```json\n{\n  \"name\": \"myapp\",\n  \"build\": {\n    \"dockerfile\": \"Dockerfile\"\n  },\n  \"customizations\": {\n    \"dcx\": {\n      \"buildSecrets\": {\n        \"NPM_TOKEN\": \"op read op://Development/npm/token\"\n      }\n    }\n  }\n}\n```\n\nUse in Dockerfile:\n```dockerfile\nRUN --mount=type=secret,id=NPM_TOKEN \\\n    NPM_TOKEN=$(cat /run/secrets/NPM_TOKEN) npm install\n```\n\nBuild secrets are never baked into image layers - they're only available during the build step that mounts them.\n\n### Lockfiles\n\nLock feature versions for reproducible builds:\n\n```bash\ndcx lock              # Generate devcontainer-lock.json\ndcx lock --verify     # Verify lockfile matches current resolution\ndcx lock --frozen     # CI mode: fail if lockfile missing or mismatched\n```\n\nThe lockfile pins:\n- Exact semantic versions\n- OCI manifest digests\n- SHA256 integrity hashes\n\n## Build Options\n\nDCX supports three build strategies:\n\n### Image\n\nUse a pre-built image:\n\n```json\n{\n  \"image\": \"mcr.microsoft.com/devcontainers/go:1\"\n}\n```\n\n### Dockerfile\n\nBuild from a Dockerfile:\n\n```json\n{\n  \"build\": {\n    \"dockerfile\": \"Dockerfile\",\n    \"context\": \"..\",\n    \"args\": {\n      \"GO_VERSION\": \"1.22\"\n    },\n    \"target\": \"development\"\n  }\n}\n```\n\n### Docker Compose\n\nUse Docker Compose for multi-container setups:\n\n```json\n{\n  \"name\": \"myapp\",\n  \"dockerComposeFile\": \"docker-compose.yml\",\n  \"service\": \"app\",\n  \"workspaceFolder\": \"/workspace\"\n}\n```\n\nThe `service` field specifies which container to use as the primary devcontainer. Other services in the compose file start automatically.\n\n### Build Pipeline\n\nWhen features are configured, DCX builds a derived image:\n\n```\nBase Image → Features → UID Sync → Final Image\n```\n\nEach layer is cached. Use `dcx up --rebuild` to force a fresh build.\n\n## Runtime\n\n### Lifecycle Hooks\n\nCommands run at specific points in the container lifecycle:\n\n```json\n{\n  \"onCreateCommand\": \"npm install\",\n  \"postCreateCommand\": \"npm run setup\",\n  \"postStartCommand\": \"npm run dev\"\n}\n```\n\n| Hook | When | Runs |\n|------|------|------|\n| `initializeCommand` | Before container creation (on host) | Once |\n| `onCreateCommand` | After container created | Once |\n| `updateContentCommand` | When content is updated | Once |\n| `postCreateCommand` | After onCreate | Once |\n| `postStartCommand` | After container starts | Every start |\n| `postAttachCommand` | When client connects | Every attach |\n\n### Environment Variables\n\n```json\n{\n  \"containerEnv\": {\n    \"NODE_ENV\": \"development\"\n  },\n  \"remoteEnv\": {\n    \"EDITOR\": \"vim\"\n  }\n}\n```\n\n- `containerEnv` - Set at container creation\n- `remoteEnv` - Set in shell sessions\n\n### User Configuration\n\n```json\n{\n  \"remoteUser\": \"node\",\n  \"updateRemoteUserUID\": true\n}\n```\n\nWhen `updateRemoteUserUID` is true, DCX updates the container user's UID/GID to match your host user, ensuring file permissions work correctly with mounted volumes.\n\n## Shell Completions\n\n```bash\n# Bash\ndcx completion bash \u003e /etc/bash_completion.d/dcx\n\n# Zsh\ndcx completion zsh \u003e \"${fpath[1]}/_dcx\"\n\n# Fish\ndcx completion fish \u003e ~/.config/fish/completions/dcx.fish\n```\n\n## Development\n\n```bash\n# Build\nmake build\n\n# Run tests\nmake test\n\n# Build release binaries\nmake build-release\n\n# Run with verbose output\n./bin/dcx -v up\n```\n\n### Requirements\n\n- Go 1.24+\n- Docker Engine\n- docker compose CLI plugin\n\n## Built With\n\nDeveloped using [Claude Code](https://claude.ai/code) by Anthropic.\n\n## License\n\n[MIT License](LICENSE) - Copyright (c) 2026 Griffith Industries Inc\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgriffithind%2Fdcx","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fgriffithind%2Fdcx","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgriffithind%2Fdcx/lists"}