mcpField
A
argent-lens

argent-lens

github.com/software-mansion设计与 UI3.1k23.2k 次安装今天更新
代码仓库

关于 argent-lens

argent-lens 是用于应用界面迭代的设计评审技能。它将已实现方案的截图与模拟器画面关联展示,供评审者选择并添加评论。

主要功能

  1. 01提交已实现的设计方案
  2. 02在模拟器画面旁展示截图
  3. 03将提案锚定到界面元素
  4. 04收集选择结果和评论

适用场景

  1. 01比较不同的搜索框设计
  2. 02评审主要操作按钮方案
  3. 03收集针对界面元素的反馈

安装

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

$npx skills add https://github.com/software-mansion/argent --skill argent-lens

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

详细介绍

前提条件:功能开关。 此工作流受 argent-lens 标志控制(默认关闭)。使用前运行一次 argent enable argent-lens。如果 propose_variant / await_user_selection 返回未找到,则表示标志已关闭;启用后重试。

1. 概述

你需要实现多个候选设计,捕获每个设计在设备上的运行效果,然后通过 propose_variant 提交。每个提议的元素都会以浮动卡片的形式显示在 Argent Lens 窗口中的实时模拟器画面旁边(这是一个会自动打开的原生窗口),并通过细线连接到实际元素。用户可以逐个元素进行选择,也可以选择将自由格式的评论固定到元素上,然后按 Complete selection。await_user_selection 是唯一的阻塞调用,会返回用户的决定。

黄金法则:一个变体 = 一张真实且_不同_的截图。 只有当其 previewImage 显示设备上实际呈现的变体,且截图是在应用该特定变体后捕获的,提议才有用。切勿提议尚未构建并在屏幕上查看过的变体,也切勿让两个变体指向同一个文件路径:如果两张截图最终字节完全相同,说明你实际上什么都没改,Argent Lens 就只会显示相同的缩略图。依次对每个元素的每个变体重复执行:规划 → 构建 → 导航 → 截图 → 提议,然后等待一次。

2. 工具

工具是否阻塞?用途
propose_variant否为一个元素提交一个变体。每个变体调用一次。继续操作。
await_user_selection是提交所有变体后调用一次。等待用户完成选择。

propose_variant 参数:element(人类可读的名称)、可选的 match({ by: "text"|"label"|"identifier"|"role", value })、可选的 udid(你捕获这些变体时使用的设备 ID),以及 variant({ name, summary, code?, filePath?, previewImage?, frame? })。使用相同的 element 重复调用会在该元素下累积变体;不同的 element 值会创建不同的卡片。

务必传入 udid(即你截图并描述所用的同一个模拟器/模拟机 ID)。预览窗口随后会直接播放_该_设备的画面:用户无需选择模拟器。在一轮中的首次 propose_variant 调用时设置此参数;后续调用可以省略(最后一次设置的值会生效)。

3. 工作流

先解析模拟器/模拟机(argent-ios-simulator-setup / argent-android-emulator-setup),如果使用 React Native,还要使用 argent-react-native-app-workflow 来运行应用并重新加载 bundle。Argent 会在用户屏幕上自动打开的原生预览窗口中显示已提交的变体;你无需自行打开或显示任何内容。只需提交变体并调用 await_user_selection,窗口就会自动出现。

步骤 0:规划变体

在修改代码之前,明确决定要重新设计的元素,以及每个元素对应的不同变体。将它们写下来(例如:“搜索框:填充式 / 描边式 / 胶囊式”,“主要 CTA:纯色 / 渐变”)。每个变体都必须是单一、独立的更改,可以单独应用、截图并还原。模糊或相互重叠的变体无法形成有用的提议。

步骤 1:获取精确的匹配条件

对于每个元素,在它所在的屏幕上运行 describe(RN 项目则运行 debugger-component-tree),读取其确切的 label / identifier / role。将其作为 match 传入,以便浮动卡片的连接线锚定到正确的元素:

  • 稳定的 testID / accessibilityIdentifier → { by: "identifier", value: "search-input" }(最可靠)
  • 确切的 a11y 标签 → { by: "label", value: "Search" }
  • 其他情况 → { by: "text", value: "Search" }(模糊包含;省略 match 时的默认值)

省略 match 时,默认值为 { by: "text", value: element },仅当元素的可见文本唯一时才适用。

步骤 2:针对每个变体:构建 → 导航 → 截图 → 提交

