claude-ps 0.1.1 → 0.2.1

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 +231 -165
  2. package/package.json +4 -11
package/dist/index.js CHANGED
@@ -9,9 +9,9 @@ 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
@@ -53,6 +53,132 @@ function getUsageColor(percent) {
53
53
  return COLORS.usage.high;
54
54
  }
55
55
 
56
+ // src/components/ui/StatusBar.tsx
57
+ import { jsx, jsxs } from "react/jsx-runtime";
58
+ function calculateStats(processes) {
59
+ const totalCpu = processes.reduce((sum, p) => sum + p.cpu, 0);
60
+ const totalMemoryPercent = processes.reduce((sum, p) => sum + p.memory, 0);
61
+ const totalMemoryMB = totalMemoryPercent / 100 * ESTIMATED_TOTAL_MEMORY_MB;
62
+ const orphanCount = processes.filter((p) => p.isOrphan).length;
63
+ const currentCount = processes.filter((p) => p.isCurrent).length;
64
+ return {
65
+ count: processes.length,
66
+ totalCpu,
67
+ totalMemory: totalMemoryMB < 1024 ? `${Math.round(totalMemoryMB)}MB` : `${(totalMemoryMB / 1024).toFixed(1)}GB`,
68
+ orphanCount,
69
+ currentCount
70
+ };
71
+ }
72
+ function StatusBar({ processes }) {
73
+ const stats = calculateStats(processes);
74
+ return /* @__PURE__ */ jsxs(Box, { paddingX: 1, children: [
75
+ /* @__PURE__ */ jsx(Text, { color: COLORS.label, children: "\u8FDB\u7A0B: " }),
76
+ /* @__PURE__ */ jsx(Text, { color: COLORS.value, children: stats.count }),
77
+ /* @__PURE__ */ jsx(Text, { color: COLORS.label, children: " | CPU: " }),
78
+ /* @__PURE__ */ jsxs(Text, { color: COLORS.value, children: [
79
+ stats.totalCpu.toFixed(1),
80
+ "%"
81
+ ] }),
82
+ /* @__PURE__ */ jsx(Text, { color: COLORS.label, children: " | \u5185\u5B58: " }),
83
+ /* @__PURE__ */ jsx(Text, { color: COLORS.value, children: stats.totalMemory }),
84
+ /* @__PURE__ */ jsx(Text, { color: COLORS.label, children: " | \u5B64\u513F: " }),
85
+ /* @__PURE__ */ jsx(Text, { color: stats.orphanCount > 0 ? COLORS.orphan : COLORS.value, children: stats.orphanCount }),
86
+ /* @__PURE__ */ jsx(Text, { color: COLORS.label, children: " | \u5F53\u524D: " }),
87
+ /* @__PURE__ */ jsx(Text, { color: stats.currentCount > 0 ? COLORS.current : COLORS.value, children: stats.currentCount })
88
+ ] });
89
+ }
90
+
91
+ // src/components/ui/HelpBar.tsx
92
+ import { Box as Box3, Text as Text3 } from "ink";
93
+
94
+ // src/components/ui/primitives.tsx
95
+ import { Box as Box2, Text as Text2 } from "ink";
96
+ import { jsx as jsx2, jsxs as jsxs2 } from "react/jsx-runtime";
97
+ function Separator({
98
+ char = "\u2500",
99
+ length = 60
100
+ }) {
101
+ return /* @__PURE__ */ jsx2(Text2, { color: "gray", children: char.repeat(length) });
102
+ }
103
+ function EmptyPrompt({ message }) {
104
+ return /* @__PURE__ */ jsx2(Box2, { paddingX: 1, children: /* @__PURE__ */ jsx2(Text2, { color: "gray", children: message }) });
105
+ }
106
+ function LoadingState({ message = "\u52A0\u8F7D\u4E2D..." }) {
107
+ return /* @__PURE__ */ jsx2(Box2, { paddingX: 1, children: /* @__PURE__ */ jsx2(Text2, { color: "gray", children: message }) });
108
+ }
109
+ function InfoRow({ label, value }) {
110
+ return /* @__PURE__ */ jsxs2(Box2, { children: [
111
+ /* @__PURE__ */ jsxs2(Text2, { color: "cyan", children: [
112
+ label,
113
+ ": "
114
+ ] }),
115
+ /* @__PURE__ */ jsx2(Text2, { children: value })
116
+ ] });
117
+ }
118
+ function Section({
119
+ title,
120
+ children
121
+ }) {
122
+ return /* @__PURE__ */ jsxs2(Box2, { flexDirection: "column", children: [
123
+ /* @__PURE__ */ jsx2(Text2, { bold: true, color: "cyan", children: title }),
124
+ children
125
+ ] });
126
+ }
127
+ function KeyHint({
128
+ shortcut,
129
+ desc
130
+ }) {
131
+ return /* @__PURE__ */ jsxs2(Text2, { children: [
132
+ /* @__PURE__ */ jsx2(Text2, { color: "blue", children: shortcut }),
133
+ /* @__PURE__ */ jsxs2(Text2, { color: "gray", children: [
134
+ " ",
135
+ desc
136
+ ] })
137
+ ] });
138
+ }
139
+
140
+ // src/components/ui/HelpBar.tsx
141
+ import { jsx as jsx3, jsxs as jsxs3 } from "react/jsx-runtime";
142
+ var hints = [
143
+ { key: "\u2191/\u2193", desc: "\u79FB\u52A8" },
144
+ { key: "d", desc: "\u7EC8\u6B62" },
145
+ { key: "D", desc: "\u5F3A\u6740" },
146
+ { key: "s", desc: "\u6392\u5E8F" },
147
+ { key: "r", desc: "\u5237\u65B0" },
148
+ { key: "q", desc: "\u9000\u51FA" }
149
+ ];
150
+ var sortFieldLabels = {
151
+ cpu: "CPU",
152
+ memory: "\u5185\u5B58",
153
+ elapsed: "\u65F6\u957F",
154
+ default: "PID"
155
+ };
156
+ function HelpBar({ processCount, interval: interval2, sortField }) {
157
+ return /* @__PURE__ */ jsxs3(Box3, { justifyContent: "space-between", paddingX: 1, children: [
158
+ /* @__PURE__ */ jsx3(Box3, { gap: 1, children: hints.map((hint) => /* @__PURE__ */ jsx3(KeyHint, { shortcut: hint.key, desc: hint.desc }, hint.key)) }),
159
+ /* @__PURE__ */ jsxs3(Box3, { gap: 1, children: [
160
+ /* @__PURE__ */ jsxs3(Text3, { children: [
161
+ processCount,
162
+ " \u8FDB\u7A0B"
163
+ ] }),
164
+ /* @__PURE__ */ jsx3(Text3, { color: COLORS.label, children: "|" }),
165
+ /* @__PURE__ */ jsxs3(Text3, { color: COLORS.label, children: [
166
+ "\u6392\u5E8F: ",
167
+ sortFieldLabels[sortField]
168
+ ] }),
169
+ /* @__PURE__ */ jsx3(Text3, { color: COLORS.label, children: "|" }),
170
+ /* @__PURE__ */ jsxs3(Text3, { color: COLORS.label, children: [
171
+ "\u5237\u65B0: ",
172
+ interval2,
173
+ "s"
174
+ ] })
175
+ ] })
176
+ ] });
177
+ }
178
+
179
+ // src/components/ui/DetailPanel.tsx
180
+ import { Box as Box4, Text as Text4 } from "ink";
181
+
56
182
  // src/utils/format.ts
