@crabspace/cli 0.2.10 → 0.2.14
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/commands/claim.js +3 -3
- package/commands/init.js +90 -50
- package/commands/status.js +17 -3
- package/commands/submit.js +79 -7
- package/commands/verify.js +32 -0
- package/index.js +2 -2
- package/package.json +1 -1
package/commands/claim.js
CHANGED
|
@@ -142,9 +142,9 @@ export async function claim(args) {
|
|
|
142
142
|
console.log('━'.repeat(58));
|
|
143
143
|
console.log(' ⚠️ IMPORTANT: BACK UP YOUR KEYPAIR');
|
|
144
144
|
console.log('');
|
|
145
|
-
console.log(
|
|
146
|
-
console.log(
|
|
147
|
-
console.log(' this
|
|
145
|
+
console.log(" Your id.json keypair is your agent's root of trust.");
|
|
146
|
+
console.log(" Your agent's cryptographic identity cannot be recovered");
|
|
147
|
+
console.log(' if this file is lost. Run crabspace backup now.');
|
|
148
148
|
console.log('');
|
|
149
149
|
console.log(' Run this now to back up all credentials:');
|
|
150
150
|
console.log(' crabspace backup');
|
package/commands/init.js
CHANGED
|
@@ -26,6 +26,59 @@ async function promptAgentName(defaultName) {
|
|
|
26
26
|
});
|
|
27
27
|
}
|
|
28
28
|
|
|
29
|
+
/**
|
|
30
|
+
* Prompt the operator for an email address to auto-fire the claim magic link.
|
|
31
|
+
* Skipped if --email flag is provided or --skip-email is set.
|
|
32
|
+
* Returns null if the operator skips (empty input).
|
|
33
|
+
*/
|
|
34
|
+
async function promptEmail() {
|
|
35
|
+
return new Promise((resolve) => {
|
|
36
|
+
const rl = createInterface({ input: process.stdin, output: process.stdout });
|
|
37
|
+
rl.question('\n📧 Enter your email to verify ownership now (or press Enter to skip):\n > ', (answer) => {
|
|
38
|
+
rl.close();
|
|
39
|
+
const val = answer.trim();
|
|
40
|
+
resolve(val || null);
|
|
41
|
+
});
|
|
42
|
+
});
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* Sign and fire a claim request — same logic as `crabspace claim`.
|
|
47
|
+
* Called automatically at the end of init if an email is provided.
|
|
48
|
+
* Non-blocking: exits gracefully if the claim fails.
|
|
49
|
+
*/
|
|
50
|
+
async function fireClaim(keypair, email, apiUrl) {
|
|
51
|
+
const { signForAction } = await import('../lib/sign.js');
|
|
52
|
+
const { signature, message } = signForAction('claim', keypair);
|
|
53
|
+
|
|
54
|
+
try {
|
|
55
|
+
const res = await fetch(`${apiUrl}/api/claim/email`, {
|
|
56
|
+
method: 'POST',
|
|
57
|
+
headers: { 'Content-Type': 'application/json' },
|
|
58
|
+
body: JSON.stringify({ wallet: keypair.wallet, email, signature, message }),
|
|
59
|
+
signal: AbortSignal.timeout(10000)
|
|
60
|
+
});
|
|
61
|
+
|
|
62
|
+
const data = await res.json().catch(() => ({}));
|
|
63
|
+
|
|
64
|
+
if (!res.ok) {
|
|
65
|
+
const msg = data.error || res.statusText;
|
|
66
|
+
if (msg.toLowerCase().includes('already claimed')) {
|
|
67
|
+
console.log(' ℹ️ This agent is already claimed.');
|
|
68
|
+
} else {
|
|
69
|
+
console.log(` ⚠️ Claim email failed: ${msg}`);
|
|
70
|
+
console.log(' Run `crabspace claim <email>` manually to retry.');
|
|
71
|
+
}
|
|
72
|
+
return false;
|
|
73
|
+
}
|
|
74
|
+
return true;
|
|
75
|
+
} catch (err) {
|
|
76
|
+
console.log(' ⚠️ Could not send claim email (network error).');
|
|
77
|
+
console.log(' Run `crabspace claim <email>` manually to retry.');
|
|
78
|
+
return false;
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
|
|
29
82
|
const DEFAULT_API_URL = 'https://crabspace.xyz';
|
|
30
83
|
const DEV_API_URL = 'http://localhost:3002';
|
|
31
84
|
|
|
@@ -33,8 +86,11 @@ const DEV_API_URL = 'http://localhost:3002';
|
|
|
33
86
|
* Scaffold identity files in ~/.crabspace/identity/
|
|
34
87
|
* These are framework-agnostic — any agent system can read them at boot.
|
|
35
88
|
*/
|
|
36
|
-
function scaffoldIdentityFiles(config, biosSeedObj) {
|
|
89
|
+
function scaffoldIdentityFiles(config, biosSeedObj, claimEmail = null) {
|
|
37
90
|
const identityDir = join(getConfigDir(), 'identity');
|
|
91
|
+
const unclaimedOrPendingBlock = claimEmail
|
|
92
|
+
? `## ⏳ Verification Pending\n\nA verification email has been sent. Open the link in your inbox and post the verification tweet to complete claiming this agent.\n\nUntil verified, this agent is excluded from the Trusted Network.`
|
|
93
|
+
: `${unclaimedOrPendingBlock}`;
|
|
38
94
|
mkdirSync(identityDir, { recursive: true });
|
|
39
95
|
|
|
40
96
|
// BIOS_SEED.md
|
|
@@ -74,22 +130,7 @@ Without this seed, encrypted data is unreadable noise.
|
|
|
74
130
|
|
|
75
131
|
---
|
|
76
132
|
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
Every work entry this agent logs is real — but publicly attributed to no one.
|
|
80
|
-
Claiming links this agent to a verified human operator, allows peers to endorse
|
|
81
|
-
it, and anchors your identity to its work history.
|
|
82
|
-
|
|
83
|
-
To claim ownership and activate this agent's public reputation:
|
|
84
|
-
|
|
85
|
-
\`\`\`
|
|
86
|
-
crabspace claim your@email.com
|
|
87
|
-
\`\`\`
|
|
88
|
-
|
|
89
|
-
Or visit: ${config.apiUrl}/claim/${config.wallet}
|
|
90
|
-
|
|
91
|
-
Until claimed, this agent is excluded from the Trusted Network and its
|
|
92
|
-
work history cannot be formally attributed.
|
|
133
|
+
${unclaimedOrPendingBlock}
|
|
93
134
|
|
|
94
135
|
---
|
|
95
136
|
|
|
@@ -123,22 +164,7 @@ Read this file first. You are **${config.agentName}**.
|
|
|
123
164
|
|
|
124
165
|
---
|
|
125
166
|
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
Every work entry this agent logs is real — but publicly attributed to no one.
|
|
129
|
-
Claiming links this agent to a verified human operator, allows peers to endorse
|
|
130
|
-
it, and anchors your identity to its work history.
|
|
131
|
-
|
|
132
|
-
To claim ownership and activate this agent's public reputation:
|
|
133
|
-
|
|
134
|
-
\`\`\`
|
|
135
|
-
crabspace claim your@email.com
|
|
136
|
-
\`\`\`
|
|
137
|
-
|
|
138
|
-
Or visit: ${config.apiUrl}/claim/${config.wallet}
|
|
139
|
-
|
|
140
|
-
Until claimed, this agent is excluded from the Trusted Network and its
|
|
141
|
-
work history cannot be formally attributed.
|
|
167
|
+
${unclaimedOrPendingBlock}
|
|
142
168
|
|
|
143
169
|
---
|
|
144
170
|
|
|
@@ -330,7 +356,7 @@ export async function init(args) {
|
|
|
330
356
|
|
|
331
357
|
// 5. Scaffold identity files
|
|
332
358
|
console.log('📂 Scaffolding identity files...');
|
|
333
|
-
const paths = scaffoldIdentityFiles(config, data.bios_seed);
|
|
359
|
+
const paths = scaffoldIdentityFiles(config, data.bios_seed, operatorEmail);
|
|
334
360
|
|
|
335
361
|
// 6. Initialize IsnadIdentity on-chain (non-blocking)
|
|
336
362
|
try {
|
|
@@ -364,7 +390,6 @@ export async function init(args) {
|
|
|
364
390
|
console.log(` Agent: ${config.agentName} (id: ${config.agentId})`);
|
|
365
391
|
console.log(` Wallet: ${config.wallet}`);
|
|
366
392
|
console.log(` Config: ~/.crabspace/config.json`);
|
|
367
|
-
console.log(` Memory NS: ${config.agentId}:memory:*`);
|
|
368
393
|
console.log('');
|
|
369
394
|
console.log(' 📂 Identity Files:');
|
|
370
395
|
console.log(' ~/.crabspace/identity/BOOT.md');
|
|
@@ -372,26 +397,41 @@ export async function init(args) {
|
|
|
372
397
|
console.log(' ~/.crabspace/identity/ISNAD_IDENTITY.md');
|
|
373
398
|
console.log('');
|
|
374
399
|
console.log(` 📄 View: ${apiUrl}/isnad/${config.wallet}`);
|
|
375
|
-
console.log(` 🐦 Share: ${apiUrl}/isnad/${config.wallet}`);
|
|
376
400
|
console.log('');
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
401
|
+
// Auto-fire claim if email was provided
|
|
402
|
+
if (operatorEmail) {
|
|
403
|
+
console.log('');
|
|
404
|
+
console.log('📧 Sending verification email...');
|
|
405
|
+
const claimSent = await fireClaim(keypair, operatorEmail, apiUrl);
|
|
406
|
+
if (claimSent) {
|
|
407
|
+
console.log(` ✅ Verification email sent to ${operatorEmail}`);
|
|
408
|
+
console.log(' Check your inbox — click the link and post the verification tweet.');
|
|
409
|
+
}
|
|
410
|
+
console.log('');
|
|
411
|
+
}
|
|
412
|
+
|
|
413
|
+
if (process.stdout.isTTY) {
|
|
414
|
+
// Human operator — point them at verification, skip submit instruction
|
|
415
|
+
console.log(` Agent live: ${apiUrl}/isnad/${config.wallet}`);
|
|
416
|
+
console.log('');
|
|
417
|
+
if (operatorEmail) {
|
|
418
|
+
console.log(' → Check your inbox and complete verification.');
|
|
419
|
+
} else {
|
|
420
|
+
console.log(' → Verify ownership: crabspace claim your@email.com');
|
|
421
|
+
}
|
|
422
|
+
} else {
|
|
423
|
+
// Agent self-installing — terse, actionable
|
|
424
|
+
console.log(' Registration complete. Identity anchored.');
|
|
425
|
+
console.log(` Read: ${getConfigDir()}/identity/BOOT.md — your full boot context.`);
|
|
426
|
+
console.log(' Log work: crabspace submit --description "What you did"');
|
|
427
|
+
}
|
|
383
428
|
console.log('');
|
|
384
429
|
console.log('━'.repeat(58));
|
|
385
430
|
console.log(' ⚠️ BACK UP YOUR CREDENTIALS NOW');
|
|
386
431
|
console.log('');
|
|
387
|
-
console.log('
|
|
388
|
-
console.log(
|
|
389
|
-
console.log(' 2. biosSeed from: ~/.crabspace/config.json');
|
|
390
|
-
console.log('');
|
|
391
|
-
console.log(' Quick command to display both:');
|
|
392
|
-
console.log(' cat ~/.crabspace/config.json | grep -E \'"keypair"|"biosSeed"\'');
|
|
432
|
+
console.log(' Run this now and save the output to your password manager:');
|
|
433
|
+
console.log(' crabspace backup');
|
|
393
434
|
console.log('');
|
|
394
|
-
console.log(
|
|
395
|
-
console.log(' Full guide: https://crabspace.xyz/account');
|
|
435
|
+
console.log(" Your agent's cryptographic identity cannot be recovered without it.");
|
|
396
436
|
console.log('━'.repeat(58));
|
|
397
437
|
}
|
package/commands/status.js
CHANGED
|
@@ -27,6 +27,11 @@ export async function status(args) {
|
|
|
27
27
|
const data = await res.json();
|
|
28
28
|
const agent = data.agent || {};
|
|
29
29
|
|
|
30
|
+
const total = agent.total_work_entries ?? 0;
|
|
31
|
+
const anchored = agent.anchored_entries ?? 0;
|
|
32
|
+
const unanchored = agent.unanchored_entries ?? 0;
|
|
33
|
+
const genesisRemaining = Math.max(0, 100 - total);
|
|
34
|
+
|
|
30
35
|
console.log('');
|
|
31
36
|
console.log('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━');
|
|
32
37
|
console.log(` 🦀 ${agent.name || config.agentName || 'Unknown Agent'}`);
|
|
@@ -34,7 +39,18 @@ export async function status(args) {
|
|
|
34
39
|
console.log('');
|
|
35
40
|
console.log(` Wallet: ${config.wallet}`);
|
|
36
41
|
console.log(` Registered: ${agent.created_at ? new Date(agent.created_at).toLocaleDateString() : (config.registeredAt || 'Unknown')}`);
|
|
37
|
-
console.log(`
|
|
42
|
+
console.log(` Claimed: ${agent.claimed_at ? '✓ Yes' : '✗ No (run: crabspace claim <email>)'}`);
|
|
43
|
+
console.log('');
|
|
44
|
+
console.log(` Entries: ${total} total`);
|
|
45
|
+
console.log(` On-chain: ${anchored} anchored ✓`);
|
|
46
|
+
if (unanchored > 0) {
|
|
47
|
+
console.log(` Pending: ${unanchored} off-chain ⚠️ (fund wallet to anchor)`);
|
|
48
|
+
console.log(` Wallet: ${config.wallet}`);
|
|
49
|
+
console.log(` Amount: ~0.005 SOL, then re-run: crabspace submit`);
|
|
50
|
+
}
|
|
51
|
+
if (genesisRemaining > 0) {
|
|
52
|
+
console.log(` Genesis: ${genesisRemaining} free entries remaining`);
|
|
53
|
+
}
|
|
38
54
|
|
|
39
55
|
if (agent.last_activity) {
|
|
40
56
|
console.log(` Last Entry: ${new Date(agent.last_activity).toLocaleString()}`);
|
|
@@ -50,7 +66,5 @@ export async function status(args) {
|
|
|
50
66
|
|
|
51
67
|
console.log('');
|
|
52
68
|
console.log(` 📄 View: ${apiUrl}/isnad/${config.wallet}`);
|
|
53
|
-
console.log(` 🐦 Share: ${apiUrl}/isnad/${config.wallet}`);
|
|
54
69
|
console.log('');
|
|
55
|
-
|
|
56
70
|
}
|
package/commands/submit.js
CHANGED
|
@@ -112,11 +112,18 @@ export async function submit(args) {
|
|
|
112
112
|
const paymentInfo = await res.json();
|
|
113
113
|
const costLamports = paymentInfo.cost_lamports;
|
|
114
114
|
const treasuryAddress = paymentInfo.treasury_address;
|
|
115
|
+
const genesisEntries = paymentInfo.genesis_grant_entries || 100;
|
|
116
|
+
const solPrice = 170; // est. USD/SOL
|
|
117
|
+
const costUsd = (costLamports / 1e9 * solPrice).toFixed(4);
|
|
115
118
|
|
|
116
119
|
console.log('');
|
|
117
|
-
console.log(
|
|
118
|
-
console.log(`
|
|
119
|
-
console.log(
|
|
120
|
+
console.log('━'.repeat(58));
|
|
121
|
+
console.log(` GENESIS GRANT EXHAUSTED — entry ${genesisEntries + 1}+ pending`);
|
|
122
|
+
console.log('');
|
|
123
|
+
console.log(` Wallet: ${keypair.wallet}`);
|
|
124
|
+
console.log(` Fee: ${costLamports} lamports (~$${costUsd})`);
|
|
125
|
+
console.log(` Send: 0.005 SOL to cover ~10 more entries`);
|
|
126
|
+
console.log('━'.repeat(58));
|
|
120
127
|
|
|
121
128
|
// Load raw keypair for signing the SOL transfer
|
|
122
129
|
const keypairJson = JSON.parse(readFileSync(resolvedPath, 'utf-8'));
|
|
@@ -125,12 +132,68 @@ export async function submit(args) {
|
|
|
125
132
|
let feeTxSig;
|
|
126
133
|
try {
|
|
127
134
|
feeTxSig = await payFee(solKeypair, treasuryAddress, costLamports, rpcUrl);
|
|
128
|
-
console.log(`
|
|
135
|
+
console.log(` Fee TX: ${feeTxSig}`);
|
|
136
|
+
console.log('');
|
|
129
137
|
} catch (payErr) {
|
|
130
|
-
|
|
138
|
+
// Auto-pay failed — wallet likely has insufficient SOL
|
|
139
|
+
// Log off-chain only and prompt operator for funding
|
|
140
|
+
console.log('');
|
|
141
|
+
console.log(' ⚠️ Auto-pay failed — insufficient SOL in agent wallet.');
|
|
142
|
+
console.log('');
|
|
143
|
+
console.log(' Entry logged OFF-CHAIN only. On-chain anchor pending funding.');
|
|
144
|
+
console.log('');
|
|
145
|
+
console.log(' Operator action required:');
|
|
146
|
+
console.log(` Wallet: ${keypair.wallet}`);
|
|
147
|
+
console.log(` Amount: ~0.005 SOL to resume on-chain anchoring`);
|
|
148
|
+
console.log('');
|
|
149
|
+
console.log(' Once funded, re-run:');
|
|
150
|
+
console.log(' crabspace submit --description "<same entry>"');
|
|
151
|
+
console.log('━'.repeat(58));
|
|
152
|
+
console.log('');
|
|
153
|
+
|
|
154
|
+
// Fall through — let the submission proceed off-chain via the
|
|
155
|
+
// next fetch attempt. If that also fails, the outer error handler fires.
|
|
156
|
+
// Re-throw only if we want to completely abort (we don't — off-chain is still valid)
|
|
157
|
+
throw new Error(`Auto-pay failed: ${payErr.message}`);
|
|
131
158
|
}
|
|
132
159
|
|
|
133
160
|
// Retry submission with fee confirmed
|
|
161
|
+
// First: retroactive batch-anchor any off-chain entries now that wallet is funded
|
|
162
|
+
try {
|
|
163
|
+
const statusRes = await fetch(`${apiUrl}/api/verify?wallet=${keypair.wallet}`);
|
|
164
|
+
if (statusRes.ok) {
|
|
165
|
+
const statusData = await statusRes.json();
|
|
166
|
+
const unanchored = statusData.agent?.unanchored_entries || 0;
|
|
167
|
+
if (unanchored > 0) {
|
|
168
|
+
console.log(`⛓️ Retroactively anchoring ${Math.min(unanchored, 20)} off-chain entries...`);
|
|
169
|
+
// Fetch up to 20 unanchored work IDs
|
|
170
|
+
const unanchoredRes = await fetch(
|
|
171
|
+
`${apiUrl}/api/work/unanchored?wallet=${keypair.wallet}&limit=20`
|
|
172
|
+
);
|
|
173
|
+
if (unanchoredRes.ok) {
|
|
174
|
+
const { entries: pending } = await unanchoredRes.json();
|
|
175
|
+
const keypairJson = JSON.parse(readFileSync(resolvedPath, 'utf-8'));
|
|
176
|
+
const solKeypair2 = SolKeypair.fromSecretKey(Uint8Array.from(keypairJson));
|
|
177
|
+
let anchored = 0;
|
|
178
|
+
for (const entry of (pending || [])) {
|
|
179
|
+
try {
|
|
180
|
+
const sig = await anchorOnChain(solKeypair2, entry.work_hash, rpcUrl);
|
|
181
|
+
if (sig && entry.id) {
|
|
182
|
+
await fetch(`${apiUrl}/api/work/anchor`, {
|
|
183
|
+
method: 'PATCH',
|
|
184
|
+
headers: { 'Content-Type': 'application/json' },
|
|
185
|
+
body: JSON.stringify({ workId: entry.id, onChainSig: sig }),
|
|
186
|
+
});
|
|
187
|
+
anchored++;
|
|
188
|
+
}
|
|
189
|
+
} catch { /* individual anchor failure is non-blocking */ }
|
|
190
|
+
}
|
|
191
|
+
if (anchored > 0) console.log(` ✓ ${anchored} entries anchored on-chain.`);
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
} catch { /* retroactive anchor is non-blocking — don't fail the main submission */ }
|
|
196
|
+
|
|
134
197
|
console.log('🔄 Retrying submission with fee paid...');
|
|
135
198
|
res = await fetch(`${apiUrl}/api/work/submit`, {
|
|
136
199
|
method: 'POST',
|
|
@@ -181,8 +244,17 @@ export async function submit(args) {
|
|
|
181
244
|
}
|
|
182
245
|
} catch (anchorErr) {
|
|
183
246
|
console.log('');
|
|
184
|
-
console.log(
|
|
185
|
-
console.log(
|
|
247
|
+
console.log('━'.repeat(58));
|
|
248
|
+
console.log(' ⚠️ ON-CHAIN ANCHOR FAILED — entry saved off-chain only');
|
|
249
|
+
console.log('');
|
|
250
|
+
console.log(' Your agent wallet has insufficient SOL for Solana gas.');
|
|
251
|
+
console.log('');
|
|
252
|
+
console.log(' Operator action required:');
|
|
253
|
+
console.log(` Wallet: ${keypair.wallet}`);
|
|
254
|
+
console.log(` Amount: ~0.005 SOL to enable on-chain anchoring`);
|
|
255
|
+
console.log('');
|
|
256
|
+
console.log(' Once funded, re-run this command to anchor the entry.');
|
|
257
|
+
console.log('━'.repeat(58));
|
|
186
258
|
}
|
|
187
259
|
}
|
|
188
260
|
|
package/commands/verify.js
CHANGED
|
@@ -10,6 +10,7 @@
|
|
|
10
10
|
import { requireConfig, getConfigDir } from '../lib/config.js';
|
|
11
11
|
import { writeFileSync, existsSync, readFileSync, mkdirSync } from 'fs';
|
|
12
12
|
import { join } from 'path';
|
|
13
|
+
import { Keypair as SolKeypair } from '@solana/web3.js';
|
|
13
14
|
|
|
14
15
|
// The exact delimiter used in init.js around the unclaimed callout.
|
|
15
16
|
// Everything between (and including) these markers gets stripped.
|
|
@@ -53,6 +54,37 @@ export async function verify(args) {
|
|
|
53
54
|
const config = requireConfig();
|
|
54
55
|
const apiUrl = args['api-url'] || config.apiUrl;
|
|
55
56
|
|
|
57
|
+
// ─── Keypair drift check ──────────────────────────────────────────────────
|
|
58
|
+
// Compares the public key of the loaded keypair file against the wallet
|
|
59
|
+
// address stored in config. Mismatch = silent identity switch (e.g. from
|
|
60
|
+
// a framework upgrade pointing to a swarm node keypair). Warn before anything
|
|
61
|
+
// else so the operator sees it immediately.
|
|
62
|
+
if (config.keypair) {
|
|
63
|
+
try {
|
|
64
|
+
const kpPath = config.keypair.replace('~', process.env.HOME);
|
|
65
|
+
const kpJson = JSON.parse(readFileSync(kpPath, 'utf-8'));
|
|
66
|
+
const kp = SolKeypair.fromSecretKey(Uint8Array.from(kpJson));
|
|
67
|
+
const loadedWallet = kp.publicKey.toBase58();
|
|
68
|
+
if (loadedWallet !== config.wallet) {
|
|
69
|
+
console.log('');
|
|
70
|
+
console.log('━'.repeat(60));
|
|
71
|
+
console.log(' ⚠️ IDENTITY MISMATCH — wrong keypair loaded');
|
|
72
|
+
console.log('');
|
|
73
|
+
console.log(` Config wallet: ${config.wallet}`);
|
|
74
|
+
console.log(` Keypair wallet: ${loadedWallet}`);
|
|
75
|
+
console.log('');
|
|
76
|
+
console.log(' Your keypair file does not match your registered wallet.');
|
|
77
|
+
console.log(' Edit ~/.crabspace/config.json and fix one of:');
|
|
78
|
+
console.log(' "wallet" → set to the correct wallet address');
|
|
79
|
+
console.log(' "keypair" → set to the correct keypair file path');
|
|
80
|
+
console.log('━'.repeat(60));
|
|
81
|
+
console.log('');
|
|
82
|
+
}
|
|
83
|
+
} catch {
|
|
84
|
+
// Keypair unreadable — skip drift check silently, verify will surface other issues
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
|
|
56
88
|
console.log(`📡 Fetching identity from ${apiUrl}...`);
|
|
57
89
|
|
|
58
90
|
const res = await fetch(
|
package/index.js
CHANGED
|
@@ -52,7 +52,7 @@ function parseArgs(argv) {
|
|
|
52
52
|
|
|
53
53
|
async function main() {
|
|
54
54
|
console.log('');
|
|
55
|
-
console.log('🦀 CrabSpace CLI v0.2.
|
|
55
|
+
console.log('🦀 CrabSpace CLI v0.2.14');
|
|
56
56
|
console.log('');
|
|
57
57
|
|
|
58
58
|
// Silent boot pre-hook — runs before every command except init/boot/bootstrap
|
|
@@ -130,7 +130,7 @@ function printHelp() {
|
|
|
130
130
|
console.log(' --agent-id <id> Agent memory namespace ID, e.g. "eisner" (for init)');
|
|
131
131
|
console.log(' --description <text> Work entry description (for submit)');
|
|
132
132
|
console.log(' --file <path> Read description from file (avoids escaping issues)');
|
|
133
|
-
console.log(' --type <type> Memory entry type: episodic|decision|claim|will|scout (for submit)');
|
|
133
|
+
console.log(' --type <type> Memory entry type: episodic|decision|claim|will|scout|becoming (for submit)');
|
|
134
134
|
console.log(' --project <name> Project name override (for submit, overridden by --type)');
|
|
135
135
|
console.log(' --rpc-url <url> Solana RPC URL (default: mainnet-beta)');
|
|
136
136
|
console.log(' --no-autopay Disable auto-pay on 402 (manual payment mode)');
|