@moltbankhq/openclaw 0.1.16 → 0.1.18

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
@@ -1,6 +1,6 @@
1
1
  # @moltbankhq/openclaw
2
2
 
3
- Standalone CLI for [MoltBank](https://moltbank.bot) — stablecoin treasury controls, approvals, and audit trails for agent fleets.
3
+ Standalone CLI and optional OpenClaw plugin for [MoltBank](https://moltbank.bot) — stablecoin treasury controls, approvals, and audit trails for agent fleets.
4
4
 
5
5
  ## Install
6
6
 
@@ -22,6 +22,12 @@ Or from a local install:
22
22
  npm exec --package @moltbankhq/openclaw -- moltbank setup
23
23
  ```
24
24
 
25
+ OpenClaw plugin mode still exists in this pass for compatibility:
26
+
27
+ ```bash
28
+ openclaw plugins install @moltbankhq/openclaw
29
+ ```
30
+
25
31
  ## What it does
26
32
 
27
33
  This package connects your OpenClaw agent to MoltBank's stablecoin treasury infrastructure. During setup, it:
@@ -34,7 +40,7 @@ This package connects your OpenClaw agent to MoltBank's stablecoin treasury infr
34
40
 
35
41
  Once set up, your agent can manage treasury operations, set per-agent spending limits, handle x402 payments, and interact with MoltBank's MCP server — all within OpenClaw.
36
42
 
37
- The standalone `moltbank` CLI is the supported path for install, setup, auth status, and repair flows. Actual treasury operations should run through the installed skill wrapper scripts inside the skill directory.
43
+ The standalone `moltbank` CLI is for install, setup, auth status, and repair flows. Actual treasury operations should run through the installed skill wrapper scripts inside the skill directory.
38
44
 
39
45
  ## Setup
40
46
 
@@ -65,7 +71,25 @@ CLI flags:
65
71
 
66
72
  ```bash
67
73
  moltbank setup --app-base-url https://app.moltbank.bot --skill-name MoltBank
68
- moltbank setup --workspace ~/.openclaw/workspace
74
+ ```
75
+
76
+ Plugin mode can still read optional config from your `openclaw.json`:
77
+
78
+ Optional config in your `openclaw.json`:
79
+
80
+ ```json
81
+ {
82
+ "plugins": {
83
+ "entries": {
84
+ "moltbank": {
85
+ "config": {
86
+ "appBaseUrl": "https://app.moltbank.bot",
87
+ "skillName": "MoltBank"
88
+ }
89
+ }
90
+ }
91
+ }
92
+ }
69
93
  ```
70
94
 
71
95
  ## Environment Variables
@@ -74,7 +98,6 @@ moltbank setup --workspace ~/.openclaw/workspace
74
98
  |----------|-------------|
75
99
  | `APP_BASE_URL` | MoltBank deployment URL (default: `https://app.moltbank.bot`) |
76
100
  | `MOLTBANK_SKILL_NAME` | Override skill folder name (default: `MoltBank`) |
77
- | `OPENCLAW_WORKSPACE` | Override OpenClaw workspace path (default: `~/.openclaw/workspace`) |
78
101
  | `MOLTBANK_CREDENTIALS_PATH` | Custom credentials file path |
79
102
  | `MOLTBANK_SETUP_AUTH_WAIT_MODE` | `blocking` or `nonblocking` (default: `nonblocking`) |
80
103
 
package/cli.ts CHANGED
@@ -16,7 +16,6 @@ import {
16
16
  type CliConfig = {
17
17
  appBaseUrl?: string;
18
18
  skillName?: string;
19
- workspacePath?: string;
20
19
  };
21
20
 
22
21
  type ParsedArgs = {
@@ -46,7 +45,6 @@ Commands:
46
45
  Options:
47
46
  --app-base-url <url> Override MoltBank deployment URL
48
47
  --skill-name <name> Override skill folder name
49
- --workspace <path> Override OpenClaw workspace path
50
48
  --blocking Compatibility flag; setup already waits for approval
51
49
  --restart-gateway Force gateway restart after successful host setup
52
50
  --no-restart-gateway Skip gateway restart after successful host setup
@@ -56,7 +54,6 @@ Options:
56
54
 
57
55
  Examples:
58
56
  moltbank setup
59
- moltbank setup --workspace ~/.openclaw/workspace
60
57
  moltbank setup --verbose
61
58
  moltbank status
62
59
  moltbank register --app-base-url https://app.moltbank.bot
@@ -140,21 +137,6 @@ function parseArgs(argv: string[]): ParsedArgs {
140
137
  continue;
141
138
  }
142
139
 
143
- if (arg === '--workspace') {
144
- const value = argv[index + 1];
145
- if (!value) {
146
- throw new Error('missing value for --workspace');
147
- }
148
- config.workspacePath = value;
149
- index += 1;
150
- continue;
151
- }
152
-
153
- if (arg.startsWith('--workspace=')) {
154
- config.workspacePath = arg.slice('--workspace='.length);
155
- continue;
156
- }
157
-
158
140
  if (arg.startsWith('-')) {
159
141
  throw new Error(`unknown option: ${arg}`);
160
142
  }
package/index.ts CHANGED
@@ -1,16 +1,15 @@
1
1
  import { spawn, spawnSync } from 'child_process';
2
2
  import { chmodSync, chownSync, existsSync, mkdirSync, readdirSync, readFileSync, unlinkSync, writeFileSync, type Dirent } from 'fs';
3
- import { join, dirname, basename, resolve } from 'path';
3
+ import { join, dirname, basename } from 'path';
4
4
  import { homedir, userInfo } from 'os';
5
5
  const IS_WIN = process.platform === 'win32';
6
6
 
7
7
  type OpenclawConfig = Record<string, unknown>;
8
8
  type ParsedJsonObject = Record<string, unknown>;
9
9
 
10
- export interface MoltbankConfig {
10
+ export interface MoltbankPluginConfig {
11
11
  skillName?: string;
12
12
  appBaseUrl?: string;
13
- workspacePath?: string;
14
13
  }
15
14
 
16
15
  interface CredentialsOrganization {
@@ -54,6 +53,36 @@ export interface SetupCommandLoggerOptions {
54
53
  statusCommand?: string;
55
54
  }
56
55
 
56
+ interface ServiceDefinition {
57
+ id: string;
58
+ start: () => void | Promise<void>;
59
+ stop: () => void | Promise<void>;
60
+ }
61
+
62
+ interface CliCommandLike {
63
+ command(name: string): CliCommandLike;
64
+ createCommand(name: string): CliCommandLike;
65
+ description(text: string): CliCommandLike;
66
+ addCommand(command: CliCommandLike): CliCommandLike;
67
+ action(handler: () => void | Promise<void>): CliCommandLike;
68
+ }
69
+
70
+ interface PluginApiConfig {
71
+ plugins?: {
72
+ entries?: {
73
+ moltbank?: {
74
+ config?: MoltbankPluginConfig;
75
+ };
76
+ };
77
+ };
78
+ }
79
+
80
+ interface PluginApi extends LoggerApi {
81
+ config?: PluginApiConfig;
82
+ registerService(service: ServiceDefinition): void;
83
+ registerCli(handler: (args: { program: CliCommandLike }) => void, options: { commands: string[] }): void;
84
+ }
85
+
57
86
  export type AuthWaitMode = 'blocking' | 'nonblocking';
58
87
  const oauthPollers = new Map<string, ReturnType<typeof spawn>>();
59
88
  const backgroundFinalizers = new Map<string, ReturnType<typeof spawn>>();
@@ -392,13 +421,9 @@ function resolveWindowsCommandPath(command: string, env: NodeJS.ProcessEnv): str
392
421
  const extensions = getWindowsCommandExtensions(env);
393
422
 
394
423
  const tryCandidates = (basePath: string): string => {
395
- const lower = basePath.toLowerCase();
396
- const hasKnownExtension = extensions.some((ext) => lower.endsWith(ext));
397
-
398
- if (hasKnownExtension && existsSync(basePath)) {
399
- return basePath;
400
- }
424
+ if (existsSync(basePath)) return basePath;
401
425
 
426
+ const lower = basePath.toLowerCase();
402
427
  for (const ext of extensions) {
403
428
  if (lower.endsWith(ext)) continue;
404
429
  const candidate = `${basePath}${ext}`;
@@ -407,10 +432,6 @@ function resolveWindowsCommandPath(command: string, env: NodeJS.ProcessEnv): str
407
432
  }
408
433
  }
409
434
 
410
- if (existsSync(basePath)) {
411
- return basePath;
412
- }
413
-
414
435
  return '';
415
436
  };
416
437
 
@@ -895,41 +916,19 @@ function lastNonEmptyLine(text: string): string {
895
916
  return lines.length ? lines[lines.length - 1] : '';
896
917
  }
897
918
 
898
- function normalizeWorkspacePath(rawPath: string): string {
899
- const trimmed = rawPath.trim();
900
- if (!trimmed) {
901
- return join(homedir(), '.openclaw', 'workspace');
902
- }
903
-
904
- if (trimmed === '~') {
905
- return homedir();
906
- }
907
-
908
- if (trimmed.startsWith('~/') || trimmed.startsWith('~\\')) {
909
- return resolve(join(homedir(), trimmed.slice(2)));
910
- }
911
-
912
- return resolve(trimmed);
913
- }
914
-
915
- export function getWorkspace(cfg?: MoltbankConfig): string {
916
- return normalizeWorkspacePath(cfg?.workspacePath || process.env.OPENCLAW_WORKSPACE || join(homedir(), '.openclaw', 'workspace'));
919
+ function getWorkspace(): string {
920
+ return process.env.OPENCLAW_WORKSPACE || join(homedir(), '.openclaw', 'workspace');
917
921
  }
918
922
 
919
- function getWorkspaceFromSkillDir(skillDir: string): string {
920
- const skillsDir = dirname(skillDir);
921
- return basename(skillsDir) === 'skills' ? dirname(skillsDir) : getWorkspace();
922
- }
923
-
924
- export function getSkillName(cfg: MoltbankConfig): string {
923
+ export function getSkillName(cfg: MoltbankPluginConfig): string {
925
924
  return cfg?.skillName || process.env.MOLTBANK_SKILL_NAME || 'MoltBank';
926
925
  }
927
926
 
928
- export function getAppBaseUrl(cfg: MoltbankConfig): string {
927
+ export function getAppBaseUrl(cfg: MoltbankPluginConfig): string {
929
928
  return (cfg?.appBaseUrl || process.env.APP_BASE_URL || 'https://app.moltbank.bot').trim();
930
929
  }
931
930
 
932
- export function getSkillBundleBaseUrl(cfg: MoltbankConfig): string {
931
+ export function getSkillBundleBaseUrl(cfg: MoltbankPluginConfig): string {
933
932
  const base = getAppBaseUrl(cfg).replace(/\/$/, '');
934
933
  return base.endsWith('/skill') ? base : `${base}/skill`;
935
934
  }
@@ -945,9 +944,9 @@ function isSandboxEnabled(): boolean {
945
944
  }
946
945
  }
947
946
 
948
- export function getSkillDir(cfg: MoltbankConfig): string {
947
+ export function getSkillDir(cfg: MoltbankPluginConfig): string {
949
948
  const skillName = getSkillName(cfg);
950
- return join(getWorkspace(cfg), 'skills', skillName);
949
+ return join(getWorkspace(), 'skills', skillName);
951
950
  }
952
951
 
953
952
  function getCredentialsPath(): string {
@@ -1066,6 +1065,47 @@ function setNestedValue(obj: Record<string, unknown>, path: string[], value: unk
1066
1065
  current[path[path.length - 1]] = value;
1067
1066
  }
1068
1067
 
1068
+ function cleanupStaleMoltbankPluginLoadPaths(api: LoggerApi): boolean {
1069
+ try {
1070
+ const config = readOpenclawConfig();
1071
+ const loadPathsPath = ['plugins', 'load', 'paths'];
1072
+ const current = getNestedValue(config, loadPathsPath);
1073
+ if (!Array.isArray(current)) return false;
1074
+
1075
+ const removed: string[] = [];
1076
+ const next: unknown[] = [];
1077
+
1078
+ for (const entry of current) {
1079
+ if (typeof entry !== 'string') {
1080
+ next.push(entry);
1081
+ continue;
1082
+ }
1083
+
1084
+ const normalized = entry.replace(/\\/g, '/').toLowerCase();
1085
+ const looksLikeMoltbankPath = normalized.includes('moltbank');
1086
+ if (looksLikeMoltbankPath && !existsSync(entry)) {
1087
+ removed.push(entry);
1088
+ continue;
1089
+ }
1090
+
1091
+ next.push(entry);
1092
+ }
1093
+
1094
+ if (removed.length === 0) {
1095
+ api.logger.info('[moltbank] ✓ no stale MoltBank plugin load paths found');
1096
+ return false;
1097
+ }
1098
+
1099
+ setNestedValue(config, loadPathsPath, next);
1100
+ writeOpenclawConfig(config);
1101
+ api.logger.info(`[moltbank] ✓ removed stale MoltBank plugin load path(s): ${removed.join(', ')}`);
1102
+ return true;
1103
+ } catch (e) {
1104
+ api.logger.warn('[moltbank] could not clean stale MoltBank plugin load paths: ' + String(e));
1105
+ return false;
1106
+ }
1107
+ }
1108
+
1069
1109
  // ─── mcporter ────────────────────────────────────────────────────────────────
1070
1110
 
1071
1111
  function ensureMcporter(api: LoggerApi) {
@@ -1652,12 +1692,11 @@ function startBackgroundFinalizeAfterAuth(skillDir: string, appBaseUrl: string,
1652
1692
  }
1653
1693
  if (existing) backgroundFinalizers.delete(skillDir);
1654
1694
 
1655
- const child = spawn('moltbank', ['setup-blocking'], {
1695
+ const child = spawn('openclaw', ['moltbank', 'setup-blocking'], {
1656
1696
  cwd: skillDir,
1657
1697
  env: {
1658
1698
  ...process.env,
1659
1699
  APP_BASE_URL: appBaseUrl,
1660
- OPENCLAW_WORKSPACE: getWorkspaceFromSkillDir(skillDir),
1661
1700
  MOLTBANK_SETUP_AUTH_WAIT_MODE: 'blocking'
1662
1701
  },
1663
1702
  stdio: 'ignore', // Ignore logs so it doesn't hang the parent
@@ -1810,7 +1849,7 @@ function ensureMoltbankAuth(skillDir: string, appBaseUrl: string, api: LoggerApi
1810
1849
  const backgroundTimeoutSeconds = Math.max(30, expiresAt - now - 5);
1811
1850
  startBackgroundOauthPoll(skillDir, appBaseUrl, credsPath, deviceCode, backgroundTimeoutSeconds, api);
1812
1851
  api.logger.info('[moltbank] once approved in browser, setup finalization will continue automatically');
1813
- api.logger.info('[moltbank] optional immediate check: `moltbank status`');
1852
+ api.logger.info('[moltbank] optional immediate check: `openclaw moltbank auth-status`');
1814
1853
  return false;
1815
1854
  }
1816
1855
 
@@ -2210,7 +2249,7 @@ function restartGatewayAfterHostSetup(api: LoggerApi): boolean {
2210
2249
  // ─── main setup ───────────────────────────────────────────────────────────────
2211
2250
 
2212
2251
  export async function runSetup(
2213
- cfg: MoltbankConfig,
2252
+ cfg: MoltbankPluginConfig,
2214
2253
  api: LoggerApi,
2215
2254
  options: { authWaitMode?: AuthWaitMode; restartGatewayOnSuccess?: boolean } = {}
2216
2255
  ) {
@@ -2229,6 +2268,9 @@ export async function runSetup(
2229
2268
  api.logger.info(`[moltbank] skill dir: ${skillDir}`);
2230
2269
  api.logger.info(`[moltbank] base url: ${appBaseUrl}`);
2231
2270
  api.logger.info(`[moltbank] ══════════════════════════════════════`);
2271
+ api.logger.info('[moltbank] preflight: cleaning stale MoltBank plugin load paths...');
2272
+ cleanupStaleMoltbankPluginLoadPaths(api);
2273
+
2232
2274
  if (sandbox) {
2233
2275
  api.logger.info('[moltbank] configuring sandbox mode...');
2234
2276
 
@@ -2256,10 +2298,10 @@ export async function runSetup(
2256
2298
  if (pending) {
2257
2299
  api.logger.warn('[moltbank] sandbox auth pending — startup continues without blocking channel startup');
2258
2300
  api.logger.info('[moltbank] setup will finalize automatically after browser approval');
2259
- api.logger.info('[moltbank] optional immediate check: `moltbank status`');
2301
+ api.logger.info('[moltbank] optional immediate check: `openclaw moltbank auth-status`');
2260
2302
  } else {
2261
2303
  api.logger.warn('[moltbank] sandbox auth setup failed before issuing a valid device code');
2262
- api.logger.warn('[moltbank] review the previous error and rerun `moltbank setup`');
2304
+ api.logger.warn('[moltbank] review the previous error and rerun `openclaw moltbank setup`');
2263
2305
  }
2264
2306
  return;
2265
2307
  }
@@ -2315,10 +2357,10 @@ export async function runSetup(
2315
2357
  if (pending) {
2316
2358
  api.logger.warn('[moltbank] host auth pending — startup continues without blocking channel startup');
2317
2359
  api.logger.info('[moltbank] setup will finalize automatically after browser approval');
2318
- api.logger.info('[moltbank] optional immediate check: `moltbank status`');
2360
+ api.logger.info('[moltbank] optional immediate check: `openclaw moltbank auth-status`');
2319
2361
  } else {
2320
2362
  api.logger.warn('[moltbank] host auth setup failed before issuing a valid device code');
2321
- api.logger.warn('[moltbank] review the previous error and rerun `moltbank setup`');
2363
+ api.logger.warn('[moltbank] review the previous error and rerun `openclaw moltbank setup`');
2322
2364
  }
2323
2365
  return;
2324
2366
  }
@@ -2335,11 +2377,7 @@ export async function runSetup(
2335
2377
  api.logger.info('[moltbank] [host 8/8] running readiness balance check...');
2336
2378
  hostReady = runHostReadinessCheck(skillDir, api);
2337
2379
 
2338
- if (hostReady) {
2339
- api.logger.info('[moltbank] host mode — setup completed with onboarding flow');
2340
- } else {
2341
- api.logger.warn('[moltbank] host mode setup finished, but operational readiness verification failed');
2342
- }
2380
+ api.logger.info('[moltbank] host mode — setup completed with onboarding flow');
2343
2381
 
2344
2382
  if (hostReady && restartGatewayOnSuccess) {
2345
2383
  restartGatewayAfterHostSetup(api);
@@ -2347,19 +2385,13 @@ export async function runSetup(
2347
2385
  }
2348
2386
 
2349
2387
  api.logger.info(`[moltbank] ══════════════════════════════════════`);
2350
- if (sandbox || hostReady) {
2351
- api.logger.info(`[moltbank] ✓ setup complete`);
2352
- } else {
2353
- api.logger.warn('[moltbank] ✗ setup incomplete');
2354
- }
2388
+ api.logger.info(`[moltbank] setup complete`);
2355
2389
  if (sandbox) {
2356
2390
  api.logger.info('[moltbank] ⏳ sandbox will be recreated in ~8s — send a message to the agent after that');
2357
2391
  } else if (hostReady) {
2358
2392
  api.logger.info('[moltbank] ✓ host ready');
2359
- } else {
2360
- api.logger.warn('[moltbank] ✗ host not ready');
2361
2393
  }
2362
- api.logger.info(`[moltbank] skill: ${skillDir}/skill/SKILL.md`);
2394
+ api.logger.info(`[moltbank] skill: ${skillDir}/SKILL.md`);
2363
2395
  api.logger.info(`[moltbank] mcporter: ${skillDir}/assets/mcporter.json`);
2364
2396
  if (sandbox) {
2365
2397
  const finalConfig = readOpenclawConfig();
@@ -2401,9 +2433,118 @@ export async function runSetup(
2401
2433
  }
2402
2434
  }
2403
2435
  api.logger.info(`[moltbank] ══════════════════════════════════════`);
2404
-
2405
- if (!sandbox && !hostReady) {
2406
- throw new Error('host setup incomplete: authenticated readiness verification failed');
2407
- }
2408
2436
  }
2409
2437
 
2438
+ // ─── plugin register ──────────────────────────────────────────────────────────
2439
+
2440
+ export default function register(api: PluginApi) {
2441
+ const cfg: MoltbankPluginConfig = api.config?.plugins?.entries?.moltbank?.config ?? {};
2442
+
2443
+ api.registerService({
2444
+ id: 'moltbank-setup',
2445
+ start: async () => {
2446
+ await runSetup(cfg, api, { authWaitMode: 'nonblocking' });
2447
+ },
2448
+ stop: async () => {
2449
+ stopBackgroundOauthPoll(getSkillDir(cfg));
2450
+ stopBackgroundFinalize(getSkillDir(cfg));
2451
+ api.logger.info('[moltbank] plugin stopped');
2452
+ }
2453
+ });
2454
+
2455
+ api.registerCli(
2456
+ ({ program }: { program: CliCommandLike }) => {
2457
+ program
2458
+ .command('moltbank')
2459
+ .description('MoltBank plugin commands')
2460
+ .addCommand(
2461
+ program
2462
+ .createCommand('setup')
2463
+ .description('Re-run MoltBank setup')
2464
+ .action(async () => {
2465
+ const verbose = process.argv.includes('--verbose');
2466
+ const restartGatewayOnSuccess = getSetupGatewayRestartEnabled(IS_WIN);
2467
+ const logger = createSetupCommandLogger({ verbose, statusCommand: 'openclaw moltbank status' });
2468
+ try {
2469
+ await runSetup(cfg, logger, { authWaitMode: 'blocking', restartGatewayOnSuccess });
2470
+ } finally {
2471
+ logger.finish();
2472
+ }
2473
+ })
2474
+ )
2475
+ .addCommand(
2476
+ program
2477
+ .createCommand('setup-blocking')
2478
+ .description('Re-run full MoltBank setup and wait for OAuth approval')
2479
+ .action(async () => {
2480
+ const verbose = process.argv.includes('--verbose');
2481
+ const restartGatewayOnSuccess = getSetupGatewayRestartEnabled(IS_WIN);
2482
+ const logger = createSetupCommandLogger({ verbose, statusCommand: 'openclaw moltbank status' });
2483
+ try {
2484
+ await runSetup(cfg, logger, { authWaitMode: 'blocking', restartGatewayOnSuccess });
2485
+ } finally {
2486
+ logger.finish();
2487
+ }
2488
+ })
2489
+ )
2490
+ .addCommand(
2491
+ program
2492
+ .createCommand('sandbox-setup')
2493
+ .description('Reconfigure sandbox docker in openclaw.json')
2494
+ .action(() => {
2495
+ const changed = configureSandbox({ logger: console });
2496
+ if (changed) {
2497
+ recreateSandboxAndRestart({ logger: console });
2498
+ } else {
2499
+ console.log('[moltbank] No sandbox docker changes — not scheduling teardown');
2500
+ }
2501
+ })
2502
+ )
2503
+ .addCommand(
2504
+ program
2505
+ .createCommand('inject-key')
2506
+ .description('Re-inject sandbox env vars from credentials.json')
2507
+ .action(() => {
2508
+ const skillDir = getSkillDir(cfg);
2509
+ const changed = injectSandboxEnv(skillDir, { logger: console });
2510
+ if (changed) {
2511
+ recreateSandboxAndRestart({ logger: console });
2512
+ } else {
2513
+ console.log('[moltbank] No env changes — not scheduling teardown');
2514
+ }
2515
+ })
2516
+ )
2517
+ .addCommand(
2518
+ program
2519
+ .createCommand('status')
2520
+ .description('Show current MoltBank auth state')
2521
+ .action(() => {
2522
+ const appBaseUrl = getAppBaseUrl(cfg);
2523
+ const skillDir = getSkillDir(cfg);
2524
+ printAuthStatus(skillDir, appBaseUrl, { logger: console });
2525
+ })
2526
+ )
2527
+ .addCommand(
2528
+ program
2529
+ .createCommand('auth-status')
2530
+ .description('Show current MoltBank auth state (credentials, pending code, background poll)')
2531
+ .action(() => {
2532
+ const appBaseUrl = getAppBaseUrl(cfg);
2533
+ const skillDir = getSkillDir(cfg);
2534
+ printAuthStatus(skillDir, appBaseUrl, { logger: console });
2535
+ })
2536
+ )
2537
+ .addCommand(
2538
+ program
2539
+ .createCommand('register')
2540
+ .description('Re-register mcporter server')
2541
+ .action(() => {
2542
+ const appBaseUrl = getAppBaseUrl(cfg);
2543
+ const skillDir = getSkillDir(cfg);
2544
+ ensureMcporterConfig(skillDir, appBaseUrl, { logger: console });
2545
+ })
2546
+ );
2547
+ },
2548
+ { commands: ['moltbank'] }
2549
+ );
2550
+ }
@@ -0,0 +1,29 @@
1
+ {
2
+ "id": "moltbank",
3
+ "name": "MoltBank",
4
+ "description": "MoltBank stablecoin treasury plugin for OpenClaw — installs mcporter, npm dependencies, sandbox setup, and the MoltBank skill",
5
+ "configSchema": {
6
+ "type": "object",
7
+ "additionalProperties": false,
8
+ "properties": {
9
+ "appBaseUrl": {
10
+ "type": "string",
11
+ "description": "MoltBank deployment URL"
12
+ },
13
+ "skillName": {
14
+ "type": "string",
15
+ "description": "Override skill folder name (default: MoltBank)"
16
+ }
17
+ }
18
+ },
19
+ "uiHints": {
20
+ "appBaseUrl": {
21
+ "label": "App Base URL",
22
+ "placeholder": "https://app.moltbank.bot"
23
+ },
24
+ "skillName": {
25
+ "label": "Skill Name",
26
+ "placeholder": "MoltBank"
27
+ }
28
+ }
29
+ }
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@moltbankhq/openclaw",
3
- "version": "0.1.16",
4
- "description": "MoltBank stablecoin treasury CLI and OpenClaw skill installer",
3
+ "version": "0.1.18",
4
+ "description": "MoltBank stablecoin treasury CLI and OpenClaw plugin",
5
5
  "homepage": "https://github.com/moltbankhq/openclaw-plugin#readme",
6
6
  "repository": {
7
7
  "type": "git",
@@ -24,8 +24,14 @@
24
24
  "README.md",
25
25
  "bin/",
26
26
  "cli.ts",
27
- "index.ts"
27
+ "index.ts",
28
+ "openclaw.plugin.json"
28
29
  ],
30
+ "openclaw": {
31
+ "extensions": [
32
+ "./index.ts"
33
+ ]
34
+ },
29
35
  "keywords": [
30
36
  "moltbank",
31
37
  "openclaw",