claude-starter 1.3.3 → 1.3.5
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.
- package/README.md +113 -113
- package/index.js +139 -54
- package/package.json +6 -2
package/README.md
CHANGED
|
@@ -11,8 +11,8 @@
|
|
|
11
11
|
<h1 align="center">🚀 Claude Starter</h1>
|
|
12
12
|
|
|
13
13
|
<p align="center">
|
|
14
|
-
<strong>Claude Code
|
|
15
|
-
<strong>
|
|
14
|
+
<strong>Your homepage for Claude Code.</strong> All your sessions, at a glance.<br/>
|
|
15
|
+
<strong>Claude Code 的主页。</strong>你的所有会话,一目了然。
|
|
16
16
|
</p>
|
|
17
17
|
|
|
18
18
|
<p align="center">
|
|
@@ -25,117 +25,7 @@
|
|
|
25
25
|
|
|
26
26
|
---
|
|
27
27
|
|
|
28
|
-
#
|
|
29
|
-
|
|
30
|
-
## 痛点
|
|
31
|
-
|
|
32
|
-
用过 Claude Code 的 `/resume` 吗?它给你的是这样一坨东西:
|
|
33
|
-
|
|
34
|
-
```
|
|
35
|
-
? Select a conversation
|
|
36
|
-
3ee0f33a-b882-424f-9ba4-260342e4dd5b - 4/3/2026, 10:53:41 AM
|
|
37
|
-
87570bab-ee92-4681-9591-54abf2fcb486 - 4/3/2026, 10:18:55 AM
|
|
38
|
-
...200 个 UUID...
|
|
39
|
-
```
|
|
40
|
-
|
|
41
|
-
一堆 UUID,没有上下文,无法搜索。**想找到上周帮你调过 bug 的那个 session?祝你好运。**
|
|
42
|
-
|
|
43
|
-
## 解决方案
|
|
44
|
-
|
|
45
|
-
**Claude Starter** 是一个精美的终端可视化工具,让你能像浏览网页一样浏览所有 Claude 历史会话。它是你的 **Claude 主页** —— 每次打开终端,`claude-starter` 一敲,所有 session 一目了然。
|
|
46
|
-
|
|
47
|
-
```bash
|
|
48
|
-
claude-starter
|
|
49
|
-
```
|
|
50
|
-
|
|
51
|
-
精美的分屏 UI,Tokyo Night 配色。左侧列表一目了然,右侧实时预览对话详情。不是 UUID,是你**真正说过的话**。
|
|
52
|
-
|
|
53
|
-
## 🔍 搜索 — 杀手级功能
|
|
54
|
-
|
|
55
|
-
按 `/` 开始输入,**就这么简单**。无需按回车。
|
|
56
|
-
|
|
57
|
-
跨项目名、Git 分支、对话内容**全文实时搜索**。输入即过滤,`↑↓` 直接导航结果。
|
|
58
|
-
|
|
59
|
-
- `auth` → 所有认证相关的对话
|
|
60
|
-
- `refactor` → 上周的代码重构
|
|
61
|
-
- `web-app fix` → 某个项目的 bug 修复
|
|
62
|
-
|
|
63
|
-
**不需要管理模式,不需要确认。输入即搜,方向键即走。**
|
|
64
|
-
|
|
65
|
-
## 核心能力
|
|
66
|
-
|
|
67
|
-
| | 功能 | 说明 |
|
|
68
|
-
|---|---|---|
|
|
69
|
-
| 🎨 | **精美 TUI** | Tokyo Night 配色,分屏布局,终端里的 App |
|
|
70
|
-
| ✨ | **一键新建** | 列表顶部直接新建对话 |
|
|
71
|
-
| 🔍 | **即时搜索** | `/` 全文搜索,无需回车 |
|
|
72
|
-
| 📂 | **项目过滤** | `p` 按项目筛选 |
|
|
73
|
-
| ⚡ | **秒级恢复** | 选中 → Enter → 回到对话 |
|
|
74
|
-
| 📋 | **对话预览** | 右侧面板展示完整元数据和对话历史 |
|
|
75
|
-
| 🔀 | **多种排序** | 时间 / 大小 / 消息数 / 项目 |
|
|
76
|
-
| 📎 | **复制 ID** | `c` 一键复制到剪贴板 |
|
|
77
|
-
| 🔒 | **权限模式** | `m` 设置权限模式,`d` 一键 danger 模式恢复 |
|
|
78
|
-
| ✏️ | **重命名会话** | `r` 直接重命名,支持中文输入 |
|
|
79
|
-
| 🗑️ | **删除会话** | `x` 删除不需要的会话 |
|
|
80
|
-
| ⌨️ | **Vim 快捷键** | `j`/`k` 上下,`g`/`G` 跳顶/底 |
|
|
81
|
-
| 🧠 | **智能 CLI** | 自动检测 `mai-claude` / `claude` |
|
|
82
|
-
| 🔐 | **完全本地** | 不联网,不上传,不追踪 |
|
|
83
|
-
|
|
84
|
-
## 安装
|
|
85
|
-
|
|
86
|
-
```bash
|
|
87
|
-
npm install -g claude-starter
|
|
88
|
-
```
|
|
89
|
-
|
|
90
|
-
或者从源码安装:
|
|
91
|
-
|
|
92
|
-
```bash
|
|
93
|
-
git clone https://github.com/Bojun-Vvibe/claude-starter.git
|
|
94
|
-
cd claude-starter
|
|
95
|
-
npm install
|
|
96
|
-
npm link
|
|
97
|
-
```
|
|
98
|
-
|
|
99
|
-
然后运行 `claude-starter`,就这么简单。
|
|
100
|
-
|
|
101
|
-
## CLI 参数
|
|
102
|
-
|
|
103
|
-
```bash
|
|
104
|
-
claude-starter # 启动交互式 TUI
|
|
105
|
-
claude-starter --list [N] # 打印最近 N 个会话(默认 30)
|
|
106
|
-
claude-starter --version # 显示版本号
|
|
107
|
-
claude-starter --update # 检查并更新到最新版本
|
|
108
|
-
claude-starter --help # 显示帮助信息
|
|
109
|
-
```
|
|
110
|
-
|
|
111
|
-
## 快捷键
|
|
112
|
-
|
|
113
|
-
| 按键 | 功能 |
|
|
114
|
-
|:---:|------|
|
|
115
|
-
| `↑` `↓` / `j` `k` | 上下导航 |
|
|
116
|
-
| `Enter` | 新建 / 恢复对话 |
|
|
117
|
-
| `n` | 直接新建 |
|
|
118
|
-
| `d` | Danger 模式恢复(bypassPermissions) |
|
|
119
|
-
| `m` | 权限模式选择器 |
|
|
120
|
-
| `r` | 重命名会话 |
|
|
121
|
-
| `/` | 搜索 |
|
|
122
|
-
| `Backspace` | 删除搜索字符,删空自动退出 |
|
|
123
|
-
| `Esc` | 清空搜索 |
|
|
124
|
-
| `p` | 按项目过滤 |
|
|
125
|
-
| `s` | 切换排序(时间/大小/消息数/项目) |
|
|
126
|
-
| `c` | 复制 Session ID |
|
|
127
|
-
| `x` / `Delete` | 删除会话 |
|
|
128
|
-
| `g` / `G` | 跳到顶 / 底 |
|
|
129
|
-
| `Ctrl-D` / `Ctrl-U` | 翻页 |
|
|
130
|
-
| `q` / `Ctrl-C` | 退出 |
|
|
131
|
-
|
|
132
|
-
## 原理
|
|
133
|
-
|
|
134
|
-
读取 `~/.claude/projects/` 下的 JSONL 会话文件,解析元数据和对话内容。200 个 session 加载耗时 ~10ms。**所有数据留在本地,不联网。**
|
|
135
|
-
|
|
136
|
-
---
|
|
137
|
-
|
|
138
|
-
# 🇬🇧 English
|
|
28
|
+
# English
|
|
139
29
|
|
|
140
30
|
## The Problem
|
|
141
31
|
|
|
@@ -256,6 +146,116 @@ MIT
|
|
|
256
146
|
|
|
257
147
|
---
|
|
258
148
|
|
|
149
|
+
# 中文
|
|
150
|
+
|
|
151
|
+
## 痛点
|
|
152
|
+
|
|
153
|
+
用过 Claude Code 的 `/resume` 吗?它给你的是这样一坨东西:
|
|
154
|
+
|
|
155
|
+
```
|
|
156
|
+
? Select a conversation
|
|
157
|
+
3ee0f33a-b882-424f-9ba4-260342e4dd5b - 4/3/2026, 10:53:41 AM
|
|
158
|
+
87570bab-ee92-4681-9591-54abf2fcb486 - 4/3/2026, 10:18:55 AM
|
|
159
|
+
...200 个 UUID...
|
|
160
|
+
```
|
|
161
|
+
|
|
162
|
+
一堆 UUID,没有上下文,无法搜索。**想找到上周帮你调过 bug 的那个 session?祝你好运。**
|
|
163
|
+
|
|
164
|
+
## 解决方案
|
|
165
|
+
|
|
166
|
+
**Claude Starter** 是一个精美的终端可视化工具,让你能像浏览网页一样浏览所有 Claude 历史会话。它是你的 **Claude 主页** —— 每次打开终端,`claude-starter` 一敲,所有 session 一目了然。
|
|
167
|
+
|
|
168
|
+
```bash
|
|
169
|
+
claude-starter
|
|
170
|
+
```
|
|
171
|
+
|
|
172
|
+
精美的分屏 UI,Tokyo Night 配色。左侧列表一目了然,右侧实时预览对话详情。不是 UUID,是你**真正说过的话**。
|
|
173
|
+
|
|
174
|
+
## 🔍 搜索 — 杀手级功能
|
|
175
|
+
|
|
176
|
+
按 `/` 开始输入,**就这么简单**。无需按回车。
|
|
177
|
+
|
|
178
|
+
跨项目名、Git 分支、对话内容**全文实时搜索**。输入即过滤,`↑↓` 直接导航结果。
|
|
179
|
+
|
|
180
|
+
- `auth` → 所有认证相关的对话
|
|
181
|
+
- `refactor` → 上周的代码重构
|
|
182
|
+
- `web-app fix` → 某个项目的 bug 修复
|
|
183
|
+
|
|
184
|
+
**不需要管理模式,不需要确认。输入即搜,方向键即走。**
|
|
185
|
+
|
|
186
|
+
## 核心能力
|
|
187
|
+
|
|
188
|
+
| | 功能 | 说明 |
|
|
189
|
+
|---|---|---|
|
|
190
|
+
| 🎨 | **精美 TUI** | Tokyo Night 配色,分屏布局,终端里的 App |
|
|
191
|
+
| ✨ | **一键新建** | 列表顶部直接新建对话 |
|
|
192
|
+
| 🔍 | **即时搜索** | `/` 全文搜索,无需回车 |
|
|
193
|
+
| 📂 | **项目过滤** | `p` 按项目筛选 |
|
|
194
|
+
| ⚡ | **秒级恢复** | 选中 → Enter → 回到对话 |
|
|
195
|
+
| 📋 | **对话预览** | 右侧面板展示完整元数据和对话历史 |
|
|
196
|
+
| 🔀 | **多种排序** | 时间 / 大小 / 消息数 / 项目 |
|
|
197
|
+
| 📎 | **复制 ID** | `c` 一键复制到剪贴板 |
|
|
198
|
+
| 🔒 | **权限模式** | `m` 设置权限模式,`d` 一键 danger 模式恢复 |
|
|
199
|
+
| ✏️ | **重命名会话** | `r` 直接重命名,支持中文输入 |
|
|
200
|
+
| 🗑️ | **删除会话** | `x` 删除不需要的会话 |
|
|
201
|
+
| ⌨️ | **Vim 快捷键** | `j`/`k` 上下,`g`/`G` 跳顶/底 |
|
|
202
|
+
| 🧠 | **智能 CLI** | 自动检测 `mai-claude` / `claude` |
|
|
203
|
+
| 🔐 | **完全本地** | 不联网,不上传,不追踪 |
|
|
204
|
+
|
|
205
|
+
## 安装
|
|
206
|
+
|
|
207
|
+
```bash
|
|
208
|
+
npm install -g claude-starter
|
|
209
|
+
```
|
|
210
|
+
|
|
211
|
+
或者从源码安装:
|
|
212
|
+
|
|
213
|
+
```bash
|
|
214
|
+
git clone https://github.com/Bojun-Vvibe/claude-starter.git
|
|
215
|
+
cd claude-starter
|
|
216
|
+
npm install
|
|
217
|
+
npm link
|
|
218
|
+
```
|
|
219
|
+
|
|
220
|
+
然后运行 `claude-starter`,就这么简单。
|
|
221
|
+
|
|
222
|
+
## CLI 参数
|
|
223
|
+
|
|
224
|
+
```bash
|
|
225
|
+
claude-starter # 启动交互式 TUI
|
|
226
|
+
claude-starter --list [N] # 打印最近 N 个会话(默认 30)
|
|
227
|
+
claude-starter --version # 显示版本号
|
|
228
|
+
claude-starter --update # 检查并更新到最新版本
|
|
229
|
+
claude-starter --help # 显示帮助信息
|
|
230
|
+
```
|
|
231
|
+
|
|
232
|
+
## 快捷键
|
|
233
|
+
|
|
234
|
+
| 按键 | 功能 |
|
|
235
|
+
|:---:|------|
|
|
236
|
+
| `↑` `↓` / `j` `k` | 上下导航 |
|
|
237
|
+
| `Enter` | 新建 / 恢复对话 |
|
|
238
|
+
| `n` | 直接新建 |
|
|
239
|
+
| `d` | Danger 模式恢复(bypassPermissions) |
|
|
240
|
+
| `m` | 权限模式选择器 |
|
|
241
|
+
| `r` | 重命名会话 |
|
|
242
|
+
| `/` | 搜索 |
|
|
243
|
+
| `Backspace` | 删除搜索字符,删空自动退出 |
|
|
244
|
+
| `Esc` | 清空搜索 |
|
|
245
|
+
| `p` | 按项目过滤 |
|
|
246
|
+
| `s` | 切换排序(时间/大小/消息数/项目) |
|
|
247
|
+
| `c` | 复制 Session ID |
|
|
248
|
+
| `x` / `Delete` | 删除会话 |
|
|
249
|
+
| `g` / `G` | 跳到顶 / 底 |
|
|
250
|
+
| `Ctrl-D` / `Ctrl-U` | 翻页 |
|
|
251
|
+
| `q` / `Ctrl-C` | 退出 |
|
|
252
|
+
|
|
253
|
+
## 原理
|
|
254
|
+
|
|
255
|
+
读取 `~/.claude/projects/` 下的 JSONL 会话文件,解析元数据和对话内容。200 个 session 加载耗时 ~10ms。**所有数据留在本地,不联网。**
|
|
256
|
+
|
|
257
|
+
---
|
|
258
|
+
|
|
259
259
|
<p align="center">
|
|
260
260
|
<sub>Built with 💜 by <a href="https://github.com/Bojun-Vvibe">Bojun</a> — powered by Claude Code itself</sub>
|
|
261
261
|
</p>
|
package/index.js
CHANGED
|
@@ -202,17 +202,20 @@ function loadSessionQuick(filePath, projectName) {
|
|
|
202
202
|
const sessionId = path.basename(filePath, '.jsonl');
|
|
203
203
|
const stat = fs.statSync(filePath);
|
|
204
204
|
|
|
205
|
+
// Use 32KB head buffer (up from 8KB) to handle sessions whose first user
|
|
206
|
+
// message is very large (e.g. pasted code blocks, long queries).
|
|
207
|
+
const HEAD_SIZE = 32768;
|
|
205
208
|
const fd = fs.openSync(filePath, 'r');
|
|
206
|
-
const headBuf = Buffer.alloc(Math.min(
|
|
209
|
+
const headBuf = Buffer.alloc(Math.min(HEAD_SIZE, stat.size));
|
|
207
210
|
fs.readSync(fd, headBuf, 0, headBuf.length, 0);
|
|
208
211
|
|
|
209
212
|
// Read tail with progressive expansion: start at 32KB, grow up to 256KB
|
|
210
213
|
// until we find a JSON line with a top-level timestamp (to get accurate lastTs).
|
|
211
214
|
let tailStr = '';
|
|
212
|
-
if (stat.size >
|
|
215
|
+
if (stat.size > HEAD_SIZE) {
|
|
213
216
|
const tailSizes = [32768, 65536, 131072, 262144];
|
|
214
217
|
for (const ts of tailSizes) {
|
|
215
|
-
const tailSize = Math.min(ts, stat.size -
|
|
218
|
+
const tailSize = Math.min(ts, stat.size - HEAD_SIZE);
|
|
216
219
|
const tailBuf = Buffer.alloc(tailSize);
|
|
217
220
|
fs.readSync(fd, tailBuf, 0, tailSize, stat.size - tailSize);
|
|
218
221
|
tailStr = tailBuf.toString('utf-8');
|
|
@@ -221,7 +224,7 @@ function loadSessionQuick(filePath, projectName) {
|
|
|
221
224
|
try { return !!JSON.parse(line).timestamp; } catch { return false; }
|
|
222
225
|
});
|
|
223
226
|
if (hasTopLevelTs) break;
|
|
224
|
-
if (tailSize >= stat.size -
|
|
227
|
+
if (tailSize >= stat.size - HEAD_SIZE) break; // already read entire file
|
|
225
228
|
}
|
|
226
229
|
}
|
|
227
230
|
fs.closeSync(fd);
|
|
@@ -250,7 +253,42 @@ function loadSessionQuick(filePath, projectName) {
|
|
|
250
253
|
userMsgCount++;
|
|
251
254
|
if (!firstUserMsg) firstUserMsg = extractUserText(d);
|
|
252
255
|
}
|
|
253
|
-
} catch (e) {
|
|
256
|
+
} catch (e) {
|
|
257
|
+
// The line was truncated by the head buffer. Try to salvage metadata
|
|
258
|
+
// via regex so we don't lose the session entirely.
|
|
259
|
+
if (!firstTs) {
|
|
260
|
+
const tsMatch = line.match(/"timestamp"\s*:\s*"([^"]+)"/);
|
|
261
|
+
if (tsMatch) firstTs = tsMatch[1];
|
|
262
|
+
}
|
|
263
|
+
if (!version) {
|
|
264
|
+
const vMatch = line.match(/"version"\s*:\s*"([^"]+)"/);
|
|
265
|
+
if (vMatch) version = vMatch[1];
|
|
266
|
+
}
|
|
267
|
+
if (!gitBranch) {
|
|
268
|
+
const bMatch = line.match(/"gitBranch"\s*:\s*"([^"]+)"/);
|
|
269
|
+
if (bMatch) gitBranch = bMatch[1];
|
|
270
|
+
}
|
|
271
|
+
if (!cwd) {
|
|
272
|
+
const cwdMatch = line.match(/"cwd"\s*:\s*"([^"]+)"/);
|
|
273
|
+
if (cwdMatch) cwd = cwdMatch[1];
|
|
274
|
+
}
|
|
275
|
+
// Try to extract user message text from the truncated JSON line.
|
|
276
|
+
// User messages have "type":"user" and text content embedded inside.
|
|
277
|
+
if (!firstUserMsg && /"type"\s*:\s*"user"/.test(line)) {
|
|
278
|
+
userMsgCount++;
|
|
279
|
+
// Match the text field inside message.content (handles both string
|
|
280
|
+
// content and array-of-objects content structures).
|
|
281
|
+
const textMatch = line.match(/"text"\s*:\s*"((?:[^"\\]|\\.)*)/) ||
|
|
282
|
+
line.match(/"content"\s*:\s*"((?:[^"\\]|\\.)*)/);
|
|
283
|
+
if (textMatch) {
|
|
284
|
+
let text = '';
|
|
285
|
+
try { text = JSON.parse('"' + textMatch[1] + '"'); } catch { text = textMatch[1]; }
|
|
286
|
+
if (!text.startsWith('<local-command') && !text.startsWith('<command-')) {
|
|
287
|
+
firstUserMsg = text.substring(0, 200);
|
|
288
|
+
}
|
|
289
|
+
}
|
|
290
|
+
}
|
|
291
|
+
}
|
|
254
292
|
}
|
|
255
293
|
|
|
256
294
|
if (tailStr) {
|
|
@@ -259,7 +297,12 @@ function loadSessionQuick(filePath, projectName) {
|
|
|
259
297
|
try {
|
|
260
298
|
const d = JSON.parse(line);
|
|
261
299
|
if (d.timestamp) lastTs = d.timestamp;
|
|
262
|
-
if (d.type === 'user')
|
|
300
|
+
if (d.type === 'user') {
|
|
301
|
+
userMsgCount++;
|
|
302
|
+
// If no real user message was found in the head (all were commands),
|
|
303
|
+
// try to pick one from the tail as a fallback topic.
|
|
304
|
+
if (!firstUserMsg) firstUserMsg = extractUserText(d);
|
|
305
|
+
}
|
|
263
306
|
if (d.type === 'custom-title' && d.customTitle) customTitle = d.customTitle;
|
|
264
307
|
} catch (e) { /* partial line */ }
|
|
265
308
|
}
|
|
@@ -1465,58 +1508,99 @@ function createApp() {
|
|
|
1465
1508
|
listPanel.focus();
|
|
1466
1509
|
}
|
|
1467
1510
|
|
|
1468
|
-
// ───
|
|
1511
|
+
// ─── Exports for Testing ────────────────────────────────────────────────────
|
|
1512
|
+
// When required as a module (e.g. by tests), export helpers without launching
|
|
1513
|
+
// the CLI / TUI. The entry-point logic only runs when executed directly.
|
|
1514
|
+
|
|
1515
|
+
if (typeof module !== 'undefined') {
|
|
1516
|
+
module.exports = {
|
|
1517
|
+
// Data helpers
|
|
1518
|
+
getProjectDisplayName,
|
|
1519
|
+
extractUserText,
|
|
1520
|
+
loadSessionQuick,
|
|
1521
|
+
loadSessionDetail,
|
|
1522
|
+
loadAllSessions,
|
|
1523
|
+
// Formatting
|
|
1524
|
+
formatTimestamp,
|
|
1525
|
+
formatFileSize,
|
|
1526
|
+
getProjectColor,
|
|
1527
|
+
esc,
|
|
1528
|
+
// Meta
|
|
1529
|
+
loadMeta,
|
|
1530
|
+
saveMeta,
|
|
1531
|
+
getSessionMeta,
|
|
1532
|
+
getEffectivePermissionMode,
|
|
1533
|
+
setSessionPermissionMode,
|
|
1534
|
+
setGlobalPermissionMode,
|
|
1535
|
+
// Constants
|
|
1536
|
+
PERMISSION_MODES,
|
|
1537
|
+
PROJECT_COLORS,
|
|
1538
|
+
CLAUDE_DIR,
|
|
1539
|
+
PROJECTS_DIR,
|
|
1540
|
+
META_FILE,
|
|
1541
|
+
// CLI
|
|
1542
|
+
detectCLI,
|
|
1543
|
+
// List mode (for integration tests)
|
|
1544
|
+
runListMode,
|
|
1545
|
+
// TUI (for interaction tests)
|
|
1546
|
+
createApp,
|
|
1547
|
+
};
|
|
1548
|
+
}
|
|
1469
1549
|
|
|
1470
|
-
|
|
1550
|
+
// ─── Entry Point ─────────────────────────────────────────────────────────────
|
|
1551
|
+
// Only run CLI/TUI when executed directly (not when required as a module).
|
|
1471
1552
|
|
|
1472
|
-
|
|
1553
|
+
if (require.main === module) {
|
|
1554
|
+
const PKG = JSON.parse(fs.readFileSync(path.join(__dirname, 'package.json'), 'utf-8'));
|
|
1473
1555
|
|
|
1474
|
-
|
|
1475
|
-
console.log(`claude-starter v${PKG.version}`);
|
|
1476
|
-
process.exit(0);
|
|
1477
|
-
}
|
|
1556
|
+
const args = process.argv.slice(2);
|
|
1478
1557
|
|
|
1479
|
-
if (args.includes('--
|
|
1480
|
-
|
|
1481
|
-
|
|
1482
|
-
|
|
1483
|
-
red: '\x1b[31m',
|
|
1484
|
-
};
|
|
1485
|
-
console.log(`\n${C.cyan}🔄 Checking for updates…${C.reset}\n`);
|
|
1558
|
+
if (args.includes('--version') || args.includes('-v') || args.includes('-V')) {
|
|
1559
|
+
console.log(`claude-starter v${PKG.version}`);
|
|
1560
|
+
process.exit(0);
|
|
1561
|
+
}
|
|
1486
1562
|
|
|
1487
|
-
|
|
1488
|
-
const
|
|
1489
|
-
|
|
1490
|
-
|
|
1491
|
-
|
|
1563
|
+
if (args.includes('--update') || args.includes('-u')) {
|
|
1564
|
+
const C = {
|
|
1565
|
+
reset: '\x1b[0m', dim: '\x1b[2m', bold: '\x1b[1m',
|
|
1566
|
+
cyan: '\x1b[36m', yellow: '\x1b[33m', green: '\x1b[32m',
|
|
1567
|
+
red: '\x1b[31m',
|
|
1568
|
+
};
|
|
1569
|
+
console.log(`\n${C.cyan}🔄 Checking for updates…${C.reset}\n`);
|
|
1492
1570
|
|
|
1493
|
-
|
|
1494
|
-
|
|
1495
|
-
|
|
1496
|
-
|
|
1571
|
+
try {
|
|
1572
|
+
const latest = execSync('npm view claude-starter version 2>/dev/null', {
|
|
1573
|
+
stdio: ['pipe', 'pipe', 'pipe'],
|
|
1574
|
+
timeout: 10000,
|
|
1575
|
+
}).toString().trim();
|
|
1576
|
+
|
|
1577
|
+
if (latest === PKG.version) {
|
|
1578
|
+
console.log(`${C.green}✓ Already on the latest version (v${PKG.version})${C.reset}\n`);
|
|
1579
|
+
process.exit(0);
|
|
1580
|
+
}
|
|
1497
1581
|
|
|
1498
|
-
|
|
1499
|
-
|
|
1500
|
-
|
|
1582
|
+
console.log(`${C.yellow} Current: v${PKG.version}${C.reset}`);
|
|
1583
|
+
console.log(`${C.green} Latest: v${latest}${C.reset}\n`);
|
|
1584
|
+
console.log(`${C.cyan}📦 Updating…${C.reset}\n`);
|
|
1501
1585
|
|
|
1502
|
-
|
|
1503
|
-
|
|
1504
|
-
|
|
1586
|
+
try {
|
|
1587
|
+
execSync('npm install -g claude-starter@latest', { stdio: 'inherit', timeout: 60000 });
|
|
1588
|
+
console.log(`\n${C.green}${C.bold}✓ Updated to v${latest}${C.reset}\n`);
|
|
1589
|
+
} catch (e) {
|
|
1590
|
+
console.error(`\n${C.red}✗ Update failed. Try manually:${C.reset}`);
|
|
1591
|
+
console.log(`${C.yellow} npm install -g claude-starter@latest${C.reset}\n`);
|
|
1592
|
+
process.exit(1);
|
|
1593
|
+
}
|
|
1505
1594
|
} catch (e) {
|
|
1506
|
-
console.error(
|
|
1507
|
-
console.log(`${C.yellow} npm install -g claude-starter@latest${C.reset}\n`);
|
|
1595
|
+
console.error(`${C.red}✗ Could not check for updates (network error or npm not found)${C.reset}\n`);
|
|
1508
1596
|
process.exit(1);
|
|
1509
1597
|
}
|
|
1510
|
-
} catch (e) {
|
|
1511
|
-
console.error(`${C.red}✗ Could not check for updates (network error or npm not found)${C.reset}\n`);
|
|
1512
|
-
process.exit(1);
|
|
1513
|
-
}
|
|
1514
1598
|
|
|
1515
|
-
|
|
1516
|
-
}
|
|
1599
|
+
process.exit(0);
|
|
1600
|
+
}
|
|
1517
1601
|
|
|
1518
|
-
if (args.includes('--help') || args.includes('-h')) {
|
|
1519
|
-
|
|
1602
|
+
if (args.includes('--help') || args.includes('-h')) {
|
|
1603
|
+
console.log(`
|
|
1520
1604
|
\x1b[36m🚀 Claude Starter\x1b[0m \x1b[2mv${PKG.version}\x1b[0m
|
|
1521
1605
|
|
|
1522
1606
|
Usage:
|
|
@@ -1542,14 +1626,15 @@ TUI Keyboard Shortcuts:
|
|
|
1542
1626
|
Esc Clear filter
|
|
1543
1627
|
q / Ctrl-C Quit
|
|
1544
1628
|
`);
|
|
1545
|
-
|
|
1546
|
-
}
|
|
1629
|
+
process.exit(0);
|
|
1630
|
+
}
|
|
1547
1631
|
|
|
1548
|
-
if (args.includes('--list') || args.includes('-l')) {
|
|
1549
|
-
|
|
1550
|
-
|
|
1551
|
-
|
|
1552
|
-
|
|
1553
|
-
}
|
|
1632
|
+
if (args.includes('--list') || args.includes('-l')) {
|
|
1633
|
+
const limitIdx = args.indexOf('--list') !== -1 ? args.indexOf('--list') : args.indexOf('-l');
|
|
1634
|
+
const limit = parseInt(args[limitIdx + 1]) || 30;
|
|
1635
|
+
runListMode(limit);
|
|
1636
|
+
process.exit(0);
|
|
1637
|
+
}
|
|
1554
1638
|
|
|
1555
|
-
createApp();
|
|
1639
|
+
createApp();
|
|
1640
|
+
}
|
package/package.json
CHANGED
|
@@ -1,13 +1,17 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "claude-starter",
|
|
3
|
-
"version": "1.3.
|
|
3
|
+
"version": "1.3.5",
|
|
4
4
|
"description": "A beautiful terminal UI for managing Claude Code sessions — start new or resume past conversations",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"bin": {
|
|
7
7
|
"claude-starter": "./index.js"
|
|
8
8
|
},
|
|
9
9
|
"scripts": {
|
|
10
|
-
"start": "node index.js"
|
|
10
|
+
"start": "node index.js",
|
|
11
|
+
"test": "node --test test.js",
|
|
12
|
+
"test:tui": "node --test --test-force-exit test-tui.js",
|
|
13
|
+
"test:all": "node --test --test-force-exit test.js test-tui.js",
|
|
14
|
+
"prepublishOnly": "npm run test:all"
|
|
11
15
|
},
|
|
12
16
|
"keywords": [
|
|
13
17
|
"claude",
|