auriga-cli 1.20.3 → 1.20.5
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 +2 -3
- package/README.zh-CN.md +2 -3
- package/dist/catalog.d.ts +5 -5
- package/dist/catalog.json +29 -33
- package/dist/cli.js +8 -8
- package/dist/codex-plugin-config.d.ts +0 -11
- package/dist/codex-plugin-config.js +1 -28
- package/dist/guide.js +5 -5
- package/dist/hooks.js +12 -11
- package/dist/marketplace.js +6 -8
- package/dist/plugins.d.ts +38 -2
- package/dist/plugins.js +194 -53
- package/dist/skills.js +0 -1
- package/dist/utils.js +2 -46
- package/package.json +3 -3
package/README.md
CHANGED
|
@@ -11,7 +11,7 @@ This repo itself is a fully configured harness project. You can clone it to see
|
|
|
11
11
|
| Module | Description |
|
|
12
12
|
|---|---|
|
|
13
13
|
| **Workflow** | `CLAUDE.md` auriga workflow: requirement clarification -> TDD -> Review, Harness principles, Subagent usage guide |
|
|
14
|
-
| **Skills** | External development process skills —
|
|
14
|
+
| **Skills** | External development process skills — systematic-debugging, TDD, verification, planning, playwright (spec authoring ships as the `spec-design` skill inside the `auriga-workflow-skills` 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, codex, auriga-go, auriga-git-guards, auriga-workflow-skills, auriga-notify, session-instructions-loader, deep-review |
|
|
17
17
|
| **Hooks** | Legacy Claude Code hook installer. No repo-owned hooks are currently exposed here; `notify` ships as the `auriga-notify` plugin. |
|
|
@@ -96,7 +96,6 @@ Installs selected skills via `npx skills add`, targeting both Claude Code and Co
|
|
|
96
96
|
|
|
97
97
|
| Skill | Source | Description |
|
|
98
98
|
|---|---|---|
|
|
99
|
-
| brainstorming | [obra/superpowers](https://github.com/obra/superpowers) | Requirement clarification and design exploration |
|
|
100
99
|
| systematic-debugging | [obra/superpowers](https://github.com/obra/superpowers) | Systematic debugging — find root cause before fixing |
|
|
101
100
|
| test-driven-development | [obra/superpowers](https://github.com/obra/superpowers) | Test-driven development workflow |
|
|
102
101
|
| verification-before-completion | [obra/superpowers](https://github.com/obra/superpowers) | Pre-completion verification — evidence before assertions |
|
|
@@ -139,7 +138,7 @@ npx -y auriga-cli install plugins --agent both --plugin auriga-git-guards
|
|
|
139
138
|
| codex | Claude Code | Codex cross-model collaboration |
|
|
140
139
|
| auriga-go | Claude Code / Codex | Workflow autopilot for the auriga workflow. Reminder-based navigation across the `CLAUDE.md` phases. Bundles two skills: `auriga-go` (description-based NL trigger + `/auriga-go`) and `/goalify` (plans an autonomous goal from a spec or work-in-progress and dispatches it via Claude Code's built-in `/goal` command). |
|
|
141
140
|
| auriga-git-guards | Claude Code / Codex | Three git-lifecycle guardrails plus the bundled `git-workflow` skill. Hooks: `commit-reminder` (PostToolUse on `Edit` / `Write` / `MultiEdit` in Claude Code and on `apply_patch` — Codex's canonical file-edit `tool_name` — so it fires in both runtimes → when uncommitted diff vs `HEAD` exceeds 200 lines or 8 files and the last reminder was ≥ 60 s ago, inject a nudge to commit at the next semantic boundary), `pr-create-guard` (PostToolUse on `gh pr create` → fetch the new PR's body via `gh pr view` and inject headings + TODO counts as `additionalContext` so the Agent can self-verify the five-element PR description: scope / acceptance criteria / design decisions / risks / remaining TODOs), and `pr-ready-guard` (PreToolUse on `gh pr ready` → block on stray planning docs at `findings.md` / `progress.md` / `task_plan.md` / `docs/superpowers/specs/*.md`, unfinalized active specs in `docs/specs/*.md`, or unpushed commits; otherwise inject the body snapshot). 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). |
|
|
142
|
-
| auriga-workflow-skills | Claude Code / Codex | Bundles the auriga-owned workflow execution skills: `incremental-impl`, `test-designer`, and `
|
|
141
|
+
| auriga-workflow-skills | Claude Code / Codex | Bundles the auriga-owned workflow execution skills: `incremental-impl`, `test-designer`, `session-compound`, and `spec-design`. Installed by default through the plugin path instead of `install skills`. |
|
|
143
142
|
| auriga-notify *(opt-in)* | Claude Code | macOS native notification plugin for Claude Code `Notification` events. Focus-aware sound-only mode, click-to-activate, per-project notification grouping, and migrated `config.json` / `icon.png` support. Not installed by `install --all`; install explicitly with `install plugins --plugin auriga-notify`. |
|
|
144
143
|
| session-instructions-loader | Codex | Codex-only SessionStart plugin that injects ancestor `AGENTS.md` files plus repo-configured extra instruction files. |
|
|
145
144
|
| deep-review | Claude Code / Codex | Multi-dimensional PR review orchestrator — dispatches parallel reviewers (spec-conformance, correctness, test-quality, docs-sync, plus conditional robustness/UX/performance/structure/code-quality/skill-plugin-quality) and synthesizes findings into an actionable punch list. Bundles a companion `reviewer-creator` skill for scaffolding project-level custom reviewers under `docs/rules/review/`. Drives the formal-review phase in `CLAUDE.md`. |
|
package/README.zh-CN.md
CHANGED
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
| 模块 | 说明 |
|
|
12
12
|
|---|---|
|
|
13
13
|
| **Workflow** | `CLAUDE.md` 里的 auriga 工作流:需求澄清 → TDD → Review,Harness 原则,Subagent 使用指南 |
|
|
14
|
-
| **Skills** | 外部开发流程 skills ——
|
|
14
|
+
| **Skills** | 外部开发流程 skills —— systematic-debugging、TDD、verification、planning、playwright(spec 撰写由 `auriga-workflow-skills` 插件内的 `spec-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、codex、auriga-go、auriga-git-guards、auriga-workflow-skills、auriga-notify、session-instructions-loader、deep-review |
|
|
17
17
|
| **Hooks** | 传统 Claude Code hook 安装器。目前没有仓库自维护 hook 暴露在这里;`notify` 已迁移为 `auriga-notify` 插件。 |
|
|
@@ -96,7 +96,6 @@ npx auriga-cli
|
|
|
96
96
|
|
|
97
97
|
| Skill | 来源 | 说明 |
|
|
98
98
|
|---|---|---|
|
|
99
|
-
| brainstorming | [obra/superpowers](https://github.com/obra/superpowers) | 需求澄清与设计探索 |
|
|
100
99
|
| systematic-debugging | [obra/superpowers](https://github.com/obra/superpowers) | 系统化调试,先找根因再修复 |
|
|
101
100
|
| test-driven-development | [obra/superpowers](https://github.com/obra/superpowers) | 测试驱动开发流程 |
|
|
102
101
|
| verification-before-completion | [obra/superpowers](https://github.com/obra/superpowers) | 完成前验证,用证据说话 |
|
|
@@ -139,7 +138,7 @@ npx -y auriga-cli install plugins --agent both --plugin auriga-git-guards
|
|
|
139
138
|
| codex | Claude Code | Codex 跨模型协作 |
|
|
140
139
|
| auriga-go | Claude Code / Codex | auriga 工作流的自动驾驶:按 `CLAUDE.md` 的 phase 做 reminder-based 导航。内置两个 skill:`auriga-go`(按 description 的自然语言触发 + `/auriga-go` slash command)和 `/goalify`(根据 spec 或当前进展 plan 出 goal,并通过 Claude Code 内置的 `/goal` 命令分发执行)。 |
|
|
141
140
|
| auriga-git-guards | Claude Code / Codex | 三个 git-lifecycle guardrail + 内置 `git-workflow` skill。Hooks:`commit-reminder`(Claude Code 下 PostToolUse 匹配 `Edit` / `Write` / `MultiEdit`,Codex 下匹配 `apply_patch`(Codex 文件编辑 canonical `tool_name`),两个 runtime 都触发 —— 未提交 diff 对比 `HEAD` 超过 200 行或 8 个文件,且距上次提醒 ≥ 60 s 时,注入提醒让 Agent 在下一个语义边界 commit)、`pr-create-guard`(`gh pr create` 的 PostToolUse —— 通过 `gh pr view` 拉真实 PR body,扫 `^##` / `^###` headings 并统计 `- [ ]` / `- [x]` 注入 `additionalContext`,让 Agent 对照五要素:scope / acceptance criteria / design decisions / risks / remaining TODOs)、`pr-ready-guard`(`gh pr ready` 的 PreToolUse —— 仅按结构信号拦截:游离 `findings.md` / `progress.md` / `task_plan.md` / `docs/superpowers/specs/*.md`、`docs/specs/*.md` 内未结案的活跃 spec、未 push commits;放行时注入 body 快照)。两个 PostToolUse hook 在 Claude Code / Codex 上完全对齐;Codex 仅对 `pr-ready-guard` 的 PreToolUse `additionalContext` 信息路径 fail-open(block 路径两边一致)。 |
|
|
142
|
-
| auriga-workflow-skills | Claude Code / Codex | 打包 auriga 自维护的工作流执行 skills:`incremental-impl`、`test-designer`、`session-compound`。默认通过插件路径安装,不再通过 `install skills` 作为独立条目安装。 |
|
|
141
|
+
| auriga-workflow-skills | Claude Code / Codex | 打包 auriga 自维护的工作流执行 skills:`incremental-impl`、`test-designer`、`session-compound`、`spec-design`。默认通过插件路径安装,不再通过 `install skills` 作为独立条目安装。 |
|
|
143
142
|
| auriga-notify *(opt-in)* | Claude Code | Claude Code `Notification` 事件的 macOS 原生通知插件。支持焦点感知仅提示音、点击唤起终端、按项目分组通知,并迁移旧 `config.json` / `icon.png`。不随 `install --all` 默认安装,需要显式执行 `install plugins --plugin auriga-notify`。 |
|
|
144
143
|
| session-instructions-loader | Codex | Codex-only SessionStart 插件,注入上层目录的 `AGENTS.md` 和仓库配置的额外 instruction 文件。 |
|
|
145
144
|
| deep-review | Claude Code / Codex | 多维度 PR review 编排器 —— 并行派发各维度 reviewer(spec-conformance、correctness、test-quality、docs-sync,以及条件触发的 robustness/UX/performance/structure/code-quality/skill-plugin-quality),汇总成 punch list。同包内打包了 `reviewer-creator` skill,用于在 `docs/rules/review/` 下生成项目级自定义 reviewer。承担 `CLAUDE.md` 中的正式评审职责。 |
|
package/dist/catalog.d.ts
CHANGED
|
@@ -2,11 +2,11 @@ export interface CatalogEntry {
|
|
|
2
2
|
name: string;
|
|
3
3
|
description: string;
|
|
4
4
|
/** Build-time-baked agent map for plugin entries. Derived from
|
|
5
|
-
*
|
|
6
|
-
* files are NOT shipped in the npm tarball, so the scanner can't
|
|
7
|
-
* them at runtime. Baking here lets `/api/state` correctly classify
|
|
8
|
-
* dual-Agent plugins as `["claude","codex"]` for installed users.
|
|
9
|
-
*
|
|
5
|
+
* repo marketplace manifests plus `extra_plugin_configs.json` — those
|
|
6
|
+
* config files are NOT shipped in the npm tarball, so the scanner can't
|
|
7
|
+
* read them at runtime. Baking here lets `/api/state` correctly classify
|
|
8
|
+
* dual-Agent plugins as `["claude","codex"]` for installed users. Absent
|
|
9
|
+
* on skill / hook entries. */
|
|
10
10
|
agents?: ("claude" | "codex")[];
|
|
11
11
|
/** True for plugins whose source lives in an UPSTREAM marketplace
|
|
12
12
|
* (skill-creator / claude-md-management / codex), not in this repo.
|
package/dist/catalog.json
CHANGED
|
@@ -1,10 +1,6 @@
|
|
|
1
1
|
{
|
|
2
|
-
"generatedAt": "2026-05-
|
|
2
|
+
"generatedAt": "2026-05-15T04:24:39.164Z",
|
|
3
3
|
"workflowSkills": [
|
|
4
|
-
{
|
|
5
|
-
"name": "brainstorming",
|
|
6
|
-
"description": "You MUST use this before any creative work - creating features, building components, adding functionality, or modifying behavior. Explores user intent, requirements and design before implementation."
|
|
7
|
-
},
|
|
8
4
|
{
|
|
9
5
|
"name": "planning-with-files",
|
|
10
6
|
"description": "Implements Manus-style file-based planning to organize and track progress on complex tasks. Creates task_plan.md, findings.md, and progress.md. Use when asked to plan out, break down, or organize a multi-step project, research task, or any work requiring 5+ tool calls. Supports automatic session recovery after /clear."
|
|
@@ -61,30 +57,6 @@
|
|
|
61
57
|
}
|
|
62
58
|
],
|
|
63
59
|
"plugins": [
|
|
64
|
-
{
|
|
65
|
-
"name": "skill-creator",
|
|
66
|
-
"description": "Create and manage custom skills",
|
|
67
|
-
"agents": [
|
|
68
|
-
"claude"
|
|
69
|
-
],
|
|
70
|
-
"external": true
|
|
71
|
-
},
|
|
72
|
-
{
|
|
73
|
-
"name": "claude-md-management",
|
|
74
|
-
"description": "Audit and improve CLAUDE.md files",
|
|
75
|
-
"agents": [
|
|
76
|
-
"claude"
|
|
77
|
-
],
|
|
78
|
-
"external": true
|
|
79
|
-
},
|
|
80
|
-
{
|
|
81
|
-
"name": "codex",
|
|
82
|
-
"description": "Cross-model collaboration with Codex",
|
|
83
|
-
"agents": [
|
|
84
|
-
"claude"
|
|
85
|
-
],
|
|
86
|
-
"external": true
|
|
87
|
-
},
|
|
88
60
|
{
|
|
89
61
|
"name": "auriga-go",
|
|
90
62
|
"description": "(Claude/Codex) Workflow autopilot for the auriga workflow. Reminder-based navigation across CLAUDE.md's phases. Bundles a /goalify skill that plans an autonomous goal from a spec or work-in-progress and dispatches it via Claude Code's built-in /goal command.",
|
|
@@ -95,7 +67,7 @@
|
|
|
95
67
|
},
|
|
96
68
|
{
|
|
97
69
|
"name": "auriga-git-guards",
|
|
98
|
-
"description": "(Claude/Codex) Git lifecycle guardrails: commit-reminder +
|
|
70
|
+
"description": "(Claude/Codex) Git lifecycle guardrails: commit-reminder (PostToolUse on Edit/Write/MultiEdit/apply_patch) + pr-create-guard with PR-body snapshot and Conventional Commits title check (PostToolUse on `gh pr create`) + pr-ready-guard structural block at PR Ready transitions, firing on BOTH `gh pr ready` AND `gh pr create` without `--draft` (PreToolUse). Bundles the git-workflow skill. Dual-Agent compatible (Claude Code + Codex).",
|
|
99
71
|
"agents": [
|
|
100
72
|
"claude",
|
|
101
73
|
"codex"
|
|
@@ -103,7 +75,7 @@
|
|
|
103
75
|
},
|
|
104
76
|
{
|
|
105
77
|
"name": "auriga-workflow-skills",
|
|
106
|
-
"description": "(Claude/Codex) Bundles the auriga-owned workflow execution skills: incremental-impl, test-designer, and
|
|
78
|
+
"description": "(Claude/Codex) Bundles the auriga-owned workflow execution skills: incremental-impl, test-designer, session-compound, and spec-design. Dual-Agent compatible (Claude Code + Codex).",
|
|
107
79
|
"agents": [
|
|
108
80
|
"claude",
|
|
109
81
|
"codex"
|
|
@@ -111,19 +83,43 @@
|
|
|
111
83
|
},
|
|
112
84
|
{
|
|
113
85
|
"name": "auriga-notify",
|
|
114
|
-
"description": "(opt-in) Opt-in macOS native notification hook for Claude Code Notification events
|
|
86
|
+
"description": "(opt-in) Opt-in macOS native notification hook for Claude Code Notification events.",
|
|
115
87
|
"agents": [
|
|
116
88
|
"claude"
|
|
117
89
|
]
|
|
118
90
|
},
|
|
119
91
|
{
|
|
120
92
|
"name": "deep-review",
|
|
121
|
-
"description": "(Claude/Codex) Multi-dimensional PR review orchestrator. Dispatches parallel reviewers (spec-conformance, correctness, test-quality, docs-sync, robustness, security, ux, performance, structure, code-quality, skill-plugin-quality) and synthesizes findings into an actionable punch list. Supports project-level custom reviewers via docs/rules/review
|
|
93
|
+
"description": "(Claude/Codex) Multi-dimensional PR review orchestrator. Dispatches parallel reviewers (spec-conformance, correctness, test-quality, docs-sync, robustness, security, ux, performance, structure, code-quality, skill-plugin-quality) and synthesizes findings into an actionable punch list. Supports project-level custom reviewers via `docs/rules/review/` and ships a `reviewer-creator` skill for scaffolding them.",
|
|
122
94
|
"agents": [
|
|
123
95
|
"claude",
|
|
124
96
|
"codex"
|
|
125
97
|
]
|
|
126
98
|
},
|
|
99
|
+
{
|
|
100
|
+
"name": "skill-creator",
|
|
101
|
+
"description": "Create and manage custom skills",
|
|
102
|
+
"agents": [
|
|
103
|
+
"claude"
|
|
104
|
+
],
|
|
105
|
+
"external": true
|
|
106
|
+
},
|
|
107
|
+
{
|
|
108
|
+
"name": "claude-md-management",
|
|
109
|
+
"description": "Audit and improve CLAUDE.md files",
|
|
110
|
+
"agents": [
|
|
111
|
+
"claude"
|
|
112
|
+
],
|
|
113
|
+
"external": true
|
|
114
|
+
},
|
|
115
|
+
{
|
|
116
|
+
"name": "codex",
|
|
117
|
+
"description": "Cross-model collaboration with Codex",
|
|
118
|
+
"agents": [
|
|
119
|
+
"claude"
|
|
120
|
+
],
|
|
121
|
+
"external": true
|
|
122
|
+
},
|
|
127
123
|
{
|
|
128
124
|
"name": "session-instructions-loader",
|
|
129
125
|
"description": "(Codex) Injects extra instruction files on session start",
|
package/dist/cli.js
CHANGED
|
@@ -593,15 +593,15 @@ async function runUi(p, version) {
|
|
|
593
593
|
// Always read from the installed npm package; can't be fetched because
|
|
594
594
|
// dist/ is built artifact, not git content.
|
|
595
595
|
// - contentRoot: where the runtime install recipes live (CLAUDE.md,
|
|
596
|
-
//
|
|
597
|
-
//
|
|
596
|
+
// marketplace manifests, extra_plugin_configs.json, skills-lock.json).
|
|
597
|
+
// These files are
|
|
598
598
|
// NOT in the npm tarball — the `files` allowlist only ships `dist/*`
|
|
599
599
|
// + npm defaults. They are fetched from GitHub, pinned to the CLI
|
|
600
600
|
// version tag, by fetchContentRoot(). Under DEV=1 fetchContentRoot
|
|
601
601
|
// short-circuits to the repo root so this is a no-op there.
|
|
602
602
|
// Without the contentRoot fix, tarball-installed Web UI users hit ENOENT
|
|
603
|
-
// on any
|
|
604
|
-
//
|
|
603
|
+
// on any plugin install (apply handlers read non-tarball install inputs
|
|
604
|
+
// from packageRoot).
|
|
605
605
|
const tarballRoot = getPackageRoot();
|
|
606
606
|
let contentRoot;
|
|
607
607
|
try {
|
|
@@ -671,8 +671,8 @@ async function runUi(p, version) {
|
|
|
671
671
|
pluginAgentsByName.set(name, def.agents);
|
|
672
672
|
}
|
|
673
673
|
const applyHandlers = buildDefaultApplyHandlers({
|
|
674
|
-
// contentRoot: install handlers read CLAUDE.md,
|
|
675
|
-
//
|
|
674
|
+
// contentRoot: install handlers read CLAUDE.md, marketplace manifests,
|
|
675
|
+
// extra_plugin_configs.json, and skills-lock.json — all CONTENT_FILES.
|
|
676
676
|
// Routing them at tarballRoot fails ENOENT for npm-installed users.
|
|
677
677
|
packageRoot: contentRoot,
|
|
678
678
|
cwd,
|
|
@@ -697,7 +697,7 @@ async function runUi(p, version) {
|
|
|
697
697
|
cwd,
|
|
698
698
|
// server reads dist/catalog.json (tarball-shipped) via
|
|
699
699
|
// buildScanCatalog on each /api/state call; install-time content
|
|
700
|
-
// (
|
|
700
|
+
// (marketplace manifests, extra plugin config, CLAUDE.md, …) was already injected
|
|
701
701
|
// into applyHandlers above with contentRoot.
|
|
702
702
|
packageRoot: tarballRoot,
|
|
703
703
|
heartbeatTimeoutMs: UI_HEARTBEAT_TIMEOUT_MS,
|
|
@@ -800,7 +800,7 @@ async function runLegacyMenu() {
|
|
|
800
800
|
message: "Select module types to install:",
|
|
801
801
|
choices: [
|
|
802
802
|
{ name: "Workflow — CLAUDE.md + AGENTS.md", value: "workflow", checked: true },
|
|
803
|
-
{ name: "Skills — Development process skills (
|
|
803
|
+
{ name: "Skills — Development process skills (TDD, debugging, verification, planning...)", value: "skills", checked: true },
|
|
804
804
|
{ name: "Recommended Skills — Extra utility skills (claude-code-agent, codex-agent...)", value: "recommended", checked: true },
|
|
805
805
|
{ name: "Plugins — Claude Code / Codex plugins (skill-creator, codex, auriga-go...)", value: "plugins", checked: true },
|
|
806
806
|
{ name: "Hooks — Claude Code hooks (notifications, etc.)", value: "hooks", checked: true },
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import { type MarketplaceRef } from "./marketplace.js";
|
|
2
1
|
export interface CodexMarketplacePlugin {
|
|
3
2
|
name: string;
|
|
4
3
|
source?: {
|
|
@@ -10,16 +9,6 @@ export interface CodexMarketplace {
|
|
|
10
9
|
name: string;
|
|
11
10
|
plugins: CodexMarketplacePlugin[];
|
|
12
11
|
}
|
|
13
|
-
export interface CodexInstallPlugin {
|
|
14
|
-
name: string;
|
|
15
|
-
description?: string;
|
|
16
|
-
defaultOn?: boolean;
|
|
17
|
-
marketplace?: MarketplaceRef;
|
|
18
|
-
}
|
|
19
|
-
export interface CodexInstallConfig {
|
|
20
|
-
plugins: CodexInstallPlugin[];
|
|
21
|
-
}
|
|
22
12
|
export declare function validateCodexMarketplace(raw: unknown): asserts raw is CodexMarketplace;
|
|
23
|
-
export declare function validateCodexInstallConfig(raw: unknown): asserts raw is CodexInstallConfig;
|
|
24
13
|
export declare function codexLocalPluginPath(plugin: CodexMarketplacePlugin): string | undefined;
|
|
25
14
|
export declare function codexManifestPath(plugin: CodexMarketplacePlugin): string | undefined;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import path from "node:path";
|
|
2
|
-
import { MARKETPLACE_NAME_RE
|
|
2
|
+
import { MARKETPLACE_NAME_RE } from "./marketplace.js";
|
|
3
3
|
const PLUGIN_NAME_RE = /^[A-Za-z0-9][A-Za-z0-9._-]{0,127}$/;
|
|
4
4
|
export function validateCodexMarketplace(raw) {
|
|
5
5
|
if (!raw || typeof raw !== "object") {
|
|
@@ -22,33 +22,6 @@ export function validateCodexMarketplace(raw) {
|
|
|
22
22
|
}
|
|
23
23
|
}
|
|
24
24
|
}
|
|
25
|
-
export function validateCodexInstallConfig(raw) {
|
|
26
|
-
if (!raw || typeof raw !== "object") {
|
|
27
|
-
throw new Error("Codex install.json: root must be an object");
|
|
28
|
-
}
|
|
29
|
-
const cfg = raw;
|
|
30
|
-
if (!Array.isArray(cfg.plugins)) {
|
|
31
|
-
throw new Error("Codex install.json: .plugins must be an array");
|
|
32
|
-
}
|
|
33
|
-
for (const [i, plugin] of cfg.plugins.entries()) {
|
|
34
|
-
if (!plugin || typeof plugin !== "object") {
|
|
35
|
-
throw new Error(`Codex install.json: plugins[${i}] must be an object`);
|
|
36
|
-
}
|
|
37
|
-
const p = plugin;
|
|
38
|
-
if (typeof p.name !== "string" || !PLUGIN_NAME_RE.test(p.name)) {
|
|
39
|
-
throw new Error(`Codex install.json: plugins[${i}].name ${JSON.stringify(p.name)} does not match ${PLUGIN_NAME_RE}`);
|
|
40
|
-
}
|
|
41
|
-
if (p.description !== undefined && typeof p.description !== "string") {
|
|
42
|
-
throw new Error(`Codex install.json: plugins[${i}].description must be a string`);
|
|
43
|
-
}
|
|
44
|
-
if (p.defaultOn !== undefined && typeof p.defaultOn !== "boolean") {
|
|
45
|
-
throw new Error(`Codex install.json: plugins[${i}].defaultOn must be a boolean`);
|
|
46
|
-
}
|
|
47
|
-
if (p.marketplace !== undefined) {
|
|
48
|
-
validateMarketplaceField(`Codex install.json: plugins[${i}]`, p.marketplace);
|
|
49
|
-
}
|
|
50
|
-
}
|
|
51
|
-
}
|
|
52
25
|
export function codexLocalPluginPath(plugin) {
|
|
53
26
|
const sourcePath = typeof plugin.source === "object" && plugin.source?.source === "local"
|
|
54
27
|
? plugin.source.path
|
package/dist/guide.js
CHANGED
|
@@ -68,7 +68,7 @@ the legacy hooks category is currently empty; recommended skills are NOT include
|
|
|
68
68
|
|
|
69
69
|
Targeted — single category, picking from the catalog surfaced in Step 2:
|
|
70
70
|
${cmd("npx -y auriga-cli install workflow --lang en")}
|
|
71
|
-
${cmd("npx -y auriga-cli install skills --skill
|
|
71
|
+
${cmd("npx -y auriga-cli install skills --skill systematic-debugging test-driven-development")}
|
|
72
72
|
${cmd("npx -y auriga-cli install plugins --plugin skill-creator codex --scope user")}
|
|
73
73
|
${cmd("npx -y auriga-cli install plugins --agent codex --plugin session-instructions-loader")}
|
|
74
74
|
|
|
@@ -93,8 +93,8 @@ Exit codes:
|
|
|
93
93
|
|
|
94
94
|
${h("## Step 4 — Reload session (REQUIRED when installed non-interactively)")}
|
|
95
95
|
|
|
96
|
-
${warn("⚠")} CLAUDE.md, .agents/skills/,
|
|
97
|
-
|
|
96
|
+
${warn("⚠")} CLAUDE.md, .agents/skills/, plugin enablement, and hook/plugin
|
|
97
|
+
registrations are loaded at session startup. If you ran
|
|
98
98
|
\`npx -y auriga-cli install\` inside an existing Claude Code or Codex session
|
|
99
99
|
(e.g., \`claude -p\` / \`claude -p --worktree\` / \`codex exec\`), the current session
|
|
100
100
|
will NOT see the new harness.
|
|
@@ -106,11 +106,11 @@ Action:
|
|
|
106
106
|
|
|
107
107
|
${h("## Step 5 — Verify install")}
|
|
108
108
|
|
|
109
|
-
Expected artifacts:
|
|
109
|
+
Expected artifacts/checks:
|
|
110
110
|
- CLAUDE.md (workflow manifesto)
|
|
111
111
|
- AGENTS.md -> CLAUDE.md (symlink)
|
|
112
112
|
- .agents/skills/<name>/ (one per installed skill)
|
|
113
|
-
-
|
|
113
|
+
- claude plugins list (shows Claude plugins, if Claude plugins selected)
|
|
114
114
|
- ~/.codex/config.toml (Codex plugin enablement, if Codex plugins selected)
|
|
115
115
|
- .claude/settings.json (updated hook/plugin registrations, if selected)
|
|
116
116
|
- .claude/auriga-notify/ (project notify config, if auriga-notify selected)
|
package/dist/hooks.js
CHANGED
|
@@ -5,11 +5,11 @@ import path from "node:path";
|
|
|
5
5
|
import { checkbox, confirm, input, select } from "@inquirer/prompts";
|
|
6
6
|
import { atomicWriteFile, exec, fetchExtraContentBinary, log, withEsc, } from "./utils.js";
|
|
7
7
|
// --- Registry validation ---
|
|
8
|
-
// hooks
|
|
9
|
-
//
|
|
10
|
-
// filesystem paths is one
|
|
11
|
-
//
|
|
12
|
-
//
|
|
8
|
+
// The root hooks registry is legacy-only, but when present it may still be
|
|
9
|
+
// loaded from runtime-fetched content. Any downstream code that interpolates
|
|
10
|
+
// registry values into shell commands or filesystem paths is one bad config
|
|
11
|
+
// away from RCE / arbitrary-file-write. Validate every untrusted value once at
|
|
12
|
+
// load time, then trust it through the rest of the install flow.
|
|
13
13
|
const HOOK_NAME_RE = /^[a-z][a-z0-9-]*$/;
|
|
14
14
|
// Matches a flat brew formula name (`jq`, `pngquant`) OR a fully
|
|
15
15
|
// qualified tap-prefixed name (`vjeantet/tap/alerter`) — up to 2
|
|
@@ -424,12 +424,11 @@ function preflightDeps(hook) {
|
|
|
424
424
|
* Lazy-fetch a hook's payload files into `packageRoot` so they can be
|
|
425
425
|
* copied from there into the user's target directory.
|
|
426
426
|
*
|
|
427
|
-
* IMPORTANT:
|
|
428
|
-
*
|
|
429
|
-
*
|
|
430
|
-
*
|
|
431
|
-
*
|
|
432
|
-
* repo root, so the files are already on disk and we skip the fetch.
|
|
427
|
+
* IMPORTANT: this is retained for legacy root-hook installs. New hooks should
|
|
428
|
+
* ship inside plugins instead. In production, `packageRoot` is the temp dir
|
|
429
|
+
* created by `fetchContentRoot()` (utils.ts) — not the npm package install
|
|
430
|
+
* dir. In DEV mode `packageRoot` is the live repo root, so the files are
|
|
431
|
+
* already on disk and we skip the fetch.
|
|
433
432
|
*
|
|
434
433
|
* The hook payload list is owned by `hook.files` in `hooks.json`, which
|
|
435
434
|
* loadHooksConfig already validated for path-traversal safety, so each
|
|
@@ -540,6 +539,8 @@ function writeMergedSettings(resolved, hook, parsed) {
|
|
|
540
539
|
}
|
|
541
540
|
export function loadHooksConfig(packageRoot) {
|
|
542
541
|
const configPath = path.join(packageRoot, ".claude", "hooks", "hooks.json");
|
|
542
|
+
if (!fs.existsSync(configPath))
|
|
543
|
+
return { hooks: [] };
|
|
543
544
|
const raw = JSON.parse(fs.readFileSync(configPath, "utf-8"));
|
|
544
545
|
if (!raw || !Array.isArray(raw.hooks)) {
|
|
545
546
|
throw new Error(`${configPath} must have a "hooks" array at the top level`);
|
package/dist/marketplace.js
CHANGED
|
@@ -1,25 +1,23 @@
|
|
|
1
1
|
// Shared shape + validators for cross-Agent marketplace references.
|
|
2
2
|
// Used by:
|
|
3
|
-
// -
|
|
4
|
-
// -
|
|
5
|
-
// (Codex side, .agents/plugins/install.json)
|
|
3
|
+
// - extra_plugin_configs.json external plugin refs
|
|
4
|
+
// - Codex local marketplace materialization refs
|
|
6
5
|
//
|
|
7
6
|
// Both sides interpolate `<source>` into shell commands like
|
|
8
7
|
// `codex plugin marketplace add https://github.com/<source>.git` and
|
|
9
8
|
// `<plugin>@<name>` into TOML keys, so these regexes are the only thing
|
|
10
9
|
// standing between a compromised metadata source and arbitrary command
|
|
11
10
|
// execution. Tighten with care — a regression here is a shell-injection
|
|
12
|
-
// vector.
|
|
11
|
+
// vector. The metadata files are fetched from raw GitHub at runtime.
|
|
13
12
|
export const MARKETPLACE_NAME_RE = /^[A-Za-z0-9][A-Za-z0-9._-]{0,127}$/;
|
|
14
13
|
// GitHub `owner/repo` shape: exactly one `/`, both segments kebab-case-ish
|
|
15
14
|
// without leading punctuation. Tighter than the prior PLUGIN_SOURCE_RE
|
|
16
15
|
// which permitted multi-slash / `..` / trailing `.git` patterns and would
|
|
17
16
|
// compose into confusing git-layer errors like `https://github.com/a/../b.git`.
|
|
18
17
|
export const MARKETPLACE_SOURCE_RE = /^[A-Za-z0-9][A-Za-z0-9._-]{0,127}\/[A-Za-z0-9][A-Za-z0-9._-]{0,127}$/;
|
|
19
|
-
// Centralizes the marketplace field shape check so
|
|
20
|
-
//
|
|
21
|
-
//
|
|
22
|
-
// the caller's file context (e.g. `plugins.json: plugins[3]`) survives.
|
|
18
|
+
// Centralizes the marketplace field shape check so Claude and Codex plugin
|
|
19
|
+
// config paths stay in lockstep. `label` is interpolated into the thrown Error
|
|
20
|
+
// so the caller's file context survives.
|
|
23
21
|
export function validateMarketplaceField(label, raw) {
|
|
24
22
|
if (!raw || typeof raw !== "object") {
|
|
25
23
|
throw new Error(`${label}.marketplace must be an object`);
|
package/dist/plugins.d.ts
CHANGED
|
@@ -1,5 +1,41 @@
|
|
|
1
|
-
import
|
|
2
|
-
|
|
1
|
+
import { type MarketplaceRef } from "./marketplace.js";
|
|
2
|
+
import type { InstallOpts } from "./utils.js";
|
|
3
|
+
export type PluginRuntime = "claude" | "codex";
|
|
4
|
+
export interface ClaudeMarketplacePlugin {
|
|
5
|
+
name: string;
|
|
6
|
+
description?: string;
|
|
7
|
+
source?: string;
|
|
8
|
+
}
|
|
9
|
+
export interface ClaudeMarketplace {
|
|
10
|
+
name: string;
|
|
11
|
+
plugins: ClaudeMarketplacePlugin[];
|
|
12
|
+
}
|
|
13
|
+
export interface ExtraPluginConfig {
|
|
14
|
+
name: string;
|
|
15
|
+
agents?: PluginRuntime[];
|
|
16
|
+
description?: string;
|
|
17
|
+
defaultOn?: boolean;
|
|
18
|
+
claude?: {
|
|
19
|
+
package?: string;
|
|
20
|
+
marketplace?: MarketplaceRef;
|
|
21
|
+
};
|
|
22
|
+
codex?: {
|
|
23
|
+
marketplace?: MarketplaceRef;
|
|
24
|
+
};
|
|
25
|
+
}
|
|
26
|
+
export interface ExtraPluginConfigs {
|
|
27
|
+
plugins: ExtraPluginConfig[];
|
|
28
|
+
}
|
|
29
|
+
export declare function validateExtraPluginConfigs(raw: unknown): asserts raw is ExtraPluginConfigs;
|
|
30
|
+
export declare function loadExtraPluginConfigs(packageRoot: string): ExtraPluginConfigs;
|
|
31
|
+
export declare function extraAppliesTo(extra: ExtraPluginConfig, runtime: PluginRuntime): boolean;
|
|
32
|
+
export declare function extraByNameForRuntime(extras: ExtraPluginConfigs, runtime: PluginRuntime): Map<string, ExtraPluginConfig>;
|
|
33
|
+
export declare function applyExtraPluginFields<T extends {
|
|
34
|
+
name: string;
|
|
35
|
+
description?: string;
|
|
36
|
+
defaultOn?: boolean;
|
|
37
|
+
}>(plugin: T, extra: ExtraPluginConfig | undefined): T;
|
|
38
|
+
export declare function loadClaudeMarketplace(packageRoot: string): ClaudeMarketplace | null;
|
|
3
39
|
export declare function installPlugins(packageRoot: string, opts: InstallOpts): Promise<void>;
|
|
4
40
|
/**
|
|
5
41
|
* Uninstall a single plugin.
|
package/dist/plugins.js
CHANGED
|
@@ -3,18 +3,19 @@ import os from "node:os";
|
|
|
3
3
|
import path from "node:path";
|
|
4
4
|
import { checkbox, select } from "@inquirer/prompts";
|
|
5
5
|
import { parse as parseToml, stringify as stringifyToml } from "smol-toml";
|
|
6
|
-
import { codexLocalPluginPath, codexManifestPath,
|
|
6
|
+
import { codexLocalPluginPath, codexManifestPath, validateCodexMarketplace, } from "./codex-plugin-config.js";
|
|
7
7
|
import { validateMarketplaceField } from "./marketplace.js";
|
|
8
|
-
import { atomicWriteFile, exec, execAsync,
|
|
8
|
+
import { atomicWriteFile, exec, execAsync, log, withEsc } from "./utils.js";
|
|
9
9
|
// Plugin names and plugin-package names end up in `claude plugins ...`
|
|
10
|
-
// shell commands via string interpolation.
|
|
11
|
-
// fetched from raw GitHub at runtime, so every value must pass a
|
|
10
|
+
// shell commands via string interpolation. Marketplace and extra config
|
|
11
|
+
// files are fetched from raw GitHub at runtime, so every value must pass a
|
|
12
12
|
// conservative whitelist before composing the command. Without this a
|
|
13
|
-
// compromised
|
|
13
|
+
// compromised config would execute arbitrary commands via shell
|
|
14
14
|
// metachar injection. Marketplace shape (name + source) lives in
|
|
15
15
|
// `./marketplace.js` so Claude and Codex sides share one validator.
|
|
16
16
|
const PLUGIN_NAME_RE = /^[A-Za-z0-9][A-Za-z0-9._-]{0,127}$/;
|
|
17
17
|
const PLUGIN_PACKAGE_RE = /^[A-Za-z0-9][A-Za-z0-9._@/-]{0,255}$/;
|
|
18
|
+
const LOCAL_MARKETPLACE_SOURCE = "Ben2pc/auriga-cli";
|
|
18
19
|
const MIGRATED_WORKFLOW_SKILLS = [
|
|
19
20
|
"incremental-impl",
|
|
20
21
|
"test-designer",
|
|
@@ -24,30 +25,73 @@ const NOTIFY_PLUGIN_NAME = "auriga-notify";
|
|
|
24
25
|
const WORKFLOW_SKILLS_PLUGIN_NAME = "auriga-workflow-skills";
|
|
25
26
|
const LEGACY_NOTIFY_MARKER = "auriga:notify";
|
|
26
27
|
const CODEX_PLUGIN_VERSION_RE = /^[A-Za-z0-9][A-Za-z0-9._+-]{0,127}$/;
|
|
27
|
-
|
|
28
|
+
function validateClaudeMarketplace(raw) {
|
|
28
29
|
if (!raw || typeof raw !== "object") {
|
|
29
|
-
throw new Error("
|
|
30
|
+
throw new Error("Claude marketplace.json: root must be an object");
|
|
30
31
|
}
|
|
31
32
|
const cfg = raw;
|
|
33
|
+
if (typeof cfg.name !== "string" || !PLUGIN_NAME_RE.test(cfg.name)) {
|
|
34
|
+
throw new Error("Claude marketplace.json: root must include a safe name");
|
|
35
|
+
}
|
|
32
36
|
if (!Array.isArray(cfg.plugins)) {
|
|
33
|
-
throw new Error("
|
|
37
|
+
throw new Error("Claude marketplace.json: .plugins must be an array");
|
|
34
38
|
}
|
|
35
39
|
cfg.plugins.forEach((p, i) => {
|
|
36
40
|
if (!p || typeof p !== "object") {
|
|
37
|
-
throw new Error(`
|
|
41
|
+
throw new Error(`Claude marketplace.json: plugins[${i}] must be an object`);
|
|
38
42
|
}
|
|
39
43
|
const plugin = p;
|
|
40
44
|
if (typeof plugin.name !== "string" || !PLUGIN_NAME_RE.test(plugin.name)) {
|
|
41
|
-
throw new Error(`
|
|
45
|
+
throw new Error(`Claude marketplace.json: plugins[${i}].name ${JSON.stringify(plugin.name)} does not match ${PLUGIN_NAME_RE}`);
|
|
42
46
|
}
|
|
43
|
-
if (typeof plugin.
|
|
44
|
-
throw new Error(`
|
|
47
|
+
if (plugin.description !== undefined && typeof plugin.description !== "string") {
|
|
48
|
+
throw new Error(`Claude marketplace.json: plugins[${i}].description must be a string`);
|
|
45
49
|
}
|
|
46
|
-
|
|
47
|
-
|
|
50
|
+
});
|
|
51
|
+
}
|
|
52
|
+
export function validateExtraPluginConfigs(raw) {
|
|
53
|
+
if (!raw || typeof raw !== "object") {
|
|
54
|
+
throw new Error("extra_plugin_configs.json: root must be an object");
|
|
55
|
+
}
|
|
56
|
+
const cfg = raw;
|
|
57
|
+
if (!Array.isArray(cfg.plugins)) {
|
|
58
|
+
throw new Error("extra_plugin_configs.json: .plugins must be an array");
|
|
59
|
+
}
|
|
60
|
+
cfg.plugins.forEach((p, i) => {
|
|
61
|
+
if (!p || typeof p !== "object") {
|
|
62
|
+
throw new Error(`extra_plugin_configs.json: plugins[${i}] must be an object`);
|
|
63
|
+
}
|
|
64
|
+
const plugin = p;
|
|
65
|
+
if (typeof plugin.name !== "string" || !PLUGIN_NAME_RE.test(plugin.name)) {
|
|
66
|
+
throw new Error(`extra_plugin_configs.json: plugins[${i}].name ${JSON.stringify(plugin.name)} does not match ${PLUGIN_NAME_RE}`);
|
|
67
|
+
}
|
|
68
|
+
if (plugin.agents !== undefined) {
|
|
69
|
+
if (!Array.isArray(plugin.agents) || !plugin.agents.every((agent) => agent === "claude" || agent === "codex")) {
|
|
70
|
+
throw new Error(`extra_plugin_configs.json: plugins[${i}].agents must contain only claude/codex`);
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
if (plugin.description !== undefined && typeof plugin.description !== "string") {
|
|
74
|
+
throw new Error(`extra_plugin_configs.json: plugins[${i}].description must be a string`);
|
|
48
75
|
}
|
|
49
76
|
if (plugin.defaultOn !== undefined && typeof plugin.defaultOn !== "boolean") {
|
|
50
|
-
throw new Error(`
|
|
77
|
+
throw new Error(`extra_plugin_configs.json: plugins[${i}].defaultOn must be a boolean`);
|
|
78
|
+
}
|
|
79
|
+
for (const runtime of ["claude", "codex"]) {
|
|
80
|
+
const runtimeCfg = plugin[runtime];
|
|
81
|
+
if (runtimeCfg === undefined)
|
|
82
|
+
continue;
|
|
83
|
+
if (!runtimeCfg || typeof runtimeCfg !== "object") {
|
|
84
|
+
throw new Error(`extra_plugin_configs.json: plugins[${i}].${runtime} must be an object`);
|
|
85
|
+
}
|
|
86
|
+
const runtimeRecord = runtimeCfg;
|
|
87
|
+
if (runtime === "claude" && runtimeRecord.package !== undefined) {
|
|
88
|
+
if (typeof runtimeRecord.package !== "string" || !PLUGIN_PACKAGE_RE.test(runtimeRecord.package)) {
|
|
89
|
+
throw new Error(`extra_plugin_configs.json: plugins[${i}].claude.package ${JSON.stringify(runtimeRecord.package)} does not match ${PLUGIN_PACKAGE_RE}`);
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
if (runtimeRecord.marketplace !== undefined) {
|
|
93
|
+
validateMarketplaceField(`extra_plugin_configs.json: plugins[${i}].${runtime}`, runtimeRecord.marketplace);
|
|
94
|
+
}
|
|
51
95
|
}
|
|
52
96
|
});
|
|
53
97
|
}
|
|
@@ -100,6 +144,67 @@ function getInstalledMarketplaces() {
|
|
|
100
144
|
return new Set();
|
|
101
145
|
}
|
|
102
146
|
}
|
|
147
|
+
export function loadExtraPluginConfigs(packageRoot) {
|
|
148
|
+
const configPath = path.join(packageRoot, "extra_plugin_configs.json");
|
|
149
|
+
if (!fs.existsSync(configPath))
|
|
150
|
+
return { plugins: [] };
|
|
151
|
+
const raw = JSON.parse(fs.readFileSync(configPath, "utf-8"));
|
|
152
|
+
validateExtraPluginConfigs(raw);
|
|
153
|
+
return raw;
|
|
154
|
+
}
|
|
155
|
+
export function extraAppliesTo(extra, runtime) {
|
|
156
|
+
return extra.agents === undefined || extra.agents.includes(runtime);
|
|
157
|
+
}
|
|
158
|
+
export function extraByNameForRuntime(extras, runtime) {
|
|
159
|
+
return new Map(extras.plugins
|
|
160
|
+
.filter((extra) => extraAppliesTo(extra, runtime))
|
|
161
|
+
.map((extra) => [extra.name, extra]));
|
|
162
|
+
}
|
|
163
|
+
export function applyExtraPluginFields(plugin, extra) {
|
|
164
|
+
if (!extra)
|
|
165
|
+
return plugin;
|
|
166
|
+
return {
|
|
167
|
+
...plugin,
|
|
168
|
+
...(extra.description !== undefined ? { description: extra.description } : {}),
|
|
169
|
+
...(extra.defaultOn !== undefined ? { defaultOn: extra.defaultOn } : {}),
|
|
170
|
+
};
|
|
171
|
+
}
|
|
172
|
+
export function loadClaudeMarketplace(packageRoot) {
|
|
173
|
+
const marketplacePath = path.join(packageRoot, ".claude-plugin", "marketplace.json");
|
|
174
|
+
if (!fs.existsSync(marketplacePath))
|
|
175
|
+
return null;
|
|
176
|
+
const raw = JSON.parse(fs.readFileSync(marketplacePath, "utf-8"));
|
|
177
|
+
validateClaudeMarketplace(raw);
|
|
178
|
+
return raw;
|
|
179
|
+
}
|
|
180
|
+
function loadClaudePluginsConfig(packageRoot) {
|
|
181
|
+
const extras = loadExtraPluginConfigs(packageRoot);
|
|
182
|
+
const extraByName = extraByNameForRuntime(extras, "claude");
|
|
183
|
+
const marketplace = loadClaudeMarketplace(packageRoot);
|
|
184
|
+
const plugins = new Map();
|
|
185
|
+
if (marketplace) {
|
|
186
|
+
for (const plugin of marketplace.plugins) {
|
|
187
|
+
plugins.set(plugin.name, applyExtraPluginFields({
|
|
188
|
+
name: plugin.name,
|
|
189
|
+
package: `${plugin.name}@${marketplace.name}`,
|
|
190
|
+
description: plugin.description ?? plugin.name,
|
|
191
|
+
marketplace: { name: marketplace.name, source: LOCAL_MARKETPLACE_SOURCE },
|
|
192
|
+
}, extraByName.get(plugin.name)));
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
for (const extra of extras.plugins) {
|
|
196
|
+
if (!extraAppliesTo(extra, "claude") || !extra.claude?.package)
|
|
197
|
+
continue;
|
|
198
|
+
plugins.set(extra.name, {
|
|
199
|
+
name: extra.name,
|
|
200
|
+
package: extra.claude.package,
|
|
201
|
+
description: extra.description ?? extra.name,
|
|
202
|
+
...(extra.defaultOn !== undefined ? { defaultOn: extra.defaultOn } : {}),
|
|
203
|
+
...(extra.claude.marketplace ? { marketplace: extra.claude.marketplace } : {}),
|
|
204
|
+
});
|
|
205
|
+
}
|
|
206
|
+
return plugins.size > 0 ? { plugins: [...plugins.values()] } : null;
|
|
207
|
+
}
|
|
103
208
|
function loadCodexMarketplace(packageRoot) {
|
|
104
209
|
const marketplacePath = path.join(packageRoot, ".agents", "plugins", "marketplace.json");
|
|
105
210
|
if (!fs.existsSync(marketplacePath))
|
|
@@ -109,12 +214,28 @@ function loadCodexMarketplace(packageRoot) {
|
|
|
109
214
|
return raw;
|
|
110
215
|
}
|
|
111
216
|
function loadCodexInstallConfig(packageRoot) {
|
|
112
|
-
const
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
const
|
|
116
|
-
|
|
117
|
-
|
|
217
|
+
const extras = loadExtraPluginConfigs(packageRoot);
|
|
218
|
+
const extraByName = extraByNameForRuntime(extras, "codex");
|
|
219
|
+
const marketplace = loadCodexMarketplace(packageRoot);
|
|
220
|
+
const plugins = new Map();
|
|
221
|
+
if (marketplace) {
|
|
222
|
+
for (const plugin of marketplace.plugins) {
|
|
223
|
+
plugins.set(plugin.name, applyExtraPluginFields({
|
|
224
|
+
name: plugin.name,
|
|
225
|
+
}, extraByName.get(plugin.name)));
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
for (const extra of extras.plugins) {
|
|
229
|
+
if (!extraAppliesTo(extra, "codex") || !extra.codex?.marketplace)
|
|
230
|
+
continue;
|
|
231
|
+
plugins.set(extra.name, {
|
|
232
|
+
name: extra.name,
|
|
233
|
+
description: extra.description,
|
|
234
|
+
...(extra.defaultOn !== undefined ? { defaultOn: extra.defaultOn } : {}),
|
|
235
|
+
marketplace: extra.codex.marketplace,
|
|
236
|
+
});
|
|
237
|
+
}
|
|
238
|
+
return plugins.size > 0 ? { plugins: [...plugins.values()] } : null;
|
|
118
239
|
}
|
|
119
240
|
function resolveCodexPluginSelection(all, selected) {
|
|
120
241
|
if (!selected)
|
|
@@ -131,6 +252,17 @@ function resolveCodexPluginSelection(all, selected) {
|
|
|
131
252
|
function codexHome() {
|
|
132
253
|
return process.env.CODEX_HOME || path.join(os.homedir(), ".codex");
|
|
133
254
|
}
|
|
255
|
+
function codexMarketplaceCacheRoot(marketplaceName) {
|
|
256
|
+
return path.join(codexHome(), ".tmp", "marketplaces", marketplaceName);
|
|
257
|
+
}
|
|
258
|
+
function resolveCodexMarketplaceContentRoot(packageRoot, marketplaceName) {
|
|
259
|
+
const cachedRoot = codexMarketplaceCacheRoot(marketplaceName);
|
|
260
|
+
if (fs.existsSync(path.join(cachedRoot, ".agents", "plugins", "marketplace.json"))) {
|
|
261
|
+
return cachedRoot;
|
|
262
|
+
}
|
|
263
|
+
throw new Error(`Codex marketplace ${marketplaceName} cache missing at ${cachedRoot}. ` +
|
|
264
|
+
"Run `codex plugin marketplace add/upgrade` successfully before materializing local plugins.");
|
|
265
|
+
}
|
|
134
266
|
function shellQuote(value) {
|
|
135
267
|
return `'${value.replace(/'/g, "'\\''")}'`;
|
|
136
268
|
}
|
|
@@ -297,7 +429,7 @@ function codexMarketplaceAddCommand(packageRoot) {
|
|
|
297
429
|
return "codex plugin marketplace add https://github.com/Ben2pc/auriga-cli.git";
|
|
298
430
|
}
|
|
299
431
|
function codexExternalMarketplaceAddCommand(source) {
|
|
300
|
-
// `source` is validated by
|
|
432
|
+
// `source` is validated by validateExtraPluginConfigs against
|
|
301
433
|
// MARKETPLACE_SOURCE_RE (alphanumerics + `._/-`) — no shell metachars
|
|
302
434
|
// can reach this string. URL form deliberately mirrors
|
|
303
435
|
// codexMarketplaceAddCommand's hardcoded production branch.
|
|
@@ -323,8 +455,10 @@ function escapeRegex(value) {
|
|
|
323
455
|
function isCodexMarketplaceAlreadyAdded(error, marketplaceName) {
|
|
324
456
|
const text = commandErrorText(error);
|
|
325
457
|
const marketplacePattern = new RegExp(`marketplace ['"]?${escapeRegex(marketplaceName)}['"]? is already added`, "i");
|
|
326
|
-
return marketplacePattern.test(text)
|
|
327
|
-
|
|
458
|
+
return marketplacePattern.test(text);
|
|
459
|
+
}
|
|
460
|
+
function isCodexMarketplaceDifferentSource(error) {
|
|
461
|
+
return /already added from a different source/i.test(commandErrorText(error));
|
|
328
462
|
}
|
|
329
463
|
function pluginHasHooks(packageRoot, plugin) {
|
|
330
464
|
const relativeManifestPath = codexManifestPath(plugin);
|
|
@@ -341,12 +475,12 @@ function resolveSelectedCodexMarketplacePlugins(localMarketplace, localSelected)
|
|
|
341
475
|
return localSelected.map((p) => {
|
|
342
476
|
const plugin = localMpByName.get(p.name);
|
|
343
477
|
if (!plugin) {
|
|
344
|
-
throw new Error(`Codex
|
|
478
|
+
throw new Error(`Codex plugin ${p.name} is selected but not present in marketplace.json`);
|
|
345
479
|
}
|
|
346
480
|
return plugin;
|
|
347
481
|
});
|
|
348
482
|
}
|
|
349
|
-
|
|
483
|
+
function ensureCodexPluginManifests(packageRoot, plugins) {
|
|
350
484
|
for (const plugin of plugins) {
|
|
351
485
|
const manifestPath = codexManifestPath(plugin);
|
|
352
486
|
if (!manifestPath) {
|
|
@@ -354,7 +488,7 @@ async function ensureCodexPluginManifests(packageRoot, plugins) {
|
|
|
354
488
|
}
|
|
355
489
|
if (fs.existsSync(path.join(packageRoot, manifestPath)))
|
|
356
490
|
continue;
|
|
357
|
-
|
|
491
|
+
throw new Error(`Codex plugin ${plugin.name} manifest missing at ${manifestPath}`);
|
|
358
492
|
}
|
|
359
493
|
}
|
|
360
494
|
function readCodexPluginVersion(packageRoot, plugin) {
|
|
@@ -489,7 +623,13 @@ async function addCodexMarketplaceWithRetry(marketplaceName, addCommand, opts, m
|
|
|
489
623
|
return;
|
|
490
624
|
}
|
|
491
625
|
catch (e) {
|
|
492
|
-
if (
|
|
626
|
+
if (isCodexMarketplaceDifferentSource(e)) {
|
|
627
|
+
const msg = `Codex marketplace ${marketplaceName} is already added from a different source`;
|
|
628
|
+
log.error(`${msg}\n${commandErrorText(e)}`);
|
|
629
|
+
failures.push(msg);
|
|
630
|
+
return;
|
|
631
|
+
}
|
|
632
|
+
if (isCodexMarketplaceAlreadyAdded(e, marketplaceName)) {
|
|
493
633
|
try {
|
|
494
634
|
exec(codexMarketplaceUpgradeCommand(marketplaceName), marketplaceExecOpts);
|
|
495
635
|
log.ok(`Codex marketplace ${marketplaceName} upgraded`);
|
|
@@ -510,20 +650,20 @@ async function addCodexMarketplaceWithRetry(marketplaceName, addCommand, opts, m
|
|
|
510
650
|
}
|
|
511
651
|
// Builds the `<name>@<marketplace>` config keys + decides whether
|
|
512
652
|
// features.plugin_hooks needs to flip on. Local plugins resolve through
|
|
513
|
-
// this repo's marketplace.json and require a manifest
|
|
514
|
-
// inspection; external plugins emit a key directly from
|
|
653
|
+
// this repo's marketplace.json and require a manifest check + hooks
|
|
654
|
+
// inspection; external plugins emit a key directly from extra_plugin_configs.json
|
|
515
655
|
// (Codex CLI fetches the upstream manifest itself). External plugins do
|
|
516
656
|
// NOT flip plugin_hooks today — we don't have access to the upstream
|
|
517
657
|
// manifest at install time. Acceptable while no external plugin ships
|
|
518
658
|
// hooks; once one does, prefer fetching the manifest or adding an
|
|
519
|
-
// explicit `requiresPluginHooks: true` field on the
|
|
520
|
-
async function composeCodexPluginKeys(
|
|
659
|
+
// explicit `requiresPluginHooks: true` field on the extra config entry.
|
|
660
|
+
async function composeCodexPluginKeys(pluginContentRoot, localMarketplace, selectedMarketplacePlugins, externalSelected) {
|
|
521
661
|
const pluginKeys = [];
|
|
522
662
|
let needsPluginHooks = false;
|
|
523
663
|
if (localMarketplace) {
|
|
524
664
|
for (const plugin of selectedMarketplacePlugins) {
|
|
525
665
|
pluginKeys.push(`${plugin.name}@${localMarketplace.name}`);
|
|
526
|
-
if (pluginHasHooks(
|
|
666
|
+
if (pluginHasHooks(pluginContentRoot, plugin))
|
|
527
667
|
needsPluginHooks = true;
|
|
528
668
|
}
|
|
529
669
|
}
|
|
@@ -535,7 +675,7 @@ async function composeCodexPluginKeys(packageRoot, localMarketplace, selectedMar
|
|
|
535
675
|
async function installCodexPlugins(packageRoot, opts) {
|
|
536
676
|
const installConfig = loadCodexInstallConfig(packageRoot);
|
|
537
677
|
if (!installConfig) {
|
|
538
|
-
const msg = "No .agents/plugins/
|
|
678
|
+
const msg = "No Codex plugins found in .agents/plugins/marketplace.json or extra_plugin_configs.json";
|
|
539
679
|
if (!opts.interactive)
|
|
540
680
|
throw new Error(msg);
|
|
541
681
|
log.warn(msg);
|
|
@@ -555,11 +695,10 @@ async function installCodexPlugins(packageRoot, opts) {
|
|
|
555
695
|
log.skip("No Codex plugins selected");
|
|
556
696
|
return;
|
|
557
697
|
}
|
|
558
|
-
// Local plugins are described by this repo's .agents/plugins/marketplace.json
|
|
559
|
-
//
|
|
560
|
-
//
|
|
561
|
-
//
|
|
562
|
-
// marketplace and emit the right `<name>@<marketplace>` plugin key.
|
|
698
|
+
// Local plugins are described by this repo's .agents/plugins/marketplace.json.
|
|
699
|
+
// External plugins come from extra_plugin_configs.json and are resolved by
|
|
700
|
+
// Codex CLI itself when their marketplace is added — we only need to
|
|
701
|
+
// register that marketplace and emit the right `<name>@<marketplace>` key.
|
|
563
702
|
let localSelected = selected.filter((p) => p.marketplace === undefined);
|
|
564
703
|
const externalSelected = selected.filter((p) => p.marketplace !== undefined);
|
|
565
704
|
let localMarketplace = null;
|
|
@@ -599,14 +738,20 @@ async function installCodexPlugins(packageRoot, opts) {
|
|
|
599
738
|
await addCodexMarketplaceWithRetry(mp.name, codexExternalMarketplaceAddCommand(mp.source), opts, marketplaceExecOpts, failures);
|
|
600
739
|
}
|
|
601
740
|
if (failures.length === 0) {
|
|
602
|
-
const
|
|
603
|
-
?
|
|
741
|
+
const localMarketplaceContentRoot = localMarketplace
|
|
742
|
+
? resolveCodexMarketplaceContentRoot(packageRoot, localMarketplace.name)
|
|
743
|
+
: packageRoot;
|
|
744
|
+
const effectiveLocalMarketplace = localMarketplace
|
|
745
|
+
? loadCodexMarketplace(localMarketplaceContentRoot) ?? localMarketplace
|
|
746
|
+
: null;
|
|
747
|
+
const selectedMarketplacePlugins = effectiveLocalMarketplace
|
|
748
|
+
? resolveSelectedCodexMarketplacePlugins(effectiveLocalMarketplace, localSelected)
|
|
604
749
|
: [];
|
|
605
|
-
|
|
606
|
-
if (
|
|
607
|
-
materializeLocalCodexPluginCache(
|
|
750
|
+
ensureCodexPluginManifests(localMarketplaceContentRoot, selectedMarketplacePlugins);
|
|
751
|
+
if (effectiveLocalMarketplace) {
|
|
752
|
+
materializeLocalCodexPluginCache(localMarketplaceContentRoot, effectiveLocalMarketplace.name, selectedMarketplacePlugins);
|
|
608
753
|
}
|
|
609
|
-
const { pluginKeys, needsPluginHooks } = await composeCodexPluginKeys(
|
|
754
|
+
const { pluginKeys, needsPluginHooks } = await composeCodexPluginKeys(localMarketplaceContentRoot, effectiveLocalMarketplace, selectedMarketplacePlugins, externalSelected);
|
|
610
755
|
enableCodexPluginConfig(path.join(codexHome(), "config.toml"), pluginKeys, needsPluginHooks);
|
|
611
756
|
for (const plugin of [...localSelected, ...externalSelected]) {
|
|
612
757
|
log.ok(`${plugin.name} enabled for Codex`);
|
|
@@ -659,21 +804,17 @@ export async function installPlugins(packageRoot, opts) {
|
|
|
659
804
|
return;
|
|
660
805
|
}
|
|
661
806
|
const failures = [];
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
log.warn("No .claude/plugins.json found");
|
|
807
|
+
let config = loadClaudePluginsConfig(packageRoot);
|
|
808
|
+
if (!config) {
|
|
809
|
+
log.warn("No Claude plugins found in .claude-plugin/marketplace.json or extra_plugin_configs.json");
|
|
666
810
|
if (agent === "both")
|
|
667
811
|
failures.push("Claude Code plugins config missing");
|
|
668
812
|
else
|
|
669
813
|
return;
|
|
670
814
|
}
|
|
671
815
|
else {
|
|
672
|
-
const raw = JSON.parse(fs.readFileSync(configPath, "utf-8"));
|
|
673
|
-
validatePluginsConfig(raw);
|
|
674
|
-
config = raw;
|
|
675
816
|
if (config.plugins.length === 0) {
|
|
676
|
-
log.warn("No plugins defined
|
|
817
|
+
log.warn("No Claude plugins defined");
|
|
677
818
|
if (agent === "both")
|
|
678
819
|
failures.push("Claude Code plugins config empty");
|
|
679
820
|
else
|
package/dist/skills.js
CHANGED
|
@@ -7,7 +7,6 @@ import { atomicWriteFile, exec, execAsync, log, withEsc } from "./utils.js";
|
|
|
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 = [
|
|
10
|
-
"brainstorming",
|
|
11
10
|
"planning-with-files",
|
|
12
11
|
"playwright-cli",
|
|
13
12
|
"systematic-debugging",
|
package/dist/utils.js
CHANGED
|
@@ -148,53 +148,9 @@ function resolveContentRef() {
|
|
|
148
148
|
const CONTENT_FILES = [
|
|
149
149
|
"CLAUDE.md",
|
|
150
150
|
"skills-lock.json",
|
|
151
|
-
".claude/
|
|
151
|
+
".claude-plugin/marketplace.json",
|
|
152
152
|
".agents/plugins/marketplace.json",
|
|
153
|
-
".
|
|
154
|
-
".claude/hooks/hooks.json",
|
|
155
|
-
"plugins/auriga-go/.claude-plugin/plugin.json",
|
|
156
|
-
"plugins/auriga-go/.codex-plugin/plugin.json",
|
|
157
|
-
"plugins/auriga-go/README.md",
|
|
158
|
-
"plugins/auriga-go/skills/auriga-go/SKILL.md",
|
|
159
|
-
"plugins/auriga-go/skills/goalify/SKILL.md",
|
|
160
|
-
"plugins/auriga-git-guards/.claude-plugin/plugin.json",
|
|
161
|
-
"plugins/auriga-git-guards/.codex-plugin/plugin.json",
|
|
162
|
-
"plugins/auriga-git-guards/README.md",
|
|
163
|
-
"plugins/auriga-git-guards/hooks/hooks.json",
|
|
164
|
-
"plugins/auriga-git-guards/scripts/commit-reminder.mjs",
|
|
165
|
-
"plugins/auriga-git-guards/scripts/pr-create-guard.mjs",
|
|
166
|
-
"plugins/auriga-git-guards/scripts/pr-ready-guard.mjs",
|
|
167
|
-
"plugins/auriga-git-guards/skills/git-workflow/SKILL.md",
|
|
168
|
-
"plugins/auriga-workflow-skills/.claude-plugin/plugin.json",
|
|
169
|
-
"plugins/auriga-workflow-skills/.codex-plugin/plugin.json",
|
|
170
|
-
"plugins/auriga-workflow-skills/README.md",
|
|
171
|
-
"plugins/auriga-workflow-skills/skills/incremental-impl/SKILL.md",
|
|
172
|
-
"plugins/auriga-workflow-skills/skills/session-compound/SKILL.md",
|
|
173
|
-
"plugins/auriga-workflow-skills/skills/session-compound/analyzers/claude-code.mjs",
|
|
174
|
-
"plugins/auriga-workflow-skills/skills/session-compound/analyzers/codex.mjs",
|
|
175
|
-
"plugins/auriga-workflow-skills/skills/session-compound/template.html",
|
|
176
|
-
"plugins/auriga-workflow-skills/skills/test-designer/SKILL.md",
|
|
177
|
-
"plugins/session-instructions-loader/.codex-plugin/plugin.json",
|
|
178
|
-
"plugins/session-instructions-loader/README.md",
|
|
179
|
-
"plugins/session-instructions-loader/hooks/hooks.json",
|
|
180
|
-
"plugins/session-instructions-loader/scripts/session-start.mjs",
|
|
181
|
-
"plugins/deep-review/.claude-plugin/plugin.json",
|
|
182
|
-
"plugins/deep-review/.codex-plugin/plugin.json",
|
|
183
|
-
"plugins/deep-review/README.md",
|
|
184
|
-
"plugins/deep-review/skills/deep-review/SKILL.md",
|
|
185
|
-
"plugins/deep-review/skills/deep-review/references/reviewers/code-quality.md",
|
|
186
|
-
"plugins/deep-review/skills/deep-review/references/reviewers/correctness.md",
|
|
187
|
-
"plugins/deep-review/skills/deep-review/references/reviewers/docs-sync.md",
|
|
188
|
-
"plugins/deep-review/skills/deep-review/references/reviewers/performance.md",
|
|
189
|
-
"plugins/deep-review/skills/deep-review/references/reviewers/robustness.md",
|
|
190
|
-
"plugins/deep-review/skills/deep-review/references/reviewers/security.md",
|
|
191
|
-
"plugins/deep-review/skills/deep-review/references/reviewers/skill-plugin-quality.md",
|
|
192
|
-
"plugins/deep-review/skills/deep-review/references/reviewers/spec-conformance.md",
|
|
193
|
-
"plugins/deep-review/skills/deep-review/references/reviewers/structure.md",
|
|
194
|
-
"plugins/deep-review/skills/deep-review/references/reviewers/test-quality.md",
|
|
195
|
-
"plugins/deep-review/skills/deep-review/references/reviewers/ux.md",
|
|
196
|
-
"plugins/deep-review/skills/reviewer-creator/SKILL.md",
|
|
197
|
-
"plugins/deep-review/skills/reviewer-creator/references/template.md",
|
|
153
|
+
"extra_plugin_configs.json",
|
|
198
154
|
];
|
|
199
155
|
async function fetchFile(file) {
|
|
200
156
|
const ref = resolveContentRef();
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "auriga-cli",
|
|
3
|
-
"version": "1.20.
|
|
3
|
+
"version": "1.20.5",
|
|
4
4
|
"description": "Interactive CLI to install Claude Code harness modules (Workflow, Skills, Recommended Skills, Plugins, Hooks)",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|
|
@@ -25,8 +25,8 @@
|
|
|
25
25
|
"dev": "tsc --watch",
|
|
26
26
|
"start": "node dist/cli.js",
|
|
27
27
|
"pretest": "npm run build",
|
|
28
|
-
"test": "tsc -p tsconfig.test.json && DEV=1 node --test --experimental-test-module-mocks dist-test/tests/hooks.test.js dist-test/tests/hooks-uninstall.test.js dist-test/tests/skills.test.js dist-test/tests/skills-uninstall.test.js dist-test/tests/catalog.test.js dist-test/tests/cli-parse.test.js dist-test/tests/install-nontty.test.js dist-test/tests/plugins.test.js dist-test/tests/plugins-uninstall.test.js dist-test/tests/content-fetch.test.js dist-test/tests/utils.test.js dist-test/tests/guide.test.js dist-test/tests/validators.test.js dist-test/tests/entrypoint.test.js dist-test/tests/state.test.js dist-test/tests/server.test.js dist-test/tests/server-auth.test.js dist-test/tests/server-apply.test.js dist-test/tests/apply-handlers.test.js dist-test/tests/ui-fetch.test.js dist-test/tests/workflow-install.test.js dist-test/tests/workflow-uninstall.test.js dist-test/tests/tarball-shape.test.js",
|
|
29
|
-
"test:watch": "tsc -p tsconfig.test.json --watch & node --test --watch --experimental-test-module-mocks dist-test/tests/hooks.test.js dist-test/tests/hooks-uninstall.test.js dist-test/tests/skills.test.js dist-test/tests/skills-uninstall.test.js dist-test/tests/catalog.test.js dist-test/tests/cli-parse.test.js dist-test/tests/install-nontty.test.js dist-test/tests/plugins.test.js dist-test/tests/plugins-uninstall.test.js dist-test/tests/content-fetch.test.js dist-test/tests/utils.test.js dist-test/tests/guide.test.js dist-test/tests/validators.test.js dist-test/tests/entrypoint.test.js dist-test/tests/state.test.js dist-test/tests/server.test.js dist-test/tests/server-auth.test.js dist-test/tests/server-apply.test.js dist-test/tests/apply-handlers.test.js dist-test/tests/ui-fetch.test.js dist-test/tests/workflow-install.test.js dist-test/tests/workflow-uninstall.test.js dist-test/tests/tarball-shape.test.js",
|
|
28
|
+
"test": "tsc -p tsconfig.test.json && DEV=1 node --test --experimental-test-module-mocks dist-test/tests/hooks.test.js dist-test/tests/hooks-uninstall.test.js dist-test/tests/skills.test.js dist-test/tests/skills-uninstall.test.js dist-test/tests/catalog.test.js dist-test/tests/cli-parse.test.js dist-test/tests/install-nontty.test.js dist-test/tests/plugins.test.js dist-test/tests/plugins-uninstall.test.js dist-test/tests/content-fetch.test.js dist-test/tests/utils.test.js dist-test/tests/guide.test.js dist-test/tests/validators.test.js dist-test/tests/entrypoint.test.js dist-test/tests/state.test.js dist-test/tests/server.test.js dist-test/tests/server-auth.test.js dist-test/tests/server-apply.test.js dist-test/tests/apply-handlers.test.js dist-test/tests/ui-fetch.test.js dist-test/tests/workflow-install.test.js dist-test/tests/workflow-uninstall.test.js dist-test/tests/tarball-shape.test.js dist-test/tests/spec-design.test.js",
|
|
29
|
+
"test:watch": "tsc -p tsconfig.test.json --watch & node --test --watch --experimental-test-module-mocks dist-test/tests/hooks.test.js dist-test/tests/hooks-uninstall.test.js dist-test/tests/skills.test.js dist-test/tests/skills-uninstall.test.js dist-test/tests/catalog.test.js dist-test/tests/cli-parse.test.js dist-test/tests/install-nontty.test.js dist-test/tests/plugins.test.js dist-test/tests/plugins-uninstall.test.js dist-test/tests/content-fetch.test.js dist-test/tests/utils.test.js dist-test/tests/guide.test.js dist-test/tests/validators.test.js dist-test/tests/entrypoint.test.js dist-test/tests/state.test.js dist-test/tests/server.test.js dist-test/tests/server-auth.test.js dist-test/tests/server-apply.test.js dist-test/tests/apply-handlers.test.js dist-test/tests/ui-fetch.test.js dist-test/tests/workflow-install.test.js dist-test/tests/workflow-uninstall.test.js dist-test/tests/tarball-shape.test.js dist-test/tests/spec-design.test.js",
|
|
30
30
|
"pretest:e2e": "npm run build",
|
|
31
31
|
"test:e2e": "tsc -p tsconfig.test.json && node --test dist-test/tests/e2e-install.test.js",
|
|
32
32
|
"pretest:web-ui-e2e": "npm run build && npm --prefix ui ci && npm --prefix ui run build",
|