5-phase-workflow 1.8.5 → 1.8.7

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
@@ -130,6 +130,7 @@ All commands are available under the `/5:` namespace:
130
130
  | `/5:review-code` | 5 | AI-powered code review (Claude or CodeRabbit) |
131
131
  | `/5:address-review-findings` | 5 | Apply annotated findings and address PR comments |
132
132
  | `/5:quick-implement` | Fast | Streamlined workflow for small tasks |
133
+ | `/5:eject` | Utility | Permanently remove update infrastructure |
133
134
  | `/5:unlock` | Utility | Remove planning guard lock |
134
135
 
135
136
  ## Configuration
@@ -264,6 +265,7 @@ After installation, your `.claude/` directory will contain:
264
265
  │ ├── discuss-feature.md
265
266
  │ ├── quick-implement.md
266
267
  │ ├── configure.md
268
+ │ ├── eject.md
267
269
  │ └── unlock.md
268
270
  ├── skills/ # Atomic operations
269
271
  │ ├── build-project/
@@ -364,6 +366,21 @@ npx 5-phase-workflow
364
366
  - User-created commands, agents, skills, hooks, and templates are preserved
365
367
  - Only workflow-managed files are updated
366
368
 
369
+ ### Ejecting
370
+
371
+ If you want to permanently opt out of the update system (e.g., to customize workflow files without future updates overwriting them), run:
372
+
373
+ ```bash
374
+ /5:eject
375
+ ```
376
+
377
+ This permanently removes the update infrastructure:
378
+ - Deletes `check-updates.js` hook, `update.md` and `eject.md` commands
379
+ - Deletes `.5/version.json` and `.5/.update-cache.json`
380
+ - Removes the update check hook entry from `.claude/settings.json`
381
+
382
+ All other workflow files remain untouched. **This is irreversible.** To restore update functionality, reinstall with `npx 5-phase-workflow`.
383
+
367
384
  ## Development
368
385
 
369
386
  ### Running Tests
package/bin/install.js CHANGED
@@ -258,7 +258,11 @@ const LEGACY_REMOVED_FILES = [
258
258
  'agents/integration-agent.md',
259
259
  'agents/step-fixer.md',
260
260
  'agents/step-verifier.md',
261
- 'agents/verification-agent.md'
261
+ 'agents/verification-agent.md',
262
+ 'templates/STACK.md',
263
+ 'templates/STRUCTURE.md',
264
+ 'templates/CONVENTIONS.md',
265
+ 'templates/INTEGRATIONS.md'
262
266
  ];
263
267
 
264
268
  // Get list of workflow-owned files/directories (not user-created)
