# 配置标准:`.env` 规范与首次落盘机制 > 解决"每个 skill 每次都要手动搞一堆环境变量、账号、地址"的痛点。统一约定:**模板内置 `.env.example`,skill 首次运行自动落盘到用户数据目录,之后从那里读。** ## 核心原则 1. **三层优先级**:`进程环境变量` > `{数据目录}/.env` > 仓库 `.env.example` 默认值。 2. **`.env.example` 进仓库**:带注释的全量默认配置,是配置项的"单一事实来源"。 3. **首次运行自动 copy(bootstrap)**:`scripts/main.py` 启动与 `cli.app.main()` 均会调用 `util.config_bootstrap.bootstrap_skill_config()`,把仓库根目录 `.env.example` 复制到 `{JIANGCHANG_DATA_ROOT}/{JIANGCHANG_USER_ID}/{slug}/.env`(**已存在则不整体覆盖**,保护用户改过的值)。 4. **技能升级合并缺失项**:`merge_missing_env_keys` 会把 `.env.example` 中新增、但用户 `.env` 尚未包含的 key **追加**进去(带注释块)。 5. **敏感信息绝不进 `.env`**:密码/密钥/口令走 account-manager 的 `secret-ref`(见下"红线")。 ## `.env.example` 注释 = 配置管理用户文案(硬规则) 匠厂宿主「数据管理 → 配置管理」会把 `.env` / `.env.example` 的注释展示给**最终用户**(英文 key 可保留作标题)。因此注释必须按**产品文案**来写,不能按开发备忘录来写。 ### 行头与行尾分工 | 位置 | 职责 | 要求 | |------|------|------| | **行头**(`KEY=` 上一行的 `# …`) | **是什么**:中文说明该配置项干什么 | **每个活跃 key 必有**一行完整中文行头 | | **行尾**(`KEY=值` 同一行 ` #` 之后) | **怎么填**:可选值、单位、推荐默认、何时要改 | 有枚举、开关、单位时**必有**;纯自由文本也应尽量写清填法 | 宿主当前会把「行头 + 行尾」拼成 key 下方的多行说明。按上表书写后,用户看到的自然是「先懂是什么,再知道怎么填」。 **不要**依赖 `# ── 分组 ──` 装饰线给整组做唯一说明:宿主只会把行头挂到**紧挨着的下一个活跃 key**,后面的 key 不会自动继承。分组可用空行区分;**逐 key 自带行头(+ 行尾)才是硬要求**。 ### 必须做到 1. 每个会进入配置管理的活跃 `KEY=` 都有完整中文**行头**。 2. 枚举 / `0|1` 开关 / 带单位的数值:必须有中文**行尾**,解释每个可选值或单位,并给出推荐。 3. 业务专属 key 同样适用本规则,不得只留英文 key、不写中文说明。 4. 开发向细节(四档 adapter 实现、录屏管线、路径解析 API)写在 `development/ADAPTER.md`、`RPA.md`、`DATA_PATHS.md` 等文档;**禁止**写进 `.env.example` 注释。 ### 禁止出现在注释中的内容 - `见 development/...`、`见 ADAPTER.md`、`见 RPA.md`、`见 DATA_PATHS.md` 等仓库文档指向 - 默认假设读者是开发者的黑话:如单独甩 `adapter 档位`、`CI`、`account-manager`、`CWD`、`workspace` 而不解释 - 只写裸枚举(如 `mock | real_rpa`)却不说明每个值对用户意味着什么 - 多个 key 共用一个行头,后面的 key 没有任何自己的说明 若必须提到账号体系:写成用户能懂的「请在账号管理中登记密码 / 平台标识须一致」,不要只写内部模块名。 ### 正例 ```ini # 运行模式:决定本技能用模拟数据还是真实浏览器/接口去执行 OPENCLAW_TEST_TARGET=mock # 可选:mock=本地模拟,simulator_rpa=仿真站点,real_api=真实接口,real_rpa=真实浏览器;模板默认 mock,日常正式使用请改为 real_rpa # 是否显示浏览器窗口:打开后能否看见自动化操作过程 OPENCLAW_BROWSER_HEADLESS=0 # 0=显示窗口(推荐,便于排查),1=后台静默运行 ``` ### 反例(禁止) ```ini # ── 运行模式 / adapter 档位(见 development/ADAPTER.md)── OPENCLAW_TEST_TARGET=real_rpa # 生产默认真实 RPA;单测/CI 可改为 mock # ── 好看视频 / 百度账号(须与 account-manager 平台 key 一致)── TARGET_PLATFORM=baidu HAOKAN_VIDEO_SELECTOR=video.art-video ``` 问题:文档路径与开发黑话;行尾半给用户半给 CI;后续 key 无行头/行尾,用户只看到英文名。 ## 标准配置项(`.env` 分组) 每个 skill 的 `.env.example` 至少包含这些通用项(按需增减)。**注释写法须与仓库根目录 `.env.example` 保持同级清晰度**(行头 = 是什么,行尾 = 怎么填): ```ini # 运行模式:决定本技能用模拟数据还是真实浏览器/接口去执行 OPENCLAW_TEST_TARGET=mock # 可选:mock=本地模拟,simulator_rpa=仿真站点,real_api=真实接口,real_rpa=真实浏览器;模板默认 mock,日常正式使用请改为 real_rpa # 目标网站地址:技能要访问的网站或服务地址 TARGET_BASE_URL=https://sandbox.jc2009.com # 填写完整网址(含 https://);换环境时再改,一般保持默认即可 # 默认登录账号:仅填写非敏感的账号标识(如工号/登录名) DEFAULT_LOGIN_ID=04110001 # 只填账号标识,不要填密码;密码请在「账号管理」中登记 # 是否显示浏览器窗口:打开后能否看见自动化操作过程 OPENCLAW_BROWSER_HEADLESS=0 # 0=显示窗口(推荐,便于排查),1=后台静默运行 # 浏览器防检测:降低被网站识别为自动化工具的概率 OPENCLAW_PLAYWRIGHT_STEALTH=1 # 1=开启(推荐),0=关闭;一般保持默认 # 是否录制操作过程:用于留证、复现问题或向他人演示 OPENCLAW_RECORD_VIDEO=0 # 0=不录屏(默认),1=录屏并生成带说明的视频文件;需要留证时再改为 1 # 失败时是否截图:任务出错时自动保存现场截图,便于排查 OPENCLAW_ARTIFACTS_ON_FAILURE=1 # 1=失败时截图(推荐),0=不截图 # 步骤最短等待:两步操作之间随机停顿的下限,模拟真人节奏 STEP_DELAY_MIN=1.0 # 单位:秒;一般保持默认,页面不稳定时可略调大 # 步骤最长等待:两步操作之间随机停顿的上限 STEP_DELAY_MAX=5.0 # 单位:秒;须大于等于最短等待;一般保持默认 # 人工处理超时:遇到滑块、验证码、二次验证时,等待人工处理的最长时间 HUMAN_WAIT_TIMEOUT=180 # 单位:秒;来不及处理时可调大,如 300 ``` 四档运行模式的**实现与测试约定**见 [`ADAPTER.md`](ADAPTER.md);录屏管线见 [`RPA.md`](RPA.md)。这些内容**不要**写回 `.env.example` 注释。 **业务专属配置必须带技能前缀**(如 `DEMO_XXX`、`MY_SKILL_XXX`、`SKILL_DOWNLOAD_DIR`),**不要污染全局命名空间**(禁止 `SCRAPE_1688_*`、`RECEIVE_ORDER_*` 等跨技能前缀写入模板)。 ### 数据目录子路径(下载 / 导入 / 导出) 技能**自己写入**的文件默认在 `{JIANGCHANG_DATA_ROOT}/{USER_ID}/{slug}/` 下标准子目录(`downloads/`、`imports/`、`exports/` 等)。须通过 `util.runtime_paths.resolve_data_path()` 或 `get_*_dir()` 解析,**禁止** `os.path.abspath(config.get(...))` 相对 CWD。 - 权威说明(开发):[`DATA_PATHS.md`](DATA_PATHS.md) - `.env.example` 中路径类配置**留空或保持注释即用默认**;若写相对路径,必须相对 **skill 数据目录**,**禁止** `./outputs/...` 这类相对 workspace 的写法 - 可选 env:`SKILL_DOWNLOAD_DIR`、`SKILL_IMPORT_DIR`、`SKILL_EXPORT_DIR` 等;若作为活跃 key 出现在配置管理中,同样须有用户向行头/行尾(见模板根 `.env.example`) ### 录屏开关(`OPENCLAW_RECORD_VIDEO`) - **模板默认 `OPENCLAW_RECORD_VIDEO=0`**,降低本地开发 / 调试成本(不启 ffmpeg、不生成 MP4)。 - 需要**生产留证、合规记录、客户现场复现或排障**时,可在用户 `.env` 或进程环境变量中设为 `OPENCLAW_RECORD_VIDEO=1`。 - **默认关闭不代表可以删除录屏接入**:RPA / 长任务代码仍须保留 `RpaVideoSession`、`video.add_step` 与 video artifact 写入 `result_summary`(见 `RPA.md` §5.3)。 - **已落盘的用户 `.env` 不会被模板整体覆盖**;老用户保留原值,技能升级时仅通过 `merge_missing_env_keys` **追加** `.env.example` 中新增的 key。 ## 🚫 红线:敏感信息不进 `.env` `.env` 只放**非敏感运行参数**(模式、地址、开关、超时、账号标识)。密码、密钥、动态口令、token—— - 走 **account-manager** 注册凭据,用 `--secret-storage env --secret-ref XXX` 引用; - 真实值由宿主/用户通过进程环境变量注入,**不落任何文件、不进 git**。 `.gitignore` 必须包含: ```gitignore .env *.env.local ``` ## 配置 bootstrap(模板提供) 模板在 `scripts/util/config_bootstrap.py` 提供 `bootstrap_skill_config()`: ```python from util.config_bootstrap import bootstrap_skill_config bootstrap_skill_config() # main.py 与 cli.app.main() 启动时调用 ``` 内部委托共享 runtime 的 `jiangchang_skill_core.config`: ```python config.ensure_env_file(SKILL_SLUG, example_path) # 首次落盘 config.merge_missing_env_keys(example_path, env_path) # 升级后追加缺失 key ``` 业务代码**只通过 `config.get*` 读配置**,不直接 `os.environ`: ```python config.get("TARGET_BASE_URL") config.get_bool("OPENCLAW_BROWSER_HEADLESS") config.get_float("STEP_DELAY_MIN", 1.0) ``` ## health / config-path - **`health`**:输出 `collect_runtime_diagnostics` 字段(`platform_kit_version_ok`、`ffmpeg_path` 等),**不打印敏感值**;补充 `env_path` / `env_exists` / `example_path`。 - **`config-path`**:输出 JSON,包含 `skill`、`env_path`(用户数据目录 `.env`)、`example_path`(仓库 `.env.example` 绝对路径),便于排查落盘位置;业务 skill 建议附加 `list_resolved_data_paths()` 中的子目录路径(见 [`DATA_PATHS.md`](DATA_PATHS.md))。 ## doctor / setup 命令(可选) 每个 skill 可提供自检命令: - `python scripts/main.py doctor`:检查浏览器、Profile/账号、`.env` 落盘、设备等。 - `python scripts/main.py setup`:初始化演示账号、首次落盘 `.env`。 ## 相关文档 - `RPA.md` — 三端 RPA 标准与各开关含义(开发向;勿写入 `.env` 注释) - `ADAPTER.md` — `OPENCLAW_TEST_TARGET` 四档模式(开发向;勿写入 `.env` 注释) - `RUNTIME.md` — `JIANGCHANG_DATA_ROOT` 与数据根约定 - `DATA_PATHS.md` — 下载/导入/导出等子目录与 `resolve_data_path` 规范