auriga-cli 1.28.0 → 1.29.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -10,7 +10,7 @@ This repo itself is a fully configured harness project. You can clone it to see
10
10
 
11
11
  | Module | Description |
12
12
  |---|---|
13
- | **Workflow** | `CLAUDE.md` auriga workflow: requirement clarification -> TDD -> Review, Harness principles, Subagent usage guide |
13
+ | **Workflow** | `AGENTS.md` auriga workflow: requirement clarification -> TDD -> Review, Harness principles, Subagent usage guide |
14
14
  | **Skills** | External development process skills — systematic-debugging, TDD, verification, planning, playwright (spec authoring and architecture design ship as the `spec-design` and `arch-design` skills inside the `auriga-workflow` plugin) |
15
15
  | **Recommended Skills** | Optional utility skills (e.g. `codex-agent`, `claude-code-agent`) you can add on top of the workflow skills |
16
16
  | **Plugins** | Recommended Claude Code and Codex plugins — skill-creator, claude-md-management, playground, codex, auriga-workflow, auriga-notify, session-instructions-loader |
@@ -40,9 +40,9 @@ The leading `-y` belongs to `npx` (it auto-confirms package installation), **not
40
40
  Non-interactive install commands:
41
41
 
42
42
  ```bash
43
- npx -y auriga-cli install --preset # curated workflow core: CLAUDE.md/AGENTS.md
43
+ npx -y auriga-cli install --preset # curated workflow core: AGENTS.md/CLAUDE.md
44
44
  # + workflow skills + auriga-workflow plugin
45
- # (defaults: scope user, agent both, lang en)
45
+ # (defaults: scope user, agent both, lang zh-CN)
46
46
  npx -y auriga-cli install --all # everything: workflow + skills + recommended + plugins
47
47
  npx -y auriga-cli install recommended # just the opt-in utility skills
48
48
  npx -y auriga-cli install plugins --agent codex --plugin session-instructions-loader
@@ -50,9 +50,9 @@ npx -y auriga-cli install <type> [--flags] # one of: workflow | skills | recom
50
50
  npx -y auriga-cli --help # full catalog + flags
51
51
  ```
52
52
 
53
- `--preset` is atomic — it cannot be combined with a `<type>` or any filter flag, but it accepts `--scope`, `--agent`, and `--lang` (preset defaults: `user` / `both` / `en`, which differ from the per-category defaults).
53
+ `--preset` is atomic — it cannot be combined with a `<type>` or any filter flag, but it accepts `--scope`, `--agent`, and `--lang` (preset defaults: `user` / `both` / `zh-CN`, which differ from the per-category defaults).
54
54
 
55
- Exit codes: `0` success, `1` fatal (precheck / parse / fetch), `2` partial success — `stderr` lists per-category `[OK]/[FAIL]` and a `Retry:` hint. After install, reload the Claude Code or Codex session so the new `CLAUDE.md` / skills / plugins / hook-plugin registrations are picked up.
55
+ Exit codes: `0` success, `1` fatal (precheck / parse / fetch), `2` partial success — `stderr` lists per-category `[OK]/[FAIL]` and a `Retry:` hint. After install, reload the Claude Code or Codex session so the new `AGENTS.md` / skills / plugins / hook-plugin registrations are picked up.
56
56
 
57
57
  ### Web UI (opt-in)
58
58
 
@@ -76,21 +76,21 @@ Interactive menu — select what to install:
76
76
 
77
77
  ```
78
78
  ? Select what to install:
79
- ◉ Recommended preset — CLAUDE.md/AGENTS.md + workflow skills + auriga-workflow plugin
79
+ ◉ Recommended preset — AGENTS.md/CLAUDE.md + workflow skills + auriga-workflow plugin
80
80
  ◯ Optional skills — opt-in utility skills (claude-code-agent, codex-agent...)
81
81
  ◯ Other plugins — everything except auriga-workflow (auriga-notify, skill-creator, codex...)
82
82
  ```
83
83
 
84
- The **Recommended preset** is checked by default and installs silently with the preset defaults (scope `user`, agent `both`, language `en`) — to fine-tune those, use the non-interactive `install --preset` flags. The other two items drill down into a per-item sub-selection. Plugin installation also asks which runtime to target: Claude Code, Codex, or both.
84
+ The **Recommended preset** is checked by default and installs silently with the preset defaults (scope `user`, agent `both`, language `zh-CN`) — to fine-tune those, use the non-interactive `install --preset` flags. The other two items drill down into a per-item sub-selection. Plugin installation also asks which runtime to target: Claude Code, Codex, or both.
85
85
 
86
86
  ## Module Details
87
87
 
88
88
  ### Workflow
89
89
 
90
- Installs `CLAUDE.md` into the target project and creates an `AGENTS.md` symlink for compatibility with different Agent frameworks. Supports English and Chinese you choose during installation.
90
+ Installs `AGENTS.md` into the target project and creates a `CLAUDE.md` symlink for Claude Code compatibility. Chinese is the default; English remains available with `--lang en`.
91
91
 
92
92
  - **Extensible and upgradable**: the auriga workflow ships inside a managed block delimited by `<!-- AURIGA:WORKFLOW:v1 START/END -->` markers. Add your project-specific instructions *after* the END marker — re-running install upgrades the managed block in place and leaves your section untouched.
93
- - A pre-marker `CLAUDE.md` (installed by an older version) is migrated to the marked format on the next install, with the old file backed up to `CLAUDE.md.bak`. A foreign `CLAUDE.md` from another tool is kept as your user section below a fresh managed block.
93
+ - A pre-marker `CLAUDE.md` (installed by an older version) is safely migrated into the new `AGENTS.md` primary shape on the next install, with the old file backed up to `CLAUDE.md.bak`. A foreign `AGENTS.md` or `CLAUDE.md` from another tool is kept as your user section below a fresh managed block.
94
94
  - Covers: requirement clarification, TDD, code review, branch workflow, subagent orchestration
95
95
 
96
96
  ### Skills
@@ -134,7 +134,7 @@ npx -y auriga-cli install plugins --agent codex --plugin session-instructions-lo
134
134
  | Plugin | Runtime | Description |
135
135
  |---|---|---|
136
136
  | skill-creator | Claude Code | Create and manage custom skills |
137
- | claude-md-management | Claude Code / Codex | Audit and improve CLAUDE.md |
137
+ | claude-md-management | Claude Code / Codex | Audit and improve AGENTS.md / CLAUDE.md |
138
138
  | playground | Claude Code / Codex | Build interactive HTML playgrounds |
139
139
  | codex | Claude Code | Codex cross-model collaboration |