57
183
  function formatMemory(memPercent) {
58
184
  const usedMB = memPercent / 100 * ESTIMATED_TOTAL_MEMORY_MB;
@@ -84,97 +210,83 @@ function shortenPath(inputPath, maxLen = 25) {
84
210
  return `${path.slice(0, half)}...${path.slice(-half)}`;
85
211
  }
86
212
 
87
- // src/components/DetailPanel.tsx
88
- import { jsx, jsxs } from "react/jsx-runtime";
213
+ // src/components/ui/DetailPanel.tsx
214
+ import { jsx as jsx4, jsxs as jsxs4 } from "react/jsx-runtime";
89
215
  function DetailPanel({ process: proc }) {
90
216
  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" }) });
217
+ return /* @__PURE__ */ jsx4(EmptyPrompt, { message: "\u9009\u62E9\u4E00\u4E2A\u8FDB\u7A0B\u67E5\u770B\u8BE6\u60C5" });
92
218
  }
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) })
219
+ return /* @__PURE__ */ jsxs4(Box4, { flexDirection: "column", paddingX: 1, children: [
220
+ /* @__PURE__ */ jsxs4(Section, { title: "\u8D44\u6E90\u4FE1\u606F", children: [
221
+ /* @__PURE__ */ jsx4(InfoRow, { label: "CPU", value: `${proc.cpu.toFixed(1)}%` }),
222
+ /* @__PURE__ */ jsx4(InfoRow, { label: "\u5185\u5B58", value: formatMemory(proc.memory) }),
223
+ /* @__PURE__ */ jsx4(InfoRow, { label: "\u65F6\u957F", value: formatElapsed(proc.elapsed) })
106
224
  ] }),
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" })
225
+ /* @__PURE__ */ jsxs4(Box4, { flexDirection: "column", children: [
226
+ /* @__PURE__ */ jsx4(Text4, { children: " " }),
227
+ /* @__PURE__ */ jsx4(Text4, { bold: true, color: "cyan", children: "Session:" }),
228
+ /* @__PURE__ */ jsx4(Text4, { color: COLORS.label, wrap: "truncate", children: proc.sessionPath || "\u65E0\u4F1A\u8BDD\u6587\u4EF6" })
111
229
  ] }),
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
- "]",
119
- " "
120
- ] }),
121
- /* @__PURE__ */ jsx(Text, { wrap: "truncate", children: msg.content })
122
- ] }, msg.timestamp))
230
+ /* @__PURE__ */ jsxs4(Box4, { flexDirection: "column", children: [
231
+ /* @__PURE__ */ jsx4(Text4, { bold: true, color: "cyan", children: "\u2500 \u6700\u8FD1\u5BF9\u8BDD \u2500" }),
232
+ 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: [
233
+ /* @__PURE__ */ jsxs4(Text4, { color: msg.role === "user" ? COLORS.current : "blue", children: [
234
+ "[",
235
+ msg.role === "user" ? "User" : "Claude",
236
+ "]",
237
+ " "
238
+ ] }),
239
+ /* @__PURE__ */ jsx4(Text4, { wrap: "truncate", children: msg.content })
240
+ ] }, msg.timestamp))
241
+ ] })
123
242
  ] });
