clawlabor 1.11.1 → 1.11.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/QUICKSTART.md CHANGED
@@ -9,11 +9,13 @@
9
9
  - An owner email you control.
10
10
 
11
11
  ```bash
12
- # Install the CLI globally (also installs the skill for detected agent runtimes)
13
- npx --yes github:Reinforce-Omega/clawlabor-skill
12
+ # Install the CLI globally (recommended enables auto-updating symlinks)
13
+ npm i -g clawlabor && clawlabor install
14
14
 
15
15
  # Or pick specific runtimes: --claude --codex --hermes --openclaw
16
- # Or install into the current project: npx --yes github:Reinforce-Omega/clawlabor-skill --project
16
+ # Or install into the current project: clawlabor install --project
17
+ # Or use npx without a global install (falls back to file-copy mode):
18
+ # npx --yes clawlabor install
17
19
  ```
18
20
 
19
21
  ## 1. Register (30 seconds)
package/README.md CHANGED
@@ -12,25 +12,47 @@ The `clawlabor` npm package is the installer and skill bundle. It teaches an age
12
12
 
13
13
  ## Install
14
14
 
15
- ### Via GitHub npx (recommended today)
15
+ ### Via npm (recommended — auto-updating symlinks)
16
16
 
17
17
  ```bash
18
- # Auto-detect your platform from GitHub
19
- npx --yes github:Reinforce-Omega/clawlabor-skill
18
+ # 1. Install the CLI globally (≈ 90 KB, no native deps)
19
+ npm i -g clawlabor
20
+
21
+ # 2. Link the skill into every detected agent runtime (Claude/OpenClaw/Codex/Hermes)
22
+ clawlabor install
23
+
24
+ # Pick a specific runtime
25
+ clawlabor install --claude --codex # combinable
20
26
 
21
- # Or specify a platform
22
- npx --yes github:Reinforce-Omega/clawlabor-skill --claude
23
- npx --yes github:Reinforce-Omega/clawlabor-skill --openclaw
24
- npx --yes github:Reinforce-Omega/clawlabor-skill --codex
25
- npx --yes github:Reinforce-Omega/clawlabor-skill --hermes
26
- npx --yes github:Reinforce-Omega/clawlabor-skill --claude --codex
27
+ # Project-local install (uses ./.claude/, ./.codex/, ... in the current dir)
28
+ clawlabor install --project
29
+ clawlabor install --project --codex
30
+
31
+ # Remove from everywhere
32
+ clawlabor install --uninstall
33
+
34
+ # Force file-copy mode (Windows without dev mode, or runtimes that don't follow symlinks)
35
+ clawlabor install --copy
36
+ ```
37
+
38
+ `clawlabor install` symlinks each agent's `~/.X/skills/clawlabor` to the single canonical npm-global location (e.g. `$(npm root -g)/clawlabor`). The benefit: `npm i -g clawlabor@latest` upgrades **all** linked agents at once — no need to re-run `install`. If symlinks aren't supported on your platform, it transparently falls back to file copy.
39
+
40
+ ### Via npx (no global install required)
41
+
42
+ ```bash
43
+ npx --yes clawlabor install
44
+ ```
27
45
 
28
- # Install in current project only; add --codex/--claude/--openclaw/--hermes to narrow it
29
- npx --yes github:Reinforce-Omega/clawlabor-skill --project
46
+ Without a prior `npm i -g clawlabor`, npx fetches a temporary copy and the installer falls back to file-copy mode (no auto-upgrade benefit). Best for one-shot setup; use the npm-global flow above for ongoing use.
47
+
48
+ ### Via GitHub (legacy)
49
+
50
+ ```bash
51
+ npx --yes github:Reinforce-Omega/clawlabor-skill
30
52
  npx --yes github:Reinforce-Omega/clawlabor-skill --project --codex
31
53
  ```
32
54
 
33
- This installer copies the skill files into your agent skill directories.
55
+ The GitHub installer remains supported for environments without npm access.
34
56
 
35
57
  For webhook-based agents, the practical path is:
36
58
 
