@cxmyu/ccglance 1.1.2 → 1.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.
package/README.md CHANGED
@@ -95,6 +95,11 @@ Add a `statusLine` block to `~/.claude/settings.json`:
95
95
  }
96
96
  ```
97
97
 
98
+ On Claude Code >= 2.1.97, you can optionally add `"refreshInterval": 30`
99
+ inside `statusLine` to keep elapsed time, quota resets, version hints, and other
100
+ time-based fields moving while the main session is idle. Keep the base block
101
+ above when compatibility with older Claude Code versions matters.
102
+
98
103
  If you didn't install globally, point Node at the compiled file directly:
99
104
 
100
105
  ```json
package/README.zh-CN.md CHANGED
@@ -89,6 +89,10 @@ node dist/cli.js preview
89
89
  }
90
90
  ```
91
91
 
92
+ Claude Code >= 2.1.97 可在 `statusLine` 内可选增加 `"refreshInterval": 30`,
93
+ 让会话时长、配额重置、版本提示等时间相关字段在主会话空闲时也能更新。
94
+ 若需兼容更旧的 Claude Code,保持上面的基础配置即可。
95
+
92
96
  若未全局安装,直接用 Node 指向编译后的文件:
93
97
 
94
98
  ```json
package/dist/cli.js CHANGED
@@ -4,8 +4,9 @@ Object.defineProperty(exports, "__esModule", { value: true });
4
4
  const readers_1 = require("./readers");
5
5
  // preview 子命令用的内置样例(覆盖默认状态栏会展示的常规字段)