140
140
  | auriga-workflow | Claude Code / Codex | The auriga workflow plugin — workflow skills plus the git lifecycle hooks that enforce them. Skills: `incremental-impl`, `test-designer`, `spec-design`, `arch-design`, `code-simplify`, `session-compound`, `goalify` (plans an autonomous goal and dispatches it via the built-in `/goal` command), `deep-review` (multi-dimensional PR review orchestrator — parallel per-dimension reviewers synthesized into an actionable punch list), `reviewer-creator` (scaffolds project-level custom reviewers under `docs/rules/review/`), and `git-workflow` (git lifecycle skill). Hooks: `commit-reminder` (PostToolUse on file edits — `Edit` / `Write` / `MultiEdit` in Claude Code, `apply_patch` in Codex — nudges to commit at the next semantic boundary when uncommitted diff vs `HEAD` exceeds 200 lines or 8 files), `pr-create-guard` (PostToolUse on `gh pr create` → injects a PR-body snapshot for five-element self-verification and flags non-Conventional-Commits titles), `pr-ready-guard` (PreToolUse on `gh pr ready` and non-draft `gh pr create` → blocks on stray planning docs, unfinalized active specs under `docs/specs/`, or unpushed commits), and `pr-merge-guard` (PreToolUse on `gh pr merge` → blocks while the PR body's Acceptance criteria section still has unchecked checklist items). The two PostToolUse hooks reach full Claude Code / Codex parity; Codex currently fails open on `pr-ready-guard`'s PreToolUse `additionalContext` informational path (block path identical). Installed by default through the plugin path. |
package/README.zh-CN.md CHANGED
@@ -10,7 +10,7 @@
10
10
 
11
11
  | 模块 | 说明 |
12
12
  |---|---|
13
- | **Workflow** | `CLAUDE.md` 里的 auriga 工作流:需求澄清 → TDD → Review,Harness 原则,Subagent 使用指南 |
13
+ | **Workflow** | `AGENTS.md` 里的 auriga 工作流:需求澄清 → TDD → Review,Harness 原则,Subagent 使用指南 |
14
14
  | **Skills** | 外部开发流程 skills —— systematic-debugging、TDD、verification、planning、playwright(spec 撰写与架构设计由 `auriga-workflow` 插件内的 `spec-design`、`arch-design` skill 提供)|
15
15
  | **Recommended Skills** | 可选的工具类 skills(如 `codex-agent`、`claude-code-agent`),在 workflow skills 之外按需追加 |
16
16
  | **Plugins** | 推荐的 Claude Code 和 Codex 插件 —— skill-creator、claude-md-management、playground、codex、auriga-workflow、auriga-notify、session-instructions-loader |
@@ -40,9 +40,9 @@ npx -y auriga-cli guide
40
40
  非交互安装命令:
41
41
 
42
42
  ```bash
43
- npx -y auriga-cli install --preset # 工作流核心:CLAUDE.md/AGENTS.md
43
+ npx -y auriga-cli install --preset # 工作流核心:AGENTS.md/CLAUDE.md
44
44
  # + 工作流 skill + auriga-workflow 插件
45
- # (默认:scope user、agent both、lang en)
45
+ # (默认:scope user、agent both、lang zh-CN)
46
46
  npx -y auriga-cli install --all # 全装:workflow + skills + recommended + plugins
47
47
  npx -y auriga-cli install recommended # 只装可选工具 skills
48
48
  npx -y auriga-cli install plugins --agent codex --plugin session-instructions-loader
@@ -50,9 +50,9 @@ npx -y auriga-cli install <type> [--flags] # 单类:workflow | skills | recomm
50
50
  npx -y auriga-cli --help # 完整 catalog + flag 说明
51
51
  ```
52
52
 
53
- `--preset` 是原子标志 —— 不能与 `<type>` 或任何过滤标志同时使用,但可带 `--scope`、`--agent`、`--lang`(预设默认 `user` / `both` / `en`,与分类安装的默认不同)。
53
+ `--preset` 是原子标志 —— 不能与 `<type>` 或任何过滤标志同时使用,但可带 `--scope`、`--agent`、`--lang`(预设默认 `user` / `both` / `zh-CN`,与分类安装的默认不同)。
54
54
 
55
- 退出码:`0` 成功;`1` 致命错误(前置检查 / 解析 / 拉取失败);`2` 部分成功——`stderr` 会列出逐类 `[OK]/[FAIL]` 和 `Retry:` 提示。装完后请重启 Claude Code 或 Codex 会话,让新的 `CLAUDE.md` / skills / plugins / hook 插件注册生效。
55
+ 退出码:`0` 成功;`1` 致命错误(前置检查 / 解析 / 拉取失败);`2` 部分成功——`stderr` 会列出逐类 `[OK]/[FAIL]` 和 `Retry:` 提示。装完后请重启 Claude Code 或 Codex 会话,让新的 `AGENTS.md` / skills / plugins / hook 插件注册生效。
56
56
 
57
57
  ### Web UI(可选)
58
58
 
@@ -76,21 +76,21 @@ npx auriga-cli
76
76
 
77
77
  ```
78
78
  ? Select what to install:
79
- ◉ Recommended preset — CLAUDE.md/AGENTS.md + workflow skills + auriga-workflow plugin
79
+ ◉ Recommended preset — AGENTS.md/CLAUDE.md + workflow skills + auriga-workflow plugin
80
80
  ◯ Optional skills — opt-in utility skills (claude-code-agent, codex-agent...)
81
81
  ◯ Other plugins — everything except auriga-workflow (auriga-notify, skill-creator, codex...)
82
82
  ```
83
83
 
84
- **Recommended preset** 默认勾选,以预设默认值静默安装(scope `user`、agent `both`、语言 `en`)—— 要精调这些参数,改用非交互的 `install --preset` 标志。另两项会下钻到逐项子勾选。安装插件时还会先选择目标运行时:Claude Code、Codex 或两者都装。
84
+ **Recommended preset** 默认勾选,以预设默认值静默安装(scope `user`、agent `both`、语言 `zh-CN`)—— 要精调这些参数,改用非交互的 `install --preset` 标志。另两项会下钻到逐项子勾选。安装插件时还会先选择目标运行时:Claude Code、Codex 或两者都装。
85
85
 
86
86
  ## 模块详情
87
87
 
88
88
  ### Workflow
89
89
 
90
- 将 `CLAUDE.md` 安装到目标项目,并创建 `AGENTS.md` 软链接以兼容不同 Agent 框架。支持中英文版本,安装时可选择。
90
+ 将 `AGENTS.md` 安装到目标项目,并创建 `CLAUDE.md` 软链接以兼容 Claude Code。默认安装中文版本,英文可通过 `--lang en` 显式选择。
91
91
 
92
92
  - **可扩展、可升级**:auriga 工作流被一对 `<!-- AURIGA:WORKFLOW:v1 START/END -->` 标记包成「受管区块」。把你的工程专属规则写在 END 标记**之后**——再次安装只就地升级受管区块,你的内容原样保留。
93
- - 旧版本装下的、无标记的 `CLAUDE.md` 会在下次安装时迁移为标记格式,旧文件备份到 `CLAUDE.md.bak`。别的工具生成的 `CLAUDE.md` 会作为用户区保留在全新受管区块下方。
93
+ - 旧版本装下的、无标记的 `CLAUDE.md` 会在下次安装时安全迁移到新的 `AGENTS.md` 主文件形态,旧文件备份到 `CLAUDE.md.bak`。别的工具生成的 `AGENTS.md` 或 `CLAUDE.md` 会作为用户区保留在全新受管区块下方。
94
94
  - 涵盖:需求澄清、TDD、代码 Review、分支工作流、Subagent 编排
95
95
 
96
96
  ### Skills
@@ -134,7 +134,7 @@ npx -y auriga-cli install plugins --agent codex --plugin session-instructions-lo
134
134
  | 插件 | 运行时 | 说明 |
135
135
  |---|---|---|
136
136
  | skill-creator | Claude Code | 创建和管理自定义 skills |
137
- | claude-md-management | Claude Code / Codex | 审计和改进 CLAUDE.md |
137
+ | claude-md-management | Claude Code / Codex | 审计和改进 AGENTS.md / CLAUDE.md |
138
138
  | playground | Claude Code / Codex | 构建交互式 HTML playground |
139
139
  | codex | Claude Code | Codex 跨模型协作 |
140
140
  | auriga-workflow | Claude Code / Codex | auriga 工作流插件 —— 工作流 skill 加上强制执行工作流的 git 生命周期 hook。Skills:`incremental-impl`、`test-designer`、`spec-design`、`arch-design`、`code-simplify`、`session-compound`、`goalify`(plan 出自驱 goal 并通过内置 `/goal` 命令分发执行)、`deep-review`(多维度 PR review 编排器——并行派发各维度 reviewer,汇总成可执行的 punch list)、`reviewer-creator`(在 `docs/rules/review/` 下生成项目级自定义 reviewer)、`git-workflow`(git 生命周期 skill)。Hooks:`commit-reminder`(文件编辑的 PostToolUse —— Claude Code 匹配 `Edit` / `Write` / `MultiEdit`,Codex 匹配 `apply_patch` —— 未提交 diff 对比 `HEAD` 超过 200 行或 8 个文件时,提醒在下一个语义边界 commit)、`pr-create-guard`(`gh pr create` 的 PostToolUse —— 注入 PR body 快照供五要素自检,并对不符合 Conventional Commits 的标题提示)、`pr-ready-guard`(`gh pr ready` 与非 draft `gh pr create` 的 PreToolUse —— 拦截游离规划文档、`docs/specs/` 内未结案的活跃 spec、未 push commits)、`pr-merge-guard`(`gh pr merge` 的 PreToolUse —— PR body 的验收标准章节仍有未勾选清单项时拦截合并)。两个 PostToolUse hook 在 Claude Code / Codex 上完全对齐;Codex 仅对 `pr-ready-guard` 的 PreToolUse `additionalContext` 信息路径 fail-open(block 路径两边一致)。默认通过插件路径安装。 |
@@ -71,11 +71,11 @@ export interface PluginState {
71
71
  }
72
72
  export interface StateWarning {
73
73
  code: "claude-cli-missing" | "codex-cli-missing" | "marketplace-offline" | "claude-code-not-installed" | "settings-unreadable" | "skill-malformed"
74
- /** Project-scope CLAUDE.md (or the user-scope fallback when scanning
75
- * user scope) is present but has no recognizable `# auriga Workflow (vX.Y.Z)`
76
- * header. The row reports `not-installed`; install will back up the
77
- * existing file to `CLAUDE.md.bak` and write ours. */
78
- | "workflow-foreign-claudemd";
74
+ /** Workflow instruction file is present but has no recognizable
75
+ * `# auriga Workflow (vX.Y.Z)` header. The row reports `not-installed`;
76
+ * install keeps the existing content in the user region before writing
77
+ * ours. */
78
+ | "workflow-foreign-agentsmd" | "workflow-foreign-claudemd";
79
79
  message: string;
80
80
  }
81
81
  export type ApplyCategory = "workflow" | "skill" | "recommended-skill" | "plugin"
@@ -93,10 +93,10 @@ export type ApplyAction = "install" | "uninstall";
93
93
  */
94
94
  export type ApplyScope = "project" | "user";
95
95
  /**
96
- * Workflow CLAUDE.md language variant.
96
+ * Workflow AGENTS.md language variant.
97
97
  *
98
- * - "en": English CLAUDE.md (the default).
99
- * - "zh-CN": Simplified Chinese CLAUDE.md (the localized variant).
98
+ * - "zh-CN": Simplified Chinese AGENTS.md (the default).
99
+ * - "en": English AGENTS.en.md.
100
100
  *
101
101
  * Only meaningful for `category === "workflow"`; rejected for other
102
102
  * categories so the API surface stays explicit.
@@ -120,7 +120,7 @@ export interface ApplyItemRef {
120
120
  * server rejects this field for category="workflow" because workflow
121
121
  * has no scope concept (it's a single file at the project root). */
122
122
  scope?: ApplyScope;
123
- /** Workflow CLAUDE.md language variant. Omitted = "en" (back-compat
123
+ /** Workflow AGENTS.md language variant. Omitted = "zh-CN"
124
124
  * default). The server accepts this field only for category="workflow"
125
125
  * and category="preset" (the preset installs the workflow doc). */
126
126
  lang?: ApplyLang;
@@ -11,7 +11,7 @@ export interface ApplyHandlerContext {
11
11
  * and the handler iterates the list, installing to each agent in turn.
12
12
  * Names not in the map default to `["claude"]` (existing CLI default). */
13
13
  pluginAgentsByName: Map<string, ("claude" | "codex")[]>;
14
- /** Workflow language for install. Defaults to "en". */
14
+ /** Workflow language for install. Defaults to "zh-CN". */
15
15
  workflowLang?: ApplyLang;
16
16
  }
17
17
  export declare function buildDefaultApplyHandlers(ctx: ApplyHandlerContext): ApplyHandlers;
@@ -23,6 +23,7 @@
23
23
  import { installPlugins, uninstallPlugin, } from "./plugins.js";
24
24
  import { installPreset } from "./preset.js";
25
25
  import { installRecommendedSkills, installSkills, uninstallSkill, } from "./skills.js";
26
+ import { DEFAULT_WORKFLOW_LANG } from "./utils.js";
26
27
  import { installWorkflow, uninstallWorkflow } from "./workflow.js";
27
28
  const ALL_ACTIONS = new Set([
28
29
  "install",
@@ -37,7 +38,7 @@ function assertAction(action) {
37
38
  }
38
39
  export function buildDefaultApplyHandlers(ctx) {
39
40
  const { packageRoot, cwd, pluginAgentsByName } = ctx;
40
- const lang = ctx.workflowLang ?? "en";
41
+ const lang = ctx.workflowLang ?? DEFAULT_WORKFLOW_LANG;
41
42
  const workflow = async (action, _name, { onLog, lang: requestedLang }) => {
42
43
  assertAction(action);
43
44
  // Per-item lang overrides the ctx default (the UI now drives this via
@@ -155,7 +156,7 @@ export function buildDefaultApplyHandlers(ctx) {
155
156
  // The preset is a single apply item that drives the whole installPreset
156
157
  // orchestration. scope / agent / lang come from the Dashboard's preset
157
158
  // controls; omitted values fall back to the preset defaults
158
- // (user / both / en). Uninstall is not a preset operation.
159
+ // (user / both / zh-CN). Uninstall is not a preset operation.
159
160
  const preset = async (action, _name, { onLog, scope, lang: requestedLang, agent }) => {
160
161
  assertAction(action);
161
162
  if (action !== "install") {
package/dist/catalog.json CHANGED
@@ -1,5 +1,5 @@
1
1
  {
2
- "generatedAt": "2026-05-16T10:40:59.234Z",
2
+ "generatedAt": "2026-05-16T13:16:49.448Z",
3
3
  "workflowSkills": [
4
4
  {
5
5
  "name": "planning-with-files",
@@ -78,7 +78,7 @@
78
78
  },
79
79
  {
80
80
  "name": "claude-md-management",
81
- "description": "(Claude/Codex) Audit and improve CLAUDE.md files",
81
+ "description": "(Claude/Codex) Audit and improve AGENTS.md / CLAUDE.md files",
82
82
  "agents": [
83
83
  "claude",
84
84
  "codex"
package/dist/cli.d.ts CHANGED
@@ -49,7 +49,7 @@ type LegacyMenuValue = "preset" | "recommended" | "plugins";
49
49
  *
50
50
  * Workflow + Skills are absorbed by the「推荐预设」item.
51
51
  * The preset label spells out the silent defaults (scope user / agent
52
- * both / lang en) so a TTY user knows what they're getting — fine-tuning
52
+ * both / lang zh-CN) so a TTY user knows what they're getting — fine-tuning
53
53
  * those goes through the non-interactive `install --preset` flags.
54
54
  */
55
55
  export declare const LEGACY_MENU_CHOICES: ReadonlyArray<{
package/dist/cli.js CHANGED
@@ -2,7 +2,7 @@
2
2
  import fs from "node:fs";
3
3
  import path from "node:path";
4
4
  import { fileURLToPath } from "node:url";
5
- import { exec, fetchContentRoot, getPackageRoot, isNonInteractive, LANGUAGES, log, readPackageVersion, } from "./utils.js";
5
+ import { exec, DEFAULT_WORKFLOW_LANG, fetchContentRoot, getPackageRoot, isNonInteractive, LANGUAGES, log, readPackageVersion, } from "./utils.js";
6
6
  import { installWorkflow } from "./workflow.js";
7
7
  import { installSkills, installRecommendedSkills } from "./skills.js";
8
8
  import { installPlugins } from "./plugins.js";
@@ -11,7 +11,7 @@ import { loadCatalog } from "./catalog.js";
11
11
  import { renderHelp, renderTypeHelp } from "./help.js";
12
12
  import { renderGuide } from "./guide.js";
13
13
  import { CATEGORY_NAMES } from "./types.js";
14
- const RELOAD_REMINDER = "\n⚠ Reload your Claude Code or Codex session to pick up the new harness (CLAUDE.md / skills / plugins are loaded at session startup).\n";
14
+ const RELOAD_REMINDER = "\n⚠ Reload your Claude Code or Codex session to pick up the new harness (AGENTS.md / skills / plugins are loaded at session startup).\n";
15
15
  const CATEGORY_SET = new Set(CATEGORY_NAMES);
16
16
  const TYPE_FOR_FILTER = {
17
17
  "--skill": "skills",
@@ -259,7 +259,7 @@ function validateInstall(out, filterFlag) {
259
259
  // (workflow doc + workflow skills + auriga-workflow plugin) and cannot
260
260
  // combine with a <type>, a sub-item filter, or --all. Unlike a category
261
261
  // install it DOES accept --scope / --agent / --lang as preset modifiers
262
- // (the preset defaults differ: user / both / en). --cwd is not a preset
262
+ // (the preset defaults differ: user / both / zh-CN). --cwd is not a preset
263
263
  // modifier — the workflow doc always lands in the current directory.
264
264
  if (out.preset) {
265
265
  if (out.all) {
@@ -475,7 +475,7 @@ async function runInstall(p) {
475
475
  * succeed → 0; any step fails → 2 with per-step status on stderr.
476
476
  *
477
477
  * The preset defaults differ from a category install — scope=user,
478
- * agent=both, lang=en — and are resolved here before handing off, so
478
+ * agent=both, lang=zh-CN — and are resolved here before handing off, so
479
479
  * `installPreset` itself stays default-free (the TUI / Web UI callers
480
480
  * resolve their own defaults the same way).
481
481
  */
@@ -489,7 +489,7 @@ async function runPreset(p) {
489
489
  interactive: false,
490
490
  scope: p.scope ?? "user",
491
491
  agent,
492
- lang: p.lang ?? "en",
492
+ lang: p.lang ?? DEFAULT_WORKFLOW_LANG,
493
493
  });
494
494
  for (const r of results) {
495
495
  if (r.ok) {
@@ -507,7 +507,14 @@ async function runPreset(p) {
507
507
  // The preset is one atomic "install the right defaults" action — the
508
508
  // retry is the whole command again, not a per-category fan-out like
509
509
  // runAll's hint.
510
- process.stderr.write("\nRetry:\n npx -y auriga-cli install --preset\n");
510
+ const retryArgs = ["install", "--preset"];
511
+ if (p.scope)
512
+ retryArgs.push("--scope", p.scope);
513
+ if (p.agent)
514
+ retryArgs.push("--agent", p.agent);
515
+ if (p.lang)
516
+ retryArgs.push("--lang", p.lang);
517
+ process.stderr.write(`\nRetry:\n npx -y auriga-cli ${retryArgs.join(" ")}\n`);
511
518
  if (failed.length < results.length) {
512
519
  process.stderr.write(RELOAD_REMINDER);
513
520
  }
@@ -619,7 +626,7 @@ async function runAll(p) {
619
626
  process.stderr.write(` npx -y auriga-cli install ${s.category}${suffix}\n`);
620
627
  }
621
628
  // Partial success still installed assets that need a session reload
622
- // (CLAUDE.md / skills / plugins load at startup). Without this hint
629
+ // (AGENTS.md / skills / plugins load at startup). Without this hint
623
630
  // the user may retry the failed category and act on stale state.
624
631
  if (failed.length < status.length) {
625
632
  process.stderr.write(RELOAD_REMINDER);
@@ -686,7 +693,7 @@ async function runUi(p, version) {
686
693
  // - tarballRoot: where `dist/catalog.json` + the bundled DEV ui/dist live.
687
694
  // Always read from the installed npm package; can't be fetched because
688
695
  // dist/ is built artifact, not git content.
689
- // - contentRoot: where the runtime install recipes live (CLAUDE.md,
696
+ // - contentRoot: where the runtime install recipes live (AGENTS.md,
690
697
  // marketplace manifests, extra_plugin_configs.json, skills-lock.json).
691
698
  // These files are
692
699
  // NOT in the npm tarball — the `files` allowlist only ships `dist/*`
@@ -750,7 +757,7 @@ async function runUi(p, version) {
750
757
  return 1;
751
758
  }
752
759
  const applyCatalog = {
753
- // Workflow is a singleton (one CLAUDE.md per project); we pick the
760
+ // Workflow is a singleton (one AGENTS.md per project); we pick the
754
761
  // sentinel name "workflow" to match what the Web UI's Dashboard sends
755
762
  // and to remain semantically self-describing. The handler ignores the
756
763
  // name argument either way.
@@ -767,7 +774,7 @@ async function runUi(p, version) {
767
774
  pluginAgentsByName.set(name, def.agents);
768
775
  }
769
776
  const applyHandlers = buildDefaultApplyHandlers({
770
- // contentRoot: install handlers read CLAUDE.md, marketplace manifests,
777
+ // contentRoot: install handlers read AGENTS.md, marketplace manifests,
771
778
  // extra_plugin_configs.json, and skills-lock.json — all CONTENT_FILES.
772
779
  // Routing them at tarballRoot fails ENOENT for npm-installed users.
773
780
  packageRoot: contentRoot,
@@ -793,7 +800,7 @@ async function runUi(p, version) {
793
800
  cwd,
794
801
  // server reads dist/catalog.json (tarball-shipped) via
795
802
  // buildScanCatalog on each /api/state call; install-time content
796
- // (marketplace manifests, extra plugin config, CLAUDE.md, …) was already injected
803
+ // (marketplace manifests, extra plugin config, AGENTS.md, …) was already injected
797
804
  // into applyHandlers above with contentRoot.
798
805
  packageRoot: tarballRoot,
799
806
  heartbeatTimeoutMs: UI_HEARTBEAT_TIMEOUT_MS,
@@ -878,13 +885,13 @@ function highlight(text) {
878
885
  *
879
886
  * Workflow + Skills are absorbed by the「推荐预设」item.
880
887
  * The preset label spells out the silent defaults (scope user / agent
881
- * both / lang en) so a TTY user knows what they're getting — fine-tuning
888
+ * both / lang zh-CN) so a TTY user knows what they're getting — fine-tuning
882
889
  * those goes through the non-interactive `install --preset` flags.
883
890
  */
884
891
  export const LEGACY_MENU_CHOICES = [
885
892
  {
886
893
  value: "preset",
887
- name: "Recommended preset — CLAUDE.md/AGENTS.md + workflow skills + auriga-workflow plugin (scope user · agent both · lang en)",
894
+ name: "Recommended preset — AGENTS.md/CLAUDE.md + workflow skills + auriga-workflow plugin (scope user · agent both · lang zh-CN)",
888
895
  checked: true,
889
896
  },
890
897
  {
@@ -928,7 +935,7 @@ async function runLegacyMenu() {
928
935
  return 0;
929
936
  }
930
937
  // 「推荐预设」silently uses the preset defaults (scope user / agent
931
- // both / lang en) — it does not prompt for them. The other two items
938
+ // both / lang zh-CN) — it does not prompt for them. The other two items
932
939
  // drill down into their category's per-item sub-selection as before.
933
940
  if (picks.includes("preset")) {
934
941
  console.log("\n--- Recommended preset ---\n");
@@ -936,7 +943,7 @@ async function runLegacyMenu() {
936
943
  interactive: true,
937
944
  scope: "user",
938
945
  agent: "both",
939
- lang: "en",
946
+ lang: DEFAULT_WORKFLOW_LANG,
940
947
  });
941
948
  }
942
949
  if (picks.includes("recommended")) {
package/dist/guide.js CHANGED
@@ -20,7 +20,7 @@ export function renderGuide(opts) {
20
20
  return `${h(`# auriga-cli bootstrap SOP (v${opts.version})`)}
21
21
 
22
22
  This guide walks an Agent through installing the auriga harness
23
- (CLAUDE.md + skills + plugins) into the current repository.
23
+ (AGENTS.md + skills + plugins) into the current repository.
24
24
 
25
25
  Run each step in order. If any step fails with exit 1, stop and report.
26
26
  If exit 2, see stderr for per-category status and follow the "Retry"
@@ -61,9 +61,10 @@ Per-type detail (flags + only that category's catalog slice):
61
61
 
62
62
  ${h("## Step 3 — Install")}
63
63
 
64
- Recommended — the curated workflow preset (CLAUDE.md/AGENTS.md +
64
+ Recommended — the curated workflow preset (AGENTS.md/CLAUDE.md +
65
65
  workflow skills + the auriga-workflow plugin). Defaults: scope user,
66
- agent both (Claude Code + Codex), lang en:
66
+ agent both (Claude Code + Codex), lang zh-CN. Scope applies to skills
67
+ and plugins; the workflow doc always writes to the current project:
67
68
  ${cmd("npx -y auriga-cli install --preset")}
68
69
 
69
70
  Everything — workflow + skills + recommended skills + default plugins:
@@ -96,7 +97,7 @@ Exit codes:
96
97
 
97
98
  ${h("## Step 4 — Reload session (REQUIRED when installed non-interactively)")}
98
99
 
99
- ${warn("⚠")} CLAUDE.md, .agents/skills/, and plugin enablement /
100
+ ${warn("⚠")} AGENTS.md, .agents/skills/, and plugin enablement /
100
101
  registrations are loaded at session startup. If you ran
101
102
  \`npx -y auriga-cli install\` inside an existing Claude Code or Codex session
102
103
  (e.g., \`claude -p\` / \`claude -p --worktree\` / \`codex exec\`), the current session
@@ -110,8 +111,8 @@ Action:
110
111
  ${h("## Step 5 — Verify install")}
111
112
 
112
113
  Expected artifacts/checks:
113
- - CLAUDE.md (workflow manifesto)
114
- - AGENTS.md -> CLAUDE.md (symlink)
114
+ - AGENTS.md (workflow manifesto, Chinese by default)
115
+ - CLAUDE.md -> AGENTS.md (Claude Code compatibility symlink)
115
116
  - .agents/skills/<name>/ (one per installed skill)
116
117
  - claude plugins list (shows Claude plugins, if Claude plugins selected)
117
118
  - ~/.codex/config.toml (Codex plugin enablement, if Codex plugins selected)
package/dist/help.js CHANGED
@@ -13,7 +13,8 @@ USAGE
13
13
  npx auriga-cli install --preset [--scope <s>] [--agent <a>] [--lang <code>]
14
14
  curated default set: workflow doc
15
15
  + workflow skills + auriga-workflow plugin
16
- (defaults: scope user, agent both, lang en)
16
+ (defaults: scope user, agent both, lang zh-CN)
17
+ scope applies to skills/plugins; workflow writes current project
17
18
  npx auriga-cli install --all [--scope <s>] [--agent <a>]
18
19
  everything: workflow + skills
19
20
  + recommended + plugins
@@ -28,13 +29,13 @@ USAGE
28
29
  npx -y auriga-cli install --preset
29
30
 
30
31
  TYPES (exactly one with <type> form)
31
- workflow CLAUDE.md + AGENTS.md (workflow manifesto)
32
+ workflow AGENTS.md + CLAUDE.md symlink (workflow manifesto)
32
33
  skills Default-on workflow skills (listed below)
33
34
  recommended Opt-in utility skills (listed below)
34
35
  plugins Claude Code and Codex plugins (listed below)
35
36
 
36
37
  TYPE-SPECIFIC FLAGS
37
- workflow: --lang <code> default en; available: en, zh-CN
38
+ workflow: --lang <code> default zh-CN; available: zh-CN, en
38
39
  --cwd <dir> default current working directory
39
40
  skills: --skill <names...> space-separated; '*' = all
40
41
  --scope <project|user> default project
@@ -80,11 +81,11 @@ USAGE
80
81
  npx auriga-cli install workflow [--lang <code>] [--cwd <dir>]
81
82
 
82
83
  FLAGS
83
- --lang <code> default en; available: en, zh-CN
84
+ --lang <code> default zh-CN; available: zh-CN, en
84
85
  --cwd <dir> default current working directory
85
86
 
86
87
  NOTE
87
- workflow has no --scope flag (single file + AGENTS.md symlink).
88
+ workflow has no --scope flag (AGENTS.md primary + CLAUDE.md symlink).
88
89
  `;
89
90
  case "skills":
90
91
  return `${header}
package/dist/preset.d.ts CHANGED
@@ -6,7 +6,7 @@ import type { PluginAgent } from "./utils.js";
6
6
  */
7
7
  export declare const PRESET_PLUGINS: readonly ["auriga-workflow"];
8
8
  /**
9
- * installPreset 的输入。三个默认值(scope=user / agent=both / lang=en)
9
+ * installPreset 的输入。三个默认值(scope=user / agent=both / lang=zh-CN)
10
10
  * 与分类安装不同,由调用方负责落定后再传入 —— 预设的默认不在本函数内
11
11
  * 兜底,使「默认值是什么」对每个调用端都显式可见。
12
12
  */
package/dist/preset.js CHANGED
@@ -3,7 +3,7 @@
3
3
  // installPreset —— 「推荐预设安装」的单一编排入口。
4
4
  //
5
5
  // 预设由三部分组成,按下面的顺序安装:
6
- // 1. workflow 文档 (CLAUDE.md + AGENTS.md)
6
+ // 1. workflow 文档 (AGENTS.md + CLAUDE.md 兼容软链)
7
7
  // 2. 工作流 skill (WORKFLOW_SKILLS 全集 —— installSkills 自身已限定)
8
8
  // 3. auriga-workflow 插件
9
9
  //
package/dist/server.d.ts CHANGED
@@ -5,8 +5,8 @@ export interface ApplyHandlerOptions {
5
5
  * translate into the per-installer flag (`--scope project|user`). The
6
6
  * workflow handler ignores it (workflow has no scope concept). */
7
7
  scope?: "project" | "user";
8
- /** Workflow CLAUDE.md language variant. Meaningful for the workflow and
9
- * preset handlers; other handlers ignore it. Omitted = "en". */
8
+ /** Workflow AGENTS.md language variant. Meaningful for the workflow and
9
+ * preset handlers; other handlers ignore it. Omitted = "zh-CN". */
10
10
  lang?: "en" | "zh-CN";
11
11
  /** Preset install runtime. Only meaningful for the preset handler;
12
12
  * other handlers ignore it. Omitted = "both". */
package/dist/skills.js CHANGED
@@ -3,7 +3,7 @@ import os from "node:os";
3
3
  import path from "node:path";
4
4
  import { checkbox, select } from "@inquirer/prompts";
5
5
  import { atomicWriteFile, exec, execAsync, log, withEsc } from "./utils.js";
6
- // Curated default-on set: skills that the workflow in the root CLAUDE.md
6
+ // Curated default-on set: skills that the workflow in the root AGENTS.md
7
7
  // directly references. Anything else in skills-lock.json is surfaced via
8
8
  // installRecommendedSkills as an opt-in utility.
9
9
  export const WORKFLOW_SKILLS = [
package/dist/state.js CHANGED
@@ -3,7 +3,8 @@
3
3
  // own dev-repo layout. The truth sources:
4
4
  //
5
5
  // Workflow: ~/.claude/CLAUDE.md (user scope)
6
- // <proj>/CLAUDE.md (project scope)
6
+ // <proj>/AGENTS.md (project scope primary)
7
+ // <proj>/CLAUDE.md (project scope legacy fallback)
7
8
  // Skills: ~/.claude/skills/<name>/SKILL.md (user scope)
8
9
  // <proj>/.claude/skills/<name>/SKILL.md (project scope)
9
10
  // Plugins(Claude): execPluginList(scope) + settings.json enabledPlugins
@@ -25,6 +26,7 @@ import os from "node:os";
25
26
  import path from "node:path";
26
27
  import { parse as parseToml } from "smol-toml";
27
28
  import { hasAurigaHeader, parseMarkers } from "./workflow-markers.js";
29
+ import { WORKFLOW_COMPAT_FILE, WORKFLOW_PRIMARY_FILE, } from "./workflow-docs.js";
28
30
  /**
29
31
  * Shorten an absolute path by replacing the user's $HOME with `~`. Avoids
30
32
  * leaking the full username in screenshots and keeps the TopBar label
@@ -152,29 +154,44 @@ function workflowPathsForScope(scope, projectRoot, home) {
152
154
  if (scope === "user") {
153
155
  return [path.join(home, ".claude", "CLAUDE.md")];
154
156
  }
155
- // Project: only `<proj>/CLAUDE.md` the auriga workflow installer
156
- // (src/workflow.ts) writes here and never to `<proj>/.claude/CLAUDE.md`.
157
- // The old fallback collapsed onto `$HOME/.claude/CLAUDE.md` when
158
- // projectRoot === $HOME (user runs `web-ui` from home dir), leaking
159
- // user-scope content into the project-scope row.
160
- return [path.join(projectRoot, "CLAUDE.md")];
157
+ // Project: prefer the current `<proj>/AGENTS.md` primary. Keep
158
+ // `<proj>/CLAUDE.md` as a legacy fallback so already-installed projects do
159
+ // not flash as missing before their next install flips the symlink direction.
160
+ // Never fall back to `<proj>/.claude/CLAUDE.md`: that path can collapse onto
161
+ // user scope when projectRoot === HOME.
162
+ return [
163
+ path.join(projectRoot, WORKFLOW_PRIMARY_FILE),
164
+ path.join(projectRoot, WORKFLOW_COMPAT_FILE),
165
+ ];
161
166
  }
162
- function scanWorkflow(scope, projectRoot, home, warnings) {
163
- const candidates = workflowPathsForScope(scope, projectRoot, home);
164
- let content = null;
167
+ function workflowForeignWarningCode(filePath) {
168
+ return path.basename(filePath) === WORKFLOW_PRIMARY_FILE
169
+ ? "workflow-foreign-agentsmd"
170
+ : "workflow-foreign-claudemd";
171
+ }
172
+ function workflowForeignWarningMessage(filePath) {
173
+ const name = path.basename(filePath);
174
+ return `Foreign ${name} detected at the workflow path — no auriga-workflow header. Install will preserve existing content or link intent before replacing the workflow path.`;
175
+ }
176
+ function readFirstWorkflowCandidate(candidates) {
165
177
  for (const candidate of candidates) {
166
178
  try {
167
- content = fs.readFileSync(candidate, "utf8");
168
- break;
179
+ return { content: fs.readFileSync(candidate, "utf8"), filePath: candidate };
169
180
  }
170
181
  catch {
171
182
  // try next candidate
172
183
  }
173
184
  }
174
- if (content === null) {
185
+ return null;
186
+ }
187
+ function scanWorkflow(scope, projectRoot, home, warnings) {
188
+ const candidates = workflowPathsForScope(scope, projectRoot, home);
189
+ const workflowFile = readFirstWorkflowCandidate(candidates);
190
+ if (workflowFile === null) {
175
191
  return { status: "not-installed", observedScope: scope };
176
192
  }
177
- // "Is this our CLAUDE.md?" two recognizable shapes:
193
+ const { content, filePath } = workflowFile;
194
+ // "Is this our workflow instruction file?" — two recognizable shapes:
178
195
  // - managed-block markers (the current install format). The START marker
179
196
  // is an HTML comment ahead of the auriga header, so a first-non-blank-
180
197
  // line header walk would miss it — detect the marker pair directly.
@@ -183,13 +200,13 @@ function scanWorkflow(scope, projectRoot, home, warnings) {
183
200
  if (parseMarkers(content).kind === "marked" || hasAurigaHeader(content)) {
184
201
  return { status: "installed", observedScope: scope };
185
202
  }
186
- // CLAUDE.md exists but is neither marked nor auriga-headed. The file is
187
- // foreign — not our workflow. Report `not-installed` honestly; the install
188
- // path (src/workflow.ts) keeps the foreign content as the user region
189
- // below a fresh managed block, so nothing is lost.
203
+ // The workflow path exists but is neither marked nor auriga-headed. The file
204
+ // is foreign — not our workflow. Report `not-installed` honestly; the install
205
+ // path keeps the foreign content as the user region below a fresh managed
206
+ // block, so nothing is lost.
190
207
  warnings.push({
191
- code: "workflow-foreign-claudemd",
192
- message: `Foreign CLAUDE.md detected at the workflow path — no auriga-workflow header. Install will keep your content as the user region below the managed block.`,
208
+ code: workflowForeignWarningCode(filePath),
209
+ message: workflowForeignWarningMessage(filePath),
193
210
  });
194
211
  return { status: "not-installed", observedScope: scope };
195
212
  }
package/dist/utils.d.ts CHANGED
@@ -92,6 +92,8 @@ export interface LangOption {
92
92
  label: string;
93
93
  file: string;
94
94
  }
95
+ export declare const DEFAULT_WORKFLOW_LANG = "zh-CN";
96
+ export declare const DEFAULT_WORKFLOW_TEMPLATE_FILE = "AGENTS.md";
95
97
  export declare const LANGUAGES: LangOption[];
96
98
  /**
97
99
  * Reads `version` from the packaged manifest. Throws when the package
package/dist/utils.js CHANGED
@@ -100,9 +100,11 @@ export function execAsync(cmd, opts) {
100
100
  });
101
101
  });
102
102
  }
103
+ export const DEFAULT_WORKFLOW_LANG = "zh-CN";
104
+ export const DEFAULT_WORKFLOW_TEMPLATE_FILE = "AGENTS.md";
103
105
  export const LANGUAGES = [
104
- { value: "en", label: "English", file: "CLAUDE.md" },
105
- { value: "zh-CN", label: "中文", file: "CLAUDE.zh-CN.md" },
106
+ { value: "zh-CN", label: "中文", file: "AGENTS.md" },
107
+ { value: "en", label: "English", file: "AGENTS.en.md" },
106
108
  ];
107
109
  // --- Remote content ---
108
110
  const REPO = "Ben2pc/auriga-cli";
@@ -146,7 +148,8 @@ function resolveContentRef() {
146
148
  return "main";
147
149
  }
148
150
  const CONTENT_FILES = [
149
- "CLAUDE.md",
151
+ DEFAULT_WORKFLOW_TEMPLATE_FILE,
152
+ "AGENTS.en.md",
150
153
  "skills-lock.json",
151
154
  ".claude-plugin/marketplace.json",
152
155
  ".agents/plugins/marketplace.json",
@@ -182,8 +185,10 @@ export async function fetchContentRoot() {
182
185
  return tmpDir;
183
186
  }
184
187
  export async function fetchExtraContent(tmpDir, file) {
185
- const content = await fetchFile(file);
186
188
  const dest = path.join(tmpDir, file);
189
+ if (fs.existsSync(dest))
190
+ return;
191
+ const content = await fetchFile(file);
187
192
  fs.mkdirSync(path.dirname(dest), { recursive: true });
188
193
  fs.writeFileSync(dest, content);
189
194
  }
@@ -0,0 +1,4 @@
1
+ export declare const WORKFLOW_PRIMARY_FILE = "AGENTS.md";
2
+ export declare const WORKFLOW_COMPAT_FILE = "CLAUDE.md";
3
+ export declare const WORKFLOW_COMPAT_SYMLINK_TARGET = "AGENTS.md";
4
+ export declare const LEGACY_AGENTS_SYMLINK_TARGET = "CLAUDE.md";
@@ -0,0 +1,4 @@
1
+ export const WORKFLOW_PRIMARY_FILE = "AGENTS.md";
2
+ export const WORKFLOW_COMPAT_FILE = "CLAUDE.md";
3
+ export const WORKFLOW_COMPAT_SYMLINK_TARGET = WORKFLOW_PRIMARY_FILE;
4
+ export const LEGACY_AGENTS_SYMLINK_TARGET = WORKFLOW_COMPAT_FILE;
@@ -30,7 +30,7 @@ export type MarkerParse = {
30
30
  endHash: string | null;
31
31
  };
32
32
  /**
33
- * Classify a CLAUDE.md body by its managed-block markers.
33
+ * Classify an AGENTS.md body by its managed-block markers.
34
34
  *
35
35
  * - `unmarked` — neither marker present (fresh-target / foreign / old-format)
36
36
  * - `malformed` — exactly one marker, or END before START (can't safely splice)
@@ -38,7 +38,7 @@ export type MarkerParse = {
38
38
  */
39
39
  export declare function parseMarkers(content: string): MarkerParse;
40
40
  /**
41
- * Build a marked CLAUDE.md from its three parts. The END marker hash is
41
+ * Build a marked AGENTS.md from its three parts. The END marker hash is
42
42
  * computed from `blockBody` here, so callers never hand-maintain it.
43
43
  *
44
44
  * `blockBody` is expected to end with a newline (it is the content the START
@@ -55,5 +55,5 @@ export declare function composeMarkedFile(opts: {
55
55
  lang?: string;
56
56
  }): string;
57
57
  /** True when the first non-blank line is an auriga workflow header. Used to
58
- * tell an old-format (pre-marker) auriga CLAUDE.md from a foreign one. */
58
+ * tell an old-format (pre-marker) auriga workflow file from a foreign one. */
59
59
  export declare function hasAurigaHeader(content: string): boolean;
@@ -1,14 +1,14 @@
1
- // Managed-block markers for the installed CLAUDE.md.
1
+ // Managed-block markers for the installed AGENTS.md.
2
2
  //
3
3
  // auriga-cli installs its workflow document wrapped in a pair of HTML-comment
4
4
  // markers. Everything *between* the markers is the "managed block" — owned by
5
5
  // auriga-cli, replaced wholesale on upgrade. Everything *outside* (notably the
6
6
  // region after the END marker) is the project's own — auriga-cli never touches
7
- // it. This lets a downstream project extend its CLAUDE.md while still
7
+ // it. This lets a downstream project extend its AGENTS.md while still
8
8
  // receiving workflow upgrades.
9
9
  //
10
10
  // Markers are HTML comments so both Claude Code and Codex (which read the same
11
- // file via the AGENTS.md → CLAUDE.md symlink) treat them as inert.
11
+ // file via the CLAUDE.md → AGENTS.md symlink) treat them as inert.
12
12
  //
13
13
  // This module is the single source of truth for the marker contract; it is
14
14
  // imported by both src/workflow.ts (install / upgrade) and src/state.ts
@@ -21,7 +21,7 @@ export const MARKER_SCHEMA = "v1";
21
21
  * START marker line, one per template language. Only the prose differs — the
22
22
  * structural `AURIGA:WORKFLOW:v1 START` token is language-independent, so the
23
23
  * parser (`START_LINE_RE`) keys on the token alone and never needs to know the
24
- * language. The English `CLAUDE.md` gets the English marker; `CLAUDE.zh-CN.md`
24
+ * language. The English `AGENTS.en.md` gets the English marker; `AGENTS.md`
25
25
  * gets the Chinese one, so a downstream file never carries a comment in the
26
26
  * wrong language for its document.
27
27
  */
@@ -53,7 +53,7 @@ export function hashBlock(blockBody) {
53
53
  return createHash("sha256").update(blockBody, "utf8").digest("hex").slice(0, 16);
54
54
  }
55
55
  /**
56
- * Classify a CLAUDE.md body by its managed-block markers.
56
+ * Classify an AGENTS.md body by its managed-block markers.
57
57
  *
58
58
  * - `unmarked` — neither marker present (fresh-target / foreign / old-format)
59
59
  * - `malformed` — exactly one marker, or END before START (can't safely splice)
@@ -87,7 +87,7 @@ export function parseMarkers(content) {
87
87
  };
88
88
  }
89
89
  /**
90
- * Build a marked CLAUDE.md from its three parts. The END marker hash is
90
+ * Build a marked AGENTS.md from its three parts. The END marker hash is
91
91
  * computed from `blockBody` here, so callers never hand-maintain it.
92
92
  *
93
93
  * `blockBody` is expected to end with a newline (it is the content the START
@@ -105,7 +105,7 @@ export function composeMarkedFile(opts) {
105
105
  (opts.userRegion ?? ""));
106
106
  }
107
107
  /** True when the first non-blank line is an auriga workflow header. Used to
108
- * tell an old-format (pre-marker) auriga CLAUDE.md from a foreign one. */
108
+ * tell an old-format (pre-marker) auriga workflow file from a foreign one. */
109
109
  export function hasAurigaHeader(content) {
110
110
  for (const line of content.split("\n")) {
111
111
  if (line.trim().length === 0)
@@ -1,14 +1,13 @@
1
1
  import { type InstallOpts } from "./utils.js";
2
2
  export declare function installWorkflow(packageRoot: string, opts: InstallOpts): Promise<void>;
3
3
  /**
4
- * Uninstall the workflow (CLAUDE.md + AGENTS.md) from `opts.cwd`.
4
+ * Uninstall the workflow (AGENTS.md + CLAUDE.md) from `opts.cwd`.
5
5
  *
6
6
  * Safety contract:
7
7
  * - `opts.force` MUST be true. The CLI / server caller is responsible for
8
8
  * confirming user intent BEFORE invoking this; we refuse otherwise.
9
- * - `AGENTS.md` is removed ONLY if it's a symlink (the install-time shape).
10
- * A real-file AGENTS.md is left in place with a warning — the user has
11
- * diverged from the install pattern and probably hand-edited it.
9
+ * - Real files are removed only when they are recognizable auriga workflow
10
+ * files. Foreign instruction files are left in place with a warning.
12
11
  * - Missing files are a no-op: callers can re-run uninstall idempotently.
13
12
  * - `.claude/` is not touched; skills / plugins / hooks have their own
14
13
  * uninstall paths.
package/dist/workflow.js CHANGED
@@ -1,8 +1,9 @@
1
1
  import fs from "node:fs";
2
2
  import path from "node:path";
3
3
  import { input, select } from "@inquirer/prompts";
4
- import { LANGUAGES, fetchExtraContent, log, withEsc, } from "./utils.js";
4
+ import { DEFAULT_WORKFLOW_LANG, DEFAULT_WORKFLOW_TEMPLATE_FILE, LANGUAGES, fetchExtraContent, log, withEsc, } from "./utils.js";
5
5
  import { composeMarkedFile, hasAurigaHeader, hashBlock, parseMarkers, } from "./workflow-markers.js";
6
+ import { LEGACY_AGENTS_SYMLINK_TARGET, WORKFLOW_COMPAT_FILE, WORKFLOW_COMPAT_SYMLINK_TARGET, WORKFLOW_PRIMARY_FILE, } from "./workflow-docs.js";
6
7
  /**
7
8
  * Back up `filePath` once. The canonical `<file>.bak` slot is reserved for the
8
9
  * FIRST capture (the user's pre-auriga original) and is never overwritten — a
@@ -12,8 +13,8 @@ import { composeMarkedFile, hasAurigaHeader, hashBlock, parseMarkers, } from "./
12
13
  * `verbatimSymlinks` copies a symlink AS a symlink, preserving its literal
13
14
  * (possibly relative) target — a foreign AGENTS.md may be a symlink pointing
14
15
  * elsewhere, and we want the backup to preserve that target verbatim rather
15
- * than snapshot whatever it currently resolves to. A real file (CLAUDE.md)
16
- * copies as a real file. `lstat` (not `existsSync`) probes the `.bak` slot so
16
+ * than snapshot whatever it currently resolves to. A real workflow file copies
17
+ * as a real file. `lstat` (not `existsSync`) probes the `.bak` slot so
17
18
  * a backup that is itself a possibly-broken symlink still counts as present
18
19
  * and is not silently overwritten.
19
20
  */
@@ -32,14 +33,26 @@ function backupOnce(filePath) {
32
33
  fs.cpSync(filePath, dest, { verbatimSymlinks: true });
33
34
  return dest;
34
35
  }
36
+ function lstatMaybe(filePath) {
37
+ try {
38
+ return fs.lstatSync(filePath);
39
+ }
40
+ catch {
41
+ return undefined;
42
+ }
43
+ }
44
+ function isSymlinkTo(filePath, target) {
45
+ const stat = lstatMaybe(filePath);
46
+ return !!stat?.isSymbolicLink() && fs.readlinkSync(filePath) === target;
47
+ }
35
48
  export async function installWorkflow(packageRoot, opts) {
36
49
  const lang = opts.interactive
37
50
  ? await withEsc(select({
38
- message: "CLAUDE.md language:",
51
+ message: "Workflow language:",
39
52
  choices: LANGUAGES.map((l) => ({ name: l.label, value: l.value })),
40
- default: "en",
53
+ default: DEFAULT_WORKFLOW_LANG,
41
54
  }))
42
- : (opts.lang ?? "en");
55
+ : (opts.lang ?? DEFAULT_WORKFLOW_LANG);
43
56
  const targetDir = opts.interactive
44
57
  ? await withEsc(input({
45
58
  message: "Workflow install target directory:",
@@ -56,19 +69,19 @@ export async function installWorkflow(packageRoot, opts) {
56
69
  throw new Error(msg);
57
70
  }
58
71
  const langOpt = LANGUAGES.find((l) => l.value === lang);
59
- // Lazy fetch: only download non-default language file when needed
60
- if (langOpt.file !== "CLAUDE.md") {
72
+ // Lazy fetch: only download non-default language files when needed.
73
+ if (langOpt.file !== DEFAULT_WORKFLOW_TEMPLATE_FILE) {
61
74
  console.log(`Fetching ${langOpt.label} template...`);
62
75
  await fetchExtraContent(packageRoot, langOpt.file);
63
76
  }
64
- const sourceClaude = path.join(packageRoot, langOpt.file);
65
- const targetClaude = path.join(resolved, "CLAUDE.md");
66
- const targetAgents = path.join(resolved, "AGENTS.md");
77
+ const sourceWorkflow = path.join(packageRoot, langOpt.file);
78
+ const targetPrimary = path.join(resolved, WORKFLOW_PRIMARY_FILE);
79
+ const targetCompat = path.join(resolved, WORKFLOW_COMPAT_FILE);
67
80
  // The packaged template is authored with managed-block markers. Extract its
68
81
  // managed block (the auriga workflow body) and its user-region placeholder.
69
82
  // Defensive fallback: if the template somehow lacks markers, treat the whole
70
83
  // file as the managed block with an empty user region.
71
- const sourceContent = fs.readFileSync(sourceClaude, "utf8");
84
+ const sourceContent = fs.readFileSync(sourceWorkflow, "utf8");
72
85
  const sourceParsed = parseMarkers(sourceContent);
73
86
  const sourceBlock = sourceParsed.kind === "marked"
74
87
  ? sourceParsed.blockBody
@@ -76,16 +89,43 @@ export async function installWorkflow(packageRoot, opts) {
76
89
  ? sourceContent
77
90
  : sourceContent + "\n";
78
91
  const templateUserRegion = sourceParsed.kind === "marked" ? sourceParsed.userRegion : "";
92
+ const primaryStat = lstatMaybe(targetPrimary);
93
+ const compatStat = lstatMaybe(targetCompat);
94
+ const legacyShape = primaryStat?.isSymbolicLink() === true &&
95
+ fs.readlinkSync(targetPrimary) === LEGACY_AGENTS_SYMLINK_TARGET &&
96
+ compatStat?.isFile() === true;
97
+ const primaryForeignSymlink = primaryStat?.isSymbolicLink() === true &&
98
+ fs.readlinkSync(targetPrimary) !== LEGACY_AGENTS_SYMLINK_TARGET;
99
+ const compatIsCurrentPrimary = !primaryStat &&
100
+ compatStat !== undefined &&
101
+ !isSymlinkTo(targetCompat, WORKFLOW_COMPAT_SYMLINK_TARGET);
102
+ const currentPath = primaryStat && !primaryStat.isSymbolicLink()
103
+ ? targetPrimary
104
+ : legacyShape || compatIsCurrentPrimary
105
+ ? targetCompat
106
+ : undefined;
107
+ let wrotePrimary = false;
108
+ const writePrimary = (content) => {
109
+ if (primaryStat?.isSymbolicLink()) {
110
+ if (primaryForeignSymlink) {
111
+ const bak = backupOnce(targetPrimary);
112
+ log.warn(`AGENTS.md 是指向其它目标的软链;已备份到 ${path.basename(bak)} 后改为主文件。`);
113
+ }
114
+ fs.unlinkSync(targetPrimary);
115
+ }
116
+ fs.writeFileSync(targetPrimary, content);
117
+ wrotePrimary = true;
118
+ };
79
119
  // Installing the workflow doc is one of five cases. The managed block is
80
120
  // always replaced with the packaged version; the cases differ in how the
81
121
  // project's own content (the user region) is preserved or backed up.
82
- if (!fs.existsSync(targetClaude)) {
122
+ if (!currentPath) {
83
123
  // 1. Fresh install — write the marked template as-is, no backup.
84
- fs.writeFileSync(targetClaude, composeMarkedFile({ blockBody: sourceBlock, userRegion: templateUserRegion, lang }));
85
- log.ok(`CLAUDE.md installed (${langOpt.label})`);
124
+ writePrimary(composeMarkedFile({ blockBody: sourceBlock, userRegion: templateUserRegion, lang }));
125
+ log.ok(`AGENTS.md installed (${langOpt.label})`);
86
126
  }
87
127
  else {
88
- const current = fs.readFileSync(targetClaude, "utf8");
128
+ const current = fs.readFileSync(currentPath, "utf8");
89
129
  const parsed = parseMarkers(current);
90
130
  if (parsed.kind === "marked") {
91
131
  // 2. Upgrade — splice the managed block, preserve the user region.
@@ -97,80 +137,74 @@ export async function installWorkflow(packageRoot, opts) {
97
137
  // marker). Can't prove the block is untouched, so back up
98
138
  // conservatively rather than risk silently dropping an edit.
99
139
  if (parsed.endHash === null) {
100
- const bak = backupOnce(targetClaude);
101
- log.warn(`CLAUDE.md 的受管区块缺少校验标记,无法确认是否被改动;升级前已备份到 ${path.basename(bak)}`);
140
+ const bak = backupOnce(currentPath);
141
+ log.warn(`工作流文档的受管区块缺少校验标记,无法确认是否被改动;升级前已备份到 ${path.basename(bak)}`);
102
142
  }
103
143
  else if (parsed.endHash !== hashBlock(parsed.blockBody)) {
104
- const bak = backupOnce(targetClaude);
105
- log.warn(`CLAUDE.md 的受管区块曾被手改;升级已整块覆盖该区块,改动前的文件见 ${path.basename(bak)}`);
144
+ const bak = backupOnce(currentPath);
145
+ log.warn(`工作流文档的受管区块曾被手改;升级已整块覆盖该区块,改动前的文件见 ${path.basename(bak)}`);
106
146
  }
107
- fs.writeFileSync(targetClaude, composeMarkedFile({
147
+ writePrimary(composeMarkedFile({
108
148
  prefix: parsed.prefix,
109
149
  blockBody: sourceBlock,
110
150
  userRegion: parsed.userRegion,
111
151
  lang,
112
152
  }));
113
- log.ok(`CLAUDE.md upgraded (${langOpt.label}); your project section was preserved`);
153
+ log.ok(`AGENTS.md upgraded (${langOpt.label}); your project section was preserved`);
114
154
  }
115
155
  else if (parsed.kind === "unmarked" && hasAurigaHeader(current)) {
116
- // 3. Old-format migration — an auriga CLAUDE.md from before markers
156
+ // 3. Old-format migration — an auriga workflow doc from before markers
117
157
  // existed. The user region can't be recovered from an unmarked file,
118
158
  // so back the whole thing up and install fresh.
119
- const bak = backupOnce(targetClaude);
120
- fs.writeFileSync(targetClaude, composeMarkedFile({ blockBody: sourceBlock, userRegion: templateUserRegion, lang }));
121
- log.warn(`检测到旧版 CLAUDE.md(无受管标记);已备份到 ${path.basename(bak)}。` +
159
+ const bak = backupOnce(currentPath);
160
+ writePrimary(composeMarkedFile({ blockBody: sourceBlock, userRegion: templateUserRegion, lang }));
161
+ log.warn(`检测到旧版工作流文档(无受管标记);已备份到 ${path.basename(bak)}。` +
122
162
  `若你改过它,请从备份把工程定制手动迁移到 END 标记之后的用户区。`);
123
- log.ok(`CLAUDE.md migrated to the managed-block format (${langOpt.label})`);
163
+ log.ok(`AGENTS.md migrated to the managed-block format (${langOpt.label})`);
124
164
  }
125
165
  else if (parsed.kind === "unmarked") {
126
- // 4. Foreign first install — a CLAUDE.md from another tool. Keep its
166
+ // 4. Foreign first install — a workflow doc from another tool. Keep its
127
167
  // content in place as the user region; no backup needed.
128
168
  const foreign = current.endsWith("\n") ? current : current + "\n";
129
- fs.writeFileSync(targetClaude, composeMarkedFile({ blockBody: sourceBlock, userRegion: "\n" + foreign, lang }));
130
- log.ok(`CLAUDE.md installed (${langOpt.label}); your existing content was kept below the managed block`);
169
+ writePrimary(composeMarkedFile({ blockBody: sourceBlock, userRegion: "\n" + foreign, lang }));
170
+ log.ok(`AGENTS.md installed (${langOpt.label}); your existing content was kept below the managed block`);
171
+ if (currentPath === targetPrimary) {
172
+ log.warn("AGENTS.md already existed; its content was kept below the managed block.");
173
+ }
131
174
  }
132
175
  else {
133
176
  // 5. Malformed markers — can't locate the block boundaries safely.
134
177
  // Back up and reinstall fresh rather than splice into a broken file.
135
- const bak = backupOnce(targetClaude);
136
- fs.writeFileSync(targetClaude, composeMarkedFile({ blockBody: sourceBlock, userRegion: templateUserRegion, lang }));
137
- log.warn(`CLAUDE.md 的受管标记已损坏(${parsed.reason});已备份到 ${path.basename(bak)} 并重装。`);
178
+ const bak = backupOnce(currentPath);
179
+ writePrimary(composeMarkedFile({ blockBody: sourceBlock, userRegion: templateUserRegion, lang }));
180
+ log.warn(`工作流文档的受管标记已损坏(${parsed.reason});已备份到 ${path.basename(bak)} 并重装。`);
138
181
  }
139
182
  }
140
- // Point AGENTS.md at CLAUDE.md via a symlink (the install shape — Claude
141
- // Code and Codex then read the same workflow doc). If the path is already
142
- // occupied by something that ISN'T that symlink — a real file from another
143
- // tool, or a symlink pointing elsewhere — it holds content or intent we
144
- // must not silently destroy. Back it up first (symmetric with how a foreign
145
- // / hand-edited CLAUDE.md is preserved above), then replace.
146
- let agentsStat;
147
- try {
148
- agentsStat = fs.lstatSync(targetAgents);
149
- }
150
- catch {
151
- // does not exist — nothing to preserve.
152
- }
153
- if (agentsStat) {
154
- const pointsToClaude = agentsStat.isSymbolicLink() &&
155
- fs.readlinkSync(targetAgents) === "CLAUDE.md";
156
- if (!pointsToClaude) {
157
- const bak = backupOnce(targetAgents);
158
- log.warn(`AGENTS.md 不是指向 CLAUDE.md 的软链;已备份到 ${path.basename(bak)} 后替换为软链。`);
183
+ // Point CLAUDE.md at AGENTS.md via a compatibility symlink. If CLAUDE.md was
184
+ // the old primary file and its content was migrated above, replacing it with
185
+ // the symlink is safe. Otherwise preserve any real file or foreign symlink
186
+ // before replacing it.
187
+ const latestCompatStat = lstatMaybe(targetCompat);
188
+ if (latestCompatStat) {
189
+ const pointsToPrimary = isSymlinkTo(targetCompat, WORKFLOW_COMPAT_SYMLINK_TARGET);
190
+ const migratedFromCompat = currentPath === targetCompat && wrotePrimary && !latestCompatStat.isSymbolicLink();
191
+ if (!pointsToPrimary && !migratedFromCompat) {
192
+ const bak = backupOnce(targetCompat);
193
+ log.warn(`CLAUDE.md 不是指向 AGENTS.md 的软链;已备份到 ${path.basename(bak)} 后替换为软链。`);
159
194
  }
160
- fs.unlinkSync(targetAgents);
195
+ fs.unlinkSync(targetCompat);
161
196
  }
162
- fs.symlinkSync("CLAUDE.md", targetAgents);
163
- log.ok("AGENTS.md -> CLAUDE.md symlink created");
197
+ fs.symlinkSync(WORKFLOW_COMPAT_SYMLINK_TARGET, targetCompat);
198
+ log.ok("CLAUDE.md -> AGENTS.md symlink created");
164
199
  }
165
200
  /**
166
- * Uninstall the workflow (CLAUDE.md + AGENTS.md) from `opts.cwd`.
201
+ * Uninstall the workflow (AGENTS.md + CLAUDE.md) from `opts.cwd`.
167
202
  *
168
203
  * Safety contract:
169
204
  * - `opts.force` MUST be true. The CLI / server caller is responsible for
170
205
  * confirming user intent BEFORE invoking this; we refuse otherwise.
171
- * - `AGENTS.md` is removed ONLY if it's a symlink (the install-time shape).
172
- * A real-file AGENTS.md is left in place with a warning — the user has
173
- * diverged from the install pattern and probably hand-edited it.
206
+ * - Real files are removed only when they are recognizable auriga workflow
207
+ * files. Foreign instruction files are left in place with a warning.
174
208
  * - Missing files are a no-op: callers can re-run uninstall idempotently.
175
209
  * - `.claude/` is not touched; skills / plugins / hooks have their own
176
210
  * uninstall paths.
@@ -190,38 +224,58 @@ export async function uninstallWorkflow(opts) {
190
224
  const emit = (line) => {
191
225
  opts.onLog?.(line);
192
226
  };
193
- const targetClaude = path.join(resolved, "CLAUDE.md");
194
- const targetAgents = path.join(resolved, "AGENTS.md");
195
- // CLAUDE.md flat file. lstat to avoid following a symlink (would be
196
- // unusual but we'd rather refuse to traverse than chase one out).
197
- if (fs.existsSync(targetClaude)) {
198
- fs.unlinkSync(targetClaude);
199
- log.ok("CLAUDE.md removed");
200
- emit("removed CLAUDE.md");
201
- }
202
- else {
203
- log.skip("CLAUDE.md not present");
204
- emit("CLAUDE.md not present");
205
- }
206
- // AGENTS.md — only remove symlinks (our install shape). lstatSync
207
- // refuses to follow the link so we inspect the link itself.
208
- try {
209
- const stat = fs.lstatSync(targetAgents);
227
+ const targetClaude = path.join(resolved, WORKFLOW_COMPAT_FILE);
228
+ const targetAgents = path.join(resolved, WORKFLOW_PRIMARY_FILE);
229
+ const isAurigaWorkflowFile = (filePath) => {
230
+ try {
231
+ const content = fs.readFileSync(filePath, "utf8");
232
+ return parseMarkers(content).kind === "marked" || hasAurigaHeader(content);
233
+ }
234
+ catch {
235
+ return false;
236
+ }
237
+ };
238
+ const removeWorkflowPath = (filePath, name) => {
239
+ let stat;
240
+ try {
241
+ stat = fs.lstatSync(filePath);
242
+ }
243
+ catch (err) {
244
+ const code = err.code;
245
+ if (code === "ENOENT") {
246
+ log.skip(`${name} not present`);
247
+ emit(`${name} not present`);
248
+ return;
249
+ }
250
+ throw err;
251
+ }
210
252
  if (stat.isSymbolicLink()) {
211
- fs.unlinkSync(targetAgents);
212
- log.ok("AGENTS.md symlink removed");
213
- emit("removed AGENTS.md symlink");
253
+ const linkTarget = fs.readlinkSync(filePath);
254
+ const isManagedSymlink = (name === WORKFLOW_PRIMARY_FILE && linkTarget === LEGACY_AGENTS_SYMLINK_TARGET) ||
255
+ (name === WORKFLOW_COMPAT_FILE && linkTarget === WORKFLOW_COMPAT_SYMLINK_TARGET);
256
+ if (isManagedSymlink) {
257
+ fs.unlinkSync(filePath);
258
+ log.ok(`${name} symlink removed`);
259
+ emit(`removed ${name} symlink`);
260
+ }
261
+ else {
262
+ log.warn(`foreign ${name} symlink left in place`);
263
+ emit(`foreign ${name} symlink left in place`);
264
+ }
265
+ }
266
+ else if (stat.isFile() && isAurigaWorkflowFile(filePath)) {
267
+ fs.unlinkSync(filePath);
268
+ log.ok(`${name} removed`);
269
+ emit(`removed ${name}`);
214
270
  }
215
271
  else {
216
- // Real file (or directory) — user diverged from install. Don't
217
- // silently destroy their content; warn and leave it.
218
- log.warn("AGENTS.md is not a symlink; left in place");
219
- emit("AGENTS.md is not a symlink; left in place");
272
+ log.warn(`foreign ${name} left in place`);
273
+ emit(`foreign ${name} left in place`);
220
274
  }
221
- }
222
- catch {
223
- // ENOENT already gone, idempotent no-op.
224
- log.skip("AGENTS.md not present");
225
- emit("AGENTS.md not present");
226
- }
275
+ };
276
+ // Remove AGENTS.md first because it is the current primary. lstatSync refuses
277
+ // to follow symlinks, so the legacy AGENTS.md -> CLAUDE.md shape is handled
278
+ // without deleting CLAUDE.md through the link.
279
+ removeWorkflowPath(targetAgents, "AGENTS.md");
280
+ removeWorkflowPath(targetClaude, "CLAUDE.md");
227
281
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "auriga-cli",
3
- "version": "1.28.0",
3
+ "version": "1.29.0",
4
4
  "description": "Interactive CLI to install Claude Code harness modules (Workflow, Skills, Recommended Skills, Plugins)",
5
5
  "license": "MIT",
6
6
  "repository": {