claude-ps 0.1.1 → 0.2.2

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/index.js +278 -202
  2. package/package.json +4 -11
package/dist/index.js CHANGED
@@ -9,16 +9,12 @@ import { withFullScreen } from "fullscreen-ink";
9
9
  import meow from "meow";
10
10
 
11
11
  // src/App.tsx
12
- import { Box as Box5, Text as Text5, useApp, useInput, useStdout } from "ink";
12
+ import { Box as Box7, Text as Text7, useApp, useInput, useStdout } from "ink";
13
13
 
14
- // src/components/DetailPanel.tsx
14
+ // src/components/ui/StatusBar.tsx
15
15
  import { Box, Text } from "ink";
16
16
 
17
17
  // src/constants/theme.ts
18
- var USAGE_THRESHOLD = {
19
- LOW: 30,
20
- HIGH: 70
21
- };
22
18
  var COLORS = {
23
19
  /** 使用率颜色 */
24
20
  usage: {
@@ -47,11 +43,132 @@ var COLUMN_WIDTH = {
47
43
  elapsed: 9
48
44
  };
49
45
  var ESTIMATED_TOTAL_MEMORY_MB = 16 * 1024;
50
- function getUsageColor(percent) {
51
- if (percent < USAGE_THRESHOLD.LOW) return COLORS.usage.low;
52
- if (percent < USAGE_THRESHOLD.HIGH) return COLORS.usage.medium;
53
- return COLORS.usage.high;
46
+
47
+ // src/components/ui/StatusBar.tsx
48
+ import { jsx, jsxs } from "react/jsx-runtime";
49
+ function calculateStats(processes) {
50
+ const totalCpu = processes.reduce((sum, p) => sum + p.cpu, 0);
51
+ const totalMemoryPercent = processes.reduce((sum, p) => sum + p.memory, 0);
52
+ const totalMemoryMB = totalMemoryPercent / 100 * ESTIMATED_TOTAL_MEMORY_MB;
53
+ const orphanCount = processes.filter((p) => p.isOrphan).length;
54
+ const currentCount = processes.filter((p) => p.isCurrent).length;
55
+ return {
56
+ count: processes.length,
57
+ totalCpu,
58
+ totalMemory: totalMemoryMB < 1024 ? `${Math.round(totalMemoryMB)}MB` : `${(totalMemoryMB / 1024).toFixed(1)}GB`,
59
+ orphanCount,
60
+ currentCount
61
+ };
54
62
  }
63
+ function StatusBar({ processes }) {
64
+ const stats = calculateStats(processes);
65
+ return /* @__PURE__ */ jsxs(Box, { height: 2, children: [
66
+ /* @__PURE__ */ jsx(Text, { color: COLORS.label, children: "\u8FDB\u7A0B: " }),
67
+ /* @__PURE__ */ jsx(Text, { color: COLORS.value, children: stats.count }),
68
+ /* @__PURE__ */ jsx(Text, { color: COLORS.label, children: " | CPU: " }),
69
+ /* @__PURE__ */ jsxs(Text, { color: COLORS.value, children: [
70
+ stats.totalCpu.toFixed(1),
71
+ "%"
72
+ ] }),
73
+ /* @__PURE__ */ jsx(Text, { color: COLORS.label, children: " | \u5185\u5B58: " }),
74
+ /* @__PURE__ */ jsx(Text, { color: COLORS.value, children: stats.totalMemory }),
75
+ /* @__PURE__ */ jsx(Text, { color: COLORS.label, children: " | \u5B64\u513F: " }),
76
+ /* @__PURE__ */ jsx(Text, { color: stats.orphanCount > 0 ? COLORS.orphan : COLORS.value, children: stats.orphanCount }),
77
+ /* @__PURE__ */ jsx(Text, { color: COLORS.label, children: " | \u5F53\u524D: " }),
78
+ /* @__PURE__ */ jsx(Text, { color: stats.currentCount > 0 ? COLORS.current : COLORS.value, children: stats.currentCount })
79
+ ] });
80
+ }
81
+
82
+ // src/components/ui/HelpBar.tsx
83
+ import { Box as Box3, Text as Text3 } from "ink";
84
+
85
+ // src/components/ui/primitives.tsx
86
+ import { Box as Box2, Text as Text2 } from "ink";
87
+ import { jsx as jsx2, jsxs as jsxs2 } from "react/jsx-runtime";
88
+ function Separator({
89
+ char = "\u2500",
90
+ length = 60
91
+ }) {
92
+ return /* @__PURE__ */ jsx2(Text2, { color: "gray", children: char.repeat(length) });
93
+ }
94
+ function EmptyPrompt({ message }) {
95
+ return /* @__PURE__ */ jsx2(Box2, { paddingX: 1, children: /* @__PURE__ */ jsx2(Text2, { color: "gray", children: message }) });
96
+ }
97
+ function LoadingState({ message = "\u52A0\u8F7D\u4E2D..." }) {
98
+ return /* @__PURE__ */ jsx2(Box2, { paddingX: 1, children: /* @__PURE__ */ jsx2(Text2, { color: "gray", children: message }) });
99
+ }
100
+ function InfoRow({ label, value }) {
101
+ return /* @__PURE__ */ jsxs2(Box2, { children: [
102
+ /* @__PURE__ */ jsxs2(Text2, { color: "cyan", children: [
103
+ label,
104
+ ": "
105
+ ] }),
106
+ /* @__PURE__ */ jsx2(Text2, { children: value })
107
+ ] });
108
+ }
109
+ function Section({
110
+ title,
111
+ children
112
+ }) {
113
+ return /* @__PURE__ */ jsxs2(Box2, { flexDirection: "column", children: [
114
+ /* @__PURE__ */ jsx2(Text2, { bold: true, color: "cyan", children: title }),
115
+ children
116
+ ] });
117
+ }
118
+ function KeyHint({
119
+ shortcut,
120
+ desc
121
+ }) {
122
+ return /* @__PURE__ */ jsxs2(Text2, { children: [
123
+ /* @__PURE__ */ jsx2(Text2, { color: "blue", children: shortcut }),
124
+ /* @__PURE__ */ jsxs2(Text2, { color: "gray", children: [
125
+ " ",
126
+ desc
127
+ ] })
128
+ ] });
129
+ }
130
+
131
+ // src/components/ui/HelpBar.tsx
132
+ import { jsx as jsx3, jsxs as jsxs3 } from "react/jsx-runtime";
133
+ var hints = [
134
+ { key: "\u2191/\u2193", desc: "\u79FB\u52A8" },
135
+ { key: "d", desc: "\u7EC8\u6B62" },
136
+ { key: "D", desc: "\u5F3A\u6740" },
137
+ { key: "s", desc: "\u6392\u5E8F" },
138
+ { key: "r", desc: "\u5237\u65B0" },
139
+ { key: "q", desc: "\u9000\u51FA" }
140
+ ];
141
+ var sortFieldLabels = {
142
+ cpu: "CPU",
143
+ memory: "\u5185\u5B58",
144
+ elapsed: "\u65F6\u957F",
145
+ default: "PID"
146
+ };
147
+ function HelpBar({ processCount, interval: interval2, sortField }) {
148
+ return /* @__PURE__ */ jsxs3(Box3, { justifyContent: "space-between", paddingX: 1, children: [
149
+ /* @__PURE__ */ jsx3(Box3, { gap: 1, children: hints.map((hint) => /* @__PURE__ */ jsx3(KeyHint, { shortcut: hint.key, desc: hint.desc }, hint.key)) }),
150
+ /* @__PURE__ */ jsxs3(Box3, { gap: 1, children: [
151
+ /* @__PURE__ */ jsxs3(Text3, { children: [
152
+ processCount,
153
+ " \u8FDB\u7A0B"
154
+ ] }),
155
+ /* @__PURE__ */ jsx3(Text3, { color: COLORS.label, children: "|" }),
156
+ /* @__PURE__ */ jsxs3(Text3, { color: COLORS.label, children: [
157
+ "\u6392\u5E8F: ",
158
+ sortFieldLabels[sortField]
159
+ ] }),
160
+ /* @__PURE__ */ jsx3(Text3, { color: COLORS.label, children: "|" }),
161
+ /* @__PURE__ */ jsxs3(Text3, { color: COLORS.label, children: [
162
+ "\u5237\u65B0: ",
163
+ interval2,
164
+ "s"
165
+ ] })
166
+ ] })
167
+ ] });
168
+ }
169
+
170
+ // src/components/ui/DetailPanel.tsx
171
+ import { Box as Box4, Text as Text4 } from "ink";
55
172
 
56
173
  // src/utils/format.ts
57
174
  function formatMemory(memPercent) {
@@ -73,184 +190,109 @@ function formatElapsed(elapsed) {
73
190
  }
74
191
  return elapsed;
75
192
  }
76
- function shortenPath(inputPath, maxLen = 25) {
77
- let path = inputPath;
78
- const home = process.env.HOME || "";
79
- if (home && path.startsWith(home)) {
80
- path = `~${path.slice(home.length)}`;
81
- }
82
- if (path.length <= maxLen) return path;
83
- const half = Math.floor((maxLen - 3) / 2);
84
- return `${path.slice(0, half)}...${path.slice(-half)}`;
85
- }
86
193
 
87
- // src/components/DetailPanel.tsx
88
- import { jsx, jsxs } from "react/jsx-runtime";
194
+ // src/components/ui/DetailPanel.tsx
195
+ import { jsx as jsx4, jsxs as jsxs4 } from "react/jsx-runtime";
89
196
  function DetailPanel({ process: proc }) {
90
197
  if (!proc) {
91
- return /* @__PURE__ */ jsx(Box, { flexDirection: "column", paddingLeft: 1, children: /* @__PURE__ */ jsx(Text, { color: COLORS.label, children: "\u9009\u62E9\u4E00\u4E2A\u8FDB\u7A0B\u67E5\u770B\u8BE6\u60C5" }) });
198
+ return /* @__PURE__ */ jsx4(EmptyPrompt, { message: "\u9009\u62E9\u4E00\u4E2A\u8FDB\u7A0B\u67E5\u770B\u8BE6\u60C5" });
92
199
  }
93
- return /* @__PURE__ */ jsxs(Box, { flexDirection: "column", paddingLeft: 1, children: [
94
- /* @__PURE__ */ jsxs(Box, { children: [
95
- /* @__PURE__ */ jsx(Text, { color: COLORS.title, children: "CPU: " }),
96
- /* @__PURE__ */ jsxs(Text, { children: [
97
- proc.cpu.toFixed(1),
98
- "%"
99
- ] }),
100
- /* @__PURE__ */ jsx(Text, { children: " " }),
101
- /* @__PURE__ */ jsx(Text, { color: COLORS.title, children: "\u5185\u5B58: " }),
102
- /* @__PURE__ */ jsx(Text, { children: formatMemory(proc.memory) }),
103
- /* @__PURE__ */ jsx(Text, { children: " " }),
104
- /* @__PURE__ */ jsx(Text, { color: COLORS.title, children: "\u65F6\u957F: " }),
105
- /* @__PURE__ */ jsx(Text, { children: formatElapsed(proc.elapsed) })
200
+ return /* @__PURE__ */ jsxs4(Box4, { flexDirection: "column", children: [
201
+ /* @__PURE__ */ jsxs4(Section, { title: "\u8D44\u6E90\u4FE1\u606F", children: [
202
+ /* @__PURE__ */ jsx4(InfoRow, { label: "CPU", value: `${proc.cpu.toFixed(1)}%` }),
203
+ /* @__PURE__ */ jsx4(InfoRow, { label: "\u5185\u5B58", value: formatMemory(proc.memory) }),
204
+ /* @__PURE__ */ jsx4(InfoRow, { label: "\u65F6\u957F", value: formatElapsed(proc.elapsed) })
106
205
  ] }),
107
- /* @__PURE__ */ jsx(Text, { children: " " }),
108
- /* @__PURE__ */ jsxs(Box, { flexDirection: "column", children: [
109
- /* @__PURE__ */ jsx(Text, { color: COLORS.title, children: "Session:" }),
110
- /* @__PURE__ */ jsx(Text, { color: COLORS.label, wrap: "truncate", children: proc.sessionPath || "\u65E0\u4F1A\u8BDD\u6587\u4EF6" })
206
+ /* @__PURE__ */ jsxs4(Box4, { flexDirection: "column", paddingBottom: 1, children: [
207
+ /* @__PURE__ */ jsx4(Text4, { children: " " }),
208
+ /* @__PURE__ */ jsx4(Text4, { bold: true, color: "cyan", children: "Session:" }),
209
+ /* @__PURE__ */ jsx4(Text4, { color: COLORS.label, wrap: "truncate", children: proc.sessionPath || "\u65E0\u4F1A\u8BDD\u6587\u4EF6" })
111
210
  ] }),
112
- /* @__PURE__ */ jsx(Text, { children: " " }),
113
- /* @__PURE__ */ jsx(Text, { color: COLORS.title, bold: true, children: "\u2500 \u6700\u8FD1\u5BF9\u8BDD \u2500" }),
114
- proc.messages.length === 0 ? /* @__PURE__ */ jsx(Text, { color: COLORS.label, children: "\u65E0\u5BF9\u8BDD\u8BB0\u5F55" }) : proc.messages.map((msg) => /* @__PURE__ */ jsxs(Box, { flexDirection: "row", children: [
115
- /* @__PURE__ */ jsxs(Text, { color: msg.role === "user" ? COLORS.current : "blue", children: [
116
- "[",
117
- msg.role === "user" ? "User" : "Claude",
118
- "]",
211
+ /* @__PURE__ */ jsx4(Box4, { paddingBottom: 1, children: /* @__PURE__ */ jsx4(Text4, { bold: true, color: "cyan", children: "\u6700\u8FD1\u5BF9\u8BDD" }) }),
212
+ /* @__PURE__ */ jsx4(Box4, { flexDirection: "column", children: proc.messages.length === 0 ? /* @__PURE__ */ jsx4(Text4, { color: COLORS.label, children: "\u65E0\u5BF9\u8BDD\u8BB0\u5F55" }) : proc.messages.map((msg) => /* @__PURE__ */ jsxs4(Box4, { flexDirection: "row", children: [
213
+ /* @__PURE__ */ jsxs4(Text4, { color: msg.role === "user" ? COLORS.current : "blue", children: [
214
+ msg.role === "user" ? "[User]" : "[Claude]",
119
215
  " "
120
216
  ] }),
121
- /* @__PURE__ */ jsx(Text, { wrap: "truncate", children: msg.content })
122
- ] }, msg.timestamp))
217
+ /* @__PURE__ */ jsx4(Text4, { wrap: "truncate", children: msg.content })
218
+ ] }, msg.timestamp)) })
123
219
  ] });
124
220
  }
125
221
 
126
- // src/components/HelpBar.tsx
127
- import { Box as Box2, Text as Text2 } from "ink";
128
- import React from "react";
129
- import { jsx as jsx2, jsxs as jsxs2 } from "react/jsx-runtime";
130
- var hints = [
131
- { key: "\u2191/\u2193", desc: "\u79FB\u52A8" },
132
- { key: "d", desc: "\u7EC8\u6B62" },
133
- { key: "D", desc: "\u5F3A\u6740" },
134
- { key: "s", desc: "\u6392\u5E8F" },
135
- { key: "r", desc: "\u5237\u65B0" },
136
- { key: "q", desc: "\u9000\u51FA" }
137
- ];
138
- var sortFieldLabels = {
139
- cpu: "CPU",
140
- memory: "\u5185\u5B58",
141
- elapsed: "\u65F6\u957F",
142
- default: "PID"
222
+ // src/components/ProcessList.tsx
223
+ import { Box as Box6, Text as Text6 } from "ink";
224
+
225
+ // src/components/ui/ProcessItem.tsx
226
+ import { Text as Text5 } from "ink";
227
+ import { jsx as jsx5 } from "react/jsx-runtime";
228
+ var PADDING_X = 1;
229
+ var BG_CODES = {
230
+ reset: "\x1B[49m",
231
+ blue: "\x1B[48;5;24m",
232
+ // 深蓝背景
233
+ gray: "\x1B[48;5;240m"
234
+ // 深灰背景
143
235
  };
144
- function HelpBar({ processCount, interval: interval2, sortField }) {
145
- return /* @__PURE__ */ jsxs2(Box2, { justifyContent: "space-between", children: [
146
- /* @__PURE__ */ jsx2(Box2, { children: hints.map((hint, i) => /* @__PURE__ */ jsxs2(React.Fragment, { children: [
147
- /* @__PURE__ */ jsx2(Text2, { color: COLORS.selected, children: hint.key }),
148
- /* @__PURE__ */ jsxs2(Text2, { color: COLORS.label, children: [
149
- " ",
150
- hint.desc
151
- ] }),
152
- i < hints.length - 1 && /* @__PURE__ */ jsx2(Text2, { children: " " })
153
- ] }, hint.key)) }),
154
- /* @__PURE__ */ jsxs2(Box2, { children: [
155
- /* @__PURE__ */ jsxs2(Text2, { color: COLORS.value, children: [
156
- processCount,
157
- " \u8FDB\u7A0B"
158
- ] }),
159
- /* @__PURE__ */ jsx2(Text2, { color: COLORS.label, children: " | " }),
160
- /* @__PURE__ */ jsx2(Text2, { color: COLORS.label, children: "\u6392\u5E8F: " }),
161
- /* @__PURE__ */ jsx2(Text2, { color: COLORS.value, children: sortFieldLabels[sortField] }),
162
- /* @__PURE__ */ jsx2(Text2, { color: COLORS.label, children: " | " }),
163
- /* @__PURE__ */ jsxs2(Text2, { color: COLORS.label, children: [
164
- "\u5237\u65B0: ",
165
- interval2,
166
- "s"
167
- ] })
168
- ] })
169
- ] });
236
+ function withBgColor(text, bgColor) {
237
+ return `${BG_CODES[bgColor]}${text}${BG_CODES.reset}`;
238
+ }
239
+ function ProcessItem({ process: process2, isSelected }) {
240
+ let cwdColor = void 0;
241
+ if (process2.isOrphan) cwdColor = "red";
242
+ else if (process2.isCurrent) cwdColor = "green";
243
+ const pidText = String(process2.pid).padEnd(COLUMN_WIDTH.pid);
244
+ const cpuText = `${process2.cpu.toFixed(1)}%`.padEnd(COLUMN_WIDTH.cpu);
245
+ const memText = `${process2.memory.toFixed(1)}%`.padEnd(COLUMN_WIDTH.memory);
246
+ const elapsedText = formatElapsed(process2.elapsed).padEnd(
247
+ COLUMN_WIDTH.elapsed
248
+ );
249
+ const cwdText = process2.cwd;
250
+ const rowText = pidText + cpuText + memText + elapsedText + cwdText + " ".repeat(PADDING_X);
251
+ const displayText = isSelected ? withBgColor(rowText, "blue") : rowText;
252
+ return /* @__PURE__ */ jsx5(
253
+ Text5,
254
+ {
255
+ color: isSelected ? void 0 : cwdColor,
256
+ dimColor: !isSelected && cwdColor === void 0,
257
+ children: displayText
258
+ }
259
+ );
170
260
  }
171
261
 
172
262
  // src/components/ProcessList.tsx
173
- import { Box as Box3, Text as Text3 } from "ink";
174
- import { jsx as jsx3, jsxs as jsxs3 } from "react/jsx-runtime";
175
- function formatPercent(value, width) {
176
- const str = `${value.toFixed(1)}%`;
177
- return str.padStart(width);
263
+ import { jsx as jsx6, jsxs as jsxs5 } from "react/jsx-runtime";
264
+ function TableHeader() {
265
+ return /* @__PURE__ */ jsxs5(Text6, { bold: true, color: COLORS.title, children: [
266
+ "PID".padEnd(COLUMN_WIDTH.pid),
267
+ "CPU".padEnd(COLUMN_WIDTH.cpu),
268
+ "MEM".padEnd(COLUMN_WIDTH.memory),
269
+ "\u65F6\u957F".padEnd(COLUMN_WIDTH.elapsed),
270
+ "\u5DE5\u4F5C\u76EE\u5F55"
271
+ ] });
178
272
  }
179
273
  function ProcessList({
180
274
  processes,
181
275
  selectedIndex,
182
- loading
276
+ loading,
277
+ leftWidth
183
278
  }) {
184
279
  if (loading) {
185
- return /* @__PURE__ */ jsx3(Box3, { flexDirection: "column", children: /* @__PURE__ */ jsx3(Text3, { color: "gray", children: "\u52A0\u8F7D\u4E2D..." }) });
280
+ return /* @__PURE__ */ jsx6(LoadingState, { message: "\u52A0\u8F7D\u4E2D..." });
186
281
  }
187
282
  if (processes.length === 0) {
188
- return /* @__PURE__ */ jsx3(Box3, { flexDirection: "column", children: /* @__PURE__ */ jsx3(Text3, { color: "gray", children: "\u65E0\u8FD0\u884C\u4E2D\u7684 Claude \u8FDB\u7A0B" }) });
283
+ return /* @__PURE__ */ jsx6(EmptyPrompt, { message: "\u65E0\u8FD0\u884C\u4E2D\u7684 Claude \u8FDB\u7A0B" });
189
284
  }
190
- return /* @__PURE__ */ jsxs3(Box3, { flexDirection: "column", children: [
191
- /* @__PURE__ */ jsxs3(Box3, { children: [
192
- /* @__PURE__ */ jsx3(Text3, { bold: true, color: COLORS.title, children: " " }),
193
- /* @__PURE__ */ jsx3(Box3, { width: COLUMN_WIDTH.pid, children: /* @__PURE__ */ jsx3(Text3, { bold: true, color: COLORS.title, children: "PID" }) }),
194
- /* @__PURE__ */ jsx3(Box3, { width: COLUMN_WIDTH.cpu, children: /* @__PURE__ */ jsx3(Text3, { bold: true, color: COLORS.title, children: "CPU" }) }),
195
- /* @__PURE__ */ jsx3(Box3, { width: COLUMN_WIDTH.memory, children: /* @__PURE__ */ jsx3(Text3, { bold: true, color: COLORS.title, children: "MEM" }) }),
196
- /* @__PURE__ */ jsx3(Box3, { width: COLUMN_WIDTH.elapsed, children: /* @__PURE__ */ jsx3(Text3, { bold: true, color: COLORS.title, children: "\u65F6\u957F" }) }),
197
- /* @__PURE__ */ jsx3(Text3, { bold: true, color: COLORS.title, children: "\u5DE5\u4F5C\u76EE\u5F55" })
198
- ] }),
199
- /* @__PURE__ */ jsx3(Text3, { color: "gray", children: "\u2500".repeat(60) }),
200
- processes.map((proc, index) => {
201
- const isSelected = index === selectedIndex;
202
- const prefix = isSelected ? "\u25B6 " : " ";
203
- let cwdColor = void 0;
204
- if (proc.isOrphan) cwdColor = COLORS.orphan;
205
- else if (proc.isCurrent) cwdColor = COLORS.current;
206
- return /* @__PURE__ */ jsxs3(Box3, { children: [
207
- /* @__PURE__ */ jsx3(Text3, { color: isSelected ? COLORS.selected : void 0, children: prefix }),
208
- /* @__PURE__ */ jsx3(Box3, { width: COLUMN_WIDTH.pid, children: /* @__PURE__ */ jsx3(Text3, { color: isSelected ? COLORS.selected : void 0, children: proc.pid }) }),
209
- /* @__PURE__ */ jsx3(Box3, { width: COLUMN_WIDTH.cpu, children: /* @__PURE__ */ jsx3(Text3, { color: getUsageColor(proc.cpu), children: formatPercent(proc.cpu, COLUMN_WIDTH.cpu - 1) }) }),
210
- /* @__PURE__ */ jsx3(Box3, { width: COLUMN_WIDTH.memory, children: /* @__PURE__ */ jsx3(Text3, { color: getUsageColor(proc.memory), children: formatPercent(proc.memory, COLUMN_WIDTH.memory - 1) }) }),
211
- /* @__PURE__ */ jsx3(Box3, { width: COLUMN_WIDTH.elapsed, children: /* @__PURE__ */ jsx3(Text3, { color: isSelected ? COLORS.selected : "gray", children: formatElapsed(proc.elapsed).slice(0, COLUMN_WIDTH.elapsed - 1) }) }),
212
- /* @__PURE__ */ jsxs3(Text3, { color: cwdColor, children: [
213
- shortenPath(proc.cwd, 30),
214
- proc.isCurrent ? " \u25CF" : ""
215
- ] })
216
- ] }, proc.pid);
217
- })
218
- ] });
219
- }
220
-
221
- // src/components/StatusBar.tsx
222
- import { Box as Box4, Text as Text4 } from "ink";
223
- import { jsx as jsx4, jsxs as jsxs4 } from "react/jsx-runtime";
224
- function calculateStats(processes) {
225
- const totalCpu = processes.reduce((sum, p) => sum + p.cpu, 0);
226
- const totalMemoryPercent = processes.reduce((sum, p) => sum + p.memory, 0);
227
- const totalMemoryMB = totalMemoryPercent / 100 * ESTIMATED_TOTAL_MEMORY_MB;
228
- const orphanCount = processes.filter((p) => p.isOrphan).length;
229
- const currentCount = processes.filter((p) => p.isCurrent).length;
230
- return {
231
- count: processes.length,
232
- totalCpu,
233
- totalMemory: totalMemoryMB < 1024 ? `${Math.round(totalMemoryMB)}MB` : `${(totalMemoryMB / 1024).toFixed(1)}GB`,
234
- orphanCount,
235
- currentCount
236
- };
237
- }
238
- function StatusBar({ processes }) {
239
- const stats = calculateStats(processes);
240
- return /* @__PURE__ */ jsxs4(Box4, { children: [
241
- /* @__PURE__ */ jsx4(Text4, { color: COLORS.label, children: "\u8FDB\u7A0B: " }),
242
- /* @__PURE__ */ jsx4(Text4, { color: COLORS.value, children: stats.count }),
243
- /* @__PURE__ */ jsx4(Text4, { color: COLORS.label, children: " | CPU: " }),
244
- /* @__PURE__ */ jsxs4(Text4, { color: COLORS.value, children: [
245
- stats.totalCpu.toFixed(1),
246
- "%"
247
- ] }),
248
- /* @__PURE__ */ jsx4(Text4, { color: COLORS.label, children: " | \u5185\u5B58: " }),
249
- /* @__PURE__ */ jsx4(Text4, { color: COLORS.value, children: stats.totalMemory }),
250
- /* @__PURE__ */ jsx4(Text4, { color: COLORS.label, children: " | \u5B64\u513F: " }),
251
- /* @__PURE__ */ jsx4(Text4, { color: stats.orphanCount > 0 ? COLORS.orphan : COLORS.value, children: stats.orphanCount }),
252
- /* @__PURE__ */ jsx4(Text4, { color: COLORS.label, children: " | \u5F53\u524D: " }),
253
- /* @__PURE__ */ jsx4(Text4, { color: stats.currentCount > 0 ? COLORS.current : COLORS.value, children: stats.currentCount })
285
+ return /* @__PURE__ */ jsxs5(Box6, { flexDirection: "column", children: [
286
+ /* @__PURE__ */ jsx6(TableHeader, {}),
287
+ /* @__PURE__ */ jsx6(Separator, { char: "\u2500", length: leftWidth - 12 }),
288
+ processes.map((proc, index) => /* @__PURE__ */ jsx6(
289
+ ProcessItem,
290
+ {
291
+ process: proc,
292
+ isSelected: index === selectedIndex
293
+ },
294
+ proc.pid
295
+ ))
254
296
  ] });
255
297
  }
256
298
 
@@ -467,7 +509,7 @@ function useProcesses(interval2) {
467
509
  }
468
510
 
469
511
  // src/App.tsx
470
- import { jsx as jsx5, jsxs as jsxs5 } from "react/jsx-runtime";
512
+ import { jsx as jsx7, jsxs as jsxs6 } from "react/jsx-runtime";
471
513
  function App({ interval: interval2 }) {
472
514
  const { exit } = useApp();
473
515
  const { stdout } = useStdout();
@@ -507,52 +549,76 @@ function App({ interval: interval2 }) {
507
549
  const rightWidth = termWidth - leftWidth - 1;
508
550
  const contentHeight = termHeight - 4;
509
551
  if (error) {
510
- return /* @__PURE__ */ jsx5(Box5, { flexDirection: "column", width: termWidth, height: termHeight, children: /* @__PURE__ */ jsxs5(Text5, { color: COLORS.orphan, children: [
552
+ return /* @__PURE__ */ jsx7(Box7, { flexDirection: "column", width: termWidth, height: termHeight, children: /* @__PURE__ */ jsxs6(Text7, { color: COLORS.orphan, children: [
511
553
  "\u9519\u8BEF: ",
512
554
  error
513
555
  ] }) });
514
556
  }
515
- return /* @__PURE__ */ jsxs5(Box5, { flexDirection: "column", width: termWidth, height: termHeight, children: [
516
- /* @__PURE__ */ jsxs5(Box5, { children: [
517
- /* @__PURE__ */ jsx5(Text5, { bold: true, color: COLORS.title, children: "claude-ps" }),
518
- /* @__PURE__ */ jsx5(Text5, { color: COLORS.label, children: " - Claude Code \u8FDB\u7A0B\u7BA1\u7406\u5668" })
519
- ] }),
520
- /* @__PURE__ */ jsx5(StatusBar, { processes }),
521
- /* @__PURE__ */ jsxs5(Box5, { height: contentHeight, children: [
522
- /* @__PURE__ */ jsx5(Box5, { width: leftWidth, flexDirection: "column", height: contentHeight, children: /* @__PURE__ */ jsx5(
523
- ProcessList,
524
- {
525
- processes,
526
- selectedIndex,
527
- loading
528
- }
529
- ) }),
530
- /* @__PURE__ */ jsx5(Box5, { width: 1, flexDirection: "column", height: contentHeight, children: /* @__PURE__ */ jsx5(Text5, { color: COLORS.label, children: "\u2502\n".repeat(contentHeight).trim() }) }),
531
- /* @__PURE__ */ jsx5(Box5, { width: rightWidth, flexDirection: "column", height: contentHeight, children: /* @__PURE__ */ jsx5(DetailPanel, { process: selectedProcess }) })
532
- ] }),
533
- /* @__PURE__ */ jsx5(
534
- Box5,
535
- {
536
- borderStyle: "single",
537
- borderTop: true,
538
- borderBottom: false,
539
- borderLeft: false,
540
- borderRight: false,
541
- children: /* @__PURE__ */ jsx5(
542
- HelpBar,
557
+ return /* @__PURE__ */ jsxs6(
558
+ Box7,
559
+ {
560
+ flexDirection: "column",
561
+ width: termWidth,
562
+ height: termHeight,
563
+ paddingX: 4,
564
+ children: [
565
+ /* @__PURE__ */ jsxs6(Box7, { height: contentHeight, children: [
566
+ /* @__PURE__ */ jsxs6(Box7, { width: leftWidth, flexDirection: "column", height: contentHeight, children: [
567
+ /* @__PURE__ */ jsx7(Box7, { flexDirection: "column", children: /* @__PURE__ */ jsx7(Text7, { bold: true, color: "cyan", children: `
568
+ \u250F\u2501\u2578\u257B \u250F\u2501\u2513\u257B \u257B\u257A\u2533\u2513\u250F\u2501\u2578 \u250F\u2501\u2513\u250F\u2501\u2513
569
+ \u2503 \u2503 \u2523\u2501\u252B\u2503 \u2503 \u2503\u2503\u2523\u2578 \u257A\u2501\u2578\u2523\u2501\u251B\u2517\u2501\u2513
570
+ \u2517\u2501\u2578\u2517\u2501\u2578\u2579 \u2579\u2517\u2501\u251B\u257A\u253B\u251B\u2517\u2501\u2578 \u2579 \u2517\u2501\u251B
571
+ ` }) }),
572
+ /* @__PURE__ */ jsx7(Box7, { flexDirection: "column", height: 2, children: /* @__PURE__ */ jsx7(Text7, { color: "gray", children: "Claude Code \u8FDB\u7A0B\u7BA1\u7406\u5668" }) }),
573
+ /* @__PURE__ */ jsx7(StatusBar, { processes }),
574
+ /* @__PURE__ */ jsx7(
575
+ ProcessList,
576
+ {
577
+ leftWidth,
578
+ processes,
579
+ selectedIndex,
580
+ loading
581
+ }
582
+ )
583
+ ] }),
584
+ /* @__PURE__ */ jsx7(Box7, { width: 1, flexDirection: "column", height: contentHeight, children: /* @__PURE__ */ jsx7(Text7, { color: COLORS.label, children: "\u2502\n".repeat(contentHeight).trim() }) }),
585
+ /* @__PURE__ */ jsx7(
586
+ Box7,
587
+ {
588
+ width: rightWidth,
589
+ flexDirection: "column",
590
+ height: contentHeight,
591
+ paddingX: 4,
592
+ paddingY: 2,
593
+ children: /* @__PURE__ */ jsx7(DetailPanel, { process: selectedProcess })
594
+ }
595
+ )
596
+ ] }),
597
+ /* @__PURE__ */ jsx7(
598
+ Box7,
543
599
  {
544
- processCount: processes.length,
545
- interval: interval2,
546
- sortField
600
+ borderStyle: "single",
601
+ borderTop: true,
602
+ borderBottom: false,
603
+ borderLeft: false,
604
+ borderRight: false,
605
+ children: /* @__PURE__ */ jsx7(
606
+ HelpBar,
607
+ {
608
+ processCount: processes.length,
609
+ interval: interval2,
610
+ sortField
611
+ }
612
+ )
547
613
  }
548
614
  )
549
- }
550
- )
551
- ] });
615
+ ]
616
+ }
617
+ );
552
618
  }
553
619
 
554
620
  // src/index.tsx
555
- import { jsx as jsx6 } from "react/jsx-runtime";
621
+ import { jsx as jsx8 } from "react/jsx-runtime";
556
622
  var cli = meow(
557
623
  `
558
624
  Usage
@@ -574,6 +640,11 @@ var cli = meow(
574
640
  {
575
641
  importMeta: import.meta,
576
642
  flags: {
643
+ help: {
644
+ type: "boolean",
645
+ shortFlag: "h",
646
+ default: false
647
+ },
577
648
  list: {
578
649
  type: "boolean",
579
650
  shortFlag: "l",
@@ -588,6 +659,11 @@ var cli = meow(
588
659
  type: "number",
589
660
  shortFlag: "i",
590
661
  default: 2
662
+ },
663
+ version: {
664
+ type: "boolean",
665
+ shortFlag: "v",
666
+ default: false
591
667
  }
592
668
  }
593
669
  }
@@ -606,4 +682,4 @@ if (list || json) {
606
682
  }
607
683
  process.exit(0);
608
684
  }
609
- withFullScreen(/* @__PURE__ */ jsx6(App, { interval })).start();
685
+ withFullScreen(/* @__PURE__ */ jsx8(App, { interval })).start();
package/package.json CHANGED
@@ -1,15 +1,13 @@
1
1
  {
2
2
  "name": "claude-ps",
3
- "version": "0.1.1",
3
+ "version": "0.2.2",
4
4
  "description": "TUI application for viewing and managing Claude Code processes",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
7
7
  "bin": {
8
8
  "claude-ps": "dist/index.js"
9
9
  },
10
- "files": [
11
- "dist"
12
- ],
10
+ "files": ["dist"],
13
11
  "scripts": {
14
12
  "dev": "tsx src/index.tsx",
15
13
  "build": "tsup",
@@ -19,12 +17,7 @@
19
17
  "typecheck": "tsc --noEmit",
20
18
  "all": "pnpm format && pnpm typecheck && pnpm lint"
21
19
  },
22
- "keywords": [
23
- "claude",
24
- "tui",
25
- "terminal",
26
- "process-manager"
27
- ],
20
+ "keywords": ["claude", "tui", "terminal", "process-manager"],
28
21
  "author": "ziheng",
29
22
  "license": "MIT",
30
23
  "dependencies": {
@@ -44,4 +37,4 @@
44
37
  "engines": {
45
38
  "node": ">=18"
46
39
  }
47
- }
40
+ }