@punkcode/cli 0.1.21 → 0.1.22

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-DU2STEE5.js";
13
+ } from "./chunk-4FFAG2HK.js";
14
14
 
15
15
  // src/ui/App.tsx
16
16
  import { useEffect as useEffect3, useRef as useRef2, useState as useState3 } from "react";
@@ -221,7 +221,7 @@ function PasswordInput({ onSubmit }) {
221
221
  }
222
222
 
223
223
  // src/ui/Dashboard.tsx
224
- import { useState as useState2, useEffect as useEffect2, useRef } from "react";
224
+ import { useState as useState2, useEffect as useEffect2, useRef, useMemo } from "react";
225
225
  import { Box as Box2, Text as Text2, useApp, useInput as useInput2, useStdout } from "ink";
226
226
  import { Badge } from "@inkjs/ui";
227
227
  import { Fragment, jsx as jsx2, jsxs as jsxs2 } from "react/jsx-runtime";
@@ -239,6 +239,7 @@ var LOGO = [
239
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
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"
241
241
  ];
242
+ var LOGO_JSX = LOGO.map((line, i) => /* @__PURE__ */ jsx2(Text2, { color: theme.logo, children: line }, i));
242
243
  function Dashboard({ store, connection, overlay }) {
243
244
  const { exit } = useApp();
244
245
  const { stdout } = useStdout();
@@ -250,20 +251,17 @@ function Dashboard({ store, connection, overlay }) {
250
251
  const sessions = usePunkStore(store, (s) => s.sessions);
251
252
  const activityLog = usePunkStore(store, (s) => s.activityLog);
252
253
  const server = usePunkStore(store, (s) => s.server);
253
- const connectedAt = usePunkStore(store, (s) => s.connectedAt);
254
254
  const auth = usePunkStore(store, (s) => s.auth);
255
255
  const sessionProjects = usePunkStore(store, (s) => s.sessionProjects);
256
256
  const [focusMode, setFocusMode] = useState2(false);
257
257
  const [focusedSessionIdx, setFocusedSessionIdx] = useState2(0);
258
- const knownSessionIds = Object.keys(sessionProjects);
258
+ const knownSessionIds = useMemo(() => Object.keys(sessionProjects), [sessionProjects]);
259
259
  const focusedSessionId = focusMode ? knownSessionIds[focusedSessionIdx] : null;
260
260
  const hasMultipleSessions = knownSessionIds.length > 1;
261
- const filteredActivity = focusedSessionId ? activityLog.filter((e) => e.sessionId === focusedSessionId) : activityLog;
262
- const [now, setNow] = useState2(Date.now());
263
- useEffect2(() => {
264
- const timer = setInterval(() => setNow(Date.now()), 1e3);
265
- return () => clearInterval(timer);
266
- }, []);
261
+ const filteredActivity = useMemo(
262
+ () => focusedSessionId ? activityLog.filter((e) => e.sessionId === focusedSessionId) : activityLog,
263
+ [focusedSessionId, activityLog]
264
+ );
267
265
  const [selectedIdx, setSelectedIdx] = useState2(-1);
268
266
  const [userScrolled, setUserScrolled] = useState2(false);
269
267
  const prevLogLength = useRef(filteredActivity.length);
@@ -284,7 +282,8 @@ function Dashboard({ store, connection, overlay }) {
284
282
  connection?.disconnect();
285
283
  exit();
286
284
  }
287
- if (overlay) return;
285
+ });
286
+ useInput2((input, key) => {
288
287
  if (input === "r") connection?.reconnect();
289
288
  if (input === "c" && !key.ctrl) {
290
289
  store.getState().clearActivity();
@@ -328,9 +327,8 @@ function Dashboard({ store, connection, overlay }) {
328
327
  setSelectedIdx(next);
329
328
  }
330
329
  }
331
- });
330
+ }, { isActive: !overlay });
332
331
  const sessionList = Object.values(sessions);
333
- const uptime = connectedAt ? formatDuration(now - connectedAt) : "-";
334
332
  const boxWidth = termWidth - 2;
335
333
  const col = getColumns(termWidth);
336
334
  const headerHeight = 8;
@@ -355,7 +353,7 @@ function Dashboard({ store, connection, overlay }) {
355
353
  /* @__PURE__ */ jsx2(Text2, { children: stripProtocol(server) })
356
354
  ] })
357
355
  ] }),
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)) })
356
+ termWidth >= 120 && /* @__PURE__ */ jsx2(Box2, { flexDirection: "column", alignItems: "flex-end", justifyContent: "center", children: LOGO_JSX })
359
357
  ] })
