settings
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
Chinese/settings — view or change project config
/settings — 查看或更改项目配置
Manages (team-wide config, committed) and
(per-developer overrides, gitignored). Use this skill to inspect current
settings or change them without manually editing YAML.
project.yamlproject.local.yamlAutomation mode: Resolve ( →
→ default ). The approval gates in Phase 4 and
Phase 5 follow the pattern in . Note:
writing to is a decision (a default
category), so confirms config writes even
in mode unless the user has removed from their
always-ask list.
modes.automationproject.local.yamlproject.yamlcollaborative.claude/docs/automation-modes.mdproject.yamlschema_changesautomation_always_ask/settingsautonomousschema_changes管理 (提交到版本控制库的团队级配置)和
(每位开发人员的本地覆盖配置,已被 gitignore)。使用此 skill 可检查当前
设置,或在不手动编辑 YAML 的情况下更改设置。
project.yamlproject.local.yaml自动化模式:解析 ( →
→ 默认值 )。第 4 阶段和第 5 阶段的审批关卡遵循
中的模式。注意:
写入 属于 决策(默认的
类别),因此,即使处于 模式,
仍会确认配置写入操作,除非用户已从始终询问列表中删除
。
modes.automationproject.local.yamlproject.yamlcollaborative.claude/docs/automation-modes.mdproject.yamlschema_changesautomation_always_askautonomous/settingsschema_changesPhase 0: Parse Arguments
第 0 阶段:解析参数
Determine which of the four forms the user invoked:
| Form | Mode |
|---|---|
| View-all (Phase 2) |
| View-one (Phase 3) |
| Set-yaml (Phase 4) |
| Set-local (Phase 5) |
For Set-yaml and Set-local, is a dotted YAML path (e.g.
, ) and is the new value.
<key>modes.review_modetesting.strict.logic<value>Empty-operand validation: After splitting the operand on
, if either or is empty, this is malformed — route to
Phase 6 (usage) rather than attempting the write. The rule applies in both
Set-yaml and Set-local routing: for , strip the token
first, then check the remaining operand the same way (so
and both go to Phase 6).
key=value=<key><value>--local--local/settings --local =foo/settings --local key=Anything else that doesn't match the four forms above → Phase 6 (usage).
确定用户调用的是以下四种形式之一:
| 形式 | 模式 |
|---|---|
| 查看全部(第 2 阶段) |
| 查看单项(第 3 阶段) |
| 设置 YAML(第 4 阶段) |
| 设置本地值(第 5 阶段) |
对于“设置 YAML”和“设置本地值”模式, 是一个点分隔的 YAML 路径
(例如 、), 是新值。
<key>modes.review_modetesting.strict.logic<value>空操作数验证:按 拆分 操作数后,如果 或
任一为空,则格式错误——转到第 6 阶段(用法),不要尝试写入。
此规则同时适用于“设置 YAML”和“设置本地值”路由:对于 ,先移除
标记,然后以相同方式检查剩余操作数(因此
和 均转到第 6 阶段)。
=key=value<key><value>--local--local/settings --local =foo/settings --local key=其他任何不匹配上述四种形式的内容 → 第 6 阶段(用法)。
Phase 1: Load Helper
第 1 阶段:加载辅助脚本
All four subcommands need . Run each helper call as its own
plain command:
yaml-helper.shbash
bash "${CLAUDE_SKILL_DIR}/../../hooks/yaml-helper.sh" <helper call><helper call>resolve_setting modes.review_modevalidate_yaml_enum project.yamlproject.yamlproject.local.yamlis_locally_overridable01sourcecd ... &&; echo $?If is missing, this is not a CCGS project.
Report the error and exit.
.claude/hooks/yaml-helper.sh所有四个子命令都需要 。每次辅助函数调用都应单独作为
普通命令运行:
yaml-helper.shbash
bash "${CLAUDE_SKILL_DIR}/../../hooks/yaml-helper.sh" <helper call><helper call>resolve_setting modes.review_modevalidate_yaml_enum project.yamlproject.yamlproject.local.yamlis_locally_overridable01sourcecd ... &&; echo $?如果 不存在,则当前项目不是 CCGS 项目。
报告错误并退出。
.claude/hooks/yaml-helper.shPhase 1b: Reserved-setting detection
第 1b 阶段:检测保留设置
Some settings are fully documented and settable, and no skill
or hook reads them — setting one changes nothing. This skill must say so.
Returning an ordinary success lets a user reasonably believe the behaviour the
setting describes is now enforced — an accessibility tier being the case that
motivates this. (The key is not named here on purpose; see the note below.)
The banner exists only in
, which someone
configuring their project will never open. A setting that does nothing must never look
exactly like one that works — obligation 3.
.claude/docs/effects-map.md.claude/rules/skill-authoring.mdDerive the set; do not hardcode it (obligation 5):
bash
grep -B14 '^> ### RESERVED' .claude/docs/effects-map.md | grep -E '^## 'Match the banner HEADING (), never the bare word "RESERVED".
's section mentions the banner in prose, to record that it
carried one and later became a live setting. A looser match re-reports a working
setting as dead — the direction that understates what the framework does, and
why the dead-settings gate asserts both directions.
> ### RESERVEDplatform.cert_tierA heading may name two keys joined by " and " — split on that separator so
both are captured, or the second one silently escapes the set. Let
be the result.
RESERVED_SETDeliberately phrased without naming those keys. The dead-settings gate asserts that a setting on the allowlist has no readers, and it counts any skill file that spells the key. Naming them here to illustrate the split would makeregister as a reader of two settings nothing reads, and the gate would fail — correctly. Spelling a dead path out while explaining why not to use it trips the same wire. Reword instead of adding an exemption: the strictness is the point, so do not re-introduce the literal names to make an example clearer./settings
Never refuse a write to a reserved key. Storing the value a user intends is
legitimate; storing it silently is the defect.
有些设置已有完整文档且可以设置,但没有任何 skill 或 hook 读取它们——
设置这些选项不会产生任何效果。此 skill 必须明确说明这一点。
如果只返回常规成功信息,用户会合理地以为该设置所描述的行为现在已生效——
无障碍等级设置正是促成这一要求的典型情况。(这里故意不指出具体键名;
请参阅下方说明。)该横幅只存在于 ,
而配置项目的人永远不会打开它。无效设置绝不能看起来与有效设置完全一样——
这是 义务 3 的要求。
.claude/docs/effects-map.md.claude/rules/skill-authoring.md应推导出该集合,不要将其硬编码(义务 5):
bash
grep -B14 '^> ### RESERVED' .claude/docs/effects-map.md | grep -E '^## '必须匹配横幅标题(),绝不能只匹配裸词 。
的章节在正文中提及过该横幅,用于记录它曾经拥有
横幅,后来变成了有效设置。更宽松的匹配会把有效设置重新报告为失效设置——
这种错误方向会低估框架的实际能力,也正是失效设置门禁同时断言两个方向的原因。
> ### RESERVEDRESERVEDplatform.cert_tier一个标题可能用 连接两个键——必须按该分隔符拆分,
否则第二个键会悄悄漏出集合。令结果为 。
andRESERVED_SET这里刻意不指出这些键名。失效设置门禁会断言,白名单中的设置没有读取方, 并统计任何明确写出键名的 skill 文件。如果在这里为说明拆分方式而指出这些键名,就会被登记为两个无人读取设置的读取方,门禁将失败——而且失败得完全正确。 在解释为何不要使用它们时写出失效路径,也会触发同样的陷阱。 请改写措辞,而不是添加例外:严格性正是重点,因此不要为了让示例更清楚 而重新引入字面键名。/settings
绝不能拒绝写入保留键。存储用户意图的值是合理行为;静默存储才是缺陷。
Phase 2: View-all Mode
第 2 阶段:查看全部模式
(when no arguments)
-
Confirmexists. If missing, report:
project.yaml"Nofound — runproject.yamlto create one." And exit./start -
Check ifexists.
project.local.yaml -
Runand capture any errors. If
validate_yaml_enum project.yamlexists, also runproject.local.yaml. Tag each error with its source file so the user can tell them apart.validate_yaml_enum project.local.yaml -
Enumerate leaves. Use thetool to read both YAML files as text. Walk through each file's structure and collect every leaf key into a deduplicated list of dotted paths. A leaf is a
Readline whose value is non-empty (a scalar or inline-array) — NOT a parent block that introduces a nested map. Maintain insertion order per file; merge by appending leaves fromkey: valuethat aren't already present fromproject.local.yaml. The resulting list is the set of leaves to display.project.yamlThen append the rigor family —,modes.rigor,modes.workflow,docs.density,qa.level,modes.story_granularity,modes.review_mode— for any of the seven the merged list does not already contain. These are normally leaves of neither file:team.sizehas a terminal default and the other six are supplied by the rigor expansion (modes.rigorandmodes.review_modemay also appear as file leaves when set locally, but must still be appended so their derived value shows). Enumerating only file leaves would hide exactly the settings a user just chose, in the one view meant to show them.team.size -
For each leaf, perform three reads and one check:
- →
resolve_setting <path>, TAB,<value>. This walks the whole chain (<source>→project.local.yaml→ legacy file →project.yamlexpansion → default), so it is the only read that can report a derived value or name what supplied it.rigor - → yaml-only value (needed only to show what a local override is shadowing)
get_yaml_key project.yaml <path> - → 0 (overridable) or 1 (locked)
is_locally_overridable <path>
Compute the source annotation from:<source><source>Annotation , yaml-only value non-emptyproject.local.yaml(LOCAL OVERRIDE — yaml has: <yamlvalue>), yaml-only value emptyproject.local.yaml(project.local.yaml)project.yaml(project.yaml)a legacy file path (e.g. )production/review-mode.txt(<path>, legacy)rigor:<level>(derived from rigor: <level>)default(default)unsetskip the leaf (don't print unset keys) Appendto the annotation when, lockedreturned 1.is_locally_overridableAppendwhen the leaf is in, reserved(Phase 1b), and print this line with the legend below the block:RESERVED_SETreserved = stored, but nothing reads it. Setting it changes no behaviour today.All four phases must carry the reserved marking — view-one, view-all, and both write paths. Marking view-one and the writes while leaving view-all — the most-used form of this skill — unmarked means a user who set a reserved key sees it listed beside working settings with an ordinaryannotation, in the view most people actually run. Guard all four: view-one and view-all are twins in exactly the way the two write paths are.(project.yaml) -
Print, grouped by top-level section (,
framework,modes, etc.) in the order leaves first appeared. The grouping is determined by the dotted path, not by which file the leaf came from — e.g.enginegroups undermodes.automationeven if onlymodes:defines it. Within each section, indent leaves by 2 spaces; nest further for sub-blocks (e.g.project.local.yaml). Example output:testing.strict.*
project.yaml: present
project.local.yaml: present
Schema validation: ok
Effective config:
framework:
version: 1.2.0 (project.yaml, locked)
modes:
review_mode: lean (project.yaml)
automation: autonomous (LOCAL OVERRIDE — yaml has: collaborative)
rigor: full (project.yaml, locked)
workflow: full (derived from rigor: full, locked)
story_granularity: fine (derived from rigor: full, locked)
docs:
density: terse (project.yaml, locked)
qa:
level: full (derived from rigor: full, locked)
engine:
name: Godot (project.yaml, locked)
version: 4.7 (project.yaml, locked)
testing:
strict:
logic: false (LOCAL OVERRIDE — yaml has: true)
integration: true (project.yaml)
locked = cannot be overridden in project.local.yaml (project-wide setting).
It does NOT mean fixed: a derived value can still be set explicitly with
/settings <key>=<value>, and an explicit value wins over rigor.Print that two-line legend after the config block whenever any rendered
line carries . Without it users read as "immutable" and
conclude a rigor-derived knob cannot be changed — the opposite of what
Phase 3's view-one tells them for the same knob ("an explicit value wins
over rigor"). The two views must not leave contradictory impressions of
the same knob's mutability.
lockedlockedThe line above is the precedence rule made visible: an
explicit value keeps winning over the level would
otherwise derive, so "comprehensive but compact" stays expressible.
docs.densityproject.yamlrigorIf schema errors exist, print them in this form before the effective
config block:
Schema validation: ERRORS
[project.yaml] modes.review_mode: 'chaotic' is not a valid value (expected: full|lean|solo)
[project.local.yaml] engine.name: 'Pygame' is not a valid value (expected: Godot|Unity|Unreal)(无参数时)
-
确认存在。如果不存在,请报告:
project.yaml“未找到——运行project.yaml创建一个。” 然后退出。/start -
检查是否存在。
project.local.yaml -
运行并捕获所有错误。 如果
validate_yaml_enum project.yaml存在,也运行project.local.yaml。为每条错误标注其来源文件, 以便用户区分。validate_yaml_enum project.local.yaml -
枚举叶节点。 使用工具以文本形式读取两个 YAML 文件。 遍历每个文件的结构,将所有叶节点键收集到去重后的点分隔路径列表中。 叶节点是值非空的
Read行(标量或行内数组),而不是引入嵌套映射的 父级块。保持每个文件中的插入顺序;对于key: value中尚不存在的键, 将project.yaml中的叶节点追加到末尾。最终得到的列表就是要显示的 叶节点集合。project.local.yaml然后追加配置系列——rigor、modes.rigor、modes.workflow、docs.density、qa.level、modes.story_granularity、modes.review_mode——将其中尚未出现在合并列表中的键追加进去。这七项通常都不是 两个文件中的叶节点:team.size具有最终默认值,其他六项由modes.rigor扩展提供 (当在本地设置时,rigor和modes.review_mode也可能作为文件叶节点出现, 但仍须追加它们,以显示其派生值)。仅枚举文件叶节点,会在这个专门用于 展示设置的视图中,恰好隐藏用户刚刚选择的设置。team.size -
针对每个叶节点,执行三次读取和一次检查:
- →
resolve_setting <path>、制表符、<value>。这会遍历整个 解析链(<source>→project.local.yaml→ 旧版文件 →project.yaml扩展 → 默认值),因此它是唯一能够报告派生值或指出其来源的读取操作。rigor - → 仅 YAML 中的值(仅用于显示本地覆盖 遮蔽了哪个项目级值)。
get_yaml_key project.yaml <path> - →
is_locally_overridable <path>(可覆盖)或0(锁定)。1
根据计算来源标注:<source><source>标注 ,仅 YAML 的值非空project.local.yaml(LOCAL OVERRIDE — yaml has: <yamlvalue>),仅 YAML 的值为空project.local.yaml(project.local.yaml)project.yaml(project.yaml)旧版文件路径(例如 )production/review-mode.txt(<path>, legacy)rigor:<level>(derived from rigor: <level>)default(default)unset跳过该叶节点(不要打印未设置的键) 当返回is_locally_overridable时,在标注后追加1。, locked当叶节点位于中时,追加RESERVED_SET(第 1b 阶段), 并在配置块下方打印以下说明:, reservedreserved = stored, but nothing reads it. Setting it changes no behaviour today.所有四种模式都必须带有保留标记——查看单项、查看全部,以及两条写入路径。 只标记查看单项和写入路径,却漏掉查看全部——这个 skill 最常用的形式—— 会导致设置过保留键的用户在最常使用的视图中,看到它与有效设置并列显示, 并附带普通的标注。必须保护全部四种模式:查看单项和查看全部 彼此对应,正如两条写入路径彼此对应。(project.yaml) -
打印,按顶层区块(、
framework、modes等)分组, 顺序采用叶节点首次出现的顺序。分组依据是点分隔路径,而不是叶节点来自 哪个文件——例如,即使只有engine定义了project.local.yaml, 它仍会归入modes.automation。每个区块内的叶节点缩进 2 个空格;更深层级的子区块 继续嵌套(例如modes:)。输出示例:testing.strict.*
project.yaml: present
project.local.yaml: present
Schema validation: ok
Effective config:
framework:
version: 1.2.0 (project.yaml, locked)
modes:
review_mode: lean (project.yaml)
automation: autonomous (LOCAL OVERRIDE — yaml has: collaborative)
rigor: full (project.yaml, locked)
workflow: full (derived from rigor: full, locked)
story_granularity: fine (derived from rigor: full, locked)
docs:
density: terse (project.yaml, locked)
qa:
level: full (derived from rigor: full, locked)
engine:
name: Godot (project.yaml, locked)
version: 4.7 (project.yaml, locked)
testing:
strict:
logic: false (LOCAL OVERRIDE — yaml has: true)
integration: true (project.yaml)
locked = cannot be overridden in project.local.yaml (project-wide setting).
It does NOT mean fixed: a derived value can still be set explicitly with
/settings <key>=<value>, and an explicit value wins over rigor.只要渲染出的任何一行带有 ,就在配置块后打印上述两行说明。
否则,用户会将 理解为“不可修改”,从而认定由 派生的选项
无法更改——这恰好与第 3 阶段查看单项时给出的信息相反(“显式值优先于 rigor”)。
两个视图不能对同一选项的可修改性留下相互矛盾的印象。
lockedlockedrigor上面的 行展示了优先级规则:显式的 值会继续优先于
原本由 级别派生的值,因此仍可表达“全面但紧凑”的要求。
docs.densityproject.yamlrigor如果存在 schema 错误,请在有效配置块之前按以下形式打印:
Schema validation: ERRORS
[project.yaml] modes.review_mode: 'chaotic' is not a valid value (expected: full|lean|solo)
[project.local.yaml] engine.name: 'Pygame' is not a valid value (expected: Godot|Unity|Unreal)Phase 3: View-one Mode
第 3 阶段:查看单项模式
(when single arg, no )
=If is in , print this BEFORE the value block — above,
not below. A caveat under a value reads as a footnote on a working setting:
<key>RESERVED_SETis RESERVED — nothing reads it. The value below is stored; it changes no behaviour today.<key>
Let be the argument. Perform four reads:
<key>- →
resolve_setting <key>, TAB,<value>(effective value + provenance)<source> - → yaml-only value
get_yaml_key project.yaml <key> - → local-only value (skip if file absent)
get_yaml_key project.local.yaml <key> - → 0 (overridable) or 1 (locked)
is_locally_overridable <key>
Determine the source from (same table as Phase 2 step 5)
and the Locally overridden status:
<source>- if the local-only value is non-empty
yes - otherwise
no
Print:
<key>
Effective value: <effective-value or "(not set)" if <source> is unset>
Source: <project.yaml | project.local.yaml | project.local.yaml (overrides project.yaml) | derived from rigor: <level> | default>
Locally overridden: <yes | no>
Whitelist: <"can be locally overridden" if is_locally_overridable returned 0, else "locked — project-wide">When both files set the key (the LOCAL OVERRIDE case), add two more
lines under Source:
project.yaml value: <yamlvalue>
project.local.yaml value: <localvalue>When is , add one line under Source so the user
knows the value is settable and how:
<source>rigor:<level> Set explicitly with: /settings <key>=<value> (an explicit value wins over rigor)When the effective value is empty (key not set anywhere), print just:
<key>
Effective value: (not set)
Locally overridden: no
Whitelist: <"can be locally overridden" | "locked — project-wide">(单个参数,不含 时)
=如果 位于 中,请在值块之前打印以下内容——
放在上方,而不是下方。位于值下方的警告看起来会像有效设置的脚注:
<key>RESERVED_SET已保留(RESERVED)——没有任何组件读取它。 下方值已存储; 目前不会改变任何行为。<key>
令 为传入的参数。执行四次读取:
<key>- →
resolve_setting <key>、制表符、<value>(有效值和来源)<source> - → 仅项目 YAML 中的值
get_yaml_key project.yaml <key> - → 仅本地 YAML 中的值(文件不存在时跳过)
get_yaml_key project.local.yaml <key> - →
is_locally_overridable <key>(可覆盖)或0(锁定)1
根据 确定来源(与第 2 阶段第 5 步的表格相同),并确定
本地覆盖状态:
<source>- 本地值为非空时为
yes - 否则为
no
打印:
<key>
Effective value: <effective-value or "(not set)" if <source> is unset>
Source: <project.yaml | project.local.yaml | project.local.yaml (overrides project.yaml) | derived from rigor: <level> | default>
Locally overridden: <yes | no>
Whitelist: <"can be locally overridden" if is_locally_overridable returned 0, else "locked — project-wide">当两个文件都设置了该键时,在 Source 下增加两行:
project.yaml value: <yamlvalue>
project.local.yaml value: <localvalue>当 为 时,在 Source 下增加一行,让用户知道该值
可以设置以及设置方式:
<source>rigor:<level> Set explicitly with: /settings <key>=<value> (an explicit value wins over rigor)当有效值为空(任何位置都未设置该键)时,仅打印:
<key>
Effective value: (not set)
Locally overridden: no
Whitelist: <"can be locally overridden" | "locked — project-wide">Phase 4: Set-yaml Mode
第 4 阶段:设置 YAML 模式
(when , no )
<key>=<value>--local- Schema validation: call . If it returns 1, the stderr line is shown to the user verbatim (
validate_enum_value <key> <value>) and the skill exits without writing. If it returns 0, the value is either valid or the key has no enum constraint — proceed.Invalid value '<value>' for '<key>'. Allowed: ...
1b. Known-key check: run, from the project root as in Phase 1,
and read its
row. If it says , proceed. If it says , nothing in CCGS reads
that key, so writing it changes nothing; it is most often a typo. Do not
write yet: say so, and ask via with the options
(only when the row ends ),
, . Continue only on an explicit choice; with
, start this phase again with that key. A skipped or
empty answer cancels.
bash .claude/scripts/config-set.sh <key> <value> --dry-runknownyesnoAskUserQuestionUse <nearest> insteadnearest: <key>Write <key> anywayCancelUse <nearest> instead-
Reserved warning: ifis in
<key>(Phase 1b), print BEFORE the approval prompt:RESERVED_SET"Note:is RESERVED — no skill or hook reads it, so setting it will not change any behaviour. Your value is stored either way."<key>Then continue to the approval gate as normal. Phase 5 carries the identical warning. Warning on one write path and not the other leaves a silent route to the same outcome, which is the whole failure this guards against. -
Shadow warning: read. If it returns a non-empty value, print BEFORE the approval prompt:
get_yaml_key project.local.yaml <key>"Note: this setting is currently locally overridden in(value:project.local.yaml). Writing to<localvalue>will not change your effective value."project.yaml -
Approval gate: use:
AskUserQuestion- Prompt:
Set `<key>=<value>` in `project.yaml`? - Options: /
[A] Yes, write[B] No, cancel
- Prompt:
-
Write using thetool. The edit strategy depends on what already exists in
Edit:project.yamlCase A — key exists: Read. Locate the lineproject.yamland the line immediately above it that introduces its parent block (e.g.<lastsegment>: <oldvalue>formodes:). Construct themodes.review_modewithEditthat includes the parent block line PLUS the leaf line, so the match is unique even ifold_stringappears elsewhere. Example for<lastsegment>: <oldvalue>:modes.review_mode=fullold_string: modes: review_mode: lean new_string: modes: review_mode: fullCase B — parent block exists, leaf doesn't: Find the last line of the parent block. Useto append the new leaf line at the correct indentation, using the last existing leaf as theEditanchor.old_stringCase C — parent block doesn't exist: Append a new top-level block at end-of-file (deterministic — always end-of-file, never between blocks). Usewith the last non-empty line of the file asEditand append the new block after it.old_stringCase D — file structure is unusual (commented-out keys with the same name, ambiguous nesting, malformed YAML): STOP and ask via:AskUserQuestion"Couldn't find a clean insertion point forin<key>. Show me what to do."project.yaml -
Confirm:
Set `<key>=<value>` in `project.yaml`.Whenis<key>, the write also moves six other knobs, so print what they resolve to now — re-read each withmodes.rigorrather than reciting the expansion table, since any of them may carry an explicit value that still wins:resolve_settingSet modes.rigor=full in project.yaml. It now supplies: modes.workflow: full (derived from rigor: full) docs.density: terse (project.yaml — explicit, unchanged) qa.level: full (derived from rigor: full) modes.story_granularity: fine (derived from rigor: full) modes.review_mode: full (derived from rigor: full) team.size: studio (derived from rigor: full)
(当参数为 ,且不含 时)
<key>=<value>--local- Schema 验证:调用 。如果 返回
validate_enum_value <key> <value>,则将 stderr 行原样显示给用户 (1),并且不写入任何内容就退出。 如果返回Invalid value '<value>' for '<key>'. Allowed: ...,则说明该值有效,或者该键没有枚举约束——继续执行。0
1b. 已知键检查:从项目根目录运行(与第 1 阶段相同):
,并读取其 行。
如果结果为 ,则继续。如果结果为 ,说明 CCGS 中没有任何内容读取该键,
因此写入它不会产生任何效果;这通常是拼写错误。暂时不要写入:说明情况,
并通过 询问,提供以下选项:
(仅当该行以 结尾时提供)、
、。只有在用户明确选择后才可继续;选择
时,使用该键重新开始本阶段。跳过或提供空回答均视为取消。
bash .claude/scripts/config-set.sh <key> <value> --dry-runknownyesnoAskUserQuestionUse <nearest> insteadnearest: <key>Write <key> anywayCancelUse <nearest> instead-
保留设置警告:如果位于
<key>中(第 1b 阶段), 请在审批提示之前打印:RESERVED_SET“注意:已保留(RESERVED)——没有 skill 或 hook 读取它, 因此设置它不会改变任何行为。无论如何都会存储你的值。”<key>然后照常继续执行审批关卡。第 5 阶段包含完全相同的警告。 如果只警告一条写入路径而不警告另一条,就会留下通向同一结果的静默路径, 而这正是此机制要防范的整个问题。 -
遮蔽警告:读取。如果 返回非空值,请在审批提示之前打印:
get_yaml_key project.local.yaml <key>“注意:此设置目前在中被本地覆盖(值:project.local.yaml)。 写入<localvalue>不会改变你的有效值。”project.yaml -
审批关卡:使用:
AskUserQuestion- 提示:
Set `<key>=<value>` in `project.yaml`? - 选项:/
[A] Yes, write[B] No, cancel
- 提示:
-
使用工具执行写入。具体编辑策略取决于
Edit中 已经存在的内容:project.yaml情况 A——键已存在:读取。找到project.yaml这一行,以及紧邻其上方、用于引入父级块的行(例如<lastsegment>: <oldvalue>对应的modes.review_mode)。构造modes:时,Edit必须同时包含父级块行和叶节点行, 以确保即使old_string在其他位置出现,匹配仍然唯一。<lastsegment>: <oldvalue>的示例:modes.review_mode=fullold_string: modes: review_mode: lean new_string: modes: review_mode: full情况 B——父级块存在,但叶节点不存在:找到父级块的最后一行。 使用,以现有最后一个叶节点作为Edit锚点,按正确缩进 追加新的叶节点行。old_string情况 C——父级块不存在:在文件末尾追加一个新的顶层块 (必须始终追加到文件末尾,绝不能插入两个块之间)。使用, 以文件中最后一个非空行为Edit,并在其后追加新块。old_string情况 D——文件结构异常(存在同名但已注释的键、嵌套关系不明确或 YAML 格式错误):停止操作,并通过询问:AskUserQuestion“无法在中为project.yaml找到清晰的插入点。请告诉我该怎么做。”<key> -
确认:
Set `<key>=<value>` in `project.yaml`.当为<key>时,此次写入还会影响另外六个选项, 因此请打印它们当前解析出的值——应重新读取每个选项,而不是照抄扩展表, 因为其中任何选项都可能具有仍然优先的显式值:modes.rigorSet modes.rigor=full in project.yaml. It now supplies: modes.workflow: full (derived from rigor: full) docs.density: terse (project.yaml — explicit, unchanged) qa.level: full (derived from rigor: full) modes.story_granularity: fine (derived from rigor: full) modes.review_mode: full (derived from rigor: full) team.size: studio (derived from rigor: full)
Phase 5: Set-local Mode
第 5 阶段:设置本地值模式
(when )
--local <key>=<value>-
Whitelist check: call.
is_locally_overridable <key>- If it returns 1 (locked), print one line:
<key> cannot be locally overridden — it's a project-wide setting. Use `/settings <key>=<value>` (no `--local`) to change it for the whole team. - Exit without writing.
- If it returns 1 (locked), print one line:
-
Schema validation: call. If it returns 1, show the stderr message verbatim and exit without writing.
validate_enum_value <key> <value>
2a. Known-key check: as in Phase 4 step 1b, with before
: if the row says , ask before writing, offering the key
when the row names one.
--local<key>knownnonearest:2b. Reserved warning: if is in (Phase 1b), print
BEFORE the approval prompt:
<key>RESERVED_SET"Note:is RESERVED — no skill or hook reads it, so setting it will not change any behaviour. Your value is stored either way."<key>
Identical to Phase 4 step 2, and deliberately so. Both write paths reach the
same file-of-record for a user's intent; warning on one only would leave
as the silent route.
--local-
Base check: ifdoesn't exist:
project.yaml"Cannot create—project.local.yamlis missing. Runproject.yamlto create one first." Exit. (Local overrides require a base, per spec.)/start -
Approval gate: use:
AskUserQuestion- Prompt:
Set `<key>=<value>` in `project.local.yaml` (your personal override, gitignored)? - Options: /
[A] Yes, write[B] No, cancel
- Prompt:
-
Write:
- If doesn't exist, use
project.local.yamlto create it with the new setting wrapped in its parent block(s). Minimal example forWrite:--local modes.automation=autonomousyaml# project.local.yaml — per-developer overrides (gitignored) modes: automation: autonomous - If it exists, use with the same Case A/B/C strategy from Phase 4 step 4.
Edit
- If
-
Confirm:
Set `<key>=<value>` in `project.local.yaml` (your override).
(当参数为 时)
--local <key>=<value>-
白名单检查:调用。
is_locally_overridable <key>- 如果返回 (已锁定),打印一行:
1“无法在本地覆盖——这是项目级设置。使用<key>(不带/settings <key>=<value>)为整个团队更改。” 不写入任何内容并退出。--local
- 如果返回
-
Schema 验证:调用。如果 返回
validate_enum_value <key> <value>,则将 stderr 消息原样显示,并且不写入任何内容就退出。1
2a. 已知键检查:与第 4 阶段第 1b 步相同,但 位于 之前:
如果 行的结果为 ,则先询问用户是否仍要写入,并在该行指定
键时提供相应选项。
--local<key>knownnonearest:2b. 保留设置警告:如果 位于 中(第 1b 阶段),
请在审批提示之前打印:
<key>RESERVED_SET“注意:已保留(RESERVED)——没有 skill 或 hook 读取它, 因此设置它不会改变任何行为。无论如何都会存储你的值。”<key>
这与第 4 阶段第 2 步完全相同,而且是有意如此。两条写入路径最终都会将
用户意图写入同一个正式配置记录;如果只警告其中一条,就会让
成为静默路径。
--local-
基础文件检查:如果不存在:
project.yaml“无法创建——缺少project.local.yaml。 请先运行project.yaml创建一个。” 然后退出。(按照规范,本地覆盖必须基于项目级配置。)/start -
审批关卡:使用:
AskUserQuestion- 提示:
Set `<key>=<value>` in `project.local.yaml` (your personal override, gitignored)? - 选项:/
[A] Yes, write[B] No, cancel
- 提示:
-
写入:
- 如果 不存在,使用
project.local.yaml创建它,并将新设置 包裹在相应的父级块中。为Write时的 最小示例:--local modes.automation=autonomousyaml# project.local.yaml — per-developer overrides (gitignored) modes: automation: autonomous - 如果该文件已存在,使用 ,并采用与第 4 阶段第 5 步相同的情况 A/B/C 策略。
Edit
- 如果
-
确认:
Set `<key>=<value>` in `project.local.yaml` (your override).
Phase 6: Usage
第 6 阶段:用法
When the argument doesn't match any of the four valid forms (or has
empty operands), print:
Usage:
/settings — view all effective config
/settings <key> — view a single setting
/settings <key>=<value> — change a setting (project.yaml)
/settings --local <key>=<value> — change a setting locally
(project.local.yaml, gitignored)
Examples:
/settings modes.review_mode
/settings modes.review_mode=full
/settings --local modes.automation=autonomous当参数不匹配四种有效形式之一(或操作数为空)时,打印:
Usage:
/settings — view all effective config
/settings <key> — view a single setting
/settings <key>=<value> — change a setting (project.yaml)
/settings --local <key>=<value> — change a setting locally
(project.local.yaml, gitignored)
Examples:
/settings modes.review_mode
/settings modes.review_mode=full
/settings --local modes.automation=autonomousNotes
说明
- All YAML writes go through (existing keys/blocks) or
Edit(new files). The skill does not depend onWriteor any external YAML library.yq - The whitelist is enforced in (
yaml-helper.shfunction). To extend it, edit theis_locally_overridableconstant — do not duplicate the list here._yaml_helper_locally_overridable - Derived values are not stored anywhere. ,
modes.workflow,docs.density,qa.level,modes.story_granularityandmodes.review_modehave no terminal default; when no file sets them their value comes from theteam.sizeexpansion inmodes.rigor(yaml-helper.sh). Report them via_yaml_helper_rigor_expansion— aresolve_settingread returns empty and would render them "(not set)" while every skill is in fact acting on a real value.get_yaml_key - The schema-validation enum constants are in (
yaml-helper.sh)._yaml_helper_enumsis the single-key validator for pending writes;validate_enum_valuevalidates whole files (used byvalidate_yaml_enum).session-start.sh - is gitignored. These overrides never propagate to teammates.
project.local.yaml - For which value to choose for a given game type or situation — and when to
suggest changing one — see (advisory presets
.claude/docs/settings-guidance.md- change triggers). says what each setting does; that doc says which to pick.
effects-map.md
- change triggers).
- 所有 YAML 写入都通过 (现有键或区块)或
Edit(新文件)完成。 此 skill 不依赖Write或任何外部 YAML 库。yq - 白名单在 的
yaml-helper.sh函数中执行。 如需扩展,请编辑is_locally_overridable常量——不要在此处重复该列表。_yaml_helper_locally_overridable - 派生值不会存储在任何位置。 、
modes.workflow、docs.density、qa.level、modes.story_granularity和modes.review_mode没有最终默认值;当没有文件设置它们时,其值来自team.size中的yaml-helper.sh扩展(modes.rigor)。请通过_yaml_helper_rigor_expansion报告它们——使用resolve_setting读取会返回空值, 从而将其显示为“(not set)”,但实际上每个 skill 都在使用真实值。get_yaml_key - Schema 验证的枚举常量位于 (
yaml-helper.sh)。_yaml_helper_enums是待写入内容的单键验证器;validate_enum_value用于验证整个文件(由validate_yaml_enum使用)。session-start.sh - 已被 gitignore。这些覆盖配置永远不会传播给团队成员。
project.local.yaml - 有关特定游戏类型或场景应选择哪个值,以及何时建议更改设置,请参阅
(建议预设和更改触发条件)。
.claude/docs/settings-guidance.md说明每个设置的作用;该文档则说明应选择哪个值。effects-map.md