lazyclaude-ai 0.1.1 → 0.1.2

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
@@ -5,8 +5,8 @@ simple local activation, prompt-triggered ultrawork discipline,
5
5
  planner/executor/reviewer agents, lifecycle hooks, MCP scaffolding, and
6
6
  LSP-backed code checks.
7
7
 
8
- The current public package is `lazyclaude-ai@0.1.0`, and this checkout prepares
9
- the next `0.1.1` patch for personal install convenience. The repo can remain
8
+ The current public package is `lazyclaude-ai@0.1.1`, and this checkout prepares
9
+ the next `0.1.2` patch for personal install convenience. The repo can remain
10
10
  private and quiet; publishing to npm here does not imply public repo promotion,
11
11
  marketplace publication, or advertisement. Future package releases still require
12
12
  explicit user approval.
@@ -73,10 +73,11 @@ Inside Claude Code, reload local plugin metadata after edits:
73
73
  ```
74
74
 
75
75
  If an OMC/omc Claude plugin is installed, do not co-load it with LazyClaude
76
- while testing this MVP. LazyClaude is loaded directly by `--plugin-dir` and does
77
- not ship a root Claude marketplace skeleton. If user-level OMC creates a local
78
- `.omc/` state directory during smoke tests, LazyClaude ignores and excludes that
79
- directory from git and npm package surfaces.
76
+ while testing this MVP. Local checkout tests use `--plugin-dir`, and npm installs
77
+ create only a LazyClaude-managed local marketplace under the user's LazyClaude
78
+ home. The checkout does not ship a root Claude marketplace skeleton. If
79
+ user-level OMC creates a local `.omc/` state directory during smoke tests,
80
+ LazyClaude ignores and excludes that directory from git and npm package surfaces.
80
81
 
81
82
  ## ULW Usage
82
83
 
package/README_ko-KR.md CHANGED
@@ -5,8 +5,8 @@ LazyClaude는 LazyCodex 스타일의 작업 흐름을 Claude Code에 맞게 옮
5
5
  실행자 에이전트, hooks, MCP scaffold, LSP doctor를 Claude Code 플러그인
6
6
  형태로 제공합니다.
7
7
 
8
- 현재 공개 npm 패키지는 `lazyclaude-ai@0.1.0`이고, 이 checkout은 다음
9
- `0.1.1` 패치 배포 후보를 준비합니다. 목적은 다른 PC에서도 빠르게
8
+ 현재 공개 npm 패키지는 `lazyclaude-ai@0.1.1`이고, 이 checkout은 다음
9
+ `0.1.2` 패치 배포 후보를 준비합니다. 목적은 다른 PC에서도 빠르게
10
10
  설치하기 위한 개인용 배포물입니다. 저장소는 비공개 저장소로 유지할 수
11
11
  있고, npm 배포가 곧 홍보, 공개 저장소 운영, Claude marketplace 등록을
12
12
  의미하지는 않습니다. 새 버전 배포는 항상 별도의 명시적 승인 후에
@@ -54,9 +54,10 @@ npx --yes lazyclaude-ai uninstall
54
54
  ```
55
55
 
56
56
  installer는 `lazyclaude@lazyclaude-ai`를 Claude Code user plugin registry
57
- 아래의 `~/.claude/plugins`에 등록하고 `settings.json`의 `enabledPlugins`에
58
- 활성 상태를 기록합니다. 따라서 매번 긴 `--plugin-dir` 명령을 입력할
59
- 필요가 없습니다. 격리 테스트가 필요할 때만
57
+ 아래의 `~/.claude/plugins`에 등록하고 `settings.json`의 `enabledPlugins`와
58
+ LazyClaude 전용 local marketplace 항목, `known_marketplaces.json`을 함께
59
+ 기록합니다. 따라서 매번 `--plugin-dir` 명령을 입력할 필요가 없습니다.
60
+ 격리 테스트가 필요할 때만
60
61
  `CLAUDE_CONFIG_DIR=/some/path`와 `LAZYCLAUDE_HOME=/some/path`를 지정하세요.
61
62
 
62
63
  ## 로컬 개발
