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 +7 -6
- package/README_ko-KR.md +12 -9
- package/RELEASE_CHECKLIST.md +13 -9
- package/bin/lazyclaude-ai.js +103 -12
- package/docs/migration.md +3 -2
- package/package.json +1 -1
- package/plugins/lazyclaude/.claude-plugin/plugin.json +1 -1
- package/scripts/qa-portable-install.sh +24 -1
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.
|
|
9
|
-
the next `0.1.
|
|
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.
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
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.
|
|
9
|
-
`0.1.
|
|
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
|
-
|
|
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하지 않는 것을 권장합니다.
|
|
79
|
-
`--plugin-dir`로 직접
|
|
80
|
-
|
|
81
|
-
|
|
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
|
|
package/RELEASE_CHECKLIST.md
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
# LazyClaude Release Checklist
|
|
2
2
|
|
|
3
|
-
Status: quiet public npm package `lazyclaude-ai@0.1.
|
|
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.
|
|
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
|
|
44
|
-
|
|
45
|
-
|
|
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.
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
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
|
|
package/bin/lazyclaude-ai.js
CHANGED
|
@@ -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
|
|
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
|
|
169
|
+
const unregisterMarketplace = (home = claudeHome()) => {
|
|
99
170
|
const settingsPath = claudeSettingsPath(home);
|
|
100
|
-
if (
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
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
|
-
|
|
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
|
-
|
|
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
|
@@ -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
|