@moreih29/nexus-core 0.15.1 → 0.16.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.
Files changed (99) hide show
  1. package/dist/claude/.claude-plugin/marketplace.json +75 -0
  2. package/dist/claude/.claude-plugin/plugin.json +67 -0
  3. package/dist/claude/agents/architect.md +172 -0
  4. package/dist/claude/agents/designer.md +120 -0
  5. package/dist/claude/agents/engineer.md +98 -0
  6. package/dist/claude/agents/lead.md +59 -0
  7. package/dist/claude/agents/postdoc.md +117 -0
  8. package/dist/claude/agents/researcher.md +132 -0
  9. package/dist/claude/agents/reviewer.md +133 -0
  10. package/dist/claude/agents/strategist.md +111 -0
  11. package/dist/claude/agents/tester.md +190 -0
  12. package/dist/claude/agents/writer.md +114 -0
  13. package/dist/claude/dist/hooks/agent-bootstrap.js +121 -0
  14. package/dist/claude/dist/hooks/agent-finalize.js +180 -0
  15. package/dist/claude/dist/hooks/prompt-router.js +7316 -0
  16. package/dist/claude/dist/hooks/session-init.js +37 -0
  17. package/dist/claude/hooks/hooks.json +52 -0
  18. package/dist/claude/settings.json +3 -0
  19. package/dist/claude/skills/nx-init/SKILL.md +189 -0
  20. package/dist/claude/skills/nx-plan/SKILL.md +353 -0
  21. package/dist/claude/skills/nx-run/SKILL.md +154 -0
  22. package/dist/claude/skills/nx-sync/SKILL.md +87 -0
  23. package/dist/codex/agents/architect.toml +172 -0
  24. package/dist/codex/agents/designer.toml +120 -0
  25. package/dist/codex/agents/engineer.toml +102 -0
  26. package/dist/codex/agents/lead.toml +64 -0
  27. package/dist/codex/agents/postdoc.toml +117 -0
  28. package/dist/codex/agents/researcher.toml +133 -0
  29. package/dist/codex/agents/reviewer.toml +134 -0
  30. package/dist/codex/agents/strategist.toml +111 -0
  31. package/dist/codex/agents/tester.toml +191 -0
  32. package/dist/codex/agents/writer.toml +118 -0
  33. package/dist/codex/dist/hooks/agent-bootstrap.js +121 -0
  34. package/dist/codex/dist/hooks/agent-finalize.js +180 -0
  35. package/dist/codex/dist/hooks/prompt-router.js +7316 -0
  36. package/dist/codex/dist/hooks/session-init.js +37 -0
  37. package/dist/codex/hooks/hooks.json +28 -0
  38. package/dist/codex/install/AGENTS.fragment.md +60 -0
  39. package/dist/codex/install/config.fragment.toml +5 -0
  40. package/dist/codex/install/install.sh +60 -0
  41. package/dist/codex/package.json +20 -0
  42. package/dist/codex/plugin/.codex-plugin/plugin.json +57 -0
  43. package/dist/codex/plugin/skills/nx-init/SKILL.md +189 -0
  44. package/dist/codex/plugin/skills/nx-plan/SKILL.md +353 -0
  45. package/dist/codex/plugin/skills/nx-run/SKILL.md +154 -0
  46. package/dist/codex/plugin/skills/nx-sync/SKILL.md +87 -0
  47. package/dist/codex/prompts/architect.md +166 -0
  48. package/dist/codex/prompts/designer.md +114 -0
  49. package/dist/codex/prompts/engineer.md +97 -0
  50. package/dist/codex/prompts/lead.md +60 -0
  51. package/dist/codex/prompts/postdoc.md +111 -0
  52. package/dist/codex/prompts/researcher.md +127 -0
  53. package/dist/codex/prompts/reviewer.md +128 -0
  54. package/dist/codex/prompts/strategist.md +105 -0
  55. package/dist/codex/prompts/tester.md +185 -0
  56. package/dist/codex/prompts/writer.md +113 -0
  57. package/dist/hooks/agent-bootstrap.js +19 -3
  58. package/dist/hooks/agent-finalize.js +19 -3
  59. package/dist/hooks/prompt-router.js +19 -3
  60. package/dist/hooks/session-init.js +19 -3
  61. package/dist/manifests/opencode-manifest.json +4 -4
  62. package/dist/opencode/.opencode/skills/nx-init/SKILL.md +189 -0
  63. package/dist/opencode/.opencode/skills/nx-plan/SKILL.md +353 -0
  64. package/dist/opencode/.opencode/skills/nx-run/SKILL.md +154 -0
  65. package/dist/opencode/.opencode/skills/nx-sync/SKILL.md +87 -0
  66. package/dist/opencode/package.json +23 -0
  67. package/dist/opencode/src/agents/architect.ts +176 -0
  68. package/dist/opencode/src/agents/designer.ts +124 -0
  69. package/dist/opencode/src/agents/engineer.ts +105 -0
  70. package/dist/opencode/src/agents/lead.ts +66 -0
  71. package/dist/opencode/src/agents/postdoc.ts +121 -0
  72. package/dist/opencode/src/agents/researcher.ts +136 -0
  73. package/dist/opencode/src/agents/reviewer.ts +137 -0
  74. package/dist/opencode/src/agents/strategist.ts +115 -0
  75. package/dist/opencode/src/agents/tester.ts +194 -0
  76. package/dist/opencode/src/agents/writer.ts +121 -0
  77. package/dist/opencode/src/index.ts +25 -0
  78. package/dist/opencode/src/plugin.ts +6 -0
  79. package/dist/scripts/build-agents.d.ts +0 -1
  80. package/dist/scripts/build-agents.d.ts.map +1 -1
  81. package/dist/scripts/build-agents.js +3 -15
  82. package/dist/scripts/build-agents.js.map +1 -1
  83. package/dist/scripts/build-hooks.d.ts.map +1 -1
  84. package/dist/scripts/build-hooks.js +41 -5
  85. package/dist/scripts/build-hooks.js.map +1 -1
  86. package/dist/scripts/smoke/smoke-claude.d.ts +2 -0
  87. package/dist/scripts/smoke/smoke-claude.d.ts.map +1 -0
  88. package/dist/scripts/smoke/smoke-claude.js +58 -0
  89. package/dist/scripts/smoke/smoke-claude.js.map +1 -0
  90. package/dist/scripts/smoke/smoke-codex.d.ts +2 -0
  91. package/dist/scripts/smoke/smoke-codex.d.ts.map +1 -0
  92. package/dist/scripts/smoke/smoke-codex.js +50 -0
  93. package/dist/scripts/smoke/smoke-codex.js.map +1 -0
  94. package/dist/scripts/smoke/smoke-opencode.d.ts +2 -0
  95. package/dist/scripts/smoke/smoke-opencode.d.ts.map +1 -0
  96. package/dist/scripts/smoke/smoke-opencode.js +99 -0
  97. package/dist/scripts/smoke/smoke-opencode.js.map +1 -0
  98. package/docs/contract/harness-io.md +51 -6
  99. package/package.json +7 -3
