dwe

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

DWE — Dev Workspace Engine

DWE — Dev Workspace Engine

DWE is a CLI that orchestrates Docker-based local development environments on top of a project's compose file — configuration layering, lifecycle, validation, declarative commands. It does not replace compose; edit the compose file freely.
This skill is a navigator with an authoring layer, not a reference. It says which command to run, which file to edit and in what order. Every schema, field and deep behaviour lives in the built-in docs, versioned with the binary:
dwe docs show <topic> --lang en
. Look things up there instead of guessing.
DWE 是一个 CLI,在项目的 compose 文件之上编排基于 Docker 的本地开发环境——涵盖配置分层、生命周期、验证和声明式命令。它不会取代 compose;可以自由编辑 compose 文件。
该 skill 是一个带编写层的导航器,而不是参考资料。它会说明应运行哪个命令、应编辑哪个文件以及按什么顺序编辑。每个 schema、字段和深层行为都收录在内置文档中,并与二进制一同进行版本管理:
dwe docs show <topic> --lang en
。请在那里查询,而不是猜测。

Detecting a DWE project

检测 DWE 项目

Walk up from cwd until a directory contains
workspace.yml
— that is the root. Every
dwe
command resolves the root itself; run it from the root or any descendant. A project with only
workspace.yml
plus commented scaffold files is a fresh
dwe init
— see
references/populate-init-repo.md
.
从 cwd 向上遍历,直到找到包含
workspace.yml
的目录——该目录即为根目录。每个
dwe
命令都会自行解析根目录;可以在根目录或其任意后代目录中运行。仅包含
workspace.yml
和已注释脚手架文件的项目,是刚执行过
dwe init
的全新项目——参见
references/populate-init-repo.md
。

First step: orient yourself

第一步:了解项目上下文

Once per session, inside the project:
shell
dwe docs llms-txt --lang en
It emits a project-aware index (services, live command list, both builtin registries, template syntax by site, doc topics). Read it before anything else.
If a root
AGENTS.md
exists, read it too.
It is the project-specific layer (real services, real command IDs, project rules); this skill is the generic layer. On a project fact the
AGENTS.md
wins; on a generic rule the skill wins.
Two different
AGENTS.md
files exist — do not confuse them:
FileOriginEdit?
root
AGENTS.md
(next to
workspace.yml
)
written once by
dwe init
, then hand-maintained
yes, directly
hub
AGENTS.md
(inside a service hub,
services/<name>/
)
generated by the
ai
render pack (
dwe render ai
, or a
render ai
deploy step)
no — edit
workspace/templates/ai/<pack>/
, hand off
dwe render ai
Neither has a
CLAUDE.md
beside it: Claude Code reads
AGENTS.md
natively, and a
CLAUDE.md
in or above the cwd would make it skip every
AGENTS.md
.
每个会话在项目内执行一次:
shell
dwe docs llms-txt --lang en
它会输出一份感知当前项目上下文的索引(服务、实时命令列表、两个内置注册表、按站点划分的模板语法、文档主题)。在执行其他操作前先阅读它。
如果根目录存在
AGENTS.md
,也要阅读它。
它是项目专属层(真实服务、真实命令 ID、项目规则);本 skill 是通用层。对于项目事实,
AGENTS.md
优先;对于通用规则,本 skill 优先。
存在两种不同的
AGENTS.md
文件——不要混淆:
文件来源可编辑?
根目录
AGENTS.md
(与
workspace.yml
相邻)
由
dwe init
写入一次,之后手动维护
是,直接编辑
hub
AGENTS.md
(位于服务 hub 内的
services/<name>/
)
由
ai
render pack 生成(
dwe render ai
,或
render ai
部署步骤)
否——编辑
workspace/templates/ai/<pack>/
,然后交给
dwe render ai
处理
两者旁边都没有
CLAUDE.md
:Claude Code 原生读取
AGENTS.md
,而位于 cwd 中或 cwd 上方的
CLAUDE.md
会让它跳过所有
AGENTS.md
。

Project anatomy

