@punkcode/cli 0.1.6 → 0.1.8

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 (2) hide show
  1. package/dist/cli.js +94 -6
  2. package/package.json +1 -1
package/dist/cli.js CHANGED
@@ -33,6 +33,36 @@ async function* promptWithImages(text, images, sessionId) {
33
33
  session_id: sessionId
34
34
  };
35
35
  }
36
+ async function getSessionInfo(sessionId, cwd) {
37
+ const q = query({
38
+ prompt: "",
39
+ options: {
40
+ resume: sessionId,
41
+ ...cwd && { cwd }
42
+ }
43
+ });
44
+ try {
45
+ const [init, commands, mcpServers] = await Promise.all([
46
+ q.initializationResult(),
47
+ q.supportedCommands(),
48
+ q.mcpServerStatus()
49
+ ]);
50
+ const cmdList = commands.length >= init.commands.length ? commands : init.commands;
51
+ return {
52
+ sessionId,
53
+ tools: [],
54
+ slashCommands: cmdList.map((c) => ({ name: c.name, description: c.description })),
55
+ skills: [],
56
+ mcpServers: mcpServers.map((s) => ({ name: s.name, status: s.status })),
57
+ model: init.models?.[0]?.value ?? "",
58
+ cwd: cwd ?? "",
59
+ claudeCodeVersion: "",
60
+ permissionMode: "default"
61
+ };
62
+ } finally {
63
+ q.close();
64
+ }
65
+ }
36
66
  function runClaude(options, callbacks) {
37
67
  const opts = options.options || {};
38
68
  const isBypass = opts.permissionMode === "bypassPermissions";
@@ -49,6 +79,7 @@ function runClaude(options, callbacks) {
49
79
  ...opts.allowedTools && { allowedTools: opts.allowedTools },
50
80
  ...opts.disallowedTools && { disallowedTools: opts.disallowedTools },
51
81
  ...opts.maxTurns && { maxTurns: opts.maxTurns },
82
+ systemPrompt: opts.systemPrompt ?? { type: "preset", preset: "claude_code" },
52
83
  ...options.cwd && { cwd: options.cwd },
53
84
  ...options.sessionId && { resume: options.sessionId },
54
85
  maxThinkingTokens: 1e4,
@@ -148,10 +179,18 @@ function runClaude(options, callbacks) {
148
179
  case "system": {
149
180
  const sys = message;
150
181
  if (sys.subtype === "init" && callbacks.onSessionCreated) {
182
+ let slashCommands = (sys.slash_commands ?? []).map((cmd) => ({ name: cmd, description: "" }));
183
+ try {
184
+ const cmds = await q.supportedCommands();
185
+ if (cmds.length > 0) {
186
+ slashCommands = cmds.map((c) => ({ name: c.name, description: c.description }));
187
+ }
188
+ } catch {
189
+ }
151
190
  callbacks.onSessionCreated({
152
191
  sessionId: sys.session_id ?? "",
153
192
  tools: sys.tools ?? [],
154
- slashCommands: (sys.slash_commands ?? []).map((cmd) => ({ name: cmd, description: "" })),
193
+ slashCommands,
155
194
  skills: sys.skills ?? [],
156
195
  mcpServers: sys.mcp_servers ?? [],
157
196
  model: sys.model ?? "",
@@ -218,14 +257,18 @@ function getOrCreateDeviceId() {
218
257
  fs.writeFileSync(CONFIG_FILE, JSON.stringify(config, null, 2) + "\n", "utf-8");
219
258
  return id;
220
259
  }
221
- function collectDeviceInfo(deviceId, customName) {
260
+ function collectDeviceInfo(deviceId, customName, customTags) {
222
261
  if (customName) {
223
262
  saveConfigField("deviceName", customName);
224
263
  }
264
+ if (customTags && customTags.length > 0) {
265
+ saveConfigField("tags", customTags);
266
+ }
225
267
  const cpus = os.cpus();
226
268
  return {
227
269
  deviceId,
228
270
  name: customName || getDeviceName(),
271
+ tags: customTags && customTags.length > 0 ? customTags : getTags(),
229
272
  platform: process.platform,
230
273
  arch: process.arch,
231
274
  username: os.userInfo().username,
@@ -254,6 +297,14 @@ function getDeviceName() {
254
297
  }
255
298
  return os.hostname();
256
299
  }
300
+ function getTags() {
301
+ try {
302
+ const config = JSON.parse(fs.readFileSync(CONFIG_FILE, "utf-8"));
303
+ if (Array.isArray(config.tags)) return config.tags;
304
+ } catch {
305
+ }
306
+ return [];
307
+ }
257
308
  function saveConfigField(key, value) {
258
309
  fs.mkdirSync(PUNK_DIR, { recursive: true });
259
310
  let config = {};
@@ -543,7 +594,7 @@ function parseSessionFile(content) {
543
594
  }
544
595
  if (entry.type === "system" && entry.subtype === "compact_boundary") {
545
596
  messages.push({
546
- role: "assistant",
597
+ role: "system",
547
598
  content: [],
548
599
  timestamp: entry.timestamp,
549
600
  type: "system",
@@ -553,6 +604,24 @@ function parseSessionFile(content) {
553
604
  });
554
605
  continue;
555
606
  }
607
+ if (entry.isCompactSummary && entry.message) {
608
+ const summaryContent = entry.message.content;
609
+ let summaryText = "";
610
+ if (typeof summaryContent === "string") {
611
+ summaryText = summaryContent;
612
+ } else if (Array.isArray(summaryContent)) {
613
+ summaryText = summaryContent.filter((b) => b.type === "text" && typeof b.text === "string").map((b) => b.text).join("\n");
614
+ }
615
+ if (summaryText) {
616
+ for (let i = messages.length - 1; i >= 0; i--) {
617
+ if (messages[i].subtype === "compact_boundary") {
618
+ messages[i].content = [{ type: "text", text: summaryText }];
619
+ break;
620
+ }
621
+ }
622
+ }
623
+ continue;
624
+ }
556
625
  if ((entry.type === "user" || entry.type === "assistant") && entry.message) {
557
626
  const msgContent = entry.message.content;
558
627
  messages.push({
@@ -870,7 +939,7 @@ async function connect(server, options) {
870
939
  const activeSessions = /* @__PURE__ */ new Map();
871
940
  socket.on("connect", () => {
872
941
  logger.info("Connected");
873
- const deviceInfo = collectDeviceInfo(deviceId, options.name);
942
+ const deviceInfo = collectDeviceInfo(deviceId, options.name, options.tag);
874
943
  socket.emit("register", deviceInfo, (response) => {
875
944
  if (response.success) {
876
945
  logger.info({ deviceId }, "Registered");
@@ -897,6 +966,11 @@ async function connect(server, options) {
897
966
  handleGetContext(socket, msg);
898
967
  }
899
968
  });
969
+ socket.on("get-session-info", (msg) => {
970
+ if (msg.type === "get-session-info") {
971
+ handleGetSessionInfo(socket, msg);
972
+ }
973
+ });
900
974
  socket.on("cancel", (msg) => {
901
975
  handleCancel(msg.id, activeSessions);
902
976
  });
@@ -918,7 +992,7 @@ async function connect(server, options) {
918
992
  });
919
993
  socket.on("reconnect", (attemptNumber) => {
920
994
  logger.info({ attemptNumber }, "Reconnected");
921
- socket.emit("register", collectDeviceInfo(deviceId, options.name));
995
+ socket.emit("register", collectDeviceInfo(deviceId, options.name, options.tag));
922
996
  });
923
997
  socket.on("connect_error", (err) => {
924
998
  logger.error({ err }, "Connection error");
@@ -1035,6 +1109,20 @@ async function handleLoadSession(socket, msg) {
1035
1109
  log2.warn("Session not found");
1036
1110
  }
1037
1111
  }
1112
+ async function handleGetSessionInfo(socket, msg) {
1113
+ const { id, sessionId, cwd } = msg;
1114
+ const log2 = createChildLogger({ sessionId });
1115
+ log2.info("Getting session info...");
1116
+ try {
1117
+ const data = await getSessionInfo(sessionId, cwd);
1118
+ send(socket, "response", { type: "session_info", data, requestId: id });
1119
+ log2.info("Session info retrieved");
1120
+ } catch (err) {
1121
+ const message = err instanceof Error ? err.message : String(err);
1122
+ send(socket, "response", { type: "error", message, requestId: id });
1123
+ log2.error({ err }, "Session info error");
1124
+ }
1125
+ }
1038
1126
  async function handleGetContext(socket, msg) {
1039
1127
  const { id, sessionId, cwd } = msg;
1040
1128
  const log2 = createChildLogger({ sessionId });
@@ -1122,7 +1210,7 @@ function logout() {
1122
1210
 
1123
1211
  // src/commands/index.ts
1124
1212
  function registerCommands(program2) {
1125
- program2.command("connect").argument("[server]", "Backend server URL", "https://api.punkcode.dev").description("Connect to backend server").option("-t, --token <token>", "Authentication token").option("-d, --device-id <deviceId>", "Device identifier (defaults to hostname)").option("-n, --name <name>", "Custom device display name").action(connect);
1213
+ program2.command("connect").argument("[server]", "Backend server URL", "https://api.punkcode.dev").description("Connect to backend server").option("-t, --token <token>", "Authentication token").option("-d, --device-id <deviceId>", "Device identifier (defaults to hostname)").option("-n, --name <name>", "Custom device display name").option("--tag <tag>", "Device tag (repeatable, e.g. --tag home --tag mac --tag docker)", (val, acc) => [...acc, val], []).action(connect);
1126
1214
  program2.command("login").description("Log in with your email and password").action(login);
1127
1215
  program2.command("logout").description("Log out and clear stored credentials").action(logout);
1128
1216
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@punkcode/cli",
3
- "version": "0.1.6",
3
+ "version": "0.1.8",
4
4
  "description": "Control Claude Code from your phone",
5
5
  "type": "module",
6
6
  "bin": {