get-shit-done-cc 1.5.28 → 1.5.30
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/agents/gsd-plan-checker.md +3 -2
- package/bin/install.js +13 -109
- package/commands/gsd/audit-milestone.md +23 -19
- package/commands/gsd/create-roadmap.md +2 -2
- package/commands/gsd/discuss-phase.md +24 -15
- package/commands/gsd/execute-phase.md +18 -24
- package/commands/gsd/new-project.md +7 -2
- package/commands/gsd/plan-phase.md +37 -22
- package/commands/gsd/progress.md +4 -4
- package/commands/gsd/research-phase.md +13 -7
- package/commands/gsd/verify-work.md +15 -5
- package/get-shit-done/templates/context.md +143 -13
- package/get-shit-done/workflows/create-roadmap.md +2 -2
- package/get-shit-done/workflows/diagnose-issues.md +10 -20
- package/get-shit-done/workflows/discuss-phase.md +95 -46
- package/get-shit-done/workflows/verify-work.md +170 -14
- package/hooks/gsd-check-update.js +51 -0
- package/hooks/statusline.js +84 -0
- package/package.json +1 -1
- package/hooks/gsd-check-update.sh +0 -20
- package/hooks/gsd-notify.sh +0 -59
- package/hooks/statusline.sh +0 -58
|
@@ -334,28 +334,180 @@ Spawning parallel debug agents to investigate each issue.
|
|
|
334
334
|
- Spawn parallel debug agents for each issue
|
|
335
335
|
- Collect root causes
|
|
336
336
|
- Update UAT.md with root causes
|
|
337
|
-
- Proceed to `
|
|
337
|
+
- Proceed to `plan_gap_closure`
|
|
338
338
|
|
|
339
339
|
Diagnosis runs automatically - no user prompt. Parallel agents investigate simultaneously, so overhead is minimal and fixes are more accurate.
|
|
340
340
|
</step>
|
|
341
341
|
|
|
342
|
-
<step name="
|
|
343
|
-
**
|
|
342
|
+
<step name="plan_gap_closure">
|
|
343
|
+
**Auto-plan fixes from diagnosed gaps:**
|
|
344
344
|
|
|
345
|
+
Display:
|
|
346
|
+
```
|
|
347
|
+
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
348
|
+
GSD ► PLANNING FIXES
|
|
349
|
+
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
350
|
+
|
|
351
|
+
◆ Spawning planner for gap closure...
|
|
345
352
|
```
|
|
346
|
-
---
|
|
347
353
|
|
|
348
|
-
|
|
354
|
+
Spawn gsd-planner in --gaps mode:
|
|
349
355
|
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
356
|
+
```
|
|
357
|
+
Task(
|
|
358
|
+
prompt="""
|
|
359
|
+
<planning_context>
|
|
360
|
+
|
|
361
|
+
**Phase:** {phase_number}
|
|
362
|
+
**Mode:** gap_closure
|
|
363
|
+
|
|
364
|
+
**UAT with diagnoses:**
|
|
365
|
+
@.planning/phases/{phase_dir}/{phase}-UAT.md
|
|
366
|
+
|
|
367
|
+
**Project State:**
|
|
368
|
+
@.planning/STATE.md
|
|
369
|
+
|
|
370
|
+
**Roadmap:**
|
|
371
|
+
@.planning/ROADMAP.md
|
|
372
|
+
|
|
373
|
+
</planning_context>
|
|
374
|
+
|
|
375
|
+
<downstream_consumer>
|
|
376
|
+
Output consumed by /gsd:execute-phase
|
|
377
|
+
Plans must be executable prompts.
|
|
378
|
+
</downstream_consumer>
|
|
379
|
+
""",
|
|
380
|
+
subagent_type="gsd-planner",
|
|
381
|
+
description="Plan gap fixes for Phase {phase}"
|
|
382
|
+
)
|
|
383
|
+
```
|
|
384
|
+
|
|
385
|
+
On return:
|
|
386
|
+
- **PLANNING COMPLETE:** Proceed to `verify_gap_plans`
|
|
387
|
+
- **PLANNING INCONCLUSIVE:** Report and offer manual intervention
|
|
388
|
+
</step>
|
|
389
|
+
|
|
390
|
+
<step name="verify_gap_plans">
|
|
391
|
+
**Verify fix plans with checker:**
|
|
392
|
+
|
|
393
|
+
Display:
|
|
394
|
+
```
|
|
395
|
+
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
396
|
+
GSD ► VERIFYING FIX PLANS
|
|
397
|
+
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
398
|
+
|
|
399
|
+
◆ Spawning plan checker...
|
|
400
|
+
```
|
|
401
|
+
|
|
402
|
+
Initialize: `iteration_count = 1`
|
|
403
|
+
|
|
404
|
+
Spawn gsd-plan-checker:
|
|
405
|
+
|
|
406
|
+
```
|
|
407
|
+
Task(
|
|
408
|
+
prompt="""
|
|
409
|
+
<verification_context>
|
|
410
|
+
|
|
411
|
+
**Phase:** {phase_number}
|
|
412
|
+
**Phase Goal:** Close diagnosed gaps from UAT
|
|
413
|
+
|
|
414
|
+
**Plans to verify:**
|
|
415
|
+
@.planning/phases/{phase_dir}/*-PLAN.md
|
|
416
|
+
|
|
417
|
+
</verification_context>
|
|
418
|
+
|
|
419
|
+
<expected_output>
|
|
420
|
+
Return one of:
|
|
421
|
+
- ## VERIFICATION PASSED — all checks pass
|
|
422
|
+
- ## ISSUES FOUND — structured issue list
|
|
423
|
+
</expected_output>
|
|
424
|
+
""",
|
|
425
|
+
subagent_type="gsd-plan-checker",
|
|
426
|
+
description="Verify Phase {phase} fix plans"
|
|
427
|
+
)
|
|
428
|
+
```
|
|
429
|
+
|
|
430
|
+
On return:
|
|
431
|
+
- **VERIFICATION PASSED:** Proceed to `present_ready`
|
|
432
|
+
- **ISSUES FOUND:** Proceed to `revision_loop`
|
|
433
|
+
</step>
|
|
434
|
+
|
|
435
|
+
<step name="revision_loop">
|
|
436
|
+
**Iterate planner ↔ checker until plans pass (max 3):**
|
|
437
|
+
|
|
438
|
+
**If iteration_count < 3:**
|
|
439
|
+
|
|
440
|
+
Display: `Sending back to planner for revision... (iteration {N}/3)`
|
|
441
|
+
|
|
442
|
+
Spawn gsd-planner with revision context:
|
|
443
|
+
|
|
444
|
+
```
|
|
445
|
+
Task(
|
|
446
|
+
prompt="""
|
|
447
|
+
<revision_context>
|
|
448
|
+
|
|
449
|
+
**Phase:** {phase_number}
|
|
450
|
+
**Mode:** revision
|
|
451
|
+
|
|
452
|
+
**Existing plans:**
|
|
453
|
+
@.planning/phases/{phase_dir}/*-PLAN.md
|
|
454
|
+
|
|
455
|
+
**Checker issues:**
|
|
456
|
+
{structured_issues_from_checker}
|
|
457
|
+
|
|
458
|
+
</revision_context>
|
|
459
|
+
|
|
460
|
+
<instructions>
|
|
461
|
+
Read existing PLAN.md files. Make targeted updates to address checker issues.
|
|
462
|
+
Do NOT replan from scratch unless issues are fundamental.
|
|
463
|
+
</instructions>
|
|
464
|
+
""",
|
|
465
|
+
subagent_type="gsd-planner",
|
|
466
|
+
description="Revise Phase {phase} plans"
|
|
467
|
+
)
|
|
468
|
+
```
|
|
469
|
+
|
|
470
|
+
After planner returns → spawn checker again (verify_gap_plans logic)
|
|
471
|
+
Increment iteration_count
|
|
472
|
+
|
|
473
|
+
**If iteration_count >= 3:**
|
|
474
|
+
|
|
475
|
+
Display: `Max iterations reached. {N} issues remain.`
|
|
476
|
+
|
|
477
|
+
Offer options:
|
|
478
|
+
1. Force proceed (execute despite issues)
|
|
479
|
+
2. Provide guidance (user gives direction, retry)
|
|
480
|
+
3. Abandon (exit, user runs /gsd:plan-phase manually)
|
|
481
|
+
|
|
482
|
+
Wait for user response.
|
|
483
|
+
</step>
|
|
484
|
+
|
|
485
|
+
<step name="present_ready">
|
|
486
|
+
**Present completion and next steps:**
|
|
487
|
+
|
|
488
|
+
```
|
|
489
|
+
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
490
|
+
GSD ► FIXES READY ✓
|
|
491
|
+
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
492
|
+
|
|
493
|
+
**Phase {X}: {Name}** — {N} gap(s) diagnosed, {M} fix plan(s) created
|
|
494
|
+
|
|
495
|
+
| Gap | Root Cause | Fix Plan |
|
|
496
|
+
|-----|------------|----------|
|
|
497
|
+
| {truth 1} | {root_cause} | {phase}-04 |
|
|
498
|
+
| {truth 2} | {root_cause} | {phase}-04 |
|
|
499
|
+
|
|
500
|
+
Plans verified and ready for execution.
|
|
501
|
+
|
|
502
|
+
───────────────────────────────────────────────────────────────
|
|
503
|
+
|
|
504
|
+
## ▶ Next Up
|
|
505
|
+
|
|
506
|
+
**Execute fixes** — run fix plans
|
|
507
|
+
|
|
508
|
+
`/clear` then `/gsd:execute-phase {phase}`
|
|
355
509
|
|
|
356
|
-
|
|
357
|
-
- `/gsd:plan-phase {phase} --gaps` — Create fix plans from diagnosed gaps
|
|
358
|
-
- `/gsd:verify-work {phase}` — Re-test after fixes
|
|
510
|
+
───────────────────────────────────────────────────────────────
|
|
359
511
|
```
|
|
360
512
|
</step>
|
|
361
513
|
|
|
@@ -403,5 +555,9 @@ Default to **major** if unclear. User can correct if needed.
|
|
|
403
555
|
- [ ] Severity inferred from description (never asked)
|
|
404
556
|
- [ ] Batched writes: on issue, every 5 passes, or completion
|
|
405
557
|
- [ ] Committed on completion
|
|
406
|
-
- [ ]
|
|
558
|
+
- [ ] If issues: parallel debug agents diagnose root causes
|
|
559
|
+
- [ ] If issues: gsd-planner creates fix plans (gap_closure mode)
|
|
560
|
+
- [ ] If issues: gsd-plan-checker verifies fix plans
|
|
561
|
+
- [ ] If issues: revision loop until plans pass (max 3 iterations)
|
|
562
|
+
- [ ] Ready for `/gsd:execute-phase` when complete
|
|
407
563
|
</success_criteria>
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
// Check for GSD updates in background, write result to cache
|
|
3
|
+
// Called by SessionStart hook - runs once per session
|
|
4
|
+
|
|
5
|
+
const fs = require('fs');
|
|
6
|
+
const path = require('path');
|
|
7
|
+
const os = require('os');
|
|
8
|
+
const { execSync, spawn } = require('child_process');
|
|
9
|
+
|
|
10
|
+
const homeDir = os.homedir();
|
|
11
|
+
const cacheDir = path.join(homeDir, '.claude', 'cache');
|
|
12
|
+
const cacheFile = path.join(cacheDir, 'gsd-update-check.json');
|
|
13
|
+
const versionFile = path.join(homeDir, '.claude', 'get-shit-done', 'VERSION');
|
|
14
|
+
|
|
15
|
+
// Ensure cache directory exists
|
|
16
|
+
if (!fs.existsSync(cacheDir)) {
|
|
17
|
+
fs.mkdirSync(cacheDir, { recursive: true });
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
// Run check in background (spawn detached process)
|
|
21
|
+
const child = spawn(process.execPath, ['-e', `
|
|
22
|
+
const fs = require('fs');
|
|
23
|
+
const { execSync } = require('child_process');
|
|
24
|
+
|
|
25
|
+
const cacheFile = ${JSON.stringify(cacheFile)};
|
|
26
|
+
const versionFile = ${JSON.stringify(versionFile)};
|
|
27
|
+
|
|
28
|
+
let installed = '0.0.0';
|
|
29
|
+
try {
|
|
30
|
+
installed = fs.readFileSync(versionFile, 'utf8').trim();
|
|
31
|
+
} catch (e) {}
|
|
32
|
+
|
|
33
|
+
let latest = null;
|
|
34
|
+
try {
|
|
35
|
+
latest = execSync('npm view get-shit-done-cc version', { encoding: 'utf8', timeout: 10000 }).trim();
|
|
36
|
+
} catch (e) {}
|
|
37
|
+
|
|
38
|
+
const result = {
|
|
39
|
+
update_available: latest && installed !== latest,
|
|
40
|
+
installed,
|
|
41
|
+
latest: latest || 'unknown',
|
|
42
|
+
checked: Math.floor(Date.now() / 1000)
|
|
43
|
+
};
|
|
44
|
+
|
|
45
|
+
fs.writeFileSync(cacheFile, JSON.stringify(result));
|
|
46
|
+
`], {
|
|
47
|
+
detached: true,
|
|
48
|
+
stdio: 'ignore'
|
|
49
|
+
});
|
|
50
|
+
|
|
51
|
+
child.unref();
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
// Claude Code Statusline - GSD Edition
|
|
3
|
+
// Shows: model | current task | directory | context usage
|
|
4
|
+
|
|
5
|
+
const fs = require('fs');
|
|
6
|
+
const path = require('path');
|
|
7
|
+
const os = require('os');
|
|
8
|
+
|
|
9
|
+
// Read JSON from stdin
|
|
10
|
+
let input = '';
|
|
11
|
+
process.stdin.setEncoding('utf8');
|
|
12
|
+
process.stdin.on('data', chunk => input += chunk);
|
|
13
|
+
process.stdin.on('end', () => {
|
|
14
|
+
try {
|
|
15
|
+
const data = JSON.parse(input);
|
|
16
|
+
const model = data.model?.display_name || 'Claude';
|
|
17
|
+
const dir = data.workspace?.current_dir || process.cwd();
|
|
18
|
+
const session = data.session_id || '';
|
|
19
|
+
const remaining = data.context_window?.remaining_percentage;
|
|
20
|
+
|
|
21
|
+
// Context window display (shows USED percentage)
|
|
22
|
+
let ctx = '';
|
|
23
|
+
if (remaining != null) {
|
|
24
|
+
const rem = Math.round(remaining);
|
|
25
|
+
const used = 100 - rem;
|
|
26
|
+
|
|
27
|
+
// Build progress bar (10 segments)
|
|
28
|
+
const filled = Math.floor(used / 10);
|
|
29
|
+
const bar = '█'.repeat(filled) + '░'.repeat(10 - filled);
|
|
30
|
+
|
|
31
|
+
// Color based on usage
|
|
32
|
+
if (used < 50) {
|
|
33
|
+
ctx = ` \x1b[32m${bar} ${used}%\x1b[0m`;
|
|
34
|
+
} else if (used < 65) {
|
|
35
|
+
ctx = ` \x1b[33m${bar} ${used}%\x1b[0m`;
|
|
36
|
+
} else if (used < 80) {
|
|
37
|
+
ctx = ` \x1b[38;5;208m${bar} ${used}%\x1b[0m`;
|
|
38
|
+
} else {
|
|
39
|
+
ctx = ` \x1b[5;31m💀 ${bar} ${used}%\x1b[0m`;
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
// Current task from todos
|
|
44
|
+
let task = '';
|
|
45
|
+
const homeDir = os.homedir();
|
|
46
|
+
const todosDir = path.join(homeDir, '.claude', 'todos');
|
|
47
|
+
if (session && fs.existsSync(todosDir)) {
|
|
48
|
+
const files = fs.readdirSync(todosDir)
|
|
49
|
+
.filter(f => f.startsWith(session) && f.includes('-agent-') && f.endsWith('.json'))
|
|
50
|
+
.map(f => ({ name: f, mtime: fs.statSync(path.join(todosDir, f)).mtime }))
|
|
51
|
+
.sort((a, b) => b.mtime - a.mtime);
|
|
52
|
+
|
|
53
|
+
if (files.length > 0) {
|
|
54
|
+
try {
|
|
55
|
+
const todos = JSON.parse(fs.readFileSync(path.join(todosDir, files[0].name), 'utf8'));
|
|
56
|
+
const inProgress = todos.find(t => t.status === 'in_progress');
|
|
57
|
+
if (inProgress) task = inProgress.activeForm || '';
|
|
58
|
+
} catch (e) {}
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
// GSD update available?
|
|
63
|
+
let gsdUpdate = '';
|
|
64
|
+
const cacheFile = path.join(homeDir, '.claude', 'cache', 'gsd-update-check.json');
|
|
65
|
+
if (fs.existsSync(cacheFile)) {
|
|
66
|
+
try {
|
|
67
|
+
const cache = JSON.parse(fs.readFileSync(cacheFile, 'utf8'));
|
|
68
|
+
if (cache.update_available) {
|
|
69
|
+
gsdUpdate = '\x1b[33m⬆ /gsd:update\x1b[0m │ ';
|
|
70
|
+
}
|
|
71
|
+
} catch (e) {}
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
// Output
|
|
75
|
+
const dirname = path.basename(dir);
|
|
76
|
+
if (task) {
|
|
77
|
+
process.stdout.write(`${gsdUpdate}\x1b[2m${model}\x1b[0m │ \x1b[1m${task}\x1b[0m │ \x1b[2m${dirname}\x1b[0m${ctx}`);
|
|
78
|
+
} else {
|
|
79
|
+
process.stdout.write(`${gsdUpdate}\x1b[2m${model}\x1b[0m │ \x1b[2m${dirname}\x1b[0m${ctx}`);
|
|
80
|
+
}
|
|
81
|
+
} catch (e) {
|
|
82
|
+
// Silent fail - don't break statusline on parse errors
|
|
83
|
+
}
|
|
84
|
+
});
|
package/package.json
CHANGED
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
#!/bin/bash
|
|
2
|
-
# Check for GSD updates in background, write result to cache
|
|
3
|
-
# Called by SessionStart hook - runs once per session
|
|
4
|
-
|
|
5
|
-
CACHE_FILE="$HOME/.claude/cache/gsd-update-check.json"
|
|
6
|
-
mkdir -p "$HOME/.claude/cache"
|
|
7
|
-
|
|
8
|
-
# Run check in background (non-blocking)
|
|
9
|
-
(
|
|
10
|
-
installed=$(cat "$HOME/.claude/get-shit-done/VERSION" 2>/dev/null || echo "0.0.0")
|
|
11
|
-
latest=$(npm view get-shit-done-cc version 2>/dev/null)
|
|
12
|
-
|
|
13
|
-
if [[ -n "$latest" && "$installed" != "$latest" ]]; then
|
|
14
|
-
echo "{\"update_available\":true,\"installed\":\"$installed\",\"latest\":\"$latest\",\"checked\":$(date +%s)}" > "$CACHE_FILE"
|
|
15
|
-
else
|
|
16
|
-
echo "{\"update_available\":false,\"installed\":\"$installed\",\"latest\":\"${latest:-unknown}\",\"checked\":$(date +%s)}" > "$CACHE_FILE"
|
|
17
|
-
fi
|
|
18
|
-
) &
|
|
19
|
-
|
|
20
|
-
exit 0
|
package/hooks/gsd-notify.sh
DELETED
|
@@ -1,59 +0,0 @@
|
|
|
1
|
-
#!/bin/bash
|
|
2
|
-
# GSD Completion Notification Hook
|
|
3
|
-
# Cross-platform alert when Claude stops (task complete, needs input, etc.)
|
|
4
|
-
|
|
5
|
-
input=$(cat)
|
|
6
|
-
session_id=$(echo "$input" | jq -r '.session_id // empty')
|
|
7
|
-
cwd=$(echo "$input" | jq -r '.cwd // empty')
|
|
8
|
-
transcript_path=$(echo "$input" | jq -r '.transcript_path // empty')
|
|
9
|
-
|
|
10
|
-
# Extract project name
|
|
11
|
-
project="Claude Code"
|
|
12
|
-
if [[ -n "$cwd" ]]; then
|
|
13
|
-
project=$(basename "$cwd")
|
|
14
|
-
fi
|
|
15
|
-
|
|
16
|
-
# Check todo list for current/completed task
|
|
17
|
-
message=""
|
|
18
|
-
if [[ -n "$session_id" ]]; then
|
|
19
|
-
todo_file=$(ls -t "$HOME/.claude/todos/${session_id}"*.json 2>/dev/null | head -1)
|
|
20
|
-
if [[ -f "$todo_file" ]]; then
|
|
21
|
-
# Get most recently completed task, or in-progress task
|
|
22
|
-
completed=$(jq -r '[.[] | select(.status=="completed")] | last | .content // empty' "$todo_file" 2>/dev/null)
|
|
23
|
-
if [[ -n "$completed" ]]; then
|
|
24
|
-
message="Completed: $completed"
|
|
25
|
-
else
|
|
26
|
-
in_progress=$(jq -r '.[] | select(.status=="in_progress") | .content' "$todo_file" 2>/dev/null | head -1)
|
|
27
|
-
if [[ -n "$in_progress" ]]; then
|
|
28
|
-
message="Paused: $in_progress"
|
|
29
|
-
fi
|
|
30
|
-
fi
|
|
31
|
-
fi
|
|
32
|
-
fi
|
|
33
|
-
|
|
34
|
-
# Fallback: generic message
|
|
35
|
-
if [[ -z "$message" ]]; then
|
|
36
|
-
message="Ready for input"
|
|
37
|
-
fi
|
|
38
|
-
|
|
39
|
-
# Send notification based on OS
|
|
40
|
-
case "$(uname -s)" in
|
|
41
|
-
Darwin)
|
|
42
|
-
osascript -e "display alert \"GSD: $project\" message \"$message\" as informational" &>/dev/null &
|
|
43
|
-
;;
|
|
44
|
-
Linux)
|
|
45
|
-
if command -v notify-send &>/dev/null; then
|
|
46
|
-
notify-send "GSD: $project" "$message" --urgency=normal
|
|
47
|
-
elif command -v zenity &>/dev/null; then
|
|
48
|
-
zenity --info --title="GSD: $project" --text="$message" &
|
|
49
|
-
fi
|
|
50
|
-
;;
|
|
51
|
-
MINGW*|CYGWIN*|MSYS*)
|
|
52
|
-
# Windows via PowerShell
|
|
53
|
-
if command -v powershell.exe &>/dev/null; then
|
|
54
|
-
powershell.exe -Command "Add-Type -AssemblyName System.Windows.Forms; [System.Windows.Forms.MessageBox]::Show('$message', 'GSD: $project', 'OK', 'Information')" &>/dev/null &
|
|
55
|
-
fi
|
|
56
|
-
;;
|
|
57
|
-
esac
|
|
58
|
-
|
|
59
|
-
exit 0
|
package/hooks/statusline.sh
DELETED
|
@@ -1,58 +0,0 @@
|
|
|
1
|
-
#!/bin/bash
|
|
2
|
-
# Claude Code Statusline - GSD Edition
|
|
3
|
-
# Shows: model | current task | directory | context usage
|
|
4
|
-
|
|
5
|
-
input=$(cat)
|
|
6
|
-
model=$(echo "$input" | jq -r '.model.display_name')
|
|
7
|
-
dir=$(echo "$input" | jq -r '.workspace.current_dir')
|
|
8
|
-
session=$(echo "$input" | jq -r '.session_id')
|
|
9
|
-
remaining=$(echo "$input" | jq -r '.context_window.remaining_percentage // empty')
|
|
10
|
-
|
|
11
|
-
# Context window display (shows USED percentage)
|
|
12
|
-
ctx=""
|
|
13
|
-
if [ -n "$remaining" ]; then
|
|
14
|
-
rem=$(printf "%.0f" "$remaining")
|
|
15
|
-
used=$((100 - rem))
|
|
16
|
-
|
|
17
|
-
# Build progress bar (10 segments) - fills as context is consumed
|
|
18
|
-
filled=$((used / 10))
|
|
19
|
-
bar=""
|
|
20
|
-
for ((i=0; i<filled; i++)); do bar+="█"; done
|
|
21
|
-
for ((i=filled; i<10; i++)); do bar+="░"; done
|
|
22
|
-
|
|
23
|
-
# Color based on usage with blinking skull at 80%+
|
|
24
|
-
if [ "$used" -lt 50 ]; then
|
|
25
|
-
ctx=$' \033[32m'"$bar $used%"$'\033[0m'
|
|
26
|
-
elif [ "$used" -lt 65 ]; then
|
|
27
|
-
ctx=$' \033[33m'"$bar $used%"$'\033[0m'
|
|
28
|
-
elif [ "$used" -lt 80 ]; then
|
|
29
|
-
ctx=$' \033[38;5;208m'"$bar $used%"$'\033[0m'
|
|
30
|
-
else
|
|
31
|
-
# Blinking red with skull
|
|
32
|
-
ctx=$' \033[5;31m💀 '"$bar $used%"$'\033[0m'
|
|
33
|
-
fi
|
|
34
|
-
fi
|
|
35
|
-
|
|
36
|
-
# Current task from todos
|
|
37
|
-
task=""
|
|
38
|
-
todo=$(ls -t "$HOME/.claude/todos/${session}"-agent-*.json 2>/dev/null | head -1)
|
|
39
|
-
if [[ -f "$todo" ]]; then
|
|
40
|
-
task=$(jq -r '.[] | select(.status=="in_progress") | .activeForm' "$todo" 2>/dev/null | head -1)
|
|
41
|
-
fi
|
|
42
|
-
|
|
43
|
-
# GSD update available?
|
|
44
|
-
gsd_update=""
|
|
45
|
-
if [[ -f "$HOME/.claude/cache/gsd-update-check.json" ]]; then
|
|
46
|
-
update_available=$(jq -r '.update_available' "$HOME/.claude/cache/gsd-update-check.json" 2>/dev/null)
|
|
47
|
-
if [[ "$update_available" == "true" ]]; then
|
|
48
|
-
gsd_update=$'\033[33m⬆ /gsd:update\033[0m │ '
|
|
49
|
-
fi
|
|
50
|
-
fi
|
|
51
|
-
|
|
52
|
-
# Output
|
|
53
|
-
dirname=$(basename "$dir")
|
|
54
|
-
if [[ -n "$task" ]]; then
|
|
55
|
-
printf '%s\033[2m%s\033[0m │ \033[1m%s\033[0m │ \033[2m%s\033[0m%s' "$gsd_update" "$model" "$task" "$dirname" "$ctx"
|
|
56
|
-
else
|
|
57
|
-
printf '%s\033[2m%s\033[0m │ \033[2m%s\033[0m%s' "$gsd_update" "$model" "$dirname" "$ctx"
|
|
58
|
-
fi
|