claude-trello-cli 0.1.5 → 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 +31 -4
  2. package/dist/index.js +312 -77
  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.
@@ -104,12 +127,16 @@ The main command. Select a board interactively, review the cards, and launch a C
104
127
  npx claude-trello-cli run
105
128
  npx claude-trello-cli run --board 60d5e2a3f1a2b40017c3d4e5
106
129
  npx claude-trello-cli run --dir ~/projects/my-api
130
+ npx claude-trello-cli run --message "Check the development branch for comparison"
107
131
  ```
108
132
 
133
+ Without `--message`, you'll be prompted interactively before the session starts. Press Enter to skip.
134
+
109
135
  | Flag | Description |
110
136
  |------|-------------|
111
137
  | `-b, --board <id>` | Board ID — skip interactive selection |
112
138
  | `-d, --dir <path>` | Working directory (default: current directory) |
139
+ | `-m, --message <text>` | Initial instructions for Claude (e.g. "focus on API cards first") |
113
140
 
114
141
  ### `claude-trello-cli boards`
115
142
 
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 {
@@ -258,13 +477,20 @@ Do not mark items complete unless the code change has actually been made and ver
258
477
  After completing ALL checklist items on a card, call move_card_to_done with the cardId to move it to the Done list.
259
478
  Once a card is in Done, do not interact with it again \u2014 move on to the next card.
260
479
  Focus on one card at a time. Complete all its items, move it to Done, then proceed to the next.`;
261
- function buildUserPrompt(boardData) {
262
- return `Here is the Trello board with tasks to complete:
480
+ function buildUserPrompt(boardData, userMessage) {
481
+ let prompt = `Here is the Trello board with tasks to complete:
263
482
 
264
483
  ${JSON.stringify(boardData, null, 2)}`;
484
+ if (userMessage?.trim()) {
485
+ prompt += `
486
+
487
+ Additional instructions from the user:
488
+ ${userMessage.trim()}`;
489
+ }
490
+ return prompt;
265
491
  }
266
492
  function launchSession(options) {
267
- const { credentials, boardData, cwd, abortController } = options;
493
+ const { credentials, boardData, cwd, userMessage, abortController } = options;
268
494
  const trello = createTrelloClient(
269
495
  credentials.trelloApiKey,
270
496
  credentials.trelloToken
@@ -316,7 +542,7 @@ function launchSession(options) {
316
542
  tools: [checkTrelloItem, moveCardToDone]
317
543
  });
318
544
  return query({
319
- prompt: buildUserPrompt(activeBoardData),
545
+ prompt: buildUserPrompt(activeBoardData, userMessage),
320
546
  options: {
321
547
  abortController,
322
548
  cwd,
@@ -340,10 +566,10 @@ function launchSession(options) {
340
566
  }
341
567
 
342
568
  // src/commands/run.ts
343
- 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)").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) => {
344
570
  if (!isLoggedIn()) {
345
571
  console.log(
346
- chalk3.red("Not logged in. Run `claude-trello login` first.")
572
+ chalk5.red("Not logged in. Run `claude-trello login` first.")
347
573
  );
348
574
  process.exit(1);
349
575
  }
@@ -351,7 +577,7 @@ var runCommand = new Command3("run").description("Select a Trello board and star
351
577
  let boardId = opts.board;
352
578
  let boardName = "";
353
579
  if (!boardId) {
354
- const spinner = ora2("Fetching boards...").start();
580
+ const spinner = ora4("Fetching boards...").start();
355
581
  let boards;
356
582
  try {
357
583
  boards = await getBoards();
@@ -364,7 +590,7 @@ var runCommand = new Command3("run").description("Select a Trello board and star
364
590
  }
365
591
  if (boards.length === 0) {
366
592
  console.log(
367
- chalk3.red("No boards found. Create a board on Trello first.")
593
+ chalk5.red("No boards found. Create a board on Trello first.")
368
594
  );
369
595
  process.exit(1);
370
596
  }
@@ -378,7 +604,7 @@ var runCommand = new Command3("run").description("Select a Trello board and star
378
604
  });
379
605
  boardName = boards.find((b) => b.id === boardId)?.name ?? boardId;
380
606
  }
381
- const dataSpinner = ora2("Fetching cards and checklists...").start();
607
+ const dataSpinner = ora4("Fetching cards and checklists...").start();
382
608
  let cardsResponse;
383
609
  try {
384
610
  cardsResponse = await getBoardData(boardId);
@@ -392,8 +618,8 @@ var runCommand = new Command3("run").description("Select a Trello board and star
392
618
  const { cards, lists, doneListId } = cardsResponse;
393
619
  if (!boardName) boardName = boardId;
394
620
  console.log(`
395
- ${chalk3.bold(boardName)}`);
396
- console.log(chalk3.dim("\u2500".repeat(boardName.length)));
621
+ ${chalk5.bold(boardName)}`);
622
+ console.log(chalk5.dim("\u2500".repeat(boardName.length)));
397
623
  const doneCards = doneListId ? cards.filter((c) => c.idList === doneListId) : [];
