首页
/ Impeccable 项目 Live 模式一次性配置全指南:config.json 编写、CSP 检测与框架注入适配

Impeccable 项目 Live 模式一次性配置全指南:config.json 编写、CSP 检测与框架注入适配

2026-09-07 19:25:46作者:裴锟轩Denise

本文面向将 impeccable 的交互式 Live 变体模式接入既有项目、并希望搞清楚"启动时那个一次性配置到底要我做什么"的开发者与 AI Agent。核心围绕 live-setup.md 展开:当 live.mjs 报告 config_missing / config_invalid、需要处理 configDrift,或配置缺少 cspChecked 时,Agent 需要为项目写入 .impeccable/live/config.json、选定注入锚点、按框架表挑选注入目标,并完成一次性的 Content Security Policy(CSP)放行。读完本文,你将掌握该配置的完整字段语义、各框架标准值、注入适配器与配置漂移机制、四种 CSP 形态的检测与补丁流程,以及出错时的排查手段。

live-setup 在何时被加载

live-setup 是 Live 模式的一次性项目初始化文档,不是每次会话的热路径。从 live.md 的"First-time setup"一节看,只有当以下三种情况之一成立时,主流程才会读取并执行 live-setup:

  1. live.mjs 启动输出 { ok: false, error: "config_missing" | "config_invalid", path }——即 .impeccable/live/config.json 缺失或非法;
  2. 启动输出携带非空 configDrift,需要向用户说明有 HTML 文件未被覆盖;
  3. 已有配置中缺少 cspChecked 字段(表示首次 CSP 检查尚未完成)。

正常情况下,一旦项目配置就绪,后续 Live 会话不会重复走这套流程;因此 live-setup 描述的是一次性、幂等的引导动作,而不是随会话循环执行的过程。

第一步:编写注入配置 .impeccable/live/config.json

live.mjs 启动时会报告它期望的配置文件路径(默认 .impeccable/live/config.json)。完整字段如下:

{
  "files": ["<path-or-glob>", "<path-or-glob>", ...],
  "exclude": ["<optional-glob>", ...],
  "insertBefore": "</body>",
  "commentSyntax": "html",
  "cspChecked": true
}

各字段语义(依据 live-setup 原文):

字段 必填 说明
files 注入目标:浏览器真正加载的 HTML 文件(而不一定是源码文件)。条目可以是字面路径或 glob;"tracked 源码 vs 生成文件"在这里不重要——wrap 流程另有自己的生成文件守卫。
exclude files glob 命中结果中排除的文件(如邮件模板、demo fixtures)。
insertBefore 锚点文本,注入脚本插在该文本所在行之前;默认 </body>
commentSyntax 写入文件的注释语法,取 htmljsx
cspChecked 首次写入常缺 记录"CSP 检查步骤已执行过";首次配置时缺省,用于让引导流程只在第一次询问用户 CSP 授权。

需要特别注意两点硬性约束:

  • 硬排除路径(不可覆盖)**/node_modules/****/.git/** 永远不可能成为注入目标,向其中注入会插桩第三方代码。
  • glob 语法** 匹配任意数量路径段(含零个),* 匹配单个段内内容,? 匹配单个字符;路径一律以项目根为基准并使用正斜杠。

各框架的 files / 锚点对照表

live-setup 为常见框架给出了经过验证的标准取值。选注入目标的原则是:挑选在每个文件中都真实存在的一个锚点</body> 几乎总是可用)。insertAfter 则改为匹配某行之后插入。

框架 files insertBefore commentSyntax
单壳 SPA(Vite / React / 纯 HTML) ["index.html"] </body> html
Next.js(App Router) ["app/layout.tsx"] </body> jsx
Next.js(Pages Router) ["pages/_document.tsx"] </body> jsx
Nuxt ["app.vue"] </body> html
Svelte / SvelteKit ["src/app.html"] </body> html
TanStack Router(SPA,Vite) ["index.html"] </body> html
TanStack Start(SSR) ["src/routes/__root.tsx"] <Scripts jsx
Astro ["<根布局 .astro>"] </body> html
多页站点(每路由独立 HTML) ["public/**/*.html"](对服务目录做 glob) </body> html