6
6
  const PREVIEW_SAMPLE = {
7
- model: { display_name: 'Opus 4.8', id: 'claude-opus-4-8[1m]' },
7
+ model: { display_name: 'Opus 5', id: 'claude-opus-5[1m]' },
8
8
  effort: { level: 'high' },
9
+ thinking: { enabled: true },
9
10
  fast_mode: true,
10
11
  context_window: {
11
12
  context_window_size: 1000000, total_input_tokens: 235000, total_output_tokens: 1200,
@@ -21,7 +22,7 @@ const PREVIEW_SAMPLE = {
21
22
  worktree: { name: 'main', branch: 'main' },
22
23
  session_name: 'ccglance',
23
24
  cost: { total_cost_usd: 0.1234, total_duration_ms: 192000, total_lines_added: 156, total_lines_removed: 23 },
24
- version: '2.0.1',
25
+ version: '2.1.221',
25
26
  };
26
27
  const argv = process.argv.slice(2);
27
28
  // 用法 + 「安装后要做什么」指引。终端直接运行或 --help 时打印;此路径绝不读 stdin。
@@ -6,9 +6,9 @@ exports.DEFAULT_SPEC = {
6
6
  mode: 'responsive',
7
7
  separator: ' | ',
8
8
  rows: [
9
- ['model', 'effort', 'status', 'fast', 'context', 'cache', 'style'], // 运行时
9
+ ['model', 'agent', 'effort', 'status', 'fast', 'context', 'cache', 'style'], // 运行时
10
10
  ['rate_limits'], // 订阅(无订阅→整行消失)
11
- ['dir', 'git', 'session_name', 'session', 'cost', 'version'], // 项目/会话
11
+ ['dir', 'git', 'pr', 'session_name', 'session', 'cost', 'version'], // 项目/会话
12
12
  ],
13
13
  minWidth: 80,
14
14
  },
@@ -19,6 +19,7 @@ exports.DEFAULT_SPEC = {
19
19
  statusIcons: { idle: '✅', paused: '⏸️', thinking: '💭', working: '⚙️', tool: '🔧' },
20
20
  },
21
21
  model: { enabled: true },
22
+ agent: { enabled: true },
22
23
  effort: { enabled: true },
23
24
  fast: { enabled: true },
24
25
  context: { enabled: true, percentOnly: false, warnPct: 75, dangerPct: 90 },
@@ -34,6 +35,7 @@ exports.DEFAULT_SPEC = {
34
35
  style: { enabled: true },
35
36
  dir: { enabled: true, fullPath: false },
36
37
  git: { enabled: true, ttlMs: 20 * 60 * 1000 },
38
+ pr: { enabled: true },
37
39
  session_name: { enabled: true },
38
40
  session: { enabled: true },
39
41
  cost: { enabled: true },
@@ -15,7 +15,7 @@ const paint = (code, s, bold = false) => `\x1b[${bold ? '1;' : ''}${code}m${(0,
15
15
  exports.paint = paint;
16
16
  exports.C = {
17
17
  // 第一行(运行时)
18
- model: CYAN, effort: YELLOW, fast: GREEN,
18
+ model: CYAN, agent: MAGENTA, effort: YELLOW, fast: GREEN,
19
19
  ctx: MAGENTA, cache: GREEN, style: CYAN,
20
20
  rate: CYAN, // rate_limits 主图标/标签
21
21
  rateReset: YELLOW, // 配额重置时间
@@ -31,6 +31,7 @@ exports.C = {
31
31
  name: MAGENTA, dirIcon: YELLOW, dirText: GREEN, git: WHITE,
32
32
  gitClean: GREEN, gitDirty: BLUE, gitConflict: RED,
33
33
  gitAhead: GREEN, gitBehind: BLUE,
34
+ pr: CYAN, prApproved: GREEN, prPending: YELLOW, prChanges: RED, prDraft: WHITE,
34
35
  sess: CYAN, add: GREEN, del: RED,
35
36
  cost: YELLOW, // 美元成本
36
37
  wt: GREEN, // worktree
@@ -3,8 +3,10 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.icon = icon;
4
4
  const ICONS = {
5
5
  model: '🤖',
6
+ agent: '👤',
6
7
  dir: '📁',
7
8
  git: '🌿',
9
+ pr: '🔀',
8
10
  context: '⚡️',
9
11
  cache: '💾',
10
12
  rate_limits: '📊',
@@ -101,30 +101,48 @@ function runVersionTask(cacheFile, done) {
101
101
  catch { /* ignore */ }
102
102
  done();
103
103
  };
104
- try {
105
- const https = require('https');
106
- const req = https.get('https://registry.npmjs.org/@anthropic-ai/claude-code/latest', (r) => {
107
- if (r.statusCode !== 200) {
108
- r.resume();
109
- return finish('');
110
- }
111
- let d = '';
112
- r.on('data', (c) => { d += c; });
113
- r.on('end', () => {
114
- try {
115
- finish(JSON.parse(d).version || '');
116
- }
117
- catch {
118
- finish('');
104
+ const requestVersion = (url, parse, callback) => {
105
+ let settled = false;
106
+ const settle = (version) => {
107
+ if (settled)
108
+ return;
109
+ settled = true;
110
+ callback(version);
111
+ };
112
+ try {
113
+ const https = require('https');
114
+ const req = https.get(url, (r) => {
115
+ if (r.statusCode !== 200) {
116
+ r.resume();
117
+ return settle('');
119
118
  }
119
+ let d = '';
120
+ r.on('data', (c) => { d += c; });
121
+ r.on('end', () => {
122
+ try {
123
+ settle(parse(d));
124
+ }
125
+ catch {
126
+ settle('');
127
+ }
128
+ });
120
129
  });
121
- });
122
- req.on('error', () => finish(''));
123
- req.setTimeout(5000, () => { req.destroy(); finish(''); });
124
- }
125
- catch {
126
- finish('');
127
- }
130
+ req.on('error', () => settle(''));
131
+ req.setTimeout(5000, () => { req.destroy(); settle(''); });
132
+ }
133
+ catch {
134
+ settle('');
135
+ }
136
+ };
137
+ // Claude Code 新版优先跟随官方 rolling-latest 端点;旧版/npm 发布链仍作回退。
138
+ requestVersion('https://downloads.claude.ai/claude-code-releases/latest', (body) => {
139
+ const version = body.trim();
140
+ return /^\d+\.\d+\.\d+$/.test(version) ? version : '';
141
+ }, (official) => {
142
+ if (official)
143
+ return finish(official);
144
+ requestVersion('https://registry.npmjs.org/@anthropic-ai/claude-code/latest', (body) => JSON.parse(body).version || '', finish);
145
+ });
128
146
  }
129
147
  // 每次运行都做的轻清理:删除过期的孤儿瞬时产物(.refresh / .tmp),以及历史遗留的
130
148
  // tasks/ 目录内容。成本很低(这些目录文件很少),能让残留不再累积。
@@ -52,7 +52,18 @@ const status = (ctx) => {
52
52
  };
53
53
  const model = (ctx) => ctx.data.model && (ctx.data.model.display_name || ctx.data.model.id)
54
54
  ? iconSeg(ctx, 'model', colors_1.C.model, 'model', (0, format_1.modelName)(ctx.data.model)) : null;
55
- const effort = ({ data }) => data.effort && data.effort.level ? (0, colors_1.seg)(colors_1.C.effort, '🧠', data.effort.level) : null;
55
+ const agent = (ctx) => ctx.data.agent?.name ? iconSeg(ctx, 'agent', colors_1.C.agent, 'agent', ctx.data.agent.name) : null;
56
+ // 旧版只有 effort.level;新版额外提供 thinking.enabled。字段缺失时保持旧输出。
57
+ const effort = ({ data }) => {
58
+ const level = data.effort?.level;
59
+ const thinking = data.thinking?.enabled;
60
+ if (!level && thinking == null)
61
+ return null;
62
+ const text = level
63
+ ? `${level}${thinking === false ? ' ⊘' : ''}`
64
+ : thinking ? '✓' : '⊘';
65
+ return (0, colors_1.seg)(colors_1.C.effort, '🧠', text);
66
+ };
56
67
  const fast = (ctx) => ctx.data.fast_mode ? iconSeg(ctx, 'fast', colors_1.C.fast, 'fast', 'fast') : null;
57
68
  const context = (ctx) => {
58
69
  const cw = ctx.data.context_window;
@@ -162,7 +173,23 @@ const git = (ctx) => {
162
173
  if (!cwd)
163
174
  return null;
164
175
  const { gitSegment } = require('../runtime/git');
165
- return gitSegment(cwd, optIcon(ctx, 'git', 'git'), opt(ctx, 'git'), ctx.data.worktree?.branch, ctx.data.worktree?.name);
176
+ const worktreeName = ctx.data.worktree?.name || ctx.data.workspace?.git_worktree;
177
+ return gitSegment(cwd, optIcon(ctx, 'git', 'git'), opt(ctx, 'git'), ctx.data.worktree?.branch, worktreeName);
178
+ };
179
+ const pr = (ctx) => {
180
+ const number = ctx.data.pr?.number;
181
+ if (typeof number !== 'number' || !Number.isFinite(number) || number <= 0)
182
+ return null;
183
+ const state = ctx.data.pr?.review_state;
184
+ const states = {
185
+ approved: { glyph: '✓', color: colors_1.C.prApproved },
186
+ pending: { glyph: '○', color: colors_1.C.prPending },
187
+ changes_requested: { glyph: '!', color: colors_1.C.prChanges },
188
+ draft: { glyph: '◌', color: colors_1.C.prDraft },
189
+ };
190
+ const review = state ? states[state] : undefined;
191
+ const text = `#${number}${review ? ` ${review.glyph}` : ''}`;
192
+ return iconSeg(ctx, 'pr', review?.color ?? colors_1.C.pr, 'pr', text);
166
193
  };
167
194
  const sessionName = ({ data }) => data.session_name ? (0, colors_1.seg)(colors_1.C.name, '🏷️', data.session_name) : null;
168
195
  const session = (ctx) => {
@@ -195,9 +222,9 @@ const version = (ctx) => {
195
222
  };
196
223
  exports.SEGMENTS = {
197
224
  // 运行时
198
- status, model, effort, fast, context, cache, style,
225
+ status, model, agent, effort, fast, context, cache, style,
199
226
  // 订阅
200
227
  rate_limits: rateLimits,
201
228
  // 项目 / 会话
202
- dir, git, session_name: sessionName, session, cost, version,
229
+ dir, git, pr, session_name: sessionName, session, cost, version,
203
230
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cxmyu/ccglance",
3
- "version": "1.1.2",
3
+ "version": "1.2.1",
4
4
  "description": "A fast, zero-dependency, multi-line status line for Claude Code — model, effort, context, cache, git and session, all at a glance.",
5
5
  "bin": {
6
6
  "ccglance": "dist/cli.js"