mcpField
F
flag-targeting

flag-targeting

github.com/growthbook开发2540 次安装4 周前更新
代码仓库

关于 flag-targeting

用于为 GrowthBook 现有功能标志添加、编辑或移除定向规则的技能,面向管理用户分组发布策略的团队。它支持条件、已保存组和前置标志,并将改动保存在草稿中等待发布。

主要功能

  1. 01添加、编辑和移除规则
  2. 02支持强制值与百分比推出
  3. 03组合属性条件、已保存组和前置标志
  4. 04变更先进入草稿修订

适用场景

  1. 01向匹配属性的用户定向提供标志值
  2. 02逐步向一定比例用户推出功能
  3. 03按已保存组或其他标志设置规则
  4. 04调整现有规则的范围或条件

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/growthbook/skills --skill flag-targeting

安装后在 Claude Code 中输入/flag-targeting确认已加载。

详细介绍

flag-targeting

在现有的 GrowthBook 功能标记上添加、编辑或移除定向规则。支持 force(向匹配的用户提供指定值)和 rollout(向随机比例的用户提供某个值)规则类型,并全面支持条件、已保存分组和规则级前置条件。

所有更改都要经过草稿修订,并且需要发布。发布时请使用 flag-publish — 它可以处理需要审批和合并冲突等失败情况。

所有 API 调用都通过捆绑的辅助工具执行:${CLAUDE_PLUGIN_ROOT}/scripts/gb-call。需要在环境变量中设置 GB_API_KEY,或通过 /growthbook:gb-setup 将其写入 ~/.config/growthbook/.env。

必需输入

开始前收集:

  • Flag ID — kebab-case 键。使用 flag-search 根据描述查找。
  • 操作 — add、edit 或 remove。根据用户的请求推断;修改前先确认。

各操作所需输入

add
  • 规则类型 — force(指定用户)或 rollout(百分比)。根据措辞推断:“X% 的用户” → rollout;“针对符合 Y 条件的用户” → force。
  • 值 — 匹配时规则提供的值。必须与标记的 valueType 相符,并序列化为字符串。
  • 范围 — allEnvironments: true 或 environments: [<env-ids>]。如果未指定,请询问。
  • 条件(可选)— 已保存分组、属性条件,或另一个标记的前置条件(参见下方的条件决策树)。
  • 对于 rollout 规则 — coverage(0–1)和 hashAttribute(当 coverage < 1 时必需)。
  • 描述(可选,但建议提供)。
edit
  • 规则 ID — 通过交互方式显示带编号的列表来确定(步骤 3b)。用户按编号选择。
  • 补丁字段 — 仅包含用户希望更改的字段。
remove
  • 规则 ID — 以与 edit 相同的方式确定。

工作流

- [ ] 1. Fetch flag and current state
- [ ] 2. Confirm the action (add / edit / remove)
- [ ] 3a. Add path
- [ ] 3b. Edit path
- [ ] 3c. Remove path
- [ ] 4. Hand off to flag-publish
1. 获取标记及当前状态
gb-call GET /api/v2/features/<flag-id>

记录:valueType、environmentSettings 键(可用环境 ID)以及 rules 数组(包含完整列表及 ID、类型、范围和启用状态)。如果返回 404,则停止并提示:“没有 ID 为 <flag-id> 的标记。”建议使用 flag-search。

2. 确认操作

如果用户的请求不明确,请在修改前询问。

3a. 添加流程

新规则会追加到 rules 数组末尾。规则按从上到下的顺序进行评估;第一个匹配项生效。如果标记已有规则,请说明:

“该标记已有 <N> 条规则;这条新规则将最后评估。如果它需要优先于现有规则,请在添加后通过 flag-rules 调整顺序。”

预先验证 value 是否与 valueType 相符 — API 在写入时不会检查是否匹配:

  • boolean → 必须为 "true" 或 "false"
  • number → 必须能解析为数字
  • json → 必须是有效的 JSON
  • string → 任意非空字符串

确定范围。 根据 environmentSettings 确认环境 ID。设置 allEnvironments: true 或 environments: [...] 其中之一 — 不可同时设置。

获取可用属性 — 在询问用户描述任何条件之前执行此操作。如果标记属于某个项目,将其作为 projectId 传入,以仅获取相关属性(组织范围 + 项目范围);对于组织范围的标记,则省略该参数:

# Flag has a project:
gb-call GET '/api/v1/attributes?projectId=<flag-project-id>'

# Flag is org-wide (no project):
gb-call GET /api/v1/attributes

按类型对返回的列表进行分组并展示给用户,同时指出重要的元数据:

Available targeting attributes for this flag:
  id            (string, hashAttribute)
  country       (string, format: isoCountryCode)
  app_version   (string, format: version)
  plan          (enum: free|pro|enterprise)
  is_employee   (boolean)

如果没有属性(或没有适用范围内的属性),请提示:“该项目尚未注册定向属性。请先在 Settings → Attributes 下添加属性,再进行定向。”

为 rollout 规则确定 hashAttribute(当 coverage < 1 时必需): 在筛选后的属性列表中,优先选择 hashAttribute: true 的条目。“按用户”默认使用 id;“按公司”则选择公司范围的属性。

一条规则包含三个可以自由组合的独立定向属性。确定适用的属性,然后在提交前构建所有相关字段。

condition — 基于属性的定向(MongoDB 风格的 JSON 字符串) 根据传入 SDK 的属性定位用户。从上方获取的筛选列表中选择属性。如果用户的描述无法明确对应到可用属性,请展示列表并让用户选择。拒绝任何不在筛选列表中的属性名称——未注册的属性在 SDK 求值时会被静默忽略。

将条件对象序列化为 JSON 字符串并放入载荷中。

类别运算符含义
相等$eq、$ne(或直接使用键/值表示 eq)=、≠
比较$lt、$lte、$gt、$gte<、≤、>、≥
语义化版本$veq、$vne、$vlt、$vlte、$vgt、$vgte感知版本号的比较——"1.0.10" > "1.0.9"。用于 format: version 属性。
集合成员关系$in、$nin属于其中任一项、不属于其中任何项(区分大小写)
集合成员关系(不区分大小写)$ini、$nini属于其中任一项/不属于其中任何项——忽略大小写
字符串包含$includes、$notIncludes字符串或数组包含/不包含指定值
正则表达式$regex、$notRegex匹配/不匹配模式(区分大小写)
正则表达式(不区分大小写)$regexi、$notRegexi同上,但忽略大小写
存在性$exists、$notExists不是 NULL / 是 NULL
空值$empty、$notEmpty字符串或数组为空/不为空
布尔值$true、$false属性为真值/假值
类型$typeJS 类型等于指定值(例如 "string"、"number")
数组$elemMatch、$all、$alli、$size元素符合条件;包含所有值($alli 不区分大小写);长度比较
已保存分组(原始)$inGroup、$notInGroup按 ID 属于/不属于已保存分组——优先使用 savedGroups 规则字段
逻辑$or、$and、$nor、$not顶层键之间为 AND 关系;使用这些运算符表示 OR / 取反

关键规则:

  • 多个顶层键之间为 AND 关系:{"country": "US", "plan": "pro"} 要求两者都匹配。
  • 默认情况下,字符串比较区分大小写——需要时使用 $ini/$regexi 变体。
  • 条件由客户端 SDK 进行求值——属性值不会传到 GrowthBook 服务器。
  • 只能使用此表中的运算符。未列出的 MongoDB 运算符(例如 $where、$expr)会被静默忽略,永远不会匹配。

示例:

{"country": "US"}
{"country": {"$ini": ["us", "ca", "gb"]}}
{"plan": {"$ne": "free"}}
{"appVersion": {"$vgte": "3.0.0"}}
{"age": {"$gte": 18, "$lt": 65}}
{"email": {"$regexi": "@acme\\.com$"}}
{"$or": [{"country": "US"}, {"beta": true}]}
{"tags": {"$includes": "power-user"}}
{"company": {"$exists": true}, "plan": {"$in": ["pro", "enterprise"]}}

savedGroups — 已保存分组定位(单独的规则字段)

定位属于预定义已保存分组的用户。获取可用分组:

gb-call GET /api/v1/saved-groups

将该字段构建为分组引用数组:

"savedGroups": [
  { "ids": ["<sg-id>"], "match": "all" }
]
  • ids — 要引用的已保存分组 ID 数组
  • match: "all" — 用户必须属于列出的所有分组;"any" — 用户必须属于至少一个分组

