claude-rpc 0.15.2 → 0.15.4
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/package.json +1 -1
- package/src/cli.js +51 -19
- package/src/install.js +1 -0
- package/src/version.js +1 -1
package/package.json
CHANGED
package/src/cli.js
CHANGED
|
@@ -1137,22 +1137,49 @@ async function doSquadCmd(argv) {
|
|
|
1137
1137
|
});
|
|
1138
1138
|
}
|
|
1139
1139
|
|
|
1140
|
-
// ── Link (
|
|
1140
|
+
// ── Link (one profile across machines) ───────────────────────────────────
|
|
1141
1141
|
//
|
|
1142
|
-
//
|
|
1143
|
-
//
|
|
1144
|
-
//
|
|
1145
|
-
//
|
|
1146
|
-
|
|
1147
|
-
|
|
1148
|
-
|
|
1149
|
-
|
|
1150
|
-
|
|
1151
|
-
|
|
1152
|
-
|
|
1142
|
+
// Two-sided by design — one verb owns the whole story:
|
|
1143
|
+
// claude-rpc link on your MAIN (verified) machine → mints a
|
|
1144
|
+
// one-time code, no browser needed
|
|
1145
|
+
// claude-rpc link <code> on the NEW machine → claims it, merging this
|
|
1146
|
+
// install into the same leaderboard identity
|
|
1147
|
+
// The browser fallback lives at claude-rpc.vercel.app/link (log in with
|
|
1148
|
+
// GitHub → same code) for when the other machine isn't handy. Claiming
|
|
1149
|
+
// verifies the profile (✓) and unlocks managing squads from the browser.
|
|
1150
|
+
|
|
1151
|
+
const LINK_PAGE = 'https://claude-rpc.vercel.app/link';
|
|
1152
|
+
|
|
1153
|
+
// Mint side: this machine asks the worker for a code. The worker only obliges
|
|
1154
|
+
// when this install's canonical profile is verified — the ✓ a claim grants
|
|
1155
|
+
// has to root in an already-proven identity.
|
|
1156
|
+
async function linkMint(ctx) {
|
|
1157
|
+
const r = await ctx.post('/pair/start', {});
|
|
1158
|
+
if (r.status === 403) {
|
|
1159
|
+
return fail('link codes come from a verified machine — this one isn\'t yet', {
|
|
1160
|
+
hint: `verify here first (claude-rpc profile verify), or mint in the browser: ${LINK_PAGE}`,
|
|
1161
|
+
code: EX_BAD_STATE,
|
|
1153
1162
|
});
|
|
1154
1163
|
}
|
|
1164
|
+
if (r.status !== 200 || !r.json?.code) {
|
|
1165
|
+
return fail(`could not mint a link code: ${r.json?.error || r.status}`, { code: EX_SYS_ERROR });
|
|
1166
|
+
}
|
|
1167
|
+
const mins = Math.round((r.json.expiresInSec || 600) / 60);
|
|
1168
|
+
console.log('');
|
|
1169
|
+
console.log(` ${c.green}✓${c.reset} link code: ${c.cyan}${c.bold}${r.json.code}${c.reset} ${c.dim}(expires in ${mins} min)${c.reset}`);
|
|
1170
|
+
console.log('');
|
|
1171
|
+
console.log(` ${c.dim}on the new machine:${c.reset}`);
|
|
1172
|
+
console.log(` npx claude-rpc@latest setup`);
|
|
1173
|
+
console.log(` ${c.cyan}claude-rpc link ${r.json.code}${c.reset}`);
|
|
1174
|
+
console.log('');
|
|
1175
|
+
console.log(` ${c.dim}one leaderboard profile — stats from every linked machine count as one${c.reset}`);
|
|
1176
|
+
console.log('');
|
|
1177
|
+
}
|
|
1178
|
+
|
|
1179
|
+
async function doLink(argv) {
|
|
1155
1180
|
const ctx = squadAuth();
|
|
1181
|
+
const code = (argv[0] || '').trim();
|
|
1182
|
+
if (!code) return linkMint(ctx);
|
|
1156
1183
|
// Make sure the profile row exists server-side before claiming — same
|
|
1157
1184
|
// pre-publish profileVerify does, so link works on a fresh `profile on`.
|
|
1158
1185
|
if (lb.profileIsPublishable(ctx.cfg.profile || {})) {
|
|
@@ -1162,14 +1189,19 @@ async function doLink(argv) {
|
|
|
1162
1189
|
const r = await ctx.post('/pair/claim', { code });
|
|
1163
1190
|
if (r.status !== 200) {
|
|
1164
1191
|
return fail(`link failed: ${r.json?.error || r.status}`,
|
|
1165
|
-
{ hint:
|
|
1192
|
+
{ hint: `get a fresh code: run \`claude-rpc link\` on your main machine, or ${LINK_PAGE}`, code: EX_SYS_ERROR });
|
|
1166
1193
|
}
|
|
1167
1194
|
// Mirror the verified identity locally so `profile status` agrees.
|
|
1168
1195
|
const userCfg = readJson(CONFIG_PATH, {});
|
|
1169
1196
|
userCfg.profile = { ...(userCfg.profile || {}), githubUser: r.json.githubUser, verified: true };
|
|
1170
1197
|
writeFileSync(CONFIG_PATH, JSON.stringify(userCfg, null, 2));
|
|
1171
1198
|
console.log(` ${c.green}✓${c.reset} linked as ${c.cyan}@${r.json.githubUser}${c.reset} — profile verified, squads unlocked in the browser`);
|
|
1172
|
-
|
|
1199
|
+
if (r.json.merged) {
|
|
1200
|
+
// This machine joined an existing identity: its stats now roll up under the
|
|
1201
|
+
// canonical handle, one board row across all your machines.
|
|
1202
|
+
console.log(` ${c.green}✓${c.reset} this machine now merges into ${c.cyan}@${r.json.handle}${c.reset} ${c.dim}— stats from all your machines count as one${c.reset}`);
|
|
1203
|
+
}
|
|
1204
|
+
console.log(` ${c.dim}started in a browser tab? it picks the link up automatically${c.reset}`);
|
|
1173
1205
|
}
|
|
1174
1206
|
|
|
1175
1207
|
// ── Community totals ─────────────────────────────────────────────────────
|
|
@@ -1318,7 +1350,7 @@ function profileNextStep() {
|
|
|
1318
1350
|
if (!next) {
|
|
1319
1351
|
console.log(` ${c.dim}→ all set — you're live at${c.reset} ${c.cyan}https://claude-rpc.vercel.app/u/${encodeURIComponent(p.handle)}${c.reset}`);
|
|
1320
1352
|
} else if (next.key === 'verify') {
|
|
1321
|
-
console.log(` ${c.dim}→ next:
|
|
1353
|
+
console.log(` ${c.dim}→ next: run${c.reset} ${c.cyan}claude-rpc link${c.reset} ${c.dim}on a machine that's already verified, then${c.reset} ${c.cyan}claude-rpc link <code>${c.reset} ${c.dim}here — first machine? ${LINK_PAGE}${c.reset}`);
|
|
1322
1354
|
} else {
|
|
1323
1355
|
console.log(` ${c.dim}→ next:${c.reset} ${c.cyan}${next.cmd}${c.reset} ${c.dim}(${next.label})${c.reset}`);
|
|
1324
1356
|
}
|
|
@@ -1361,12 +1393,12 @@ function profileStatus() {
|
|
|
1361
1393
|
: `${c.cyan}${s.cmd}${c.reset}${i === nextIdx ? ` ${c.dim}← next${c.reset}` : ''}`;
|
|
1362
1394
|
return `${mark} ${i + 1}. ${label}${' '.repeat(Math.max(1, 20 - s.label.length))}${tail}`;
|
|
1363
1395
|
});
|
|
1364
|
-
//
|
|
1396
|
+
// Link codes are the primary verify path; the gist dance stays available
|
|
1365
1397
|
// for terminals with no browser nearby.
|
|
1366
1398
|
if (!steps[2].done) {
|
|
1367
1399
|
lines.push('');
|
|
1368
|
-
lines.push(`${c.dim}the code comes from${c.reset} ${c.cyan}
|
|
1369
|
-
lines.push(`${c.dim}
|
|
1400
|
+
lines.push(`${c.dim}the code comes from${c.reset} ${c.cyan}claude-rpc link${c.reset} ${c.dim}on a machine you already verified${c.reset}`);
|
|
1401
|
+
lines.push(`${c.dim}first machine? log in at${c.reset} ${c.cyan}${LINK_PAGE}${c.reset} ${c.dim}— or no browser:${c.reset} ${c.cyan}claude-rpc profile verify${c.reset}`);
|
|
1370
1402
|
}
|
|
1371
1403
|
box('next steps', lines);
|
|
1372
1404
|
}
|
|
@@ -1699,7 +1731,7 @@ function help() {
|
|
|
1699
1731
|
['community', 'Opt in/out of anonymous community totals (on|off|status|report)'],
|
|
1700
1732
|
['profile', 'Public leaderboard identity (status|set|on|off|publish|verify)'],
|
|
1701
1733
|
['squad', 'Private mini-leaderboards with friends (create|join|leave|status)'],
|
|
1702
|
-
['link', '
|
|
1734
|
+
['link', 'Link machines into one profile (mints a code; `link <code>` claims it)'],
|
|
1703
1735
|
['doctor', 'Run a diagnostic checklist — common-failure triage (--fix to auto-repair)'],
|
|
1704
1736
|
['tail', 'Tail the daemon log file'],
|
|
1705
1737
|
['daemon', 'Run daemon in foreground (debug)'],
|
package/src/install.js
CHANGED
|
@@ -570,6 +570,7 @@ export function setupOutro(target, changed = true) {
|
|
|
570
570
|
if (IS_PACKAGED) point('start daemon', `"${target}" daemon`, 'also runs automatically at login');
|
|
571
571
|
else point('manage daemon', 'claude-rpc start · stop · status');
|
|
572
572
|
point('config', CONFIG_PATH, 'a working Discord app is bundled — set clientId only to use your own');
|
|
573
|
+
point('other machine?', 'claude-rpc link', 'run it there, claim the code here — one leaderboard profile');
|
|
573
574
|
console.log('');
|
|
574
575
|
}
|
|
575
576
|
|