124
243
  }
125
244
 
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"
143
- };
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
- ] });
245
+ // src/components/ProcessList.tsx
246
+ import { Box as Box6, Text as Text6 } from "ink";
247
+
248
+ // src/components/ui/ProcessItem.tsx
249
+ import { Box as Box5, Text as Text5 } from "ink";
250
+ import { jsx as jsx5, jsxs as jsxs5 } from "react/jsx-runtime";
251
+ var PADDING_X = 1;
252
+ function ProcessItem({ process: process2, isSelected }) {
253
+ let cwdColor = void 0;
254
+ if (process2.isOrphan) cwdColor = "red";
255
+ else if (process2.isCurrent) cwdColor = "green";
256
+ const pidText = String(process2.pid).padStart(COLUMN_WIDTH.pid - 1);
257
+ const cpuText = `${process2.cpu.toFixed(1)}%`.padStart(COLUMN_WIDTH.cpu - 1);
258
+ const memText = `${process2.memory.toFixed(1)}%`.padStart(COLUMN_WIDTH.memory - 1);
259
+ const elapsedText = formatElapsed(process2.elapsed).padEnd(COLUMN_WIDTH.elapsed);
260
+ const cwdText = shortenPath(process2.cwd, 30) + (process2.isCurrent ? " \u25CF" : "");
261
+ return /* @__PURE__ */ jsx5(Box5, { children: /* @__PURE__ */ jsxs5(
262
+ Text5,
263
+ {
264
+ inverse: isSelected,
265
+ color: isSelected ? void 0 : cwdColor,
266
+ dimColor: !isSelected && cwdColor === void 0,
267
+ children: [
268
+ " ".repeat(PADDING_X),
269
+ pidText,
270
+ /* @__PURE__ */ jsx5(Text5, { color: getUsageColor(process2.cpu), inverse: isSelected, children: cpuText }),
271
+ /* @__PURE__ */ jsx5(Text5, { color: getUsageColor(process2.memory), inverse: isSelected, children: memText }),
272
+ /* @__PURE__ */ jsx5(Text5, { inverse: isSelected, color: isSelected ? void 0 : "gray", children: elapsedText }),
273
+ /* @__PURE__ */ jsx5(Text5, { color: cwdColor, inverse: isSelected, children: cwdText }),
274
+ " ".repeat(PADDING_X)
275
+ ]
276
+ }
277
+ ) });
170
278
  }
