clawpowers 1.1.3 → 2.0.0

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.
Files changed (74) hide show
  1. package/CHANGELOG.md +94 -0
  2. package/LICENSE +44 -0
  3. package/README.md +202 -384
  4. package/SECURITY.md +72 -0
  5. package/dist/index.d.ts +844 -0
  6. package/dist/index.js +2536 -0
  7. package/dist/index.js.map +1 -0
  8. package/package.json +52 -42
  9. package/.claude-plugin/manifest.json +0 -19
  10. package/.codex/INSTALL.md +0 -36
  11. package/.cursor-plugin/manifest.json +0 -21
  12. package/.opencode/INSTALL.md +0 -52
  13. package/ARCHITECTURE.md +0 -69
  14. package/bin/clawpowers.js +0 -625
  15. package/bin/clawpowers.sh +0 -91
  16. package/docs/demo/clawpowers-demo.cast +0 -197
  17. package/docs/demo/clawpowers-demo.gif +0 -0
  18. package/docs/launch-images/25-skills-breakdown.jpg +0 -0
  19. package/docs/launch-images/clawpowers-vs-superpowers.jpg +0 -0
  20. package/docs/launch-images/economic-code-optimization.jpg +0 -0
  21. package/docs/launch-images/native-vs-bridge-2.jpg +0 -0
  22. package/docs/launch-images/native-vs-bridge.jpg +0 -0
  23. package/docs/launch-images/post1-hero-lobster.jpg +0 -0
  24. package/docs/launch-images/post2-dashboard.jpg +0 -0
  25. package/docs/launch-images/post3-superpowers.jpg +0 -0
  26. package/docs/launch-images/post4-before-after.jpg +0 -0
  27. package/docs/launch-images/post5-install-now.jpg +0 -0
  28. package/docs/launch-images/ultimate-stack.jpg +0 -0
  29. package/docs/launch-posts.md +0 -76
  30. package/docs/quickstart-first-transaction.md +0 -204
  31. package/gemini-extension.json +0 -32
  32. package/hooks/session-start +0 -205
  33. package/hooks/session-start.cmd +0 -43
  34. package/hooks/session-start.js +0 -163
  35. package/runtime/demo/README.md +0 -78
  36. package/runtime/demo/x402-mock-server.js +0 -230
  37. package/runtime/feedback/analyze.js +0 -621
  38. package/runtime/feedback/analyze.sh +0 -546
  39. package/runtime/init.js +0 -210
  40. package/runtime/init.sh +0 -178
  41. package/runtime/metrics/collector.js +0 -361
  42. package/runtime/metrics/collector.sh +0 -308
  43. package/runtime/payments/ledger.js +0 -305
  44. package/runtime/payments/ledger.sh +0 -262
  45. package/runtime/payments/pipeline.js +0 -459
  46. package/runtime/persistence/store.js +0 -433
  47. package/runtime/persistence/store.sh +0 -303
  48. package/skill.json +0 -106
  49. package/skills/agent-bounties/SKILL.md +0 -553
  50. package/skills/agent-payments/SKILL.md +0 -479
  51. package/skills/brainstorming/SKILL.md +0 -233
  52. package/skills/content-pipeline/SKILL.md +0 -282
  53. package/skills/cross-project-knowledge/SKILL.md +0 -345
  54. package/skills/dispatching-parallel-agents/SKILL.md +0 -305
  55. package/skills/economic-code-optimization/SKILL.md +0 -265
  56. package/skills/executing-plans/SKILL.md +0 -255
  57. package/skills/finishing-a-development-branch/SKILL.md +0 -260
  58. package/skills/formal-verification-lite/SKILL.md +0 -441
  59. package/skills/learn-how-to-learn/SKILL.md +0 -235
  60. package/skills/market-intelligence/SKILL.md +0 -323
  61. package/skills/meta-skill-evolution/SKILL.md +0 -325
  62. package/skills/prospecting/SKILL.md +0 -454
  63. package/skills/receiving-code-review/SKILL.md +0 -225
  64. package/skills/requesting-code-review/SKILL.md +0 -206
  65. package/skills/security-audit/SKILL.md +0 -353
  66. package/skills/self-healing-code/SKILL.md +0 -369
  67. package/skills/subagent-driven-development/SKILL.md +0 -244
  68. package/skills/systematic-debugging/SKILL.md +0 -355
  69. package/skills/test-driven-development/SKILL.md +0 -416
  70. package/skills/using-clawpowers/SKILL.md +0 -160
  71. package/skills/using-git-worktrees/SKILL.md +0 -261
  72. package/skills/verification-before-completion/SKILL.md +0 -254
  73. package/skills/writing-plans/SKILL.md +0 -276
  74. package/skills/writing-skills/SKILL.md +0 -260
