claude-blip 1.0.1 → 1.0.3
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 +2 -29
- package/package.json +1 -1
- package/statusline.js +6 -50
package/README.md
CHANGED
|
@@ -15,7 +15,7 @@
|
|
|
15
15
|
|
|
16
16
|
</div>
|
|
17
17
|
|
|
18
|
-
|
|
18
|
+
Four segments. No config files. No themes. No plugins.
|
|
19
19
|
It just shows you what matters and gets out of the way.
|
|
20
20
|
|
|
21
21
|
## Install
|
|
@@ -30,42 +30,15 @@ That's it. Restart Claude Code. Done.
|
|
|
30
30
|
|
|
31
31
|
| Segment | What it shows | Style |
|
|
32
32
|
|---------|--------------|-------|
|
|
33
|
-
| **Task** | What Claude is working on right now | **bold** |
|
|
34
33
|
| **Project** | Directory name | dim |
|
|
35
34
|
| **Branch** | Current git branch | dim |
|
|
36
35
|
| **Model** | opus, sonnet, haiku | dim |
|
|
37
36
|
| **Context** | Usage bar + token count | green → yellow → red |
|
|
38
37
|
|
|
39
|
-
Everything is dim except the
|
|
38
|
+
Everything is dim except the context bar — your eyes go to the thing that matters.
|
|
40
39
|
|
|
41
40
|
Terminal too narrow? Segments drop off the left. Context bar always stays.
|
|
42
41
|
|
|
43
|
-
## Examples
|
|
44
|
-
|
|
45
|
-
Normal — plenty of room:
|
|
46
|
-
|
|
47
|
-
```
|
|
48
|
-
Fixing auth bug · myapp · main · opus · ━━──────── 40K
|
|
49
|
-
```
|
|
50
|
-
|
|
51
|
-
Getting warm — yellow at 70%:
|
|
52
|
-
|
|
53
|
-
```
|
|
54
|
-
myapp · main · opus · ━━━━━━━─── 140K
|
|
55
|
-
```
|
|
56
|
-
|
|
57
|
-
Running hot — red at 90%, time to wrap up:
|
|
58
|
-
|
|
59
|
-
```
|
|
60
|
-
myapp · main · opus · ━━━━━━━━━─ 180K
|
|
61
|
-
```
|
|
62
|
-
|
|
63
|
-
No task, no git — it adapts:
|
|
64
|
-
|
|
65
|
-
```
|
|
66
|
-
scripts · sonnet · ━━━━────── 80K
|
|
67
|
-
```
|
|
68
|
-
|
|
69
42
|
## Scopes
|
|
70
43
|
|
|
71
44
|
```sh
|
package/package.json
CHANGED
package/statusline.js
CHANGED
|
@@ -1,11 +1,9 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
// claude-blip — a single-file statusline for Claude Code
|
|
3
|
-
// Shows:
|
|
3
|
+
// Shows: project │ branch │ model │ context usage
|
|
4
4
|
|
|
5
5
|
const { execSync } = require("child_process");
|
|
6
|
-
const fs = require("fs");
|
|
7
6
|
const path = require("path");
|
|
8
|
-
const os = require("os");
|
|
9
7
|
|
|
10
8
|
// ─────────────────────────────────────────────────────────────
|
|
11
9
|
// Config
|
|
@@ -23,7 +21,6 @@ const CONFIG = {
|
|
|
23
21
|
// ─────────────────────────────────────────────────────────────
|
|
24
22
|
const ANSI = {
|
|
25
23
|
dim: "\x1b[2m",
|
|
26
|
-
bold: "\x1b[1m",
|
|
27
24
|
reset: "\x1b[0m",
|
|
28
25
|
green: "\x1b[38;5;108m",
|
|
29
26
|
yellow: "\x1b[38;5;222m",
|
|
@@ -31,7 +28,6 @@ const ANSI = {
|
|
|
31
28
|
};
|
|
32
29
|
|
|
33
30
|
const dim = (s) => `${ANSI.dim}${s}${ANSI.reset}`;
|
|
34
|
-
const bold = (s) => `${ANSI.bold}${s}${ANSI.reset}`;
|
|
35
31
|
const color = (s, c) => `${c}${s}${ANSI.reset}`;
|
|
36
32
|
const stripAnsi = (s) => s.replace(/\x1b\[[0-9;]*m/g, "");
|
|
37
33
|
|
|
@@ -51,39 +47,6 @@ function formatTokens(n) {
|
|
|
51
47
|
// Data Fetchers
|
|
52
48
|
// ─────────────────────────────────────────────────────────────
|
|
53
49
|
|
|
54
|
-
function getCurrentTask(sessionId) {
|
|
55
|
-
if (!sessionId) return null;
|
|
56
|
-
|
|
57
|
-
const todosDir = path.join(os.homedir(), ".claude", "todos");
|
|
58
|
-
if (!fs.existsSync(todosDir)) return null;
|
|
59
|
-
|
|
60
|
-
try {
|
|
61
|
-
const files = fs
|
|
62
|
-
.readdirSync(todosDir)
|
|
63
|
-
.filter(
|
|
64
|
-
(f) =>
|
|
65
|
-
f.startsWith(sessionId) &&
|
|
66
|
-
f.includes("-agent-") &&
|
|
67
|
-
f.endsWith(".json"),
|
|
68
|
-
)
|
|
69
|
-
.map((f) => ({
|
|
70
|
-
name: f,
|
|
71
|
-
mtime: fs.statSync(path.join(todosDir, f)).mtime,
|
|
72
|
-
}))
|
|
73
|
-
.sort((a, b) => b.mtime - a.mtime);
|
|
74
|
-
|
|
75
|
-
if (files.length === 0) return null;
|
|
76
|
-
|
|
77
|
-
const todos = JSON.parse(
|
|
78
|
-
fs.readFileSync(path.join(todosDir, files[0].name), "utf8"),
|
|
79
|
-
);
|
|
80
|
-
const inProgress = todos.find((t) => t.status === "in_progress");
|
|
81
|
-
return inProgress?.activeForm || null;
|
|
82
|
-
} catch {
|
|
83
|
-
return null;
|
|
84
|
-
}
|
|
85
|
-
}
|
|
86
|
-
|
|
87
50
|
function getContextDisplay(ctxWindow) {
|
|
88
51
|
const rawUsed = ctxWindow?.used_percentage;
|
|
89
52
|
const maxTokens = ctxWindow?.context_window_size || 200_000;
|
|
@@ -121,21 +84,14 @@ function buildStatusline(input) {
|
|
|
121
84
|
}
|
|
122
85
|
|
|
123
86
|
const dir = data.workspace?.current_dir || process.cwd();
|
|
124
|
-
const sessionId = data.session_id || "";
|
|
125
87
|
|
|
126
88
|
const parts = [];
|
|
127
89
|
|
|
128
|
-
// 1.
|
|
129
|
-
const task = getCurrentTask(sessionId);
|
|
130
|
-
if (task) {
|
|
131
|
-
parts.push(bold(task));
|
|
132
|
-
}
|
|
133
|
-
|
|
134
|
-
// 2. Project name
|
|
90
|
+
// 1. Project name
|
|
135
91
|
const project = path.basename(dir);
|
|
136
92
|
parts.push(dim(project));
|
|
137
93
|
|
|
138
|
-
//
|
|
94
|
+
// 2. Git branch
|
|
139
95
|
try {
|
|
140
96
|
const branch = execSync("git branch --show-current", {
|
|
141
97
|
cwd: dir,
|
|
@@ -147,7 +103,7 @@ function buildStatusline(input) {
|
|
|
147
103
|
// Not a git repo or git not available
|
|
148
104
|
}
|
|
149
105
|
|
|
150
|
-
//
|
|
106
|
+
// 3. Model
|
|
151
107
|
const model = data.model?.display_name;
|
|
152
108
|
if (model) {
|
|
153
109
|
// Extract tier name: "Opus 4.6" → "opus", "Sonnet 4.5" → "sonnet"
|
|
@@ -155,13 +111,13 @@ function buildStatusline(input) {
|
|
|
155
111
|
parts.push(dim(tier));
|
|
156
112
|
}
|
|
157
113
|
|
|
158
|
-
//
|
|
114
|
+
// 4. Context window (bar + token count)
|
|
159
115
|
const ctx = getContextDisplay(data.context_window);
|
|
160
116
|
if (ctx) {
|
|
161
117
|
parts.push(ctx);
|
|
162
118
|
}
|
|
163
119
|
|
|
164
|
-
// Truncate if wider than terminal — drops segments from the left
|
|
120
|
+
// Truncate if wider than terminal — drops segments from the left
|
|
165
121
|
const sep = dim(" \u00B7 ");
|
|
166
122
|
const cols = process.stdout.columns || 80;
|
|
167
123
|
while (parts.length > 1 && stripAnsi(parts.join(sep)).length > cols) {
|