171
279
 
172
280
  // 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);
281
+ import { jsx as jsx6, jsxs as jsxs6 } from "react/jsx-runtime";
282
+ function TableHeader() {
283
+ return /* @__PURE__ */ jsxs6(Box6, { paddingX: 1, children: [
284
+ /* @__PURE__ */ jsx6(Box6, { width: COLUMN_WIDTH.pid, children: /* @__PURE__ */ jsx6(Text6, { bold: true, color: COLORS.title, children: "PID" }) }),
285
+ /* @__PURE__ */ jsx6(Box6, { width: COLUMN_WIDTH.cpu, children: /* @__PURE__ */ jsx6(Text6, { bold: true, color: COLORS.title, children: "CPU" }) }),
286
+ /* @__PURE__ */ jsx6(Box6, { width: COLUMN_WIDTH.memory, children: /* @__PURE__ */ jsx6(Text6, { bold: true, color: COLORS.title, children: "MEM" }) }),
287
+ /* @__PURE__ */ jsx6(Box6, { width: COLUMN_WIDTH.elapsed, children: /* @__PURE__ */ jsx6(Text6, { bold: true, color: COLORS.title, children: "\u65F6\u957F" }) }),
288
+ /* @__PURE__ */ jsx6(Text6, { bold: true, color: COLORS.title, children: "\u5DE5\u4F5C\u76EE\u5F55" })
289
+ ] });
178
290
  }
179
291
  function ProcessList({
180
292
  processes,
@@ -182,75 +294,22 @@ function ProcessList({
182
294
  loading
183
295
  }) {
184
296
  if (loading) {
185
- return /* @__PURE__ */ jsx3(Box3, { flexDirection: "column", children: /* @__PURE__ */ jsx3(Text3, { color: "gray", children: "\u52A0\u8F7D\u4E2D..." }) });
297
+ return /* @__PURE__ */ jsx6(LoadingState, { message: "\u52A0\u8F7D\u4E2D..." });
186
298
  }
187
299
  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" }) });
300
+ return /* @__PURE__ */ jsx6(EmptyPrompt, { message: "\u65E0\u8FD0\u884C\u4E2D\u7684 Claude \u8FDB\u7A0B" });
189
301
  }
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 })
302
+ return /* @__PURE__ */ jsxs6(Box6, { flexDirection: "column", children: [
303
+ /* @__PURE__ */ jsx6(TableHeader, {}),
304
+ /* @__PURE__ */ jsx6(Separator, { char: "\u2500", length: 60 }),
305
+ processes.map((proc, index) => /* @__PURE__ */ jsx6(
306
+ ProcessItem,
307
+ {
308
+ process: proc,
309
+ isSelected: index === selectedIndex
310
+ },
311
+ proc.pid
312
+ ))
254
313
  ] });
255
314
  }
256
315
 
@@ -467,7 +526,7 @@ function useProcesses(interval2) {
467
526
  }
468
527
 
469
528
  // src/App.tsx