@@ -75,10 +76,12 @@ Claude Code 안에서 플러그인 메타데이터를 다시 읽고 싶으면
75
76
  ```
76
77
 
77
78
  기존 OMC/omc Claude 플러그인이 설치되어 있다면 MVP 테스트 중에는
78
- LazyClaude와 함께 co-load하지 않는 것을 권장합니다. LazyClaude는
79
- `--plugin-dir`로 직접 로드하며 root Claude marketplace skeleton을 배포하지
80
- 않습니다. user-level OMC가 검증 `.omc/` 상태 디렉터리를 만들더라도
81
- LazyClaude는 이를 git npm package surface에서 제외합니다.
79
+ LazyClaude와 함께 co-load하지 않는 것을 권장합니다. 로컬 checkout 테스트는
80
+ `--plugin-dir`로 직접 로드하고, npm 설치는 사용자 아래에 LazyClaude가
81
+ 관리하는 local marketplace만 만듭니다. root Claude marketplace skeleton은
82
+ 저장소 checkout에 배포하지 않습니다. user-level OMC가 검증 중 `.omc/`
83
+ 상태 디렉터리를 만들더라도 LazyClaude는 이를 git 및 npm package surface에서
84
+ 제외합니다.
82
85
 
83
86
  ## ULW 사용법
84
87
 
@@ -1,8 +1,8 @@
1
1
  # LazyClaude Release Checklist
2
2
 
3
- Status: quiet public npm package `lazyclaude-ai@0.1.0` is published for
3
+ Status: quiet public npm package `lazyclaude-ai@0.1.1` is published for
4
4
  personal install convenience after explicit user approval. This checkout is
5
- prepared as the next `0.1.1` patch candidate until the user explicitly approves
5
+ prepared as the next `0.1.2` patch candidate until the user explicitly approves
6
6
  another publish.
7
7
 
8
8
  DO NOT publish a new version of LazyClaude, run `npm publish`, push release
@@ -40,9 +40,10 @@ Use this track after an approved npm package version exists:
40
40
  3. Start Claude Code with the normal `claude` command.
41
41
 
42
42
  The installer should register `lazyclaude@lazyclaude-ai` in Claude Code's user
43
- plugin registry and `settings.json` `enabledPlugins`. Do not ask users to type a
44
- generated command that shells out to `npx --yes lazyclaude-ai path` for normal
45
- npm installs.
43
+ plugin registry, `settings.json` `enabledPlugins`, and the LazyClaude-managed
44
+ local marketplace metadata needed by `claude plugin details`. Do not ask users
45
+ to type a generated command that shells out to `npx --yes lazyclaude-ai path` for
46
+ normal npm installs.
46
47
 
47
48
  ## Quiet Public NPM Package Release Or Update
48
49
 
@@ -92,10 +93,13 @@ rollback action with user approval:
92
93
  Local checkout testing still uses `claude --plugin-dir ./plugins/lazyclaude`.
93
94
  NPM installs should use the global Claude user plugin registry and normal
94
95
  `claude` launches. A root Claude marketplace file is intentionally not shipped
95
- because users may already have an OMC/omc marketplace or plugin installed. Do
96
- not add a local or remote marketplace entry without explicit user approval. If
97
- user-level OMC creates `.omc/` state during validation, keep it ignored and
98
- confirm it is absent from the package dry-run.
96
+ because users may already have an OMC/omc marketplace or plugin installed. The
97
+ npm installer creates a LazyClaude-managed local marketplace under
98
+ `LAZYCLAUDE_HOME` and registers only `lazyclaude-ai` in Claude's user marketplace
99
+ metadata so skills and hooks appear in `claude plugin details`. Do not add a
100
+ remote marketplace entry without explicit user approval. If user-level OMC
101
+ creates `.omc/` state during validation, keep it ignored and confirm it is
102
+ absent from the package dry-run.
99
103
 
100
104
  ## Rollback
101
105
 
@@ -43,9 +43,13 @@ const currentRoot = (home = lazyHome()) => join(home, "current");
43
43
  const pluginPathForRoot = (installRoot) => join(installRoot, "plugins", "lazyclaude");
44
44
  const claudePluginRoot = (home = claudeHome()) => join(home, "plugins", "cache", "lazyclaude-ai", "lazyclaude", version);
45
45
  const installedPluginsPath = (home = claudeHome()) => join(home, "plugins", "installed_plugins.json");
46
+ const knownMarketplacesPath = (home = claudeHome()) => join(home, "plugins", "known_marketplaces.json");
46
47
  const claudeSettingsPath = (home = claudeHome()) => join(home, "settings.json");
47
48
  const pluginKey = "lazyclaude@lazyclaude-ai";
49
+ const marketplaceName = "lazyclaude-ai";
48
50
  const intendedPluginPath = (home = claudeHome()) => claudePluginRoot(home);
51
+ const marketplaceRoot = (home = lazyHome()) => join(home, "marketplaces", marketplaceName);
52
+ const marketplacePluginPath = (home = lazyHome()) => join(marketplaceRoot(home), "plugins", "lazyclaude");
49
53
  const sourcePluginPath = () => join(root, "plugins", "lazyclaude");
50
54
 
51
55
  const printUsage = () => {
@@ -88,23 +92,98 @@ const writeClaudeSettings = (settings, home = claudeHome()) => {
88
92
  writeFileSync(settingsPath, `${JSON.stringify(settings, null, 2)}\n`);
89
93
  };
90
94
 
91
- const enableClaudePlugin = (home = claudeHome()) => {
95
+ const readKnownMarketplaces = (home = claudeHome()) => {
96
+ const path = knownMarketplacesPath(home);
97
+ if (!existsSync(path)) return {};
98
+ return JSON.parse(readFileSync(path, "utf8"));
99
+ };
100
+
101
+ const writeKnownMarketplaces = (knownMarketplaces, home = claudeHome()) => {
102
+ const path = knownMarketplacesPath(home);
103
+ mkdirSync(dirname(path), { recursive: true });
104
+ writeFileSync(path, `${JSON.stringify(knownMarketplaces, null, 2)}\n`);
105
+ };
106
+
107
+ const marketplaceSource = (marketplacePath) => ({
108
+ source: "directory",
109
+ path: marketplacePath,
110
+ });
111
+
112
+ const writeLocalMarketplace = (legacyHome = lazyHome()) => {
113
+ const rootPath = marketplaceRoot(legacyHome);
114
+ const targetPlugin = marketplacePluginPath(legacyHome);
115
+ rmSync(rootPath, { recursive: true, force: true });
116
+ mkdirSync(dirname(targetPlugin), { recursive: true });
117
+ cpSync(sourcePluginPath(), targetPlugin, { recursive: true });
118
+ const marketplaceManifestPath = join(rootPath, ".claude-plugin", "marketplace.json");
119
+ mkdirSync(dirname(marketplaceManifestPath), { recursive: true });
120
+ writeFileSync(
121
+ marketplaceManifestPath,
122
+ `${JSON.stringify(
123
+ {
124
+ $schema: "https://anthropic.com/claude-code/marketplace.schema.json",
125
+ name: marketplaceName,
126
+ description: "Local LazyClaude npm-installed marketplace.",
127
+ owner: {
128
+ name: "LazyClaude contributors",
129
+ },
130
+ plugins: [
131
+ {
132
+ name: "lazyclaude",
133
+ description: packageJson.description,
134
+ author: {
135
+ name: "LazyClaude contributors",
136
+ },
137
+ source: "./plugins/lazyclaude",
138
+ category: "development",
139
+ homepage: "https://github.com/code-yeongyu/lazycodex",
140
+ },
141
+ ],
142
+ },
143
+ null,
144
+ 2,
145
+ )}\n`,
146
+ );
147
+ return rootPath;
148
+ };
149
+
150
+ const registerMarketplace = (marketplacePath, home = claudeHome()) => {
92
151
  const settings = readClaudeSettings(home);
93
152
  settings.enabledPlugins = settings.enabledPlugins ?? {};
94
153
  settings.enabledPlugins[pluginKey] = true;
154
+ settings.extraKnownMarketplaces = settings.extraKnownMarketplaces ?? {};
155
+ settings.extraKnownMarketplaces[marketplaceName] = {
156
+ source: marketplaceSource(marketplacePath),
157
+ };
95
158
  writeClaudeSettings(settings, home);
159
+
160
+ const knownMarketplaces = readKnownMarketplaces(home);
161
+ knownMarketplaces[marketplaceName] = {
162
+ source: marketplaceSource(marketplacePath),
163
+ installLocation: marketplacePath,
164
+ lastUpdated: new Date().toISOString(),
165
+ };
166
+ writeKnownMarketplaces(knownMarketplaces, home);
96
167
  };
97
168
 
98
- const disableClaudePlugin = (home = claudeHome()) => {
169
+ const unregisterMarketplace = (home = claudeHome()) => {
99
170
  const settingsPath = claudeSettingsPath(home);
100
- if (!existsSync(settingsPath)) return;
101
- const settings = readClaudeSettings(home);
102
- if (!settings.enabledPlugins) return;
103
- delete settings.enabledPlugins[pluginKey];
104
- writeClaudeSettings(settings, home);
171
+ if (existsSync(settingsPath)) {
172
+ const settings = readClaudeSettings(home);
173
+ if (settings.enabledPlugins) delete settings.enabledPlugins[pluginKey];
174
+ if (settings.extraKnownMarketplaces) delete settings.extraKnownMarketplaces[marketplaceName];
175
+ writeClaudeSettings(settings, home);
176
+ }
177
+
178
+ const knownPath = knownMarketplacesPath(home);
179
+ if (existsSync(knownPath)) {
180
+ const knownMarketplaces = readKnownMarketplaces(home);
181
+ delete knownMarketplaces[marketplaceName];
182
+ writeKnownMarketplaces(knownMarketplaces, home);
183
+ }
105
184
  };
106
185
 
107
- const registerClaudePlugin = (installRoot, home = claudeHome()) => {
186
+ const registerClaudePlugin = (installRoot, marketplacePath, home = claudeHome()) => {
108
187
  const registry = readInstalledPlugins(home);
109
188
  const now = new Date().toISOString();
110
189
  const existing = registry.plugins[pluginKey]?.[0] ?? {};
@@ -120,7 +199,7 @@ const registerClaudePlugin = (installRoot, home = claudeHome()) => {
120
199
  },
121
200
  ];
122
201
  writeInstalledPlugins(registry, home);
123
- enableClaudePlugin(home);
202
+ registerMarketplace(marketplacePath, home);
124
203
  };
125
204
 
126
205
  const unregisterClaudePlugin = (home = claudeHome()) => {
@@ -158,10 +237,12 @@ const install = ({ dryRun }) => {
158
237
  const legacyHome = lazyHome();
159
238
  const targetPlugin = claudePluginRoot(home);
160
239
  const sourcePlugin = sourcePluginPath();
240
+ const targetMarketplace = marketplaceRoot(legacyHome);
161
241
 
162
242
  if (dryRun) {
163
243
  process.stdout.write(`DRY_RUN: install LazyClaude ${version}\n`);
164
244
  process.stdout.write(`Would copy: ${sourcePlugin} -> ${targetPlugin}\n`);
245
+ process.stdout.write(`Would create local marketplace: ${targetMarketplace}\n`);
165
246
  process.stdout.write(`Would register Claude plugin: ${pluginKey}\n`);
166
247
  process.stdout.write("Launch with: claude\n");
167
248
  return;
@@ -174,7 +255,8 @@ const install = ({ dryRun }) => {
174
255
  rmSync(targetPlugin, { recursive: true, force: true });
175
256
  mkdirSync(dirname(targetPlugin), { recursive: true });
176
257
  cpSync(sourcePlugin, targetPlugin, { recursive: true });
177
- registerClaudePlugin(targetPlugin, home);
258
+ const localMarketplace = writeLocalMarketplace(legacyHome);
259
+ registerClaudePlugin(targetPlugin, localMarketplace, home);
178
260
 
179
261
  const legacyRoot = versionRoot(legacyHome);
180
262
  rmSync(legacyRoot, { recursive: true, force: true });
@@ -184,6 +266,7 @@ const install = ({ dryRun }) => {
184
266
 
185
267
  process.stdout.write(`INSTALL_PASS: LazyClaude ${version} installed\n`);
186
268
  process.stdout.write(`Claude plugin: ${pluginKey}\n`);
269
+ process.stdout.write(`Marketplace: ${localMarketplace}\n`);
187
270
  process.stdout.write(`Plugin path: ${intendedPluginPath(home)}\n`);
188
271
  process.stdout.write("Launch with: claude\n");
189
272
  };
@@ -229,6 +312,13 @@ const doctor = ({ dryRun }) => {
229
312
  fail("Claude plugin validation failed.");
230
313
  }
231
314
  process.stdout.write("CLAUDE_PLUGIN_VALIDATE_PASS\n");
315
+ const details = spawnSync("claude", ["plugin", "details", pluginKey], { encoding: "utf8" });
316
+ if (details.status !== 0) {
317
+ if (details.stdout) process.stderr.write(details.stdout);
318
+ if (details.stderr) process.stderr.write(details.stderr);
319
+ fail("Claude plugin details failed.");
320
+ }
321
+ process.stdout.write("CLAUDE_PLUGIN_DETAILS_PASS\n");
232
322
  }
233
323
 
234
324
  process.stdout.write(`Plugin path: ${pluginPath}\n`);
@@ -261,13 +351,14 @@ const uninstall = ({ dryRun }) => {
261
351
  const home = lazyHome();
262
352
  const pluginCacheRoot = join(claudeHome(), "plugins", "cache", "lazyclaude-ai");
263
353
  if (dryRun) {
264
- process.stdout.write(`DRY_RUN: remove ${join(home, "lazyclaude-ai")}, ${currentRoot(home)}, ${pluginCacheRoot}, ${pluginKey}, and its enabledPlugins entry\n`);
354
+ process.stdout.write(`DRY_RUN: remove ${join(home, "lazyclaude-ai")}, ${currentRoot(home)}, ${marketplaceRoot(home)}, ${pluginCacheRoot}, ${pluginKey}, and its marketplace/settings entries\n`);
265
355
  return;
266
356
  }
267
357
  rmSync(currentRoot(home), { recursive: true, force: true });
268
358
  rmSync(join(home, "lazyclaude-ai"), { recursive: true, force: true });
359
+ rmSync(marketplaceRoot(home), { recursive: true, force: true });
269
360
  unregisterClaudePlugin();
270
- disableClaudePlugin();
361
+ unregisterMarketplace();
271
362
  rmSync(pluginCacheRoot, { recursive: true, force: true });
272
363
  process.stdout.write("UNINSTALL_PASS\n");
273
364
  };
package/docs/migration.md CHANGED
@@ -38,9 +38,10 @@ claude
38
38
  ```
