Dynamic workspace mounting wrapper for Colima devcontainers.
Problem: Colima mounts are static (configured at startup). Running devcontainer up requires workspaces to already exist in the VM, but they're dynamic local paths. Mounting $HOME broadly exposes all projects to every container — a security risk, especially when running autonomous agents.
Solution: dcx dynamically mounts only the workspace you need, only while in use. It uses bindfs (a FUSE userspace tool) to project your workspace into a pre-mounted relay directory (~/.colima-mounts), then starts the devcontainer there.
Benefits:
- Security: Only the active workspace is mounted; other projects remain private
- Performance: No need to mount
$HOMEbroadly; multiple isolated workspaces can coexist - Convenience: One command (
dcx up) handles mount creation, devcontainer startup, and cleanup
curl -fsSL https://raw.githubusercontent.com/aroonavm/dcx/main/install.sh | shInstalls to /usr/local/bin by default. Override with DCX_BIN_DIR=~/.local/bin.
Prerequisites: bindfs, devcontainer CLI, and Colima.
# Setup (one time)
sudo apt install bindfs # Linux — see specs/guides/setup.md for macOS
# Edit ~/.config/colima/default/colima.yaml to mount ~/.colima-mounts
colima stop && colima start
# Usage
dcx up # Start devcontainer with mount
dcx exec --workspace-folder . /bin/zsh # Run command in container
dcx down # Stop container and cleanupSet DCX_DEVCONTAINER_CONFIG_DIR_PATH to avoid passing --config-dir on every invocation:
export DCX_DEVCONTAINER_CONFIG_DIR_PATH=~/.dcx/
dcx up --workspace-folder ~/project-a # Uses env var config directory
dcx up --workspace-folder ~/project-b # Uses env var config directory
dcx up --workspace-folder ~/project-c --config-dir /other/config # Flag overrides env varThe directory must contain a devcontainer.json file and optionally a dcx_config.yaml file.
Mount specific host files into containers via a dcx_config.yaml file or the --file CLI flag.
Option 1: Per-project config file (dcx_config.yaml)
Create .devcontainer/dcx_config.yaml (or dcx_config.yaml in your project root):
up:
network: minimal
files:
- path: ~/.gitconfig # Hardlinked: static config, writes propagate to host
- path: ~/.claude.json # Live-synced: keeps file in sync via inotify/FSEvents
sync: trueThen:
dcx up --workspace-folder .File mounting strategies:
-
Standard files (
sync: falseor omitted): Hardlinked into the container (writes propagate back to host), or copied as readonly if on a different filesystem. Works well for config files that don't change frequently. -
Live-synced files (
sync: true): Content is copied to a staging directory and kept in sync bidirectionally via a background daemon. Perfect for authentication files like~/.claude.jsonthat may be updated atomically by the host application. The daemon uses inotify (Linux) / FSEvents (macOS) for immediate change detection, with SHA256-based debouncing to avoid spurious syncs.
When to use sync: true:
- Authentication/credential files that apps write atomically (temp+rename)
- Files that change while the container is running and the container needs the latest version
- Example:
~/.claude.json(Claude Code writes atomically on auth changes)
When to use standard mounting:
- Static config files (git, ssh config)
- Files that rarely change after container start
- Files that should be bidirectionally linked (hard/soft links)
For the full configuration reference including merge behavior and discovery rules, see Configuration Reference.
Option 2: CLI flag
Mount files ad-hoc with --file:
dcx up --workspace-folder . --file ~/.gitconfig --file ~/.ssh/id_ed25519Add these mounts to your Colima config file (~/.config/colima/default/colima.yaml on Linux, ~/.colima/default/colima.yaml on macOS):
mounts:
- location: ~/.gitconfig
writable: false
- location: ~/.claude
writable: true
- location: ~/.colima-mounts
writable: truedcx reads this file at startup and automatically injects any listed mounts (except ~/.colima-mounts itself) into every container it starts. For ~/.gitconfig and ~/.claude, it also sets GIT_CONFIG_GLOBAL and CLAUDE_CONFIG_DIR so the tools find their config at the right path.
This means git identity and Claude login are available in every container without any per-project configuration.
Control network access per container with --network:
# Default: minimal — dev tools only (GitHub, npm, Anthropic APIs, VSCode, Sentry)
dcx up --workspace-folder ~/my-project
# Restricted: no external network access
dcx up --workspace-folder ~/my-project --network restricted
# Host-only: connect to services on host machine (localhost:*)
dcx up --workspace-folder ~/my-project --network host
# Open: unrestricted access (use for local dev only)
dcx up --workspace-folder ~/my-project --network openEach container gets its own network mode. Useful for:
- Security: Autonomous agents with restricted network (can't exfiltrate data)
- Sandboxing: Different projects with different trust levels
- Testing: Host-only mode to test against local services
# Example: Shared dev environment with mixed trust levels
dcx up --config-dir ~/.dcx --workspace-folder ~/trusted-project --network minimal
dcx up --config-dir ~/.dcx --workspace-folder ~/untrusted-agent --network restricted
dcx up --config-dir ~/.dcx --workspace-folder ~/testing-project --network host
# The base image is shared: same devcontainer.json content → same image.
# Changing devcontainer.json (e.g. bumping a package version) triggers a new build.Configure Colima to start automatically on system boot using dcx autostart:
# Enable autostart (writes systemd service on Linux, launchd plist on macOS)
dcx autostart enable
# Check current status
dcx autostart status
# Disable autostart later
dcx autostart disableThe service file location depends on your platform:
- Linux:
~/.config/systemd/user/colima.service(user-level systemd service) - macOS:
~/Library/LaunchAgents/io.colima.autostart.plist(launchd agent)
This eliminates the need to manually start Colima after system boot — it will start automatically and be ready for your first dcx up command.
- Setup Guide — Installation & configuration
- Architecture — How it works, commands, usage
- Troubleshooting — Error recovery
- Full Index — All documentation
Three Dockerfiles are provided for different use cases:
| File | Base | Purpose |
|---|---|---|
.devcontainer/slim/Dockerfile |
rust:slim-bookworm |
Slim dev image (git + bindfs). Default for contributors. |
.devcontainer/full/Dockerfile |
node:latest |
Full image (Claude Code, zsh, git-delta). For a more complete dev environment. |
tests/e2e/Dockerfile.test |
rust:slim-bookworm |
Minimal test image (git + node + devcontainer CLI, no bindfs). |
# Slim image (default) — start with:
dcx up --workspace-folder . --config-dir .devcontainer/slim
# Full image — for the complete dev environment:
dcx up --workspace-folder . --config-dir .devcontainer/fullThe .devcontainer/full/ directory includes a dcx_config.yaml that stages:
~/.gitconfig— hardlinked into staging (standard mount, static config). Also auto-injected by dcx via colima.yaml mounts.~/.claude.json— live-synced (sync: true, via inotify/FSEvents daemon)
This means Claude Code in the container will see authentication updates from the host in real-time as you log in/out, without needing to restart the container. Note: ~/.gitconfig appears in both the dcx_config.yaml and colima.yaml; dcx automatically deduplicates these at runtime. Git config remains hardlinked for efficiency since it rarely changes during container runtime.
cargo build --release
cargo install --path .This installs dcx to ~/.cargo/bin/. Ensure ~/.cargo/bin is in your PATH (add export PATH="$HOME/.cargo/bin:$PATH" to your shell rc file if needed).
The release process builds binaries for all platforms (Linux x86_64/aarch64, macOS x86_64/aarch64) and publishes them as GitHub Release assets, along with a Debian package.
-
Update version in
Cargo.toml:# Edit Cargo.toml, change version = "0.1.0" to version = "0.1.2" -
Update Cargo.lock by building:
cargo build --release
-
Commit both files:
git add Cargo.toml Cargo.lock git commit -m "Bump version to 0.1.2" -
Create a git tag (tag must match version in Cargo.toml):
git tag v0.1.2
-
Push commits and tag (in two steps to avoid race conditions):
git push origin main git push origin v0.1.2
The tag push triggers three workflows:
validate-release.yml— Checks that tag, Cargo.toml, and Cargo.lock all matchrelease.yml— Builds binaries for 4 platforms + Debian package + creates GitHub Release- If validation fails, release is skipped (CI shows error)
Once the GitHub Release is published, users can install from:
# Install script (auto-detects platform, downloads binary)
curl -fsSL https://raw.githubusercontent.com/aroonavm/dcx/main/install.sh | sh
# Debian/Ubuntu
sudo dpkg -i dcx_<version>_amd64.deb
# Manual (download from releases, extract, move to PATH)
tar -xzf dcx-v<version>-<platform>.tar.gz
sudo mv dcx /usr/local/bin/