slash-do 1.2.0 → 1.3.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.
- package/hooks/slashdo-statusline.js +20 -13
- package/install.sh +11 -4
- package/package.json +1 -1
- package/src/installer.js +26 -12
- package/uninstall.sh +7 -1
|
@@ -8,9 +8,13 @@ const os = require('os');
|
|
|
8
8
|
|
|
9
9
|
// Read JSON from stdin
|
|
10
10
|
let input = '';
|
|
11
|
+
// Timeout guard: if stdin doesn't close within 3s (e.g. pipe issues on
|
|
12
|
+
// Windows/Git Bash), exit silently instead of hanging.
|
|
13
|
+
const stdinTimeout = setTimeout(() => process.exit(0), 3000);
|
|
11
14
|
process.stdin.setEncoding('utf8');
|
|
12
15
|
process.stdin.on('data', chunk => input += chunk);
|
|
13
16
|
process.stdin.on('end', () => {
|
|
17
|
+
clearTimeout(stdinTimeout);
|
|
14
18
|
try {
|
|
15
19
|
const data = JSON.parse(input);
|
|
16
20
|
const model = data.model?.display_name || 'Claude';
|
|
@@ -18,14 +22,14 @@ process.stdin.on('end', () => {
|
|
|
18
22
|
const session = data.session_id || '';
|
|
19
23
|
const remaining = data.context_window?.remaining_percentage;
|
|
20
24
|
|
|
21
|
-
// Context window display (shows USED percentage scaled to
|
|
22
|
-
// Claude Code
|
|
25
|
+
// Context window display (shows USED percentage scaled to usable context)
|
|
26
|
+
// Claude Code reserves ~16.5% for autocompact buffer, so usable context
|
|
27
|
+
// is 83.5% of the total window. We normalize to show 100% at that point.
|
|
28
|
+
const AUTO_COMPACT_BUFFER_PCT = 16.5;
|
|
23
29
|
let ctx = '';
|
|
24
30
|
if (remaining != null) {
|
|
25
|
-
const
|
|
26
|
-
const
|
|
27
|
-
// Scale: 80% real usage = 100% displayed
|
|
28
|
-
const used = Math.min(100, Math.round((rawUsed / 80) * 100));
|
|
31
|
+
const usableRemaining = Math.max(0, ((remaining - AUTO_COMPACT_BUFFER_PCT) / (100 - AUTO_COMPACT_BUFFER_PCT)) * 100);
|
|
32
|
+
const used = Math.max(0, Math.min(100, Math.round(100 - usableRemaining)));
|
|
29
33
|
|
|
30
34
|
// Write context metrics to bridge file for context-monitor hooks
|
|
31
35
|
if (session) {
|
|
@@ -48,12 +52,12 @@ process.stdin.on('end', () => {
|
|
|
48
52
|
const filled = Math.floor(used / 10);
|
|
49
53
|
const bar = '█'.repeat(filled) + '░'.repeat(10 - filled);
|
|
50
54
|
|
|
51
|
-
// Color based on
|
|
52
|
-
if (used <
|
|
55
|
+
// Color based on usable context thresholds
|
|
56
|
+
if (used < 50) {
|
|
53
57
|
ctx = ` \x1b[32m${bar} ${used}%\x1b[0m`;
|
|
54
|
-
} else if (used <
|
|
58
|
+
} else if (used < 65) {
|
|
55
59
|
ctx = ` \x1b[33m${bar} ${used}%\x1b[0m`;
|
|
56
|
-
} else if (used <
|
|
60
|
+
} else if (used < 80) {
|
|
57
61
|
ctx = ` \x1b[38;5;208m${bar} ${used}%\x1b[0m`;
|
|
58
62
|
} else {
|
|
59
63
|
ctx = ` \x1b[5;31m💀 ${bar} ${used}%\x1b[0m`;
|
|
@@ -63,7 +67,9 @@ process.stdin.on('end', () => {
|
|
|
63
67
|
// Current task from todos
|
|
64
68
|
let task = '';
|
|
65
69
|
const homeDir = os.homedir();
|
|
66
|
-
|
|
70
|
+
// Respect CLAUDE_CONFIG_DIR for custom config directory setups
|
|
71
|
+
const claudeDir = process.env.CLAUDE_CONFIG_DIR || path.join(homeDir, '.claude');
|
|
72
|
+
const todosDir = path.join(claudeDir, 'todos');
|
|
67
73
|
if (session && fs.existsSync(todosDir)) {
|
|
68
74
|
try {
|
|
69
75
|
const entries = fs.readdirSync(todosDir);
|
|
@@ -91,7 +97,8 @@ process.stdin.on('end', () => {
|
|
|
91
97
|
|
|
92
98
|
// Update notifications (GSD + slashdo)
|
|
93
99
|
let updates = '';
|
|
94
|
-
const
|
|
100
|
+
const cacheDir = path.join(claudeDir, 'cache');
|
|
101
|
+
const gsdCacheFile = path.join(cacheDir, 'gsd-update-check.json');
|
|
95
102
|
if (fs.existsSync(gsdCacheFile)) {
|
|
96
103
|
try {
|
|
97
104
|
const cache = JSON.parse(fs.readFileSync(gsdCacheFile, 'utf8'));
|
|
@@ -100,7 +107,7 @@ process.stdin.on('end', () => {
|
|
|
100
107
|
}
|
|
101
108
|
} catch (e) {}
|
|
102
109
|
}
|
|
103
|
-
const slashdoCacheFile = path.join(
|
|
110
|
+
const slashdoCacheFile = path.join(cacheDir, 'slashdo-update-check.json');
|
|
104
111
|
if (fs.existsSync(slashdoCacheFile)) {
|
|
105
112
|
try {
|
|
106
113
|
const cache = JSON.parse(fs.readFileSync(slashdoCacheFile, 'utf8'));
|
package/install.sh
CHANGED
|
@@ -152,12 +152,19 @@ install_claude() {
|
|
|
152
152
|
modified = true;
|
|
153
153
|
}
|
|
154
154
|
|
|
155
|
-
// Statusline
|
|
155
|
+
// Statusline: upgrade gsd-statusline → slashdo-statusline (superset)
|
|
156
156
|
const statuslineHookPath = path.join(hooksDir, "slashdo-statusline.js");
|
|
157
|
-
if (
|
|
157
|
+
if (fs.existsSync(statuslineHookPath)) {
|
|
158
158
|
const slCmd = "node \"" + statuslineHookPath + "\"";
|
|
159
|
-
settings.statusLine
|
|
160
|
-
|
|
159
|
+
const currentCmd = (settings.statusLine && typeof settings.statusLine.command === "string") ? settings.statusLine.command : "";
|
|
160
|
+
if (!settings.statusLine) {
|
|
161
|
+
settings.statusLine = { type: "command", command: slCmd };
|
|
162
|
+
modified = true;
|
|
163
|
+
} else if (currentCmd.indexOf("gsd-statusline") !== -1) {
|
|
164
|
+
settings.statusLine = { type: "command", command: slCmd };
|
|
165
|
+
modified = true;
|
|
166
|
+
}
|
|
167
|
+
// slashdo-statusline already active or custom statusline → no change
|
|
161
168
|
}
|
|
162
169
|
|
|
163
170
|
if (modified) {
|
package/package.json
CHANGED
package/src/installer.js
CHANGED
|
@@ -146,18 +146,25 @@ function registerHooksInSettings(env, hookFiles, dryRun) {
|
|
|
146
146
|
}
|
|
147
147
|
}
|
|
148
148
|
|
|
149
|
-
// Configure statusline
|
|
149
|
+
// Configure statusline: upgrade gsd-statusline → slashdo-statusline (superset)
|
|
150
150
|
const statuslineHook = hookFiles.find(h => h.name === 'slashdo-statusline.js');
|
|
151
|
-
if (statuslineHook
|
|
151
|
+
if (statuslineHook) {
|
|
152
152
|
const statuslineCommand = `node "${path.join(env.hooksDir, statuslineHook.name)}"`;
|
|
153
|
-
settings.statusLine
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
153
|
+
const currentCmd = typeof settings.statusLine?.command === 'string' ? settings.statusLine.command : '';
|
|
154
|
+
|
|
155
|
+
if (!settings.statusLine) {
|
|
156
|
+
settings.statusLine = { type: 'command', command: statuslineCommand };
|
|
157
|
+
modified = true;
|
|
158
|
+
actions.push({ name: 'settings/statusLine', status: dryRun ? 'would configure' : 'configured' });
|
|
159
|
+
} else if (currentCmd.includes('gsd-statusline')) {
|
|
160
|
+
settings.statusLine = { type: 'command', command: statuslineCommand };
|
|
161
|
+
modified = true;
|
|
162
|
+
actions.push({ name: 'settings/statusLine', status: dryRun ? 'would upgrade (gsd→slashdo)' : 'upgraded (gsd→slashdo)' });
|
|
163
|
+
} else if (currentCmd.includes('slashdo-statusline')) {
|
|
164
|
+
actions.push({ name: 'settings/statusLine', status: 'already configured' });
|
|
165
|
+
} else {
|
|
166
|
+
actions.push({ name: 'settings/statusLine', status: 'existing statusline preserved' });
|
|
167
|
+
}
|
|
161
168
|
}
|
|
162
169
|
|
|
163
170
|
if (!dryRun && modified) {
|
|
@@ -214,9 +221,16 @@ function deregisterHooksFromSettings(env, dryRun) {
|
|
|
214
221
|
|
|
215
222
|
// Remove statusline if it references slashdo-statusline
|
|
216
223
|
if (settings.statusLine?.command?.includes('slashdo-statusline')) {
|
|
217
|
-
|
|
224
|
+
// Restore gsd-statusline if its hook file still exists
|
|
225
|
+
const gsdHookPath = path.join(env.hooksDir, 'gsd-statusline.js');
|
|
226
|
+
if (fs.existsSync(gsdHookPath)) {
|
|
227
|
+
settings.statusLine = { type: 'command', command: `node "${gsdHookPath}"` };
|
|
228
|
+
actions.push({ name: 'settings/statusLine', status: dryRun ? 'would downgrade (slashdo→gsd)' : 'downgraded (slashdo→gsd)' });
|
|
229
|
+
} else {
|
|
230
|
+
delete settings.statusLine;
|
|
231
|
+
actions.push({ name: 'settings/statusLine', status: dryRun ? 'would remove' : 'removed' });
|
|
232
|
+
}
|
|
218
233
|
modified = true;
|
|
219
|
-
actions.push({ name: 'settings/statusLine', status: dryRun ? 'would remove' : 'removed' });
|
|
220
234
|
}
|
|
221
235
|
|
|
222
236
|
if (!dryRun && modified) {
|
package/uninstall.sh
CHANGED
|
@@ -135,7 +135,13 @@ uninstall_claude() {
|
|
|
135
135
|
|
|
136
136
|
if (settings.statusLine && settings.statusLine.command &&
|
|
137
137
|
settings.statusLine.command.indexOf("slashdo-statusline") !== -1) {
|
|
138
|
-
|
|
138
|
+
var hooksDir = path.join(home, ".claude", "hooks");
|
|
139
|
+
var gsdHookPath = path.join(hooksDir, "gsd-statusline.js");
|
|
140
|
+
if (fs.existsSync(gsdHookPath)) {
|
|
141
|
+
settings.statusLine = { type: "command", command: "node \"" + gsdHookPath + "\"" };
|
|
142
|
+
} else {
|
|
143
|
+
delete settings.statusLine;
|
|
144
|
+
}
|
|
139
145
|
modified = true;
|
|
140
146
|
}
|
|
141
147
|
|