398
624
  const activeCards = doneListId ? cards.filter((c) => c.idList !== doneListId) : cards;
399
625
  const listMap = /* @__PURE__ */ new Map();
@@ -408,7 +634,7 @@ ${chalk3.bold(boardName)}`);
408
634
  const listName = listMap.get(listId)?.name ?? "Unknown";
409
635
  console.log(
410
636
  `
411
- ${chalk3.cyan.bold(listName)} (${listCards.length} card${listCards.length === 1 ? "" : "s"}):`
637
+ ${chalk5.cyan.bold(listName)} (${listCards.length} card${listCards.length === 1 ? "" : "s"}):`
412
638
  );
413
639
  for (const card of listCards) {
414
640
  const total = card.checklists.reduce(
@@ -421,31 +647,37 @@ ${chalk3.bold(boardName)}`);
421
647
  );
422
648
  const progress = total > 0 ? ` [${done}/${total}]` : "";
423
649
  console.log(
424
- ` ${chalk3.white("\u2022")} ${card.name}${chalk3.dim(progress)}`
650
+ ` ${chalk5.white("\u2022")} ${card.name}${chalk5.dim(progress)}`
425
651
  );
426
652
  }
427
653
  }
428
654
  if (doneCards.length > 0) {
429
655
  console.log(
430
656
  `
431
- ${chalk3.dim(`Done (${doneCards.length} card${doneCards.length === 1 ? "" : "s"}) [skipped]`)}`
657
+ ${chalk5.dim(`Done (${doneCards.length} card${doneCards.length === 1 ? "" : "s"}) [skipped]`)}`
432
658
  );
433
659
  }
434
660
  if (activeCards.length === 0) {
435
- console.log(chalk3.dim("\n No active cards to work on."));
661
+ console.log(chalk5.dim("\n No active cards to work on."));
436
662
  return;
437
663
  }
438
664
  console.log(`
439
- ${chalk3.dim(`Working directory: ${cwd}`)}`);
440
- const proceed = await confirm({
665
+ ${chalk5.dim(`Working directory: ${cwd}`)}`);
666
+ const proceed = await confirm2({
441
667
  message: `Start Claude Code session? (${activeCards.length} active card${activeCards.length === 1 ? "" : "s"})`,
442
668
  default: true
443
669
  });
444
670
  if (!proceed) {
445
- console.log(chalk3.dim("Cancelled."));
671
+ console.log(chalk5.dim("Cancelled."));
446
672
  return;
447
673
  }
448
- const credSpinner = ora2("Loading credentials...").start();
674
+ let userMessage = opts.message;
675
+ if (!userMessage) {
676
+ userMessage = await input3({
677
+ message: "Instructions for Claude (optional \u2014 press Enter to skip):"
678
+ });
679
+ }
680
+ const credSpinner = ora4("Loading credentials...").start();
449
681
  let credentials;
450
682
  try {
451
683
  credentials = await getCredentials();
@@ -462,11 +694,11 @@ ${chalk3.bold(boardName)}`);
462
694
  doneListId: doneListId ?? void 0
463
695
  };
464
696
  console.log(`
465
- ${chalk3.bold.blue("Starting Claude Code session...")}
697
+ ${chalk5.bold.blue("Starting Claude Code session...")}
466
698
  `);
467
699
  const abortController = new AbortController();
468
700
  const sigintHandler = () => {
469
- console.log(chalk3.dim("\n\nAborting session..."));
701
+ console.log(chalk5.dim("\n\nAborting session..."));
470
702
  abortController.abort();
471
703
  };
472
704
  process.on("SIGINT", sigintHandler);
@@ -475,20 +707,21 @@ ${chalk3.bold.blue("Starting Claude Code session...")}
475
707
  credentials,
476
708
  boardData,
477
709
  cwd,
710
+ userMessage: userMessage || void 0,
478
711
  abortController
479
712
  });
480
713
  for await (const message of session) {
481
714
  await handleMessage(message, session);
482
715
  }
483
716
  console.log(`
484
- ${chalk3.green.bold("Session complete.")}
717
+ ${chalk5.green.bold("Session complete.")}
485
718
  `);
