claude-trello-cli 0.1.6 → 0.1.7

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 +27 -4
  2. package/dist/index.js +295 -74
  3. package/package.json +1 -1
package/README.md CHANGED
@@ -5,12 +5,13 @@ Point [Claude Code](https://docs.anthropic.com/en/docs/claude-code) at a Trello
5
5
  ## Quick Start
6
6
 
7
7
  ```bash
8
- npx claude-trello-cli login
8
+ npx claude-trello-cli register # create an account (or `login` if you have one)
9
+ npx claude-trello-cli setup # connect Trello + save your Anthropic API key
9
10
  cd ~/my-project
10
- npx claude-trello-cli run
11
+ npx claude-trello-cli run # pick a board and start working
11
12
  ```
12
13
 
13
- That's it. No config files, no setup scripts just sign in and go.
14
+ Everything happens in your terminalno web app required.
14
15
 
15
16
  ## What It Does
16
17
 
@@ -78,11 +79,25 @@ claude-trello run
78
79
 
79
80
  ## Prerequisites
80
81
 
81
- - **A Claude Trello Bridge account** — sign up at [ct.joshualevine.me](https://ct.joshualevine.me), connect your Trello account, and save your Anthropic API key
82
+ - **A Trello account** — you'll connect it during `setup`
83
+ - **An Anthropic API key** — get one from [console.anthropic.com](https://console.anthropic.com/settings/keys)
82
84
  - **Node.js 20+**
83
85
 
84
86
  ## Commands
85
87
 
88
+ ### `claude-trello-cli register`
89
+
90
+ Create a new account. You'll be prompted for your name, email, and password.
91
+
92
+ ```bash
93
+ npx claude-trello-cli register
94
+ npx claude-trello-cli register --server https://your-self-hosted-instance.com
95
+ ```
96
+
97
+ | Flag | Description |
98
+ |------|-------------|
99
+ | `-s, --server <url>` | Server URL (default: `https://ct.joshualevine.me`) |
100
+
86
101
  ### `claude-trello-cli login`
87
102
 
88
103
  Sign in with your email and password. Your session is stored at `~/.config/claude-trello/config.json` with restricted file permissions.
@@ -96,6 +111,14 @@ npx claude-trello-cli login --server https://your-app.vercel.app
96
111
  |------|-------------|
97
112
  | `-s, --server <url>` | Server URL (default: `https://ct.joshualevine.me`) |
98
113
 
114
+ ### `claude-trello-cli setup`
115
+
116
+ Interactive wizard that walks you through connecting Trello and saving your Anthropic API key. Opens your browser for Trello authorization and polls until complete.
117
+
118
+ ```bash
119
+ npx claude-trello-cli setup
120
+ ```
121
+
99
122
  ### `claude-trello-cli run`
100
123
 
101
124
  The main command. Select a board interactively, review the cards, and launch a Claude Code session.
package/dist/index.js CHANGED
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
 
3
3
  // src/index.ts
4
- import { Command as Command6 } from "commander";
4
+ import { Command as Command8 } from "commander";
5
5
 
6
6
  // src/commands/login.ts
7
7
  import { Command } from "commander";
@@ -101,14 +101,14 @@ async function apiFetch(path, options) {
101
101
  }
102
102
  return res.json();
103
103
  }
104
- async function signIn(serverUrl, email, password2) {
104
+ async function signIn(serverUrl, email, password4) {
105
105
  const res = await fetch(`${serverUrl}/api/auth/sign-in/email`, {
106
106
  method: "POST",
107
107
  headers: {
108
108
  "Content-Type": "application/json",
109
109
  Origin: serverUrl
110
110
  },
111
- body: JSON.stringify({ email, password: password2 }),
111
+ body: JSON.stringify({ email, password: password4 }),
112
112
  redirect: "manual"
113
113
  });
114
114
  if (!res.ok) {
@@ -128,6 +128,43 @@ async function signIn(serverUrl, email, password2) {
128
128
  const data = await res.json();
129
129
  return { cookies, user: data.user };
130
130
  }
131
+ async function signUp(serverUrl, name, email, password4) {
132
+ const res = await fetch(`${serverUrl}/api/auth/sign-up/email`, {
133
+ method: "POST",
134
+ headers: {
135
+ "Content-Type": "application/json",
136
+ Origin: serverUrl
137
+ },
138
+ body: JSON.stringify({ name, email, password: password4 }),
139
+ redirect: "manual"
140
+ });
141
+ if (!res.ok) {
142
+ let errorMsg = "Registration failed";
143
+ try {
144
+ const body = await res.json();
145
+ errorMsg = body.message || body.error || errorMsg;
146
+ } catch {
147
+ }
148
+ throw new ApiError(res.status, errorMsg);
149
+ }
150
+ const setCookieHeaders = res.headers.getSetCookie?.() ?? [];
151
+ const cookies = setCookieHeaders.map((c) => c.split(";")[0]).join("; ");
152
+ if (!cookies) {
153
+ throw new ApiError(500, "No session cookie received from server");
154
+ }
155
+ const data = await res.json();
156
+ return { cookies, user: data.user };
157
+ }
158
+ async function getTrelloAuthUrl() {
159
+ const data = await apiFetch("/api/trello/authorize");
160
+ return data.url;
161
+ }
162
+ async function saveApiKey(apiKey) {
163
+ await apiFetch("/api/settings/apikey", {
164
+ method: "POST",
165
+ body: JSON.stringify({ apiKey })
166
+ });
167
+ }
131
168
  async function getIntegrationStatus() {
132
169
  return apiFetch("/api/settings/status");
133
170
  }
@@ -169,18 +206,200 @@ var loginCommand = new Command("login").description("Sign in to Claude Trello Br
169
206
  }
170
207
  });
171
208
 
172
- // src/commands/logout.ts
209
+ // src/commands/register.ts
173
210
  import { Command as Command2 } from "commander";
211
+ import { input as input2, password as password2 } from "@inquirer/prompts";
174
212
  import chalk2 from "chalk";
175
- var logoutCommand = new Command2("logout").description("Sign out and clear stored session").action(() => {
213
+ import ora2 from "ora";
214
+ var registerCommand = new Command2("register").description("Create a new Claude Trello Bridge account").option("-s, --server <url>", "Server URL (default: https://ct.joshualevine.me)").action(async (opts) => {
215
+ const serverUrl = opts.server || getServerUrl();
216
+ console.log(chalk2.bold("Create a Claude Trello Bridge account"));
217
+ console.log(chalk2.dim(`Server: ${serverUrl}
218
+ `));
219
+ const name = await input2({ message: "Name:" });
220
+ const email = await input2({ message: "Email:" });
221
+ const pass = await password2({ message: "Password (min 8 characters):" });
222
+ if (pass.length < 8) {
223
+ console.log(chalk2.red("Password must be at least 8 characters."));
224
+ process.exit(1);
225
+ }
226
+ const spinner = ora2("Creating account...").start();
227
+ try {
228
+ const { cookies, user } = await signUp(serverUrl, name, email, pass);
229
+ saveConfig({
230
+ serverUrl,
231
+ sessionCookie: cookies,
232
+ userEmail: user.email,
233
+ userName: user.name
234
+ });
235
+ spinner.succeed(
236
+ `Account created! Signed in as ${chalk2.bold(user.name)} (${user.email})`
237
+ );
238
+ console.log(
239
+ chalk2.dim(
240
+ "\n Run `claude-trello setup` to connect Trello and add your API key.\n"
241
+ )
242
+ );
243
+ } catch (err) {
244
+ spinner.fail(err instanceof Error ? err.message : "Registration failed");
245
+ process.exit(1);
246
+ }
247
+ });
248
+
249
+ // src/commands/setup.ts
250
+ import { exec } from "child_process";
251
+ import { Command as Command3 } from "commander";
252
+ import { password as password3, confirm } from "@inquirer/prompts";
253
+ import chalk3 from "chalk";
254
+ import ora3 from "ora";
255
+ function openBrowser(url) {
256
+ const cmd = process.platform === "darwin" ? "open" : process.platform === "win32" ? "start" : "xdg-open";
257
+ exec(`${cmd} ${JSON.stringify(url)}`);
258
+ }
259
+ async function pollForTrello(timeoutMs = 12e4, intervalMs = 2e3) {
260
+ const deadline = Date.now() + timeoutMs;
261
+ while (Date.now() < deadline) {
262
+ try {
263
+ const status = await getIntegrationStatus();
264
+ if (status.trelloLinked) return true;
265
+ } catch {
266
+ }
267
+ await new Promise((r) => setTimeout(r, intervalMs));
268
+ }
269
+ return false;
270
+ }
271
+ var setupCommand = new Command3("setup").description("Connect Trello and save your Anthropic API key").action(async () => {
272
+ if (!isLoggedIn()) {
273
+ console.log(
274
+ chalk3.red(
275
+ "Not logged in. Run `claude-trello register` or `claude-trello login` first."
276
+ )
277
+ );
278
+ process.exit(1);
279
+ }
280
+ console.log(chalk3.bold("\nClaude Trello Bridge \u2014 Setup\n"));
281
+ const statusSpinner = ora3("Checking current status...").start();
282
+ let status;
283
+ try {
284
+ status = await getIntegrationStatus();
285
+ statusSpinner.stop();
286
+ } catch (err) {
287
+ statusSpinner.fail(
288
+ err instanceof Error ? err.message : "Failed to check status"
289
+ );
290
+ process.exit(1);
291
+ }
292
+ if (status.trelloLinked) {
293
+ console.log(
294
+ ` ${chalk3.green("1.")} Trello ${chalk3.green("Connected")}`
295
+ );
296
+ } else {
297
+ console.log(
298
+ ` ${chalk3.yellow("1.")} Trello ${chalk3.yellow("Not connected")}
299
+ `
300
+ );
301
+ const proceed = await confirm({
302
+ message: "Open your browser to connect Trello? (you'll authorize and be redirected back)",
303
+ default: true
304
+ });
305
+ if (!proceed) {
306
+ console.log(chalk3.dim("Setup cancelled."));
307
+ return;
308
+ }
309
+ const urlSpinner = ora3("Getting Trello authorization URL...").start();
310
+ let authUrl;
311
+ try {
312
+ authUrl = await getTrelloAuthUrl();
313
+ urlSpinner.stop();
314
+ } catch (err) {
315
+ urlSpinner.fail(
316
+ err instanceof Error ? err.message : "Failed to get auth URL"
317
+ );
318
+ process.exit(1);
319
+ }
320
+ console.log(chalk3.dim(`
321
+ Opening: ${authUrl}
322
+ `));
323
+ openBrowser(authUrl);
324
+ console.log(
325
+ chalk3.dim(
326
+ " Authorize the app on Trello, then come back here.\n If the browser didn't open, copy the URL above manually.\n"
327
+ )
328
+ );
329
+ const pollSpinner = ora3(
330
+ "Waiting for Trello connection (up to 2 minutes)..."
331
+ ).start();
332
+ const connected = await pollForTrello();
333
+ if (connected) {
334
+ pollSpinner.succeed("Trello connected!");
335
+ } else {
336
+ pollSpinner.fail(
337
+ "Timed out waiting for Trello connection. Run `claude-trello setup` to try again."
338
+ );
339
+ process.exit(1);
340
+ }
341
+ }
342
+ if (status.hasApiKey) {
343
+ console.log(
344
+ ` ${chalk3.green("2.")} Anthropic API Key ${chalk3.green("Configured")}`
345
+ );
346
+ } else {
347
+ console.log(
348
+ `
349
+ ${chalk3.yellow("2.")} Anthropic API Key ${chalk3.yellow("Not set")}
350
+ `
351
+ );
352
+ console.log(
353
+ chalk3.dim(
354
+ " Get your key from https://console.anthropic.com/settings/keys\n"
355
+ )
356
+ );
357
+ const apiKey = await password3({
358
+ message: "Paste your Anthropic API key (sk-ant-api03-...):"
359
+ });
360
+ if (!apiKey.startsWith("sk-ant-api03-")) {
361
+ console.log(
362
+ chalk3.red('Invalid key format. Must start with "sk-ant-api03-".')
363
+ );
364
+ process.exit(1);
365
+ }
366
+ const keySpinner = ora3("Saving API key...").start();
367
+ try {
368
+ await saveApiKey(apiKey);
369
+ keySpinner.succeed("API key saved (encrypted on server)");
370
+ } catch (err) {
371
+ keySpinner.fail(
372
+ err instanceof Error ? err.message : "Failed to save API key"
373
+ );
374
+ process.exit(1);
375
+ }
376
+ }
377
+ const serverUrl = getServerUrl();
378
+ console.log(
379
+ chalk3.green.bold(
380
+ "\n All set! Run `claude-trello run` to start a session.\n"
381
+ )
382
+ );
383
+ console.log(
384
+ chalk3.dim(
385
+ ` You can manage your settings anytime at ${serverUrl}/settings
386
+ `
387
+ )
388
+ );
389
+ });
390
+
391
+ // src/commands/logout.ts
392
+ import { Command as Command4 } from "commander";
393
+ import chalk4 from "chalk";
394
+ var logoutCommand = new Command4("logout").description("Sign out and clear stored session").action(() => {
176
395
  if (!isLoggedIn()) {
177
- console.log(chalk2.dim("Not currently logged in."));
396
+ console.log(chalk4.dim("Not currently logged in."));
178
397
  return;
179
398
  }
180
399
  const config = getConfig();
181
400
  clearConfig();
182
401
  console.log(
183
- chalk2.green(
402
+ chalk4.green(
184
403
  `Signed out${config.userEmail ? ` (${config.userEmail})` : ""}.`
185
404
  )
186
405
  );
@@ -188,10 +407,10 @@ var logoutCommand = new Command2("logout").description("Sign out and clear store
188
407
 
189
408
  // src/commands/run.ts
190
409
  import { resolve } from "path";
191
- import { Command as Command3 } from "commander";
192
- import { select, confirm, input as input2 } from "@inquirer/prompts";
193
- import chalk3 from "chalk";
194
- import ora2 from "ora";
410
+ import { Command as Command5 } from "commander";
411
+ import { select, confirm as confirm2, input as input3 } from "@inquirer/prompts";
412
+ import chalk5 from "chalk";
413
+ import ora4 from "ora";
195
414
 
196
415
  // src/lib/runner.ts
197
416
  import {
@@ -347,10 +566,10 @@ function launchSession(options) {
347
566
  }
348
567
 
349
568
  // src/commands/run.ts
350
- var runCommand = new Command3("run").description("Select a Trello board and start a Claude Code session").option("-b, --board <id>", "Board ID (skip interactive selection)").option("-d, --dir <path>", "Working directory (default: current)").option("-m, --message <text>", "Initial instructions for Claude").action(async (opts) => {
569
+ var runCommand = new Command5("run").description("Select a Trello board and start a Claude Code session").option("-b, --board <id>", "Board ID (skip interactive selection)").option("-d, --dir <path>", "Working directory (default: current)").option("-m, --message <text>", "Initial instructions for Claude").action(async (opts) => {
351
570
  if (!isLoggedIn()) {
352
571
  console.log(
353
- chalk3.red("Not logged in. Run `claude-trello login` first.")
572
+ chalk5.red("Not logged in. Run `claude-trello login` first.")
354
573
  );
355
574
  process.exit(1);
356
575
  }
@@ -358,7 +577,7 @@ var runCommand = new Command3("run").description("Select a Trello board and star
358
577
  let boardId = opts.board;
359
578
  let boardName = "";
360
579
  if (!boardId) {
361
- const spinner = ora2("Fetching boards...").start();
580
+ const spinner = ora4("Fetching boards...").start();
362
581
  let boards;
363
582
  try {
364
583
  boards = await getBoards();
@@ -371,7 +590,7 @@ var runCommand = new Command3("run").description("Select a Trello board and star
371
590
  }
372
591
  if (boards.length === 0) {
373
592
  console.log(
374
- chalk3.red("No boards found. Create a board on Trello first.")
593
+ chalk5.red("No boards found. Create a board on Trello first.")
375
594
  );
376
595
  process.exit(1);
377
596
  }
@@ -385,7 +604,7 @@ var runCommand = new Command3("run").description("Select a Trello board and star
385
604
  });
386
605
  boardName = boards.find((b) => b.id === boardId)?.name ?? boardId;
387
606
  }
388
- const dataSpinner = ora2("Fetching cards and checklists...").start();
607
+ const dataSpinner = ora4("Fetching cards and checklists...").start();
389
608
  let cardsResponse;
390
609
  try {
391
610
  cardsResponse = await getBoardData(boardId);
@@ -399,8 +618,8 @@ var runCommand = new Command3("run").description("Select a Trello board and star
399
618
  const { cards, lists, doneListId } = cardsResponse;
400
619
  if (!boardName) boardName = boardId;
401
620
  console.log(`
402
- ${chalk3.bold(boardName)}`);
403
- console.log(chalk3.dim("\u2500".repeat(boardName.length)));
621
+ ${chalk5.bold(boardName)}`);
622
+ console.log(chalk5.dim("\u2500".repeat(boardName.length)));
404
623
  const doneCards = doneListId ? cards.filter((c) => c.idList === doneListId) : [];
405
624
  const activeCards = doneListId ? cards.filter((c) => c.idList !== doneListId) : cards;
406
625
  const listMap = /* @__PURE__ */ new Map();
@@ -415,7 +634,7 @@ ${chalk3.bold(boardName)}`);
415
634
  const listName = listMap.get(listId)?.name ?? "Unknown";
416
635
  console.log(
417
636
  `
418
- ${chalk3.cyan.bold(listName)} (${listCards.length} card${listCards.length === 1 ? "" : "s"}):`
637
+ ${chalk5.cyan.bold(listName)} (${listCards.length} card${listCards.length === 1 ? "" : "s"}):`
419
638
  );
420
639
  for (const card of listCards) {
421
640
  const total = card.checklists.reduce(
@@ -428,37 +647,37 @@ ${chalk3.bold(boardName)}`);
428
647
  );
429
648
  const progress = total > 0 ? ` [${done}/${total}]` : "";
430
649
  console.log(
431
- ` ${chalk3.white("\u2022")} ${card.name}${chalk3.dim(progress)}`
650
+ ` ${chalk5.white("\u2022")} ${card.name}${chalk5.dim(progress)}`
432
651
  );
433
652
  }
434
653
  }
435
654
  if (doneCards.length > 0) {
436
655
  console.log(
437
656
  `
438
- ${chalk3.dim(`Done (${doneCards.length} card${doneCards.length === 1 ? "" : "s"}) [skipped]`)}`
657
+ ${chalk5.dim(`Done (${doneCards.length} card${doneCards.length === 1 ? "" : "s"}) [skipped]`)}`
439
658
  );
440
659
  }
441
660
  if (activeCards.length === 0) {
442
- console.log(chalk3.dim("\n No active cards to work on."));
661
+ console.log(chalk5.dim("\n No active cards to work on."));
443
662
  return;
444
663
  }
445
664
  console.log(`
446
- ${chalk3.dim(`Working directory: ${cwd}`)}`);
447
- const proceed = await confirm({
665
+ ${chalk5.dim(`Working directory: ${cwd}`)}`);
666
+ const proceed = await confirm2({
448
667
  message: `Start Claude Code session? (${activeCards.length} active card${activeCards.length === 1 ? "" : "s"})`,
449
668
  default: true
450
669
  });
451
670
  if (!proceed) {
452
- console.log(chalk3.dim("Cancelled."));
671
+ console.log(chalk5.dim("Cancelled."));
453
672
  return;
454
673
  }
455
674
  let userMessage = opts.message;
456
675
  if (!userMessage) {
457
- userMessage = await input2({
676
+ userMessage = await input3({
458
677
  message: "Instructions for Claude (optional \u2014 press Enter to skip):"
459
678
  });
460
679
  }
461
- const credSpinner = ora2("Loading credentials...").start();
680
+ const credSpinner = ora4("Loading credentials...").start();
462
681
  let credentials;
463
682
  try {
464
683
  credentials = await getCredentials();
@@ -475,11 +694,11 @@ ${chalk3.bold(boardName)}`);
475
694
  doneListId: doneListId ?? void 0
476
695
  };
477
696
  console.log(`
478
- ${chalk3.bold.blue("Starting Claude Code session...")}
697
+ ${chalk5.bold.blue("Starting Claude Code session...")}
479
698
  `);
480
699
  const abortController = new AbortController();
481
700
  const sigintHandler = () => {
482
- console.log(chalk3.dim("\n\nAborting session..."));
701
+ console.log(chalk5.dim("\n\nAborting session..."));
483
702
  abortController.abort();
484
703
  };
485
704
  process.on("SIGINT", sigintHandler);
@@ -495,14 +714,14 @@ ${chalk3.bold.blue("Starting Claude Code session...")}
495
714
  await handleMessage(message, session);
496
715
  }
497
716
  console.log(`
498
- ${chalk3.green.bold("Session complete.")}
717
+ ${chalk5.green.bold("Session complete.")}
499
718
  `);
500
719
  } catch (err) {
501
720
  if (abortController.signal.aborted) {
502
- console.log(chalk3.dim("\nSession aborted."));
721
+ console.log(chalk5.dim("\nSession aborted."));
503
722
  } else {
504
723
  console.error(
505
- chalk3.red(
724
+ chalk5.red(
506
725
  `
507
726
  Session error: ${err instanceof Error ? err.message : "Unknown error"}`
508
727
  )
@@ -518,7 +737,7 @@ async function handleMessage(message, session) {
518
737
  case "system": {
519
738
  if (message.subtype === "init") {
520
739
  console.log(
521
- chalk3.dim(
740
+ chalk5.dim(
522
741
  ` Session initialized (model: ${message.model})
523
742
  `
524
743
  )
@@ -537,17 +756,17 @@ async function handleMessage(message, session) {
537
756
  const name = block.name;
538
757
  const toolInput = block.input ?? {};
539
758
  if (name === "mcp__trello-tools__check_trello_item") {
540
- console.log(chalk3.green(` \u2713 Checked item on Trello`));
759
+ console.log(chalk5.green(` \u2713 Checked item on Trello`));
541
760
  } else if (name === "mcp__trello-tools__move_card_to_done") {
542
- console.log(chalk3.green.bold(` \u2713 Moved card to Done`));
761
+ console.log(chalk5.green.bold(` \u2713 Moved card to Done`));
543
762
  } else if (name === "AskUserQuestion") {
544
763
  const questions = toolInput.questions;
545
764
  if (questions && questions.length > 0) {
546
765
  const questionText = questions.map((q) => q.question).join("\n");
547
- console.log(chalk3.yellow(`
766
+ console.log(chalk5.yellow(`
548
767
  ? ${questionText}
549
768
  `));
550
- const answer = await input2({ message: ">" });
769
+ const answer = await input3({ message: ">" });
551
770
  async function* userInput() {
552
771
  yield {
553
772
  type: "user",
@@ -570,7 +789,7 @@ async function handleMessage(message, session) {
570
789
  }
571
790
  case "result": {
572
791
  const result = message.result ?? message.subtype;
573
- console.log(chalk3.dim(`
792
+ console.log(chalk5.dim(`
574
793
  Result: ${result}`));
575
794
  break;
576
795
  }
@@ -578,62 +797,62 @@ async function handleMessage(message, session) {
578
797
  }
579
798
  function formatToolUse(name, toolInput) {
580
799
  const path = toolInput.file_path ?? toolInput.path ?? toolInput.pattern ?? "";
581
- const shortPath = path ? ` ${chalk3.cyan(path)}` : "";
800
+ const shortPath = path ? ` ${chalk5.cyan(path)}` : "";
582
801
  switch (name) {
583
802
  case "Read":
584
- return chalk3.dim(` Reading${shortPath}`);
803
+ return chalk5.dim(` Reading${shortPath}`);
585
804
  case "Edit":
586
- return chalk3.dim(` Editing${shortPath}`);
805
+ return chalk5.dim(` Editing${shortPath}`);
587
806
  case "Write":
588
- return chalk3.dim(` Writing${shortPath}`);
807
+ return chalk5.dim(` Writing${shortPath}`);
589
808
  case "Glob":
590
- return chalk3.dim(` Searching files${shortPath}`);
809
+ return chalk5.dim(` Searching files${shortPath}`);
591
810
  case "Grep":
592
- return chalk3.dim(
593
- ` Searching for ${chalk3.cyan(toolInput.pattern || "...")}${toolInput.path ? ` in ${chalk3.cyan(toolInput.path)}` : ""}`
811
+ return chalk5.dim(
812
+ ` Searching for ${chalk5.cyan(toolInput.pattern || "...")}${toolInput.path ? ` in ${chalk5.cyan(toolInput.path)}` : ""}`
594
813
  );
595
814
  case "Bash": {
596
815
  const cmd = toolInput.command || "";
597
816
  const preview = cmd.length > 80 ? cmd.slice(0, 77) + "..." : cmd;
598
- return chalk3.dim(` Running ${chalk3.cyan(preview)}`);
817
+ return chalk5.dim(` Running ${chalk5.cyan(preview)}`);
599
818
  }
600
819
  case "TodoWrite":
601
- return chalk3.dim(" Updating task list");
820
+ return chalk5.dim(" Updating task list");
602
821
  case "Agent":
603
- return chalk3.dim(
822
+ return chalk5.dim(
604
823
  ` Spawning agent${toolInput.description ? `: ${toolInput.description}` : ""}`
605
824
  );
606
825
  default:
607
- return chalk3.dim(` [${name}]${shortPath}`);
826
+ return chalk5.dim(` [${name}]${shortPath}`);
608
827
  }
609
828
  }
610
829
 
611
830
  // src/commands/boards.ts
612
- import { Command as Command4 } from "commander";
613
- import chalk4 from "chalk";
614
- import ora3 from "ora";
615
- var boardsCommand = new Command4("boards").description("List your Trello boards").action(async () => {
831
+ import { Command as Command6 } from "commander";
832
+ import chalk6 from "chalk";
833
+ import ora5 from "ora";
834
+ var boardsCommand = new Command6("boards").description("List your Trello boards").action(async () => {
616
835
  if (!isLoggedIn()) {
617
836
  console.log(
618
- chalk4.red("Not logged in. Run `claude-trello login` first.")
837
+ chalk6.red("Not logged in. Run `claude-trello login` first.")
619
838
  );
620
839
  process.exit(1);
621
840
  }
622
- const spinner = ora3("Fetching boards...").start();
841
+ const spinner = ora5("Fetching boards...").start();
623
842
  try {
624
843
  const boards = await getBoards();
625
844
  spinner.stop();
626
845
  if (boards.length === 0) {
627
- console.log(chalk4.dim("No boards found."));
846
+ console.log(chalk6.dim("No boards found."));
628
847
  return;
629
848
  }
630
- console.log(chalk4.bold(`
849
+ console.log(chalk6.bold(`
631
850
  Your Trello Boards (${boards.length}):
632
851
  `));
633
852
  for (const board of boards) {
634
- console.log(` ${chalk4.cyan(board.name)} ${chalk4.dim(board.id)}`);
853
+ console.log(` ${chalk6.cyan(board.name)} ${chalk6.dim(board.id)}`);
635
854
  if (board.desc) {
636
- console.log(` ${chalk4.dim(board.desc.slice(0, 80))}`);
855
+ console.log(` ${chalk6.dim(board.desc.slice(0, 80))}`);
637
856
  }
638
857
  console.log();
639
858
  }
@@ -646,40 +865,40 @@ Your Trello Boards (${boards.length}):
646
865
  });
647
866
 
648
867
  // src/commands/status.ts
649
- import { Command as Command5 } from "commander";
650
- import chalk5 from "chalk";
651
- import ora4 from "ora";
652
- var statusCommand = new Command5("status").description("Check connection and integration status").action(async () => {
868
+ import { Command as Command7 } from "commander";
869
+ import chalk7 from "chalk";
870
+ import ora6 from "ora";
871
+ var statusCommand = new Command7("status").description("Check connection and integration status").action(async () => {
653
872
  const config = getConfig();
654
- console.log(chalk5.bold("\nClaude Trello Bridge \u2014 Status\n"));
655
- console.log(` Server: ${chalk5.dim(getServerUrl())}`);
873
+ console.log(chalk7.bold("\nClaude Trello Bridge \u2014 Status\n"));
874
+ console.log(` Server: ${chalk7.dim(getServerUrl())}`);
656
875
  if (!isLoggedIn()) {
657
- console.log(` Auth: ${chalk5.red("Not logged in")}`);
658
- console.log(chalk5.dim("\n Run `claude-trello login` to sign in.\n"));
876
+ console.log(` Auth: ${chalk7.red("Not logged in")}`);
877
+ console.log(chalk7.dim("\n Run `claude-trello login` to sign in.\n"));
659
878
  return;
660
879
  }
661
880
  console.log(
662
- ` Auth: ${chalk5.green("Signed in")} as ${config.userName ?? config.userEmail ?? "unknown"}`
881
+ ` Auth: ${chalk7.green("Signed in")} as ${config.userName ?? config.userEmail ?? "unknown"}`
663
882
  );
664
- const spinner = ora4("Checking integrations...").start();
883
+ const spinner = ora6("Checking integrations...").start();
665
884
  try {
666
885
  const status = await getIntegrationStatus();
667
886
  spinner.stop();
668
887
  console.log(
669
- ` Trello: ${status.trelloLinked ? chalk5.green("Connected") : chalk5.red("Not connected")}`
888
+ ` Trello: ${status.trelloLinked ? chalk7.green("Connected") : chalk7.red("Not connected")}`
670
889
  );
671
890
  console.log(
672
- ` API Key: ${status.hasApiKey ? chalk5.green("Configured") : chalk5.red("Not set")}`
891
+ ` API Key: ${status.hasApiKey ? chalk7.green("Configured") : chalk7.red("Not set")}`
673
892
  );
674
893
  if (!status.trelloLinked || !status.hasApiKey) {
675
894
  console.log(
676
- chalk5.dim(
895
+ chalk7.dim(
677
896
  "\n Complete setup at your web dashboard to use the CLI.\n"
678
897
  )
679
898
  );
680
899
  } else {
681
900
  console.log(
682
- chalk5.green("\n Ready to go! Run `claude-trello run` to start.\n")
901
+ chalk7.green("\n Ready to go! Run `claude-trello run` to start.\n")
683
902
  );
684
903
  }
685
904
  } catch (err) {
@@ -691,11 +910,13 @@ var statusCommand = new Command5("status").description("Check connection and int
691
910
  });
692
911
 
693
912
  // src/index.ts
694
- var program = new Command6();
913
+ var program = new Command8();
695
914
  program.name("claude-trello").description(
696
915
  "Bridge Trello boards and Claude Code \u2014 work through tasks from your terminal"
697
916
  ).version("0.1.0");
917
+ program.addCommand(registerCommand);
698
918
  program.addCommand(loginCommand);
919
+ program.addCommand(setupCommand);
699
920
  program.addCommand(logoutCommand);
700
921
  program.addCommand(runCommand);
701
922
  program.addCommand(boardsCommand);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "claude-trello-cli",
3
- "version": "0.1.6",
3
+ "version": "0.1.7",
4
4
  "description": "CLI for Claude Trello Bridge — point Claude Code at a Trello board and work through tasks from your terminal",
5
5
  "type": "module",
6
6
  "bin": {