@@ -0,0 +1,50 @@
1
+ // Issue #42 — agents/*.toml standalone schema 회귀 감지
2
+ // Verifies each dist/codex/agents/*.toml satisfies standalone role file schema.
3
+ import { readFileSync, readdirSync, existsSync } from "node:fs";
4
+ import { join } from "node:path";
5
+ import { fileURLToPath } from "node:url";
6
+ import { findPackageRoot } from "../../src/shared/package-root.js";
7
+ const __dirname = fileURLToPath(new URL(".", import.meta.url));
8
+ const ROOT = findPackageRoot(__dirname);
9
+ const AGENTS_DIR = join(ROOT, "dist/codex/agents");
10
+ function fail(msg) {
11
+ process.stderr.write(`[smoke-codex] FAIL: ${msg}\n`);
12
+ process.exit(1);
13
+ }
14
+ if (!existsSync(AGENTS_DIR)) {
15
+ fail(`dist/codex/agents/ not found — run \`bun run build-agents\` (or nexus-core sync --harness=codex) first`);
16
+ }
17
+ const files = readdirSync(AGENTS_DIR).filter((f) => f.endsWith(".toml"));
18
+ if (files.length === 0) {
19
+ fail(`no .toml files found in ${AGENTS_DIR}`);
20
+ }
21
+ const failures = [];
22
+ for (const file of files) {
23
+ const filePath = join(AGENTS_DIR, file);
24
+ const content = readFileSync(filePath, "utf-8");
25
+ const fileErrors = [];
26
+ // Assert standalone schema — root-level fields (no indentation)
27
+ if (!/^name = "/m.test(content)) {
28
+ fileErrors.push("missing root-level `name = \"...\"` line");
29
+ }
30
+ if (!/^description = "/m.test(content)) {
31
+ fileErrors.push("missing root-level `description = \"...\"` line");
32
+ }
33
+ if (!/^developer_instructions = ("""|")/m.test(content)) {
34
+ fileErrors.push("missing root-level `developer_instructions = ...` line");
35
+ }
36
+ // Detect nested [agents.<name>] header which signals old bundle schema
37
+ if (/^\[agents\./m.test(content)) {
38
+ fileErrors.push("contains `[agents.*]` section header — old bundle schema, should be standalone");
39
+ }
40
+ if (fileErrors.length > 0) {
41
+ failures.push(` ${file}:\n${fileErrors.map((e) => ` - ${e}`).join("\n")}`);
42
+ }
43
+ }
44
+ if (failures.length > 0) {
45
+ process.stderr.write(`[smoke-codex] FAIL: ${failures.length}/${files.length} file(s) failed schema check:\n`);
46
+ process.stderr.write(failures.join("\n") + "\n");
47
+ process.exit(1);
48
+ }
49
+ console.log(`[smoke-codex] PASS — ${files.length} file(s) passed standalone schema check`);
50
+ //# sourceMappingURL=smoke-codex.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"smoke-codex.js","sourceRoot":"","sources":["../../../scripts/smoke/smoke-codex.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=smoke-opencode.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"smoke-opencode.d.ts","sourceRoot":"","sources":["../../../scripts/smoke/smoke-opencode.ts"],"names":[],"mappings":""}
@@ -0,0 +1,99 @@
1
+ // Issue #39 OpenCode 경로 — spawnHandler stdout null 회귀 감지
2
+ // Verifies opencode-manifest.json has session-init entry and spawning its handler produces side-effects.
3
+ import { spawn } from "node:child_process";
4
+ import { readFileSync, mkdtempSync, rmSync, existsSync } from "node:fs";
5
+ import { join } from "node:path";
6
+ import { tmpdir } from "node:os";
7
+ import { randomUUID } from "node:crypto";
8
+ import { fileURLToPath } from "node:url";
9
+ import { findPackageRoot } from "../../src/shared/package-root.js";
10
+ const __dirname = fileURLToPath(new URL(".", import.meta.url));
11
+ const ROOT = findPackageRoot(__dirname);
12
+ const MANIFEST_PATH = join(ROOT, "dist/manifests/opencode-manifest.json");
13
+ function fail(msg) {
14
+ process.stderr.write(`[smoke-opencode] FAIL: ${msg}\n`);
15
+ process.exit(1);
16
+ }
17
+ // --- 1. Load manifest and find session-init entry ---
18
+ if (!existsSync(MANIFEST_PATH)) {
19
+ fail(`manifest not found: ${MANIFEST_PATH} — run \`bun run build\` first`);
20
+ }
21
+ const manifest = JSON.parse(readFileSync(MANIFEST_PATH, "utf-8"));
22
+ if (!Array.isArray(manifest.hooks)) {
23
+ fail(`manifest.hooks is not an array`);
24
+ }
25
+ const entry = manifest.hooks.find((h) => h.events.includes("SessionStart"));
26
+ if (!entry) {
27
+ fail(`no SessionStart hook found in manifest`);
28
+ }
29
+ // --- 2. Resolve handler path ---
30
+ // Resolve handlerPath the same way opencode-mount.ts does:
31
+ // relative to the manifest file location.
32
+ const manifestUrl = new URL(`file://${MANIFEST_PATH}`);
33
+ const resolvedPath = fileURLToPath(new URL(entry.handlerPath, manifestUrl));
34
+ // Fall back to the compiled dist bundle if the manifest-relative path doesn't exist.
35
+ // This allows smoke to detect path mismatches (Issue #43) while still validating
36
+ // spawn + side-effect behavior against the known-good compiled bundle.
37
+ const handlerPath = existsSync(resolvedPath)
38
+ ? resolvedPath
39
+ : join(ROOT, "dist/hooks", `${entry.name}.js`);
40
+ if (!existsSync(handlerPath)) {
41
+ fail(`handler not found at either:\n manifest-resolved: ${resolvedPath}\n dist bundle: ${join(ROOT, "dist/hooks", `${entry.name}.js`)}`);
42
+ }
43
+ // Warn when manifest path doesn't resolve — this is the Issue #43 symptom
44
+ if (!existsSync(resolvedPath)) {
45
+ process.stderr.write(`[smoke-opencode] WARN: manifest handlerPath "${entry.handlerPath}" resolved to non-existent ` +
46
+ `"${resolvedPath}"; falling back to dist bundle. Fix manifest to resolve Issue #43.\n`);
47
+ }
48
+ // --- 3. Spawn handler with SessionStart payload ---
49
+ const tmpDir = mkdtempSync(join(tmpdir(), "nexus-smoke-opencode-"));
50
+ const sid = randomUUID();
51
+ const payload = JSON.stringify({
52
+ hook_event_name: "SessionStart",
53
+ session_id: sid,
54
+ cwd: tmpDir,
55
+ source: "startup",
56
+ });
57
+ try {
58
+ const child = spawn("node", [handlerPath], {
59
+ env: { ...process.env, NEXUS_HARNESS: "opencode" },
60
+ stdio: ["pipe", "pipe", "pipe"],
61
+ });
62
+ let stdout = "";
63
+ let stderr = "";
64
+ child.stdout.on("data", (d) => { stdout += d.toString(); });
65
+ child.stderr.on("data", (d) => { stderr += d.toString(); });
66
+ child.stdin.write(payload);
67
+ child.stdin.end();
68
+ const code = await new Promise((resolve) => {
69
+ child.on("exit", (c) => resolve(c ?? 1));
70
+ child.on("error", () => resolve(1));
71
+ });
72
+ // --- 4. Assert exit 0 ---
73
+ if (code !== 0) {
74
+ fail(`handler exited with code ${code}. stderr:\n${stderr}`);
75
+ }
76
+ // Assert stdout is empty or valid JSON (not corrupted)
77
+ if (stdout.trim() && stdout.trim() !== "null") {
78
+ try {
79
+ JSON.parse(stdout);
80
+ }
81
+ catch {
82
+ fail(`stdout is non-empty and not valid JSON: ${stdout.slice(0, 200)}`);
83
+ }
84
+ }
85
+ // --- 5. Assert side-effects ---
86
+ const stateDir = join(tmpDir, ".nexus/state", sid);
87
+ if (!existsSync(stateDir)) {
88
+ fail(`state directory not created: ${stateDir} — handler ran but produced no side-effects (Issue #39 regression)\n` +
89
+ ` handlerPath: ${handlerPath}\n` +
90
+ ` code: ${code}\n` +
91
+ ` stdout: ${JSON.stringify(stdout)}\n` +
92
+ ` stderr: ${JSON.stringify(stderr)}`);
93
+ }
94
+ console.log("[smoke-opencode] PASS — manifest valid, handler spawned, side-effects confirmed");
95
+ }
96
+ finally {
97
+ rmSync(tmpDir, { recursive: true, force: true });
98
+ }
99
+ //# sourceMappingURL=smoke-opencode.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"smoke-opencode.js","sourceRoot":"","sources":["../../../scripts/smoke/smoke-opencode.ts"],"names":[],"mappings":"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"}
@@ -126,18 +126,50 @@ multi-harness 빌드가 필요한 경우 소비자가 `--harness`와 `--target`
126
126
  |---|---|---|
127
127
  | `package.json` | Template | npm 패키지 메타 — 저자 name·version 편집 |
128
128
  | `src/plugin.ts` | **Template (신규)** | mountHooks 진입점 보일러플레이트 |
129
- | `opencode.json.fragment` | Managed | consumer에 merge될 agents 배열 fragment |
130
- | `src/index.ts` | Managed | 에이전트 export 인덱스 |
129
+ | `src/index.ts` | Managed | 에이전트 export 인덱스 (`export const agents = [...]` 포함) |
131
130
  | `src/agents/<name>.ts` | Managed | 에이전트 TS 모듈 |
132
131
  | `.opencode/skills/<name>/SKILL.md` | Managed | 스킬 마크다운 |
133
132
 
134
- **fragment 경로**: `opencode.json.fragment`는 core가 생성하는 agents 배열 fragment다. 이 파일의 consumer `opencode.json` merge는 wrapper(opencode-nexus)의 postinstall 스크립트가 수행한다.
133
+ #### Consumer 설정 가이드 (canonical 경로)
134
+
135
+ **1단계 — 의존성 설치**
136
+
137
+ ```bash
138
+ bun add -d @moreih29/nexus-core @opencode-ai/plugin typescript
139
+ ```
140
+
141
+ **2단계 — sync 실행**
142
+
143
+ `bun run sync`를 실행하면 `src/index.ts`에 `export const agents = [...]`가 생성되고, `src/plugin.ts`에 `mountHooks` 기반 Plugin export 보일러플레이트가 생성된다. 이 두 파일이 OpenCode plugin auto-register의 canonical 진입점이다.
144
+
145
+ **3단계 — consumer 워크스페이스 `.opencode/opencode.json` 구성**
146
+
147
+ ```json
148
+ {
149
+ "$schema": "https://opencode.ai/config.json",
150
+ "plugin": ["<your-plugin-name>"],
151
+ "default_agent": "<primary-agent-id>",
152
+ "mcp": { "nx": { "type": "local", "command": ["nexus-mcp"] } }
153
+ }
154
+ ```
155
+
156
+ `agent` 객체는 optional이다. 특정 agent의 model 또는 permission을 개별 override해야 할 때만 추가한다.
157
+
158
+ > **주의**: `{ "agents": [...] }` 형태로 config에 agents를 직접 나열하면 OpenCode가 `Unrecognized key: "agents"` 오류로 기동에 실패한다. agents 등록은 반드시 `plugin: ["<name>"]` 경로(plugin auto-register)를 통해야 한다.
159
+
160
+ **4단계 — postinstall 허용 (Bun 1.3+)**
161
+
162
+ ```bash
163
+ bun pm trust <your-plugin-name>
164
+ ```
165
+
166
+ Bun 1.3+에서 plugin의 postinstall 스크립트를 허용하기 위해 필요하다.
135
167
 
136
168
  **hooks 경로**: OpenCode는 Claude/Codex와 달리 `hooks/hooks.json` 파일을 target에 기록하지 않는다. 대신 `src/plugin.ts`의 `mountHooks(ctx, manifest)`가 런타임에 `@moreih29/nexus-core/hooks/opencode-manifest` JSON과 `@moreih29/nexus-core/hooks/opencode-mount` 함수를 import해 consume하며, handler 경로는 node_modules 내부 패키지 기준으로 해석된다. consumer target에는 물리 복사가 발생하지 않는다.
137
169
 
138
170
  **Skill discovery 경계 (결정 #7)**: core는 consumer 프로젝트의 `.opencode/skills/<name>/SKILL.md` 파일 존재를 보장한다. `node_modules/<plugin>/.opencode/skills/` 자동 감지 여부는 OpenCode 런타임 영역으로 본 계약 외부다. wrapper(opencode-nexus)는 postinstall 스크립트로 패키지 내부 `.opencode/skills/`를 consumer 경로로 복사할 책임을 진다.
139
171
 
140
- **Consumer(opencode-nexus wrapper) 책임**: `src/plugin.ts` 실 진입점 유지 · `opencode.json.fragment` consumer merge · postinstall skill copy · npm publish.
172
+ **Consumer(opencode-nexus wrapper) 책임**: `src/plugin.ts` 실 진입점 유지 · plugin auto-register 경로(`src/index.ts` export) 유지 · postinstall skill copy · npm publish.
141
173
 
142
174
  ---
143
175
 
@@ -166,6 +198,19 @@ multi-harness 빌드가 필요한 경우 소비자가 `--harness`와 `--target`
166
198
  - `install/config.fragment.toml` — MCP 서버 등록 TOML fragment
167
199
  - `install/AGENTS.fragment.md` — primary agent body를 `<!-- nexus-core:<agent-id>:start -->` / `<!-- nexus-core:<agent-id>:end -->` 마커로 감싼 fragment. `<agent-id>`는 primary agent의 frontmatter `id`이며 기본값은 `lead`이다
168
200
 
201
+ **`agents/*.toml` — standalone role file 스키마**: `agents/<name>.toml`은 Codex의 `~/.codex/agents/`에 **standalone role file**로 직접 설치된다. 파일 스키마는 root-level 필드를 사용한다.
202
+
203
+ ```toml
204
+ name = "<agent-id>"
205
+ description = "..."
206
+ developer_instructions = """<body>"""
207
+ model = "..."
208
+ sandbox_mode = "..."
209
+ disabled_tools = [...]
210
+ ```
211
+
212
+ > **주의**: `[agents.<id>]` nested 구조는 `~/.codex/config.toml`(global config)의 agent 정의용이며, standalone role file과 혼용하면 안 된다. standalone 파일에는 반드시 root-level `name`·`developer_instructions` 형식을 사용한다.
213
+
169
214
  **도메인 서브디렉터리 구조**: Codex 내부 `plugin/`·`agents/`·`install/` 서브디렉터리는 Codex 생태계가 `~/.codex/plugins/`·`~/.codex/agents/`·`~/.codex/config.toml` 3곳에 분리 설치되는 구조를 반영한다. 이 도메인 prefix는 flat 출력 규칙(§4 공통 규칙)과 직교하며 유지된다.
170
215
 
171
216
  **Consumer(codex-nexus wrapper) 책임**: `install.sh` 편집·실행 · block-marker merge(`config.toml`·`AGENTS.md`) · npm 혹은 GitHub source 배포 선택.
@@ -182,13 +227,13 @@ multi-harness 빌드가 필요한 경우 소비자가 `--harness`와 `--target`
182
227
  2. 하네스 네이티브 자산 빌드 — agents (`.md`/`.ts`/`.toml`), skills (`SKILL.md`), plugin manifest
183
228
  3. Integration fragment 제공:
184
229
  - Claude: `settings.json`
185
- - OpenCode: `opencode.json.fragment`
230
+ - OpenCode: `src/index.ts`의 `export const agents` (plugin auto-register — fragment 없음)
186
231
  - Codex: `install/config.fragment.toml`·`install/AGENTS.fragment.md`
187
232
  4. Runtime exports (`mountHooks`, manifest JSON, mcp 서버)
188
233
 
189
234
  ### 5-2. wrapper 책임
190
235
 
191
- 1. Fragment의 consumer 환경 실제 머지 로직 — block-marker·conditional merge·OS 경로 해석
236
+ 1. Fragment의 consumer 환경 실제 머지 로직 — block-marker·conditional merge·OS 경로 해석 (Claude `settings.json`, Codex `config.fragment.toml`·`AGENTS.fragment.md`)
192
237
  2. 배포 — marketplace 등록·npm publish·`install.sh` 실행
193
238
  3. Plugin 진입점 코드 — OpenCode `src/plugin.ts`·Codex `install/install.sh`
194
239
  4. Version·changelog 관리
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@moreih29/nexus-core",
3
- "version": "0.15.1",
3
+ "version": "0.16.0",
4
4
  "description": "Nexus ecosystem authoring layer — canonical agents/skills/hooks and 3-harness build pipeline (Claude Code, OpenCode, Codex)",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -53,11 +53,15 @@
53
53
  },
54
54
  "packageManager": "bun@1.3.12",
55
55
  "scripts": {
56
- "build": "tsc -p tsconfig.build.json && bun run scripts/build-hooks.ts",
56
+ "build": "tsc -p tsconfig.build.json && bun run scripts/build-hooks.ts && node dist/scripts/cli.js sync --harness=claude --target=dist/claude && node dist/scripts/cli.js sync --harness=codex --target=dist/codex && node dist/scripts/cli.js sync --harness=opencode --target=dist/opencode",
57
57
  "clean": "rm -rf dist",
58
58
  "test": "bun test src/ scripts/",
59
59
  "typecheck": "tsc --noEmit",
60
- "prepublishOnly": "bun run test"
60
+ "prepublishOnly": "bun run test",
61
+ "smoke:claude": "bun run scripts/smoke/smoke-claude.ts",
62
+ "smoke:codex": "bun run scripts/smoke/smoke-codex.ts",
63
+ "smoke:opencode": "bun run scripts/smoke/smoke-opencode.ts",
64
+ "smoke": "bun run smoke:claude && bun run smoke:codex && bun run smoke:opencode"
61
65
  },
62
66
  "dependencies": {
63
67
  "@modelcontextprotocol/sdk": "^1.0.0",