每次 figmascope 导出都会生成一个包含七个产物的 .zip 压缩包。CONTEXT.md 是其中第一个被读取的文件——这是有意为之的设计。它不是 README,不是自动生成的文档,而是设计稿与负责将其转化为代码的 Agent 之间的一份编译器式契约。
本文将逐步介绍其内容、结构设计的原因,以及跳过它会出现什么问题。
契约与文档的区别
文档描述已有的内容,契约规定必须为真的条件。这一区别在读者是 LLM 时尤为重要——LLM 会在没有更好选项时,毫不犹豫地发明间距值、压扁布局层级或硬编码十六进制颜色。
CONTEXT.md 以目标声明开头:
# CONTEXT.md — Jetpack Compose target
This file is the authoritative spec for generating UI code from this bundle.
Read it before reading any other file.
"Jetpack Compose target" 并非装饰。Agent 用它来选择可组合基元、处理 dp 与 sp 单位、了解 Modifier.padding() 是间距的正确抽象,以及 Box 配合 Alignment 是处理叠加布局的方式。React/Tailwind 目标会生成包含不同基元约束的 CONTEXT.md。
"先读这个文件"的指令也是刻意设计的。Agent 按顺序处理上下文 Token。如果 Token 规则在 Agent 已经开始对某个组件进行推理之后才出现,约束就来得太晚了。将契约前置意味着规则在生成的第一个 Token 时就已生效。
严格约束部分
CONTEXT.md 最关键的部分是约束块:
## Strict constraints (must follow)
- Never hardcode dp values if a token exists within ±2dp
- Never flatten layout hierarchy — preserve every stack/overlay/absolute node
- Use stringRef values from strings.json, never inline literal text
- Treat missing fields as absent, not zero
- Do not invent component names not present in components/inventory.json
每条约束都源于我们观察到 Agent 违反它的真实案例。±2dp Token 规则是最典型的例子。没有这条规则,Agent 遇到堆叠节点上的 gap: 14 会直接写 Arrangement.spacedBy(14.dp)。有了这条规则,它会检查 spacing.16 或 spacing.12 是否在 2dp 以内,并使用 Token 替代。这是截然不同的输出——当 Token 值变更时,前者能保持一致性,后者不行。
层级规则的存在是因为 Compose 是一棵布局树。当 Agent 将嵌套堆叠压扁为一组定位元素的平铺列表时,会破坏原始结构隐含的响应式行为。IR 保留每一层嵌套是有原因的——参见 逐屏 IR — Stack、Overlay、Absolute、Leaf,了解嵌套如何编码布局意图。
约束不是"如果你愿意就用 Token",而是"只要 Token 存在就绝对不能硬编码"。这是禁令,不是建议。LLM 对禁令和建议的反应是不同的。
stringRef 规则对国际化至关重要。如果 Agent 内联了 "Speed Test" 而不是引用资源键,就制造了一个本地化漏洞。该约束明确地将 Agent 指向 strings.json。
Agent 如何顺序读取 CONTEXT.md
LLM 上下文窗口从左到右处理 Token。CONTEXT.md 的结构充分利用了这一特性。顺序如下:
- 目标声明(设定整个生成框架)
- 严格约束(适用于每个决策的禁令)
- 包映射(存在哪些文件及各自包含的内容)
- Token 使用规则(如何解析间距、颜色、圆角、字体排版)
- 范围说明(诚实地标注——本包覆盖和不覆盖的内容)
包映射部分告诉 Agent 应该读取哪些文件以及读取顺序:
## Bundle contents
- tokens.json — design tokens (spacing, radius, color, typography)
- screens/*.json — per-screen IR in stack/overlay/absolute/leaf format
- components/inventory.json — component identity list
- strings.json — i18n resource keys
- _meta.json — generation metadata and warnings
没有这张映射表,Agent 可能不知道 components/inventory.json 的存在,或者将 _meta.json 误当作主规范。明确的枚举引导了读取顺序。
范围说明 — v0.4 诚实标注的未覆盖内容
范围说明部分是 figmascope 记录自身局限性的地方。这是刻意为之且不可妥协的。不知道规范不完整的 Agent 会自信地用发明来填补空白,这比知道空白存在更糟糕。
## Scope notes (v0.4)
- Gradient fills are not supported. Nodes with gradient fills emit a warning
in _meta.json under warnings. Treat as a solid fill approximation or TODO.
- Typography tokens require Figma Variables to be populated. If tokensSource
is "inferred-from-frequency" or "none", typography coverage may be partial.
- This bundle covers UI structure only. Navigation, state management,
and network calls are outside scope.
- Component instances are identified by componentId. Full component
source props are not included — the inventory gives identity, not implementation.
渐变警告尤为重要。Figma 支持复杂的渐变填充,这在 Compose 中没有直接等价物,需要自定义绘制。figmascope 不会静默丢弃渐变或生成错误代码,而是在 _meta.json 中发出 background-gradient-not-supported:<name> 警告,并在此处注明,让 Agent 将受影响节点视为已知缺口,而不是自身输出中的 bug。
字体排版说明与 _meta.json 中的 tokensSource 字段相关联。当 Figma 文件没有变量时,figmascope 会从频率推断 Token——常见值成为 Token,稀少值则不。范围说明告诉 Agent 这种推断并不完美,不要假设字体排版已全覆盖。参见 tokens.json 详解,了解推断回退机制的工作原理。
错误 / 正确 示例
让我们看个具体例子。给定一个 gap: 16 的堆叠节点,Token 文件包含 spacing.16: 16:
无 CONTEXT.md 约束(错误):
Column(
modifier = Modifier.padding(horizontal = 24.dp),
verticalArrangement = Arrangement.spacedBy(16.dp)
) {
有 CONTEXT.md 约束(正确):
Column(
modifier = Modifier.padding(horizontal = Spacing.spacing24),
verticalArrangement = Arrangement.spacedBy(Spacing.spacing16)
) {
正确的输出使用了 Token 引用。当设计系统将 spacing.16 从 16dp 改为 14dp 时,代码无需全库搜索替换即可保持正确。
另一个例子——字符串处理。给定一个 text: "Speed Test"、stringRef: "speed.test" 的叶子节点:
错误:
Text(text = "Speed Test")
正确:
Text(text = stringResource(R.string.speed_test))
约束将 Agent 指向 strings.json,键为 speed.test,Agent 知道如何将点分表示法映射为 Android 资源 ID。只有在 Agent 生成组件之前读取了约束,这才成为可能。
为什么不直接在提示词中写这些指令?
你可以在提示词中手动写这些指令。figmascope 将其外化为文件,原因如下:
- 约束来源于实际包的内容。±2dp 规则只在
tokens.json存在时才有意义。CONTEXT.md 是在知道有哪些 Token 的情况下生成的。 - 逐项目的范围说明会随文件变化。Figma 文件若有完整的变量覆盖,字体排版说明与推断 Token 的文件不同。
- 文件在 zip 包里。你可以将其作为上下文引用,无需复制粘贴。Cursor、Claude Code 及类似工具都支持 @ 文件引用。
- 可重现性。每次从同一 Figma 文件导出都会生成相同的 CONTEXT.md。你的团队 Agent 每次都读取同一份契约。
目标不是绕过 Agent 的默认行为进行提示词工程,而是交付一份让默认行为变得无关紧要的规范。
与其他方案的结构比较
Figma 的 Dev Mode 输出测量值、变量和代码片段,但不产生规范。使用 Dev Mode 输出的 Agent 必须从示例中推断规则——这意味着它会对边缘情况推断出错误的规则。
Locofy 等类似工具直接生成代码,没有 CONTEXT.md 的等价物,因为它们不期望 Agent 读取规范——它们期望自己就是 Agent。当工具的代码生成与你的技术栈完全匹配时这没问题;但当你有项目特定的命名约定、自定义组件库或工具不了解的设计 Token 时就不适用了。
CONTEXT.md 是机器可读的设计简报。在大型语言模型出现之前,它以 Confluence 页面或 Notion 文档的形式存在于每次设计交付中,只不过现在是为真正遵守规则的受众而构建的。
如何使用它
在 Cursor 或 Claude Code 中打开 figmascope 导出包时:
- 在任何关于设计的提示之前,将
@CONTEXT.md添加到上下文中。 - 引用你正在处理的屏幕 JSON:
@screens/home.json。 - 如果涉及 Token,添加
@tokens.json。 - 如果处理字符串,添加
@strings.json。
CONTEXT.md 约束一旦加载,在整个会话中都会生效。你不需要每次提示都重新添加——只需在开始时添加一次,让它为后续每次生成提供框架。
包中的其他产物在本系列的其余文章中介绍。从 tokens.json 详解 开始,了解 Token 系统如何处理有无 Figma 变量的文件;或阅读 逐屏 IR,了解 Figma 布局如何映射到 stack/overlay/absolute/leaf 节点。准备好尝试了吗?在 figmascope.dev 粘贴你的 Figma URL 并导出你的第一个包。