39
39
 
40
40
  The installer writes the user plugin cache, `plugins/installed_plugins.json`,
41
- and the `settings.json` `enabledPlugins` entry for `lazyclaude@lazyclaude-ai`.
41
+ the `settings.json` `enabledPlugins` entry for `lazyclaude@lazyclaude-ai`, and
42
+ a LazyClaude-managed local marketplace entry in `known_marketplaces.json`.
42
43
  This keeps installation convenient without requiring public repo promotion,
43
- manual `--plugin-dir` launch commands, or a Claude marketplace entry.
44
+ manual `--plugin-dir` launch commands, or a remote Claude marketplace entry.
44
45
 
45
46
  If OMC/omc is already installed in Claude Code, keep it disabled or start a
46
47
  separate Claude Code session without OMC while testing LazyClaude. This repo no
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lazyclaude-ai",
3
- "version": "0.1.1",
3
+ "version": "0.1.2",
4
4
  "description": "Claude Code-native LazyCodex-style workflow distribution.",
5
5
  "type": "module",
6
6
  "bin": {
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "lazyclaude",
3
3
  "description": "Claude Code-native LazyCodex-style workflow plugin.",
4
- "version": "0.1.1",
4
+ "version": "0.1.2",
5
5
  "author": {
6
6
  "name": "LazyClaude contributors"
7
7
  },
@@ -71,13 +71,35 @@ if [ ! -f "$TMP_CLAUDE_HOME/settings.json" ]; then
71
71
  echo "INSTALL_FAIL"
72
72
  exit 1
73
73
  fi
74
+ if [ ! -f "$TMP_CLAUDE_HOME/plugins/known_marketplaces.json" ]; then
75
+ echo "INSTALL_FAIL: Claude known marketplaces missing" >> "$EVIDENCE"
76
+ echo "INSTALL_FAIL"
77
+ exit 1
78
+ fi
79
+ if [ ! -f "$TMP_HOME/marketplaces/lazyclaude-ai/.claude-plugin/marketplace.json" ]; then
80
+ echo "INSTALL_FAIL: LazyClaude local marketplace missing" >> "$EVIDENCE"
81
+ echo "INSTALL_FAIL"
82
+ exit 1
83
+ fi
74
84
  node -e 'const fs = require("fs"); const p = process.argv[1]; const registry = JSON.parse(fs.readFileSync(`${p}/plugins/installed_plugins.json`, "utf8")); const entry = registry.plugins["lazyclaude@lazyclaude-ai"]?.[0]; if (!entry || entry.scope !== "user" || !entry.installPath.includes("/plugins/cache/lazyclaude-ai/lazyclaude/")) process.exit(1);' "$TMP_CLAUDE_HOME"
75
- node -e 'const fs = require("fs"); const p = process.argv[1]; const settings = JSON.parse(fs.readFileSync(`${p}/settings.json`, "utf8")); if (settings.enabledPlugins?.["lazyclaude@lazyclaude-ai"] !== true) process.exit(1);' "$TMP_CLAUDE_HOME"
85
+ node -e 'const fs = require("fs"); const p = process.argv[1]; const h = process.argv[2]; const settings = JSON.parse(fs.readFileSync(`${p}/settings.json`, "utf8")); const market = settings.extraKnownMarketplaces?.["lazyclaude-ai"]; if (settings.enabledPlugins?.["lazyclaude@lazyclaude-ai"] !== true || market?.source?.source !== "directory" || market.source.path !== `${h}/marketplaces/lazyclaude-ai`) process.exit(1);' "$TMP_CLAUDE_HOME" "$TMP_HOME"
86
+ node -e 'const fs = require("fs"); const p = process.argv[1]; const h = process.argv[2]; const known = JSON.parse(fs.readFileSync(`${p}/plugins/known_marketplaces.json`, "utf8")); const market = known["lazyclaude-ai"]; if (market?.source?.source !== "directory" || market.installLocation !== `${h}/marketplaces/lazyclaude-ai`) process.exit(1);' "$TMP_CLAUDE_HOME" "$TMP_HOME"
76
87
  echo "INSTALL_PASS" >> "$EVIDENCE"
77
88
 
78
89
  run_step DOCTOR node "$ROOT/bin/lazyclaude-ai.js" doctor
79
90
  echo "DOCTOR_PASS" >> "$EVIDENCE"
80
91
 
92
+ if command -v claude >/dev/null 2>&1; then
93
+ run_step CLAUDE_PLUGIN_DETAILS claude plugin details lazyclaude@lazyclaude-ai
94
+ if ! grep -q "Skills (7)" "$EVIDENCE" || ! grep -q "ulw-loop" "$EVIDENCE" || ! grep -q "ulw-plan" "$EVIDENCE" || ! grep -q "Hooks (4)" "$EVIDENCE"; then
95
+ echo "CLAUDE_PLUGIN_DETAILS_FAIL: expected LazyClaude skills/hooks inventory" >> "$EVIDENCE"
96
+ echo "CLAUDE_PLUGIN_DETAILS_FAIL"
97
+ exit 1
98
+ fi
99
+ else
100
+ echo "CLAUDE_PLUGIN_DETAILS_SKIP: claude executable not found" >> "$EVIDENCE"
101
+ fi
102
+
81
103
  run_step DRY_RUN_UNINSTALL node "$ROOT/bin/lazyclaude-ai.js" --dry-run uninstall
82
104
  if [ ! -d "$PLUGIN_PATH" ]; then
83
105
  echo "DRY_RUN_UNINSTALL_FAIL: plugin removed during dry-run" >> "$EVIDENCE"
@@ -91,6 +113,7 @@ if [ -e "$TMP_HOME/current" ] || [ -e "$TMP_HOME/lazyclaude-ai" ] || [ -e "$TMP_
91
113
  exit 1
92
114
  fi
93
115
  node -e 'const fs = require("fs"); const p = process.argv[1]; const settings = JSON.parse(fs.readFileSync(`${p}/settings.json`, "utf8")); if (settings.enabledPlugins?.["lazyclaude@lazyclaude-ai"] !== undefined) process.exit(1);' "$TMP_CLAUDE_HOME"
116
+ node -e 'const fs = require("fs"); const p = process.argv[1]; const settings = JSON.parse(fs.readFileSync(`${p}/settings.json`, "utf8")); const known = JSON.parse(fs.readFileSync(`${p}/plugins/known_marketplaces.json`, "utf8")); if (settings.extraKnownMarketplaces?.["lazyclaude-ai"] !== undefined || known["lazyclaude-ai"] !== undefined) process.exit(1);' "$TMP_CLAUDE_HOME"
94
117
  echo "UNINSTALL_PASS" >> "$EVIDENCE"
95
118
 
96
119
  cleanup