@web42/cli 0.1.0 → 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.
@@ -5,6 +5,7 @@ import chalk from "chalk";
5
5
  import inquirer from "inquirer";
6
6
  import { requireAuth } from "../utils/config.js";
7
7
  import { parseSkillMd } from "../utils/skill.js";
8
+ import { resolvePlatform, listPlatforms } from "../platforms/registry.js";
8
9
  import { AGENTS_MD, IDENTITY_MD, SOUL_MD, TOOLS_MD, USER_MD, HEARTBEAT_MD, INIT_BOOTSTRAP_MD, } from "../platforms/openclaw/templates.js";
9
10
  function detectWorkspaceSkills(cwd) {
10
11
  const skillsDir = join(cwd, "skills");
@@ -29,24 +30,13 @@ function detectWorkspaceSkills(cwd) {
29
30
  }
30
31
  return skills.sort((a, b) => a.name.localeCompare(b.name));
31
32
  }
32
- const CATEGORIES = [
33
- "Customer Support",
34
- "Healthcare",
35
- "Developer Tools",
36
- "Personal Assistant",
37
- "Sales",
38
- "Marketing",
39
- "Education",
40
- "Finance",
41
- "Content Creation",
42
- "Productivity",
43
- ];
44
33
  export const initCommand = new Command("init")
45
34
  .description("Create a manifest.json for your agent package")
