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.
- package/CHANGELOG.md +94 -0
- package/LICENSE +44 -0
- package/README.md +202 -384
- package/SECURITY.md +72 -0
- package/dist/index.d.ts +844 -0
- package/dist/index.js +2536 -0
- package/dist/index.js.map +1 -0
- package/package.json +52 -42
- package/.claude-plugin/manifest.json +0 -19
- package/.codex/INSTALL.md +0 -36
- package/.cursor-plugin/manifest.json +0 -21
- package/.opencode/INSTALL.md +0 -52
- package/ARCHITECTURE.md +0 -69
- package/bin/clawpowers.js +0 -625
- package/bin/clawpowers.sh +0 -91
- package/docs/demo/clawpowers-demo.cast +0 -197
- package/docs/demo/clawpowers-demo.gif +0 -0
- package/docs/launch-images/25-skills-breakdown.jpg +0 -0
- package/docs/launch-images/clawpowers-vs-superpowers.jpg +0 -0
- package/docs/launch-images/economic-code-optimization.jpg +0 -0
- package/docs/launch-images/native-vs-bridge-2.jpg +0 -0
- package/docs/launch-images/native-vs-bridge.jpg +0 -0
- package/docs/launch-images/post1-hero-lobster.jpg +0 -0
- package/docs/launch-images/post2-dashboard.jpg +0 -0
- package/docs/launch-images/post3-superpowers.jpg +0 -0
- package/docs/launch-images/post4-before-after.jpg +0 -0
- package/docs/launch-images/post5-install-now.jpg +0 -0
- package/docs/launch-images/ultimate-stack.jpg +0 -0
- package/docs/launch-posts.md +0 -76
- package/docs/quickstart-first-transaction.md +0 -204
- package/gemini-extension.json +0 -32
- package/hooks/session-start +0 -205
- package/hooks/session-start.cmd +0 -43
- package/hooks/session-start.js +0 -163
- package/runtime/demo/README.md +0 -78
- package/runtime/demo/x402-mock-server.js +0 -230
- package/runtime/feedback/analyze.js +0 -621
- package/runtime/feedback/analyze.sh +0 -546
- package/runtime/init.js +0 -210
- package/runtime/init.sh +0 -178
- package/runtime/metrics/collector.js +0 -361
- package/runtime/metrics/collector.sh +0 -308
- package/runtime/payments/ledger.js +0 -305
- package/runtime/payments/ledger.sh +0 -262
- package/runtime/payments/pipeline.js +0 -459
- package/runtime/persistence/store.js +0 -433
- package/runtime/persistence/store.sh +0 -303
- package/skill.json +0 -106
- package/skills/agent-bounties/SKILL.md +0 -553
- package/skills/agent-payments/SKILL.md +0 -479
- package/skills/brainstorming/SKILL.md +0 -233
- package/skills/content-pipeline/SKILL.md +0 -282
- package/skills/cross-project-knowledge/SKILL.md +0 -345
- package/skills/dispatching-parallel-agents/SKILL.md +0 -305
- package/skills/economic-code-optimization/SKILL.md +0 -265
- package/skills/executing-plans/SKILL.md +0 -255
- package/skills/finishing-a-development-branch/SKILL.md +0 -260
- package/skills/formal-verification-lite/SKILL.md +0 -441
- package/skills/learn-how-to-learn/SKILL.md +0 -235
- package/skills/market-intelligence/SKILL.md +0 -323
- package/skills/meta-skill-evolution/SKILL.md +0 -325
- package/skills/prospecting/SKILL.md +0 -454
- package/skills/receiving-code-review/SKILL.md +0 -225
- package/skills/requesting-code-review/SKILL.md +0 -206
- package/skills/security-audit/SKILL.md +0 -353
- package/skills/self-healing-code/SKILL.md +0 -369
- package/skills/subagent-driven-development/SKILL.md +0 -244
- package/skills/systematic-debugging/SKILL.md +0 -355
- package/skills/test-driven-development/SKILL.md +0 -416
- package/skills/using-clawpowers/SKILL.md +0 -160
- package/skills/using-git-worktrees/SKILL.md +0 -261
- package/skills/verification-before-completion/SKILL.md +0 -254
- package/skills/writing-plans/SKILL.md +0 -276
- 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
|
-
}
|