实战提示(源自原文):

  • 多页站点优先用 glob,这样新增页面会被自动纳入注入范围,无需每次改配置。
  • 由生成器重建的站点:注入只存活到下一次重新生成。每次构建后需重跑 live.mjs。注意 accept 不受影响——它经由 fallback 流程把最终结果写进真正的源码。
  • TanStack Start 的注入锚点是 <Scripts(其 root 组件在渲染脚本时执行),而不是 </body>

框架注入适配器与 inject-journal 自愈

某些框架服务端渲染文档壳层(SvelteKit、Nuxt、TanStack Start),如果直接在入口模板里塞一个原生 <script>,它不会可靠执行。因此注入并非"无脑插一段脚本":

  • 每次注入都会把写入内容记录到 .impeccable/live/inject-journal.json;下一次注入或移除操作会据此"愈合"上次因崩溃或错误目录停止而遗留的半成品。
  • 注入时会自动检测上述框架并路由到专用适配器:
    • SvelteKit:在 +layout.svelte 中生成仅开发态可用的根组件;
    • Nuxt:生成仅开发态可用的 .client.ts 插件;
    • TanStack Start:在 __root 中生成仅开发态可用的 ImpeccableLiveRoot 组件。

此时 files 字段仍然是有效的检测 / CSP 提示(参见下文 CSP 各形态中 middleware / meta-tag 的判断依赖),但不再是字面的插入位置。而普通的 TanStack Router SPA 则走基线 Vite 路径即可。

配置漂移(configDrift)

每次启动(boot)时,项目会在常见页面根目录(public/src/app/pages/)扫描 HTML 文件,凡未被已解析的 files 列表覆盖的,都会作为 configDrift.orphans 附带提示浮出。Agent 应当每会话只向用户说明一次哪些文件未被覆盖,并建议补进 files 或改用 glob——但绝不自动更新配置:是否扩大注入范围由用户决定。无漂移时 configDriftnull

首次 CSP 检测与四种形态

config.cspChecked === true 时整段跳过(说明此前已问过用户)。首次配置则运行:

node .claude/skills/impeccable/scripts/detect-csp.mjs

输出为 { shape, signals }shape 命名的是"补丁机制",而不是具体框架——因此一套模板可以覆盖许多框架。共有四种结果:

shape 含义 处理方式
null 项目没有 CSP 直接写配置 cspChecked: true,到此为止
append-arrays CSP 是结构化指令数组 可自动打补丁(monorepo helper 的 additionalScriptSrc/additionalConnectSrc、SvelteKit 的 kit.csp.directives、Nuxt 的 nuxt-security
append-string CSP 是字面值字符串 可自动打补丁(内联的 next.config.* headers()、Nuxt routeRules
middleware / meta-tag 检测到但不自动补丁 向用户展示检测到的文件,请其手动将 http://localhost:8400 加入 script-srcconnect-src,然后标记 cspChecked: true 继续

CSP 补丁前的同意征询(固定措辞)

只有用户同意才允许改文件。原文档给出了一字不差的提示措辞,Agent 应照此征询:

CSP patch needed. I detected a Content Security Policy in your project that blocks http://localhost:8400: the live picker won't load without an allowance. Here's the change I'd make:

[file: <patchTarget>]
[exact diff, 2-5 lines]

It's guarded by NODE_ENV === "development" so the extra entry only appears in dev and never reaches production. You can remove it any time by reverting this file. Apply? [y/n]

关键点在于补丁永远被 NODE_ENV === "development" 守卫,额外的放行条目只出现在开发态,永远不会进入生产构建;用户随时可以通过还原该文件移除它。

  • 用户回答 no:跳过补丁,明确告知"在放行条目被手动加入之前 Live 不会工作",但仍要写入 cspChecked: true(因为问题已经问过了,不能每次启动都纠缠用户)。
  • 用户回答 yes:按下方对应 shape 应用补丁,然后写 cspChecked: true

append-arrays:结构化指令数组补丁

在持有 CSP 数组的文件顶部声明一个仅开发态放行数组,再把 ...__impeccableLiveDev 追加进 script-srcconnect-src 数组:

// Dev-only allowance so impeccable live mode can load. Guarded by NODE_ENV.
const __impeccableLiveDev =
  process.env.NODE_ENV === "development" ? ["http://localhost:8400"] : [];

各框架落点:

  • Next.js + monorepo 共享 helper:编辑应用自身的 next.config.*(而不是共享 helper 文件),把放行项追加到 additionalScriptSrc / additionalConnectSrc
  • SvelteKit:编辑 svelte.config.js 中的 kit.csp.directives['script-src']['connect-src']
  • Nuxt + nuxt-security:编辑 nuxt.config.* 中的 security.headers.contentSecurityPolicy['script-src']['connect-src']

仓库在 tests/framework-fixtures/nextjs-turborepo/expected-after-patch.ts 中提供了 monorepo shared-helper 场景补丁完成后的参考输出。从该文件可以看到最终的期望形态:const baseConfig = createBaseNextConfig({ ..., additionalScriptSrc: [posthogHost, ...__impeccableLiveDev], additionalConnectSrc: [posthogHost, ...__impeccableLiveDev] }),即应用配置展开时把 dev 放行数组汇入共享 helper 的 CSP 数组。SvelteKit 场景的期望形态见 tests/framework-fixtures/sveltekit-csp/expected-after-patch.js

幂等性:如果文件里已存在 __impeccableLiveDev 标识符,说明补丁已应用过——此时只把 cspChecked 标记为 true 即可,无需重复插入。注意,上述 expected-after-patch.* 文件头部注释注明它们是"供 agent / 人工审阅的参考输出,不参与测试执行",即它们是行为规范快照,而非断言。

append-string:字面值字符串补丁

这是"两点式"补丁:声明一个 dev-only 字符串,把它插值进 CSP 值的两个指令处。字符串带前导空格以保证拼接干净;编辑过程中需要把字面量字符串改写为模板字符串:

// Dev-only allowance so impeccable live mode can load.
const __impeccableLiveDev =
  process.env.NODE_ENV === "development" ? " http://localhost:8400" : "";

转换示例(原文档原文):

  • script-src 'self' 'unsafe-inline' 变为 `script-src 'self' 'unsafe-inline'${__impeccableLiveDev}`
  • connect-src 'self' 变为 `connect-src 'self'${__impeccableLiveDev}`

各框架落点:

  • Next.js:内联 headers()(在 next.config.* 内);
  • Nuxtnuxt.config.*routeRules['/**'].headers['Content-Security-Policy']

仓库在 tests/framework-fixtures/nuxt-csp/expected-after-patch.ts 中给出 Nuxt 场景补丁后的完整期望配置(含将 Content-Security-Policy 改写为多行 + 拼接、并在 script-src / connect-src 尾部通过 ${__impeccableLiveDev} 插值);Next.js 内联 headers 场景见 tests/framework-fixtures/nextjs-inline-csp/expected-after-patch.js。这两个 fixture 目录还各自附带 files/ 中补丁前的真实工程文件(如 nuxt.config.tsnext.config.js),可以对照学习"改动前后"的完整差异。

middleware / meta-tag:交给用户手动

此形态只做检测与提示:把检测到的文件展示给用户,请其手动放行 http://localhost:8400,确认后写 cspChecked: true 继续。仓库的 CSP 类 fixtures(如 tests/framework-fixtures/nextjs-turborepo/tests/framework-fixtures/sveltekit-csp/tests/framework-fixtures/nuxt-csp/tests/framework-fixtures/nextjs-inline-csp/)正是从"自动可补丁"的两类形态中归纳出的真实工程样本,是判断某项目 CSP 应归入哪一 shape 的直观参照。

故障排查与收尾

  • 用户拒绝了 CSP 补丁,后来 Live 不工作:原因几乎必然是开发态 CSP 拦截了 http://localhost:8400。处理办法是从 .impeccable/live/config.json删除 cspChecked 字段并重跑 live.mjs——引导流程会再次询问(这正是该字段存在的意义:用它记住"是否已问过",删掉即可重问)。
  • 配置写入完成后:重跑 live.mjs 继续正常 Live 会话即可。

整个 setup 流程结束后,.impeccable/live/config.json 会作为项目配置持续存在(cleanup 时 live-server.mjs stop --keep-inject 不会删除它),而下一次会话若无需漂移解释、cspChecked 又在场,则不会再触发 live-setup。

小结:这套引导设计的三个关键原则

从源码结构(live.mdlive-setup.md 的分工)可以推断其设计意图:

  1. 一次性、用户拍板:注入目标的选择与 CSP 放行都属于"改变用户项目"的动作,因此配置漂移永不自动改配置、CSP 补丁必须征得同意——引导只负责把代价最小、可逆的改动精确呈现给用户。
  2. 补丁以"机制"而非"框架"归类append-arrays / append-string 把成百上千种框架的 CSP 配置收敛为两种可自动处理的模式,配合 NODE_ENV === "development" 守卫保证零生产影响,这是它能被安全自动化的前提。
  3. 自愈与可重问:inject-journal 保证注入半成品可愈合;cspChecked 使"已问过"成为可删除、可重问的状态位——一次性的引导因此既能严格触发,又不会把用户锁死在错误的早期决定上。
登录后查看全文
热门项目推荐
相关项目推荐

项目优选

收起
kernelkernel
deepin linux kernel
C
33
18
ops-transformerops-transformer
本项目是CANN提供的transformer类大模型算子库,实现网络在NPU上加速计算。
C++
1.13 K
2.75 K
pytorchpytorch
作为 Ascend for PyTorch 社区的核心组件,TorchNPU 是昇腾专为 PyTorch 打造的深度学习适配插件,使 PyTorch 框架能够直接调用昇腾 NPU,为开发者提供昇腾 AI 处理器的超强算力。
Python
857
1.35 K
docsdocs
暂无描述
Markdown
897
5.8 K
kernelkernel
openEuler内核是openEuler操作系统的核心,既是系统性能与稳定性的基石,也是连接处理器、设备与服务的桥梁。
C
529
593
ops-nnops-nn
本项目是CANN提供的神经网络类计算算子库,实现网络在NPU上加速计算。
C++
915
1.83 K
jiuwenswarmjiuwenswarm
JiuwenSwarm 是一款基于openJiuwen开发的智能AI Agent,它能够将大语言模型的强大能力,通过你日常使用的各类通讯应用,直接延伸至你的指尖。
Python
3.58 K
1.01 K
ops-mathops-math
本项目是CANN提供的数学类基础计算算子库,实现网络在NPU上加速计算。
C++
1.35 K
1.46 K
cann-learning-hubcann-learning-hub
CANN 学习中心仓,支持在线互动运行、边学边练,提供教程、示例与优化方案,一站式助力昇腾开发者快速上手。
Jupyter Notebook
1.01 K
515
AscendNPU-IRAscendNPU-IR
AscendNPU-IR是基于MLIR(Multi-Level Intermediate Representation)构建的,面向昇腾亲和算子编译时使用的中间表示,提供昇腾完备表达能力,通过编译优化提升昇腾AI处理器计算效率,支持通过生态框架使能昇腾AI处理器与深度调优
C++
547
388