对于在标志之外管理的命名人群(“Beta 测试者”“内部用户”“企业账户”),请使用已保存分组。相比在 condition 字符串中手动编写 $inGroup,应优先使用此方式。


prerequisites — 规则级前置条件定位(单独的规则字段)

根据另一个功能标志的求值结果,决定是否启用此规则。如果前置条件对某位用户不成立,则跳过此规则并按顺序评估下一条规则——这与会跳过整个标志的功能级前置条件不同。

"prerequisites": [
  { "id": "<flag-id>", "condition": "{\"value\": true}" }
]

condition 字符串针对 { "value": <前置条件标志的求值结果> } 进行求值。value 是唯一有效的顶层键。

以下两种条件涵盖了 99% 的情况:

目标条件
布尔标志已开启{"value": true}
布尔标志已关闭{"value": false}
非布尔标志处于生效状态(返回任意值){"value": {"$exists": true}}
非布尔标志未处于生效状态{"value": {"$exists": false}}

对于更具体的情况(例如字符串标志等于某个特定变体),可使用上方 condition 部分中的完整运算符表——但在编写复杂的前置条件前,请先让用户确认。


组合使用这三项: 这三个属性采用 AND 逻辑组合。只有当用户属于已保存的用户组、属性条件匹配且所有前置标志均通过时,设置了全部三个属性的规则才会触发:

{
  "condition": "{\"country\": \"US\"}",
  "savedGroups": [{ "ids": ["sg_beta"], "match": "all" }],
  "prerequisites": [{ "id": "new-checkout", "condition": "{\"value\": true}" }]
}

模糊情形(“VIP 客户”“企业用户”)——询问:这是 GrowthBook 中的命名用户组(已保存的用户组)、用户记录上的属性(条件),还是两者都有?

用户说使用的字段
“为我们的 Beta 测试用户启用”savedGroups
“美国的用户”对 country 属性使用 condition
“使用 5.2 或更高版本的 iOS 用户”condition:{"platform": "ios", "appVersion": {"$vgte": "5.2"}}
“仅当 new-checkout 标志开启时”prerequisites
“企业用户”询问——是已保存的用户组,还是 {"plan": "enterprise"} 条件?

构建并 POST 该负载:

{
  "rule": {
    "type": "force",
    "value": "<string>",
    "description": "<optional>",
    "enabled": true,
    "allEnvironments": false,
    "environments": ["production"],
    "condition": "<optional JSON string>",
    "savedGroups": [{ "ids": ["<sg-id>"], "match": "all" }],
    "prerequisites": [{ "id": "<flag-id>", "condition": "{\"value\": true}" }]
  }
}

对于渐进发布:将 type 替换为 "rollout",并添加 coverage 和 hashAttribute。省略空数组和空字符串。

echo '<payload>' | gb-call POST /api/v2/features/<flag-id>/revisions/new/rules -

记录 revision.version。

3b. 编辑路径

将规则显示为编号列表:

Rules on `<flag-id>`:
  1. [force]    all envs     value="true"    "Beta testers" (saved group)
  2. [rollout]  production   10%             hash=id
  3. [force]    staging      value="false"   "Kill switch"

用户按编号选择。显示当前值,并询问要更改哪些字段。

**空补丁保护:**如果拟议更改与当前值完全相同,则停止操作——“没有要应用的更改”。无操作草稿会消耗速率限制额度,并可能通过 resetReviewOnChange 使先前授予的审批失效。

编辑时的规则类型行为:

  • **显式更改 type 会被服务器拒绝。**若要将强制规则转换为实验引用规则:先移除,再重新添加(3c,然后执行 3a 或 flag-experiment)。
  • **force ↔ rollout 会根据有效覆盖率自动切换。**将 coverage: 0.25 补丁应用于强制规则会静默地将其转换为渐进发布(还需要 hashAttribute)。在摘要中说明类型转换。

实验引用规则的编辑规则:

  • 服务器会拒绝的补丁:value、coverage、controlValue。尽早停止并说明原因。
  • 需要警告并确认的补丁:experimentId、variations。API 允许修改,但会导致标志与实验悄然偏离。需要明确确认:“直接更改 experimentId/variations 可能导致标志规则与实验偏离。实验是唯一事实来源。确定要更改吗?”
  • 可以安全编辑:enabled、condition、savedGroups、prerequisites、作用范围、description。