项目结构

  • 3-layer config, later wins, maps deep-merge:
    workspace.yml
    (identity:
    project
    ,
    update
    ,
    compose
    ,
    secrets
    ) →
    workspace/defaults.yml
    (tracked:
    services
    toggles,
    runtime
    ,
    vars
    ,
    exports
    ,
    bridge
    ) →
    workspace/local.yml
    (gitignored per-dev overrides; tool-written). The root is strict — free-form values live only under
    vars:
    ; a bare custom root key is a hard load error. A
    vars.*
    value may be an
    ENC[age:…]
    marker (committed secret, decrypted at load) →
    config/secrets
    .
  • workspace/docker.yml
    — compose project name, shared volumes, per-subcommand compose args, build prepull. Loaded separately, not in the 3-layer merge; per-key override, per-dev in
    docker.local.yml
    →
    config/docker
    .
  • Services = folders:
    workspace/services/<name>/service.yml
    ; the folder name is the key (no
    name:
    field). The container itself lives in the compose base or an overlay. Optional per-service
    deploy.yml
    /
    reset.yml
    .
  • User commands:
    workspace/commands/**.yml
    ; path + filename + key = dot-ID; run with
    dwe cmd <id>
    .
  • Render packs:
    workspace/templates/{config,ide,ai,git,workspace}/
    —
    config
    writes runtime files into the service hub;
    ide
    /
    ai
    /
    git
    write hub dotfiles (devcontainer, hub
    AGENTS.md
    , git hooks);
    workspace
    writes project-root artifacts selected by top-level
    render.workspace
    (explicit render only).
  • Pipelines (optional, full-replacement):
    workspace/{deploy,lifecycle,reset}.yml
    . Absent = built-in default (reported
    ⓘ
    , not an error). Also
    setup.yml
    (first-deploy wizard),
    validate.yml
    (project checks),
    snapshot.yml
    ,
    info.yml
    /
    styles.yml
    (dashboard, branding),
    i18n/
    .
  • Integration tests:
    workspace/tests/<scenario>.yml
    (name = basename; deploy step schema).
  • Generated, never hand-edited:
    .env
    ,
    .dwe/**
    (deploy journal,
    generated.yml
    , logs, test runs),
    workspace/local.yml
    , rendered hub files.
Layout reference:
dwe docs show concepts/project-layout --lang en
.
  • 3 层配置,后层优先,映射采用深度合并:
    workspace.yml
    (标识:
    project
    、
    update
    、
    compose
    、
    secrets
    )→
    workspace/defaults.yml
    (纳入版本控制:
    services
    开关、
    runtime
    、
    vars
    、
    exports
    、
    bridge
    )→
    workspace/local.yml
    (被 Git 忽略的按开发者覆盖配置;由工具写入)。根目录是严格的——自由格式的值只能放在
    vars:
    下;在根级直接添加自定义键会导致硬加载错误。
    vars.*
    值可以是
    ENC[age:…]
    标记(提交的 secret,加载时解密)→
    config/secrets
    。
  • workspace/docker.yml
    ——compose 项目名、共享卷、按子命令划分的 compose 参数、构建预拉取。它是单独加载的,不参与 3 层合并;可按键覆盖,按开发者使用
    docker.local.yml
    →
    config/docker
    。
  • 服务即文件夹:
    workspace/services/<name>/service.yml
    ;文件夹名称就是键(没有
    name:
    字段)。容器本身位于 compose base 或 overlay 中。可选的每服务
    deploy.yml
    /
    reset.yml
    。
  • 用户命令:
    workspace/commands/**.yml
    ;路径 + 文件名 + 键 = 点号 ID;使用
    dwe cmd <id>
    运行。
  • Render packs:
    workspace/templates/{config,ide,ai,git,workspace}/
    ——
    config
    将运行时文件写入服务 hub;
    ide
    /
    ai
    /
    git
    写入 hub dotfiles(devcontainer、hub
    AGENTS.md
    、Git hooks);
    workspace
    根据顶层
    render.workspace
    写入项目根目录产物(仅显式渲染)。
  • 流水线(可选,完全替换默认行为):
    workspace/{deploy,lifecycle,reset}.yml
    。缺失表示使用内置默认值(报告
    ⓘ
    ,不是错误)。此外还有
    setup.yml
    (首次部署向导)、
    validate.yml
    (项目检查)、
    snapshot.yml
    、
    info.yml
    /
    styles.yml
    (仪表板、品牌)、
    i18n/
    。
  • 集成测试:
    workspace/tests/<scenario>.yml
    (名称 = basename;使用 deploy step schema)。
  • 生成文件,绝不可手动编辑:
    .env
    、
    .dwe/**
    (deploy journal、
    generated.yml
    、日志、测试运行)、
    workspace/local.yml
    、已渲染的 hub 文件。
布局参考:
dwe docs show concepts/project-layout --lang en
。

Rules no validator will catch

验证器无法发现的规则

dwe validate
checks shape, not judgement. These pass validation either way and are what a fresh project gets wrong:
  • Two disjoint registries share the word
    builtin
    .
    when: {type: builtin}
    takes the seven condition predicates (
    dir-empty
    ·
    dir-not-empty
    ·
    dir-exists
    ·
    dir-missing
    ·
    file-exists
    ·
    file-missing
    ·
    generated-missing <svc> <field>
    ). A step body and
    check:
    take the step builtins (
    source_clone
    ,
    service_configs_render
    ,
    containers_running
    ,
    http_check
    , …). Neither accepts the other's names. Need a
    when:
    the predicates lack →
    type: shell
    ; need its inverse as a
    check:
    →
    check: auto
    . Both registries with kinds and summaries:
    dwe docs llms-txt --lang en
    § Builtins.
  • Mount the whole hub, not just
    src/
    .
    dir: ./services/<name>
    +
    dir_internal: /workspace
    +
    work_dir_internal: /workspace/src
    , as a unit. Pointing
    dir:
    at the checkout leaves rendered configs, caches and tooling state outside the container.
  • One definition. A deploy step that runs something the project already declares as a command uses
    type: command
    +
    cmd: <id>
    , never a pasted
    type: shell
    copy — the copies drift, and only the command carries service/workdir/user/env (a shell step runs on the host).
  • A
    ports:
    entry in
    service.yml
    does not publish anything
    — compose binds only when an
    exports.env
    rule surfaces it (
    {name: APP_PORT, from: services.<name>.ports.http}
    ) and compose interpolates that var. DWE tooling still reads the declaration:
    ports_free
    preflight checks it and
    dwe test
    remaps it, so removing it silently drops both.
    PROJECT
    ,
    UID
    ,
    GID
    ,
    COMPOSE_PROJECT_NAME
    are injected into
    .env
    automatically and may not be redeclared; the compose project name is set through
    docker.yml
    project_name
    , always lowercased.
dwe validate
只检查结构,不判断合理性。以下内容无论通过哪种方式都能通过验证,而全新项目最容易在这里出错:
  • 两个彼此独立的注册表都使用
    builtin
    一词。
    when: {type: builtin}
    接受七种条件谓词(
    dir-empty
    ·
    dir-not-empty
    ·
    dir-exists
    ·
    dir-missing
    ·
    file-exists
    ·
    file-missing
    ·
    generated-missing <svc> <field>
    )。步骤主体和
    check:
    接受步骤 builtin(
    source_clone
    、
    service_configs_render
    、
    containers_running
    、
    http_check
    等)。两者都不接受对方的名称。如果需要谓词中不存在的
    when:
    条件,请使用
    type: shell
    ;如果需要将其反向条件用作
    check:
    ,请使用
    check: auto
    。两个注册表及其 kind 和摘要:
    dwe docs llms-txt --lang en
    § Builtins。
  • 挂载整个 hub,而不只是
    src/
    。
    将
    dir: ./services/<name>
    +
    dir_internal: /workspace
    +
    work_dir_internal: /workspace/src
    作为一个整体使用。如果把
    dir:
    指向检出目录,就会把渲染后的配置、缓存和工具状态留在容器外。
  • 只定义一次。 如果 deploy step 运行的是项目已声明为 command 的内容,应使用
    type: command
    +
    cmd: <id>
    ,绝不能粘贴一份
    type: shell
    副本——副本会发生漂移,而且只有 command 会携带 service/workdir/user/env(shell step 在宿主机上运行)。
  • service.yml
    中的
    ports:
    条目不会发布任何内容
    ——只有当
    exports.env
    规则公开该端口(
    {name: APP_PORT, from: services.<name>.ports.http}
    )且 compose 对该变量进行插值时,compose 才会绑定端口。DWE 工具仍会读取该声明:
    ports_free
    预检会检查它,
    dwe test
    会重新映射它,因此删除它会悄悄同时移除这两项。
    PROJECT
    、
    UID
    、
    GID
    、
    COMPOSE_PROJECT_NAME
    会自动注入
    .env
    ,不得重新声明;compose 项目名通过
    docker.yml
    的
    project_name
    设置,并始终转换为小写。

Output conventions

输出约定

  • Always
    --lang en
    for docs
    (
    llms-txt|search|show|list
    ); translations may lag.
  • --output json
    (
    -o json
    ) for data you parse
    :
    status
    ,
    validate
    ,
    services list
    ,
    vars get|list|inspect
    ,
    snapshot list|inspect
    ,
    info
    ,
    logs
    ,
    commands list
    ,
    docs list|search
    ,
    test list|run|clean
    ,
    deploy plan
    ,
    secrets status
    .
  • Read the envelope keys before indexing — a wrong key returns empty with exit 0.
    status
    is
    {project, apps, tools, infra, daemons, deploy, topology, git}
    (no top-level
    services
    );
    info
    is
    {title, sections[]}
    ;
    validate
    is
    {summary, diagnostics[]}
    ;
    commands list
    is
    {commands[]}
    with
    id
    ,
    type
    , optional
    group
    ,
    description
    (localized — match on
    id
    ) +
    summary
    (its first line),
    service
    ,
    params
    ;
    deploy plan
    is
    {phases[{name, steps[{name, type, cmd, unresolved[], when, check, …}]}]}
    .
  • Exceptions:
    docs show
    and
    docs llms-txt
    always emit markdown and ignore
    -o json
    (
    docs show --raw
    when piping;
    llms-txt --out PATH
    writes a file).
    deploy state show
    is always YAML.
    render env
    is always dotenv text.
  • Scope a doc instead of reading it whole:
    dwe docs show <topic>#<anchor>
    ,
    --anchors
    ,
    --toc
    .
  • Bare
    dwe commands
    /
    dwe docs
    /
    dwe status
    /
    dwe vars
    open a TUI on a terminal
    and fall back to plain output in a pipe. Always call the explicit read forms (
    commands list
    ,
    docs list|show|search
    ,
    status --output json
    ,
    vars list
    ).
  • 对文档始终使用
    --lang en
    (
    llms-txt|search|show|list
    );翻译版本可能滞后。
  • 对于要解析的数据,使用
    --output json
    (
    -o json
    )
    :
    status
    、
    validate
    、
    services list
    、
    vars get\|list\|inspect
    、
    snapshot list\|inspect
    、
    info
    、
    logs
    、
    commands list
    、
    docs list\|search
    、
    test list\|run\|clean
    、
    deploy plan
    、
    secrets status
    。
  • 建立索引前先读取封装对象的键——键写错会返回空结果且退出码为 0。
    status
    的结构为
    {project, apps, tools, infra, daemons, deploy, topology, git}
    (没有顶层
    services
    );
    info
    的结构为
    {title, sections[]}
    ;
    validate
    的结构为
    {summary, diagnostics[]}
    ;
    commands list
    的结构为
    {commands[]}
    ,其中包含
    id
    、
    type
    、可选的
    group
    、已本地化的
    description
    (按
    id
    匹配)以及
    summary
    (首行)、
    service
    、
    params
    ;
    deploy plan
    的结构为
    {phases[{name, steps[{name, type, cmd, unresolved[], when, check, …}]}]}
    。
  • 例外:
    docs show
    和
    docs llms-txt
    始终输出 Markdown,并忽略
    -o json
    (管道传输时使用
    docs show --raw
    ;
    llms-txt --out PATH
    会写入文件)。
    deploy state show
    始终为 YAML。
    render env
    始终为 dotenv 文本。
  • 应限定文档范围,而不是通读全文:
    dwe docs show <topic>#<anchor>
    、
    --anchors
    、
    --toc
    。
  • 裸执行
    dwe commands
    /
    dwe docs
    /
    dwe status
    /
    dwe vars
    会在终端上打开 TUI,在管道中则回退为纯文本输出。始终调用显式读取形式(
    commands list
    、
    docs list\|show\|search
    、
    status --output json
    、
    vars list
    )。

When to use what

何时使用什么

GoalCommand / reference
Project overview (start here)
dwe docs llms-txt --lang en
Run a project task (tests, lint, migrate, …)
dwe commands list --output json
→
dwe cmd <id>
;
dwe cmd -i <id> --output json
first if unfamiliar — see Running things
One-off command in a service container
dwe shell <service> -c '<cmd>'
Inspect state / logs / config
dwe status --output json
·
dwe logs <service> --output json
·
dwe validate --output json
Search docs / read a topic
dwe docs search <term> --lang en
·
dwe docs show <topic> --lang en
Read vars / set a var
dwe vars get|list|inspect <var> --output json
· handoff
dwe vars set <path> <value>
(writes
local.yml
); secret-like →
--generate hex[:N]|base64url[:N]|uuid
Encrypted-secret inventory
dwe secrets status --output json
(read-only, exit 0 even when nothing decrypts;
identity.reason
/
identity.hint
name the fix)
Populate a fresh repo from git URL(s)
references/populate-init-repo.md
Add a service / tool / infra
references/add-service-and-tools.md
Author a command or daemon
references/authoring-commands.md
Render packs / vars /
.env
/ generated secrets
references/render-and-vars.md
Author a pipeline (deploy / lifecycle / setup / validate / info / styles / docker.yml)
references/pipelines-and-orchestration.md
Integration test / verify a clean deploy
references/integration-tests.md
Snapshot / reset / troubleshoot
references/snapshots-reset-troubleshoot.md
Apply a changePicking the apply command below — edit yml, then ASK the user to run it
目标命令 / 参考
项目概览(从这里开始)
dwe docs llms-txt --lang en
运行项目任务(测试、lint、迁移等)
dwe commands list --output json
→
dwe cmd <id>
;如果不熟悉,先使用
dwe cmd -i <id> --output json
——参见运行任务
服务容器内的一次性命令
dwe shell <service> -c '<cmd>'
检查状态 / 日志 / 配置
dwe status --output json
·
dwe logs <service> --output json
·
dwe validate --output json
搜索文档 / 阅读主题
dwe docs search <term> --lang en
·
dwe docs show <topic> --lang en
读取 vars / 设置 var
dwe vars get|list|inspect <var> --output json
· 交给用户运行
dwe vars set <path> <value>
(写入
local.yml
);类似 secret 的值使用
--generate hex[:N]|base64url[:N]|uuid
加密 Secret 清单
dwe secrets status --output json
(只读,即使没有内容可解密,退出码也为 0;
identity.reason
/
identity.hint
会指出修复方式)
从 Git URL 填充全新仓库
references/populate-init-repo.md
添加服务 / 工具 / 基础设施
references/add-service-and-tools.md
编写 command 或 daemon
references/authoring-commands.md
Render packs / vars /
.env
/ 生成的 Secret
references/render-and-vars.md
编写 pipeline(deploy / lifecycle / setup / validate / info / styles / docker.yml)
references/pipelines-and-orchestration.md
集成测试 / 验证全新部署
references/integration-tests.md
Snapshot / reset / 排障
references/snapshots-reset-troubleshoot.md
应用改动下面的应用命令选择指南——编辑 yml,然后让用户运行相应命令

Running things

运行任务

Most work in an existing project is running its own tasks. Two commands, not interchangeable:
dwe cmd <id>
— a task the project declares.
Prefer it: it carries the right service, workdir, user, env and compose flags. Find IDs with
dwe commands list --output json
(entries carry
id
,
description
,
service
; match on
id
, the description follows the project locale).
dwe cmd -i <id> --output json
shows what it runs, whether it takes
--set key=value
params or
${args}
pass-through after
--
(
dwe cmd site.test -- --run x.test.ts
), and its
confirmation:
flag. A command that rejects extra arguments has no
${args}
slot — the error names the one-line fix; adding it beats working around it.
dwe shell <service> -c '<cmd>'
— anything not declared.
Legitimate escape hatch; repetition is the signal it wants to be a declared command — say so rather than running it a third time.
  • Check the registry before any task a declared command may cover — tests, linters, formatters, builds, codegen, migrations, seeds, cache/token management, package-manager scripts. Once per session, again after
    workspace/commands/
    changes. Do not run the underlying npm/composer/make/docker command until that check is made.
  • Scoped first, full before giving up. A hub
    AGENTS.md
    may carry a
    Declared commands
    block naming the service's groups (
    dwe commands list <group> --output json
    ). A scoped listing that finds nothing is not proof of absence: project-wide and workflow commands declare no
    service:
    — run one full listing before falling back to
    dwe shell
    . Block counts are declared; a
    hide:
    can shorten the live listing.
  • Output streams. The
    ▶ <id>
    run banner goes to stderr (and is not printed with
    -o json
    ), so stdout of
    dwe cmd <id>
    is the command's own output.
    dwe -v cmd <id>
    also echoes the exact process it spawns (
    docker compose … exec|run …
    , host
    sh -c …
    ) to stderr.
  • Long-running command →
    dwe shell … --tty
    (
    dwe cmd
    has no such flag). Without it the child's stdout is a pipe, block-buffers, and looks hung. Leave it off when parsing output (a PTY turns
    \n
    into
    \r\n
    ).
  • Never
    docker exec
    /
    docker compose exec
    instead.
    dwe shell
    resolves the container from the service name and applies its
    cli:
    block;
    docker ps | grep
    is the tell you wanted
    dwe status
    or
    dwe shell
    .
现有项目中的大多数工作都是运行项目自身的任务。以下两个命令不可互换:
dwe cmd <id>
——项目声明的任务。
优先使用它:它会携带正确的 service、workdir、user、env 和 compose flags。使用
dwe commands list --output json
查找 ID(条目包含
id
、
description
、
service
;按
id
匹配,description 遵循项目 locale)。
dwe cmd -i <id> --output json
会显示命令实际运行的内容、是否接受
--set key=value
参数或
--
之后的
${args}
透传(
dwe cmd site.test -- --run x.test.ts
),以及其
confirmation:
标志。如果一个命令拒绝额外参数,说明它没有
${args}
槽位——错误信息会给出单行修复方法;补上该槽位优于绕过限制。
dwe shell <service> -c '<cmd>'
——未声明的任何操作。
这是合法的逃生舱;如果同类操作反复出现,就说明它应该成为已声明的 command——此时应直接说明,而不是第三次运行它。
  • 在执行声明命令可能涵盖的任何任务前,先检查注册表——测试、linters、formatters、构建、codegen、migrations、seeds、缓存/token 管理、package-manager scripts。每个会话检查一次,
    workspace/commands/
    发生变化后再次检查。在完成检查前,不要直接运行底层 npm/composer/make/docker 命令。
  • 先查限定范围,再查全量后放弃。 hub
    AGENTS.md
    可能包含一个
    Declared commands
    区块,其中列出了服务的命令组(
    dwe commands list <group> --output json
    )。限定范围查询无结果并不能证明命令不存在:项目级和工作流命令不声明
    service:
    ——在回退到
    dwe shell
    前,先运行一次完整列表。区块计数是已声明的数量;
    hide:
    可以缩短实时列表。
  • 输出流。
    ▶ <id>
    运行横幅会写入 stderr(使用
    -o json
    时不会打印),因此
    dwe cmd <id>
    的 stdout 就是命令自身的输出。
    dwe -v cmd <id>
    还会将实际启动的进程(
    docker compose … exec|run …
    、宿主机
    sh -c …
    )回显到 stderr。
  • 长时间运行的命令 →
    dwe shell … --tty
    (
    dwe cmd
    没有此标志)。不加该标志时,子进程的 stdout 是一根管道并进行块缓冲,看起来像卡住。解析输出时不要加该标志(PTY 会把
    \n
    变成
    \r\n
    )。
  • 绝不要改用
    docker exec
    /
    docker compose exec
    。
    dwe shell
    会根据服务名解析容器并应用其
    cli:
    区块;需要
    docker ps | grep
    时,应改用
    dwe status
    或
    dwe shell
    。

Picking the apply command

选择应用命令

After editing yml, hand the user the command that matches what changed (never run it yourself):
  • service.yml
    / a service's
    deploy.yml
    /
    configs
    /
    dirs
    / service
    render
    / added a service /
    workspace/deploy.yml
    →
    dwe deploy run
  • workspace/lifecycle.yml
    or the compose base/overlays →
    dwe run
  • toggled a service →
    dwe services enable|disable <name> --apply
  • workspace
    template / top-level
    render.workspace
    →
    dwe render workspace [pack…]
    (explicit; not automatic on deploy)
  • exports.env
    only →
    dwe run
    (or
    dwe deploy run --force
    ) — that block is in no config hash, so a plain
    dwe deploy run
    journal-skips the
    .env
    render (
    references/render-and-vars.md
    § 6)
  • only icon / host / display strings →
    dwe validate
    (then
    run
    /
    deploy run
    if runtime is affected)
  • authored a
    workspace/tests/<scenario>.yml
    →
    dwe validate tests
    , then
    dwe test run <scenario>
    (gated — see below)
  • mixed / unsure →
    dwe deploy run
    (ends in
    docker up --wait
    , so it covers a restart)
dwe deploy run --service <name>
requires that service's own
deploy.yml
and skips the final stack up — only for re-running one provisioned service, never for a new one. Never recommend
--force
as a clean install: it only ignores prior state (
when:
still applies). A true clean install is
dwe reset run && dwe deploy run
.
编辑 yml 后,把与改动内容相匹配的命令交给用户(绝不要自行运行):
  • service.yml
    / 服务的
    deploy.yml
    /
    configs
    /
    dirs
    / 服务
    render
    / 新增服务 /
    workspace/deploy.yml
    →
    dwe deploy run
  • workspace/lifecycle.yml
    或 compose base/overlays →
    dwe run
  • 切换服务开关 →
    dwe services enable\|disable <name> --apply
  • workspace
    template / 顶层
    render.workspace
    →
    dwe render workspace [pack…]
    (显式执行,不会在 deploy 时自动运行)
  • 仅修改
    exports.env
    →
    dwe run
    (或
    dwe deploy run --force
    )——该区块不包含在任何配置哈希中,因此普通
    dwe deploy run
    的 journal 会跳过
    .env
    渲染(
    references/render-and-vars.md
    § 6)
  • 仅修改 icon / host / display 字符串 →
    dwe validate
    (如果影响运行时,再执行
    run
    /
    deploy run
    )
  • 编写了
    workspace/tests/<scenario>.yml
    →
    dwe validate tests
    ,然后
    dwe test run <scenario>
    (受下列门槛约束)
  • 混合改动 / 不确定 →
    dwe deploy run
    (最终会执行
    docker up --wait
    ,因此也涵盖重启)
dwe deploy run --service <name>
要求该服务自身存在
deploy.yml
,并且会跳过最终的 stack up——仅用于重新运行一个已预配服务,绝不能用于新服务。不要将
--force
作为全新安装方式推荐:它只会忽略先前状态(
when:
仍会生效)。真正的全新安装是
dwe reset run && dwe deploy run
。

Permission boundary — read freely, never mutate

权限边界——可自由读取,绝不执行变更

READ — run without asking (no state change, safe even when they report errors):
  • status
    ,
    logs
    ,
    validate
    (+
    validate config|checks|env|tests|…
    ,
    --stage
    ),
    info
  • deploy plan
    ,
    reset plan
    ,
    deploy state show
    ,
    deploy eject
    /
    reset eject
    without
    --out
  • snapshot list|current|inspect
  • compose argv <subcommand>
    (bare, it errors),
    compose files
    ,
    docker ps|logs|project-name
    ,
    bridge status|logs
  • vars get|list|inspect
    ,
    commands list [group]
    /
    cmd -i <id>
    ,
    services list
  • secrets status
    ,
    secrets key list
    — no plaintext, no key material.
    secrets get
    and
    secrets key export
    DO print secret material — handoff.
  • render env
    bare only (no
    --out
    ): prints the resolved
    .env
    , writes nothing. Its unfiltered body is the whole exported secret set — always scope it:
    dwe render env | grep -E '^<NAME>='
    . Host-only.
  • docs show|search|list|llms-txt
  • test list
    (lock-free, no Docker;
    -o json
    carries each scenario's
    cost_profile
    ),
    test clean --dry-run
读取——无需询问即可运行(无状态变更,即使报告错误也安全):
  • status
    、
    logs
    、
    validate
    (+
    validate config\|checks\|env\|tests\|…
    、
    --stage
    )、
    info
  • deploy plan
    、
    reset plan
    、
    deploy state show
    、不带
    --out
    的
    deploy eject
    /
    reset eject
  • snapshot list\|current\|inspect
  • compose argv <subcommand>
    (裸执行会报错)、
    compose files
    、
    docker ps\|logs\|project-name
    、
    bridge status\|logs
  • vars get\|list\|inspect
    、
    commands list [group]
    /
    cmd -i <id>
    、
    services list
  • secrets status
    、
    secrets key list
    ——不输出明文或密钥材料。
    secrets get
    和
    secrets key export
    确实会输出 Secret 材料——应交给用户处理。
  • 仅裸执行
    render env
    (不带
    --out
    ):打印解析后的
    .env
    ,不会写入任何内容。其未过滤的输出包含全部已导出的 Secret——始终限定范围:
    dwe render env | grep -E '^<NAME>='
    。仅限宿主机执行。
  • docs show\|search\|list\|llms-txt
  • test list
    (不获取锁,不使用 Docker;
    -o json
    会携带每个场景的
    cost_profile
    )、
    test clean --dry-run

Running project tasks — judge the task, not the verb

运行项目任务——根据任务判断,而不是根据动词

dwe cmd <id>
and
dwe shell <service> -c '…'
are transports: their risk is whatever they carry.
  • Run without asking when the task only reads or verifies in place: linters, type-checks, formatters in check mode, in-container inspection, a test suite that talks to nothing stateful.
  • Ask first when it changes project or data state: migrations, seeds, resets, dependency installs, anything writing outside a build cache — and anything you are unsure about.
  • A test suite that reaches the project's database or another stateful service is in the second group. Integration suites routinely truncate and re-seed the schema they run against; pointed at the live stack they destroy the developer's working data (observed: one
    npx nx test
    via
    dwe shell
    silently replaced every row of a dev database). Check what the suite connects to; when it needs the stack, the isolated way is a
    workspace/tests/
    scenario via
    dwe test run
    , gated below.
  • dwe cmd -i <id>
    shows
    confirmation:
    — a declared one means ask. Being asked to "run the tests" is permission to run the tests, not to run them against the live stack when they write to it.
dwe cmd <id>
和
dwe shell <service> -c '…'
只是传输机制:其风险取决于所承载的任务。
  • 无需询问即可运行,前提是任务只在原位读取或验证:linters、type-checks、处于检查模式的 formatters、容器内检查,以及不访问任何有状态对象的测试套件。
  • 必须先询问,前提是任务会更改项目或数据状态:migrations、seeds、resets、依赖安装、任何写入 build cache 之外位置的操作,以及任何你不确定的任务。
  • 访问项目数据库或其他有状态服务的测试套件属于第二组。 集成测试套件经常截断并重新填充其运行所针对的 schema;如果指向实时运行的 stack,就会破坏开发者的本地数据(曾观察到:通过
    dwe shell
    运行一次
    npx nx test
    ,会悄无声息地替换开发数据库中的每一行)。应检查测试套件连接到什么;当测试需要 stack 时,隔离方式是使用
    dwe test run
    运行
    workspace/tests/
    场景,详见下方门槛。
  • dwe cmd -i <id>
    会显示
    confirmation:
    ——如果声明了该字段,就必须询问。用户要求“运行测试”,并不等于允许在会写入数据的实时 stack 上运行测试。

The
dwe test run
gate — cheap AND isolated, or ask

dwe test run
门槛——既廉价又隔离,否则先询问

dwe test run
is a full clean Docker deploy of a throwaway copy — mutating and slow, but the only way to prove a deploy pipeline still works. Read
dwe test list --output json
first; each scenario's
cost_profile
decides:
  • Hard stops — hand it over, no judgement call:
    isolation_findings
    non-empty after dropping entries with
    "shared": true
    (the fix for
    interpolated_host_port
    is routing the port through
    services.<name>.ports
    or an
    exports.env
    rule
    from: vars.<path>
    );
    shared_volumes
    > 0;
    host_steps
    > 0 (project-authored code on the host —
    type: shell
    , the
    shell
    builtin, host commands, shell
    when:
    /
    check:
    ; dwe's own subcommands don't count, so the built-in pipeline reports 0).
  • Cost — judge it:
    build_services
    ,
    external_images
    ,
    max_start_period_seconds
    . A build is not an automatic stop — read the Dockerfile; the profile reports whether there is a build, never what it costs (layer-cache warmth is not modelled).
Run unattended only when all hard stops are clear and you can account for the cost; otherwise — and when unsure — hand over the exact command. Always
dwe validate tests
(free) first, and propose a run only for substantial changes (new service, reworked pipeline, provisioning/secrets), never after a display-only edit. Details:
references/integration-tests.md
.
MUTATE — never invoke yourself. Prepare the change, then give the user the exact command:
  • dwe init
    (safe to re-run: gap-fills;
    --force
    overwrites)
  • dwe deploy run [--service|--force|--resume]
    ,
    dwe run
    /
    stop
    /
    restart
    ,
    dwe reset run
    (destructive)
  • dwe services enable|disable <name> --apply
  • dwe vars set
    ,
    dwe render config|ide|ai|git|workspace
    ,
    dwe render env --out <path>
    ,
    dwe render config --harvest
  • dwe deploy eject --out
    /
    dwe reset eject --out
    ,
    dwe deploy state clear|repair
  • dwe snapshot create|restore|rollback|remove|pack|unpack
    ,
    dwe bridge start|stop
    ,
    dwe docs generate|export|cache clear
  • dwe secrets init|set|get|encrypt|decrypt|rekey|key import|export|remove
    — each writes a layer / keyfile or prints secret material.
    key import
    is a human handoff: it opens a hidden prompt; never ask the user for the identity text so you can paste it (it would land in a transcript).
  • dwe cmd <id>
    /
    dwe shell … -c
    when the task they carry mutates
  • dwe test clean
    (without
    --dry-run
    );
    dwe test run
    when the gate above does not clear it
Pattern: edit yml → show the diff → give the exact command → wait. Never work around the boundary through
docker
/
docker compose
/ project scripts — including through
dwe shell
.
dwe test run
会对一次性副本执行完整的全新 Docker 部署——它会更改状态且速度较慢,但也是证明 deploy pipeline 仍然有效的唯一方式。先读取
dwe test list --output json
;每个场景的
cost_profile
决定后续操作:
  • 硬性停止条件——直接交给用户,不做主观判断:删除
    "shared": true
    条目后,
    isolation_findings
    仍非空(
    interpolated_host_port
    的修复方式,是通过
    services.<name>.ports
    路由端口,或使用
    exports.env
    规则
    from: vars.<path>
    );
    shared_volumes
    > 0;
    host_steps
    > 0(项目编写的宿主机代码——
    type: shell
    、
    shell
    builtin、宿主机命令、shell
    when:
    /
    check:
    ;dwe 自身的子命令不计入,因此内置 pipeline 报告 0)。
  • 成本——需要判断:
    build_services
    、
    external_images
    、
    max_start_period_seconds
    。构建并不自动构成停止条件——请阅读 Dockerfile;profile 只报告是否存在构建,而不会说明构建成本(层缓存的冷热程度不在模型中)。
只有在所有硬性停止条件均已排除,并且你能说明其成本时,才可以无人值守运行;否则——以及不确定时——把准确命令交给用户。始终先执行
dwe validate tests
(免费),并且只针对重大改动提出运行建议(新服务、重新设计的 pipeline、预配/secrets),绝不要在仅影响展示的编辑后运行。详情参见
references/integration-tests.md
。
变更——绝不要自行调用。 准备好改动,然后把准确命令交给用户:
  • dwe init
    (可安全重复运行:会补齐缺失项;
    --force
    会覆盖)
  • dwe deploy run [--service\|--force\|--resume]
    、
    dwe run
    /
    stop
    /
    restart
    、
    dwe reset run
    (破坏性操作)
  • dwe services enable\|disable <name> --apply
  • dwe vars set
    、
    dwe render config\|ide\|ai\|git\|workspace
    、
    dwe render env --out <path>
    、
    dwe render config --harvest
  • dwe deploy eject --out
    /
    dwe reset eject --out
    、
    dwe deploy state clear\|repair
  • dwe snapshot create\|restore\|rollback\|remove\|pack\|unpack
    、
    dwe bridge start\|stop
    、
    dwe docs generate\|export\|cache clear
  • dwe secrets init\|set\|get\|encrypt\|decrypt\|rekey\|key import\|export\|remove
    ——每一项都会写入 layer / keyfile 或输出 Secret 材料。
    key import
    是人工交接:它会打开隐藏提示;绝不要让用户提供身份文本供你粘贴(那会进入对话记录)。
  • 当
    dwe cmd <id>
    /
    dwe shell … -c
    承载的任务会进行变更时
  • dwe test clean
    (不带
    --dry-run
    );门槛未排除风险时运行
    dwe test run
模式:编辑 yml → 显示 diff → 给出准确命令 → 等待。 绝不要通过
docker
/
docker compose
/ 项目脚本绕过此边界——包括通过
dwe shell
绕过。

Anti-patterns

反模式

  • Do NOT bypass the lifecycle: never
    docker compose up/down
    ,
    dwe docker up
    , or
    dwe compose raw
    writes — DWE tracks state and holds locks.
  • Do NOT hand-edit generated artifacts (
    .dwe/**
    ,
    .env
    ,
    workspace/local.yml
    , rendered hub files incl. the hub
    AGENTS.md
    ). Edit the source (export rule / var / template / pack) and hand off the render/deploy.
  • Do NOT put a free-form key at the config root — it goes under
    vars:
    .
  • Do NOT "fix" an
    <encrypted>
    value or a
    secrets.unresolved
    block by editing yml. The marker means this machine lacks the project's age identity;
    dwe secrets status --output json
    names the cause and the fix (
    dwe secrets key import
    , run by the user, or
    DWE_AGE_KEY
    ). At a terminal
    dwe run
    /
    restart
    /
    deploy
    offer the import themselves. Rewriting the marker as plaintext commits the credential; deleting it breaks everyone else.
  • Do NOT assume config shape — verify with
    dwe docs show config/<area> --lang en
    before editing anything under
    workspace/
    .
  • Do NOT enumerate pending-op consumers from memory after
    dwe services …
    without
    --apply
    — run
    dwe status
    ; its banner is authoritative.
  • 不要绕过生命周期:绝不要使用
    docker compose up/down
    、
    dwe docker up
    或
    dwe compose raw
    进行写入——DWE 会跟踪状态并持有锁。
  • 不要手动编辑生成产物(
    .dwe/**
    、
    .env
    、
    workspace/local.yml
    、已渲染的 hub 文件,包括 hub
    AGENTS.md
    )。应编辑源文件(export rule / var / template / pack),然后交给 render/deploy 处理。
  • 不要在配置根级放置自由格式的键——它应位于
    vars:
    下。
  • 不要通过编辑 yml 来“修复”
    <encrypted>
    值或
    secrets.unresolved
    区块。该标记表示当前机器缺少项目的 age identity;
    dwe secrets status --output json
    会指出原因和修复方式(由用户运行
    dwe secrets key import
    ,或设置
    DWE_AGE_KEY
    )。在终端执行
    dwe run
    /
    restart
    /
    deploy
    时,应由 DWE 自行提示导入。将标记重写为明文会提交凭据;删除它则会破坏其他所有人的环境。
  • 不要假设配置结构——编辑
    workspace/
    下的任何内容之前,先使用
    dwe docs show config/<area> --lang en
    进行确认。
  • 执行
    dwe services …
    而未加
    --apply
    后,不要凭记忆枚举待处理操作的消费者——运行
    dwe status
    ;它显示的横幅才是权威依据。

Reference files

参考文件

Load on demand when the task matches:
  • references/populate-init-repo.md
    — git URL(s) / "set up this project" / fresh
    init
    'd repo: interview → init → services → deploy → commands → render/vars → validate → deploy handoff.
  • references/add-service-and-tools.md
    — app/tool/infra service, toggles, compose overlays,
    extends
    .
  • references/authoring-commands.md
    — user commands and daemons: type zoo, params, templating, bridge opt-in.
  • references/render-and-vars.md
    — render packs, generated-secret harvest, the
    vars
    sandbox,
    exports.env
    .
  • references/pipelines-and-orchestration.md
    — per-service & project
    deploy.yml
    ,
    lifecycle
    ,
    setup
    ,
    validate
    ,
    info
    /
    styles
    ,
    docker.yml
    .
  • references/integration-tests.md
    —
    workspace/tests/<scenario>.yml
    , port isolation, the debugging loop.
  • references/snapshots-reset-troubleshoot.md
    — triage trio, snapshot workflows, reset.
任务匹配时按需加载:
  • references/populate-init-repo.md
    ——Git URL / “设置此项目” / 刚通过
    init
    创建的仓库:访谈 → init → services → deploy → commands → render/vars → validate → deploy 交接。
  • references/add-service-and-tools.md
    ——应用/工具/基础设施服务、开关、compose overlays、
    extends
    。
  • references/authoring-commands.md
    ——用户 command 和 daemon:类型集合、参数、模板、bridge opt-in。
  • references/render-and-vars.md
    ——render packs、生成 Secret 的 harvest、
    vars
    沙箱、
    exports.env
    。
  • references/pipelines-and-orchestration.md
    ——每服务及项目级
    deploy.yml
    、
    lifecycle
    、
    setup
    、
    validate
    、
    info
    /
    styles
    、
    docker.yml
    。
  • references/integration-tests.md
    ——
    workspace/tests/<scenario>.yml
    、端口隔离、调试循环。
  • references/snapshots-reset-troubleshoot.md
    ——triage trio、snapshot 工作流、reset。