buddydex 0.1.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/dist/buddydex.js +450 -0
- package/package.json +20 -0
package/dist/buddydex.js
ADDED
|
@@ -0,0 +1,450 @@
|
|
|
1
|
+
#!/usr/bin/env bun
|
|
2
|
+
// @bun
|
|
3
|
+
|
|
4
|
+
// packages/engine/src/constants.ts
|
|
5
|
+
var SPECIES = [
|
|
6
|
+
"duck",
|
|
7
|
+
"goose",
|
|
8
|
+
"blob",
|
|
9
|
+
"cat",
|
|
10
|
+
"dragon",
|
|
11
|
+
"octopus",
|
|
12
|
+
"owl",
|
|
13
|
+
"penguin",
|
|
14
|
+
"turtle",
|
|
15
|
+
"snail",
|
|
16
|
+
"ghost",
|
|
17
|
+
"axolotl",
|
|
18
|
+
"capybara",
|
|
19
|
+
"cactus",
|
|
20
|
+
"robot",
|
|
21
|
+
"rabbit",
|
|
22
|
+
"mushroom",
|
|
23
|
+
"chonk"
|
|
24
|
+
];
|
|
25
|
+
var RARITIES = ["common", "uncommon", "rare", "epic", "legendary"];
|
|
26
|
+
var RARITY_WEIGHTS = [60, 25, 10, 4, 1];
|
|
27
|
+
var EYES = ["\xB7", "\u2726", "\xD7", "\u25C9", "@", "\xB0"];
|
|
28
|
+
var HATS = ["none", "crown", "tophat", "propeller", "halo", "wizard", "beanie", "tinyduck"];
|
|
29
|
+
var STAT_FLOORS = { common: 5, uncommon: 15, rare: 25, epic: 35, legendary: 50 };
|
|
30
|
+
var STAT_NAMES = ["debugging", "patience", "chaos", "wisdom", "snark"];
|
|
31
|
+
var SALT = "friend-2026-401";
|
|
32
|
+
|
|
33
|
+
// packages/cli/commands/hunt.ts
|
|
34
|
+
import { parseArgs } from "util";
|
|
35
|
+
|
|
36
|
+
// packages/engine/src/hash.ts
|
|
37
|
+
var _wyhashSync = null;
|
|
38
|
+
var _encoder = new TextEncoder;
|
|
39
|
+
function wyhashFallback(str) {
|
|
40
|
+
const buf = _encoder.encode(str);
|
|
41
|
+
const raw = _wyhashSync(buf, 0n);
|
|
42
|
+
return Number(BigInt.asUintN(64, raw) & 0xffffffffn);
|
|
43
|
+
}
|
|
44
|
+
function hashString(str) {
|
|
45
|
+
if (typeof globalThis.Bun !== "undefined") {
|
|
46
|
+
return Number(BigInt(Bun.hash(str)) & 0xffffffffn);
|
|
47
|
+
}
|
|
48
|
+
if (!_wyhashSync) {
|
|
49
|
+
throw new Error("Hash not initialized. Call initHash() first.");
|
|
50
|
+
}
|
|
51
|
+
return wyhashFallback(str);
|
|
52
|
+
}
|
|
53
|
+
// packages/engine/src/prng.ts
|
|
54
|
+
class Mulberry32 {
|
|
55
|
+
state;
|
|
56
|
+
constructor(seed) {
|
|
57
|
+
this.state = seed >>> 0;
|
|
58
|
+
}
|
|
59
|
+
nextU32() {
|
|
60
|
+
this.state = this.state + 1831565813 >>> 0;
|
|
61
|
+
let t = (this.state ^ this.state >>> 15) >>> 0;
|
|
62
|
+
t = Math.imul(t, 1 | this.state) >>> 0;
|
|
63
|
+
t = t + (Math.imul((t ^ t >>> 7) >>> 0, 61 | t) >>> 0) ^ t;
|
|
64
|
+
return (t ^ t >>> 14) >>> 0;
|
|
65
|
+
}
|
|
66
|
+
nextF64() {
|
|
67
|
+
return this.nextU32() / 4294967296;
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
// packages/engine/src/roll.ts
|
|
71
|
+
function rollBones(userId) {
|
|
72
|
+
const seed = hashString(userId + SALT);
|
|
73
|
+
const rng = new Mulberry32(seed);
|
|
74
|
+
let roll = rng.nextF64() * 100;
|
|
75
|
+
let rarity = "common";
|
|
76
|
+
for (let i = 0;i < RARITY_WEIGHTS.length; i++) {
|
|
77
|
+
roll -= RARITY_WEIGHTS[i];
|
|
78
|
+
if (roll < 0) {
|
|
79
|
+
rarity = RARITIES[i];
|
|
80
|
+
break;
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
const species = SPECIES[Math.floor(rng.nextF64() * SPECIES.length) % SPECIES.length];
|
|
84
|
+
const eye = EYES[Math.floor(rng.nextF64() * EYES.length) % EYES.length];
|
|
85
|
+
const hat = rarity === "common" ? "none" : HATS[Math.floor(rng.nextF64() * HATS.length) % HATS.length];
|
|
86
|
+
const shiny = rng.nextF64() < 0.01;
|
|
87
|
+
const floor = STAT_FLOORS[rarity];
|
|
88
|
+
const peakIdx = Math.floor(rng.nextF64() * 5) % 5;
|
|
89
|
+
let dumpIdx = Math.floor(rng.nextF64() * 5) % 5;
|
|
90
|
+
if (dumpIdx === peakIdx)
|
|
91
|
+
dumpIdx = (dumpIdx + 1) % 5;
|
|
92
|
+
const stats = {};
|
|
93
|
+
for (let i = 0;i < 5; i++) {
|
|
94
|
+
const name = STAT_NAMES[i];
|
|
95
|
+
if (i === peakIdx) {
|
|
96
|
+
stats[name] = Math.min(100, Math.floor(floor + 50 + rng.nextF64() * 30));
|
|
97
|
+
} else if (i === dumpIdx) {
|
|
98
|
+
stats[name] = Math.max(1, Math.floor(floor - 10 + rng.nextF64() * 15));
|
|
99
|
+
} else {
|
|
100
|
+
stats[name] = Math.floor(floor + rng.nextF64() * 40);
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
const totalStats = Object.values(stats).reduce((a, b) => a + b, 0);
|
|
104
|
+
return { rarity, species, eye, hat, shiny, stats, totalStats };
|
|
105
|
+
}
|
|
106
|
+
// packages/engine/src/uuid.ts
|
|
107
|
+
function generateUuid() {
|
|
108
|
+
const hex = () => Math.floor(Math.random() * 16).toString(16);
|
|
109
|
+
const h = (n) => Array.from({ length: n }, hex).join("");
|
|
110
|
+
return `${h(8)}-${h(4)}-${h(4)}-${h(4)}-${h(12)}`;
|
|
111
|
+
}
|
|
112
|
+
// packages/cli/lib/format.ts
|
|
113
|
+
var isBun = typeof Bun !== "undefined";
|
|
114
|
+
function printHeader(hashMode) {
|
|
115
|
+
const effectiveHash = hashMode === "fnv1a" ? "FNV-1a (forced)" : isBun ? "Bun.hash (Wyhash)" : "Wyhash (WASM)";
|
|
116
|
+
console.log(`
|
|
117
|
+
BuddyDex`);
|
|
118
|
+
console.log(` Runtime: ${isBun ? "Bun" : "Node.js"} Hash: ${effectiveHash}`);
|
|
119
|
+
}
|
|
120
|
+
function printBuddy(label, bones, userId) {
|
|
121
|
+
const shinyTag = bones.shiny ? " SHINY" : "";
|
|
122
|
+
const statBar = STAT_NAMES.map((s) => `${s.slice(0, 3).toUpperCase()}:${bones.stats[s]}`).join(" ");
|
|
123
|
+
console.log(`
|
|
124
|
+
${label}`);
|
|
125
|
+
if (userId) {
|
|
126
|
+
const display = userId.length > 24 ? userId.slice(0, 12) + "..." : userId;
|
|
127
|
+
console.log(` ID: ${display}`);
|
|
128
|
+
}
|
|
129
|
+
console.log(` Result: ${bones.rarity.toUpperCase()} ${bones.species}${shinyTag}`);
|
|
130
|
+
console.log(` Eye: ${bones.eye} Hat: ${bones.hat} Total: ${bones.totalStats}`);
|
|
131
|
+
console.log(` Stats: ${statBar}`);
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
// packages/cli/commands/hunt.ts
|
|
135
|
+
function cmdHunt(argv) {
|
|
136
|
+
const { values: args } = parseArgs({
|
|
137
|
+
args: argv,
|
|
138
|
+
options: {
|
|
139
|
+
species: { type: "string" },
|
|
140
|
+
rarity: { type: "string" },
|
|
141
|
+
shiny: { type: "boolean", default: false },
|
|
142
|
+
"min-stat": { type: "string" },
|
|
143
|
+
"min-total": { type: "string" },
|
|
144
|
+
perfect: { type: "string" },
|
|
145
|
+
tries: { type: "string", default: "1000000" },
|
|
146
|
+
limit: { type: "string", default: "10" }
|
|
147
|
+
}
|
|
148
|
+
});
|
|
149
|
+
const maxTries = parseInt(args.tries);
|
|
150
|
+
const maxResults = parseInt(args.limit);
|
|
151
|
+
const wantSpecies = args.species?.toLowerCase();
|
|
152
|
+
const wantRarity = args.rarity?.toLowerCase();
|
|
153
|
+
const wantShiny = args.shiny;
|
|
154
|
+
const wantMinStat = args["min-stat"]?.split(":");
|
|
155
|
+
const wantMinTotal = args["min-total"] ? parseInt(args["min-total"]) : null;
|
|
156
|
+
const wantPerfect = args.perfect ? parseInt(args.perfect) : null;
|
|
157
|
+
if (wantSpecies && !SPECIES.includes(wantSpecies)) {
|
|
158
|
+
console.error(`Unknown species: ${wantSpecies}
|
|
159
|
+
Valid: ${SPECIES.join(", ")}`);
|
|
160
|
+
process.exit(1);
|
|
161
|
+
}
|
|
162
|
+
if (wantRarity && !RARITIES.includes(wantRarity)) {
|
|
163
|
+
console.error(`Unknown rarity: ${wantRarity}
|
|
164
|
+
Valid: ${RARITIES.join(", ")}`);
|
|
165
|
+
process.exit(1);
|
|
166
|
+
}
|
|
167
|
+
printHeader();
|
|
168
|
+
const filters = [
|
|
169
|
+
`species=${wantSpecies || "any"}`,
|
|
170
|
+
`rarity=${wantRarity || "any"}`,
|
|
171
|
+
`shiny=${wantShiny}`,
|
|
172
|
+
wantMinStat ? `min-stat=${args["min-stat"]}` : null,
|
|
173
|
+
wantMinTotal ? `min-total=${wantMinTotal}` : null,
|
|
174
|
+
wantPerfect ? `perfect=${wantPerfect}` : null
|
|
175
|
+
].filter(Boolean).join(" ");
|
|
176
|
+
console.log(`
|
|
177
|
+
Filters: ${filters}`);
|
|
178
|
+
console.log(` Trying ${maxTries.toLocaleString()} random UUIDs, showing up to ${maxResults} results.
|
|
179
|
+
`);
|
|
180
|
+
const results = [];
|
|
181
|
+
const startTime = Date.now();
|
|
182
|
+
for (let i = 0;i < maxTries && results.length < maxResults; i++) {
|
|
183
|
+
const fakeId = generateUuid();
|
|
184
|
+
const bones = rollBones(fakeId);
|
|
185
|
+
if (wantSpecies && bones.species !== wantSpecies)
|
|
186
|
+
continue;
|
|
187
|
+
if (wantRarity && bones.rarity !== wantRarity)
|
|
188
|
+
continue;
|
|
189
|
+
if (wantShiny && !bones.shiny)
|
|
190
|
+
continue;
|
|
191
|
+
if (wantMinStat) {
|
|
192
|
+
const [statName, minVal] = wantMinStat;
|
|
193
|
+
if (!bones.stats[statName] || bones.stats[statName] < parseInt(minVal))
|
|
194
|
+
continue;
|
|
195
|
+
}
|
|
196
|
+
if (wantMinTotal && bones.totalStats < wantMinTotal)
|
|
197
|
+
continue;
|
|
198
|
+
if (wantPerfect && !STAT_NAMES.every((s) => bones.stats[s] >= wantPerfect))
|
|
199
|
+
continue;
|
|
200
|
+
results.push({ fakeId, ...bones });
|
|
201
|
+
}
|
|
202
|
+
const elapsed = ((Date.now() - startTime) / 1000).toFixed(2);
|
|
203
|
+
if (results.length === 0) {
|
|
204
|
+
console.log(` No matches found in ${maxTries.toLocaleString()} tries (${elapsed}s).`);
|
|
205
|
+
console.log(` Try increasing --tries or relaxing filters.
|
|
206
|
+
`);
|
|
207
|
+
} else {
|
|
208
|
+
console.log(` Found ${results.length} match(es) in ${elapsed}s:
|
|
209
|
+
`);
|
|
210
|
+
for (const r of results) {
|
|
211
|
+
const shinyTag = r.shiny ? " SHINY" : "";
|
|
212
|
+
const statBar = STAT_NAMES.map((s) => `${s.slice(0, 3).toUpperCase()}:${r.stats[s]}`).join(" ");
|
|
213
|
+
console.log(` ${r.rarity.toUpperCase()} ${r.species}${shinyTag} [${r.eye}] hat:${r.hat} total:${r.totalStats}`);
|
|
214
|
+
console.log(` Stats: ${statBar}`);
|
|
215
|
+
console.log(` Seed: ${r.fakeId}`);
|
|
216
|
+
console.log();
|
|
217
|
+
}
|
|
218
|
+
console.log(` To inject: buddydex inject <seed>
|
|
219
|
+
`);
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
// packages/cli/commands/inject.ts
|
|
224
|
+
import { parseArgs as parseArgs2 } from "util";
|
|
225
|
+
|
|
226
|
+
// packages/cli/lib/config.ts
|
|
227
|
+
import { readFileSync, writeFileSync, existsSync, mkdirSync } from "fs";
|
|
228
|
+
import { homedir } from "os";
|
|
229
|
+
import { join, dirname } from "path";
|
|
230
|
+
var CONFIG_PATH = join(homedir(), ".claude.json");
|
|
231
|
+
var BACKUP_PATH = join(homedir(), ".claude", "buddy-backup.json");
|
|
232
|
+
function readJson(path) {
|
|
233
|
+
try {
|
|
234
|
+
return JSON.parse(readFileSync(path, "utf-8"));
|
|
235
|
+
} catch {
|
|
236
|
+
return null;
|
|
237
|
+
}
|
|
238
|
+
}
|
|
239
|
+
function isValidUuid(str) {
|
|
240
|
+
return /^[0-9a-f]{32}$/i.test(str.replace(/-/g, ""));
|
|
241
|
+
}
|
|
242
|
+
function getRealUserId() {
|
|
243
|
+
const backup = readJson(BACKUP_PATH);
|
|
244
|
+
if (backup?.originalAccountUuid)
|
|
245
|
+
return backup.originalAccountUuid;
|
|
246
|
+
if (backup?.originalUserID)
|
|
247
|
+
return backup.originalUserID;
|
|
248
|
+
const config = readJson(CONFIG_PATH);
|
|
249
|
+
return config?.oauthAccount?.accountUuid ?? config?.userID ?? "anon";
|
|
250
|
+
}
|
|
251
|
+
function getEffectiveUserId() {
|
|
252
|
+
const config = readJson(CONFIG_PATH);
|
|
253
|
+
return config?.oauthAccount?.accountUuid ?? config?.userID ?? "anon";
|
|
254
|
+
}
|
|
255
|
+
function backup(config) {
|
|
256
|
+
if (existsSync(BACKUP_PATH))
|
|
257
|
+
return;
|
|
258
|
+
const dir = dirname(BACKUP_PATH);
|
|
259
|
+
if (!existsSync(dir))
|
|
260
|
+
mkdirSync(dir, { recursive: true });
|
|
261
|
+
writeFileSync(BACKUP_PATH, JSON.stringify({
|
|
262
|
+
originalAccountUuid: config.oauthAccount?.accountUuid || null,
|
|
263
|
+
originalUserID: config.userID || null,
|
|
264
|
+
backedUpAt: new Date().toISOString()
|
|
265
|
+
}, null, 2) + `
|
|
266
|
+
`);
|
|
267
|
+
}
|
|
268
|
+
function writeConfig(config) {
|
|
269
|
+
writeFileSync(CONFIG_PATH, JSON.stringify(config, null, 2) + `
|
|
270
|
+
`);
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
// packages/cli/commands/inject.ts
|
|
274
|
+
function cmdInject(argv) {
|
|
275
|
+
const { values: args, positionals } = parseArgs2({
|
|
276
|
+
args: argv,
|
|
277
|
+
options: { preview: { type: "boolean", default: false } },
|
|
278
|
+
allowPositionals: true
|
|
279
|
+
});
|
|
280
|
+
const seed = positionals[0];
|
|
281
|
+
if (!seed) {
|
|
282
|
+
console.error(`
|
|
283
|
+
Usage: buddydex inject <seed> [--preview]
|
|
284
|
+
`);
|
|
285
|
+
process.exit(1);
|
|
286
|
+
}
|
|
287
|
+
const config = readJson(CONFIG_PATH);
|
|
288
|
+
if (!config) {
|
|
289
|
+
console.error(`
|
|
290
|
+
Cannot read ${CONFIG_PATH}
|
|
291
|
+
`);
|
|
292
|
+
process.exit(1);
|
|
293
|
+
}
|
|
294
|
+
const isOAuth = !!config.oauthAccount?.accountUuid;
|
|
295
|
+
printHeader();
|
|
296
|
+
console.log(` Auth: ${isOAuth ? "OAuth (accountUuid)" : "Legacy (userID)"}`);
|
|
297
|
+
if (isOAuth && !isValidUuid(seed)) {
|
|
298
|
+
console.error(`
|
|
299
|
+
ERROR: Seed "${seed}" is not a valid UUID.`);
|
|
300
|
+
console.error(` The binary expects 32 hex chars. Non-UUID values crash on launch.
|
|
301
|
+
`);
|
|
302
|
+
process.exit(1);
|
|
303
|
+
}
|
|
304
|
+
const bones = rollBones(seed);
|
|
305
|
+
printBuddy("New buddy:", bones, seed);
|
|
306
|
+
if (args.preview) {
|
|
307
|
+
console.log(`
|
|
308
|
+
(preview only)
|
|
309
|
+
`);
|
|
310
|
+
process.exit(0);
|
|
311
|
+
}
|
|
312
|
+
backup(config);
|
|
313
|
+
if (isOAuth) {
|
|
314
|
+
config.oauthAccount.accountUuid = seed;
|
|
315
|
+
console.log(`
|
|
316
|
+
Spoofed oauthAccount.accountUuid`);
|
|
317
|
+
} else {
|
|
318
|
+
config.userID = seed;
|
|
319
|
+
console.log(`
|
|
320
|
+
Spoofed userID`);
|
|
321
|
+
}
|
|
322
|
+
delete config.companion;
|
|
323
|
+
writeConfig(config);
|
|
324
|
+
console.log(` Companion soul cleared.`);
|
|
325
|
+
console.log(`
|
|
326
|
+
Restart Claude Code to meet your new buddy!`);
|
|
327
|
+
console.log(` Run: buddydex restore
|
|
328
|
+
`);
|
|
329
|
+
}
|
|
330
|
+
|
|
331
|
+
// packages/cli/commands/restore.ts
|
|
332
|
+
import { existsSync as existsSync2 } from "fs";
|
|
333
|
+
function cmdRestore() {
|
|
334
|
+
if (!existsSync2(BACKUP_PATH)) {
|
|
335
|
+
console.error(`
|
|
336
|
+
No backup found at ${BACKUP_PATH}
|
|
337
|
+
`);
|
|
338
|
+
process.exit(1);
|
|
339
|
+
}
|
|
340
|
+
const bk = readJson(BACKUP_PATH);
|
|
341
|
+
const config = readJson(CONFIG_PATH);
|
|
342
|
+
if (!config) {
|
|
343
|
+
console.error(`
|
|
344
|
+
Cannot read ${CONFIG_PATH}
|
|
345
|
+
`);
|
|
346
|
+
process.exit(1);
|
|
347
|
+
}
|
|
348
|
+
printHeader();
|
|
349
|
+
if (bk?.originalAccountUuid && config.oauthAccount) {
|
|
350
|
+
config.oauthAccount.accountUuid = bk.originalAccountUuid;
|
|
351
|
+
console.log(`
|
|
352
|
+
Restored oauthAccount.accountUuid`);
|
|
353
|
+
}
|
|
354
|
+
if (bk?.originalUserID) {
|
|
355
|
+
config.userID = bk.originalUserID;
|
|
356
|
+
console.log(` Restored userID`);
|
|
357
|
+
}
|
|
358
|
+
delete config.companion;
|
|
359
|
+
writeConfig(config);
|
|
360
|
+
const restoredId = getEffectiveUserId();
|
|
361
|
+
const bones = rollBones(restoredId);
|
|
362
|
+
printBuddy("Restored buddy:", bones, restoredId);
|
|
363
|
+
console.log(`
|
|
364
|
+
Restart Claude Code to get your original buddy back.
|
|
365
|
+
`);
|
|
366
|
+
}
|
|
367
|
+
|
|
368
|
+
// packages/cli/commands/show.ts
|
|
369
|
+
function cmdShow() {
|
|
370
|
+
printHeader();
|
|
371
|
+
const realId = getRealUserId();
|
|
372
|
+
const effectiveId = getEffectiveUserId();
|
|
373
|
+
const realBones = rollBones(realId);
|
|
374
|
+
printBuddy("Your buddy:", realBones, realId);
|
|
375
|
+
if (effectiveId !== realId) {
|
|
376
|
+
const currentBones = rollBones(effectiveId);
|
|
377
|
+
printBuddy("Currently active (spoofed):", currentBones, effectiveId);
|
|
378
|
+
}
|
|
379
|
+
console.log();
|
|
380
|
+
}
|
|
381
|
+
|
|
382
|
+
// packages/cli/commands/roll.ts
|
|
383
|
+
import { parseArgs as parseArgs3 } from "util";
|
|
384
|
+
function cmdRoll(argv) {
|
|
385
|
+
const { positionals } = parseArgs3({
|
|
386
|
+
args: argv,
|
|
387
|
+
options: {},
|
|
388
|
+
allowPositionals: true
|
|
389
|
+
});
|
|
390
|
+
const userId = positionals[0];
|
|
391
|
+
if (!userId) {
|
|
392
|
+
console.error(`
|
|
393
|
+
Usage: buddydex roll <uuid>
|
|
394
|
+
`);
|
|
395
|
+
process.exit(1);
|
|
396
|
+
}
|
|
397
|
+
printHeader();
|
|
398
|
+
const bones = rollBones(userId);
|
|
399
|
+
printBuddy("Roll result:", bones, userId);
|
|
400
|
+
console.log();
|
|
401
|
+
}
|
|
402
|
+
|
|
403
|
+
// packages/cli/bin.ts
|
|
404
|
+
var USAGE = `
|
|
405
|
+
BuddyDex CLI
|
|
406
|
+
|
|
407
|
+
Commands:
|
|
408
|
+
hunt Search for buddies matching filters
|
|
409
|
+
inject Inject a seed UUID into ~/.claude.json
|
|
410
|
+
restore Restore your original UUID from backup
|
|
411
|
+
show Show your current buddy
|
|
412
|
+
roll Roll a specific UUID to see its buddy
|
|
413
|
+
|
|
414
|
+
Hunt options:
|
|
415
|
+
--species <name> Filter by species
|
|
416
|
+
--rarity <level> Filter by rarity (${RARITIES.join(", ")})
|
|
417
|
+
--shiny Only shiny buddies
|
|
418
|
+
--min-stat <name:val> Min value for a stat (e.g. chaos:80)
|
|
419
|
+
--min-total <val> Min total stat points (e.g. 400)
|
|
420
|
+
--perfect <val> ALL stats >= this value (e.g. 70)
|
|
421
|
+
--tries <n> UUIDs to try (default: 1000000)
|
|
422
|
+
--limit <n> Max results (default: 10)
|
|
423
|
+
|
|
424
|
+
Inject options:
|
|
425
|
+
--preview Preview without saving
|
|
426
|
+
|
|
427
|
+
Examples:
|
|
428
|
+
buddydex hunt --species dragon --rarity legendary
|
|
429
|
+
buddydex hunt --rarity legendary --perfect 70
|
|
430
|
+
buddydex inject <seed>
|
|
431
|
+
buddydex show
|
|
432
|
+
`;
|
|
433
|
+
var [command, ...rest] = process.argv.slice(2);
|
|
434
|
+
var commands = {
|
|
435
|
+
hunt: cmdHunt,
|
|
436
|
+
inject: cmdInject,
|
|
437
|
+
restore: cmdRestore,
|
|
438
|
+
show: cmdShow,
|
|
439
|
+
roll: cmdRoll
|
|
440
|
+
};
|
|
441
|
+
if (command && command in commands) {
|
|
442
|
+
commands[command](rest);
|
|
443
|
+
} else {
|
|
444
|
+
console.log(USAGE);
|
|
445
|
+
if (command && command !== "--help" && command !== "-h") {
|
|
446
|
+
console.error(` Unknown command: ${command}
|
|
447
|
+
`);
|
|
448
|
+
process.exit(1);
|
|
449
|
+
}
|
|
450
|
+
}
|
package/package.json
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "buddydex",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Hunt, browse, and inject Claude Code buddies",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"bin": {
|
|
7
|
+
"buddydex": "dist/buddydex.js"
|
|
8
|
+
},
|
|
9
|
+
"files": ["dist"],
|
|
10
|
+
"keywords": ["claude", "claude-code", "buddy", "companion", "wyhash"],
|
|
11
|
+
"author": "iammatthias",
|
|
12
|
+
"license": "MIT",
|
|
13
|
+
"repository": {
|
|
14
|
+
"type": "git",
|
|
15
|
+
"url": "git+https://github.com/iammatthias/buddydex.git"
|
|
16
|
+
},
|
|
17
|
+
"dependencies": {
|
|
18
|
+
"@buddy/engine": "workspace:*"
|
|
19
|
+
}
|
|
20
|
+
}
|