**作用范围细节:**更改作用范围时,始终同时发送 allEnvironments 和 environments。只发送 environments 而不发送 allEnvironments,会导致服务器推断 allEnvironments: false,从而静默缩小作用范围。

echo '<patch>' | gb-call PUT /api/v2/features/<flag-id>/revisions/new/rules/<rule-id> -

记录 revision.version。

3c. 移除路径

显示编号列表。确认:

“要从 <flag-id> 移除规则 <N>(<type>、<scope>、<summary>)吗?此操作会生成草稿,只有发布后才会生效。”

gb-call DELETE /api/v2/features/<flag-id>/revisions/new/rules/<rule-id>

移除实验引用规则时:“移除这条规则不会影响关联的实验。”

记录 revision.version。

4. 移交给 flag-publish

进行任何修改后,询问:“现在发布此更改,还是将其保留为草稿?”

移交给 flag-publish。它会处理:

  • 需要审批(400)——提供评审流程、组织级绕过或按令牌绕过选项
  • 合并冲突(409)——显示冲突字段,收集覆盖/丢弃决定,然后变基

Guardrails

  • 草稿版本串联。 如果本次会话中之前的写入技能已在上下文中提供版本号,请明确使用该版本号(例如 .../revisions/42/rules),而不是 new。这样可确保串联使用多个技能时,所有更改都在同一草稿中。若从头开始,则使用 new——它会通过 resolveOrCreateRevision 自动创建或复用最近更新的未关闭草稿。
  • 规则 ID 是 UUID(fr_...),不是位置编号。 始终从 rules 数组中解析,绝不要猜测。
  • force 与 rollout 在服务端大多只是表面区别。 coverage < 1 的 force 规则实际上就是 rollout。默认使用 force,除非用户提到“百分比”或指定了 coverage;服务端会自动转换。
  • coverage < 1 时必须提供 hashAttribute。 发送 POST 请求前先验证。
  • 作用范围:allEnvironments: true 和 environments: [...] 必须且只能设置其中一项。 绝不能同时设置。
  • 询问条件前,始终先获取属性。 如果该标记的作用范围限定在项目,请使用 ?projectId=<id>,以便服务端只返回相关属性。提前展示属性列表。用户提供的属性名称必须先确认在返回列表中;未经注册的属性在 SDK 求值时会静默地始终不匹配。
  • 条件是 JSON 字符串。 验证其是否可解析。优先使用已保存的分组,而不是手写条件——它们可重复使用且便于管理。
  • valueType 不匹配可能造成严重问题。 v2 规则添加处理程序在写入时不会验证。务必先在客户端进行验证。
  • 拒绝空补丁。 无操作的版本更新会消耗速率限制额度,还可能重置审核批准。
  • 新规则会追加到底部。 按顺序匹配,命中第一条后即停止。提交前说明评估顺序方面的注意事项。
  • 禁止自我批准。 执行 request-review 后不要尝试执行 submit-review。
  • **环境开关由 flag-toggle 处理,**而不是此技能。此技能不会更改环境级别的启用/禁用状态。

使用的端点

  • GET /api/v2/features/:id — 获取标记状态、当前规则、环境列表和 valueType
  • GET /api/v1/attributes — 获取属性;如果该标记的作用范围限定在项目,请传入 ?projectId=<id>;构建任何条件前先展示属性列表;rollout 时选择 hashAttribute
  • GET /api/v1/saved-groups — 解析用于定向的已保存分组
  • POST /api/v2/features/:id/revisions/new/rules — 添加规则
  • PUT /api/v2/features/:id/revisions/new/rules/:ruleId — 编辑规则
  • DELETE /api/v2/features/:id/revisions/new/rules/:ruleId — 移除规则

移交

  • flag-toggle — 用于环境级别的启用/禁用(紧急开关)
  • flag-rules — 用于重新排列规则或将其路由到其他规则类型
  • flag-experiment — 用于添加 experiment-ref 或内联实验规则
  • flag-ramp — 用于逐步提高 rollout 规则的覆盖率
  • flag-monitoring — 用于为 rollout 添加防护指标监控
  • flag-prerequisites — 用于设置功能级前置条件门控
  • flag-search — 用于根据描述解析标记 ID
  • flag-publish — 用于发布草稿(处理审批和合并冲突)

评论

支持 Markdown