# https://github.com/sjquant/skul 项目说明书

生成时间：2026-06-27 08:34:33 UTC

## 目录

- [简介、安装与命令速查](#page-intro)
- [系统架构、状态布局与 Git 集成](#page-architecture)
- [Bundle 发现、获取与多工具物化](#page-bundle)
- [根指令文件：Stealth 与 Tracked Shadow 双模式](#page-root-instruction)

<a id='page-intro'></a>

## 简介、安装与命令速查

### 相关页面

相关主题：[系统架构、状态布局与 Git 集成](#page-architecture), [Bundle 发现、获取与多工具物化](#page-bundle)

<details>
<summary>相关源码文件</summary>

以下源码文件用于生成本页说明：

- [README.md](https://github.com/sjquant/skul/blob/main/README.md)
- [package.json](https://github.com/sjquant/skul/blob/main/package.json)
- [website/README.md](https://github.com/sjquant/skul/blob/main/website/README.md)
- [website/src/pages/index.tsx](https://github.com/sjquant/skul/blob/main/website/src/pages/index.tsx)
- [src/utils/testing.ts](https://github.com/sjquant/skul/blob/main/src/utils/testing.ts)
</details>

# 简介、安装与命令速查

## 项目定位与核心价值

`skul` 是一款面向 AI 编码工具的配置包（bundle）管理 CLI，核心定位是「跨仓库、跨工具、跨团队共享 AI 资产，而不在 Git 中留下噪声」。它从 GitHub 仓库中拉取可复用的 AI 资源（包含技能 skills、斜杠命令 commands、代理 agents 与根指令 root instructions），将其写入每个工具期望的原生目录，再通过 `.git/info/exclude` 把这些本地文件从版本控制中隐藏，从而避免每次更新都污染项目工作区。资料来源：[README.md](https://github.com/sjquant/skul/blob/main/README.md)

项目同时强调「一份源、多端复用」——同一份 bundle 可下发到 Claude Code、Cursor、OpenCode、Codex、GitHub Copilot 与 Kiro 六种工具。官方文档站首页也把这一价值提炼为三条主张：*One source, many tools* / *No repo noise* / *Roll out updates fast*，并强调 `skul` 适用于「AI 设置需要在仓库、工具与团队之间共享、但每个项目都不想变成 prompt 仓库」的场景。资料来源：[website/src/pages/index.tsx](https://github.com/sjquant/skul/blob/main/website/src/pages/index.tsx)

## 环境要求与安装

`skul` 的运行时基线为 Node.js >= 20，徽章在仓库主 README 顶部明确给出；代码以 TypeScript strict 模式编写，并通过 `vitest` 进行单元测试，相关依赖统一声明在 `devDependencies` 中。运行时依赖仅三项：CLI 参数解析使用 `commander`、交互式选择使用 `@clack/prompts`、终端着色使用 `picocolors`，均在 `package.json` 的 `dependencies` 段中固定版本号。资料来源：[package.json](https://github.com/sjquant/skul/blob/main/package.json)

项目自带的文档站位于 `website/`，使用 Docusaurus 构建。`website/README.md` 给出了标准的三步本地流程：

```bash
pnpm install
pnpm start    # 本地开发预览
pnpm build    # 构建静态站点
```

资料来源：[website/README.md](https://github.com/sjquant/skul/blob/main/website/README.md)

仓库还提供了根指令相关的回归测试夹具与断言工具。`formatRootInstructionBundleBlock` 会按生产布局生成带 `<!-- BEGIN SKUL BUNDLE -->` / `<!-- END SKUL BUNDLE -->` 边界的期望文档；`formatTrackedRootInstructionShadowBlock` 则生成 `<!-- SKUL SHADOW START bundle=... -->` 形式的影子块，可被 `expectAgentsDocument`、`expectClaudeDocument` 等断言函数直接复用，便于校验 `AGENTS.md` 与 `CLAUDE.md` 的渲染一致性。资料来源：[src/utils/testing.ts](https://github.com/sjquant/skul/blob/main/src/utils/testing.ts)

## 常用命令速查

`skul` 的核心命令围绕「拉取 → 缓存 → 重放」循环展开。`skul add` 负责把一个远端 bundle 写入当前项目（或全局），首次执行会克隆源仓库到 `~/.skul/library/`，后续调用直接复用本地缓存。典型用法包括：

```bash
# 首次拉取：从 GitHub registry 取 react-expert bundle
skul add github.com/sjquant/ai-bundles react-expert

# 简写：GitHub 默认为 registry
skul add acme/shared-bundles core --agent codex

# 在团队 AGENTS.md / CLAUDE.md 之上叠加个人指令而不污染 Git
skul add acme/personal-instructions --agent codex

# 纯本地重放，无网络
skul add react-expert
```

`skul apply` 在已链接的 worktree 中重新物化 registry 中记录的文件，`skul update` 则在团队发布新版本后刷新本地缓存。资料来源：[README.md](https://github.com/sjquant/skul/blob/main/README.md)。网站首页的「典型会话」面板也展示了几乎一致的四步流程：从 `skul add ... --agent codex` 开始，到 `skul apply`、`skul update` 收尾。资料来源：[website/src/pages/index.tsx](https://github.com/sjquant/skul/blob/main/website/src/pages/index.tsx)

`skul add` 的常用选项在 README 中均有说明，常用组合可归纳为：

- `--ref <name>`：跟踪指定分支或标签，取代默认的 HEAD。
- `--pin <sha>`：锁定到 7–40 位十六进制提交 SHA，与 `--ref` 互斥。
- `--include <item>`：仅安装指定条目（`skills/<name>`、`commands/<name>`、`agents/<name>`、`root-instruction`），可重复。
- `--select-items`：打开交互式选择器；与 `--include` 联用时会预选已包含项。
- `-s, --ssh`：通过 SSH 克隆；`git@host:owner/repo` 形式的 URL 会被自动识别，协议会被持久化以便 `skul apply` 复用。
- `-g, --global`：安装到 `~/` 下的全局工具配置，而不是当前 worktree。
- `-n, --dry-run`：仅预览将要写入的内容，不做实际修改。

资料来源：[README.md](https://github.com/sjquant/skul/blob/main/README.md)

## 支持的工具与目录映射

`skul` 将统一的资源类型（skills、commands、agents、root instructions）按各工具约定落到不同目录，下表整理自 README 的「Supported Tools」一节：

| 工具 | Skills 目录 | Commands 目录 | Agents 目录 | 根指令文件 |
| --- | --- | --- | --- | --- |
| Claude Code | `.claude/skills` | `.claude/commands` | `.claude/agents` | `CLAUDE.md` |
| Cursor | `.cursor/skills` | `.cursor/commands` | `.cursor/agents` | `CLAUDE.md` |
| OpenCode | `.opencode/skills` | `.opencode/commands` | `.opencode/agents` | `CLAUDE.md` |
| Codex | `.agents/skills` | — | `.codex/agents` | `AGENTS.md` |
| GitHub Copilot | `.github/skills` | — | `.github/agents` | `.github/copilot-instructions.md` |
| Kiro | `.kiro/skills` | — | `.kiro/agents` | `AGENTS.md` |

资料来源：[README.md](https://github.com/sjquant/skul/blob/main/README.md)

可通过 `--agent <name>` 显式指定单一工具并重复该标志以覆盖多个目标。值得注意的是，当 bundle 仅提供 `AGENTS.md` 或 `CLAUDE.md` 之一时，`skul` 仍会按各工具的原生文件名（`AGENTS.md`、`CLAUDE.md`、`.github/copilot-instructions.md`）物化等价内容，从而保持多端指令的一致性。资料来源：[README.md](https://github.com/sjquant/skul/blob/main/README.md)

## See Also

- [项目主页与产品定位](https://github.com/sjquant/skul/blob/main/website/src/pages/index.tsx)
- [仓库 README 完整文档](https://github.com/sjquant/skul/blob/main/README.md)
- [文档站构建说明](https://github.com/sjquant/skul/blob/main/website/README.md)
- [package.json 依赖清单](https://github.com/sjquant/skul/blob/main/package.json)
- [根指令测试辅助](https://github.com/sjquant/skul/blob/main/src/utils/testing.ts)

---

<a id='page-architecture'></a>

## 系统架构、状态布局与 Git 集成

### 相关页面

相关主题：[Bundle 发现、获取与多工具物化](#page-bundle), [根指令文件：Stealth 与 Tracked Shadow 双模式](#page-root-instruction)

<details>
<summary>相关源码文件</summary>

以下源码文件用于生成本页说明：

- [README.md](https://github.com/sjquant/skul/blob/main/README.md)
- [src/utils/testing.ts](https://github.com/sjquant/skul/blob/main/src/utils/testing.ts)
- [website/README.md](https://github.com/sjquant/skul/blob/main/website/README.md)
- [website/src/pages/index.tsx](https://github.com/sjquant/skul/blob/main/website/src/pages/index.tsx)

> 说明：本页基于仓库当前提供的顶层文档（`README.md`）与测试辅助模块（`src/utils/testing.ts`）整理而成。架构中提到的运行时实现模块（如 `src/registry.ts`、`src/state-layout.ts`、`src/git-exclude.ts` 等）在本抓取上下文中未提供源码，下文对其的描述仅复述自 `README.md` 的公开说明，未补充推测性实现细节。
</details>

# 系统架构、状态布局与 Git 集成

## 1. 设计目标与系统定位

Skul 是一个面向 AI 编码工具的命令行工具，它的核心职责是把"团队共享的 AI 配置（skills、slash commands、agents、根指令文件）"按需写入不同工具所期望的本地目录，同时避免这些工具本地文件污染仓库的 Git 历史 [README.md](https://github.com/sjquant/skul/blob/main/README.md)。从定位上看，Skul 介于"包管理器"与"配置同步器"之间：

- **单一来源**：AI 配置以 GitHub 仓库（bundle 仓库）作为唯一来源；
- **多工具分发**：一次 fetch，多次 materialize，支持 Claude Code、Cursor、OpenCode、Codex、GitHub Copilot、Kiro 等多种工具 [README.md](https://github.com/sjquant/skul/blob/main/README.md)；
- **无 Git 噪音**：通过 `.git/info/exclude` 把 materialize 出来的工具本地文件隐藏掉 [README.md](https://github.com/sjquant/skul/blob/main/README.md)。

文档站本身使用 Docusaurus 构建（`website/` 目录，`pnpm start` 启动、`pnpm build` 构建），并通过首页 hero 区块以 "Share AI bundles without Git noise" 为主标语 [website/README.md](https://github.com/sjquant/skul/blob/main/website/README.md) 与 [website/src/pages/index.tsx](https://github.com/sjquant/skul/blob/main/website/src/pages/index.tsx)，可见 "无 Git 噪音" 与 "One source, many tools" 是产品立项的两条主线。

## 2. 状态布局：library 与 registry

Skul 把所有状态都收敛在用户主目录下，分成"源码缓存"与"期望/实际状态记录"两个部分 [README.md](https://github.com/sjquant/skul/blob/main/README.md)：

| 路径 | 角色 | 关键行为 |
|---|---|---|
| `~/.skul/library/` | bundle 源仓库缓存 | 第一次 `skul add` 时 clone，后续复用；支持 HTTPS / SSH 两种协议，并被 `skul apply` 持久化复用 [README.md](https://github.com/sjquant/skul/blob/main/README.md) |
| `~/.skul/registry.json` | 仓库级期望状态 + 每个 worktree 的实际 materialize 记录 | 区分"仓库想要哪些 bundle"与"每个 worktree 实际写入了哪些文件" [README.md](https://github.com/sjquant/skul/blob/main/README.md) |

这种"声明与事实分离"的设计有一个关键好处：**新增的 linked worktree 会立刻继承仓库级别的期望状态**，但并不会自动 materialize——用户必须显式执行 `skul apply`，从而避免在不经意间把工具本地文件洒到不期望的工作树里 [README.md](https://github.com/sjquant/skul/blob/main/README.md)。

```mermaid
flowchart LR
  User[用户] -->|skul add| CLI[Skul CLI]
  CLI -->|git clone / 复用缓存| Library["~/.skul/library/<source>"]
  CLI -->|更新期望状态| Registry["~/.skul/registry.json"]
  Registry -.期望状态.-> WorktreeA[Worktree A]
  Registry -.期望状态.-> WorktreeB[Worktree B]
  WorktreeA -->|skul apply| FilesA[工具本地文件]
  WorktreeB -->|skul apply| FilesB[工具本地文件]
  FilesA --> ExcludeA[".git/info/exclude"]
  FilesB --> ExcludeB[".git/info/exclude"]
```

## 3. Bundle 仓库结构与 Manifest

bundle 源既可以是"多 bundle"仓库，也可以是"单 bundle"仓库，Skul 在没有 `manifest.json` 的情况下会根据目录结构推断工具目标，bundle 名默认取仓库 slug [README.md](https://github.com/sjquant/skul/blob/main/README.md)。在测试辅助模块中，bundle fixture 通过显式的 manifest 来描述工具与文件路径映射，例如：

- `tools[codex].root_instruction.path` 可设为 `AGENTS.md`；
- `tools["claude-code"].root_instruction.path` 可设为 `CLAUDE.md`；
- manifest 还允许携带额外的工具覆盖（`extraTools`）以及额外文件（`extraFiles`）[src/utils/testing.ts](https://github.com/sjquant/skul/blob/main/src/utils/testing.ts)。

这说明 manifest 在内部以"工具 → 内容块（skills/commands/agents/root_instruction）→ 具体路径"的形式描述每个 bundle，并允许一个工具的根指令（如 `AGENTS.md`）被复用到另一个工具的目标文件上——README 明确指出：当 bundle 只提供 `CLAUDE.md` 时，Codex/Kiro 仍可得到 `AGENTS.md`；反之亦然 [README.md](https://github.com/sjquant/skul/blob/main/README.md)。

## 4. Git 集成：exclude、worktree 与根指令

Git 集成是 Skul 区别于"复制粘贴一份 `.claude/` 到每个项目"的关键能力：

- **`.git/info/exclude`**：所有 materialize 出来的工具本地文件都被加进此 exclude 列表，因此 `git status` 不会看到这些"已存在但未跟踪"的文件，保持工作区干净 [README.md](https://github.com/sjquant/skul/blob/main/README.md)。
- **Worktree 模型**：linked worktree 自动继承 `registry.json` 中的期望状态，但实际文件落地需要 `skul apply`，这一边界使得"团队期望"与"个人 materialize"解耦 [README.md](https://github.com/sjquant/skul/blob/main/README.md)。
- **根指令叠加**：当仓库已经提交了一份 `AGENTS.md` / `CLAUDE.md` 时，Skul 仍可在不污染工作树的前提下叠加个人指令——这正是 README 中"layer your personal instructions on top of a team-committed `AGENTS.md`"的语义 [README.md](https://github.com/sjquant/skul/blob/main/README.md)。

需要注意的是，`--pin`（固定 commit SHA）与 `--ref`（跟踪分支/标签/commit）互斥 [README.md](https://github.com/sjquant/skul/blob/main/README.md)，且 SSH 失败时 CLI 会打印对应的 HTTPS 提示命令——这些都属于 Git 集成层的稳定性细节。

## 5. 常见失败模式与边界

- **SSH 鉴权失败**：协议不匹配时 Skul 会回落到 HTTPS 提示，但已设置的 SSH 偏好会持久化在 library 缓存层 [README.md](https://github.com/sjquant/skul/blob/main/README.md)。
- **多 bundle / 单 bundle 混淆**：当仓库是单 bundle 形式时省略 `manifest.json` 是允许的，但用户在 `skul add` 时需要把 bundle 名省略或显式指定 [README.md](https://github.com/sjquant/skul/blob/main/README.md)。
- **跨工具根指令复用**：若 bundle 的指令文本不能被原样复用，跨工具物化会失败；README 强调"as long as the instruction body can be reused as-is" [README.md](https://github.com/sjquant/skul/blob/main/README.md)。
- **TUI 干扰自动化**：`SKUL_NO_TUI=1` 可用于脚本与 agent 场景，抑制所有交互式提示 [README.md](https://github.com/sjquant/skul/blob/main/README.md)。

## See Also

- [安装指南（README Quick Start）](https://github.com/sjquant/skul/blob/main/README.md)
- [支持的工具与目录映射（README Supported Tools）](https://github.com/sjquant/skul/blob/main/README.md)
- [高级维护命令（docs/advanced.md）](https://github.com/sjquant/skul/blob/main/docs/advanced.md)
- [网站与文档构建（website/README.md）](https://github.com/sjquant/skul/blob/main/website/README.md)

---

<a id='page-bundle'></a>

## Bundle 发现、获取与多工具物化

### 相关页面

相关主题：[系统架构、状态布局与 Git 集成](#page-architecture), [根指令文件：Stealth 与 Tracked Shadow 双模式](#page-root-instruction)

<details>
<summary>相关源码文件</summary>

以下源码文件用于生成本页说明：

- [src/bundle-discovery.ts](https://github.com/sjquant/skul/blob/main/src/bundle-discovery.ts)
- [src/bundle-fetch.ts](https://github.com/sjquant/skul/blob/main/src/bundle-fetch.ts)
- [src/bundle-manifest.ts](https://github.com/sjquant/skul/blob/main/src/bundle-manifest.ts)
- [src/bundle-materialization.ts](https://github.com/sjquant/skul/blob/main/src/bundle-materialization.ts)
- [src/bundle-translation.ts](https://github.com/sjquant/skul/blob/main/src/bundle-translation.ts)
- [src/bundle-items.ts](https://github.com/sjquant/skul/blob/main/src/bundle-items.ts)
</details>

# Bundle 发现、获取与多工具物化

`skul` 的核心职责是把"远端 GitHub 仓库中的共享 AI 配置（skills、commands、agents、root instructions）"安全地拉取到本地，并按目标工具的目录约定物化到工作树中。该流程由若干职责单一的模块协同完成：发现（Discovery）解析来源与包名；获取（Fetch）完成克隆与缓存；清单（Manifest）描述工具映射；翻译（Translation）处理跨工具文件名差异；物化（Materialization）最终把文件落到 `.claude/`、`.cursor/`、`.agents/`、`.github/`、`.kiro/`、`.opencode/` 等目录中。

## 模块职责与协作

`bundle-discovery.ts` 负责解析用户传入的 `owner/repo` 或完整 GitHub URL，结合默认 GitHub 注册表形成标准化的来源标识；`bundle-fetch.ts` 负责把该来源克隆到 `~/.skul/library/` 缓存目录，并在后续调用中复用本地缓存。`bundle-manifest.ts` 读取并校验 `manifest.json`（或在 Repo-as-bundle 布局下基于目录结构推断）以决定哪些内容对哪些工具可见。`bundle-translation.ts` 处理不同工具对同一类内容的命名差异（例如 `CLAUDE.md` 与 `AGENTS.md` 互转）。最后 `bundle-materialization.ts` 执行真实的文件写入与 `.git/info/exclude` 规则更新。

下表总结了关键工具的物化目录与根指令文件名：

| 工具 | Skills | Commands | Agents | 根指令文件 |
|---|---|---|---|---|
| Claude Code | `.claude/skills` | `.claude/commands` | `.claude/agents` | `CLAUDE.md` |
| Cursor | `.cursor/skills` | `.cursor/commands` | `.cursor/agents` | `CLAUDE.md` |
| OpenCode | `.opencode/skills` | `.opencode/commands` | `.opencode/agents` | `CLAUDE.md` |
| Codex | `.agents/skills` | — | `.codex/agents` | `AGENTS.md` |
| GitHub Copilot | `.github/skills` | — | `.github/agents` | `.github/copilot-instructions.md` |
| Kiro | `.kiro/skills` | — | `.kiro/agents` | `AGENTS.md` |

资料来源：[README.md:20-30]()。

## 仓库布局与发现逻辑

`skul` 支持两种仓库布局。**Multi-bundle** 布局将每个子目录视作独立 bundle，由目录名作为 bundle 名称；**Repo-as-bundle** 布局则把仓库根目录直接作为单个 bundle，无需 `manifest.json`，工具目标由目录结构推断。资料来源：[README.md:54-78]()。

在发现阶段，`bundle-discovery.ts` 会判断传入的 shorthand（如 `acme/shared-bundles`）是否需要补全为 `github.com/acme/shared-bundles`。GitHub 是默认注册表，来源与协议（SSH 或 HTTPS）会被持久化以便后续 `skul apply` 复用。SSH 协议可通过 `--ssh` 标志显式启用，或通过 `git@host:owner/repo` 形式的 URL 自动识别。资料来源：[README.md:11-19]()。

## 获取、缓存与清单读取

`bundle-fetch.ts` 首次调用时会克隆来源仓库到 `~/.skul/library/`，后续 `add` 调用直接复用本地缓存，无需网络访问。支持的固定方式包括 `--ref <branch|tag>` 与 `--pin <commit-sha>`，二者互斥，确保团队成员可以锁定到确定的版本。资料来源：[README.md:5-10]()。

`bundle-manifest.ts` 读取 `manifest.json` 中的 `tools` 字段以决定每个工具可见的 items；缺少 `manifest.json` 时，会依据目录结构推断工具目标。`bundle-items.ts` 则在用户传入 `--include` 或 `--select-items` 时负责过滤与匹配，支持的选择器包括 `skills/<name>`、`commands/<name>`、`agents/<name>`、`root-instruction`，其中 `AGENTS.md` 与 `CLAUDE.md` 也可作为等价选择器使用。资料来源：[README.md:5-10]()。

## 跨工具翻译与物化

`bundle-translation.ts` 处理以下典型翻译场景：当 bundle 仅提供 `CLAUDE.md` 时，Codex 与 Kiro 仍能物化出 `AGENTS.md`；当 bundle 仅提供 `AGENTS.md` 时，Claude Code 仍能生成 `CLAUDE.md`；当 bundle 仅提供 `AGENTS.md` 或 `CLAUDE.md` 时，GitHub Copilot 仍可物化出 `.github/copilot-instructions.md`——前提是指令正文可直接复用。资料来源：[README.md:87-100]()。

`bundle-materialization.ts` 是流程的终点。它把过滤后的内容写入目标工具目录，并通过 `skul` 边界标记（`<!-- BEGIN SKUL BUNDLE: ... -->` / `<!-- END SKUL BUNDLE: ... -->`）包裹根指令块，便于后续 `update` 与 `apply` 精准替换。物化完成后，模块会将忽略规则写入 `.git/info/exclude`，使本地 AI 文件不会污染 `git status`。当仓库已存在被 Git 跟踪的 `AGENTS.md` 或 `CLAUDE.md` 时，`skul` 可在受管区块之上叠加个人指令，并维护"影子块"以避免脏化工作树。资料来源：[README.md:1-4]()、([src/utils/testing.ts:21-50]())。

```mermaid
flowchart LR
    A[用户输入<br/>owner/repo + bundle] --> B[bundle-discovery]
    B --> C[bundle-fetch<br/>~/.skul/library/]
    C --> D[bundle-manifest<br/>manifest.json 或推断]
    D --> E[bundle-items<br/>--include / --select-items]
    E --> F[bundle-translation<br/>跨工具文件名映射]
    F --> G[bundle-materialization<br/>写入工具目录 + .git/info/exclude]
    G --> H[~/.skul/registry.json<br/>记录期望状态]
```

## 状态记录与重放

物化结果与期望状态被分别记录在 `~/.skul/registry.json`：仓库级条目描述"该项目希望应用哪些 bundle"，而工作树级条目描述"实际写入了哪些文件"。新建的链接 worktree 会立即继承期望状态——只需运行 `skul apply` 即可完成物化，无需手动复制。资料来源：[README.md:101-109]()。

## 常见失败模式

- **SSH 认证失败**：当使用 SSH 克隆失败时，`skul` 会打印提示并给出等价的 HTTPS 命令。资料来源：[README.md:36-38]()。
- **根指令名称不匹配**：当 bundle 仅提供 `CLAUDE.md` 而用户为 Codex 选择时，翻译模块会按规则物化 `AGENTS.md`，但前提是正文可复用。资料来源：[README.md:87-100]()。
- **物化被 Git 跟踪的根指令文件**：当 `AGENTS.md` 或 `CLAUDE.md` 已被仓库跟踪，`skul` 会以边界标记追加受管区块，并通过影子块机制避免脏化工作树。资料来源：[README.md:1-4]()。

## See Also

- [安装与配置](https://github.com/sjquant/skul/blob/main/README.md)
- [命令参考](https://github.com/sjquant/skul/blob/main/README.md)
- [支持的工具与目录映射](https://github.com/sjquant/skul/blob/main/README.md)

---

<a id='page-root-instruction'></a>

## 根指令文件：Stealth 与 Tracked Shadow 双模式

### 相关页面

相关主题：[系统架构、状态布局与 Git 集成](#page-architecture), [Bundle 发现、获取与多工具物化](#page-bundle)

<details>
<summary>相关源码文件</summary>

以下源码文件用于生成本页说明：

- [src/root-instruction-content.ts](https://github.com/sjquant/skul/blob/main/src/root-instruction-content.ts)
- [src/root-instruction-render.ts](https://github.com/sjquant/skul/blob/main/src/root-instruction-render.ts)
- [src/root-instruction-state.ts](https://github.com/sjquant/skul/blob/main/src/root-instruction-state.ts)
- [src/tool-mapping.ts](https://github.com/sjquant/skul/blob/main/src/tool-mapping.ts)
- [src/bundle-materialization.ts](https://github.com/sjquant/skul/blob/main/src/bundle-materialization.ts)
- [src/git-index.ts](https://github.com/sjquant/skul/blob/main/src/git-index.ts)
- [src/utils/testing.ts](https://github.com/sjquant/skul/blob/main/src/utils/testing.ts)
- [README.md](https://github.com/sjquant/skul/blob/main/README.md)
</details>

# 根指令文件：Stealth 与 Tracked Shadow 双模式

## 概述

`skul` 在管理 `AGENTS.md` 与 `CLAUDE.md` 这类根指令（root instruction）文件时，需要同时面对两种截然不同的仓库现状：一种是仓库根目录下根本不存在该文件（属于未追踪的本地状态），另一种是文件已经被团队提交进 Git（属于受版本控制的工作树状态）。为了让 AI 工具始终能够读取到一份由 bundle 渲染出的"有效内容"，同时不污染 `git status` 输出，`skul` 提供了 **Stealth 模式** 与 **Tracked Shadow 模式** 两种实现路径，二者的核心差异在于"如何让 Git 看不见这份被改写的文件"。

资料来源：[README.md:1-120]()

## 模式判定与目录映射

`skul` 的 `tool-mapping.ts` 维护了每个目标工具的根指令目标路径，常见映射如下：

| 工具 | 根指令文件 |
| --- | --- |
| Claude Code | `CLAUDE.md` |
| Codex | `AGENTS.md` |
| Kiro | `AGENTS.md` |
| GitHub Copilot | `.github/copilot-instructions.md` |

当 bundle 中只声明了 `AGENTS.md` 而目标工具是 Claude Code 时，`root-instruction-render.ts` 会复用同一份正文直接渲染成 `CLAUDE.md`；反之亦然。这种"内容等价"映射是 Stealth 与 Tracked Shadow 共用的基础。`bundle-materialization.ts` 在落盘前会先调用 `root-instruction-state.ts` 判断目标文件是否已被仓库追踪，从而选择对应的写入策略。

资料来源：[README.md:1-120]()、[src/utils/testing.ts:1-80]()

```mermaid
flowchart TD
    A[skul add / apply] --> B[读取 manifest 与 bundle 文件]
    B --> C{目标路径已被 Git 追踪?}
    C -- 否 --> D[Stealth 模式]
    C -- 是 --> E[Tracked Shadow 模式]
    D --> D1[渲染正文 + SKUL 标记]
    D1 --> D2[写入 .git/info/exclude 隐藏]
    E --> E1[读取 HEAD:path 作为基线]
    E1 --> E2[合成 base + SKUL 覆盖块]
    E2 --> E3[git update-index --skip-worktree]
    D2 --> F[更新 worktree 物化记录]
    E3 --> F
```

## Stealth 模式：未追踪的根指令文件

当 `root-instruction-state.ts` 确认目标文件在 Git 索引中不存在（例如仓库没有 `AGENTS.md`，或者文件被 `.gitignore` 排除）时，`skul` 进入 **Stealth 模式**。该模式的工作流由 `root-instruction-render.ts` 渲染正文，再由 `root-instruction-content.ts` 在写入前做合并处理：

- 如果目标路径在当前 worktree 中已经有本地内容（可能是开发者手写的草稿），`skul` 会保留这部分**本地前置内容**，然后在文件末尾追加 `SKUL` 标记包裹的 bundle 块。`src/utils/testing.ts` 中的 `expectRootInstructionDocument` 辅助函数就是用来断言这种"前置保留 + SKUL 块"的精确拼装结果。
- 渲染完成后，`skul` 把该文件的忽略规则写入 `.git/info/exclude`，使文件在工作目录中存在但**永远不会出现在 `git status` 里**。
- 由于 Stealth 模式下不存在"被 Git 管理的基线"，`skul` 允许多个 bundle 共同叠加在同一个根指令文件上，因此该路径支持**多 bundle 组合**。

资料来源：[README.md:1-120]()、[src/utils/testing.ts:1-80]()

## Tracked Shadow 模式：已追踪的根指令文件

当目标文件已经被团队提交（例如 `CLAUDE.md` 是项目策略文档），`skul` 不能简单地通过 `.git/info/exclude` 隐藏它——团队成员需要继续看到该文件被 Git 追踪。`root-instruction-state.ts` 在这种场景下切换到 **Tracked Shadow 模式**，并依赖 `git-index.ts` 来与 Git 索引交互：

1. `git-index.ts` 通过 `git show HEAD:<path>` 读取**已提交版本的 blob** 作为基线正文。
2. `root-instruction-render.ts` 把基线正文与 bundle 提供的覆盖块（`SKUL` 标记包裹）合成一份"有效内容"，写入 worktree 中的同名文件。
3. `git-index.ts` 调用 `git update-index --skip-worktree <path>`，告诉 Git 这份 worktree 副本是"临时覆盖"，不要让它出现在 `git status` 变更列表里。
4. `skul status` 会在专门的 **Shadowed Instructions** 分区中报告这种状态，包括：基线 blob 是否仍然指向当前 `HEAD`、覆盖块是否仍然匹配、`skip-worktree` 标记是否仍生效，以及是否检测到用户的手动编辑痕迹。

Tracked Shadow 模式是**单所有者**的：同一时刻只能有一个 bundle 拥有某个追踪路径的 shadow，因此多 bundle 组合仅在 Stealth 模式下可用。对于生命周期管理（`shadow --suspend` / `--refresh`、`sync`、SSH 协议下的克隆等）以及安全阈值，参见 `docs/advanced.md`。

资料来源：[README.md:1-120]()

## 跨工具等价与恢复路径

两种模式共享一个跨工具等价规则：如果 bundle 仓库中只存在 `CLAUDE.md`（或 `AGENTS.md`）一份正文，`root-instruction-render.ts` 仍可在 Codex、Kiro 上落地为 `AGENTS.md`，在 GitHub Copilot 上落地为 `.github/copilot-instructions.md`，前提是正文可以被对应工具按原样消费。这一映射使 bundle 作者无需为每个工具维护多份文件。

在恢复路径上，Stealth 模式可通过删除 worktree 中的目标文件并清掉 `.git/info/exclude` 中的对应规则来回滚；Tracked Shadow 模式则需要先 `git update-index --no-skip-worktree <path>` 恢复索引位，然后 `git checkout -- <path>` 还原为 `HEAD` 中的基线。任何"实际写过哪些文件"的明细都记录在 `~/.skul/registry.json` 的 worktree 物化区段中，可作为排查依据。

资料来源：[README.md:1-120]()

## See Also

- [README.md](https://github.com/sjquant/skul/blob/main/README.md)
- [docs/advanced.md](https://github.com/sjquant/skul/blob/main/docs/advanced.md)
- [package.json](https://github.com/sjquant/skul/blob/main/package.json)

---

<!-- evidence_pipeline_checked: true -->

---

## Doramagic 踩坑日志

项目：sjquant/skul

摘要：发现 7 个潜在踩坑项，其中 0 个为 high/blocking；最高优先级：配置坑 - 可能修改宿主 AI 配置。

## 1. 配置坑 · 可能修改宿主 AI 配置

- 严重度：medium
- 证据强度：source_linked
- 发现：项目面向 Claude/Cursor/Codex/Gemini/OpenCode 等宿主，或安装命令涉及用户配置目录。
- 对用户的影响：安装可能改变本机 AI 工具行为，用户需要知道写入位置和回滚方法。
- 证据：capability.host_targets | https://github.com/sjquant/skul | host_targets=claude

## 2. 能力坑 · 能力判断依赖假设

- 严重度：medium
- 证据强度：source_linked
- 发现：README/documentation is current enough for a first validation pass.
- 对用户的影响：假设不成立时，用户拿不到承诺的能力。
- 证据：capability.assumptions | https://github.com/sjquant/skul | README/documentation is current enough for a first validation pass.

## 3. 维护坑 · 维护活跃度未知

- 严重度：medium
- 证据强度：source_linked
- 发现：未记录 last_activity_observed。
- 对用户的影响：新项目、停更项目和活跃项目会被混在一起，推荐信任度下降。
- 证据：evidence.maintainer_signals | https://github.com/sjquant/skul | last_activity_observed missing

- 严重度：medium
- 证据强度：source_linked
- 发现：no_demo
- 证据：downstream_validation.risk_items | https://github.com/sjquant/skul | no_demo; severity=medium

## 5. 安全/权限坑 · 存在评分风险

- 严重度：medium
- 证据强度：source_linked
- 发现：no_demo
- 对用户的影响：风险会影响是否适合普通用户安装。
- 证据：risks.scoring_risks | https://github.com/sjquant/skul | no_demo; severity=medium

## 6. 维护坑 · issue/PR 响应质量未知

- 严重度：low
- 证据强度：source_linked
- 发现：issue_or_pr_quality=unknown。
- 对用户的影响：用户无法判断遇到问题后是否有人维护。
- 证据：evidence.maintainer_signals | https://github.com/sjquant/skul | issue_or_pr_quality=unknown

## 7. 维护坑 · 发布节奏不明确

- 严重度：low
- 证据强度：source_linked
- 发现：release_recency=unknown。
- 对用户的影响：安装命令和文档可能落后于代码，用户踩坑概率升高。
- 证据：evidence.maintainer_signals | https://github.com/sjquant/skul | release_recency=unknown

<!-- canonical_name: sjquant/skul; human_manual_source: deepwiki_human_wiki -->
