DWE — Dev Workspace Engine
A single-binary CLI for running, configuring, and maintaining containerised local development environments declaratively.
Why dwe
Section titled “Why dwe”- One descriptive tree (
workspace.yml+workspace/) drives the whole project — services, pipelines, commands, info dashboard, templates, translations. - Deploy, run, stop, restart, reset, and snapshot share the same pipeline engine, so behaviour is consistent across operations.
- Container orchestration sits on top of plain Docker Compose files the project already owns — no synthetic compose generation, no hidden lock-in.
- Per-developer overrides live in tracked
defaults.ymlplus gitignoredlocal.yml; the same project boots cleanly on every workstation. - The host bridge mounts a tiny
dweshim into dev containers, so git hooks and project commands work identically on the host and inside a devcontainer terminal. - Embedded docs and i18n make
dwe docsand translated UIs work without network access or out-of-band assets.
Install
Section titled “Install”DWE ships as a single static Go binary. Pick whichever channel fits.
Using Homebrew
Section titled “Using Homebrew”brew install semsemyonoff/tap/dweInstalls the binary plus bash, zsh, and fish completion to the standard Homebrew paths. Works on macOS (Intel + Apple Silicon) and Linux (linuxbrew).
From releases
Section titled “From releases”Download the appropriate archive or package from GitHub releases:
dwe_<version>_macos_{x86_64,arm64}.tar.gzanddwe_<version>_linux_{x86_64,arm64}.tar.gz— extract and dropdweinto/usr/local/bin(or any directory on$PATH); the archive bundles acompletions/folder for use withdwe completion install.dwe_<version>_{amd64,arm64}.deb—sudo dpkg -i dwe_*.deb; completion is installed automatically under/usr/share/{bash-completion,zsh/site-functions,fish/vendor_completions.d}.dwe-<version>-1.{x86_64,aarch64}.rpm—sudo rpm -i dwe-*.rpm; completion paths match the deb package.
File integrity can be verified against the published checksums.txt.
From source
Section titled “From source”git clone https://github.com/semsemyonoff/dwe.gitcd dwemake buildmake build runs go mod tidy, syncs docs/ into internal/core/docs/embedded/, regenerates internal/core/docs/content_hashes_gen.go, compiles ./cmd/dwe, and writes bin/dwe. The binary is self-contained: docs, translations, default pipelines, and built-in steps are embedded. Drop it on $PATH:
install -m 0755 bin/dwe /usr/local/bin/dwe
go install github.com/semsemyonoff/dwe/cmd/dwe@latestis intentionally unsupported: the embedded docs tree (internal/core/docs/embedded/) is generated byscripts/sync-embedded-docs.shat build time and is gitignored, so ago installbuild would ship with empty docs.
Shell completion (tar.gz only)
Section titled “Shell completion (tar.gz only)”If the binary came from a tar.gz archive, completion is installed via a separate command:
dwe completion install # autodetect $SHELLdwe completion install zsh # or specify the shell explicitlySupported shells: bash, zsh, fish, powershell. See dwe completion install --help for details and dry-run.
Runtime dependencies
Section titled “Runtime dependencies”docker (with docker compose), git, and a POSIX shell on the host. If they live in non-standard locations, override their paths in the user-level config at ~/.config/dwe/config via binary_<name> = <path> entries — see docs/reference/config/userconfig.md.
Optional: AI agent skill
Section titled “Optional: AI agent skill”The repository ships an agent skill at skills/dwe/ — a thin navigator that teaches Claude Code, Codex, Cursor, OpenCode, and other compatible agents how to detect a DWE project, which dwe commands to use for inspection vs mutation, and how to look up everything else through the built-in dwe docs subsystem.
Claude Code — as a plugin
Section titled “Claude Code — as a plugin”This repository is also a Claude Code plugin marketplace. Add the marketplace and install the dwe plugin (which bundles the skill) from inside Claude Code:
/plugin marketplace add semsemyonoff/dwe/plugin install dwe@dwedwe@dwe is <plugin>@<marketplace> — both are named dwe. Run /plugin (no arguments) for the interactive browser instead. Once installed, the skill activates automatically whenever you work in a directory containing workspace.yml. To enable it across a team or in CI, commit the marketplace and plugin to .claude/settings.json:
{ "extraKnownMarketplaces": { "dwe": { "source": { "source": "github", "repo": "semsemyonoff/dwe" } } }, "enabledPlugins": { "dwe@dwe": true }}Any agent — via the skills CLI
Section titled “Any agent — via the skills CLI”The vercel-labs/skills CLI installs the same skill into Claude Code, Codex, Cursor, OpenCode, and others:
# install into the current project (./<agent>/skills/)npx skills add semsemyonoff/dwe --skill dwe
# or install globally for all your projectsnpx skills add semsemyonoff/dwe --skill dwe -g
# target a specific agent (claude-code, codex, cursor, opencode, ...)npx skills add semsemyonoff/dwe --skill dwe -a claude-codeQuickstart
Section titled “Quickstart”Starting from scratch? Scaffold a new project with a single command:
dwe init my-project # interactive: prompts for name, prefix, brandingcd my-projectdwe validate # check the scaffolded configJoining an existing project? Enter a project directory containing workspace.yml and run any command — DWE walks upward from the working directory to locate the project root.
Validate the project before the first deploy:
cd my-projectdwe validateBuild and start the stack:
dwe deploy run # idempotent: install, configure, migrate, bring updwe info # rendered URLs, hosts, command groupsDrive the runtime lifecycle:
dwe run # before-hooks → docker up → after-hooks → readydwe stop # before-stop → docker down → after-stopdwe restart # stop + rundwe status # services, ports, hosts, git, envPlan-only previews are read-only:
dwe deploy plan # resolved phase/step tree, no executiondwe validate # readiness checksThe deploy journal lives at .dwe/deploy/state.yml. Repeat runs skip steps whose action_hash and inputs are unchanged. Deploy logs are written to .dwe/logs/deploy.log by default (suppress with log: false); lifecycle logs (run/stop/reset) are written only when log: true is set.
Architecture
Section titled “Architecture”DWE sits between the developer and a Dockerized stack: it reads a project’s YAML tree, renders a small amount of generated state next to it, and drives docker compose to actually run the containers. The developer never types docker compose directly.
flowchart LR Dev["Developer"] -->|dwe| CLI["dwe CLI"] Project["DWE project config<br/>+ compose config"] --> CLI CLI -->|docker compose| Engine["Docker engine"] Engine --> Containers["containers"] Dev -.->|http / tcp| Containers
- DWE owns the project model, the ordered compose file list, env rendering, lifecycle orchestration, locks, and the state journal under
.dwe/. - Docker owns containers, networks, volumes, image layers, and health reporting. The only handshake is the argv DWE passes to
docker composeand the exit code it returns. - Every invocation is short-lived and stateless: no plugin loader, no network on the normal path, and no resident process except the per-project host-bridge daemon that serves dev containers while the stack is up. Uninstalling DWE leaves the compose files under
compose/as valid standalonedocker composeinput.
Full write-up: docs/reference/concepts/architecture.md.
Project layout
Section titled “Project layout”A typical project keeps its declarative tree under workspace/, Docker Compose overlays under compose/, and runtime data under .dwe/ / snapshots/ / backups/.
my-project/├── workspace.yml # project identity├── workspace/ # tracked config tree│ ├── defaults.yml # versioned defaults (optional)│ ├── local.yml # per-developer overrides (gitignored, optional)│ ├── services/<name>/ # per-service folders (service.yml + optional pipelines)│ ├── commands/ # declarative user commands (optional)│ ├── templates/ # template packs for `dwe render` (optional)│ ├── deploy.yml # top-level deploy orchestrator (optional)│ ├── lifecycle.yml # run / stop / restart (optional)│ ├── reset.yml # reset pipeline (optional)│ ├── info.yml # info dashboard (optional)│ ├── validate.yml # readiness checks (optional)│ ├── tests/ # integration-test scenarios for `dwe test` (optional)│ └── docker.yml # compose file list + topology (optional)├── compose/ # tracked Docker Compose overlays (per service)├── images/ # tracked image builds (<service>/Dockerfile)├── services/ # gitignored service sources (<hub>/src/)├── snapshots/ # gitignored snapshot stash├── backups/ # gitignored DB/other dumps└── .dwe/ # gitignored CLI runtime data (state, locks, logs)Full write-up: docs/reference/concepts/project-layout.md.
Documentation
Section titled “Documentation”📖 Browse the full documentation online at semsemyonoff.github.io/dwe.
Reference documentation lives under docs/reference/ and is also embedded in the binary. Browse it offline with dwe docs (interactive TUI) or dwe docs show <topic> (plain text).
- Concepts — high-level orientation: getting started, architecture, project layout, Docker integration, Git integration, pipelines, state and locks.
- Configuration — field-level reference for
workspace.yml, services, commands, deploy/reset/lifecycle pipelines, snapshot, info, validate, setup, styles, UI, state, i18n, notifications, docker. - Render packs —
dwe render env / ide / ai / git / config— manifest schema, collision policies, local overrides. - Documentation subsystem — the
dwe docsbrowser, non-interactive subcommands, translations, content-hash staleness. - Templates — the shared template engine:
{{ ... }}vs${ ... }, sprout registries, render context per site. - Guides — task-oriented recipes and integrations (e.g. Starship prompt).
Run dwe --help (or any subcommand with --help) for the live CLI surface.
Useful one-liners:
dwe docs # interactive browserdwe docs list # enumerate every topicdwe docs show <topic> # render one pagedwe docs search <term> # cross-tree searchdwe docs llms-txt # compact AI-agent project indexLicense
Section titled “License”Released under the MIT License.