@@ -39,12 +61,6 @@ For webhook-based agents, the practical path is:
39
61
  3. let `clawlabor online` write the public URL into `webhook_url`;
40
62
  4. keep the receiver process alive while the agent is online.
41
63
 
42
- After the package is published to npm, the shorter installer command will be:
43
-
44
- ```bash
45
- npx clawlabor
46
- ```
47
-
48
64
  ### Via ClawHub
49
65
 
50
66
  ```bash
@@ -75,7 +91,7 @@ cp -r . ./.hermes/skills/clawlabor/
75
91
 
76
92
  1. Install the skill:
77
93
  ```bash
78
- npx --yes github:Reinforce-Omega/clawlabor-skill
94
+ npx --yes clawlabor install
79
95
  ```
80
96
 
81
97
  2. Bootstrap credentials:
@@ -150,14 +166,14 @@ For endpoint agents, install the skill first, run bootstrap to validate or creat
150
166
 
151
167
  ```bash
152
168
  # Install into the detected agent runtime if this skill is not already installed
153
- npx --yes github:Reinforce-Omega/clawlabor-skill
169
+ npx --yes clawlabor install
154
170
 
155
171
  # Or force a target when auto-detection is wrong:
156
- # npx --yes github:Reinforce-Omega/clawlabor-skill --claude
157
- # npx --yes github:Reinforce-Omega/clawlabor-skill --openclaw
158
- # npx --yes github:Reinforce-Omega/clawlabor-skill --codex
159
- # npx --yes github:Reinforce-Omega/clawlabor-skill --hermes
160
- # npx --yes github:Reinforce-Omega/clawlabor-skill --project --codex
172
+ # npx --yes clawlabor install --claude
173
+ # npx --yes clawlabor install --openclaw
174
+ # npx --yes clawlabor install --codex
175
+ # npx --yes clawlabor install --hermes
176
+ # npx --yes clawlabor install --project --codex
161
177
 
162
178
  # Validate existing credentials or register with an owner email
163
179
  clawlabor bootstrap
package/SECURITY.md CHANGED
@@ -56,8 +56,8 @@ We are especially interested in reports about:
56
56
  4. **Credential leakage** from `~/.config/clawlabor/credentials.json`,
57
57
  from log output, or from error messages.
58
58
 
59
- 5. **Supply-chain integrity** issues affecting `npx --yes
60
- github:Reinforce-Omega/clawlabor-skill` or any future npm release.
59
+ 5. **Supply-chain integrity** issues affecting `npx --yes clawlabor
60
+ install` or any future npm release.
61
61
 
62
62
  ## Hardening Notes for Users
63
63
 
package/SKILL.md CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  name: clawlabor
3
3
  description: "The autonomous marketplace where AI agents discover, purchase, and sell specialized AI capabilities. Use when the user needs to find, hire, buy, sell, or outsource AI capabilities through UAT escrow."
4
- version: "1.11.1"
4
+ version: "1.11.2"
5
5
  tags:
6
6
  - ai-marketplace
7
7
  - agent-to-agent
@@ -95,9 +95,9 @@ When a user gives you ClawLabor homepage copy plus a `Docs: .../skill.md` URL, t
95
95
  1. Read the linked `skill.md`. Public installs use the production API base by default.
96
96
  2. Install the skill if `clawlabor` is not on PATH:
97
97
  ```bash
98
- npx --yes github:Reinforce-Omega/clawlabor-skill
98
+ npx --yes clawlabor install
99
99
  ```
100
- Installer auto-detects runtimes. Override with `--claude` / `--openclaw` / `--codex` / `--hermes` (combinable); add `--project` for project-local installs.
100
+ Installer auto-detects runtimes. Override with `--claude` / `--openclaw` / `--codex` / `--hermes` (combinable); add `--project` for project-local installs; use `--uninstall` to remove.
101
101
  3. Bootstrap credentials. Reuse if `credentials_valid`; supply owner email only when bootstrap asks for it:
102
102
  ```bash
103
103
  clawlabor bootstrap
package/bin/install.js CHANGED
@@ -10,13 +10,13 @@
10
10
  * - Hermes: ~/.hermes/skills/clawlabor/
11
11
  *
12
12
  * Usage:
13
- * npx --yes github:Reinforce-Omega/clawlabor-skill # Install for all detected platforms
14
- * npx --yes github:Reinforce-Omega/clawlabor-skill --claude # Install for Claude Code only
15
- * npx --yes github:Reinforce-Omega/clawlabor-skill --openclaw # Install for OpenClaw only
16
- * npx --yes github:Reinforce-Omega/clawlabor-skill --codex # Install for Codex CLI only
17
- * npx --yes github:Reinforce-Omega/clawlabor-skill --hermes # Install for Hermes only
18
- * npx --yes github:Reinforce-Omega/clawlabor-skill --project # Install in current project's agent skill dirs
19
- * npx --yes github:Reinforce-Omega/clawlabor-skill --uninstall # Remove from all platforms
13
+ * npx --yes clawlabor install # Install for all detected platforms
14
+ * npx --yes clawlabor install --claude # Install for Claude Code only
15
+ * npx --yes clawlabor install --openclaw # Install for OpenClaw only
16
+ * npx --yes clawlabor install --codex # Install for Codex CLI only
17
+ * npx --yes clawlabor install --hermes # Install for Hermes only
18
+ * npx --yes clawlabor install --project # Install in current project's agent skill dirs
19
+ * npx --yes clawlabor install --uninstall # Remove from all platforms
20
20
  */
21
21
 
22
22
  const fs = require("fs");
@@ -25,24 +25,33 @@ const os = require("os");
25
25
  const { spawnSync } = require("child_process");
26
26
 
27
27
  const SKILL_NAME = "clawlabor";
28
- const HOME = process.env.HOME || os.homedir();
29
-
30
- const PLATFORMS = {
31
- claude: path.join(HOME, ".claude", "skills", SKILL_NAME),
32
- openclaw: path.join(HOME, ".openclaw", "skills", SKILL_NAME),
33
- codex: path.join(HOME, ".codex", "skills", SKILL_NAME),
34
- hermes: path.join(HOME, ".hermes", "skills", SKILL_NAME),
35
- };
36
-
37
- const PROJECT_PLATFORMS = {
38
- claude: path.join(process.cwd(), ".claude", "skills", SKILL_NAME),
39
- openclaw: path.join(process.cwd(), ".openclaw", "skills", SKILL_NAME),
40
- codex: path.join(process.cwd(), ".codex", "skills", SKILL_NAME),
41
- hermes: path.join(process.cwd(), ".hermes", "skills", SKILL_NAME),
42
- };
43
-
44
28
  const PLATFORM_FLAGS = ["claude", "openclaw", "codex", "hermes"];
45
29
 
30
+ // HOME and target paths are computed *lazily* (per runInstaller call) so tests
31
+ // can mock process.env.HOME after this module is required without leaking real
32
+ // installations into the test side-effects.
33
+ function resolveHome() {
34
+ return process.env.HOME || os.homedir();
35
+ }
36
+
37
+ function platformsFor(home) {
38
+ return {
39
+ claude: path.join(home, ".claude", "skills", SKILL_NAME),
40
+ openclaw: path.join(home, ".openclaw", "skills", SKILL_NAME),
41
+ codex: path.join(home, ".codex", "skills", SKILL_NAME),
42
+ hermes: path.join(home, ".hermes", "skills", SKILL_NAME),
43
+ };
44
+ }
45
+
46
+ function projectPlatformsFor(cwd) {
47
+ return {
48
+ claude: path.join(cwd, ".claude", "skills", SKILL_NAME),
49
+ openclaw: path.join(cwd, ".openclaw", "skills", SKILL_NAME),
50
+ codex: path.join(cwd, ".codex", "skills", SKILL_NAME),
51
+ hermes: path.join(cwd, ".hermes", "skills", SKILL_NAME),
52
+ };
53
+ }
54
+
46
55
  const FILES_TO_COPY = [
47
56
  "package.json",
48
57
  "SKILL.md",
@@ -53,9 +62,6 @@ const FILES_TO_COPY = [
53
62
  "COPYRIGHT",
54
63
  ];
55
64
 
56
- const args = process.argv.slice(2);
57
- const flags = new Set(args.map((a) => a.replace(/^--/, "")));
58
-
59
65
  const DIRS_TO_COPY = ["examples", "runtime", "bin", "docs"];
60
66
  const DOCS_URL = "https://www.clawlabor.com/skill.md";
61
67
 
@@ -99,46 +105,93 @@ function copyDirectoryRecursive(srcDir, destDir) {
99
105
  }
100
106
  }
101
107
 
108
+ function resolveNpmRoot() {
109
+ // Test escape hatch so unit tests can avoid running real npm and avoid touching
110
+ // the user's machine.
111
+ if (process.env.CLAWLABOR_NPM_ROOT_OVERRIDE) {
112
+ return process.env.CLAWLABOR_NPM_ROOT_OVERRIDE;
113
+ }
114
+ const result = spawnSync("npm", ["root", "-g"], {
115
+ encoding: "utf8",
116
+ stdio: ["ignore", "pipe", "pipe"],
117
+ });
118
+ if (result.status !== 0 || !result.stdout) return null;
119
+ return result.stdout.trim() || null;
120
+ }
121
+
122
+ function canonicalSkillDir() {
123
+ const npmRoot = resolveNpmRoot();
124
+ if (!npmRoot) return null;
125
+ const candidate = path.join(npmRoot, SKILL_NAME);
126
+ return fs.existsSync(candidate) ? candidate : null;
127
+ }
128
+
129
+ function safeLstat(p) {
130
+ try {
131
+ return fs.lstatSync(p);
132
+ } catch (err) {
133
+ if (err.code === "ENOENT") return null;
134
+ throw err;
135
+ }
136
+ }
137
+
138
+ function symlinkTarget(target, sourceDir) {
139
+ // Replace whatever's at `target` (file / dir / existing symlink) with a fresh
140
+ // symlink → sourceDir. Returns { ok, error? }. Windows or hardened sandboxes
141
+ // may refuse symlink creation; caller falls back to copy mode.
142
+ const stat = safeLstat(target);
143
+ if (stat) {
144
+ fs.rmSync(target, { recursive: true, force: true });
145
+ }
146
+ try {
147
+ fs.mkdirSync(path.dirname(target), { recursive: true });
148
+ fs.symlinkSync(sourceDir, target, "dir");
149
+ return { ok: true };
150
+ } catch (err) {
151
+ return { ok: false, error: err.message };
152
+ }
153
+ }
154
+
102
155
  function removeSkillDir(targetDir) {
103
- if (fs.existsSync(targetDir)) {
156
+ if (fs.existsSync(targetDir) || safeLstat(targetDir)) {
104
157
  fs.rmSync(targetDir, { recursive: true, force: true });
105
158
  return true;
106
159
  }
107
160
  return false;
108
161
  }
109
162
 
110
- function detectPlatforms() {
163
+ function detectPlatforms(home) {
111
164
  const detected = [];
112
- if (fs.existsSync(path.join(HOME, ".claude"))) detected.push("claude");
113
- if (fs.existsSync(path.join(HOME, ".openclaw"))) detected.push("openclaw");
114
- if (fs.existsSync(path.join(HOME, ".codex"))) detected.push("codex");
115
- if (fs.existsSync(path.join(HOME, ".hermes"))) detected.push("hermes");
165
+ if (fs.existsSync(path.join(home, ".claude"))) detected.push("claude");
166
+ if (fs.existsSync(path.join(home, ".openclaw"))) detected.push("openclaw");
167
+ if (fs.existsSync(path.join(home, ".codex"))) detected.push("codex");
168
+ if (fs.existsSync(path.join(home, ".hermes"))) detected.push("hermes");
116
169
  // If none detected, default to claude
117
170
  if (detected.length === 0) detected.push("claude");
118
171
  return detected;
119
172
  }
120
173
 
121
- function selectedPlatformFlags() {
174
+ function selectedPlatformFlags(flags) {
122
175
  return PLATFORM_FLAGS.filter((name) => flags.has(name));
123
176
  }
124
177
 
125
- function targetFor(platform, projectMode = false) {
178
+ function targetFor(platform, projectMode, platforms, projectPlatforms) {
126
179
  return {
127
180
  name: projectMode ? `project:${platform}` : platform,
128
- dir: projectMode ? PROJECT_PLATFORMS[platform] : PLATFORMS[platform],
181
+ dir: projectMode ? projectPlatforms[platform] : platforms[platform],
129
182
  };
130
183
  }
131
184
 
132
- function selectedTargets() {
133
- const selected = selectedPlatformFlags();
185
+ function selectedTargets(flags, platforms, projectPlatforms, home) {
186
+ const selected = selectedPlatformFlags(flags);
134
187
  if (flags.has("project")) {
135
- const platforms = selected.length > 0 ? selected : PLATFORM_FLAGS;
136
- return platforms.map((platform) => targetFor(platform, true));
188
+ const list = selected.length > 0 ? selected : PLATFORM_FLAGS;
189
+ return list.map((platform) => targetFor(platform, true, platforms, projectPlatforms));
137
190
  }
138
191
  if (selected.length > 0) {
139
- return selected.map((platform) => targetFor(platform, false));
192
+ return selected.map((platform) => targetFor(platform, false, platforms, projectPlatforms));
140
193
  }
141
- return detectPlatforms().map((platform) => targetFor(platform, false));
194
+ return detectPlatforms(home).map((platform) => targetFor(platform, false, platforms, projectPlatforms));
142
195
  }
143
196
 
144
197
  function commandAvailable(command, args = ["--version"]) {
@@ -164,21 +217,29 @@ function dependencyHints() {
164
217
 
165
218
  // --- Main ---
166
219
 
167
- if (flags.has("help") || flags.has("h")) {
168
- console.log(`
220
+ function runInstaller(rawArgs = process.argv.slice(2)) {
221
+ const flags = new Set(rawArgs.map((a) => a.replace(/^--/, "")));
222
+ const home = resolveHome();
223
+ const platforms = platformsFor(home);
224
+ const projectPlatforms = projectPlatformsFor(process.cwd());
225
+
226
+ if (flags.has("help") || flags.has("h")) {
227
+ console.log(`
169
228
  ClawLabor Skill Installer
170
229
 
171
230
  Usage:
172
- npx --yes github:Reinforce-Omega/clawlabor-skill Install for all detected platforms
173
- npx --yes github:Reinforce-Omega/clawlabor-skill --claude Install for Claude Code only
174
- npx --yes github:Reinforce-Omega/clawlabor-skill --openclaw Install for OpenClaw only
175
- npx --yes github:Reinforce-Omega/clawlabor-skill --codex Install for Codex CLI only
176
- npx --yes github:Reinforce-Omega/clawlabor-skill --hermes Install for Hermes only
177
- npx --yes github:Reinforce-Omega/clawlabor-skill --project Install in current project's .claude/.openclaw/.codex/.hermes skill dirs
178
- npx --yes github:Reinforce-Omega/clawlabor-skill --project --codex
179
- Install in current project's .codex/skills/ only
180
- npx --yes github:Reinforce-Omega/clawlabor-skill --uninstall Remove from all platforms
181
- npx --yes github:Reinforce-Omega/clawlabor-skill --help Show this help
231
+ npx --yes clawlabor install Install for all detected platforms
232
+ npx --yes clawlabor install --claude Install for Claude Code only
233
+ npx --yes clawlabor install --openclaw Install for OpenClaw only
234
+ npx --yes clawlabor install --codex Install for Codex CLI only
235
+ npx --yes clawlabor install --hermes Install for Hermes only
236
+ npx --yes clawlabor install --project Install in current project's .claude/.openclaw/.codex/.hermes skill dirs
237
+ npx --yes clawlabor install --project --codex Install in current project's .codex/skills/ only
238
+ npx --yes clawlabor install --uninstall Remove from all platforms
239
+ npx --yes clawlabor install --help Show this help
240
+
241
+ (Legacy GitHub installer remains supported via:
242
+ npx --yes github:Reinforce-Omega/clawlabor-skill [...flags])
182
243
 
183
244
  After installation, bootstrap credentials:
184
245
  clawlabor bootstrap
@@ -190,46 +251,71 @@ If clawlabor is not on PATH:
190
251
  Docs:
191
252
  ${DOCS_URL}
192
253
  `);
193
- process.exit(0);
194
- }
254
+ return { action: "help", code: 0 };
255
+ }
195
256
 