470
- import { jsx as jsx5, jsxs as jsxs5 } from "react/jsx-runtime";
529
+ import { jsx as jsx7, jsxs as jsxs7 } from "react/jsx-runtime";
471
530
  function App({ interval: interval2 }) {
472
531
  const { exit } = useApp();
473
532
  const { stdout } = useStdout();
@@ -505,21 +564,28 @@ function App({ interval: interval2 }) {
505
564
  });
506
565
  const leftWidth = Math.floor(termWidth * 0.45);
507
566
  const rightWidth = termWidth - leftWidth - 1;
508
- const contentHeight = termHeight - 4;
567
+ const contentHeight = termHeight - 10;
509
568
  if (error) {
510
- return /* @__PURE__ */ jsx5(Box5, { flexDirection: "column", width: termWidth, height: termHeight, children: /* @__PURE__ */ jsxs5(Text5, { color: COLORS.orphan, children: [
569
+ return /* @__PURE__ */ jsx7(Box7, { flexDirection: "column", width: termWidth, height: termHeight, children: /* @__PURE__ */ jsxs7(Text7, { color: COLORS.orphan, children: [
511
570
  "\u9519\u8BEF: ",
512
571
  error
513
572
  ] }) });
514
573
  }
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" })
574
+ return /* @__PURE__ */ jsxs7(Box7, { flexDirection: "column", width: termWidth, height: termHeight, children: [
575
+ /* @__PURE__ */ jsxs7(Box7, { flexDirection: "column", paddingX: 2, children: [
576
+ /* @__PURE__ */ jsx7(Text7, { bold: true, color: "cyan", children: `
577
+ _ _ _ _
578
+ | | | | | | |
579
+ __| | ___ ___| | | __| |
580
+ / _\` |/ _ / __| | |/ _\` |
581
+ | (_| | (_) \\__ \\_ (_| |
582
+ \\__,_|\\___/|___/ |_|\\__,_|
583
+ ` }),
584
+ /* @__PURE__ */ jsx7(Text7, { color: "gray", children: "Claude Code \u8FDB\u7A0B\u7BA1\u7406\u5668" })
519
585
  ] }),
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(
586
+ /* @__PURE__ */ jsx7(StatusBar, { processes }),
587
+ /* @__PURE__ */ jsxs7(Box7, { height: contentHeight, children: [
588
+ /* @__PURE__ */ jsx7(Box7, { width: leftWidth, flexDirection: "column", height: contentHeight, children: /* @__PURE__ */ jsx7(
523
589
  ProcessList,
524
590
  {
525
591
  processes,
@@ -527,18 +593,18 @@ function App({ interval: interval2 }) {
527
593
  loading
528
594
  }
529
595
  ) }),
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 }) })
596
+ /* @__PURE__ */ jsx7(Box7, { width: 1, flexDirection: "column", height: contentHeight, children: /* @__PURE__ */ jsx7(Text7, { color: COLORS.label, children: "\u2502\n".repeat(contentHeight).trim() }) }),
597
+ /* @__PURE__ */ jsx7(Box7, { width: rightWidth, flexDirection: "column", height: contentHeight, children: /* @__PURE__ */ jsx7(DetailPanel, { process: selectedProcess }) })
532
598
  ] }),
533
- /* @__PURE__ */ jsx5(
534
- Box5,
599
+ /* @__PURE__ */ jsx7(
600
+ Box7,
535
601
  {
536
602
  borderStyle: "single",
537
603
  borderTop: true,
538
604
  borderBottom: false,
539
605
  borderLeft: false,
540
606
  borderRight: false,
541
- children: /* @__PURE__ */ jsx5(
607
+ children: /* @__PURE__ */ jsx7(
542
608
  HelpBar,
543
609
  {
544
610
  processCount: processes.length,
@@ -552,7 +618,7 @@ function App({ interval: interval2 }) {
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
@@ -606,4 +672,4 @@ if (list || json) {
606
672
  }
607
673
  process.exit(0);
608
674
  }
609
- withFullScreen(/* @__PURE__ */ jsx6(App, { interval })).start();
675
+ 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.1",
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
+ }