# FET

[中文](https://unpkg.com/@nick848/fet/README.md) | [English](https://unpkg.com/@nick848/fet/README_en.md)

> npm 包页只展示 `README.md`，站内 `./README_en.md` 等相对链接会 404。请用上方 **unpkg** 链接打开同 npm 包内的另一份文档；源码仓库见 [Gitee](https://gitee.com/agent-team/fet)。

FET 是一个围绕 OpenSpec 构建的前端开发工作流编排 CLI。它不会直接生成业务代码，而是代理 OpenSpec 命令、维护本地工作流状态、生成可审计的项目上下文，并帮助 Cursor、Codex 等 AI 编程工具读取正确的项目资料。

## 功能概览

- 统一入口：使用 `fet <command>` 包装 OpenSpec 工作流，避免用户和 AI 工具绕过 FET 的状态记录。
- 生成上下文：扫描项目并生成 `AGENTS.md` 与 `openspec/config.yaml` 中的 `fet:` 配置。
- 管理状态：记录 active change、任务同步、手动验证声明、工具适配状态和语言偏好。
- 集成 AI 工具：为 Cursor 生成规则和 Skill，为 Codex 生成上下文、命令指南和 native slash prompt。
- 统一语言：默认使用中文输出交互信息和生成产物，可通过 `--lang <language>` 切换。
- 保护关键阶段：在 `sync` / `archive` 前检查 FET verify 状态，降低未验证变更被合入或归档的风险。
- 可选代码图：可接入 GitNexus，在大范围扫描前优先提供结构化代码上下文。
- Figma 守卫：当 change 产物含 Figma 链接时，自动写入 `figma-apply-instructions.md`（apply 前必读稿）与 `figma-stop.md`（读稿失败则停下问用户，禁止猜样式）。
- UI 展示契约：当 change 含 Figma 和/或接口文档引用时，生成 `ui-display-contract.yaml` 草案与 `ui-field-apply-instructions.md`；规划 spec 须写入「仅展示 displayFields」Requirement，避免按 OpenAPI 全量渲染。
- Spec 分层双语：英文 Requirements/Scenario 为权威，每个 Requirement 配 `<!-- 中文：... -->`；LLM 更新 spec 时须同次编辑同步中文说明（见 `fet.specLanguage` 与 `.cursor/rules/fet-spec-language.mdc`）。

## 基本原理

FET 是 OpenSpec 的透明代理和本地编排层。运行 `fet apply`、`fet archive` 等命令时，FET 会先读取项目状态和 change 状态，执行必要的 pre-hook，再调用真实的 `openspec` CLI，最后根据 OpenSpec 的结果更新 FET 状态。

FET 代理命令会保留 OpenSpec 原生命令名。例如，`fet apply --change <id>` 会调用 `openspec apply --change <id>`，`fet sync --change <id>` 会在 FET verify gate 通过后调用 `openspec sync --change <id>`。

## 环境要求

- Node.js 18 或更高版本
- OpenSpec CLI 在 `PATH` 中可用

安装 OpenSpec：

```sh
npm install -g @fission-ai/openspec
```

## 安装

```sh
npm install -g @nick848/fet
```

安装后检查：

```sh
fet --version
fet --help
fet update
```

## 第一次使用（推荐顺序）

以下流程面向**第一次在业务项目中接入 FET** 的场景。请在你希望接入 OpenSpec 的**项目根目录**（含 `package.json` 或业务源码的目录）执行，而不是在 FET 工具仓库自身目录。

### 步骤 1：安装依赖工具

1. 安装 [OpenSpec CLI](https://github.com/Fission-AI/OpenSpec)（全局）：

   ```sh
   npm install -g @fission-ai/openspec
   openspec --version
   ```

2. 安装 FET（全局）：

   ```sh
   npm install -g @nick848/fet
   fet --version
   ```

### 步骤 2：初始化项目

在业务项目根目录执行：

```sh
fet init --yes
```

`fet init` 会：

- 检测 OpenSpec；若项目尚无 `openspec/`，则调用 `openspec init`
- 扫描仓库并生成 `AGENTS.md`、`openspec/config.yaml` 的 `fet:` 配置
- 写入 `openspec/fet-state.json` 等工作流状态
- 为 **Cursor**、**Codex** 生成 Skill / 规则 / 命令指南（见下文「在 IDE 中使用」）
- 可选检测 GitNexus（未安装仅提示一次，不阻断）

需要英文产物时，可在初始化时指定：

```sh
fet init --yes --lang en
```

### 步骤 3：检查环境

```sh
fet doctor
```

确认 OpenSpec 路径、上下文文件、工具集成无 `fail`。若有锁文件残留，可执行 `fet doctor --fix-lock`。

### 步骤 4：补齐项目上下文（与 IDE 协作）

扫描器无法自动推断的内容会在 `AGENTS.md` 中标记为 `[NEEDS LLM INPUT]`。请执行：

```sh
fet fill-context
```

然后在 **Cursor** 或 **Codex** 中按生成的 handoff 说明（如 `.fet/fill-context.md`、`.cursor/skills/fet-fill-context/SKILL.md`）让 AI 协助补全占位符。补全后再次运行 `fet doctor`，占位符相关项应为通过。

### 步骤 5：（可选）配置代码图

若希望 AI 在大范围扫仓库前先读结构化代码图，请先安装 GitNexus CLI（确保 `gitnexus` 在 PATH 中），再执行：

```sh
fet graph setup    # 生成安装引导，FET 不会自动安装 GitNexus
fet graph init     # 首次构建图谱
fet graph handoff  # 生成 IDE 交接说明
```

### 步骤 6：在 IDE 中使用

初始化完成后，建议在 AI 工具中确认以下资料可被读取：

| 工具 | 主要入口 |
|------|----------|
| Cursor | `.cursor/rules/fet-context.mdc`；`.cursor/skills/fet-*/SKILL.md` |
| Codex | `.codex/fet/context.md`；`$CODEX_HOME/prompts/fet-*.md` |

工作流命令请在**终端**执行 `fet <command>`（例如 `fet apply`），不要绕过 FET 直接调用 `openspec`，否则本地状态与 verify 闸门不会更新。

### 步骤 7：完成第一个 change

初始化无误后，按 OpenSpec 工作流创建并落地第一个变更。简单路径示例：

```sh
fet propose my-first-change
# 或在 Cursor/Codex 中按提示逐步执行 fet continue
fet tdd --change my-first-change
fet apply --change my-first-change
fet test --change my-first-change
fet visual --change my-first-change
fet verify --change my-first-change
fet verify --done --change my-first-change
fet sync --change my-first-change
fet archive --change my-first-change
```

复杂路径可先 `fet new <id>`，再多次 `fet continue` 或 `fet ff`。各阶段说明见下文「日常变更流程」。

---

## 日常变更流程

在已完成「第一次使用」的项目中，典型循环为：

```sh
fet new my-change          # 或 fet propose my-change
fet continue               # 按需重复，生成下一规划产物
fet tdd --change my-change # 生成本 change 的 TDD 清单（.fet/tdd-manifest.yaml）
fet apply --change my-change
fet test --change my-change
fet visual --change my-change
fet verify --change my-change
fet verify --done --change my-change
fet sync --change my-change
fet archive --change my-change
```

说明：

- `continue`、`apply`、`ff`、`sync` 等命令在未传 `--change` 时，优先使用 FET 记录的 **active change**；若仅有一个打开的 change，会自动选中。
- `fet apply` 默认要求已运行 `fet tdd`（`openspec/config.yaml` 中 `fet.tdd.mode` 可配置）。
- `fet verify` 要求本 change 已通过 `fet test`（除非 `fet.tdd.enabled: false` 或 test 被配置为 skip）。
- 含 Figma 引用的 change 在 `fet verify` 前须通过 `fet visual`（默认 layout-only，一条命令完成清单/截图/布局检查）。
- 经 FET 执行的 `sync` / `archive` 会先检查是否已 `fet verify --done`。
- 项目结构变化后运行 `fet update-context`；仅刷新 IDE 占位符提示时运行 `fet fill-context`。

## 语言设置

FET 默认使用中文输出交互信息和生成产物。

```sh
fet init --lang zh-CN
fet init --lang en
```

`fet init --lang <language>` 会把语言写入 `openspec/fet-state.json`。后续命令如果没有传 `--lang`，会复用初始化时保存的语言。支持值：

| 参数值 | 含义 |
|------|------|
| `zh-CN`、`zh`、`cn`、`chinese` | 中文 |
| `en`、`en-US`、`english` | 英文 |

## 全局参数

| 参数 | 说明 | 示例 |
|------|------|------|
| `--cwd <path>` | 指定项目根目录，默认当前目录。 | `fet doctor --cwd ./app` |
| `--change <id>` | 指定 OpenSpec change。 | `fet apply --change add-login` |
| `--lang <language>` | 指定交互信息和生成产物语言。 | `fet init --lang en` |
| `--yes` | 对低风险确认使用默认同意。 | `fet init --yes` |
| `--json` | 输出机器可读 JSON。 | `fet doctor --json` |
| `--verbose` | 输出更多诊断信息。 | `fet doctor --verbose` |
| `--no-color` | 禁用终端颜色。 | `fet --no-color doctor` |

### 版本更新检查

除 `fet update` 外，FET 在执行其他命令前会检查 npm 上是否有新版本（默认缓存 6 小时）。发现新版本时会提示当前版本与最新版本；在交互式终端中可选择立即升级、跳过并继续当前任务，或取消命令。

| 环境变量 | 说明 |
|----------|------|
| `FET_UPDATE_CHECK` | `off` 关闭检查；`warn` 仅警告并继续；`confirm` 在 TTY 中交互询问（默认）。 |
| `FET_SKIP_UPDATE_CHECK` | 设为 `1` 时等同于 `FET_UPDATE_CHECK=off`。 |
| `FET_UPDATE_CHECK_TTL_MS` | 版本检查缓存时长（毫秒），默认 `21600000`（6 小时）。 |

使用 `--yes` 或 `--json` 时会跳过交互式升级询问；跳过某版本后，同一最新版本不会重复提示，直到检测到更高的新版本。

## 命令列表

| 命令 | 用法 | 说明 |
|------|------|------|
| `fet init` | `fet init [--yes] [--lang <language>]` | 初始化 FET 和 OpenSpec；生成上下文、状态、Cursor 集成和 Codex 工作流指南。 |
| `fet update` | `fet update` | 检查 npm 上的新版本并在需要时自动升级 FET。 |
| `fet update-context` | `fet update-context [--yes]` | 重新扫描项目并更新 `AGENTS.md` 与 `openspec/config.yaml` 的 FET 托管区域。 |
| `fet fill-context` | `fet fill-context [--yes]` | 刷新 IDE 交接命令；自动识别小程序工程并写入包体积/2MB 约束，引导 AI 补齐其余 `AGENTS.md` 占位符。 |
| `fet doctor` | `fet doctor [--fix-lock]` | 诊断 OpenSpec、FET 状态、上下文文件、工具集成和锁文件。 |
| `fet explore` | `fet explore [...args] [--change <id>]` | 通过 FET 执行 OpenSpec 原生 explore，保留交互式需求澄清。 |
| `fet propose` | `fet propose <change-id-or-description>` | 创建 OpenSpec change，并生成第一个 ready 规划产物；后续产物用 `continue` 逐步推进。 |
| `fet new` | `fet new <change-id>` | 创建新的 OpenSpec change。 |
| `fet continue` | `fet continue [...args] [--change <id>]` | 通过 FET 执行 OpenSpec 原生 continue。 |
| `fet ff` | `fet ff [...args] [--change <id>]` | 通过 FET 执行 OpenSpec 原生 ff。 |
| `fet tdd` | `fet tdd [--change <id>]` | 根据规划产物生成 `openspec/changes/<id>/.fet/tdd-manifest.yaml` 等 TDD 契约。 |
| `fet apply` | `fet apply [...args] [--change <id>]` | 准备实施指令；需先有 TDD 清单（默认）。 |
| `fet test` | `fet test [--change <id>] [--plan]` | 按 TDD 清单运行项目 test 脚本并记录绿灯状态。 |
| `fet visual` | `fet visual [--change <id>] [--base-url <url>] [--plan]` | layout-only 视觉验收（默认含截图+布局检查；含 Figma 时 verify 前必需）。 |
| `fet verify` | `fet verify --change <id>` | 生成 `.fet/verify-instructions.md`；需先 `fet test`（及含 Figma 时的 `fet visual`）通过。 |
| `fet verify --done` | `fet verify --done --change <id>` | 声明手动验证完成，允许后续 `sync` / `archive`。 |
| `fet verify --auto` | `fet verify --auto [--yes]` | 生成自动验证计划；当前版本不执行项目脚本，`--yes` 会记录计划指纹。 |
| `fet sync` | `fet sync [...args] [--change <id>]` | FET verify gate 通过后执行 OpenSpec 原生 sync。 |
| `fet archive` | `fet archive --change <id>` | FET verify gate 通过后归档 change，并追加 `CHANGELOG.md`。 |
| `fet bulk-archive` | `fet bulk-archive [...args] [--change <id>]` | 通过 FET 执行 OpenSpec 原生 bulk-archive。 |
| `fet onboard` | `fet onboard [...args] [--change <id>]` | 通过 FET 执行 OpenSpec 原生 onboard。 |
| `fet passthrough` | `fet passthrough <command> [...args]` | 透传暂未接管的 OpenSpec 命令，不更新 FET 生命周期状态。 |

## GitNexus 代码图支持

GitNexus 是可选能力。FET 会在 `fet init` 时检测 `gitnexus` 可执行文件，并把结果记录到 `openspec/fet-state.json`。如果没有安装 GitNexus，初始化只会给出一次推荐提示，主流程会继续执行；`fet doctor` 也只会把缺失 GitNexus 作为 warning。

图谱命令统一放在 `fet graph` 下：

| 命令 | 说明 |
|------|------|
| `fet graph status` | 检查 GitNexus、图谱路径和当前状态，并更新 FET 状态。 |
| `fet graph setup` | 生成 `.fet/graph-setup.md`，用于安装和 IDE 辅助配置引导；FET 不会自动安装 GitNexus。 |
| `fet graph init` | 执行 `gitnexus analyze`，用于首次构建图谱。 |
| `fet graph refresh` | 再次执行 `gitnexus analyze`，用于刷新图谱。 |
| `fet graph doctor` | 检查图谱集成健康状态，缺失只提示，不阻断 FET/OpenSpec 命令。 |
| `fet graph handoff` | 生成 `.fet/graph-handoff.md`，供 Cursor、Codex、OpenCode 等 IDE AI 在大范围扫描前优先参考图谱上下文。 |

默认情况下，FET 从 `PATH` 查找 `gitnexus`，并认为图谱目录是 `.gitnexus`。高级用户可以通过 `FET_GITNEXUS_EXECUTABLE`、`FET_GITNEXUS_COMMAND`、`FET_GITNEXUS_GRAPH_PATH` 覆盖默认行为。

## Andrej Karpathy 风格指南

`fet init` 和 `fet update-context` 会为当前工程加入一份 FET 管理的 Andrej Karpathy 风格编码指南。FET 不假设 Codex 或 OpenCode 会主动读取 `CLAUDE.md`，因此会把指南同步到多个上下文文件中：

- `CLAUDE.md`：追加或刷新 `FET:BEGIN ANDREJ-KARPATHY-SKILLS` 管理块。
- `.fet/karpathy-guidelines.md`：通用 IDE handoff。
- `.codex/fet/karpathy-guidelines.md`：Codex 专用上下文。
- `.cursor/rules/karpathy-guidelines.mdc`：Cursor 项目规则。

这份指南不是复制第三方仓库全文，而是基于 `andrej-karpathy-skills` 的使用目标生成项目级精简规则：先思考、保持简单、精准修改、按目标验证。来源项目：<https://github.com/forrestchang/andrej-karpathy-skills>。

## 生成文件

FET 可能创建或更新：

- `AGENTS.md`
- `openspec/config.yaml` 的 `fet:` 命名空间
- `openspec/fet-state.json`
- `openspec/changes/<change-id>/fet-state.json`
- `openspec/changes/<change-id>/.fet/verify-instructions.md`
- `CHANGELOG.md`
- `.fet/fill-context.md`
- `.fet/graph-setup.md`
- `.fet/graph-handoff.md`
- `.fet/karpathy-guidelines.md`
- `CLAUDE.md`
- `.cursor/skills/fet-*/SKILL.md`
- `.cursor/rules/fet-context.mdc`
- `.cursor/rules/fet-figma-stop.mdc`
- `.cursor/rules/fet-spec-language.mdc`
- `.cursor/rules/karpathy-guidelines.mdc`
- `.codex/fet/context.md`
- `.codex/fet/figma-stop.md`
- `.codex/fet/spec-language.md`
- `.codex/fet/karpathy-guidelines.md`
- `openspec/changes/<change-id>/.fet/figma-apply-instructions.md`（apply 时含 Figma 链接则写入，实施 UI 前必读）
- `openspec/changes/<change-id>/.fet/figma-stop.md`（change 含 Figma 链接时自动写入）
- `.codex/fet/commands/*.md`
- `$CODEX_HOME/prompts/fet-*.md`

FET 只拥有明确标记的托管区域。托管区域之外的用户内容应被保留。

**团队与 Git**：`openspec/fet-state.json`、锁文件等是否纳入版本库由团队自行决定。`fet init` 不再自动修改 `.gitignore`。常见做法：（1）提交共享状态并约定每人只改自己负责的 change，减少 `activeChangeId` 冲突；（2）仅在本机用 `.git/info/exclude` 排除锁文件与日志，仓库 `.gitignore` 保持团队统一；（3）整包状态不入库，由每人本地维护（适合无协作场景）。可参考 `src/templates/gitignore.ts` 中的规则片段自行合并。

## 安全边界

FET 是本地工作流辅助工具，不是沙箱、强制 CI gate 或密码学审计系统。直接调用 `openspec` 可以绕过 FET 的本地 gate。团队如果需要强制执行验证，应在 CI、分支保护或代码审查规则中重复校验。

## 开发

```sh
npm install
npm run typecheck
npm run test
npm run build
npm run release:check
```

运行真实 OpenSpec 烟测：

```powershell
$env:FET_REAL_OPENSPEC='1'; npm run test:real-openspec
```

## 许可证

MIT