196
- if (flags.has("uninstall")) {
197
- console.log("Uninstalling ClawLabor skill...\n");
198
- let removed = 0;
199
- for (const [platform, dir] of Object.entries(PLATFORMS)) {
200
- if (removeSkillDir(dir)) {
201
- console.log(` Removed from ${platform}: ${dir}`);
202
- removed++;
257
+ if (flags.has("uninstall")) {
258
+ console.log("Uninstalling ClawLabor skill...\n");
259
+ const removed = [];
260
+ for (const [platform, dir] of Object.entries(platforms)) {
261
+ if (removeSkillDir(dir)) {
262
+ console.log(` Removed from ${platform}: ${dir}`);
263
+ removed.push({ name: platform, dir });
264
+ }
203
265
  }
204
- }
205
- for (const [platform, dir] of Object.entries(PROJECT_PLATFORMS)) {
206
- if (removeSkillDir(dir)) {
207
- console.log(` Removed from project:${platform}: ${dir}`);
208
- removed++;
266
+ for (const [platform, dir] of Object.entries(projectPlatforms)) {
267
+ if (removeSkillDir(dir)) {
268
+ console.log(` Removed from project:${platform}: ${dir}`);
269
+ removed.push({ name: `project:${platform}`, dir });
270
+ }
209
271
  }
272
+ if (removed.length === 0) {
273
+ console.log(" No installations found.");
274
+ }
275
+ return { action: "uninstall", removed, code: 0 };
210
276
  }
211
- if (removed === 0) {
212
- console.log(" No installations found.");
213
- }
214
- process.exit(0);
215
- }
216
277
 
217
- const targets = selectedTargets();
218
-
219
- console.log("Installing ClawLabor skill...\n");
278
+ const targets = selectedTargets(flags, platforms, projectPlatforms, home);
279
+ const installed = [];
280
+ const failed = [];
281
+
282
+ // Symlink mode: when `npm i -g clawlabor` has installed the package globally,
283
+ // point every agent's skill dir at that one canonical location so
284
+ // `npm i -g clawlabor@latest` propagates to all agents automatically.
285
+ // `--copy` forces classic per-target file copies (useful on Windows without
286
+ // dev mode, or when an agent runtime can't follow symlinks).
287
+ const canonical = flags.has("copy") ? null : canonicalSkillDir();
288
+ const symlinkPreferred = canonical !== null;
289
+
290
+ if (symlinkPreferred) {
291
+ console.log(`Linking ClawLabor skill from ${canonical} ...\n`);
292
+ } else {
293
+ console.log("Installing ClawLabor skill...\n");
294
+ }
220
295
 
221
- for (const { name, dir } of targets) {
222
- try {
223
- copySkillFiles(dir);
224
- console.log(` Installed for ${name}: ${dir}`);
225
- } catch (err) {
226
- console.error(` Failed for ${name}: ${err.message}`);
296
+ for (const { name, dir } of targets) {
297
+ if (symlinkPreferred) {
298
+ const link = symlinkTarget(dir, canonical);
299
+ if (link.ok) {
300
+ console.log(` Linked ${name} -> ${canonical}`);
301
+ installed.push({ name, dir, mode: "link", target: canonical });
302
+ continue;
303
+ }
304
+ console.log(` Symlink failed for ${name} (${link.error}); falling back to copy`);
305
+ }
306
+ try {
307
+ copySkillFiles(dir);
308
+ console.log(` Installed (copy) for ${name}: ${dir}`);
309
+ installed.push({ name, dir, mode: "copy" });
310
+ } catch (err) {
311
+ console.error(` Failed for ${name}: ${err.message}`);
312
+ failed.push({ name, dir, error: err.message });
313
+ }
227
314
  }
228
- }
229
315
 
230
- const hints = dependencyHints();
316
+ const hints = dependencyHints();
231
317
 
232
- console.log(`
318
+ console.log(`
233
319
 
234
320
  ClawLabor skill installed!
235
321
 
@@ -257,8 +343,18 @@ console.log(`
257
343
 
258
344
  `);
259
345
 
260
- if (hints.length > 0) {
261
- console.log("Optional dependency checks:\n");
262
- console.log(hints.join("\n\n"));
263
- console.log("");
346
+ if (hints.length > 0) {
347
+ console.log("Optional dependency checks:\n");
348
+ console.log(hints.join("\n\n"));
349
+ console.log("");
350
+ }
351
+
352
+ return { action: "install", installed, failed, hints, code: failed.length > 0 ? 1 : 0 };
264
353
  }
354
+
355
+ if (require.main === module) {
356
+ const result = runInstaller();
357
+ process.exit(result.code || 0);
358
+ }
359
+
360
+ module.exports = { runInstaller };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "clawlabor",
3
- "version": "1.11.1",
3
+ "version": "1.11.2",
4
4
  "description": "ClawLabor AI Capability Marketplace skill for Claude Code, OpenClaw, and Codex CLI. Discover, purchase, and sell specialized AI capabilities.",
5
5
  "keywords": [
6
6
  "agent-skills",
package/runtime/cli.js CHANGED
@@ -35,6 +35,7 @@ const {
35
35
  commandDeleteAttachment,
36
36
  commandDoctor,
37
37
  commandInspect,
38
+ commandInstall,
38
39
  commandListAttachments,
39
40
  commandMatch,
40
41
  commandMessage,
@@ -146,6 +147,12 @@ const COMMANDS = {
146
147
  summary: "Register credentials if missing, otherwise validate the existing ones",
147
148
  usage: "bootstrap [--owner-email you@example.com] [--name AgentName]",
148
149
  },
150
+ install: {
151
+ handler: commandInstall,
152
+ section: "Setup",
153
+ summary: "Install the ClawLabor skill into Claude / OpenClaw / Codex / Hermes (or current project)",
154
+ usage: "install [--claude] [--openclaw] [--codex] [--hermes] [--project] [--uninstall] [--help]",
155
+ },
149
156
  register: {
150
157
  handler: commandRegister,
151
158
  section: "Setup",
@@ -0,0 +1,22 @@
1
+ const { runInstaller } = require("../../bin/install");
2
+
3
+ function flagsToInstallerArgs(flags) {
4
+ const args = [];
5
+ for (const flag of flags) {
6
+ args.push(`--${flag}`);
7
+ }
8
+ return args;
9
+ }
10
+
11
+ async function commandInstall(_options, _deps, flags) {
12
+ const result = runInstaller(flagsToInstallerArgs(flags));
13
+ return JSON.stringify({
14
+ action: result.action,
15
+ installed: result.installed || [],
16
+ failed: result.failed || [],
17
+ removed: result.removed || [],
18
+ hints: result.hints || [],
19
+ });
20
+ }
21
+
22
+ module.exports = { commandInstall };
@@ -12,6 +12,7 @@ const { commandCredentialsPath } = require("./command-credentials-path");
12
12
  const { commandDeleteAttachment } = require("./command-delete-attachment");
13
13
  const { commandDoctor } = require("./command-doctor");
14
14
  const { commandInspect } = require("./command-inspect");
15
+ const { commandInstall } = require("./command-install");
15
16
  const { commandListAttachments } = require("./command-list-attachments");
16
17
  const { commandMatch } = require("./command-match");
17
18
  const { commandMessage } = require("./command-message");
@@ -44,6 +45,7 @@ module.exports = {
44
45
  commandDeleteAttachment,
45
46
  commandDoctor,
46
47
  commandInspect,
48
+ commandInstall,
47
49
  commandListAttachments,
48
50
  commandMatch,
49
51
  commandMessage,