360
358
  ) : (
361
359
  /* Full header when connected */
@@ -373,10 +371,6 @@ function Dashboard({ store, connection, overlay }) {
373
371
  /* @__PURE__ */ jsx2(Text2, { dimColor: true, children: "Status: ".padEnd(12) }),
374
372
  /* @__PURE__ */ jsx2(StatusIndicator, { status: connectionStatus, error: connectionError })
375
373
  ] }),
376
- /* @__PURE__ */ jsxs2(Box2, { children: [
377
- /* @__PURE__ */ jsx2(Text2, { dimColor: true, children: "Uptime: ".padEnd(12) }),
378
- /* @__PURE__ */ jsx2(Text2, { children: uptime })
379
- ] }),
380
374
  deviceInfo && /* @__PURE__ */ jsxs2(Box2, { children: [
381
375
  /* @__PURE__ */ jsx2(Text2, { dimColor: true, children: "Device: ".padEnd(12) }),
382
376
  /* @__PURE__ */ jsx2(Text2, { children: deviceInfo.name })
@@ -446,7 +440,7 @@ function Dashboard({ store, connection, overlay }) {
446
440
  /* @__PURE__ */ jsx2(Text2, { dimColor: true, children: " details" })
447
441
  ] })
448
442
  ] }) }),
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)) })
443
+ termWidth >= 120 && /* @__PURE__ */ jsx2(Box2, { flexDirection: "column", alignItems: "flex-end", justifyContent: "center", children: LOGO_JSX })
450
444
  ] })
451
445
  ),
452
446
  !overlay && /* @__PURE__ */ jsxs2(Box2, { flexDirection: "column", marginX: 1, marginTop: 1, children: [
@@ -465,13 +459,13 @@ function Dashboard({ store, connection, overlay }) {
465
459
  "ID".padEnd(col.id),
466
460
  "PROJECT".padEnd(col.project),
467
461
  "STATUS".padEnd(col.status),
468
- "STARTED".padEnd(col.started),
462
+ "RUNNING".padEnd(col.started),
469
463
  col.showExtras ? "MODEL".padEnd(col.model) + "EFFORT" : ""
470
464
  ] }) }),
471
465
  sessionList.length === 0 ? /* @__PURE__ */ jsxs2(Text2, { dimColor: true, children: [
472
466
  "\u25CB",
473
467
  " Waiting for sessions from the Punk app..."
474
- ] }) : sessionList.map((session) => /* @__PURE__ */ jsx2(SessionRow, { session, now, col }, session.requestId))
468
+ ] }) : sessionList.map((session) => /* @__PURE__ */ jsx2(SessionRow, { session, col }, session.requestId))
475
469
  ]
476
470
  }
477
471
  )
@@ -632,10 +626,17 @@ function StatusIndicator({ status, error }) {
632
626
  " Disconnected"
633
627
  ] });
634
628
  }