遍历每个元素的所有变体:

  1. 构建变体。 在代码中实现这个变体。
  2. 在设备上应用。 重新加载 RN bundle(debugger-reload-metro),或按需重新构建,以便运行中的应用显示这个变体。
  3. 导航到对应位置。 驱动应用(argent-device-interact)进入可见该元素的屏幕:只有元素确实显示在屏幕上时,截图才有意义。
  4. 截图。 调用 screenshot,并将返回的文件路径直接设为 variant.previewImage。切勿手动裁剪、调整大小、重新编码或将截图复制到其他文件夹(例如,用 crop.py 将图片放到 /tmp/variants/):预览窗口会自行裁剪,再次裁剪会导致重复裁剪,还会把图片写入服务端无法提供的路径(“No preview”)。截取整个屏幕:预览窗口会在步骤 5 中使用 variant.frame 为你裁剪。返回的路径必须指向一个新文件;如果怀疑设备卡住或变体未生效(与上一次截图相比看不到明显变化),在提交前使用上一次的路径进行比较(shasum -a 256):截图字节完全相同,意味着变体尚未显示在屏幕上。先解决问题,再提交。
  5. 提交。 调用 propose_variant,传入 element、match、udid(截图所用的设备),并将该截图路径设为 variant.previewImage。该工具会自动捕获裁剪框:它会在提交时描述设备并匹配元素,因此只要调用 propose_variant 时变体仍显示在屏幕上,每个缩略图就会根据元素当前的布局自行裁剪。你也可以传入 variant.frame(通过对此变体运行 describe 获取的匹配节点归一化 {x, y, width, height},范围为 0..1)来覆盖自动捕获;当提交时无法让元素保持在屏幕上时,这会很有用。适当时添加 summary(说明更改内容及原因)和 code / filePath。
  6. 还原。 在构建下一个变体前撤销当前变体的更改:屏幕上一次只能显示一个变体。继续操作;propose_variant 不会阻塞。

previewImage 接受本地截图路径(从 OS 临时目录 / 当前工作目录提供服务)、http(s) URL 或 data: URI。强烈建议使用真实运行变体的本地截图。

步骤 3:等待用户决策(一次)

为每个元素暂存完所有变体后,恰好调用一次 await_user_selection。它会返回:

  • { status: "completed", selections: [{ element, chosenVariant, comment? }], unselected, annotations: [{ target, match, comment }], globalComment }:为每个元素应用 chosenVariant;跳过 unselected 中的元素。将每条 annotations(用户固定在元素上的检查器评论)和 globalComment 视为更改请求。
  • { status: "pending", proposedElements }:已超过 timeoutSeconds,但这不是错误。提议仍然有效;再次调用 await_user_selection。
  • { status: "no_proposals" }:在调用任何 propose_variant 之前就调用了它。请先暂存变体。
步骤 4:应用结果

为每个选定元素实现所选变体,处理每条批注/评论,并报告已应用和跳过的内容。如果用户评论了某个变体但跳过了它,该评论仍然重要;请据此采取行动。

4. 规则

  • 每个元素至少提供两个变体。 选择需要备选方案:你提出的每个元素都必须有 ≥2 个不同的变体(对该元素至少调用两次 propose_variant)。如果某个元素只有一种外观,要么制作一个真正不同的备选方案,要么完全不要提出该元素;单个变体不构成选择。
  • 先构建,再提出。 每个 previewImage 都必须是该变体在设备上实际运行时的截图。不得使用模型图,不得猜测,也不得提出尚未构建的想法。
  • 每个变体使用不同的截图。 两个变体共用同一个 previewImage 路径(或使用两个内容完全相同的路径)都会违背 Argent Lens 的初衷。如果无法生成明显不同的截图(例如应用为只读、无障碍功能不可用导致无法导航、软件包无法热重载),请停止并告知用户,不要提交重复内容。
  • 只进行一次阻塞调用。 propose_variant 不会阻塞;可以自由暂存。只有 await_user_selection 会等待,而且必须只调用一次,并且是最后一次。
  • 准确锚定。 从 describe 中提取匹配器;错误的 match 会使卡片指向错误元素或无法锚定。
  • 一次只让一个变体显示在屏幕上。 应用 → 截图 → 还原,再处理下一个变体,以免截图内容相互混杂。
  • pending 属于正常情况。 遇到 pending 时,只需再次等待;提案会在超时后保留。
  • 重新提出会开启新一轮。 在某一轮已被处理后调用 propose_variant,会开启第 N+1 轮并清除上一轮的元素;每一轮都要暂存完整的一组元素。

5. 示例

describe { udid }                                  # read exact label/identifier
propose_variant { element: "Search field",
  match: { by: "identifier", value: "search-input" },
  variant: { name: "Outlined", summary: "1pt border, transparent fill",
             previewImage: "/var/folders/.../search-outlined.png" } }
propose_variant { element: "Search field",
  match: { by: "identifier", value: "search-input" },
  variant: { name: "Pill", summary: "Fully rounded, filled grey",
             previewImage: "/var/folders/.../search-pill.png" } }
propose_variant { element: "Primary CTA",
  match: { by: "label", value: "Get started" },
  variant: { name: "Gradient", summary: "Accent gradient fill",
             previewImage: "/var/folders/.../cta-gradient.png" } }
await_user_selection {}                             # ONE blocking call → human picks
→ { status: "completed",
    selections: [ { element: "Search field", chosenVariant: { name: "Pill" } },
                  { element: "Primary CTA",  chosenVariant: { name: "Gradient" } } ],
    annotations: [ { target: "Tab bar", comment: "raise contrast" } ] }
# → apply Pill + Gradient, and raise tab-bar contrast.

评论

支持 Markdown