@punkcode/cli 0.1.19 → 0.1.21

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.
@@ -10,7 +10,7 @@ import {
10
10
  signIn,
11
11
  usePunkStore,
12
12
  version
13
- } from "./chunk-X7HMRB3J.js";
13
+ } from "./chunk-DU2STEE5.js";
14
14
 
15
15
  // src/ui/App.tsx
16
16
  import { useEffect as useEffect3, useRef as useRef2, useState as useState3 } from "react";
@@ -46,6 +46,7 @@ function LoginDialog({ store, server }) {
46
46
  const [colorIdx, setColorIdx] = useState(0);
47
47
  const [email, setEmail] = useState("");
48
48
  const [polling, setPolling] = useState(false);
49
+ const [pairingCode, setPairingCode] = useState("");
49
50
  const [welcomeEmail, setWelcomeEmail] = useState("");
50
51
  useEffect(() => {
51
52
  if (mode !== "success") return;
@@ -68,6 +69,7 @@ function LoginDialog({ store, server }) {
68
69
  try {
69
70
  const session = await initQrSession(server);
70
71
  setQrString(session.qrString);
72
+ setPairingCode(session.pairingCode);
71
73
  setPolling(true);
72
74
  const ac = new AbortController();
73
75
  for await (const result of session.poll(ac.signal)) {
@@ -146,11 +148,22 @@ function LoginDialog({ store, server }) {
146
148
  error
147
149
  ] }) }),
148
150
  mode === "qr" && /* @__PURE__ */ jsxs(Box, { flexDirection: "column", alignItems: "center", children: [
149
- /* @__PURE__ */ jsx(Text, { children: "Scan with the Punk app to connect:" }),
151
+ /* @__PURE__ */ jsx(Text, { bold: true, children: "Scan with the Punk app" }),
152
+ /* @__PURE__ */ jsxs(Text, { dimColor: true, children: [
153
+ "Devices ",
154
+ "\u2192",
155
+ " Add Device ",
156
+ "\u2192",
157
+ " Scan"
158
+ ] }),
150
159
  /* @__PURE__ */ jsx(Text, { children: " " }),
151
160
  qrString ? /* @__PURE__ */ jsx(Text, { color: QR_COLORS[colorIdx], children: qrString }) : /* @__PURE__ */ jsx(Spinner, { label: "Generating QR code..." }),
152
161
  /* @__PURE__ */ jsx(Text, { children: " " }),
153
- polling && /* @__PURE__ */ jsx(Spinner, { label: "Waiting for confirmation..." }),
162
+ polling && /* @__PURE__ */ jsx(Text, { dimColor: true, children: "Waiting for confirmation..." }),
163
+ pairingCode && /* @__PURE__ */ jsxs(Box, { children: [
164
+ /* @__PURE__ */ jsx(Text, { dimColor: true, children: "Can't scan? Enter code: " }),
165
+ /* @__PURE__ */ jsx(Text, { bold: true, children: pairingCode })
166
+ ] }),
154
167
  /* @__PURE__ */ jsx(Text, { children: " " }),
155
168
  /* @__PURE__ */ jsxs(Text, { children: [
156
169
  /* @__PURE__ */ jsx(Text, { color: theme.accent, bold: true, children: "e" }),
@@ -219,11 +232,12 @@ function getColumns(width) {
219
232
  return { id: 8, project: 12, status: 10, started: 8, model: 0, effort: 0, showExtras: false };
220
233
  }
221
234
  var LOGO = [
222
- "\u2588\u2588\u2588\u2588\u2588\u2588 \u2588\u2588 \u2588\u2588 \u2588\u2588 \u2588\u2588 \u2588\u2588 \u2588\u2588",
223
- "\u2588\u2588 \u2588\u2588 \u2588\u2588 \u2588\u2588 \u2588\u2588\u2588 \u2588\u2588 \u2588\u2588 \u2588\u2588 ",
224
- "\u2588\u2588\u2588\u2588\u2588\u2588 \u2588\u2588 \u2588\u2588 \u2588\u2588\u2588\u2588\u2588\u2588 \u2588\u2588\u2588\u2588 ",
225
- "\u2588\u2588 \u2588\u2588 \u2588\u2588 \u2588\u2588 \u2588\u2588\u2588 \u2588\u2588 \u2588\u2588 ",
226
- "\u2588\u2588 \u2588\u2588\u2588\u2588 \u2588\u2588 \u2588\u2588 \u2588\u2588 \u2588\u2588"
235
+ "\u2588\u2588\u2588\u2588\u2588\u2588\u2557 \u2588\u2588\u2557 \u2588\u2588\u2557\u2588\u2588\u2588\u2557 \u2588\u2588\u2557\u2588\u2588\u2557 \u2588\u2588\u2557",
236
+ "\u2588\u2588\u2554\u2550\u2550\u2588\u2588\u2557\u2588\u2588\u2551 \u2588\u2588\u2551\u2588\u2588\u2588\u2588\u2557 \u2588\u2588\u2551\u2588\u2588\u2551 \u2588\u2588\u2554\u255D",
237
+ "\u2588\u2588\u2588\u2588\u2588\u2588\u2554\u255D\u2588\u2588\u2551 \u2588\u2588\u2551\u2588\u2588\u2554\u2588\u2588\u2557 \u2588\u2588\u2551\u2588\u2588\u2588\u2588\u2588\u2554\u255D ",
238
+ "\u2588\u2588\u2554\u2550\u2550\u2550\u255D \u2588\u2588\u2551 \u2588\u2588\u2551\u2588\u2588\u2551\u255A\u2588\u2588\u2557\u2588\u2588\u2551\u2588\u2588\u2554\u2550\u2588\u2588\u2557 ",
239
+ "\u2588\u2588\u2551 \u255A\u2588\u2588\u2588\u2588\u2588\u2588\u2554\u255D\u2588\u2588\u2551 \u255A\u2588\u2588\u2588\u2588\u2551\u2588\u2588\u2551 \u2588\u2588\u2557",
240
+ "\u255A\u2550\u255D \u255A\u2550\u2550\u2550\u2550\u2550\u255D \u255A\u2550\u255D \u255A\u2550\u2550\u2550\u255D\u255A\u2550\u255D \u255A\u2550\u255D"
227
241
  ];
228
242
  function Dashboard({ store, connection, overlay }) {
229
243
  const { exit } = useApp();
@@ -270,6 +284,7 @@ function Dashboard({ store, connection, overlay }) {
270
284
  connection?.disconnect();
271
285
  exit();
272
286
  }
287
+ if (overlay) return;
273
288
  if (input === "r") connection?.reconnect();
274
289
  if (input === "c" && !key.ctrl) {
275
290
  store.getState().clearActivity();
@@ -330,104 +345,111 @@ function Dashboard({ store, connection, overlay }) {
330
345
  viewStart = Math.max(0, viewStart);
331
346
  const visibleActivity = filteredActivity.slice(viewStart, viewStart + adjustedVisibleCount);
332
347
  return /* @__PURE__ */ jsxs2(Box2, { flexDirection: "column", width: termWidth, height: termHeight, children: [
333
- /* @__PURE__ */ jsxs2(Box2, { flexDirection: "row", justifyContent: "space-between", width: termWidth - 2, paddingX: 1, children: [
334
- /* @__PURE__ */ jsxs2(Box2, { flexDirection: "column", children: [
335
- auth && /* @__PURE__ */ jsxs2(Box2, { children: [
336
- /* @__PURE__ */ jsx2(Text2, { dimColor: true, children: "User: ".padEnd(12) }),
337
- /* @__PURE__ */ jsx2(Text2, { children: auth.email })
338
- ] }),
339
- /* @__PURE__ */ jsxs2(Box2, { children: [
340
- /* @__PURE__ */ jsx2(Text2, { dimColor: true, children: "Server: ".padEnd(12) }),
341
- /* @__PURE__ */ jsx2(Text2, { children: stripProtocol(server) })
342
- ] }),
343
- /* @__PURE__ */ jsxs2(Box2, { children: [
344
- /* @__PURE__ */ jsx2(Text2, { dimColor: true, children: "Status: ".padEnd(12) }),
345
- /* @__PURE__ */ jsx2(StatusIndicator, { status: connectionStatus, error: connectionError })
346
- ] }),
347
- /* @__PURE__ */ jsxs2(Box2, { children: [
348
- /* @__PURE__ */ jsx2(Text2, { dimColor: true, children: "Uptime: ".padEnd(12) }),
349
- /* @__PURE__ */ jsx2(Text2, { children: uptime })
350
- ] }),
351
- deviceInfo && /* @__PURE__ */ jsxs2(Box2, { children: [
352
- /* @__PURE__ */ jsx2(Text2, { dimColor: true, children: "Device: ".padEnd(12) }),
353
- /* @__PURE__ */ jsx2(Text2, { children: deviceInfo.name })
348
+ overlay ? (
349
+ /* Minimal header during login */
350
+ /* @__PURE__ */ jsxs2(Box2, { flexDirection: "row", justifyContent: "space-between", width: termWidth - 2, paddingX: 1, children: [
351
+ /* @__PURE__ */ jsxs2(Box2, { flexDirection: "column", children: [
352
+ /* @__PURE__ */ jsx2(Text2, { bold: true, color: theme.primary, children: "punk" }),
353
+ /* @__PURE__ */ jsxs2(Box2, { children: [
354
+ /* @__PURE__ */ jsx2(Text2, { dimColor: true, children: "Server: ".padEnd(12) }),
355
+ /* @__PURE__ */ jsx2(Text2, { children: stripProtocol(server) })
356
+ ] })
354
357
  ] }),
355
- termWidth >= 80 && deviceInfo && /* @__PURE__ */ jsxs2(Box2, { children: [
356
- /* @__PURE__ */ jsx2(Text2, { dimColor: true, children: "Platform: ".padEnd(12) }),
357
- /* @__PURE__ */ jsxs2(Text2, { children: [
358
- deviceInfo.platform,
359
- " ",
360
- deviceInfo.arch,
361
- " ",
362
- deviceInfo.memoryGB,
363
- "GB"
358
+ termWidth >= 120 && /* @__PURE__ */ jsx2(Box2, { flexDirection: "column", alignItems: "flex-end", justifyContent: "center", children: LOGO.map((line, i) => /* @__PURE__ */ jsx2(Text2, { color: theme.logo, children: line }, i)) })
359
+ ] })
360
+ ) : (
361
+ /* Full header when connected */
362
+ /* @__PURE__ */ jsxs2(Box2, { flexDirection: "row", justifyContent: "space-between", width: termWidth - 2, paddingX: 1, children: [
363
+ /* @__PURE__ */ jsxs2(Box2, { flexDirection: "column", children: [
364
+ auth && /* @__PURE__ */ jsxs2(Box2, { children: [
365
+ /* @__PURE__ */ jsx2(Text2, { dimColor: true, children: "User: ".padEnd(12) }),
366
+ /* @__PURE__ */ jsx2(Text2, { children: auth.email })
367
+ ] }),
368
+ /* @__PURE__ */ jsxs2(Box2, { children: [
369
+ /* @__PURE__ */ jsx2(Text2, { dimColor: true, children: "Server: ".padEnd(12) }),
370
+ /* @__PURE__ */ jsx2(Text2, { children: stripProtocol(server) })
371
+ ] }),
372
+ /* @__PURE__ */ jsxs2(Box2, { children: [
373
+ /* @__PURE__ */ jsx2(Text2, { dimColor: true, children: "Status: ".padEnd(12) }),
374
+ /* @__PURE__ */ jsx2(StatusIndicator, { status: connectionStatus, error: connectionError })
375
+ ] }),
376
+ /* @__PURE__ */ jsxs2(Box2, { children: [
377
+ /* @__PURE__ */ jsx2(Text2, { dimColor: true, children: "Uptime: ".padEnd(12) }),
378
+ /* @__PURE__ */ jsx2(Text2, { children: uptime })
379
+ ] }),
380
+ deviceInfo && /* @__PURE__ */ jsxs2(Box2, { children: [
381
+ /* @__PURE__ */ jsx2(Text2, { dimColor: true, children: "Device: ".padEnd(12) }),
382
+ /* @__PURE__ */ jsx2(Text2, { children: deviceInfo.name })
383
+ ] }),
384
+ termWidth >= 80 && deviceInfo && /* @__PURE__ */ jsxs2(Box2, { children: [
385
+ /* @__PURE__ */ jsx2(Text2, { dimColor: true, children: "Platform: ".padEnd(12) }),
386
+ /* @__PURE__ */ jsxs2(Text2, { children: [
387
+ deviceInfo.platform,
388
+ " ",
389
+ deviceInfo.arch,
390
+ " ",
391
+ deviceInfo.memoryGB,
392
+ "GB"
393
+ ] })
394
+ ] }),
395
+ termWidth >= 80 && deviceInfo?.claudeCodeVersion && /* @__PURE__ */ jsxs2(Box2, { children: [
396
+ /* @__PURE__ */ jsx2(Text2, { dimColor: true, children: "Claude: ".padEnd(12) }),
397
+ /* @__PURE__ */ jsx2(Text2, { color: "#E07B39", children: deviceInfo.claudeCodeVersion })
398
+ ] }),
399
+ termWidth >= 80 && deviceInfo && deviceInfo.platform === "darwin" && /* @__PURE__ */ jsxs2(Box2, { children: [
400
+ /* @__PURE__ */ jsx2(Text2, { dimColor: true, children: "Sleep: ".padEnd(12) }),
401
+ /* @__PURE__ */ jsx2(Text2, { color: theme.success, children: "caffeinate active" })
364
402
  ] })
365
403
  ] }),
366
- termWidth >= 80 && deviceInfo?.battery && /* @__PURE__ */ jsxs2(Box2, { children: [
367
- /* @__PURE__ */ jsx2(Text2, { dimColor: true, children: "Battery: ".padEnd(12) }),
404
+ termWidth >= 80 && /* @__PURE__ */ jsx2(Box2, { flexDirection: "column", children: termWidth >= 100 ? /* @__PURE__ */ jsxs2(Fragment, { children: [
405
+ /* @__PURE__ */ jsxs2(Box2, { children: [
406
+ /* @__PURE__ */ jsx2(Text2, { color: theme.accent, bold: true, children: "<q> ".padEnd(10) }),
407
+ /* @__PURE__ */ jsx2(Text2, { dimColor: true, children: "Quit" })
408
+ ] }),
409
+ /* @__PURE__ */ jsxs2(Box2, { children: [
410
+ /* @__PURE__ */ jsx2(Text2, { color: theme.accent, bold: true, children: "<r> ".padEnd(10) }),
411
+ /* @__PURE__ */ jsx2(Text2, { dimColor: true, children: "Reconnect" })
412
+ ] }),
413
+ /* @__PURE__ */ jsxs2(Box2, { children: [
414
+ /* @__PURE__ */ jsx2(Text2, { color: theme.accent, bold: true, children: "<c> ".padEnd(10) }),
415
+ /* @__PURE__ */ jsx2(Text2, { dimColor: true, children: "Clear Activity" })
416
+ ] }),
417
+ /* @__PURE__ */ jsxs2(Box2, { children: [
418
+ /* @__PURE__ */ jsx2(Text2, { color: theme.accent, bold: true, children: "<g> ".padEnd(10) }),
419
+ /* @__PURE__ */ jsx2(Text2, { dimColor: true, children: "Group Activity" })
420
+ ] }),
421
+ /* @__PURE__ */ jsxs2(Box2, { children: [
422
+ /* @__PURE__ */ jsx2(Text2, { color: theme.accent, bold: true, children: "<l> ".padEnd(10) }),
423
+ /* @__PURE__ */ jsx2(Text2, { dimColor: true, children: "Logout" })
424
+ ] }),
425
+ /* @__PURE__ */ jsxs2(Box2, { children: [
426
+ /* @__PURE__ */ jsx2(Text2, { color: theme.accent, bold: true, children: "<enter> ".padEnd(10) }),
427
+ /* @__PURE__ */ jsx2(Text2, { dimColor: true, children: "Activity Details" })
428
+ ] })
429
+ ] }) : /* @__PURE__ */ jsxs2(Fragment, { children: [
430
+ /* @__PURE__ */ jsxs2(Text2, { children: [
431
+ /* @__PURE__ */ jsx2(Text2, { color: theme.accent, bold: true, children: "q" }),
432
+ /* @__PURE__ */ jsx2(Text2, { dimColor: true, children: " quit " }),
433
+ /* @__PURE__ */ jsx2(Text2, { color: theme.accent, bold: true, children: "r" }),
434
+ /* @__PURE__ */ jsx2(Text2, { dimColor: true, children: " reconnect" })
435
+ ] }),
368
436
  /* @__PURE__ */ jsxs2(Text2, { children: [
369
- deviceInfo.battery.level,
370
- "%",
371
- deviceInfo.battery.charging ? " \u26A1" : ""
437
+ /* @__PURE__ */ jsx2(Text2, { color: theme.accent, bold: true, children: "c" }),
438
+ /* @__PURE__ */ jsx2(Text2, { dimColor: true, children: " clear " }),
439
+ /* @__PURE__ */ jsx2(Text2, { color: theme.accent, bold: true, children: "g" }),
440
+ /* @__PURE__ */ jsx2(Text2, { dimColor: true, children: " group" })
441
+ ] }),
442
+ /* @__PURE__ */ jsxs2(Text2, { children: [
443
+ /* @__PURE__ */ jsx2(Text2, { color: theme.accent, bold: true, children: "l" }),
444
+ /* @__PURE__ */ jsx2(Text2, { dimColor: true, children: " logout " }),
445
+ /* @__PURE__ */ jsx2(Text2, { color: theme.accent, bold: true, children: "enter" }),
446
+ /* @__PURE__ */ jsx2(Text2, { dimColor: true, children: " details" })
372
447
  ] })
373
- ] }),
374
- termWidth >= 80 && deviceInfo?.claudeCodeVersion && /* @__PURE__ */ jsxs2(Box2, { children: [
375
- /* @__PURE__ */ jsx2(Text2, { dimColor: true, children: "Claude: ".padEnd(12) }),
376
- /* @__PURE__ */ jsx2(Text2, { color: "#E07B39", children: deviceInfo.claudeCodeVersion })
377
- ] }),
378
- termWidth >= 80 && deviceInfo && deviceInfo.platform === "darwin" && /* @__PURE__ */ jsxs2(Box2, { children: [
379
- /* @__PURE__ */ jsx2(Text2, { dimColor: true, children: "Sleep: ".padEnd(12) }),
380
- /* @__PURE__ */ jsx2(Text2, { color: theme.success, children: "caffeinate active" })
381
- ] })
382
- ] }),
383
- termWidth >= 80 && /* @__PURE__ */ jsx2(Box2, { flexDirection: "column", children: termWidth >= 100 ? /* @__PURE__ */ jsxs2(Fragment, { children: [
384
- /* @__PURE__ */ jsxs2(Box2, { children: [
385
- /* @__PURE__ */ jsx2(Text2, { color: theme.accent, bold: true, children: "<q> ".padEnd(10) }),
386
- /* @__PURE__ */ jsx2(Text2, { dimColor: true, children: "Quit" })
387
- ] }),
388
- /* @__PURE__ */ jsxs2(Box2, { children: [
389
- /* @__PURE__ */ jsx2(Text2, { color: theme.accent, bold: true, children: "<r> ".padEnd(10) }),
390
- /* @__PURE__ */ jsx2(Text2, { dimColor: true, children: "Reconnect" })
391
- ] }),
392
- /* @__PURE__ */ jsxs2(Box2, { children: [
393
- /* @__PURE__ */ jsx2(Text2, { color: theme.accent, bold: true, children: "<c> ".padEnd(10) }),
394
- /* @__PURE__ */ jsx2(Text2, { dimColor: true, children: "Clear Activity" })
395
- ] }),
396
- /* @__PURE__ */ jsxs2(Box2, { children: [
397
- /* @__PURE__ */ jsx2(Text2, { color: theme.accent, bold: true, children: "<g> ".padEnd(10) }),
398
- /* @__PURE__ */ jsx2(Text2, { dimColor: true, children: "Group Activity" })
399
- ] }),
400
- /* @__PURE__ */ jsxs2(Box2, { children: [
401
- /* @__PURE__ */ jsx2(Text2, { color: theme.accent, bold: true, children: "<l> ".padEnd(10) }),
402
- /* @__PURE__ */ jsx2(Text2, { dimColor: true, children: "Logout" })
403
- ] }),
404
- /* @__PURE__ */ jsxs2(Box2, { children: [
405
- /* @__PURE__ */ jsx2(Text2, { color: theme.accent, bold: true, children: "<enter> ".padEnd(10) }),
406
- /* @__PURE__ */ jsx2(Text2, { dimColor: true, children: "Activity Details" })
407
- ] })
408
- ] }) : /* @__PURE__ */ jsxs2(Fragment, { children: [
409
- /* @__PURE__ */ jsxs2(Text2, { children: [
410
- /* @__PURE__ */ jsx2(Text2, { color: theme.accent, bold: true, children: "q" }),
411
- /* @__PURE__ */ jsx2(Text2, { dimColor: true, children: " quit " }),
412
- /* @__PURE__ */ jsx2(Text2, { color: theme.accent, bold: true, children: "r" }),
413
- /* @__PURE__ */ jsx2(Text2, { dimColor: true, children: " reconnect" })
414
- ] }),
415
- /* @__PURE__ */ jsxs2(Text2, { children: [
416
- /* @__PURE__ */ jsx2(Text2, { color: theme.accent, bold: true, children: "c" }),
417
- /* @__PURE__ */ jsx2(Text2, { dimColor: true, children: " clear " }),
418
- /* @__PURE__ */ jsx2(Text2, { color: theme.accent, bold: true, children: "g" }),
419
- /* @__PURE__ */ jsx2(Text2, { dimColor: true, children: " group" })
420
- ] }),
421
- /* @__PURE__ */ jsxs2(Text2, { children: [
422
- /* @__PURE__ */ jsx2(Text2, { color: theme.accent, bold: true, children: "l" }),
423
- /* @__PURE__ */ jsx2(Text2, { dimColor: true, children: " logout " }),
424
- /* @__PURE__ */ jsx2(Text2, { color: theme.accent, bold: true, children: "enter" }),
425
- /* @__PURE__ */ jsx2(Text2, { dimColor: true, children: " details" })
426
- ] })
427
- ] }) }),
428
- termWidth >= 120 && /* @__PURE__ */ jsx2(Box2, { flexDirection: "column", alignItems: "flex-end", justifyContent: "center", children: LOGO.map((line, i) => /* @__PURE__ */ jsx2(Text2, { color: theme.logo, children: line }, i)) })
429
- ] }),
430
- /* @__PURE__ */ jsxs2(Box2, { flexDirection: "column", marginX: 1, marginTop: 1, children: [
448
+ ] }) }),
449
+ termWidth >= 120 && /* @__PURE__ */ jsx2(Box2, { flexDirection: "column", alignItems: "flex-end", justifyContent: "center", children: LOGO.map((line, i) => /* @__PURE__ */ jsx2(Text2, { color: theme.logo, children: line }, i)) })
450
+ ] })
451
+ ),
452
+ !overlay && /* @__PURE__ */ jsxs2(Box2, { flexDirection: "column", marginX: 1, marginTop: 1, children: [
431
453
  buildTopBorderJsx(`Sessions (${sessionList.length})`, boxWidth),
432
454
  /* @__PURE__ */ jsxs2(
433
455
  Box2,
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
 
3
3
  // src/version.ts
4
- var version = "0.1.19";
4
+ var version = "0.1.21";
5
5
 
6
6
  // src/lib/auth.ts
7
7
  import fs from "fs";
package/dist/cli.js CHANGED
@@ -8,7 +8,7 @@ import {
8
8
  refreshIdToken,
9
9
  signIn,
10
10
  version
11
- } from "./chunk-X7HMRB3J.js";
11
+ } from "./chunk-DU2STEE5.js";
12
12
 
13
13
  // src/cli.ts
14
14
  import { program } from "commander";
@@ -135,7 +135,7 @@ async function runHeadless(server, idToken, options) {
135
135
  async function runTui(server, options) {
136
136
  const { render } = await import("ink");
137
137
  const { createElement } = await import("react");
138
- const { App } = await import("./App-F6AWDTRZ.js");
138
+ const { App } = await import("./App-624TTCIE.js");
139
139
  const idToken = options.token ? options.token : void 0;
140
140
  process.stdout.write("\x1B[?1049h");
141
141
  process.stdout.write("\x1B[H");
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@punkcode/cli",
3
- "version": "0.1.19",
3
+ "version": "0.1.21",
4
4
  "description": "Control Claude Code from your phone",
5
5
  "type": "module",
6
6
  "bin": {