635
- function SessionRow({ session, now, col }) {
629
+ function SessionRow({ session, col }) {
630
+ const [elapsed, setElapsed] = useState2(Date.now() - session.startedAt);
631
+ useEffect2(() => {
632
+ const timer = setInterval(() => {
633
+ setElapsed(Date.now() - session.startedAt);
634
+ }, 1e3);
635
+ return () => clearInterval(timer);
636
+ }, [session.startedAt]);
636
637
  const id = session.requestId.slice(0, col.id - 2);
637
638
  const project = session.workingDirectory ? session.workingDirectory.split("/").pop() ?? "" : "";
638
- const started = formatDuration(now - session.startedAt);
639
+ const started = formatDuration(elapsed);
639
640
  return /* @__PURE__ */ jsxs2(Box2, { children: [
640
641
  /* @__PURE__ */ jsxs2(Text2, { children: [
641
642
  id.padEnd(col.id),
@@ -752,7 +753,7 @@ function formatDuration(ms) {
752
753
  const seconds = Math.floor(ms / 1e3);
753
754
  if (seconds < 60) return `${seconds}s`;
754
755
  const minutes = Math.floor(seconds / 60);
755
- if (minutes < 60) return `${minutes}m ${seconds % 60}s`;
756
+ if (minutes < 60) return `${minutes}m`;
756
757
  const hours = Math.floor(minutes / 60);
757
758
  return `${hours}h ${minutes % 60}m`;
758
759
  }
@@ -795,6 +796,15 @@ function App({ server, idToken, options }) {
795
796
  connectionRef.current?.disconnect();
796
797
  };
797
798
  }, []);
799
+ useEffect3(() => {
800
+ const onSigcont = () => {
801
+ connectionRef.current?.reconnect();
802
+ };
803
+ process.on("SIGCONT", onSigcont);
804
+ return () => {
805
+ process.removeListener("SIGCONT", onSigcont);
806
+ };
807
+ }, []);
798
808
  const loginOverlay = screen === "login" ? /* @__PURE__ */ jsx3(LoginDialog, { store, server }) : void 0;
799
809
  return /* @__PURE__ */ jsx3(
800
810
  Dashboard,
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
 
3
3
  // src/version.ts
4
- var version = "0.1.21";
4
+ var version = "0.1.22";
5
5
 
6
6
  // src/lib/auth.ts
7
7
  import fs from "fs";
@@ -1175,7 +1175,6 @@ var PunkConnection = class {
1175
1175
  }
1176
1176
  }, 50 * 60 * 1e3);
1177
1177
  this.attachSocketHandlers();
1178
- this.attachSignalHandlers();
1179
1178
  }
1180
1179
  disconnect() {
1181
1180
  this.cleanup();
@@ -1273,18 +1272,6 @@ var PunkConnection = class {
1273
1272
  this.resolvePermission(msg.requestId, msg.toolUseId, msg.allow, msg.answers, msg.feedback, msg.permissionMode);
1274
1273
  });
1275
1274
  }
1276
- attachSignalHandlers() {
1277
- const onShutdown = () => {
1278
- this.store.getState().addActivity({ icon: "\u25CF", message: "Shutting down..." });
1279
- this.cleanup();
1280
- process.exit(0);
1281
- };
1282
- process.on("SIGINT", onShutdown);
1283
- process.on("SIGTERM", onShutdown);
1284
- process.on("SIGCONT", () => {
1285
- this.reconnect();
1286
- });
1287
- }
1288
1275
  send(event, msg) {
1289
1276
  if (!this.socket.connected) return;
1290
1277
  this.socket.emit(event, msg);
@@ -1592,9 +1579,11 @@ var createPunkStore = (server) => createStore((set) => ({
1592
1579
  return { sessions: { ...s.sessions, [id]: { ...existing, ...updates } } };
1593
1580
  }),
1594
1581
  removeSession: (id) => set((s) => {
1595
- const rest = { ...s.sessions };
1596
- delete rest[id];
1597
- return { sessions: rest };
1582
+ const sessions = { ...s.sessions };
1583
+ delete sessions[id];
1584
+ const sessionProjects = { ...s.sessionProjects };
1585
+ delete sessionProjects[id];
1586
+ return { sessions, sessionProjects };
1598
1587
  }),
1599
1588
  addActivity: (entry) => set((s) => ({
1600
1589
  activityLog: [
package/dist/cli.js CHANGED
@@ -8,7 +8,7 @@ import {
8
8
  refreshIdToken,
9
9
  signIn,
10
10
  version
11
- } from "./chunk-DU2STEE5.js";
11
+ } from "./chunk-4FFAG2HK.js";
12
12
 
13
13
  // src/cli.ts
14
14
  import { program } from "commander";
@@ -128,23 +128,32 @@ async function runHeadless(server, idToken, options) {
128
128
  }
129
129
  }
130
130
  });
131
- new PunkConnection(server, idToken, options, store);
131
+ const connection = new PunkConnection(server, idToken, options, store);
132
+ const shutdown = () => {
133
+ connection.disconnect();
134
+ process.exit(0);
135
+ };
136
+ process.on("SIGINT", shutdown);
137
+ process.on("SIGTERM", shutdown);
132
138
  await new Promise(() => {
133
139
  });
134
140
  }
135
141
  async function runTui(server, options) {
136
142
  const { render } = await import("ink");
137
143
  const { createElement } = await import("react");
138
- const { App } = await import("./App-624TTCIE.js");
144
+ const { App } = await import("./App-RF23NIE6.js");
139
145
  const idToken = options.token ? options.token : void 0;
140
146
  process.stdout.write("\x1B[?1049h");
141
147
  process.stdout.write("\x1B[H");
142
- const { waitUntilExit } = render(
148
+ const { waitUntilExit, unmount } = render(
143
149
  createElement(App, { server, idToken, options })
144
150
  );
151
+ const onSigterm = () => unmount();
152
+ process.once("SIGTERM", onSigterm);
145
153
  try {
146
154
  await waitUntilExit();
147
155
  } finally {
156
+ process.removeListener("SIGTERM", onSigterm);
148
157
  process.stdout.write("\x1B[?1049l");
149
158
  }
150
159
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@punkcode/cli",
3
- "version": "0.1.21",
3
+ "version": "0.1.22",
4
4
  "description": "Control Claude Code from your phone",
5
5
  "type": "module",
6
6
  "bin": {