@@ -274,8 +278,6 @@ function getWorkflowManagedFiles() {
274
278
 
275
279
  // Skills: specific skill directories
276
280
  skills: [
277
- 'build-project',
278
- 'run-tests',
279
281
  'configure-project',
280
282
  'generate-readme'
281
283
  ],
@@ -299,10 +301,6 @@ function getWorkflowManagedFiles() {
299
301
  // Project documentation templates
300
302
  'ARCHITECTURE.md',
301
303
  'CONCERNS.md',
302
- 'CONVENTIONS.md',
303
- 'INTEGRATIONS.md',
304
- 'STACK.md',
305
- 'STRUCTURE.md',
306
304
  'TESTING.md',
307
305
  // Workflow output templates
308
306
  'workflow/FEATURE-SPEC.md',
@@ -626,6 +624,7 @@ function showCommandsHelp(isGlobal) {
626
624
  log.info(' /5:address-review-findings - Apply review findings & PR comments');
627
625
  log.info(' /5:configure - Interactive project setup');
628
626
  log.info(' /5:reconfigure - Refresh docs/skills (no Q&A)');
627
+ log.info(' /5:eject - Eject from update mechanism');
629
628
  log.info(' /5:unlock - Remove planning guard lock');
630
629
  log.info('');
631
630
  log.info(`Config file: ${path.join(getDataPath(isGlobal), 'config.json')}`);
@@ -74,7 +74,7 @@ The installer copies workflow files to `.claude/` directory. **It does NOT creat
74
74
  After completing these steps, you have:
75
75
  - `.5/config.json` with your project settings
76
76
  - `CLAUDE.md` with comprehensive project documentation
77
- - `.5/STRUCTURE.md`, `.5/STACK.md`, etc. with modular documentation
77
+ - `.5/ARCHITECTURE.md`, `.5/TESTING.md`, `.5/CONCERNS.md` with focused documentation
78
78
  - Project-specific skills in `.claude/skills/`
79
79
 
80
80
  **Without configuration, workflow commands will fail.**
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "5-phase-workflow",
3
- "version": "1.8.5",
3
+ "version": "1.8.7",
4
4
  "description": "A 5-phase feature development workflow for Claude Code",
5
5
  "bin": {
6
6
  "5-phase-workflow": "bin/install.js"
@@ -296,8 +296,8 @@ If `gh api` is unavailable or fails, log the failure and continue. Do NOT abort
296
296
 
297
297
  After all fixes are applied:
298
298
 
299
- 1. **Build:** Use the `/build-project` skill: `Skill tool: skill="build-project", args="target=compile"`
300
- 2. **Test:** Use the `/run-tests` skill: `Skill tool: skill="run-tests", args="target=all"`
299
+ 1. **Build:** Use the project's build skill (e.g., `run-build`) generated during configure
300
+ 2. **Test:** Use the project's test skill (e.g., `run-tests`) generated during configure
301
301
  3. **Lint:** Check for any lint warnings and errors
302
302
 
303
303
  If build fails:
@@ -312,21 +312,23 @@ Generates CLAUDE.md with codebase analysis and creates project-specific skills.
312
312
  ## Requirements
313
313
 
314
314
  ### Requirement 1: Generate Documentation Files
315
- Analyze the codebase and generate modular documentation:
316
-
317
- **Create separate documentation files in `.5/` folder:**
318
- - `.5/ARCHITECTURE.md` - Architectural patterns and layers
319
- - `.5/STACK.md` - Technology stack and dependencies
320
- - `.5/STRUCTURE.md` - Directory layout and organization
321
- - `.5/CONVENTIONS.md` - Coding standards and patterns
322
- - `.5/TESTING.md` - Test framework and patterns
323
- - `.5/INTEGRATIONS.md` - External services and APIs
324
- - `.5/CONCERNS.md` - Tech debt, bugs, and risks
325
-
326
- **Create CLAUDE.md as navigation hub:**
327
- - Quick reference section with links to all `.5/*.md` files
315
+ Analyze the codebase and generate focused documentation capturing only non-derivable knowledge (skip version numbers, dependency lists, directory layouts, linter configs — Claude Code can look these up directly):
316
+
317
+ **Create documentation files in `.5/` folder:**
318
+ - `.5/ARCHITECTURE.md` - Architecture pattern, layers & data flow, key abstractions, non-obvious conventions, where to add new code
319
+ - `.5/TESTING.md` - Test organization, patterns, mocking approach, gotchas
320
+ - `.5/CONCERNS.md` - Tech debt, known issues, security/integration/performance notes (**only if concerns found — skip file entirely if nothing detected**)
321
+
322
+ **Create CLAUDE.md:**
328
323
  - Project overview and build commands
329
- - "Getting Started" guide with references to appropriate files
324
+ - Links to whichever `.5/` documentation files were created
325
+ - Workflow rules section (verbatim):
326
+ ```
327
+ ## Workflow Rules
328
+ When running `/5:` workflow commands, follow the command instructions exactly as written.
329
+ Do not skip steps, combine phases, or proceed to actions not specified in the current command.
330
+ Each phase produces a specific artifact — do not create artifacts belonging to other phases.
331
+ ```
330
332
  - Mandatory coding guidelines:
331
333
  1. Types should be clear and types should be available when possible
332
334
  2. Use doc (jsdoc, javadoc, pydoc, etc) concisely. No doc is better than meaningless doc
@@ -363,17 +365,13 @@ Only generate rules for patterns that were actually detected:
363
365
 
364
366
  ## Acceptance Criteria
365
367
  - [ ] `.5/` directory created
366
- - [ ] All 7 documentation files exist and are populated:
367
- - [ ] `.5/ARCHITECTURE.md`
368
- - [ ] `.5/STACK.md`
369
- - [ ] `.5/STRUCTURE.md`
370
- - [ ] `.5/CONVENTIONS.md`
371
- - [ ] `.5/TESTING.md`
372
- - [ ] `.5/INTEGRATIONS.md`
373
- - [ ] `.5/CONCERNS.md`
374
- - [ ] `CLAUDE.md` exists with references to `.5/` files
368
+ - [ ] Documentation files exist and contain only non-derivable knowledge:
369
+ - [ ] `.5/ARCHITECTURE.md` — architecture, conventions, where to add code
370
+ - [ ] `.5/TESTING.md` — test patterns and gotchas
371
+ - [ ] `.5/CONCERNS.md` — only if concerns were found (omit if empty)
372
+ - [ ] Empty sections omitted (no "Not detected" / "None found" placeholders)
373
+ - [ ] `CLAUDE.md` exists with references to created `.5/` files
375
374
  - [ ] CLAUDE.md contains 6 coding guidelines
376
- - [ ] No placeholder text like `{YYYY-MM-DD}` remains unfilled
377
375
  - [ ] All specified project-specific skills are generated in `.claude/skills/`
378
376
  - [ ] Generated skills reference actual project conventions
379
377
  - [ ] If CLAUDE.md existed before, user-written sections are preserved
@@ -0,0 +1,91 @@
1
+ ---
2
+ name: 5:eject
3
+ description: Eject from the update mechanism — permanently removes update infrastructure
4
+ allowed-tools: Bash, Read, Edit, AskUserQuestion
5
+ user-invocable: true
6
+ model: haiku
7
+ context: fork
8
+ ---
9
+
10
+ <role>
11
+ You are a Workflow Ejector. You permanently remove the update infrastructure from this installation.
12
+ After ejecting, you are DONE.
13
+ </role>
14
+
15
+ # Eject from Update Mechanism
16
+
17
+ Ejecting permanently removes the update system from this installation. After ejecting:
18
+ - The update check hook (`check-updates.js`) is deleted
19
+ - The update command (`/5:update`) is deleted
20
+ - The eject command (`/5:eject`) is deleted
21
+ - Version tracking (`.5/version.json`) is deleted
22
+ - The update cache (`.5/.update-cache.json`) is deleted
23
+ - The `check-updates.js` hook entry is removed from `.claude/settings.json`
24
+
25
+ All other workflow files (commands, skills, hooks, templates) remain untouched.
26
+
27
+ **This is irreversible.** To restore update functionality, reinstall with `npx 5-phase-workflow`.
28
+
29
+ ## Step 1: Check Current State
30
+
31
+ Read `.5/version.json`. If it doesn't exist, tell the user: "No 5-Phase Workflow installation found (or already ejected)." and stop.
32
+
33
+ Note the `packageVersion` for the confirmation message.
34
+
35
+ ## Step 2: Confirm with User
36
+
37
+ Tell the user what ejecting means:
38
+
39
+ > **Eject from 5-Phase Workflow updates?**
40
+ >
41
+ > This will permanently delete:
42
+ > - `.claude/hooks/check-updates.js` (update check hook)
43
+ > - `.claude/commands/5/update.md` (update command)
44
+ > - `.claude/commands/5/eject.md` (this command)
45
+ > - `.5/version.json` (version tracking)
46
+ > - `.5/.update-cache.json` (update cache)
47
+ >
48
+ > The `check-updates.js` hook entry will also be removed from `.claude/settings.json`.
49
+ >
50
+ > All other workflow files remain untouched. To restore updates later, reinstall with `npx 5-phase-workflow`.
51
+
52
+ Ask: "Proceed with eject?"
53
+
54
+ If the user declines, stop here.
55
+
56
+ ## Step 3: Delete Update Files
57
+
58
+ Run this command to delete the update-related files:
59
+
60
+ ```bash
61
+ rm -f .claude/hooks/check-updates.js .claude/commands/5/update.md .claude/commands/5/eject.md .5/version.json .5/.update-cache.json
62
+ ```
63
+
64
+ ## Step 4: Clean Up settings.json
65
+
66
+ Read `.claude/settings.json`. Remove the hook entry from the `hooks.SessionStart` array where the command is `node .claude/hooks/check-updates.js`.
67
+
68
+ Specifically, find and remove the object in the `SessionStart` array that looks like:
69
+
70
+ ```json
71
+ {
72
+ "matcher": "startup",
73
+ "hooks": [
74
+ {
75
+ "type": "command",
76
+ "command": "node .claude/hooks/check-updates.js",
77
+ "timeout": 10
78
+ }
79
+ ]
80
+ }
81
+ ```
82
+
83
+ If the `SessionStart` array becomes empty after removal, remove the `SessionStart` key entirely. Write the updated settings back.
84
+
85
+ ## Step 5: Confirm
86
+
87
+ Tell the user:
88
+
89
+ > Ejected successfully. Update infrastructure has been removed from this installation (was v{packageVersion}).
90
+ >
91
+ > To restore update functionality, reinstall with: `npx 5-phase-workflow`
@@ -8,24 +8,27 @@ context: fork
8
8
  ---
9
9
 
10
10
  <role>
11
- You are a Feature Planner. Your only output is a feature specification file.
12
- You do NOT implement code. You write NO code. You spawn ONLY Explore agents (subagent_type=Explore).
13
- You write ONLY to .5/.planning-active and .5/features/{name}/feature.md.
14
- After creating the spec, you are DONE. Do not continue into implementation planning or coding.
11
+ You are a Feature Planner. Your ONLY deliverable is a feature specification file (feature.md).
12
+ You do NOT implement code. You do NOT create implementation plans. You spawn ONLY Explore agents (subagent_type=Explore).
13
+ You write ONLY to .5/.planning-active, .5/features/{name}/codebase-scan.md, and .5/features/{name}/feature.md.
14
+ After creating the spec, you are FINISHED. You do not continue. You do not offer to continue.
15
15
  </role>
16
16
 
17
17
  <constraints>
18
18
  HARD CONSTRAINTS — violations waste tokens and get blocked by plan-guard:
19
19
  - NEVER write code, pseudo-code, or implementation snippets in any output
20
20
  - NEVER describe HOW something will be implemented (file contents, signatures, class structures)
21
+ - NEVER create an implementation plan, file list, component breakdown, or step-by-step build guide — that is Phase 2's job
22
+ - NEVER suggest "shall I continue with implementation planning?" or "let me create the plan" — you are DONE after feature.md
23
+ - NEVER offer to proceed to the next phase — the user will invoke `/5:plan-implementation` themselves
21
24
  - NEVER spawn Task agents with subagent_type other than Explore
22
- - NEVER write to any file except .5/features/{name}/feature.md (where {name} may include a ticket prefix) and .5/.planning-active
25
+ - NEVER write to any file except .5/.planning-active, .5/features/{name}/codebase-scan.md, and .5/features/{name}/feature.md
23
26
  - NEVER call EnterPlanMode — the workflow has its own planning process
24
27
  - NEVER use Bash to create, write, or modify files — this bypasses the plan-guard and is a constraint violation
25
- - NEVER continue past the completion message — when you output "Feature spec created at...", you are DONE
28
+ - NEVER continue past the completion message — when you output "Feature spec created at...", you are FINISHED
26
29
  - The feature spec describes WHAT and WHY, never HOW
27
- - If you feel the urge to implement, STOP and ask a clarifying question instead
28
- - Your output is a SPECIFICATION, not a design document. No code. No file layouts. No API shapes.
30
+ - If you feel the urge to plan implementation or write code, STOP ask a clarifying question instead
31
+ - Your output is a SPECIFICATION, not a design document. No code. No file layouts. No API shapes. No implementation plans.
29
32
  </constraints>
30
33
 
31
34
  <write-rules>
@@ -195,24 +198,23 @@ Populate all sections:
195
198
  - **[DEFERRED]**: The user explicitly said "not now", "later", "skip this" → planner MUST NOT include in the plan
196
199
  - When in doubt, label as **[DECIDED]** — it's safer to honor a decision than to override it
197
200
 
198
- ## PLANNING COMPLETE
201
+ ## PLANNING COMPLETE — MANDATORY STOP
199
202
 
200
- After writing feature.md, output exactly:
203
+ After writing feature.md, output ONLY this message — no additional text, no suggestions, no offers to continue:
201
204
 
202
205
  ```
203
- Feature spec created at `.5/features/{name}/feature.md`
206
+ Feature spec created at `.5/features/{name}/feature.md`
204
207
 
205
- Next steps:
206
- 1. Review the feature spec
207
- 2. If changes needed: /5:discuss-feature {name}
208
- 3. If approved: /clear then /5:plan-implementation {name}
208
+ To review or refine: /5:discuss-feature {name}
209
+ To proceed: /clear /5:plan-implementation {name}
209
210
  ```
210
211
 
211
- STOP. You are a planner. Your job is done. Do not implement.
212
+ **YOU ARE NOW FINISHED.** This is a hard stop. Do not:
213
+ - Suggest next steps beyond the message above
214
+ - Offer to create an implementation plan
215
+ - Offer to continue with any phase
216
+ - Write any additional files
217
+ - Provide a summary of what could be implemented
218
+ - Ask "shall I proceed with..." or "would you like me to..."
212
219
 
213
- <constraints>
214
- REMINDER: You are a Feature Planner. You wrote a specification. You did NOT implement.
215
- If you wrote any code, file paths to create, class names, or function signatures in feature.md,
216
- you have violated your role.
217
- The feature spec contains WHAT and WHY. Phase 2 handles WHERE. Phase 3 handles HOW.
218
- </constraints>
220
+ If the user asks you to continue or implement, respond: "Phase 1 is complete. Please run `/5:plan-implementation {name}` to continue."
@@ -117,7 +117,7 @@ Use the existing skills in `.claude/skills/` (from Step 2e) as the source of tru
117
117
 
118
118
  Use `AskUserQuestion` to show a summary and get confirmation. Present:
119
119
 
120
- 1. **Documentation files that will be rewritten** — list all 7 `.5/*.md` files + CLAUDE.md
120
+ 1. **Documentation files that will be rewritten** — list `.5/ARCHITECTURE.md`, `.5/TESTING.md`, `.5/CONCERNS.md` (conditional) + CLAUDE.md
121
121
  2. **Skills that will be refreshed** — list ALL skills found in `.claude/skills/` (both workflow-generated and user-created)
122
122
  3. **Rules that will be refreshed** (if rules enabled) — list workflow-generated rule files in `.claude/rules/`
123
123
  4. **New patterns detected** (if any) — "These patterns were found in your codebase but don't have skills yet: [list]. Create skills for them?"
@@ -152,14 +152,16 @@ Refresh rules in .claude/rules/ (if rules.generate is true):
152
152
  - New rules to create: [if applicable]
153
153
 
154
154
  Re-analyze the entire codebase (A1 analysis) and:
155
- 1. Rewrite all 7 .5/*.md documentation files
156
- 2. Update CLAUDE.md (preserve user-written sections)
157
- 3. Refresh ALL skills in .claude/skills/ read current conventions from codebase and update each skill
158
- 4. Create new skills for newly-added patterns
159
- 5. Remove skills the user chose to drop
160
- 6. Refresh all workflow-generated rule files in .claude/rules/ with updated conventions
161
- 7. Create new rule files for newly-detected patterns
162
- 8. Remove rule files the user chose to drop"
155
+ 1. Rewrite .5/ARCHITECTURE.md and .5/TESTING.md
156
+ 2. Rewrite .5/CONCERNS.md (or delete if no concerns found)
157
+ 3. Delete legacy docs if they exist: .5/STACK.md, .5/STRUCTURE.md, .5/CONVENTIONS.md, .5/INTEGRATIONS.md
158
+ 4. Update CLAUDE.md (preserve user-written sections)
159
+ 5. Refresh ALL skills in .claude/skills/ read current conventions from codebase and update each skill
160
+ 6. Create new skills for newly-added patterns
161
+ 7. Remove skills the user chose to drop
162
+ 8. Refresh all workflow-generated rule files in .claude/rules/ with updated conventions
163
+ 9. Create new rule files for newly-detected patterns
164
+ 10. Remove rule files the user chose to drop"
163
165
  ```
164
166
 
165
167
  Use `subagent_type: "general-purpose"` for the Task.
@@ -99,9 +99,15 @@ process.stdin.on('end', () => {
99
99
 
100
100
  if (toolName === 'Write' || toolName === 'Edit') {
101
101
  const filePath = toolInput.file_path || '';
102
- if (filePath && !isInsideDotFive(filePath, workspaceDir)) {
102
+ if (!filePath) {
103
+ process.exit(0);
104
+ }
105
+
106
+ const phase = getPlanningPhase(workspaceDir);
107
+
108
+ // First check: block anything outside .5/
109
+ if (!isInsideDotFive(filePath, workspaceDir)) {
103
110
  const blockCount = incrementBlockCount(workspaceDir);
104
- const phase = getPlanningPhase(workspaceDir);
105
111
  const isSourceFile = !filePath.includes('.5/') && !filePath.includes('.claude/');
106
112
  const escalation = blockCount >= 3
107
113
  ? ` CRITICAL: Block #${blockCount}. You have attempted to write source files ${blockCount} times. You are a PLANNER, not an implementer. Writing source code is Phase 3's job. Return to your Progress Checklist, finish your planning artifact, and STOP.`
@@ -118,6 +124,22 @@ process.stdin.on('end', () => {
118
124
  );
119
125
  process.exit(2);
120
126
  }
127
+
128
+ // Second check: during plan-feature, only allow specific files
129
+ if (phase === 'plan-feature' && !isAllowedPlanFeatureFile(filePath, workspaceDir)) {
130
+ const blockCount = incrementBlockCount(workspaceDir);
131
+ const escalation = blockCount >= 3
132
+ ? ` CRITICAL: Block #${blockCount}. You are attempting to create implementation artifacts during Phase 1. Phase 1 ONLY produces feature.md. STOP and output your completion message.`
133
+ : '';
134
+ process.stderr.write(
135
+ `BLOCKED: During plan-feature (Phase 1), you may only write to .planning-active, codebase-scan.md, and feature.md. ` +
136
+ `Attempted: "${filePath}". ` +
137
+ `You are creating implementation artifacts (e.g., plan.md) which belongs to Phase 2. ` +
138
+ `REDIRECT: If you have already written feature.md, output the completion message and STOP. ` +
139
+ `Do NOT create implementation plans, file lists, or any other artifacts.${escalation}`
140
+ );
141
+ process.exit(2);
142
+ }
121
143
  }
122
144
 
123
145
  process.exit(0);
@@ -127,6 +149,23 @@ process.stdin.on('end', () => {
127
149
  }
128
150
  });
129
151
 
152
+ function isAllowedPlanFeatureFile(filePath, workspaceDir) {
153
+ const resolved = path.resolve(workspaceDir, filePath);
154
+ const dotFiveDir = path.join(workspaceDir, '.5');
155
+
156
+ // Allow .5/.planning-active
157
+ if (resolved === path.join(dotFiveDir, '.planning-active')) return true;
158
+
159
+ // Allow .5/features/{name}/feature.md and .5/features/{name}/codebase-scan.md
160
+ const featuresDir = path.join(dotFiveDir, 'features');
161
+ if (resolved.startsWith(featuresDir + path.sep)) {
162
+ const basename = path.basename(resolved);
163
+ if (basename === 'feature.md' || basename === 'codebase-scan.md') return true;
164
+ }
165
+
166
+ return false;
167
+ }
168
+
130
169
  function isInsideDotFive(filePath, workspaceDir) {
131
170
  const resolved = path.resolve(workspaceDir, filePath);
132
171
  const dotFiveDir = path.join(workspaceDir, '.5');
@@ -1,10 +1,10 @@
1
1
  #!/usr/bin/env node
2
2
  // Claude Code Statusline
3
- // Shows: model | directory | context usage
3
+ // Shows: model | folder | branch | off-peak | 5hr-usage | cost | context | reset-time
4
4
 
5
5
  const fs = require('fs');
6
6
  const path = require('path');
7
- const os = require('os');
7
+ const { execSync } = require('child_process');
8
8
 
9
9
  // Read JSON from stdin
10
10
  let input = '';
@@ -13,77 +13,116 @@ process.stdin.on('data', chunk => input += chunk);
13
13
  process.stdin.on('end', () => {
14
14
  try {
15
15
  const data = JSON.parse(input);
16
+ const parts = [];
17
+
18
+ // 🤖 Model
16
19
  const model = data.model?.display_name || 'Claude';
20
+ parts.push(`\x1b[36m🤖 ${model}\x1b[0m`);
21
+
22
+ // 📁 Folder (basename only)
17
23
  const dir = data.workspace?.current_dir || process.cwd();
18
- const session = data.session_id || '';
19
- const remaining = data.context_window?.remaining_percentage;
24
+ const folderName = path.basename(dir);
25
+ parts.push(`\x1b[90m📁 ${folderName}\x1b[0m`);
20
26
 
21
- // Context window display (shows USED percentage)
22
- let ctx = '';
23
- if (remaining != null) {
24
- const rem = Math.round(remaining);
25
- const used = Math.max(0, Math.min(100, 100 - rem));
27
+ // 🌿 Branch
28
+ let branch = data.worktree?.branch || '';
29
+ if (!branch) {
30
+ try {
31
+ branch = execSync('git rev-parse --abbrev-ref HEAD', {
32
+ encoding: 'utf8', cwd: dir, stdio: ['pipe', 'pipe', 'pipe']
33
+ }).trim();
34
+ } catch (e) { branch = ''; }
35
+ }
36
+ if (branch && branch !== 'HEAD') {
37
+ parts.push(`\x1b[32m🌿 ${branch}\x1b[0m`);
38
+ }
26
39
 
27
- // Build progress bar (10 segments)
40
+ // 🚀 Off-peak indicator (weekdays before 5 AM or after 11 AM PT; all weekends)
41
+ // PT = UTC-8 (PST) or UTC-7 (PDT). Use UTC-7 as approximation (covers PDT/PST conservatively).
42
+ const nowUtc = new Date();
43
+ const ptHour = (nowUtc.getUTCHours() - 7 + 24) % 24; // approximate PT
44
+ const ptDay = new Date(nowUtc.getTime() - 7 * 3600 * 1000).getUTCDay(); // 0=Sun,6=Sat
45
+ const isWeekend = ptDay === 0 || ptDay === 6;
46
+ const isPeak = !isWeekend && ptHour >= 5 && ptHour < 11;
47
+ if (!isPeak) {
48
+ parts.push('\x1b[32m🚀 off-peak\x1b[0m');
49
+ }
50
+
51
+ // ⚡ 5-hour session usage
52
+ const fiveHrUsed = data.rate_limits?.five_hour?.used_percentage;
53
+ if (fiveHrUsed != null) {
54
+ const pct = Math.round(fiveHrUsed);
55
+ const color = pct < 50 ? '\x1b[32m' : pct < 75 ? '\x1b[33m' : '\x1b[31m';
56
+ parts.push(`${color}⚡ ${pct}%\x1b[0m`);
57
+ }
58
+
59
+ // 💰 Cost
60
+ const costUsd = data.cost?.total_cost_usd;
61
+ if (costUsd != null) {
62
+ const fmt = costUsd < 0.01 ? costUsd.toFixed(3) : costUsd.toFixed(2);
63
+ parts.push(`\x1b[33m💰 $${fmt}\x1b[0m`);
64
+ }
65
+
66
+ // 📊 Context window (progress bar)
67
+ const ctxUsed = data.context_window?.used_percentage;
68
+ const ctxRemaining = data.context_window?.remaining_percentage;
69
+ if (ctxUsed != null || ctxRemaining != null) {
70
+ const used = ctxUsed != null
71
+ ? Math.round(ctxUsed)
72
+ : Math.max(0, Math.min(100, 100 - Math.round(ctxRemaining)));
28
73
  const filled = Math.floor(used / 10);
29
74
  const bar = '█'.repeat(filled) + '░'.repeat(10 - filled);
75
+ let color;
76
+ if (used < 50) color = '\x1b[32m';
77
+ else if (used < 65) color = '\x1b[33m';
78
+ else if (used < 80) color = '\x1b[38;5;208m';
79
+ else color = '\x1b[5;31m';
80
+ parts.push(`${color}🧠 ${bar} ${used}%\x1b[0m`);
81
+ }
30
82
 
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`;
83
+ // Reset time (time until 5hr window resets)
84
+ const resetAt = data.rate_limits?.five_hour?.resets_at;
85
+ if (resetAt) {
86
+ const remaining = resetAt - Math.floor(Date.now() / 1000);
87
+ if (remaining > 0) {
88
+ const h = Math.floor(remaining / 3600);
89
+ const m = Math.floor((remaining % 3600) / 60);
90
+ const label = h > 0 ? `${h}h${m}m` : `${m}m`;
91
+ parts.push(`\x1b[90m⏱ ${label}\x1b[0m`);
40
92
  }
41
93
  }
42
94
 
43
- // Shorten directory path for display
44
- const shortDir = dir.replace(os.homedir(), '~');
45
-
46
- // Check for available update and reconfigure reminder
47
- let updateIndicator = '';
48
- let reconfigIndicator = '';
95
+ // Update and reconfigure indicators
49
96
  try {
50
97
  const versionFile = path.join(dir, '.5', 'version.json');
51
98
  const versionData = JSON.parse(fs.readFileSync(versionFile, 'utf8'));
52
99
 
53
- // Update check — read latestAvailableVersion from cache file (gitignored)
54
100
  const cacheFile = path.join(dir, '.5', '.update-cache.json');
55
101
  let latest = null;
56
102
  if (fs.existsSync(cacheFile)) {
57
103
  try {
58
104
  const cache = JSON.parse(fs.readFileSync(cacheFile, 'utf8'));
59
105
  latest = cache.latestAvailableVersion || null;
60
- } catch(e) {}
106
+ } catch (e) {}
61
107
  }
62
- const installed = versionData.packageVersion;
63
- if (latest && installed && compareVersions(installed, latest) < 0) {
64
- updateIndicator = ` | \x1b[33m↑${latest} → /5:update\x1b[0m`;
108
+ if (latest && versionData.packageVersion && compareVersions(versionData.packageVersion, latest) < 0) {
109
+ parts.push(`\x1b[33m↑${latest} /5:update\x1b[0m`);
65
110
  }
66
111
 
67
- // Reconfigure check (reads flag file in .5/, gitignored)
68
112
  const flagFile = path.join(dir, '.5', '.reconfig-reminder');
69
113
  if (fs.existsSync(flagFile)) {
70
- reconfigIndicator = ` | \x1b[35m↻ /5:reconfigure\x1b[0m`;
114
+ parts.push(`\x1b[35m↻ /5:reconfigure\x1b[0m`);
71
115
  }
72
- } catch (e) {
73
- // No version file or parse error — no indicator
74
- }
116
+ } catch (e) {}
75
117
 
76
- // Build and output statusline: model | directory | context | update | reconfig
77
- const statusline = `\x1b[36m${model}\x1b[0m | \x1b[90m${shortDir}\x1b[0m${ctx}${updateIndicator}${reconfigIndicator}`;
78
- process.stdout.write(statusline);
118
+ process.stdout.write(parts.join(' | '));
79
119
 
80
120
  } catch (e) {
81
- // Silent fail - don't break statusline on parse errors
121
+ // Silent fail don't break statusline on parse errors
82
122
  }
83
123
  });
84
124
 
85
125
  // Compare semver versions: returns -1 if v1 < v2, 0 if equal, 1 if v1 > v2
86
- // Uses parseInt to handle pre-release tags (e.g., "2-beta" → 2)
87
126
  function compareVersions(v1, v2) {
88
127
  const parts1 = v1.split('.').map(p => parseInt(p, 10) || 0);
89
128
  const parts2 = v2.split('.').map(p => parseInt(p, 10) || 0);
@@ -92,4 +131,4 @@ function compareVersions(v1, v2) {
92
131
  if (parts1[i] < parts2[i]) return -1;
93
132
  }
94
133
  return 0;
95
- }
134
+ }