486
719
  } catch (err) {
487
720
  if (abortController.signal.aborted) {
488
- console.log(chalk3.dim("\nSession aborted."));
721
+ console.log(chalk5.dim("\nSession aborted."));
489
722
  } else {
490
723
  console.error(
491
- chalk3.red(
724
+ chalk5.red(
492
725
  `
493
726
  Session error: ${err instanceof Error ? err.message : "Unknown error"}`
494
727
  )
@@ -504,7 +737,7 @@ async function handleMessage(message, session) {
504
737
  case "system": {
505
738
  if (message.subtype === "init") {
506
739
  console.log(
507
- chalk3.dim(
740
+ chalk5.dim(
508
741
  ` Session initialized (model: ${message.model})
509
742
  `
510
743
  )
@@ -523,17 +756,17 @@ async function handleMessage(message, session) {
523
756
  const name = block.name;
524
757
  const toolInput = block.input ?? {};
525
758
  if (name === "mcp__trello-tools__check_trello_item") {
526
- console.log(chalk3.green(` \u2713 Checked item on Trello`));
759
+ console.log(chalk5.green(` \u2713 Checked item on Trello`));
527
760
  } else if (name === "mcp__trello-tools__move_card_to_done") {
528
- console.log(chalk3.green.bold(` \u2713 Moved card to Done`));
761
+ console.log(chalk5.green.bold(` \u2713 Moved card to Done`));
529
762
  } else if (name === "AskUserQuestion") {
530
763
  const questions = toolInput.questions;
531
764
  if (questions && questions.length > 0) {
532
765
  const questionText = questions.map((q) => q.question).join("\n");
533
- console.log(chalk3.yellow(`
766
+ console.log(chalk5.yellow(`
534
767
  ? ${questionText}
535
768
  `));
536
- const answer = await input2({ message: ">" });
769
+ const answer = await input3({ message: ">" });
537
770
  async function* userInput() {
538
771
  yield {
539
772
  type: "user",
@@ -556,7 +789,7 @@ async function handleMessage(message, session) {
556
789
  }
557
790
  case "result": {
558
791
  const result = message.result ?? message.subtype;
559
- console.log(chalk3.dim(`
792
+ console.log(chalk5.dim(`
560
793
  Result: ${result}`));
561
794
  break;
562
795
  }
@@ -564,62 +797,62 @@ async function handleMessage(message, session) {
564
797
  }
565
798
  function formatToolUse(name, toolInput) {
566
799
  const path = toolInput.file_path ?? toolInput.path ?? toolInput.pattern ?? "";
567
- const shortPath = path ? ` ${chalk3.cyan(path)}` : "";
800
+ const shortPath = path ? ` ${chalk5.cyan(path)}` : "";
568
801
  switch (name) {
569
802
  case "Read":
570
- return chalk3.dim(` Reading${shortPath}`);
803
+ return chalk5.dim(` Reading${shortPath}`);
571
804
  case "Edit":
572
- return chalk3.dim(` Editing${shortPath}`);
805
+ return chalk5.dim(` Editing${shortPath}`);
573
806
  case "Write":
574
- return chalk3.dim(` Writing${shortPath}`);
807
+ return chalk5.dim(` Writing${shortPath}`);
575
808
  case "Glob":
576
- return chalk3.dim(` Searching files${shortPath}`);
809
+ return chalk5.dim(` Searching files${shortPath}`);
577
810
  case "Grep":
578
- return chalk3.dim(
579
- ` 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)}` : ""}`
580
813
  );
581
814
  case "Bash": {
582
815
  const cmd = toolInput.command || "";
583
816
  const preview = cmd.length > 80 ? cmd.slice(0, 77) + "..." : cmd;
584
- return chalk3.dim(` Running ${chalk3.cyan(preview)}`);
817
+ return chalk5.dim(` Running ${chalk5.cyan(preview)}`);
585
818
  }
586
819
  case "TodoWrite":
587
- return chalk3.dim(" Updating task list");
820
+ return chalk5.dim(" Updating task list");
588
821
  case "Agent":
589
- return chalk3.dim(
822
+ return chalk5.dim(
590
823
  ` Spawning agent${toolInput.description ? `: ${toolInput.description}` : ""}`
591
824
  );
592
825
  default:
593
- return chalk3.dim(` [${name}]${shortPath}`);
826
+ return chalk5.dim(` [${name}]${shortPath}`);
594
827
  }
595
828
  }
596
829
 
597
830
  // src/commands/boards.ts
598
- import { Command as Command4 } from "commander";
599
- import chalk4 from "chalk";
600
- import ora3 from "ora";
601
- 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 () => {
602
835
  if (!isLoggedIn()) {
603
836
  console.log(
604
- chalk4.red("Not logged in. Run `claude-trello login` first.")
837
+ chalk6.red("Not logged in. Run `claude-trello login` first.")
605
838
  );
606
839
  process.exit(1);
607
840
  }
608
- const spinner = ora3("Fetching boards...").start();
841
+ const spinner = ora5("Fetching boards...").start();
609
842
  try {
610
843
  const boards = await getBoards();
611
844
  spinner.stop();
612
845
  if (boards.length === 0) {
613
- console.log(chalk4.dim("No boards found."));
846
+ console.log(chalk6.dim("No boards found."));
614
847
  return;
615
848
  }
616
- console.log(chalk4.bold(`
849
+ console.log(chalk6.bold(`
617
850
  Your Trello Boards (${boards.length}):
618
851
  `));
619
852
  for (const board of boards) {
620
- console.log(` ${chalk4.cyan(board.name)} ${chalk4.dim(board.id)}`);
853
+ console.log(` ${chalk6.cyan(board.name)} ${chalk6.dim(board.id)}`);
621
854
  if (board.desc) {
622
- console.log(` ${chalk4.dim(board.desc.slice(0, 80))}`);
855
+ console.log(` ${chalk6.dim(board.desc.slice(0, 80))}`);
623
856
  }
624
857
  console.log();
625
858
  }
@@ -632,40 +865,40 @@ Your Trello Boards (${boards.length}):
632
865
  });
633
866
 
634
867
  // src/commands/status.ts
635
- import { Command as Command5 } from "commander";
636
- import chalk5 from "chalk";
637
- import ora4 from "ora";
638
- 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 () => {
639
872
  const config = getConfig();
640
- console.log(chalk5.bold("\nClaude Trello Bridge \u2014 Status\n"));
641
- console.log(` Server: ${chalk5.dim(getServerUrl())}`);
873
+ console.log(chalk7.bold("\nClaude Trello Bridge \u2014 Status\n"));
874
+ console.log(` Server: ${chalk7.dim(getServerUrl())}`);
642
875
  if (!isLoggedIn()) {
643
- console.log(` Auth: ${chalk5.red("Not logged in")}`);
644
- 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"));
645
878
  return;
646
879
  }
647
880
  console.log(
648
- ` Auth: ${chalk5.green("Signed in")} as ${config.userName ?? config.userEmail ?? "unknown"}`
881
+ ` Auth: ${chalk7.green("Signed in")} as ${config.userName ?? config.userEmail ?? "unknown"}`
649
882
  );
650
- const spinner = ora4("Checking integrations...").start();
883
+ const spinner = ora6("Checking integrations...").start();
651
884
  try {
652
885
  const status = await getIntegrationStatus();
653
886
  spinner.stop();
654
887
  console.log(
655
- ` Trello: ${status.trelloLinked ? chalk5.green("Connected") : chalk5.red("Not connected")}`
888
+ ` Trello: ${status.trelloLinked ? chalk7.green("Connected") : chalk7.red("Not connected")}`
656
889
  );
657
890
  console.log(
658
- ` API Key: ${status.hasApiKey ? chalk5.green("Configured") : chalk5.red("Not set")}`
891
+ ` API Key: ${status.hasApiKey ? chalk7.green("Configured") : chalk7.red("Not set")}`
659
892
  );
660
893
  if (!status.trelloLinked || !status.hasApiKey) {
661
894
  console.log(
662
- chalk5.dim(
895
+ chalk7.dim(
663
896
  "\n Complete setup at your web dashboard to use the CLI.\n"
664
897
  )
665
898
  );
666
899
  } else {
667
900
  console.log(
668
- 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")
669
902
  );
670
903
  }
671
904
  } catch (err) {
@@ -677,11 +910,13 @@ var statusCommand = new Command5("status").description("Check connection and int
677
910
  });
678
911
 
679
912
  // src/index.ts
680
- var program = new Command6();
913
+ var program = new Command8();
681
914
  program.name("claude-trello").description(
682
915
  "Bridge Trello boards and Claude Code \u2014 work through tasks from your terminal"
683
916
  ).version("0.1.0");
917
+ program.addCommand(registerCommand);
684
918
  program.addCommand(loginCommand);
919
+ program.addCommand(setupCommand);
685
920
  program.addCommand(logoutCommand);
686
921
  program.addCommand(runCommand);
687
922
  program.addCommand(boardsCommand);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "claude-trello-cli",
3
- "version": "0.1.5",
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": {