projecta-rrr 1.16.9 → 1.17.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/bin/install.js +245 -1
- package/commands/rrr/check-upstream.md +37 -0
- package/commands/rrr/doctor.md +75 -1
- package/commands/rrr/update.md +44 -0
- package/docs/OHMPOSH-SETUP.md +246 -0
- package/docs/terminal.svg +70 -0
- package/hooks/rrr-sync-hud-state.sh +124 -0
- package/hooks/rrr-update-hud-state.sh +100 -0
- package/hooks/statusline.sh +9 -9
- package/package.json +9 -2
- package/rrr/ohmyposh/rrr-atomic.omp.json +112 -0
- package/rrr/ohmyposh/rrr-env.sh +49 -0
- package/rrr/ohmyposh/rrr-kushal.omp.json +55 -0
- package/scripts/doctor-rrr.js +236 -2
- package/{rrr/scripts → scripts}/register-mcp.js +2 -0
- package/scripts/rrr-hud-dynamic.js +530 -0
- package/scripts/rrr-hud.js +261 -2
- package/scripts/rrr-state-manager.js +355 -0
|
@@ -0,0 +1,246 @@
|
|
|
1
|
+
# OhMyPosh HUD Setup Guide
|
|
2
|
+
|
|
3
|
+
This guide explains how to set up the RRR HUD using OhMyPosh with **Kushal theme** styling (recommended) or Atomic theme.
|
|
4
|
+
|
|
5
|
+
## Theme Options
|
|
6
|
+
|
|
7
|
+
| Theme | Style | Colors |
|
|
8
|
+
|-------|-------|--------|
|
|
9
|
+
| **Kushal** (recommended) | Powerline segments, vibrant | Teal/Cyan/Orange/Yellow |
|
|
10
|
+
| Atomic | Diamond segments | Blue/Orange/Yellow |
|
|
11
|
+
|
|
12
|
+
## Quick Setup
|
|
13
|
+
|
|
14
|
+
```bash
|
|
15
|
+
# 1. Install OhMyPosh (if not already installed)
|
|
16
|
+
brew install jandedobbeleer/oh-my-posh/oh-my-posh
|
|
17
|
+
|
|
18
|
+
# 2. Add to your shell profile (~/.zshrc or ~/.bashrc)
|
|
19
|
+
eval "$(oh-my-posh init bash)"
|
|
20
|
+
|
|
21
|
+
# 3. Copy the RRR theme config (choose one)
|
|
22
|
+
mkdir -p ~/.poshthemes
|
|
23
|
+
|
|
24
|
+
# Kushal theme (recommended - powerline style)
|
|
25
|
+
cp ~/.claude/rrr/ohmyposh/rrr-kushal.omp.json ~/.poshthemes/
|
|
26
|
+
|
|
27
|
+
# OR Atomic theme (diamond style)
|
|
28
|
+
cp ~/.claude/rrr/ohmyposh/rrr-atomic.omp.json ~/.poshthemes/
|
|
29
|
+
|
|
30
|
+
# 4. Add to your shell profile
|
|
31
|
+
oh-my-posh --config ~/.poshthemes/rrr-kushal.omp.json # Kushal
|
|
32
|
+
# OR
|
|
33
|
+
oh-my-posh --config ~/.poshthemes/rrr-atomic.omp.json # Atomic
|
|
34
|
+
|
|
35
|
+
# 5. Reload shell
|
|
36
|
+
source ~/.zshrc # or source ~/.bashrc
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
## Files Created
|
|
40
|
+
|
|
41
|
+
| File | Purpose |
|
|
42
|
+
|------|---------|
|
|
43
|
+
| `~/.claude/rrr/hud-state.json` | JSON state file (auto-updated by RRR) |
|
|
44
|
+
| `~/.claude/rrr/ohmyposh/rrr-env.sh` | Shell script to export state as env vars |
|
|
45
|
+
| `~/.claude/rrr/ohmyposh/rrr-kushal.omp.json` | OhMyPosh theme (Kushal style) |
|
|
46
|
+
| `~/.claude/rrr/ohmyposh/rrr-atomic.omp.json` | OhMyPosh theme (Atomic style) |
|
|
47
|
+
| `scripts/rrr-state-manager.js` | CLI to update hud-state.json |
|
|
48
|
+
| `scripts/rrr-hud.js` | Extended with `--persistent` footer mode |
|
|
49
|
+
|
|
50
|
+
## Usage
|
|
51
|
+
|
|
52
|
+
### Terminal Prompt (Kushal Theme)
|
|
53
|
+
|
|
54
|
+
```
|
|
55
|
+
[v1.18] [56-01] [3/5 tasks 60%] [2m30s] $
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
**Kushal colors:**
|
|
59
|
+
- Milestone: Teal `#1BD4CD`
|
|
60
|
+
- Phase: Cyan `#00C7FC`
|
|
61
|
+
- Tasks: Yellow `#FFDE57`
|
|
62
|
+
- Execution time: Gray `#99908A`
|
|
63
|
+
|
|
64
|
+
**Right side:** Exit status (✓ green or ✗ red)
|
|
65
|
+
|
|
66
|
+
### Claude Code Footer
|
|
67
|
+
|
|
68
|
+
The statusline at the bottom of Claude Code shows RRR HUD:
|
|
69
|
+
|
|
70
|
+
```
|
|
71
|
+
[v1.17] [58-01] [1/1 100%] │ Claude 3.5 Sonnet │ projecta-rrr │ ████░░░░░░ 5%
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
### Persistent Footer (Dashboard)
|
|
75
|
+
|
|
76
|
+
Run in a separate terminal pane:
|
|
77
|
+
|
|
78
|
+
```bash
|
|
79
|
+
node scripts/rrr-hud.js --persistent
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
Displays (Kushal style):
|
|
83
|
+
```
|
|
84
|
+
╔══════════════════════════════════════════════════════════════════════╗
|
|
85
|
+
║ RRR HUD | Kushal Theme ║
|
|
86
|
+
╠══════════════════════════════════════════════════════════════════════╣
|
|
87
|
+
║ ║
|
|
88
|
+
║ [v1.17] [58-01] [1/1 ██████████████████████████████ 100%] ║
|
|
89
|
+
║ ⚠ 1 alerts ↑ 0 files → 0 behind ║
|
|
90
|
+
║ ✓ 0/0 (0%) 💾 synced 94.2% hit cmd: setup 5.0s ║
|
|
91
|
+
║ 📁 14363 files 📋 58 phases 📝 143 plans 🎯 10 milestones ║
|
|
92
|
+
║ ║
|
|
93
|
+
║ Next Actions: ║
|
|
94
|
+
║ 1. verify 2. commit 3. push 4. create-plan 5. check-upstream ║
|
|
95
|
+
║ → Recommended: run /rrr:verify ║
|
|
96
|
+
╚══════════════════════════════════════════════════════════════════════╝
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
## Update State Manually
|
|
100
|
+
|
|
101
|
+
```bash
|
|
102
|
+
# Set position
|
|
103
|
+
node scripts/rrr-state-manager.js --set-position v1.18 56 01
|
|
104
|
+
|
|
105
|
+
# Set progress
|
|
106
|
+
node scripts/rrr-state-manager.js --set-progress 3 5
|
|
107
|
+
|
|
108
|
+
# Add alert
|
|
109
|
+
node scripts/rrr-state-manager.js --add-alert "v1.9.12 available" warning
|
|
110
|
+
|
|
111
|
+
# Set drift
|
|
112
|
+
node scripts/rrr-state-manager.js --set-drift 3 "lib/core updated"
|
|
113
|
+
|
|
114
|
+
# Set sync
|
|
115
|
+
node scripts/rrr-state-manager.js --set-sync 2 1
|
|
116
|
+
|
|
117
|
+
# Set tests
|
|
118
|
+
node scripts/rrr-state-manager.js --set-tests 100 100
|
|
119
|
+
|
|
120
|
+
# Set cache
|
|
121
|
+
node scripts/rrr-state-manager.js --set-cache synced --size 2500000 --hit-rate 94.2
|
|
122
|
+
|
|
123
|
+
# Set command result
|
|
124
|
+
node scripts/rrr-state-manager.js --set-command execute --detail "phase 56" --duration 2300 --status success
|
|
125
|
+
|
|
126
|
+
# Get current state
|
|
127
|
+
node scripts/rrr-state-manager.js --get
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
## Integrate with RRR Commands
|
|
131
|
+
|
|
132
|
+
RRR commands automatically update hud-state.json. The OhMyPosh config reads the state via `rrr-env.sh`.
|
|
133
|
+
|
|
134
|
+
To enable automatic env loading, add this to your shell profile **before** the oh-my-posh init:
|
|
135
|
+
|
|
136
|
+
```bash
|
|
137
|
+
# Load RRR state as environment variables
|
|
138
|
+
source ~/.claude/rrr/ohmyposh/rrr-env.sh
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
## Environment Variables
|
|
142
|
+
|
|
143
|
+
The OhMyPosh config reads these variables:
|
|
144
|
+
|
|
145
|
+
| Variable | Description | Example |
|
|
146
|
+
|----------|-------------|---------|
|
|
147
|
+
| `RRR_MILESTONE` | Current milestone | `v1.18` |
|
|
148
|
+
| `RRR_PHASE` | Current phase | `56-01` |
|
|
149
|
+
| `RRR_PLAN` | Current plan | `01` |
|
|
150
|
+
| `RRR_TASKS` | Tasks completed | `3` |
|
|
151
|
+
| `RRR_TASKS_TOTAL` | Total tasks | `5` |
|
|
152
|
+
| `RRR_PROGRESS` | Progress percent | `60` |
|
|
153
|
+
| `RRR_ALERTS_COUNT` | Number of alerts | `2` |
|
|
154
|
+
| `RRR_DRIFT_DETECTED` | Drift status | `true` |
|
|
155
|
+
| `RRR_DRIFT_FILES` | Changed files | `3` |
|
|
156
|
+
| `RRR_SYNC_BEHIND` | Branches behind | `2` |
|
|
157
|
+
| `RRR_SYNC_AHEAD` | Branches ahead | `1` |
|
|
158
|
+
| `RRR_COMMAND_STATUS` | Last command status | `success` |
|
|
159
|
+
|
|
160
|
+
## Tab Title
|
|
161
|
+
|
|
162
|
+
The console title shows: `v1.18 56-01 3/5 ⚠2 ↑3 →2`
|
|
163
|
+
|
|
164
|
+
Format: `milestone phase tasks alerts drift sync`
|
|
165
|
+
|
|
166
|
+
## Troubleshooting
|
|
167
|
+
|
|
168
|
+
### Prompt doesn't show RRR context
|
|
169
|
+
|
|
170
|
+
1. Check if `rrr-env.sh` is sourced in your shell profile
|
|
171
|
+
2. Verify hud-state.json exists: `cat ~/.claude/rrr/hud-state.json`
|
|
172
|
+
3. Check OhMyPosh is using the right config: `oh-my-posh --config ~/.poshthemes/rrr-kushal.omp.json`
|
|
173
|
+
|
|
174
|
+
### Footer not updating
|
|
175
|
+
|
|
176
|
+
1. Run RRR commands to update state
|
|
177
|
+
2. Restart the footer: `node scripts/rrr-hud.js --persistent`
|
|
178
|
+
3. Check file permissions on hud-state.json
|
|
179
|
+
|
|
180
|
+
### Missing jq
|
|
181
|
+
|
|
182
|
+
The `rrr-env.sh` script requires `jq` for JSON parsing:
|
|
183
|
+
|
|
184
|
+
```bash
|
|
185
|
+
brew install jq
|
|
186
|
+
```
|
|
187
|
+
|
|
188
|
+
## Theme Colors
|
|
189
|
+
|
|
190
|
+
### Kushal Theme (Recommended)
|
|
191
|
+
|
|
192
|
+
Based on [Kushal OhMyPosh theme](https://github.com/JanDeDobbeleer/oh-my-posh/blob/main/themes/kushal.omp.json):
|
|
193
|
+
|
|
194
|
+
| Element | Color | Hex |
|
|
195
|
+
|---------|-------|-----|
|
|
196
|
+
| Milestone | Teal | `#1BD4CD` |
|
|
197
|
+
| Phase | Cyan | `#00C7FC` |
|
|
198
|
+
| Tasks | Yellow | `#FFDE57` |
|
|
199
|
+
| Alerts | Red | `#E44141` |
|
|
200
|
+
| Success | Teal-green | `#03DED3` |
|
|
201
|
+
| Sync pending | Yellow | `#FFDE57` |
|
|
202
|
+
| Drift | Orange | `#EF541C` |
|
|
203
|
+
| Path | Light blue | `#B6D6F2` |
|
|
204
|
+
| Execution time | Gray | `#99908A` |
|
|
205
|
+
|
|
206
|
+
### Atomic Theme
|
|
207
|
+
|
|
208
|
+
Based on atomic theme with diamond segments:
|
|
209
|
+
|
|
210
|
+
| Element | Color | Hex |
|
|
211
|
+
|---------|-------|-----|
|
|
212
|
+
| Milestone | Blue | `#0077c2` |
|
|
213
|
+
| Root/Phase | Red | `#ef5350` |
|
|
214
|
+
| Path | Orange | `#FF9248` |
|
|
215
|
+
| Tasks/Progress | Yellow | `#FFFB38` |
|
|
216
|
+
| Execution time | Purple | `#83769c` |
|
|
217
|
+
| Alerts | Red | `#ef5350` |
|
|
218
|
+
| Success | Teal | `#03DED3` |
|
|
219
|
+
| Time | Light blue | `#40c4ff` |
|
|
220
|
+
| Arrow | Cyan | `#21c7c7` |
|
|
221
|
+
|
|
222
|
+
### Setup for Atomic Theme
|
|
223
|
+
|
|
224
|
+
```bash
|
|
225
|
+
# Copy theme to poshthemes
|
|
226
|
+
mkdir -p ~/.poshthemes
|
|
227
|
+
cp ~/.claude/rrr/ohmyposh/rrr-atomic.omp.json ~/.poshthemes/
|
|
228
|
+
|
|
229
|
+
# Add to shell profile (~/.zshrc)
|
|
230
|
+
source ~/.claude/rrr/ohmyposh/rrr-env.sh
|
|
231
|
+
eval "$(oh-my-posh init bash)"
|
|
232
|
+
oh-my-posh --config ~/.poshthemes/rrr-atomic.omp.json
|
|
233
|
+
|
|
234
|
+
# Reload
|
|
235
|
+
source ~/.zshrc
|
|
236
|
+
```
|
|
237
|
+
|
|
238
|
+
### Atomic Theme Preview
|
|
239
|
+
|
|
240
|
+
```
|
|
241
|
+
v1.17 54-01 156 60% 3/5 45s node python ✓ ✓
|
|
242
|
+
✓ $
|
|
243
|
+
```
|
|
244
|
+
|
|
245
|
+
**Left side:** Milestone (blue) → Phase (red) → Files (orange) → Progress (yellow) → Duration (purple)
|
|
246
|
+
**Right side:** Node (green) → Python (blue) → Alerts (red) → Status (teal) → Time (light blue)
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 960 540">
|
|
2
|
+
<defs>
|
|
3
|
+
<style>
|
|
4
|
+
.terminal-bg { fill: #1a1b26; }
|
|
5
|
+
.terminal-border { fill: #24283b; }
|
|
6
|
+
.title-bar { fill: #1f2335; }
|
|
7
|
+
.btn-red { fill: #f7768e; }
|
|
8
|
+
.btn-yellow { fill: #e0af68; }
|
|
9
|
+
.btn-green { fill: #9ece6a; }
|
|
10
|
+
.text { font-family: 'SF Mono', 'Fira Code', 'JetBrains Mono', Consolas, monospace; }
|
|
11
|
+
.prompt { fill: #7aa2f7; }
|
|
12
|
+
.command { fill: #c0caf5; }
|
|
13
|
+
.cyan { fill: #7dcfff; }
|
|
14
|
+
.green { fill: #9ece6a; }
|
|
15
|
+
.yellow { fill: #e0af68; }
|
|
16
|
+
.orange { fill: #ff9e64; }
|
|
17
|
+
.dim { fill: #565f89; }
|
|
18
|
+
.white { fill: #c0caf5; }
|
|
19
|
+
</style>
|
|
20
|
+
</defs>
|
|
21
|
+
|
|
22
|
+
<!-- Window -->
|
|
23
|
+
<rect class="terminal-border" width="960" height="540" rx="12"/>
|
|
24
|
+
<rect class="terminal-bg" x="1" y="1" width="958" height="538" rx="11"/>
|
|
25
|
+
|
|
26
|
+
<!-- Title bar -->
|
|
27
|
+
<rect class="title-bar" x="1" y="1" width="958" height="36" rx="11"/>
|
|
28
|
+
<rect class="terminal-bg" x="1" y="26" width="958" height="12"/>
|
|
29
|
+
|
|
30
|
+
<!-- Window buttons -->
|
|
31
|
+
<circle class="btn-red" cx="24" cy="19" r="7"/>
|
|
32
|
+
<circle class="btn-yellow" cx="48" cy="19" r="7"/>
|
|
33
|
+
<circle class="btn-green" cx="72" cy="19" r="7"/>
|
|
34
|
+
|
|
35
|
+
<!-- Title -->
|
|
36
|
+
<text x="480" y="24" text-anchor="middle" class="text dim" font-size="13">Terminal</text>
|
|
37
|
+
|
|
38
|
+
<!-- Content -->
|
|
39
|
+
<g transform="translate(32, 72)">
|
|
40
|
+
<!-- Prompt line -->
|
|
41
|
+
<text class="text prompt" font-size="15" y="0">~</text>
|
|
42
|
+
<text class="text dim" font-size="15" x="16" y="0">$</text>
|
|
43
|
+
<text class="text command" font-size="15" x="36" y="0">npx projecta-rrr</text>
|
|
44
|
+
|
|
45
|
+
<!-- Banner - RRR in yellow -->
|
|
46
|
+
<text class="text yellow" font-size="14" y="48" xml:space="preserve"> ██████╗ ██████╗ ██████╗ </text>
|
|
47
|
+
<text class="text yellow" font-size="14" y="68" xml:space="preserve"> ██╔══██╗██╔══██╗██╔══██╗</text>
|
|
48
|
+
<text class="text yellow" font-size="14" y="88" xml:space="preserve"> ██████╔╝██████╔╝██████╔╝</text>
|
|
49
|
+
<text class="text yellow" font-size="14" y="108" xml:space="preserve"> ██╔══██╗██╔══██╗██╔══██╗</text>
|
|
50
|
+
<text class="text yellow" font-size="14" y="128" xml:space="preserve"> ██║ ██║██║ ██║██║ ██║</text>
|
|
51
|
+
<text class="text yellow" font-size="14" y="148" xml:space="preserve"> ╚═╝ ╚═╝╚═╝ ╚═╝╚═╝ ╚═╝</text>
|
|
52
|
+
|
|
53
|
+
<!-- Title and subtitle -->
|
|
54
|
+
<text class="text white" font-size="15" y="188"> <tspan class="yellow">RRR</tspan> <tspan class="dim">v1.5.26</tspan></text>
|
|
55
|
+
<text class="text white" font-size="15" y="212"> A meta-prompting, context engineering and spec-driven</text>
|
|
56
|
+
<text class="text white" font-size="15" y="232"> development system for Claude Code by Projecta.ai</text>
|
|
57
|
+
|
|
58
|
+
<!-- Install output -->
|
|
59
|
+
<text class="text" font-size="15" y="280"><tspan class="green"> ✓</tspan><tspan class="white"> Installed commands/rrr</tspan></text>
|
|
60
|
+
<text class="text" font-size="15" y="304"><tspan class="green"> ✓</tspan><tspan class="white"> Installed rrr</tspan></text>
|
|
61
|
+
|
|
62
|
+
<!-- Done message -->
|
|
63
|
+
<text class="text" font-size="15" y="352"><tspan class="green"> Done!</tspan><tspan class="white"> Run </tspan><tspan class="cyan">/rrr:help</tspan><tspan class="white"> to get started.</tspan></text>
|
|
64
|
+
|
|
65
|
+
<!-- New prompt -->
|
|
66
|
+
<text class="text prompt" font-size="15" y="400">~</text>
|
|
67
|
+
<text class="text dim" font-size="15" x="16" y="400">$</text>
|
|
68
|
+
<text class="text white" font-size="15" x="36" y="400">▌</text>
|
|
69
|
+
</g>
|
|
70
|
+
</svg>
|
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# RRR HUD State Sync Hook
|
|
3
|
+
# Syncs hud-state.json from RRR project state on session start
|
|
4
|
+
# Non-blocking, degrades gracefully if RRR project not found
|
|
5
|
+
|
|
6
|
+
set +e
|
|
7
|
+
|
|
8
|
+
CLAUDE_DIR="${HOME}/.claude"
|
|
9
|
+
STATE_DIR="${CLAUDE_DIR}/rrr"
|
|
10
|
+
SCRIPT_DIR="${STATE_DIR}/scripts"
|
|
11
|
+
|
|
12
|
+
# Find RRR project (look for .planning directory)
|
|
13
|
+
find_rrr_project() {
|
|
14
|
+
local dir="${1:-$(pwd)}"
|
|
15
|
+
local max_depth=5
|
|
16
|
+
local depth=0
|
|
17
|
+
|
|
18
|
+
while [ $depth -lt $max_depth ] && [ "$dir" != "/" ]; do
|
|
19
|
+
if [ -d "${dir}/.planning" ]; then
|
|
20
|
+
echo "$dir"
|
|
21
|
+
return 0
|
|
22
|
+
fi
|
|
23
|
+
dir=$(dirname "$dir")
|
|
24
|
+
depth=$((depth + 1))
|
|
25
|
+
done
|
|
26
|
+
|
|
27
|
+
# Also check current directory
|
|
28
|
+
if [ -d "$(pwd)/.planning" ]; then
|
|
29
|
+
echo "$(pwd)"
|
|
30
|
+
return 0
|
|
31
|
+
fi
|
|
32
|
+
|
|
33
|
+
return 1
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
# Sync HUD state using node
|
|
37
|
+
sync_hud_state_node() {
|
|
38
|
+
if [ -f "${SCRIPT_DIR}/rrr-hud-dynamic.js" ]; then
|
|
39
|
+
# Run from RRR project directory
|
|
40
|
+
local project_dir
|
|
41
|
+
project_dir=$(find_rrr_project) || project_dir="${CLAUDE_DIR}"
|
|
42
|
+
|
|
43
|
+
if [ -d "${project_dir}/.planning" ]; then
|
|
44
|
+
node "${SCRIPT_DIR}/rrr-hud-dynamic.js" --sync 2>/dev/null && return 0
|
|
45
|
+
fi
|
|
46
|
+
fi
|
|
47
|
+
return 1
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
# Fallback: Direct state update
|
|
51
|
+
sync_hud_state_fallback() {
|
|
52
|
+
local state_file="${STATE_DIR}/hud-state.json"
|
|
53
|
+
local project_dir
|
|
54
|
+
|
|
55
|
+
project_dir=$(find_rrr_project) || project_dir=""
|
|
56
|
+
|
|
57
|
+
# Create or update state file
|
|
58
|
+
if [ -n "$project_dir" ] && [ -d "${project_dir}/.planning" ]; then
|
|
59
|
+
local milestone=""
|
|
60
|
+
local phase=""
|
|
61
|
+
local progress=0
|
|
62
|
+
|
|
63
|
+
# Extract milestone from ROADMAP.md
|
|
64
|
+
if [ -f "${project_dir}/.planning/ROADMAP.md" ]; then
|
|
65
|
+
milestone=$(grep -E "^## Current Milestone:" "${project_dir}/.planning/ROADMAP.md" 2>/dev/null | sed 's/.*Milestone: *\(v[0-9.]*\).*/\1/' || echo "")
|
|
66
|
+
fi
|
|
67
|
+
|
|
68
|
+
# Find current phase (first incomplete)
|
|
69
|
+
if [ -n "$milestone" ] && [ -d "${project_dir}/.planning/milestones/${milestone}/phases" ]; then
|
|
70
|
+
phase=$(ls "${project_dir}/.planning/milestones/${milestone}/phases" 2>/dev/null | grep -E '^\d' | head -1 || echo "")
|
|
71
|
+
fi
|
|
72
|
+
|
|
73
|
+
# Count plans and summaries for progress
|
|
74
|
+
if [ -n "$milestone" ] && [ -n "$phase" ]; then
|
|
75
|
+
local plans_dir="${project_dir}/.planning/milestones/${milestone}/phases/${phase}"
|
|
76
|
+
if [ -d "$plans_dir" ]; then
|
|
77
|
+
local plans=$(find "$plans_dir" -maxdepth 1 -name "*-PLAN.md" 2>/dev/null | wc -l | tr -d ' ')
|
|
78
|
+
local summaries=$(find "$plans_dir" -maxdepth 1 -name "*-SUMMARY.md" 2>/dev/null | wc -l | tr -d ' ')
|
|
79
|
+
if [ "$plans" -gt 0 ]; then
|
|
80
|
+
progress=$((summaries * 100 / plans))
|
|
81
|
+
fi
|
|
82
|
+
fi
|
|
83
|
+
fi
|
|
84
|
+
|
|
85
|
+
# Write state file
|
|
86
|
+
mkdir -p "${STATE_DIR}"
|
|
87
|
+
cat > "${state_file}" << EOF
|
|
88
|
+
{
|
|
89
|
+
"milestone": "${milestone}",
|
|
90
|
+
"phase": "${phase}",
|
|
91
|
+
"plan": null,
|
|
92
|
+
"status": "active",
|
|
93
|
+
"tasks_completed": 0,
|
|
94
|
+
"tasks_total": 0,
|
|
95
|
+
"progress_percent": ${progress},
|
|
96
|
+
"started_at": "$(date -u +"%Y-%m-%dT%H:%M:%SZ")",
|
|
97
|
+
"session_start": "$(date -u +"%Y-%m-%dT%H:%M:%SZ")",
|
|
98
|
+
"drift": { "detected": false, "files_changed": 0, "details": [] },
|
|
99
|
+
"sync": { "behind": 0, "ahead": 0 },
|
|
100
|
+
"tests": { "passed": 0, "total": 0, "pass_rate": 0 },
|
|
101
|
+
"cache": { "synced": true },
|
|
102
|
+
"command": { "name": "session_start", "status": "success" },
|
|
103
|
+
"scope": { "files": 0, "phases": 0, "plans": 0, "milestones": 0 },
|
|
104
|
+
"last_updated": "$(date -u +"%Y-%m-%dT%H:%M:%SZ")"
|
|
105
|
+
}
|
|
106
|
+
EOF
|
|
107
|
+
return 0
|
|
108
|
+
fi
|
|
109
|
+
return 1
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
# Main sync
|
|
113
|
+
main() {
|
|
114
|
+
# Try node script first
|
|
115
|
+
if ! sync_hud_state_node; then
|
|
116
|
+
# Fallback to direct update
|
|
117
|
+
sync_hud_state_fallback || true
|
|
118
|
+
fi
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
main
|
|
122
|
+
|
|
123
|
+
# Always exit 0 - non-blocking hook
|
|
124
|
+
exit 0
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# RRR HUD State Update Hook
|
|
3
|
+
# Updates hud-state.json with session end information
|
|
4
|
+
# Non-blocking, degrades gracefully if tools are missing
|
|
5
|
+
|
|
6
|
+
set -euo pipefail
|
|
7
|
+
|
|
8
|
+
# Configuration
|
|
9
|
+
CLAUDE_DIR="${HOME}/.claude"
|
|
10
|
+
STATE_DIR="${CLAUDE_DIR}/rrr"
|
|
11
|
+
STATE_FILE="${STATE_DIR}/hud-state.json"
|
|
12
|
+
SCRIPT_DIR="${STATE_DIR}/scripts"
|
|
13
|
+
|
|
14
|
+
# Exit codes (we always exit 0 - this is a non-blocking hook)
|
|
15
|
+
EXIT_CODE=0
|
|
16
|
+
|
|
17
|
+
# Get session end timestamp
|
|
18
|
+
SESSION_END=$(date -u +"%Y-%m-%dT%H:%M:%SZ")
|
|
19
|
+
|
|
20
|
+
# Calculate session duration if we have start time
|
|
21
|
+
SESSION_DURATION=""
|
|
22
|
+
if command -v jq &>/dev/null && [ -f "${STATE_FILE}" ]; then
|
|
23
|
+
SESSION_START=$(jq -r '.session_start // empty' "${STATE_FILE}" 2>/dev/null || echo "")
|
|
24
|
+
if [ -n "${SESSION_START}" ]; then
|
|
25
|
+
# Calculate duration in seconds
|
|
26
|
+
START_EPOCH=$(date -u -d "${SESSION_START}" +%s 2>/dev/null || echo "0")
|
|
27
|
+
END_EPOCH=$(date -u -d "${SESSION_END}" +%s 2>/dev/null || echo "0")
|
|
28
|
+
if [ "${START_EPOCH}" != "0" ] && [ "${END_EPOCH}" != "0" ]; then
|
|
29
|
+
DURATION=$((END_EPOCH - START_EPOCH))
|
|
30
|
+
if [ ${DURATION} -gt 0 ]; then
|
|
31
|
+
if [ ${DURATION} -lt 60 ]; then
|
|
32
|
+
SESSION_DURATION="${DURATION}s"
|
|
33
|
+
elif [ ${DURATION} -lt 3600 ]; then
|
|
34
|
+
SESSION_DURATION="$((DURATION / 60))m ${((DURATION % 60))}s"
|
|
35
|
+
else
|
|
36
|
+
SESSION_DURATION="$((DURATION / 3600))h $(((DURATION % 3600) / 60))m"
|
|
37
|
+
fi
|
|
38
|
+
fi
|
|
39
|
+
fi
|
|
40
|
+
fi
|
|
41
|
+
fi
|
|
42
|
+
|
|
43
|
+
# Update hud-state.json using node if available
|
|
44
|
+
update_state_node() {
|
|
45
|
+
if [ -f "${SCRIPT_DIR}/rrr-state-manager.js" ]; then
|
|
46
|
+
node "${SCRIPT_DIR}/rrr-state-manager.js" --set-status completed --session-end "${SESSION_END}" --duration "${SESSION_DURATION}" 2>/dev/null && return 0
|
|
47
|
+
fi
|
|
48
|
+
return 1
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
# Update hud-state.json using jq fallback
|
|
52
|
+
update_state_jq() {
|
|
53
|
+
if ! command -v jq &>/dev/null; then
|
|
54
|
+
return 1
|
|
55
|
+
fi
|
|
56
|
+
|
|
57
|
+
if [ ! -f "${STATE_FILE}" ]; then
|
|
58
|
+
return 1
|
|
59
|
+
fi
|
|
60
|
+
|
|
61
|
+
# Build jq update expression
|
|
62
|
+
local update_expr=".session_end = \"${SESSION_END}\" | .last_updated = \"${SESSION_END}\""
|
|
63
|
+
|
|
64
|
+
if [ -n "${SESSION_DURATION}" ]; then
|
|
65
|
+
update_expr="${update_expr} | .session_duration = \"${SESSION_DURATION}\""
|
|
66
|
+
fi
|
|
67
|
+
|
|
68
|
+
# Update the file
|
|
69
|
+
local tmp_file
|
|
70
|
+
tmp_file=$(mktemp)
|
|
71
|
+
trap "rm -f ${tmp_file}" EXIT
|
|
72
|
+
|
|
73
|
+
if jq "${update_expr}" "${STATE_FILE}" > "${tmp_file}" 2>/dev/null; then
|
|
74
|
+
mv "${tmp_file}" "${STATE_FILE}"
|
|
75
|
+
chmod 644 "${STATE_FILE}"
|
|
76
|
+
return 0
|
|
77
|
+
fi
|
|
78
|
+
|
|
79
|
+
return 1
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
# Main update logic
|
|
83
|
+
main() {
|
|
84
|
+
# Skip if state file doesn't exist (first run)
|
|
85
|
+
if [ ! -f "${STATE_FILE}" ]; then
|
|
86
|
+
return 0
|
|
87
|
+
fi
|
|
88
|
+
|
|
89
|
+
# Try node first (more robust)
|
|
90
|
+
if ! update_state_node; then
|
|
91
|
+
# Fallback to jq
|
|
92
|
+
update_state_jq || true
|
|
93
|
+
fi
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
# Run main update
|
|
97
|
+
main
|
|
98
|
+
|
|
99
|
+
# Always exit 0 - this is a non-blocking hook
|
|
100
|
+
exit 0
|
package/hooks/statusline.sh
CHANGED
|
@@ -28,19 +28,19 @@ if [ -n "$remaining" ]; then
|
|
|
28
28
|
# Build progress bar (10 segments) - fills as context is consumed
|
|
29
29
|
filled=$((used / 10))
|
|
30
30
|
bar=""
|
|
31
|
-
for ((i=0; i<filled; i++)); do bar+="
|
|
32
|
-
for ((i=filled; i<10; i++)); do bar+="
|
|
31
|
+
for ((i=0; i<filled; i++)); do bar+="#"; done
|
|
32
|
+
for ((i=filled; i<10; i++)); do bar+="-"; done
|
|
33
33
|
|
|
34
34
|
# Color based on usage with blinking skull at 80%+
|
|
35
35
|
if [ "$used" -lt 50 ]; then
|
|
36
|
-
ctx
|
|
36
|
+
ctx=" [$bar $used%]"
|
|
37
37
|
elif [ "$used" -lt 65 ]; then
|
|
38
|
-
ctx
|
|
38
|
+
ctx=" [$bar $used%]"
|
|
39
39
|
elif [ "$used" -lt 80 ]; then
|
|
40
|
-
ctx
|
|
40
|
+
ctx=" [$bar $used%]"
|
|
41
41
|
else
|
|
42
|
-
# Blinking
|
|
43
|
-
ctx
|
|
42
|
+
# Blinking skull at critical
|
|
43
|
+
ctx=" [! $bar $used%!]"
|
|
44
44
|
fi
|
|
45
45
|
fi
|
|
46
46
|
|
|
@@ -63,7 +63,7 @@ fi
|
|
|
63
63
|
# Output
|
|
64
64
|
dirname=$(basename "$dir")
|
|
65
65
|
if [[ -n "$task" ]]; then
|
|
66
|
-
printf '%s
|
|
66
|
+
printf '%s%s | %s | %s%s' "$rrr_update" "$model" "$task" "$dirname" "$ctx"
|
|
67
67
|
else
|
|
68
|
-
printf '%s
|
|
68
|
+
printf '%s%s | %s%s' "$rrr_update" "$model" "$dirname" "$ctx"
|
|
69
69
|
fi
|
package/package.json
CHANGED
|
@@ -1,12 +1,17 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "projecta-rrr",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.17.0",
|
|
4
4
|
"description": "A meta-prompting, context engineering and spec-driven development system for Claude Code by Projecta.ai",
|
|
5
5
|
"bin": {
|
|
6
6
|
"projecta-rrr": "bin/install.js"
|
|
7
7
|
},
|
|
8
8
|
"scripts": {
|
|
9
|
-
"postinstall": "node rrr/scripts/register-mcp.js",
|
|
9
|
+
"postinstall": "node bin/install.js --hud-only --global && node rrr/scripts/register-mcp.js",
|
|
10
|
+
"watch": "node watcher/index.js",
|
|
11
|
+
"watch:verbose": "node watcher/index.js --verbose",
|
|
12
|
+
"watch:claude-code": "node watcher/watchers/claude-code.js --verbose",
|
|
13
|
+
"watch:gsd": "node watcher/watchers/github-release.js --repo=glittercowboy/get-shit-done --verbose",
|
|
14
|
+
"watch:taches": "node watcher/watchers/github-release.js --repo=glittercowboy/taches-cc-resources --verbose",
|
|
10
15
|
"test": "jest",
|
|
11
16
|
"test:vitest": "vitest",
|
|
12
17
|
"test:browser": "vitest --browser",
|
|
@@ -40,6 +45,7 @@
|
|
|
40
45
|
"rrr/package.json",
|
|
41
46
|
"rrr/lib",
|
|
42
47
|
"rrr/mcp-server",
|
|
48
|
+
"rrr/ohmyposh",
|
|
43
49
|
"rrr/presets",
|
|
44
50
|
"rrr/references",
|
|
45
51
|
"rrr/scripts",
|
|
@@ -73,6 +79,7 @@
|
|
|
73
79
|
"@vitest/browser": "^3.0.0",
|
|
74
80
|
"@vitest/ui": "^3.0.0",
|
|
75
81
|
"jest": "^30.2.0",
|
|
82
|
+
"playwright": "^1.58.0",
|
|
76
83
|
"vitest": "^3.0.0"
|
|
77
84
|
},
|
|
78
85
|
"dependencies": {
|