hatchctl is a Go command-line tool for working with Dev Container based
workspaces from the terminal. It creates or reconnects to a workspace container,
runs commands inside it, shows the resolved Dev Container configuration, and can
rerun Dev Container lifecycle hooks without requiring editor integration.
The project targets terminal-first workflows on macOS and Linux. It shells out to Docker or Podman instead of talking directly to a container engine API.
- Start, build, inspect, and enter Dev Container workspaces from one CLI
- Run one-off commands inside the managed container
- Emit JSON output for scripts
- Use Docker by default, with Podman support available
- Keep repository-controlled, host-affecting settings behind explicit trust flags
- Optional macOS bridge support for browser opening and localhost callback forwarding
- Go, if building from source
- Docker or Podman available on
PATH - Compose support from the selected backend when using compose-based Dev Containers
- macOS for bridge support
Create or reuse the Dev Container for the current workspace:
hatchctl upOpen a shell inside the managed container:
hatchctl execRun a one-off command:
hatchctl exec -- go test ./...Inspect the resolved config and detected runtime state:
hatchctl configRun lifecycle hooks again:
hatchctl run --phase startUse JSON output in scripts:
hatchctl up --json
hatchctl config --json
hatchctl exec --json -- sh -lc 'go test ./...'Use -- with exec to separate hatchctl flags from the command to run inside
the container.
hatchctl up: resolve configuration, then create or reconnect to the managed Dev Container, building it first when neededhatchctl build: build the Dev Container image without starting ithatchctl exec: open a shell or run a command inside the managed containerhatchctl config: show merged config and detected runtime statehatchctl run: run Dev Container lifecycle phases again in an existing containerhatchctl bridge doctor: inspect bridge availability and current bridge session statehatchctl version: print version information
hatchctl reads configuration from:
- user config
- Linux:
~/.config/hatchctl/config.toml - macOS:
~/Library/Application Support/hatchctl/config.toml
- Linux:
- workspace config:
.hatchctl/config.toml
Workspace config is intentionally limited until the repository is explicitly trusted.
Example config:
backend = "auto"
config = ".devcontainer/devcontainer.json"
feature_timeout = "2m"
lockfile_policy = "auto"
[dotfiles]
repository = "lauritsk/dotfiles"Useful environment variables:
HATCHCTL_TRUST_WORKSPACE=1HATCHCTL_ALLOW_HOST_LIFECYCLE=1HATCHCTL_COSIGN_STRICT=1HATCHCTL_ALLOW_INSECURE_FEATURES=1HATCHCTL_DOTFILES_REPOSITORYHATCHCTL_DOTFILES_INSTALL_COMMANDHATCHCTL_DOTFILES_TARGET_PATH
hatchctl assumes devcontainer.json and workspace-local config may come from a
repository that has not been trusted yet. Host-affecting behavior is opt-in.
Security defaults include:
- Host-side
initializeCommandis blocked unless--allow-host-lifecycleis passed - Repo-controlled backend settings that expand host access are blocked unless
--trust-workspaceis passed - Unsigned images warn by default;
HATCHCTL_COSIGN_STRICT=1blocks execution - Unsigned remote OCI features fail by default in unattended runs
- Direct tarball features must use
https, except loopbackhttpfor local use and tests - The macOS bridge uses only loopback addresses