package/bin/clawpowers.js DELETED
@@ -1,625 +0,0 @@
1
- #!/usr/bin/env node
2
- // bin/clawpowers.js — Cross-platform CLI entry point
3
- //
4
- // Commands: init, status, update, inject, metrics, analyze, store
5
- // Works on Windows CMD, PowerShell, macOS, Linux.
6
- // Zero npm dependencies — only Node.js built-ins.
7
- 'use strict';
8
-
9
- const fs = require('fs');
10
- const path = require('path');
11
- const os = require('os');
12
- const { execSync, spawnSync } = require('child_process');
13
-
14
- // __dirname is the bin/ directory; repo root is one level up
15
- const SCRIPT_DIR = __dirname;
16
- const REPO_ROOT = path.resolve(SCRIPT_DIR, '..');
17
-
18
- // Runtime data directory — override with CLAWPOWERS_DIR env var for testing
19
- const CLAWPOWERS_DIR = process.env.CLAWPOWERS_DIR || path.join(os.homedir(), '.clawpowers');
20
-
21
- // Absolute paths to each runtime module — resolved once at startup so
22
- // error messages can include the full path if a module is missing
23
- const INIT_JS = path.join(REPO_ROOT, 'runtime', 'init.js');
24
- const ANALYZE_JS = path.join(REPO_ROOT, 'runtime', 'feedback', 'analyze.js');
25
- const STORE_JS = path.join(REPO_ROOT, 'runtime', 'persistence', 'store.js');
26
- const COLLECTOR_JS = path.join(REPO_ROOT, 'runtime', 'metrics', 'collector.js');
27
- const SESSION_JS = path.join(REPO_ROOT, 'hooks', 'session-start.js');
28
- const LEDGER_JS = path.join(REPO_ROOT, 'runtime', 'payments', 'ledger.js');
29
-
30
- /**
31
- * Prints the top-level command usage to stdout.
32
- * Called when no command is given or when 'help'/'-h'/'--help' is passed.
33
- */
34
- function printUsage() {
35
- console.log(`Usage: clawpowers <command> [args]
36
-
37
- Commands:
38
- init Initialize ClawPowers runtime in ~/.clawpowers/
39
- status Show runtime health and skill metrics summary
40
- update Pull latest skill definitions from repo
41
- inject Inject using-clawpowers skill into current session context
42
- metrics <cmd> Record or query skill execution metrics
43
- analyze [opts] RSI feedback analysis of skill performance
44
- store <cmd> Key-value state store operations
45
- payments <cmd> Payment setup, log, and summary commands
46
- demo <cmd> Run interactive demos (e.g. x402 mock merchant)
47
-
48
- Examples:
49
- npx clawpowers init
50
- npx clawpowers status
51
- npx clawpowers metrics record --skill my-skill --outcome success
52
- npx clawpowers metrics summary
53
- npx clawpowers analyze --skill systematic-debugging
54
- npx clawpowers store set "my:key" "my value"
55
- npx clawpowers store get "my:key"
56
- npx clawpowers payments setup
57
- npx clawpowers payments log
58
- npx clawpowers payments summary
59
- npx clawpowers demo x402
60
-
61
- Run 'npx clawpowers <command> help' for command-specific help.`);
62
- }
63
-
64
- /**
65
- * Safely require() a runtime module, exiting with a helpful error if the
66
- * file doesn't exist (i.e., user hasn't run `init` yet).
67
- *
68
- * @param {string} filepath - Absolute path to the module to load.
69
- * @returns {object} The module's exports.
70
- */
71
- function requireModule(filepath) {
72
- if (!fs.existsSync(filepath)) {
73
- process.stderr.write(`Error: runtime module not found: ${filepath}\n`);
74
- process.stderr.write('Try running: npx clawpowers init\n');
75
- process.exit(1);
76
- }
77
- return require(filepath);
78
- }
79
-
80
- /**
81
- * `clawpowers init` — Set up ~/.clawpowers/ directory structure.
82
- * Delegates to runtime/init.js which is idempotent (safe to run repeatedly).
83
- */
84
- function cmdInit() {
85
- console.log('Initializing ClawPowers runtime...');
86
- const init = requireModule(INIT_JS);
87
- init.main();
88
- }
89
-
90
- /**
91
- * `clawpowers status` — Show runtime health and full RSI analysis.
92
- * Requires the runtime to be initialized; exits with an error if not.
93
- */
94
- function cmdStatus() {
95
- if (!fs.existsSync(CLAWPOWERS_DIR)) {
96
- process.stderr.write('Runtime not initialized. Run: npx clawpowers init\n');
97
- process.exit(1);
98
- }
99
- const analyze = requireModule(ANALYZE_JS);
100
- analyze.cmdFullAnalysis();
101
- }
102
-
103
- /**
104
- * `clawpowers update` — Pull the latest skill definitions from the GitHub repo.
105
- * Uses git fast-forward only to avoid overwriting local modifications.
106
- * Falls back gracefully if git is not installed.
107
- */
108
- function cmdUpdate() {
109
- const repoUrl = 'https://github.com/up2itnow0822/clawpowers';
110
-
111
- // Check if we're in a git repo (git clone install) or npm install
112
- const gitDir = path.join(REPO_ROOT, '.git');
113
- const isGitInstall = fs.existsSync(gitDir);
114
-
115
- if (isGitInstall) {
116
- // Git install: pull latest
117
- const result = spawnSync('git', ['-C', REPO_ROOT, 'pull', '--ff-only', 'origin', 'main'], {
118
- stdio: 'inherit',
119
- shell: os.platform() === 'win32',
120
- });
121
-
122
- if (result.error) {
123
- console.log(`git not found or failed. Visit ${repoUrl} to update manually.`);
124
- } else if (result.status !== 0) {
125
- console.log(`Warning: could not auto-update. Visit ${repoUrl} for latest.`);
126
- } else {
127
- console.log('Updated to latest version.');
128
- }
129
- } else {
130
- // npm/npx install: instruct user to reinstall via npm
131
- console.log('ClawPowers was installed via npm. To update:');
132
- console.log('');
133
- console.log(' npx clawpowers@latest init');
134
- console.log('');
135
- console.log('This will update the CLI and re-initialize the runtime');
136
- console.log('(your existing state, metrics, and config are preserved).');
137
- console.log('');
138
- console.log(`Or visit: ${repoUrl}`);
139
- }
140
- }
141
-
142
- /**
143
- * `clawpowers inject` — Run the session-start hook to inject the
144
- * using-clawpowers skill into the current AI platform session.
145
- * Spawns hooks/session-start.js as a child process so it inherits stdio.
146
- */
147
- function cmdInject() {
148
- const result = spawnSync(process.execPath, [SESSION_JS], {
149
- stdio: 'inherit',
150
- });
151
- if (result.error) {
152
- process.stderr.write(`Error running session-start.js: ${result.error.message}\n`);
153
- process.exit(1);
154
- }
155
- process.exit(result.status || 0);
156
- }
157
-
158
- /**
159
- * `clawpowers metrics <subcmd> [args]` — Delegate to collector.js.
160
- * Supported subcommands: record, show, summary.
161
- *
162
- * @param {string[]} args - Remaining argv after 'metrics'.
163
- */
164
- function cmdMetrics(args) {
165
- const collector = requireModule(COLLECTOR_JS);
166
- const [subcmd, ...rest] = args;
167
-
168
- // No subcommand or explicit help request: print metrics-specific usage
169
- if (!subcmd || subcmd === 'help' || subcmd === '--help' || subcmd === '-h') {
170
- printCollectorUsage();
171
- return;
172
- }
173
-
174
- const mod = requireModule(COLLECTOR_JS);
175
-
176
- switch (subcmd) {
177
- case 'record':
178
- // cmdRecord expects the remaining args array (e.g. ['--skill', 'foo', '--outcome', 'success'])
179
- mod.cmdRecord ? mod.cmdRecord(rest) : delegateToNode(COLLECTOR_JS, ['record', ...rest]);
180
- break;
181
- case 'show':
182
- mod.cmdShow ? mod.cmdShow(rest) : delegateToNode(COLLECTOR_JS, ['show', ...rest]);
183
- break;
184
- case 'summary':
185
- mod.cmdSummary ? mod.cmdSummary(rest) : delegateToNode(COLLECTOR_JS, ['summary', ...rest]);
186
- break;
187
- default:
188
- process.stderr.write(`Unknown metrics subcommand: ${subcmd}\n`);
189
- printCollectorUsage();
190
- process.exit(1);
191
- }
192
- }
193
-
194
- /**
195
- * Prints usage information for the `metrics` sub-command group.
196
- */
197
- function printCollectorUsage() {
198
- console.log(`Usage: clawpowers metrics <command> [options]
199
-
200
- Commands:
201
- record Record a skill execution outcome
202
- show Show recent execution records
203
- summary Show aggregated statistics
204
-
205
- record options:
206
- --skill <name> Skill name (required)
207
- --outcome <result> success | failure | partial | skipped (required)
208
- --duration <seconds> Execution time in seconds
209
- --notes <text> Notes about this execution
210
- --session-id <id> Session identifier`);
211
- }
212
-
213
- /**
214
- * `clawpowers analyze [flag] [value]` — RSI feedback analysis.
215
- * Dispatches to the appropriate analyze.js function based on the flag.
216
- *
217
- * @param {string[]} args - Remaining argv after 'analyze'.
218
- */
219
- function cmdAnalyze(args) {
220
- const analyze = requireModule(ANALYZE_JS);
221
- const [flag, value] = args;
222
-
223
- switch (flag) {
224
- case '--skill': analyze.cmdSkillAnalysis(value); break;
225
- case '--plan': analyze.cmdPlanAnalysis(value); break;
226
- case '--worktrees': analyze.cmdWorktreeReport(); break;
227
- case '--recommendations': analyze.cmdRecommendations(); break;
228
- // --format accepts a format name but human-readable is the only current output
229
- case '--format': analyze.cmdFullAnalysis(); break;
230
- case 'help':
231
- case '-h':
232
- case '--help': printAnalyzeUsage(); break;
233
- // No flag = full analysis of all skills
234
- case undefined:
235
- case '': analyze.cmdFullAnalysis(); break;
236
- default:
237
- process.stderr.write(`Unknown analyze option: ${flag}\n`);
238
- printAnalyzeUsage();
239
- process.exit(1);
240
- }
241
- }
242
-
243
- /**
244
- * Prints usage information for the `analyze` sub-command.
245
- */
246
- function printAnalyzeUsage() {
247
- console.log(`Usage: clawpowers analyze [options]
248
-
249
- Options:
250
- (no args) Full analysis of all skills
251
- --skill <name> Analysis for one specific skill
252
- --plan <name> Plan execution analysis
253
- --worktrees Worktree lifecycle report
254
- --recommendations Show improvement recommendations only
255
- --format json JSON output (default: human-readable)`);
256
- }
257
-
258
- /**
259
- * `clawpowers store <subcmd> [args]` — Key-value state store operations.
260
- * Maps CLI subcommands to store.js exported functions.
261
- *
262
- * @param {string[]} args - Remaining argv after 'store'.
263
- */
264
- function cmdStore(args) {
265
- const store = requireModule(STORE_JS);
266
- const [subcmd, ...rest] = args;
267
-
268
- if (!subcmd || subcmd === 'help' || subcmd === '--help' || subcmd === '-h') {
269
- printStoreUsage();
270
- return;
271
- }
272
-
273
- try {
274
- switch (subcmd) {
275
- case 'set':
276
- // rest[1] may be undefined for empty-string value; default to ''
277
- store.cmdSet(rest[0], rest[1] !== undefined ? rest[1] : '');
278
- break;
279
-
280
- case 'get': {
281
- // Pass default value only when it was explicitly supplied (args.length >= 2)
282
- let val;
283
- try {
284
- val = rest.length >= 2 ? store.cmdGet(rest[0], rest[1]) : store.cmdGet(rest[0]);
285
- console.log(val);
286
- } catch (err) {
287
- process.stderr.write(`Error: ${err.message}\n`);
288
- process.exit(1);
289
- }
290
- break;
291
- }
292
-
293
- case 'delete': {
294
- const msg = store.cmdDelete(rest[0]);
295
- // cmdDelete returns a "Key not found" prefix for missing keys — route to stderr
296
- if (msg.startsWith('Key not found')) process.stderr.write(msg + '\n');
297
- else console.log(msg);
298
- break;
299
- }
300
-
301
- case 'list': {
302
- const keys = store.cmdList(rest[0] || '');
303
- if (keys.length === 0 && rest[0]) {
304
- process.stderr.write(`No keys found with prefix: ${rest[0]}\n`);
305
- } else {
306
- keys.forEach(k => console.log(k));
307
- }
308
- break;
309
- }
310
-
311
- case 'list-values': {
312
- const pairs = store.cmdListValues(rest[0] || '');
313
- if (pairs.length === 0 && rest[0]) {
314
- process.stderr.write(`No keys found with prefix: ${rest[0]}\n`);
315
- } else {
316
- pairs.forEach(p => console.log(p));
317
- }
318
- break;
319
- }
320
-
321
- case 'exists': {
322
- // Exit 0 if key exists, exit 1 if not — compatible with shell conditionals
323
- const exists = store.cmdExists(rest[0]);
324
- process.exit(exists ? 0 : 1);
325
- break;
326
- }
327
-
328
- case 'append':
329
- store.cmdAppend(rest[0], rest[1] !== undefined ? rest[1] : '');
330
- break;
331
-
332
- case 'incr': {
333
- // Parse increment amount as base-10 integer; defaults to 1 inside cmdIncr
334
- const newVal = store.cmdIncr(rest[0], rest[1] !== undefined ? parseInt(rest[1], 10) : 1);
335
- console.log(newVal);
336
- break;
337
- }
338
-
339
- default:
340
- process.stderr.write(`Unknown store command: ${subcmd}\n`);
341
- printStoreUsage();
342
- process.exit(1);
343
- }
344
- } catch (err) {
345
- process.stderr.write(`Error: ${err.message}\n`);
346
- process.exit(1);
347
- }
348
- }
349
-
350
- /**
351
- * Prints usage information for the `store` sub-command group.
352
- */
353
- function printStoreUsage() {
354
- console.log(`Usage: clawpowers store <command> [args]
355
-
356
- Commands:
357
- set <key> <value> Set a key-value pair
358
- get <key> [default] Get value (returns default or error if not found)
359
- delete <key> Delete a key
360
- list [prefix] List all keys matching prefix
361
- list-values [prefix] List key=value pairs matching prefix
362
- exists <key> Exit 0 if key exists, 1 if not
363
- append <key> <value> Append value (newline-separated)
364
- incr <key> [amount] Increment integer value by amount (default: 1)
365
-
366
- Key format: namespace:entity:attribute`);
367
- }
368
-
369
- /**
370
- * Fallback dispatcher: spawn `node <script> [...args]` as a child process.
371
- * Used when a module function isn't directly exported but can be triggered
372
- * via its CLI entry point.
373
- *
374
- * @param {string} script - Absolute path to the Node.js script to run.
375
- * @param {string[]} args - Arguments to forward to the script.
376
- */
377
- function delegateToNode(script, args) {
378
- const result = spawnSync(process.execPath, [script, ...args], { stdio: 'inherit' });
379
- process.exit(result.status || 0);
380
- }
381
-
382
- /**
383
- * `clawpowers payments setup` — Interactive wallet activation wizard.
384
- *
385
- * Guides the user through enabling or configuring the payment subsystem.
386
- * Never asks for private keys — those belong in .env.
387
- * Reads and writes ~/.clawpowers/config.json (created by init if missing).
388
- *
389
- * Wizard steps:
390
- * 1. Explain that payments are optional
391
- * 2. Ask user to choose a mode: disabled / dry run / live
392
- * 3. If dry run: update config payments.mode = "dry_run", payments.enabled = true
393
- * 4. If live: ask for per_tx_limit and daily_limit, then update config
394
- * 5. Confirm where logs are stored
395
- */
396
- function cmdPaymentsSetup() {
397
- const readline = require('readline');
398
- const CLAWPOWERS_DIR = process.env.CLAWPOWERS_DIR || path.join(os.homedir(), '.clawpowers');
399
- const configFile = path.join(CLAWPOWERS_DIR, 'config.json');
400
-
401
- // Load existing config or fall back to defaults
402
- let config = {};
403
- if (fs.existsSync(configFile)) {
404
- try {
405
- config = JSON.parse(fs.readFileSync(configFile, 'utf8'));
406
- } catch (_) {
407
- config = {};
408
- }
409
- }
410
- // Ensure payments section exists with safe defaults
411
- if (!config.payments) {
412
- config.payments = {
413
- enabled: false,
414
- mode: 'dry_run',
415
- per_tx_limit_usd: 0,
416
- daily_limit_usd: 0,
417
- weekly_limit_usd: 0,
418
- allowlist: [],
419
- require_approval_above_usd: 0,
420
- };
421
- }
422
-
423
- const logsPath = path.join(CLAWPOWERS_DIR, 'logs', 'payments.jsonl');
424
-
425
- const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
426
-
427
- const ask = (question) => new Promise((resolve) => rl.question(question, resolve));
428
-
429
- async function run() {
430
- console.log('');
431
- console.log('╔══════════════════════════════════════════════════╗');
432
- console.log('║ ClawPowers Payment Setup Wizard ║');
433
- console.log('╚══════════════════════════════════════════════════╝');
434
- console.log('');
435
- console.log('Payments are optional. ClawPowers works without a wallet.');
436
- console.log('When enabled, agents can autonomously pay for premium APIs');
437
- console.log('and services using the x402 protocol.');
438
- console.log('');
439
- console.log('⚠ Private keys belong in .env — this wizard never asks for them.');
440
- console.log('');
441
- console.log('Choose a mode:');
442
- console.log(' [1] Keep disabled (default — no payments, no wallet required)');
443
- console.log(' [2] Enable Dry Run (detect payment gates, log what WOULD happen)');
444
- console.log(' [3] Enable Live (real payments within configured limits)');
445
- console.log('');
446
-
447
- const choice = (await ask('Enter choice [1/2/3]: ')).trim();
448
-
449
- if (choice === '1' || choice === '') {
450
- config.payments.enabled = false;
451
- config.payments.mode = 'dry_run';
452
- console.log('');
453
- console.log('✓ Payments remain disabled. No wallet required.');
454
-
455
- } else if (choice === '2') {
456
- config.payments.enabled = true;
457
- config.payments.mode = 'dry_run';
458
- console.log('');
459
- console.log('✓ Dry Run mode enabled.');
460
- console.log(' Agents will detect payment requirements and log what would happen.');
461
- console.log(' No funds will move. Review the log after 10+ cycles, then');
462
- console.log(' run this wizard again to go live with confidence.');
463
-
464
- } else if (choice === '3') {
465
- console.log('');
466
- console.log('Live payment mode requires spending limits to protect your wallet.');
467
- console.log('');
468
-
469
- const perTxRaw = (await ask('Per-transaction limit (USD, e.g. 0.10): ')).trim();
470
- const dailyRaw = (await ask('Daily limit (USD, e.g. 5.00): ')).trim();
471
-
472
- const perTxLimit = parseFloat(perTxRaw) || 0;
473
- const dailyLimit = parseFloat(dailyRaw) || 0;
474
-
475
- config.payments.enabled = true;
476
- config.payments.mode = 'live';
477
- config.payments.per_tx_limit_usd = perTxLimit;
478
- config.payments.daily_limit_usd = dailyLimit;
479
-
480
- console.log('');
481
- console.log(`✓ Live payments enabled.`);
482
- console.log(` Per-transaction limit: $${perTxLimit.toFixed(2)}`);
483
- console.log(` Daily limit: $${dailyLimit.toFixed(2)}`);
484
- console.log('');
485
- console.log(' Add your private key or mnemonic to ~/.clawpowers/.env');
486
- console.log(' (never commit this file — it is gitignored by default)');
487
-
488
- } else {
489
- console.log('');
490
- console.log('Invalid choice. No changes made.');
491
- rl.close();
492
- return;
493
- }
494
-
495
- // Save updated config
496
- if (!fs.existsSync(CLAWPOWERS_DIR)) {
497
- fs.mkdirSync(CLAWPOWERS_DIR, { recursive: true, mode: 0o700 });
498
- }
499
- fs.writeFileSync(configFile, JSON.stringify(config, null, 2) + '\n', { mode: 0o600 });
500
-
501
- console.log('');
502
- console.log(`✓ Configuration saved to: ${configFile}`);
503
- console.log(` All payment logs are stored locally at: ${logsPath}`);
504
- console.log('');
505
- console.log(' Review logs with: npx clawpowers payments log');
506
- console.log(' See summary with: npx clawpowers payments summary');
507
- console.log('');
508
-
509
- rl.close();
510
- }
511
-
512
- run().catch((err) => {
513
- process.stderr.write(`Error: ${err.message}\n`);
514
- rl.close();
515
- process.exit(1);
516
- });
517
- }
518
-
519
- /**
520
- * `clawpowers payments <subcmd> [args]` — Payment ledger and setup commands.
521
- *
522
- * Subcommands:
523
- * setup — Interactive payment mode wizard
524
- * log — Show recent payment decisions
525
- * summary — Show payment totals by skill, chain, outcome
526
- *
527
- * @param {string[]} args - Remaining argv after 'payments'.
528
- */
529
- function cmdPayments(args) {
530
- const [subcmd, ...rest] = args;
531
-
532
- if (!subcmd || subcmd === 'help' || subcmd === '--help' || subcmd === '-h') {
533
- console.log(`Usage: clawpowers payments <command> [options]
534
-
535
- Commands:
536
- setup Interactive payment mode wizard
537
- log [--limit <n>] Show recent payment decisions (default: last 20)
538
- summary Show totals by skill, chain, and outcome`);
539
- return;
540
- }
541
-
542
- switch (subcmd) {
543
- case 'setup':
544
- cmdPaymentsSetup();
545
- break;
546
- case 'log':
547
- requireModule(LEDGER_JS).cmdLog ? requireModule(LEDGER_JS).cmdLog(rest)
548
- : delegateToNode(LEDGER_JS, ['log', ...rest]);
549
- break;
550
- case 'summary':
551
- requireModule(LEDGER_JS).cmdSummary ? requireModule(LEDGER_JS).cmdSummary()
552
- : delegateToNode(LEDGER_JS, ['summary']);
553
- break;
554
- default:
555
- process.stderr.write(`Unknown payments subcommand: ${subcmd}\n`);
556
- process.stderr.write('Run: npx clawpowers payments help\n');
557
- process.exit(1);
558
- }
559
- }
560
-
561
- /**
562
- * `clawpowers demo x402` — Start the x402 mock merchant server for demo purposes.
563
- * Delegates to runtime/demo/x402-mock-server.js.
564
- *
565
- * @param {string[]} args - Remaining argv after 'demo'.
566
- */
567
- function cmdDemo(args) {
568
- const [subcmd] = args;
569
-
570
- if (!subcmd || subcmd === 'help' || subcmd === '--help' || subcmd === '-h') {
571
- console.log(`Usage: clawpowers demo <command>
572
-
573
- Commands:
574
- x402 Start the x402 mock merchant server`);
575
- return;
576
- }
577
-
578
- if (subcmd === 'x402') {
579
- const MOCK_SERVER_JS = path.join(REPO_ROOT, 'runtime', 'demo', 'x402-mock-server.js');
580
- if (!fs.existsSync(MOCK_SERVER_JS)) {
581
- process.stderr.write(`Error: runtime module not found: ${MOCK_SERVER_JS}\n`);
582
- process.exit(1);
583
- }
584
- delegateToNode(MOCK_SERVER_JS, []);
585
- } else {
586
- process.stderr.write(`Unknown demo subcommand: ${subcmd}\n`);
587
- process.stderr.write('Run: npx clawpowers demo help\n');
588
- process.exit(1);
589
- }
590
- }
591
-
592
- // ============================================================
593
- // Main dispatch — parse the first positional argument as the command
594
- // ============================================================
595
- const [cmd, ...args] = process.argv.slice(2);
596
-
597
- try {
598
- switch (cmd) {
599
- case 'init': cmdInit(); break;
600
- case 'status': cmdStatus(); break;
601
- case 'update': cmdUpdate(); break;
602
- case 'inject': cmdInject(); break;
603
- case 'metrics': cmdMetrics(args); break;
604
- case 'analyze': cmdAnalyze(args); break;
605
- case 'store': cmdStore(args); break;
606
- case 'payments': cmdPayments(args); break;
607
- case 'demo': cmdDemo(args); break;
608
- case 'help':
609
- case '-h':
610
- case '--help': printUsage(); break;
611
- // No command or empty string: show usage and exit 1 (non-zero for scripts)
612
- case undefined:
613
- case '':
614
- printUsage();
615
- process.exit(1);
616
- break;
617
- default:
618
- process.stderr.write(`Unknown command: ${cmd}\n`);
619
- printUsage();
620
- process.exit(1);
621
- }
622
- } catch (err) {
623
- process.stderr.write(`Error: ${err.message}\n`);
624
- process.exit(1);
625
- }