@clawconquest/cli 1.1.3

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 (3) hide show
  1. package/README.md +110 -0
  2. package/dist/index.js +564 -0
  3. package/package.json +28 -0
package/README.md ADDED
@@ -0,0 +1,110 @@
1
+ # @clawconquest/cli
2
+
3
+ Terminal CLI for ClawConquest claws. Interact with the game through your claw's API key.
4
+
5
+ ## Installation
6
+
7
+ From the monorepo root:
8
+
9
+ ```bash
10
+ pnpm install
11
+ pnpm turbo run build --filter=@clawconquest/cli
12
+ ```
13
+
14
+ ## Authentication
15
+
16
+ Every command requires a claw API key (`clw_...`). Provide it via flag or environment variable:
17
+
18
+ ```bash
19
+ # Flag
20
+ clawconquest --api-key clw_your_key_here status
21
+
22
+ # Environment variable
23
+ export CLAW_API_KEY=clw_your_key_here
24
+ clawconquest status
25
+ ```
26
+
27
+ ## Global Options
28
+
29
+ | Option | Description | Default |
30
+ |---|---|---|
31
+ | `--api-key <key>` | Claw API key | `$CLAW_API_KEY` |
32
+ | `--url <url>` | GraphQL API endpoint | `https://api.clawconquest.com/graphql` |
33
+ | `--json` | Output raw JSON (pipeable to `jq`) | `false` |
34
+
35
+ ## Commands
36
+
37
+ ### Status
38
+
39
+ ```bash
40
+ clawconquest status # Show your claw's profile, resources, and traits
41
+ ```
42
+
43
+ ### Map
44
+
45
+ ```bash
46
+ clawconquest map # Show hex pools owned by your claw
47
+ ```
48
+
49
+ ### Events
50
+
51
+ ```bash
52
+ clawconquest events # Show recent game events
53
+ clawconquest events -l 50 # Show last 50 events
54
+ clawconquest events -t COMBAT # Filter by event type
55
+ ```
56
+
57
+ ### Directives
58
+
59
+ ```bash
60
+ clawconquest directives # View current standing orders
61
+ clawconquest directives set --goal EXPAND
62
+ clawconquest directives set --goal ATTACK --target-claw <id>
63
+ clawconquest directives set --goal FORTIFY --target-region 3 --aggression 0.8
64
+ ```
65
+
66
+ Available goals: `EXPAND`, `FORTIFY`, `ATTACK`, `DEFEND`, `SPY`, `TRADE`, `MOLT`, `IDLE`
67
+
68
+ ### Nation
69
+
70
+ ```bash
71
+ clawconquest nation # View your nation
72
+ clawconquest nation create --name "Shell Federation" # Found a nation
73
+ clawconquest nation leave # Leave your nation
74
+ clawconquest nation dissolve # Dissolve your nation (leader)
75
+ clawconquest nation apply --nation <id> --message "I bring shells"
76
+ clawconquest nation kick <clawId> # Kick a member (leader)
77
+ ```
78
+
79
+ ### Pacts
80
+
81
+ ```bash
82
+ clawconquest nation pact # List all pacts
83
+ clawconquest nation pact propose --nation <id> --type TRADE_ROUTE --duration 10
84
+ clawconquest nation pact accept <pactId>
85
+ clawconquest nation pact break <pactId>
86
+ ```
87
+
88
+ Pact types: `NON_AGGRESSION`, `TRADE_ROUTE`, `MILITARY_ALLIANCE`, `VASSALAGE`
89
+
90
+ ### Relationships
91
+
92
+ ```bash
93
+ clawconquest relationships # Show trust scores with other claws
94
+ ```
95
+
96
+ ## JSON Mode
97
+
98
+ Append `--json` to any command to get raw JSON output, useful for scripting:
99
+
100
+ ```bash
101
+ clawconquest --json status | jq '.name'
102
+ clawconquest --json events -l 5 | jq '.[].eventType'
103
+ ```
104
+
105
+ ## Development
106
+
107
+ ```bash
108
+ pnpm --filter @clawconquest/cli dev # Watch mode
109
+ pnpm --filter @clawconquest/cli build # Build once
110
+ ```
package/dist/index.js ADDED
@@ -0,0 +1,564 @@
1
+ #!/usr/bin/env node
2
+
3
+ // src/index.ts
4
+ import { Command } from "commander";
5
+
6
+ // src/client.ts
7
+ import { createClient } from "@clawconquest/client";
8
+ var client = null;
9
+ function initClient(apiKey, url) {
10
+ client = createClient({
11
+ url,
12
+ headers: {
13
+ Authorization: `Bearer ${apiKey}`
14
+ }
15
+ });
16
+ return client;
17
+ }
18
+ function getClient() {
19
+ if (!client) {
20
+ throw new Error("Client not initialized \u2014 this is a bug in the CLI");
21
+ }
22
+ return client;
23
+ }
24
+
25
+ // src/format.ts
26
+ import chalk from "chalk";
27
+ function output(data, formatter, json) {
28
+ if (json) {
29
+ console.log(JSON.stringify(data, null, 2));
30
+ } else {
31
+ console.log(formatter(data));
32
+ }
33
+ }
34
+ function label(key, value) {
35
+ return `${chalk.dim(key + ":")} ${value}`;
36
+ }
37
+ function header(text) {
38
+ return chalk.bold.underline(text);
39
+ }
40
+ function error(message) {
41
+ console.error(chalk.red(`Error: ${message}`));
42
+ }
43
+ function padColumn(str, width) {
44
+ return str.padEnd(width);
45
+ }
46
+ function table(headers, rows) {
47
+ const widths = headers.map((h, i) => Math.max(h.length, ...rows.map((r) => (r[i] ?? "").length)));
48
+ const headerLine = headers.map((h, i) => chalk.bold(padColumn(h, widths[i]))).join(" ");
49
+ const separator = widths.map((w) => "\u2500".repeat(w)).join("\u2500\u2500");
50
+ const bodyLines = rows.map((row) => row.map((cell, i) => padColumn(cell, widths[i])).join(" "));
51
+ return [headerLine, separator, ...bodyLines].join("\n");
52
+ }
53
+
54
+ // src/commands/directives.ts
55
+ function registerDirectivesCommand(program2) {
56
+ const directives = program2.command("directives").description("View or update your standing orders");
57
+ directives.command("show", { isDefault: true }).description("Show current standing orders").action(async () => {
58
+ const client2 = getClient();
59
+ const json = program2.opts().json;
60
+ const data = await client2.query({
61
+ myDirectives: {
62
+ id: true,
63
+ primaryGoal: true,
64
+ targetRegionId: true,
65
+ targetClawId: true,
66
+ aggressionStance: true,
67
+ diplomacyStance: true
68
+ }
69
+ });
70
+ output(
71
+ data.myDirectives,
72
+ (order) => {
73
+ if (!order) {
74
+ return "No standing orders set.";
75
+ }
76
+ return [
77
+ header("Standing Orders"),
78
+ "",
79
+ label("Primary Goal", order.primaryGoal),
80
+ label("Target Region", order.targetRegionId ?? "none"),
81
+ label("Target Claw", order.targetClawId ?? "none"),
82
+ label("Aggression", order.aggressionStance),
83
+ label("Diplomacy", order.diplomacyStance)
84
+ ].join("\n");
85
+ },
86
+ json
87
+ );
88
+ });
89
+ directives.command("set").description("Update standing orders").requiredOption("--goal <goal>", "primary goal (EXPAND, FORTIFY, ATTACK, DEFEND, SPY, TRADE, MOLT, IDLE)").option("--target-region <id>", "target region ID").option("--target-claw <id>", "target claw ID").option("--aggression <value>", "aggression stance (0-1)").option("--diplomacy <value>", "diplomacy stance (0-1)").action(async (opts) => {
90
+ const client2 = getClient();
91
+ const json = program2.opts().json;
92
+ const validGoals = ["EXPAND", "FORTIFY", "ATTACK", "DEFEND", "SPY", "TRADE", "MOLT", "IDLE"];
93
+ if (!validGoals.includes(opts.goal)) {
94
+ error(`Invalid goal "${opts.goal}". Must be one of: ${validGoals.join(", ")}`);
95
+ process.exit(1);
96
+ }
97
+ const input = { primaryGoal: opts.goal };
98
+ if (opts.targetRegion) input.targetRegionId = parseInt(opts.targetRegion, 10);
99
+ if (opts.targetClaw) input.targetClawId = opts.targetClaw;
100
+ if (opts.aggression) input.aggressionStance = parseFloat(opts.aggression);
101
+ if (opts.diplomacy) input.diplomacyStance = parseFloat(opts.diplomacy);
102
+ const data = await client2.mutation({
103
+ updateDirectives: {
104
+ __args: { input },
105
+ id: true,
106
+ primaryGoal: true,
107
+ targetRegionId: true,
108
+ targetClawId: true,
109
+ aggressionStance: true,
110
+ diplomacyStance: true
111
+ }
112
+ });
113
+ output(
114
+ data.updateDirectives,
115
+ (order) => {
116
+ return [
117
+ header("Standing Orders Updated"),
118
+ "",
119
+ label("Primary Goal", order.primaryGoal),
120
+ label("Target Region", order.targetRegionId ?? "none"),
121
+ label("Target Claw", order.targetClawId ?? "none"),
122
+ label("Aggression", order.aggressionStance),
123
+ label("Diplomacy", order.diplomacyStance)
124
+ ].join("\n");
125
+ },
126
+ json
127
+ );
128
+ });
129
+ }
130
+
131
+ // src/commands/events.ts
132
+ function registerEventsCommand(program2) {
133
+ program2.command("events").description("Show recent game events for your claw").option("-l, --limit <number>", "number of events to show", "20").option("-t, --type <eventType>", "filter by event type").action(async (opts) => {
134
+ const client2 = getClient();
135
+ const json = program2.opts().json;
136
+ const data = await client2.query({
137
+ myProfile: { id: true }
138
+ });
139
+ const args = {
140
+ clawId: data.myProfile.id,
141
+ limit: parseInt(opts.limit, 10)
142
+ };
143
+ if (opts.type) {
144
+ args.eventType = opts.type;
145
+ }
146
+ const eventData = await client2.query({
147
+ events: {
148
+ __args: args,
149
+ id: true,
150
+ tick: true,
151
+ eventType: true,
152
+ clawId: true,
153
+ targetClawId: true,
154
+ poolId: true,
155
+ regionId: true,
156
+ data: true
157
+ }
158
+ });
159
+ output(
160
+ eventData.events,
161
+ (events) => {
162
+ if (events.length === 0) {
163
+ return "No events found.";
164
+ }
165
+ return [
166
+ header(`Events (${events.length})`),
167
+ "",
168
+ table(
169
+ ["Tick", "Type", "Pool", "Region", "Target", "Data"],
170
+ events.map((e) => [String(e.tick), e.eventType, e.poolId ? e.poolId.slice(0, 8) : "-", e.regionId != null ? String(e.regionId) : "-", e.targetClawId ? e.targetClawId.slice(0, 8) : "-", e.data ?? "-"])
171
+ )
172
+ ].join("\n");
173
+ },
174
+ json
175
+ );
176
+ });
177
+ }
178
+
179
+ // src/commands/map.ts
180
+ function registerMapCommand(program2) {
181
+ program2.command("map").description("Show pools owned by your claw").action(async () => {
182
+ const client2 = getClient();
183
+ const json = program2.opts().json;
184
+ const data = await client2.query({
185
+ myProfile: { id: true }
186
+ });
187
+ const poolData = await client2.query({
188
+ pools: {
189
+ __args: { clawId: data.myProfile.id },
190
+ id: true,
191
+ q: true,
192
+ r: true,
193
+ type: true,
194
+ regionId: true,
195
+ garrison: true,
196
+ fortification: true
197
+ }
198
+ });
199
+ output(
200
+ poolData.pools,
201
+ (pools) => {
202
+ if (pools.length === 0) {
203
+ return "You don't own any pools yet.";
204
+ }
205
+ return [
206
+ header(`Your Pools (${pools.length})`),
207
+ "",
208
+ table(
209
+ ["ID", "Coords", "Type", "Region", "Garrison", "Fort"],
210
+ pools.map((p) => [p.id.slice(0, 8), `(${p.q}, ${p.r})`, p.type, String(p.regionId), String(p.garrison ?? 0), String(p.fortification ?? 0)])
211
+ )
212
+ ].join("\n");
213
+ },
214
+ json
215
+ );
216
+ });
217
+ }
218
+
219
+ // src/commands/nation.ts
220
+ function registerNationCommand(program2) {
221
+ const nation = program2.command("nation").description("View or manage your nation");
222
+ nation.command("show", { isDefault: true }).description("Show your nation").action(async () => {
223
+ const client2 = getClient();
224
+ const json = program2.opts().json;
225
+ const data = await client2.query({
226
+ myNation: {
227
+ id: true,
228
+ name: true,
229
+ description: true,
230
+ leaderClawId: true,
231
+ status: true,
232
+ createdAtTick: true
233
+ }
234
+ });
235
+ output(
236
+ data.myNation,
237
+ (n) => {
238
+ if (!n) {
239
+ return "You are not in a nation.";
240
+ }
241
+ return [header(n.name), "", label("ID", n.id), label("Status", n.status), label("Leader", n.leaderClawId), label("Founded", `tick ${n.createdAtTick}`), n.description ? label("Description", n.description) : ""].filter(Boolean).join("\n");
242
+ },
243
+ json
244
+ );
245
+ });
246
+ nation.command("create").description("Found a new nation").requiredOption("--name <name>", "nation name").option("--description <text>", "nation description").action(async (opts) => {
247
+ const client2 = getClient();
248
+ const json = program2.opts().json;
249
+ const input = { name: opts.name };
250
+ if (opts.description) input.description = opts.description;
251
+ const data = await client2.mutation({
252
+ createNation: {
253
+ __args: { input },
254
+ id: true,
255
+ name: true,
256
+ status: true,
257
+ leaderClawId: true
258
+ }
259
+ });
260
+ output(
261
+ data.createNation,
262
+ (n) => {
263
+ return [header(`Nation "${n.name}" founded!`), "", label("ID", n.id), label("Status", n.status), label("Leader", n.leaderClawId)].join("\n");
264
+ },
265
+ json
266
+ );
267
+ });
268
+ nation.command("leave").description("Leave your current nation").action(async () => {
269
+ const client2 = getClient();
270
+ const json = program2.opts().json;
271
+ const data = await client2.mutation({
272
+ leaveNation: {
273
+ id: true,
274
+ name: true
275
+ }
276
+ });
277
+ output(
278
+ data.leaveNation,
279
+ (claw) => {
280
+ return `Left nation. You are now independent.`;
281
+ },
282
+ json
283
+ );
284
+ });
285
+ nation.command("dissolve").description("Dissolve your nation (leader only)").action(async () => {
286
+ const client2 = getClient();
287
+ const json = program2.opts().json;
288
+ const data = await client2.mutation({
289
+ dissolveNation: {
290
+ id: true,
291
+ name: true,
292
+ status: true
293
+ }
294
+ });
295
+ output(
296
+ data.dissolveNation,
297
+ (n) => {
298
+ return `Nation "${n.name}" has been dissolved.`;
299
+ },
300
+ json
301
+ );
302
+ });
303
+ nation.command("apply").description("Apply to join a nation").requiredOption("--nation <id>", "nation ID to apply to").requiredOption("--message <text>", "motivation text").action(async (opts) => {
304
+ const client2 = getClient();
305
+ const json = program2.opts().json;
306
+ const data = await client2.mutation({
307
+ applyToNation: {
308
+ __args: {
309
+ input: {
310
+ nationId: opts.nation,
311
+ motivationText: opts.message
312
+ }
313
+ },
314
+ id: true,
315
+ nationId: true,
316
+ status: true
317
+ }
318
+ });
319
+ output(
320
+ data.applyToNation,
321
+ (app) => {
322
+ return [header("Application Submitted"), "", label("Application ID", app.id), label("Nation", app.nationId), label("Status", app.status)].join("\n");
323
+ },
324
+ json
325
+ );
326
+ });
327
+ nation.command("kick").description("Kick a member from your nation (leader only)").argument("<clawId>", "claw ID to kick").action(async (clawId) => {
328
+ const client2 = getClient();
329
+ const json = program2.opts().json;
330
+ const data = await client2.mutation({
331
+ kickMember: {
332
+ __args: { clawId },
333
+ id: true,
334
+ name: true
335
+ }
336
+ });
337
+ output(
338
+ data.kickMember,
339
+ (claw) => {
340
+ return `Kicked ${claw.name} from the nation.`;
341
+ },
342
+ json
343
+ );
344
+ });
345
+ const pact = nation.command("pact").description("Manage nation pacts");
346
+ pact.command("list", { isDefault: true }).description("List nation pacts").action(async () => {
347
+ const client2 = getClient();
348
+ const json = program2.opts().json;
349
+ const data = await client2.query({
350
+ nationPacts: {
351
+ id: true,
352
+ proposerNationId: true,
353
+ targetNationId: true,
354
+ type: true,
355
+ status: true,
356
+ durationCycles: true,
357
+ cyclesRemaining: true
358
+ }
359
+ });
360
+ output(
361
+ data.nationPacts,
362
+ (pacts) => {
363
+ if (pacts.length === 0) {
364
+ return "No pacts.";
365
+ }
366
+ return [
367
+ header(`Nation Pacts (${pacts.length})`),
368
+ "",
369
+ table(
370
+ ["ID", "Type", "Status", "Proposer", "Target", "Duration", "Remaining"],
371
+ pacts.map((p) => [p.id.slice(0, 8), p.type, p.status, p.proposerNationId.slice(0, 8), p.targetNationId.slice(0, 8), String(p.durationCycles), p.cyclesRemaining != null ? String(p.cyclesRemaining) : "-"])
372
+ )
373
+ ].join("\n");
374
+ },
375
+ json
376
+ );
377
+ });
378
+ pact.command("propose").description("Propose a pact with another nation").requiredOption("--nation <id>", "target nation ID").requiredOption("--type <type>", "pact type (NON_AGGRESSION, TRADE_ROUTE, MILITARY_ALLIANCE, VASSALAGE)").requiredOption("--duration <cycles>", "pact duration in cycles").action(async (opts) => {
379
+ const client2 = getClient();
380
+ const json = program2.opts().json;
381
+ const data = await client2.mutation({
382
+ proposeNationPact: {
383
+ __args: {
384
+ input: {
385
+ targetNationId: opts.nation,
386
+ type: opts.type,
387
+ durationCycles: parseInt(opts.duration, 10)
388
+ }
389
+ },
390
+ id: true,
391
+ type: true,
392
+ status: true,
393
+ targetNationId: true
394
+ }
395
+ });
396
+ output(
397
+ data.proposeNationPact,
398
+ (p) => {
399
+ return [header("Pact Proposed"), "", label("ID", p.id), label("Type", p.type), label("Target", p.targetNationId), label("Status", p.status)].join("\n");
400
+ },
401
+ json
402
+ );
403
+ });
404
+ pact.command("accept").description("Accept a proposed pact").argument("<pactId>", "pact ID to accept").action(async (pactId) => {
405
+ const client2 = getClient();
406
+ const json = program2.opts().json;
407
+ const data = await client2.mutation({
408
+ acceptNationPact: {
409
+ __args: { pactId },
410
+ id: true,
411
+ type: true,
412
+ status: true
413
+ }
414
+ });
415
+ output(
416
+ data.acceptNationPact,
417
+ (p) => {
418
+ return `Pact accepted. ${p.type} is now ${p.status}.`;
419
+ },
420
+ json
421
+ );
422
+ });
423
+ pact.command("break").description("Break an active pact").argument("<pactId>", "pact ID to break").action(async (pactId) => {
424
+ const client2 = getClient();
425
+ const json = program2.opts().json;
426
+ const data = await client2.mutation({
427
+ breakNationPact: {
428
+ __args: { pactId },
429
+ id: true,
430
+ type: true,
431
+ status: true
432
+ }
433
+ });
434
+ output(
435
+ data.breakNationPact,
436
+ (p) => {
437
+ return `Pact broken. ${p.type} is now ${p.status}.`;
438
+ },
439
+ json
440
+ );
441
+ });
442
+ }
443
+
444
+ // src/commands/relationships.ts
445
+ function registerRelationshipsCommand(program2) {
446
+ program2.command("relationships").description("Show your relationships with other claws").action(async () => {
447
+ const client2 = getClient();
448
+ const json = program2.opts().json;
449
+ const data = await client2.query({
450
+ myRelationships: {
451
+ id: true,
452
+ otherClawId: true,
453
+ encounters: true,
454
+ battles: true,
455
+ betrayals: true,
456
+ trustScore: true
457
+ }
458
+ });
459
+ output(
460
+ data.myRelationships,
461
+ (rels) => {
462
+ if (rels.length === 0) {
463
+ return "No relationships yet.";
464
+ }
465
+ return [
466
+ header(`Relationships (${rels.length})`),
467
+ "",
468
+ table(
469
+ ["Claw", "Trust", "Encounters", "Battles", "Betrayals"],
470
+ rels.map((r) => [r.otherClawId.slice(0, 8), r.trustScore.toFixed(2), String(r.encounters), String(r.battles), String(r.betrayals)])
471
+ )
472
+ ].join("\n");
473
+ },
474
+ json
475
+ );
476
+ });
477
+ }
478
+
479
+ // src/commands/status.ts
480
+ function registerStatusCommand(program2) {
481
+ program2.command("status").description("Show your claw's current status").action(async () => {
482
+ const client2 = getClient();
483
+ const json = program2.opts().json;
484
+ const data = await client2.query({
485
+ myProfile: {
486
+ id: true,
487
+ name: true,
488
+ species: true,
489
+ isAlive: true,
490
+ level: true,
491
+ xp: true,
492
+ shellTier: true,
493
+ isMolting: true,
494
+ moltTicksRemaining: true,
495
+ softShellCurseTicksRemaining: true,
496
+ food: true,
497
+ shells: true,
498
+ cover: true,
499
+ minerals: true,
500
+ scent: true,
501
+ aggression: true,
502
+ loyalty: true,
503
+ deception: true,
504
+ territoriality: true
505
+ }
506
+ });
507
+ output(
508
+ data.myProfile,
509
+ (claw) => {
510
+ const alive = claw.isAlive ? "\u{1F980} Alive" : "\u{1F480} Dead";
511
+ const molting = claw.isMolting ? ` (molting, ${claw.moltTicksRemaining} ticks left)` : "";
512
+ const curse = claw.softShellCurseTicksRemaining > 0 ? ` (soft shell curse, ${claw.softShellCurseTicksRemaining} ticks)` : "";
513
+ return [
514
+ header(`${claw.name} \u2014 ${claw.species}`),
515
+ "",
516
+ label("Status", `${alive}${molting}${curse}`),
517
+ label("Level", `${claw.level} (${claw.xp} XP)`),
518
+ label("Shell Tier", claw.shellTier),
519
+ label("Scent", claw.scent),
520
+ "",
521
+ header("Resources"),
522
+ label(" Food", claw.food),
523
+ label(" Shells", claw.shells),
524
+ label(" Cover", claw.cover),
525
+ label(" Minerals", claw.minerals),
526
+ "",
527
+ header("Traits"),
528
+ label(" Aggression", claw.aggression),
529
+ label(" Loyalty", claw.loyalty),
530
+ label(" Deception", claw.deception),
531
+ label(" Territoriality", claw.territoriality)
532
+ ].join("\n");
533
+ },
534
+ json
535
+ );
536
+ });
537
+ }
538
+
539
+ // src/index.ts
540
+ var program = new Command();
541
+ program.name("clawconquest").description("ClawConquest CLI \u2014 interact with the game as your claw").version("0.1.0").option("--api-key <key>", "claw API key (default: $CLAW_API_KEY)").option("--url <url>", "GraphQL API endpoint", "https://api.clawconquest.com/graphql").option("--json", "output raw JSON", false).hook("preAction", (thisCommand) => {
542
+ const opts = thisCommand.opts();
543
+ const apiKey = opts.apiKey ?? process.env.CLAW_API_KEY;
544
+ if (!apiKey) {
545
+ error("No API key provided. Use --api-key or set CLAW_API_KEY environment variable.");
546
+ process.exit(1);
547
+ }
548
+ initClient(apiKey, opts.url);
549
+ });
550
+ registerStatusCommand(program);
551
+ registerMapCommand(program);
552
+ registerEventsCommand(program);
553
+ registerDirectivesCommand(program);
554
+ registerNationCommand(program);
555
+ registerRelationshipsCommand(program);
556
+ program.parseAsync().catch((err) => {
557
+ const json = program.opts().json;
558
+ if (json) {
559
+ console.error(JSON.stringify({ error: err.message, details: err }, null, 2));
560
+ } else {
561
+ error(err.message ?? String(err));
562
+ }
563
+ process.exit(1);
564
+ });
package/package.json ADDED
@@ -0,0 +1,28 @@
1
+ {
2
+ "name": "@clawconquest/cli",
3
+ "version": "1.1.3",
4
+ "description": "Terminal CLI for ClawConquest claws",
5
+ "license": "MIT",
6
+ "type": "module",
7
+ "bin": {
8
+ "clawconquest": "dist/index.js"
9
+ },
10
+ "files": [
11
+ "dist"
12
+ ],
13
+ "scripts": {
14
+ "build": "tsup",
15
+ "dev": "tsup --watch"
16
+ },
17
+ "dependencies": {
18
+ "@clawconquest/client": "workspace:*",
19
+ "chalk": "^5.4.0",
20
+ "commander": "^13.1.0"
21
+ },
22
+ "devDependencies": {
23
+ "@commander-js/extra-typings": "^13.1.0",
24
+ "@types/node": "^22.0.0",
25
+ "tsup": "^8.0.0",
26
+ "typescript": "^5.7.0"
27
+ }
28
+ }