46
35
  .action(async () => {
47
36
  const config = requireAuth();
48
37
  const cwd = process.cwd();
49
38
  const manifestPath = join(cwd, "manifest.json");
39
+ let existingManifest = null;
50
40
  if (existsSync(manifestPath)) {
51
41
  const { overwrite } = await inquirer.prompt([
52
42
  {
@@ -60,62 +50,51 @@ export const initCommand = new Command("init")
60
50
  console.log(chalk.yellow("Aborted."));
61
51
  return;
62
52
  }
53
+ try {
54
+ existingManifest = JSON.parse(readFileSync(manifestPath, "utf-8"));
55
+ }
56
+ catch {
57
+ // ignore parse errors from existing manifest
58
+ }
63
59
  }
64
- const answers = await inquirer.prompt([
60
+ const platforms = listPlatforms();
61
+ const { platform } = await inquirer.prompt([
65
62
  {
66
63
  type: "list",
67
64
  name: "platform",
68
65
  message: "Platform:",
69
- choices: ["openclaw"],
70
- default: "openclaw",
71
- },
72
- {
73
- type: "input",
74
- name: "name",
75
- message: "Agent name (lowercase, hyphens allowed):",
76
- validate: (val) => /^[a-z0-9][a-z0-9-]*$/.test(val) ||
77
- "Must be lowercase alphanumeric with hyphens",
66
+ choices: platforms,
67
+ default: platforms[0],
78
68
  },
69
+ ]);
70
+ const adapter = resolvePlatform(platform);
71
+ const initConfig = adapter.extractInitConfig(cwd);
72
+ if (!initConfig) {
73
+ console.log(chalk.red(`No agent entry found in ${adapter.name} config for this directory.\n` +
74
+ `Set up your agent in ${adapter.name} first.`));
75
+ process.exit(1);
76
+ }
77
+ console.log();
78
+ console.log(chalk.dim(` Agent: ${chalk.bold(initConfig.name)} (from ${adapter.name} config)`));
79
+ if (initConfig.model) {
80
+ console.log(chalk.dim(` Model: ${initConfig.model}`));
81
+ }
82
+ console.log();
83
+ const answers = await inquirer.prompt([
79
84
  {
80
85
  type: "input",
81
86
  name: "description",
82
87
  message: "Short description:",
83
- validate: (val) => val.length > 0 && val.length <= 500 || "1-500 characters",
88
+ default: existingManifest?.description ?? "",
89
+ validate: (val) => (val.length > 0 && val.length <= 500) || "1-500 characters",
84
90
  },
85
91
  {
86
92
  type: "input",
87
93
  name: "version",
88
94
  message: "Version:",
89
- default: "1.0.0",
95
+ default: existingManifest?.version ?? "1.0.0",
90
96
  validate: (val) => /^\d+\.\d+\.\d+$/.test(val) || "Must follow semver (e.g. 1.0.0)",
91
97
  },
92
- {
93
- type: "list",
94
- name: "category",
95
- message: "Primary category:",
96
- choices: CATEGORIES,
97
- },
98
- {
99
- type: "input",
100
- name: "tags",
101
- message: "Tags (comma-separated):",
102
- filter: (val) => val
103
- .split(",")
104
- .map((t) => t.trim())
105
- .filter(Boolean),
106
- },
107
- {
108
- type: "input",
109
- name: "primaryModel",
110
- message: "Primary model preference (e.g. claude-sonnet-4-20250514):",
111
- default: "",
112
- },
113
- {
114
- type: "input",
115
- name: "demoVideoUrl",
116
- message: "Demo video URL (optional):",
117
- default: "",
118
- },
119
98
  ]);
120
99
  const detectedSkills = detectWorkspaceSkills(cwd);
121
100
  if (detectedSkills.length > 0) {
@@ -123,18 +102,16 @@ export const initCommand = new Command("init")
123
102
  }
124
103
  const manifest = {
125
104
  format: "agentpkg/1",
126
- platform: answers.platform,
127
- name: answers.name,
105
+ platform,
106
+ name: initConfig.name,
128
107
  description: answers.description,
129
108
  version: answers.version,
130
109
  author: config.username,
131
110
  skills: detectedSkills,
132
111
  plugins: [],
133
- modelPreferences: answers.primaryModel
134
- ? { primary: answers.primaryModel }
112
+ modelPreferences: initConfig.model
113
+ ? { primary: initConfig.model }
135
114
  : undefined,
136
- tags: answers.tags,
137
- demoVideoUrl: answers.demoVideoUrl || undefined,
138
115
  configVariables: [],
139
116
  };
140
117
  writeFileSync(manifestPath, JSON.stringify(manifest, null, 2) + "\n");
@@ -66,7 +66,7 @@ export function makeInstallCommand(adapter) {
66
66
  catch (err) {
67
67
  if (err.message?.includes("Access required") &&
68
68
  agent.price_cents > 0) {
69
- const siteUrl = process.env.WEB42_API_URL ?? "https://marketplace.web42.ai";
69
+ const siteUrl = process.env.WEB42_API_URL ?? "https://web42.ai";
70
70
  spinner.fail(`This is a paid agent ($${(agent.price_cents / 100).toFixed(2)}). Purchase it on the web first:`);
71
71
  console.log(chalk.cyan(` ${siteUrl}/${username}/${agentSlug}`));
72
72
  process.exit(1);
@@ -117,7 +117,7 @@ export const pushCommand = new Command("push")
117
117
  else {
118
118
  console.log(chalk.green(" Agent updated."));
119
119
  }
120
- console.log(chalk.dim(` View at: ${config.apiUrl ? config.apiUrl.replace("https://", "") : "agents.web42.ai"}/${config.username}/${manifest.name}`));
120
+ console.log(chalk.dim(` View at: ${config.apiUrl ? config.apiUrl.replace("https://", "") : "web42.ai"}/${config.username}/${manifest.name}`));
121
121
  }
122
122
  catch (error) {
123
123
  spinner.fail("Push failed");
@@ -38,7 +38,7 @@ export const searchCommand = new Command("search")
38
38
  }
39
39
  const platform = agent.manifest?.platform ?? "openclaw";
40
40
  if (agent.price_cents > 0) {
41
- const siteUrl = process.env.WEB42_API_URL ?? "https://marketplace.web42.ai";
41
+ const siteUrl = process.env.WEB42_API_URL ?? "https://web42.ai";
42
42
  console.log(chalk.dim(` Purchase: ${siteUrl}/${agent.owner.username}/${agent.slug}`));
43
43
  }
44
44
  else {
@@ -48,9 +48,14 @@ export interface InstalledAgent {
48
48
  source?: string;
49
49
  workspace: string;
50
50
  }
51
+ export interface InitConfig {
52
+ name: string;
53
+ model?: string;
54
+ }
51
55
  export interface PlatformAdapter {
52
56
  name: string;
53
57
  home: string;
58
+ extractInitConfig(cwd: string): InitConfig | null;
54
59
  pack(options: PackOptions): Promise<PackResult>;
55
60
  install(options: InstallOptions): Promise<InstallResult>;
56
61
  uninstall(options: UninstallOptions): Promise<UninstallResult>;
@@ -1,7 +1,8 @@
1
- import type { InstalledAgent, InstallOptions, InstallResult, PackOptions, PackResult, PlatformAdapter, UninstallOptions, UninstallResult } from "../base.js";
1
+ import type { InitConfig, InstalledAgent, InstallOptions, InstallResult, PackOptions, PackResult, PlatformAdapter, UninstallOptions, UninstallResult } from "../base.js";
2
2
  export declare class OpenClawAdapter implements PlatformAdapter {
3
3
  name: string;
4
4
  home: string;
5
+ extractInitConfig(cwd: string): InitConfig | null;
5
6
  listInstalled(): Promise<InstalledAgent[]>;
6
7
  uninstall(options: UninstallOptions): Promise<UninstallResult>;
7
8
  pack(options: PackOptions): Promise<PackResult>;
@@ -283,6 +283,30 @@ function mergeOpenclawConfig(openclawConfig, configTemplate, agentSlug, username
283
283
  export class OpenClawAdapter {
284
284
  name = "openclaw";
285
285
  home = OPENCLAW_HOME;
286
+ extractInitConfig(cwd) {
287
+ if (!existsSync(OPENCLAW_CONFIG_PATH))
288
+ return null;
289
+ let raw;
290
+ try {
291
+ raw = JSON.parse(readFileSync(OPENCLAW_CONFIG_PATH, "utf-8"));
292
+ }
293
+ catch {
294
+ return null;
295
+ }
296
+ const agents = raw.agents;
297
+ const agentsList = agents?.list;
298
+ if (!Array.isArray(agentsList) || agentsList.length === 0)
299
+ return null;
300
+ const agentEntry = findAgentEntry(agentsList, cwd);
301
+ if (!agentEntry)
302
+ return null;
303
+ const name = String(agentEntry.id ?? "");
304
+ if (!name)
305
+ return null;
306
+ const model = agentEntry.model ??
307
+ agents?.defaults?.model?.primary;
308
+ return { name, model: model || undefined };
309
+ }
286
310
  async listInstalled() {
287
311
  const configPath = join(OPENCLAW_HOME, "openclaw.json");
288
312
  if (existsSync(configPath)) {
@@ -2,7 +2,7 @@ import Conf from "conf";
2
2
  const config = new Conf({
3
3
  projectName: "web42",
4
4
  defaults: {
5
- apiUrl: "https://agents.web42.ai",
5
+ apiUrl: "https://web42.ai",
6
6
  authenticated: false,
7
7
  },
8
8
  });
package/dist/version.d.ts CHANGED
@@ -1 +1 @@
1
- export declare const CLI_VERSION = "0.1.0";
1
+ export declare const CLI_VERSION = "0.1.2";
package/dist/version.js CHANGED
@@ -1 +1 @@
1
- export const CLI_VERSION = "0.1.0";
1
+ export const CLI_VERSION = "0.1.2";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@web42/cli",
3
- "version": "0.1.0",
3
+ "version": "0.1.2",
4
4
  "description": "CLI for the Web42 Agent Marketplace - push, install, and remix OpenClaw agent packages",
5
5
  "type": "module",
6
6
  "bin": {