ccglance 1.0.0

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.
@@ -0,0 +1,332 @@
1
+ # ccglance
2
+
3
+ > 面向 [Claude Code](https://docs.anthropic.com/en/docs/claude-code) 的轻量多行状态栏 —— 模型、effort、上下文、缓存、git、会话,一眼尽览。TypeScript 编写、运行时零依赖。
4
+
5
+ [![Node.js >= 22](https://img.shields.io/badge/node-%3E%3D22-3c873a)](https://nodejs.org/)
6
+ [![License: MIT](https://img.shields.io/badge/license-MIT-blue.svg)](./LICENSE)
7
+
8
+ [English](./README.md) | 简体中文
9
+
10
+ 仓库:[github.com/CxMYu/CcGlanceLine](https://github.com/CxMYu/CcGlanceLine)
11
+
12
+ `ccglance` 以 Claude Code 通过 stdin 传入的 JSON 为主数据源;`status`
13
+ 段只在启用时读取 transcript(会话记录)尾部。它用 **TypeScript** 编写,以编译后的
14
+ JavaScript 发布,**运行时零依赖**(仅用 Node 标准库)。
15
+
16
+ ## 预览
17
+
18
+ ![ccglance 预览](./docs/assets/preview.png)
19
+
20
+ 截图由 `ccglance preview` 生成。
21
+
22
+ ## 特性
23
+
24
+ - **紧凑多行布局** —— 运行时、订阅配额、项目/会话分成逻辑行;无数据的行自动消失。
25
+ - **运行时零依赖** —— 仅用 Node 标准库;TypeScript 仅为构建期工具,不进发布包。
26
+ - **stdin 优先** —— 核心段消费 Claude Code 提供的 JSON;status 只读 transcript 尾部固定字节。
27
+ - **上下文块** —— 占用百分比、本轮输入/输出 token、剩余 token。
28
+ - **缓存块** —— 缓存命中率、读取/写入 token。
29
+ - **git 段** —— 分支、干净/脏/冲突标记、领先/落后计数;只跑一次有界 `git status`,并带短缓存。
30
+ - **会话段** —— 耗时 + 新增/删除行数。
31
+ - **Claude Code 版本 + 更新提示** —— 显示 stdin 里的 Claude Code `version`;
32
+ 本地 4 小时缓存发现新版时追加 `↑latest`。刷新在 stdout 写出后异步进行,不阻塞状态栏。
33
+ - **额外会话信息** —— 5小时/7天配额、美元成本,以及 Claude Code 提供时显示在 git 分支右侧的 worktree 名。
34
+ - **响应式多行布局** —— 读终端宽度(`COLUMNS`),把每行按能容纳的宽度自动折成多行;
35
+ 正确处理 CJK/emoji 显示宽度。
36
+ - **固定内置风格** —— 不读取用户配置文件,也不读取外部样式文件;状态栏使用 ccglance 自己的 emoji 优先风格。
37
+
38
+ ## 环境要求
39
+
40
+ - Node.js **>= 22**
41
+ - `git`(可选,仅 git 段需要)
42
+
43
+ Claude Code 兼容性:
44
+
45
+ | Claude Code CLI | ccglance 行为 |
46
+ |---|---|
47
+ | >= 1.0.71 | 支持基础 statusline stdin |
48
+ | >= 2.1.80 | 官方 `rate_limits.five_hour` / `rate_limits.seven_day` 字段存在时显示订阅配额行 |
49
+ | >= 2.1.153 | 优先使用 `COLUMNS` / `LINES` 做终端宽度适配;更旧版本回退到 TTY 宽度或 80 列 |
50
+
51
+ 配额行只面向订阅场景。Claude.ai Pro/Max 这类订阅会话可能提供 `rate_limits`;
52
+ API key、Bedrock、Vertex 等按量/外部网关场景通常没有该字段,ccglance 会隐藏配额行,
53
+ 不会自行推断或伪造。
54
+
55
+ ## 安装
56
+
57
+ ### 方式 A —— npm 全局安装(推荐)
58
+
59
+ ```bash
60
+ npm install -g ccglance # npm
61
+ yarn global add ccglance # 或 yarn
62
+ pnpm add -g ccglance # 或 pnpm
63
+ ```
64
+
65
+ registry 慢?用国内镜像:
66
+
67
+ ```bash
68
+ npm install -g ccglance --registry https://registry.npmmirror.com
69
+ ```
70
+
71
+ npm 会下载**预编译好的 `dist/`**(本机不跑编译器),并把 `ccglance` 命令装到 `PATH`。
72
+ 需要 Node.js **>= 22**。
73
+
74
+ 安装之后:
75
+
76
+ - ✅ `ccglance` 命令全局可用。
77
+ - ⚙️ **只装不会自动生效** —— 必须把 `statusLine` 块加进 `~/.claude/settings.json`
78
+ (见 [配置](#配置)),然后重启 Claude Code。
79
+ - 🔎 用 `ccglance preview`(样例渲染)或 `ccglance --help`(用法 + 完整 settings.json
80
+ 配置)验证。在普通终端直接敲 `ccglance` 只会打印这份帮助。
81
+
82
+ 后续可用 `npm update -g ccglance` 更新、`npm uninstall -g ccglance` 卸载。
83
+
84
+ ### 方式 B —— 从源码构建
85
+
86
+ ```bash
87
+ git clone https://github.com/CxMYu/CcGlanceLine.git
88
+ cd CcGlanceLine
89
+ npm install # 安装 devDeps;随后 prepare 脚本自动编译 src/ → dist/
90
+ npm link # 可选:把 ccglance 链到本机 PATH
91
+ ```
92
+
93
+ `npm install` 已经通过 `prepare` 生命周期脚本帮你构建好 `dist/`,**无需再单独跑构建**。
94
+ 编译产物入口为 `dist/cli.js`;`ccglance` bin 命令和 `node dist/cli.js` 是同一个文件。验证:
95
+
96
+ ```bash
97
+ node dist/cli.js preview
98
+ ```
99
+
100
+ ## 配置
101
+
102
+ 在 `~/.claude/settings.json` 加入 `statusLine`:
103
+
104
+ ```json
105
+ {
106
+ "statusLine": {
107
+ "type": "command",
108
+ "command": "ccglance",
109
+ "padding": 0
110
+ }
111
+ }
112
+ ```
113
+
114
+ 若未全局安装,直接用 Node 指向编译后的文件:
115
+
116
+ ```json
117
+ {
118
+ "statusLine": {
119
+ "type": "command",
120
+ "command": "node /绝对路径/ccglance/dist/cli.js"
121
+ }
122
+ }
123
+ ```
124
+
125
+ Windows 用完整路径,例如 `node D:\\path\\to\\ccglance\\dist\\cli.js`。
126
+
127
+ > **跨平台路径**:Claude Code v2.1.47+ 会在所有平台展开命令开头的 `~`,所以
128
+ > `node ~/path/to/dist/cli.js` 也能用。优先用 `~` 而非 `%USERPROFILE%`(近版本不可靠);
129
+ > 全局的 `ccglance` 命令则完全不需要写路径。`"padding": 0` 去掉 Claude Code 默认的左侧缩进,
130
+ > 让状态栏从最左开始。
131
+
132
+ ## 字段说明
133
+
134
+ **第一行 —— 运行时**
135
+
136
+ | 标识 | 段 | 来源 | 展示 |
137
+ |---|---|---|---|
138
+ | 🤖 | 模型 | `model.display_name`,缺失时回退 `model.id` | stdin display name 只做轻量压缩(`Opus 4.8 1M`);缺失时用可读 id 兜底 |
139
+ | 🧠 | effort | `effort.level` | 推理强度 |
140
+ | ✅/⏸️/💭/⚙️/🔧 | 状态 | transcript 尾部 | 仅图标显示状态;工具运行时显示工具名 |
141
+ | 🚀 | fast | `fast_mode` | 仅 fast 模式开启时显示 |
142
+ | ⚡️ | 上下文 | `context_window` | 占比 · 输入 · 输出 · 剩余 |
143
+ | 💾 | 缓存 | `context_window.current_usage` | 命中率 · 缓存读取 · 缓存写入 |
144
+ | 🎯 | 输出风格 | `output_style.name` | 当前 output style |
145
+
146
+ **第二行 —— 订阅 / 配额**
147
+
148
+ | 标识 | 段 | 来源 | 展示 |
149
+ |---|---|---|---|
150
+ | 📊 | 配额 | `rate_limits.five_hour` / `rate_limits.seven_day` | Hour / Week 紧凑月相仪表,各自带百分比和重置时间;Claude Code 当前没有月配额窗口 |
151
+
152
+ **第三行 —— 项目 / 会话**
153
+
154
+ | 图标 | 段 | 来源 | 展示 |
155
+ |---|---|---|---|
156
+ | 📁 | 目录 | `workspace.current_dir` | 当前目录名 |
157
+ | 🌿 / 🌲 | git + worktree | stdin + 本地 `git` | 分支 + 状态标记:`✓` 干净、`●` 有未提交变更、`⚠` 有冲突;另含 `↑领先` `↓落后`;`worktree.name` 追加在分支状态右侧 |
158
+ | 🏷️ | 会话名 | `session_name` | 由 `--name` 或 `/rename` 设置 |
159
+ | ⏱️ | 会话 | `cost` | 耗时 + `+新增` `-删除` 行数 |
160
+ | 💰 | cost | `cost.total_cost_usd` | 美元成本,大于 0 时显示 |
161
+ | 💩 | 版本 | `version` | Claude Code 版本;4 小时缓存发现新版时追加 `↑latest` |
162
+
163
+ 配额月相映射:
164
+
165
+ | 占用 | 图标 |
166
+ |---|---|
167
+ | 0% <= 占用 < 10% | 🌑 |
168
+ | 10% <= 占用 < 30% | 🌒 |
169
+ | 30% <= 占用 < 60% | 🌓 |
170
+ | 60% <= 占用 < 90% | 🌔 |
171
+ | 90% <= 占用 <= 100% | 🌕 |
172
+
173
+ ## 图标说明
174
+
175
+ | 图标 | 含义 |
176
+ |---|---|
177
+ | 🤖 | 模型名;以 `model.display_name` 为准,缺失时用可读 `model.id` 兜底 |
178
+ | 🧠 | 推理强度 |
179
+ | ✅ | 空闲;最近一轮 assistant 输出已完成 |
180
+ | ⏸️ | 暂停;正在执行的动作被用户中断或取消 |
181
+ | 💭 | 思考中;等待或正在接收模型输出 |
182
+ | ⚙️ | 处理中;工具结果已返回,Claude 正在继续处理 |
183
+ | 🔧 | 工具调用中;可用时会显示工具名 |
184
+ | 🚀 | fast mode |
185
+ | ⚡️ | 上下文窗口占用 |
186
+ | 💾 | prompt cache 使用情况 |
187
+ | 🎯 | output style |
188
+ | 📊 | Hour / Week 订阅配额 |
189
+ | 🌑 🌒 🌓 🌔 🌕 | 配额占用档位 |
190
+ | ⏳ | 距离当前配额窗口重置的时间 |
191
+ | 📁 | 当前目录 |
192
+ | 🌿 | git 分支 |
193
+ | ✓ ● ⚠ | git 干净 / 有未提交变更 / 有冲突 |
194
+ | 🌲 | worktree 名,显示在 git 段内 |
195
+ | 🏷️ | 会话名 |
196
+ | ⏱️ | 会话耗时 |
197
+ | 💰 | 会话成本 |
198
+ | 💩 | Claude Code 版本 |
199
+ | ↑latest | 检测到更新的 Claude Code 版本 |
200
+
201
+ ## 颜色语义
202
+
203
+ | 颜色 | 含义 |
204
+ |---|---|
205
+ | 亮绿 | 空闲/健康状态、fast、缓存、新增、git 干净标记、git 领先/outgoing/push 计数 |
206
+ | 黄色 | 需要注意:暂停状态、effort、配额重置时间、成本、警戒阈值 |
207
+ | 亮红 | 风险或负向:危险阈值、冲突、删除、版本更新提示 |
208
+ | 蓝色 | Git modified/dirty 状态、落后/incoming/pull 计数 |
209
+ | 青色 / 白色 | 中性运行与项目信息:模型、输出风格、会话耗时、git 分支 |
210
+ | 品红 | 当前上下文与会话身份:上下文窗口、会话名 |
211
+
212
+ status 图标来自 transcript 尾部推断,只代表 Claude Code 触发 statusline 刷新时的近似状态,不是实时事件流。
213
+ 如果正在执行时按 Esc 取消,ccglance 会在 Claude Code 下一次重绘 statusline 时更新;transcript 里的中断标记会显示为暂停。
214
+
215
+ ## 原理
216
+
217
+ 每次刷新时,Claude Code 会运行你配置的 `command`,并把一段 JSON(模型、effort、
218
+ 上下文窗口、cost、workspace、版本……)从 **stdin** 传入。`ccglance` 用
219
+ `fs.readFileSync(0)` 一次性读入、按固定行格式化并**先打印**;`status`
220
+ 只会读取 transcript 尾部固定字节。版本段同步阶段只读本地小缓存;stdout 写出之后,如果
221
+ Claude Code 最新版缓存超过 4 小时,才 detached 后台刷新 npm registry。若 JSON 解析失败则
222
+ 静默退出,绝不影响 CLI。来自 stdin、transcript、git 的文本在输出前会清理终端控制序列,
223
+ 避免逃逸到状态栏之外。主要外部调用是本地 `git`(单次有界 status 调用并带短缓存)、按需
224
+ transcript 尾部读取,以及渲染后的后台版本检查。
225
+
226
+ ## 开发
227
+
228
+ ### 源码构建
229
+
230
+ ```bash
231
+ git clone https://github.com/CxMYu/CcGlanceLine.git
232
+ cd CcGlanceLine
233
+ npm install # 安装 devDeps,并执行 prepare -> build
234
+
235
+ npm run build # 编译 src/ → dist/
236
+ npm run typecheck # tsc --noEmit(strict)
237
+ npm test # 构建 + node:test fixtures/snapshots/smoke
238
+ npm run benchmark # 构建 + 启动耗时基准
239
+ ccglance preview # 预览全局/软链命令
240
+
241
+ # 用样例 stdin 冒烟测试:
242
+ printf '%s' '{"model":{"display_name":"Claude Opus 4.8 (1M context)","id":"claude-opus-4-8[1m]"}}' | node dist/cli.js
243
+ ```
244
+
245
+ 本地试用建议构建后执行 `npm link`,然后在 Claude Code 里配置 `"command": "ccglance"`。不做全局链接时,直接配置 `node /绝对路径/ccglance/dist/cli.js`。
246
+
247
+ ### 验证
248
+
249
+ - `test/fixtures/` 放订阅、API 风格、字段缺失、高上下文占用等 stdin 样例。
250
+ - `test/snapshots/` 固定 ANSI 彩色渲染结果,图标、间距、颜色、换行变化都必须是有意修改。
251
+ - `test/*.test.js` 使用 Node 内置 `node:test`,不额外引入运行时测试框架。
252
+ - `bench/latency.js` 会同时测空 Node 基线、无 git、订阅+transcript、git warm cache、
253
+ git cold fallback。Windows 上空 Node 冷启动通常占大头,判断 ccglance 成本时应看相对基线的增量。
254
+
255
+ ### Agent 构建范式
256
+
257
+ - `src/` 是唯一源码;不要手改 `dist/`,用 `npm run build` 重新生成。
258
+ - 保持固定内置风格:不要加用户配置读取、外部样式文件、运行时样式发现。
259
+ - 保持运行时零依赖;新增依赖只能是构建期依赖,并说明必要性。
260
+ - 改代码后执行 `npm run typecheck`、`npm run build`、`ccglance preview`。
261
+ - 修改图标或间距时,检查去掉 ANSI 后的 preview,并用至少一个合成 stdin 覆盖被改的 segment。
262
+
263
+ ### 代码结构
264
+
265
+ ```text
266
+ src/
267
+ cli.ts # 命令入口:preview / statusLine stdin
268
+ defaults/ # 固定内置风格与显示顺序
269
+ readers/ # stdin、transcript 尾读、终端宽度
270
+ render/ # 颜色、图标、布局、最终渲染
271
+ segments/ # 每个显示项的渲染逻辑
272
+ runtime/ # git、Claude Code 版本缓存等运行时能力
273
+ types/ # Claude Code stdin 与渲染类型
274
+ utils/ # 格式化、显示宽度计算
275
+ test/
276
+ fixtures/ # 代表性的 Claude Code stdin 和 transcript 数据
277
+ snapshots/ # 固定渲染输出基准
278
+ bench/
279
+ latency.js # 启动耗时与缓存路径基准
280
+ ```
281
+
282
+ 发布到 npm 的只有编译后的 `dist/`;`npm run build` 会先清空 `dist` 再编译,避免旧平铺产物混入包里。
283
+
284
+ ## 缓存文件
285
+
286
+ `ccglance` 只落盘可丢弃的运行缓存:git 状态、transcript 派生状态、Claude Code 最新版本缓存。
287
+ 文件按 `git/`、`transcript/`、`version/` 分组。
288
+
289
+ 所有平台都统一落在 Claude Code 自己的配置目录下,随 Claude 配置一起走、清理也方便:
290
+
291
+ ```text
292
+ ~/.claude/ccglance/
293
+ ├── git/ # git 状态快照(每个仓库一个)
294
+ ├── transcript/ # transcript 派生的会话状态
295
+ └── version/ # Claude Code 最新版本检查
296
+ ```
297
+
298
+ 若设置了 `CLAUDE_CONFIG_DIR` 改变 Claude Code 配置目录,ccglance 的缓存会跟着落到该目录下。
299
+ 整个 `ccglance/` 目录随时可安全删除 —— 下次渲染会自动重建。
300
+
301
+ git 缓存逻辑:
302
+
303
+ - 缓存 key 使用 Git worktree 根目录,同一仓库里的多个 Claude Code 终端共享一份 git 缓存。
304
+ - 分支名优先使用 Claude Code stdin 里的 `worktree.branch`;没有该字段时,每次渲染都会从
305
+ `.git/HEAD` 快速读取,所以普通切换分支也会立即显示。
306
+ - dirty/冲突和 ahead/behind 细节使用缓存;20 分钟内且仍属于当前分支的缓存会直接返回。
307
+ - 本地状态(`✓` / `●` / `⚠`)和上游状态(`↑领先` / `↓落后`)来自同一次
308
+ `git status --porcelain=v2 --branch` 缓存快照,所以 TTL 相同。如果本地和远程状态同时存在,
309
+ 会一起显示,例如 `main ● ↑1 ↓1`。
310
+ - 缓存过期、无缓存或分支变化时仍立即渲染:用 `.git/HEAD` 快速只显示分支,再后台刷新 `git status`。
311
+ - 刷新使用独占 `.refresh` 标记,写入使用临时文件 rename,多个终端并发不会写坏缓存。
312
+ - 没有心跳,也没有常驻 watcher。刷新是懒触发:Claude Code 重绘 statusline 时启动 ccglance,
313
+ ccglance 检查缓存年龄,只有过期时才启动 detached 后台刷新进程。
314
+
315
+ ## 相关项目
316
+
317
+ - [CCometixLine](https://github.com/Haleclipse/CCometixLine) —— Rust 编写的高性能状态栏,带交互式 TUI 配置与主题
318
+ - [ccstatusline](https://github.com/sirmalloc/ccstatusline) —— 可配置、支持 powerline 风格的状态栏
319
+ - [claude-powerline](https://github.com/Owloops/claude-powerline) —— 轻量的 powerline 风格状态栏
320
+
321
+ ## 贡献
322
+
323
+ 欢迎提 issue 和 PR。改代码前请先跑 `npm run typecheck`、`npm run build`、`ccglance preview`;
324
+ 请保持**运行时零依赖**和固定风格(不加配置加载器)。
325
+
326
+ ## Star History
327
+
328
+ [![Star History Chart](https://api.star-history.com/svg?repos=CxMYu/CcGlanceLine&type=Date)](https://star-history.com/#CxMYu/CcGlanceLine&Date)
329
+
330
+ ## 许可
331
+
332
+ [MIT](./LICENSE) © 2026 CxMYu
package/dist/cli.js ADDED
@@ -0,0 +1,91 @@
1
+ #!/usr/bin/env node
2
+ "use strict";
3
+ Object.defineProperty(exports, "__esModule", { value: true });
4
+ const readers_1 = require("./readers");
5
+ // preview 子命令用的内置样例(覆盖默认状态栏会展示的常规字段)
6
+ const PREVIEW_SAMPLE = {
7
+ model: { display_name: 'Opus 4.8', id: 'claude-opus-4-8[1m]' },
8
+ effort: { level: 'high' },
9
+ fast_mode: true,
10
+ context_window: {
11
+ context_window_size: 1000000, total_input_tokens: 235000, total_output_tokens: 1200,
12
+ used_percentage: 23.5, remaining_percentage: 76.5,
13
+ current_usage: { output_tokens: 1200, cache_read_input_tokens: 172000, cache_creation_input_tokens: 15000 },
14
+ },
15
+ output_style: { name: 'default' },
16
+ rate_limits: {
17
+ five_hour: { used_percentage: 23.5, resets_at: Math.floor(Date.now() / 1000) + 2 * 3600 },
18
+ seven_day: { used_percentage: 41.2, resets_at: Math.floor(Date.now() / 1000) + 3 * 86400 },
19
+ },
20
+ workspace: { current_dir: process.cwd() },
21
+ worktree: { name: 'main', branch: 'main' },
22
+ session_name: 'ccglance',
23
+ cost: { total_cost_usd: 0.1234, total_duration_ms: 192000, total_lines_added: 156, total_lines_removed: 23 },
24
+ version: '2.0.1',
25
+ };
26
+ const argv = process.argv.slice(2);
27
+ // 用法 + 「安装后要做什么」指引。终端直接运行或 --help 时打印;此路径绝不读 stdin。
28
+ function printHelp() {
29
+ const version = require('../package.json').version || '';
30
+ process.stdout.write(`ccglance ${version} — 面向 Claude Code 的多行状态栏 / a multi-line status line for Claude Code
31
+
32
+ 用法 Usage:
33
+ ccglance 作为 Claude Code statusLine 命令:从 stdin 读 JSON、渲染、输出后退出
34
+ (statusLine mode: reads JSON on stdin, renders, prints, exits)
35
+ ccglance preview 用内置样例渲染一次,无需 stdin (render a built-in sample)
36
+ ccglance --help, -h 显示本帮助 (show this help)
37
+ ccglance --version, -v 显示版本号 (print version)
38
+
39
+ 安装后配置 Setup — 装完必须做这一步 (required after \`npm install -g ccglance\`):
40
+ 把下面这段加进 ~/.claude/settings.json,然后重启 Claude Code。
41
+ Add this to ~/.claude/settings.json, then restart Claude Code:
42
+
43
+ {
44
+ "statusLine": {
45
+ "type": "command",
46
+ "command": "ccglance"
47
+ }
48
+ }
49
+
50
+ 未全局安装?让 Node 直接指向编译产物 (not installed globally? point Node at the built file):
51
+ "command": "node /absolute/path/to/dist/cli.js"
52
+
53
+ 文档 Docs: https://github.com/CxMYu/CcGlanceLine
54
+ `);
55
+ }
56
+ if (argv[0] === '--help' || argv[0] === '-h' || argv[0] === 'help') {
57
+ printHelp();
58
+ process.exit(0);
59
+ }
60
+ if (argv[0] === '--version' || argv[0] === '-v') {
61
+ process.stdout.write((require('../package.json').version || '') + '\n');
62
+ process.exit(0);
63
+ }
64
+ // 子命令:preview —— 用内置样例按固定样式渲染
65
+ if (argv[0] === 'preview') {
66
+ const { render, hasEnabledSegment } = require('./render');
67
+ const { DEFAULT_SPEC } = require('./defaults');
68
+ process.stdout.write(render(PREVIEW_SAMPLE, DEFAULT_SPEC, { previewStatus: { state: 'idle' } }));
69
+ if (hasEnabledSegment(DEFAULT_SPEC, 'version')) {
70
+ const { scheduleRefresh } = require('./runtime/version');
71
+ scheduleRefresh();
72
+ }
73
+ process.exit(0);
74
+ }
75
+ // 在真实终端直接运行(stdin 是 TTY、没有管道喂 JSON)时,显示帮助而非阻塞等待 stdin。
76
+ if (process.stdin.isTTY) {
77
+ printHelp();
78
+ process.exit(0);
79
+ }
80
+ // statusLine 模式:读 stdin(解析失败静默退出)
81
+ const data = (0, readers_1.readStdinData)();
82
+ if (!data)
83
+ process.exit(0);
84
+ // 先输出 —— 用户立即看到状态栏。
85
+ const { render, hasEnabledSegment } = require('./render');
86
+ const { DEFAULT_SPEC } = require('./defaults');
87
+ process.stdout.write(render(data, DEFAULT_SPEC));
88
+ if (data.version && hasEnabledSegment(DEFAULT_SPEC, 'version')) {
89
+ const { scheduleRefresh } = require('./runtime/version');
90
+ scheduleRefresh();
91
+ }
@@ -0,0 +1,42 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.DEFAULT_SPEC = void 0;
4
+ exports.DEFAULT_SPEC = {
5
+ layout: {
6
+ mode: 'responsive',
7
+ separator: ' | ',
8
+ rows: [
9
+ ['model', 'effort', 'status', 'fast', 'context', 'cache', 'style'], // 运行时
10
+ ['rate_limits'], // 订阅(无订阅→整行消失)
11
+ ['dir', 'git', 'session_name', 'session', 'cost', 'version'], // 项目/会话
12
+ ],
13
+ minWidth: 80,
14
+ },
15
+ segments: {
16
+ status: {
17
+ enabled: true,
18
+ showIdle: true,
19
+ statusIcons: { idle: '✅', paused: '⏸️', thinking: '💭', working: '⚙️', tool: '🔧' },
20
+ },
21
+ model: { enabled: true },
22
+ effort: { enabled: true },
23
+ fast: { enabled: true },
24
+ context: { enabled: true, percentOnly: false, warnPct: 75, dangerPct: 90 },
25
+ cache: { enabled: true },
26
+ rate_limits: {
27
+ enabled: true,
28
+ show: 'both',
29
+ warnPct: 70,
30
+ dangerPct: 90,
31
+ showReset: true,
32
+ labels: { five_hour: 'Hour', seven_day: 'Week' },
33
+ },
34
+ style: { enabled: true },
35
+ dir: { enabled: true, fullPath: false },
36
+ git: { enabled: true, ttlMs: 20 * 60 * 1000 },
37
+ session_name: { enabled: true },
38
+ session: { enabled: true },
39
+ cost: { enabled: true },
40
+ version: { enabled: true },
41
+ },
42
+ };
@@ -0,0 +1,13 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.detectWidth = exports.readTailLines = exports.getLatestTranscriptUsage = exports.readStdinData = void 0;
4
+ // 统一读取层:stdin / transcript / 终端宽度 三类读取的统一入口。
5
+ // 设计原则:关键路径(渲染前)只做同步、有界、零网络的读取;
6
+ // transcript 只做有上限的尾部流式读并落盘缓存。
7
+ var stdin_1 = require("./stdin");
8
+ Object.defineProperty(exports, "readStdinData", { enumerable: true, get: function () { return stdin_1.readStdinData; } });
9
+ var transcript_1 = require("./transcript");
10
+ Object.defineProperty(exports, "getLatestTranscriptUsage", { enumerable: true, get: function () { return transcript_1.getLatestTranscriptUsage; } });
11
+ Object.defineProperty(exports, "readTailLines", { enumerable: true, get: function () { return transcript_1.readTailLines; } });
12
+ var termwidth_1 = require("./termwidth");
13
+ Object.defineProperty(exports, "detectWidth", { enumerable: true, get: function () { return termwidth_1.detectWidth; } });
@@ -0,0 +1,17 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.readStdinData = readStdinData;
7
+ // stdin 读取 —— Claude Code 每次重绘把状态栏 JSON 从 stdin 管道传入。
8
+ // 一次性同步读取;解析失败返回 null(调用方据此静默退出,绝不影响 CLI)。
9
+ const fs_1 = __importDefault(require("fs"));
10
+ function readStdinData() {
11
+ try {
12
+ return JSON.parse(fs_1.default.readFileSync(0, 'utf8'));
13
+ }
14
+ catch {
15
+ return null;
16
+ }
17
+ }
@@ -0,0 +1,55 @@
1
+ "use strict";
2
+ // 终端宽度探测 —— 动态自适应布局的宽度来源,按优先级多级回退。
3
+ //
4
+ // 难点:Claude Code ≥2.1.139 常以「管道 stdio、无控制 TTY」方式 spawn statusline,
5
+ // 导致 process.stdout.columns 为 undefined。因此优先用 Claude Code 注入的 COLUMNS 环境
6
+ // 变量(2.1.153+,零成本),仅在都拿不到时才 fork 子进程兜底(Windows 跳过)。
7
+ Object.defineProperty(exports, "__esModule", { value: true });
8
+ exports.detectWidth = detectWidth;
9
+ function parsePos(v) {
10
+ if (!v)
11
+ return null;
12
+ const n = parseInt(v, 10);
13
+ return Number.isFinite(n) && n > 0 ? n : null;
14
+ }
15
+ // Unix 兜底:tput / stty(仅在无 COLUMNS 且无 TTY 时才走到,带超时避免挂起)
16
+ function unixWidth() {
17
+ const tries = ['tput cols', 'stty size'];
18
+ const { execSync } = require('child_process');
19
+ for (const cmd of tries) {
20
+ try {
21
+ const out = execSync(`${cmd} 2>/dev/null`, {
22
+ encoding: 'utf8', stdio: ['pipe', 'pipe', 'ignore'], timeout: 400, windowsHide: true,
23
+ }).trim();
24
+ // stty size 输出 "行 列",tput cols 输出 "列"
25
+ const n = cmd.startsWith('stty') ? parsePos(out.split(/\s+/)[1]) : parsePos(out);
26
+ if (n)
27
+ return n;
28
+ }
29
+ catch { /* try next */ }
30
+ }
31
+ return null;
32
+ }
33
+ // 探测终端宽度。前 3 步零成本;第 4 步(fork)仅在前面全失败时执行。
34
+ function detectWidth(fallback) {
35
+ // 1. 显式覆盖(调试 / 特殊 spawn 场景)
36
+ const override = parsePos(process.env.CCGLANCE_WIDTH);
37
+ if (override)
38
+ return override;
39
+ // 2. Claude Code 注入的 COLUMNS(首选,零成本)
40
+ const cols = parsePos(process.env.COLUMNS);
41
+ if (cols)
42
+ return cols;
43
+ // 3. 有 TTY 时的 stdout 列数
44
+ const out = process.stdout;
45
+ if (out && typeof out.columns === 'number' && out.columns > 0)
46
+ return out.columns;
47
+ // 4. Unix 子进程兜底(Windows 跳过,避免无谓 fork)
48
+ if (process.platform !== 'win32') {
49
+ const w = unixWidth();
50
+ if (w)
51
+ return w;
52
+ }
53
+ // 5. 默认兜底宽度
54
+ return fallback;
55
+ }