flow-cc 0.1.0 → 0.2.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/CHANGELOG.md +44 -0
- package/CONTRIBUTING.md +59 -0
- package/LICENSE +21 -0
- package/README.md +107 -41
- package/VERSION +1 -1
- package/bin/install.js +251 -61
- package/hooks/flow-check-update.js +80 -33
- package/hooks/flow-statusline.js +30 -3
- package/package.json +28 -3
- package/skills/flow-done.md +2 -0
- package/skills/flow-spec.md +3 -2
- package/skills/flow-update.md +11 -2
- package/templates/lessons.md.template +10 -0
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes to this project will be documented in this file.
|
|
4
|
+
|
|
5
|
+
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
|
|
6
|
+
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
|
+
|
|
8
|
+
## [0.2.0] - 2026-02-11
|
|
9
|
+
|
|
10
|
+
### Added
|
|
11
|
+
- `CHANGELOG.md` in Keep a Changelog format
|
|
12
|
+
- `CONTRIBUTING.md` with skill file format docs and testing expectations
|
|
13
|
+
- Example lesson in `templates/lessons.md.template` showing PATTERN/CAUSE/FIX/RULE format
|
|
14
|
+
- Node.js version check (requires >= 18) with clear error message
|
|
15
|
+
- Write permission check before install starts
|
|
16
|
+
- Rollback on install failure — tracks created files and cleans up
|
|
17
|
+
- Post-install verification — checks key files exist after copy
|
|
18
|
+
- `--verify` flag for install health check without modifying anything
|
|
19
|
+
- `engines` field in package.json (`node >= 18`)
|
|
20
|
+
- Error logging for hooks — writes to `~/.claude/hooks/flow-error.log` (capped at 50KB)
|
|
21
|
+
- Context size limits in `/flow:spec` — caps codebase scan at 50 files, focused mode for 500+ file repos
|
|
22
|
+
|
|
23
|
+
### Fixed
|
|
24
|
+
- `.gitignore` now has proper Node.js entries (was just `nul`)
|
|
25
|
+
- `/flow:done` archive step now creates `.planning/archive/` if missing and skips gracefully when no `.planning/` exists
|
|
26
|
+
- `/flow:update` now shows changelog for the new version before confirming update
|
|
27
|
+
|
|
28
|
+
## [0.1.1] - 2025-05-01
|
|
29
|
+
|
|
30
|
+
### Changed
|
|
31
|
+
- Updated package.json metadata (description, keywords, repository links)
|
|
32
|
+
- Polished README with badges and install instructions
|
|
33
|
+
- Added MIT license file
|
|
34
|
+
|
|
35
|
+
## [0.1.0] - 2025-05-01
|
|
36
|
+
|
|
37
|
+
### Added
|
|
38
|
+
- Initial release of Flow plugin for Claude Code
|
|
39
|
+
- 8 skills: init, spec, go, done, status, task, intro, update
|
|
40
|
+
- 2 hooks: statusline display, background update checker
|
|
41
|
+
- 4 templates: CLAUDE.md, STATE.md, ROADMAP.md, lessons.md
|
|
42
|
+
- One-command installer via `npx flow-cc`
|
|
43
|
+
- Automatic statusLine configuration
|
|
44
|
+
- Uninstall support via `npx flow-cc --uninstall`
|
package/CONTRIBUTING.md
ADDED
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
# Contributing to Flow
|
|
2
|
+
|
|
3
|
+
Thanks for your interest in contributing! Flow is a structured workflow system for Claude Code, and contributions are welcome.
|
|
4
|
+
|
|
5
|
+
## Reporting Bugs
|
|
6
|
+
|
|
7
|
+
Open an issue at [github.com/troyhoffman-oss/flow-plugin/issues](https://github.com/troyhoffman-oss/flow-plugin/issues) with:
|
|
8
|
+
|
|
9
|
+
- Steps to reproduce
|
|
10
|
+
- Expected vs. actual behavior
|
|
11
|
+
- Your OS and Node.js version
|
|
12
|
+
- Claude Code version (if relevant)
|
|
13
|
+
|
|
14
|
+
## Suggesting Features
|
|
15
|
+
|
|
16
|
+
Open an issue with the `enhancement` label. Describe:
|
|
17
|
+
|
|
18
|
+
- The problem you're trying to solve
|
|
19
|
+
- Your proposed solution
|
|
20
|
+
- Any alternatives you've considered
|
|
21
|
+
|
|
22
|
+
## Submitting Pull Requests
|
|
23
|
+
|
|
24
|
+
1. Fork the repo and create a branch from `master`
|
|
25
|
+
2. Make your changes
|
|
26
|
+
3. Test the installer: `node bin/install.js` from the repo root
|
|
27
|
+
4. Verify skills load in Claude Code (run `/flow:intro`)
|
|
28
|
+
5. Open a PR with a clear description of what changed and why
|
|
29
|
+
|
|
30
|
+
### Skill File Format
|
|
31
|
+
|
|
32
|
+
Skills live in `skills/` as Markdown files with YAML frontmatter:
|
|
33
|
+
|
|
34
|
+
```markdown
|
|
35
|
+
---
|
|
36
|
+
name: flow:example
|
|
37
|
+
description: One-line description
|
|
38
|
+
user_invocable: true
|
|
39
|
+
---
|
|
40
|
+
|
|
41
|
+
# /flow:example — Title
|
|
42
|
+
|
|
43
|
+
Instructions for Claude Code to follow when this skill is invoked.
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
### Testing Expectations
|
|
47
|
+
|
|
48
|
+
- Run `node bin/install.js` and verify all files land in `~/.claude/`
|
|
49
|
+
- Run `node bin/install.js --uninstall` and verify clean removal
|
|
50
|
+
- Run `node bin/install.js --verify` to check install health
|
|
51
|
+
- Test on both Windows and macOS/Linux if possible
|
|
52
|
+
|
|
53
|
+
## Architecture
|
|
54
|
+
|
|
55
|
+
See [DESIGN.md](DESIGN.md) for architecture decisions and system design.
|
|
56
|
+
|
|
57
|
+
## Code of Conduct
|
|
58
|
+
|
|
59
|
+
Be kind, constructive, and respectful. We're all here to build better tools.
|
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025 Troy Hoffman
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
CHANGED
|
@@ -1,66 +1,132 @@
|
|
|
1
|
-
|
|
1
|
+
<p align="center">
|
|
2
|
+
<h1 align="center">Flow</h1>
|
|
3
|
+
<p align="center">A structured workflow system for Claude Code.<br/>Spec interviews. Agent-team execution. Session handoffs. Compounding knowledge.</p>
|
|
4
|
+
</p>
|
|
2
5
|
|
|
3
|
-
|
|
6
|
+
<p align="center">
|
|
7
|
+
<a href="https://www.npmjs.com/package/flow-cc"><img src="https://img.shields.io/npm/v/flow-cc.svg" alt="npm version"></a>
|
|
8
|
+
<a href="https://github.com/troyhoffman-oss/flow-plugin/blob/master/LICENSE"><img src="https://img.shields.io/npm/l/flow-cc.svg" alt="license"></a>
|
|
9
|
+
<a href="https://www.npmjs.com/package/flow-cc"><img src="https://img.shields.io/npm/dm/flow-cc.svg" alt="downloads"></a>
|
|
10
|
+
</p>
|
|
4
11
|
|
|
5
|
-
|
|
12
|
+
---
|
|
6
13
|
|
|
7
|
-
|
|
8
|
-
- `/flow:init` -- Initialize a new project or milestone with planning scaffolding
|
|
9
|
-
- `/flow:spec` -- Run a spec interview that produces an executable PRD with wave-based phases
|
|
10
|
-
- `/flow:task` -- Lightweight task execution — bug fixes, cleanup, small features without a PRD
|
|
11
|
-
- `/flow:go` -- Execute the next phase from the PRD using agent teams
|
|
12
|
-
- `/flow:done` -- Session-end docs, lessons refinement, and handoff prompt generation
|
|
13
|
-
- `/flow:status` -- Quick "where am I?" orientation
|
|
14
|
-
- `/flow:update` -- Pull latest and re-install skills from any session
|
|
15
|
-
|
|
16
|
-
## Installation
|
|
14
|
+
## Install
|
|
17
15
|
|
|
18
16
|
```bash
|
|
19
|
-
|
|
20
|
-
git clone https://github.com/troyhoffman/flow-plugin.git && cd flow-plugin && bash setup.sh
|
|
21
|
-
|
|
22
|
-
# Windows (PowerShell)
|
|
23
|
-
git clone https://github.com/troyhoffman/flow-plugin.git; cd flow-plugin; .\setup.ps1
|
|
17
|
+
npx flow-cc
|
|
24
18
|
```
|
|
25
19
|
|
|
26
|
-
|
|
20
|
+
One command. Installs skills, hooks, templates, and configures your statusLine. Works on Mac, Linux, and Windows.
|
|
21
|
+
|
|
22
|
+
## Why Flow?
|
|
23
|
+
|
|
24
|
+
Claude Code is powerful but unstructured. Without a system, you lose context between sessions, repeat mistakes, and waste tokens re-explaining what you've already decided.
|
|
25
|
+
|
|
26
|
+
Flow fixes this by giving Claude Code a **memory system and execution framework**:
|
|
27
27
|
|
|
28
|
-
|
|
28
|
+
- **Spec interviews** extract decisions upfront so agents execute instead of guessing
|
|
29
|
+
- **PRDs become execution contracts** that agent teams follow phase-by-phase
|
|
30
|
+
- **Session handoffs** preserve context across fresh sessions — no more "where was I?"
|
|
31
|
+
- **Lessons compound** — mistakes get captured, refined, and promoted into permanent rules
|
|
29
32
|
|
|
30
|
-
|
|
33
|
+
## Commands
|
|
34
|
+
|
|
35
|
+
| Command | What it does |
|
|
36
|
+
|---|---|
|
|
37
|
+
| `/flow:intro` | Walkthrough of the system — **start here** |
|
|
38
|
+
| `/flow:init` | Initialize a project with `.planning/` scaffolding, CLAUDE.md, templates |
|
|
39
|
+
| `/flow:spec` | Spec interview that produces an executable PRD with phased execution plan |
|
|
40
|
+
| `/flow:go` | Execute the next phase from the PRD using wave-based agent teams |
|
|
41
|
+
| `/flow:task` | Bug fixes, cleanup, small features — no PRD needed |
|
|
42
|
+
| `/flow:done` | Session-end documentation, lessons refinement, handoff prompt |
|
|
43
|
+
| `/flow:status` | Quick orientation — current milestone, phase progress, next actions |
|
|
44
|
+
| `/flow:update` | Update Flow to the latest version |
|
|
31
45
|
|
|
32
46
|
## How It Works
|
|
33
47
|
|
|
34
|
-
|
|
48
|
+
```
|
|
49
|
+
/flow:init → /flow:spec → /flow:go (repeat per phase) → /flow:done
|
|
50
|
+
↓
|
|
51
|
+
handoff prompt for next session
|
|
52
|
+
|
|
53
|
+
/flow:task ← standalone path for bug fixes and small features
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
**The lifecycle in practice:**
|
|
35
57
|
|
|
36
|
-
1.
|
|
37
|
-
2.
|
|
38
|
-
3.
|
|
39
|
-
4.
|
|
40
|
-
5.
|
|
41
|
-
6. `/flow:status` -- Read-only orientation check
|
|
58
|
+
1. **`/flow:init`** — Creates `.planning/` directory, CLAUDE.md, STATE.md, ROADMAP.md, lessons.md
|
|
59
|
+
2. **`/flow:spec`** — Interviews you about the milestone. Produces a PRD with wave-based phases, acceptance criteria, and agent-team structure
|
|
60
|
+
3. **`/flow:go`** — Reads the PRD, spawns parallel agent teams per wave, builds, verifies, commits
|
|
61
|
+
4. **`/flow:done`** — Updates all planning docs, captures lessons, generates a one-line handoff prompt so the next session starts instantly
|
|
62
|
+
5. **Repeat** — Next session picks up from the handoff. Context lives in the repo, not the conversation.
|
|
42
63
|
|
|
43
|
-
##
|
|
64
|
+
## What Gets Installed
|
|
44
65
|
|
|
45
66
|
```
|
|
46
|
-
/
|
|
47
|
-
|
|
48
|
-
|
|
67
|
+
~/.claude/
|
|
68
|
+
├── commands/flow/
|
|
69
|
+
│ ├── flow-init.md # 8 skill files
|
|
70
|
+
│ ├── flow-spec.md
|
|
71
|
+
│ ├── flow-go.md
|
|
72
|
+
│ ├── flow-task.md
|
|
73
|
+
│ ├── flow-done.md
|
|
74
|
+
│ ├── flow-status.md
|
|
75
|
+
│ ├── flow-intro.md
|
|
76
|
+
│ ├── flow-update.md
|
|
77
|
+
│ ├── VERSION
|
|
78
|
+
│ └── templates/ # Project scaffolding templates
|
|
79
|
+
│ ├── CLAUDE.md.template
|
|
80
|
+
│ ├── STATE.md.template
|
|
81
|
+
│ ├── ROADMAP.md.template
|
|
82
|
+
│ └── lessons.md.template
|
|
83
|
+
├── hooks/
|
|
84
|
+
│ ├── flow-check-update.js # Notifies when updates are available
|
|
85
|
+
│ └── flow-statusline.js # Shows project context in statusLine
|
|
86
|
+
└── settings.json # statusLine configured automatically
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
## Project Structure
|
|
90
|
+
|
|
91
|
+
Every Flow project gets this structure via `/flow:init`:
|
|
49
92
|
|
|
50
|
-
/flow:task ← standalone path for bug fixes, cleanup, small features (no PRD needed)
|
|
51
93
|
```
|
|
94
|
+
your-project/
|
|
95
|
+
├── CLAUDE.md # Project-specific execution rules
|
|
96
|
+
├── PRD.md # Current milestone spec (created by /flow:spec)
|
|
97
|
+
├── .planning/
|
|
98
|
+
│ ├── STATE.md # Session GPS — current status, next actions
|
|
99
|
+
│ ├── ROADMAP.md # Milestone phases and progress
|
|
100
|
+
│ └── archive/ # Completed milestones and old PRDs
|
|
101
|
+
└── tasks/
|
|
102
|
+
└── lessons.md # Mistake catalog → refined into permanent rules
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
## The Lessons System
|
|
52
106
|
|
|
53
|
-
|
|
107
|
+
Flow's knowledge compounding is what makes it get better over time:
|
|
54
108
|
|
|
55
|
-
|
|
109
|
+
1. **Capture** — Mistake happens, lesson written to `tasks/lessons.md`
|
|
110
|
+
2. **Refine** — Each `/flow:done` merges duplicates, sharpens rules, removes obvious ones
|
|
111
|
+
3. **Promote** — Universal lessons move to `~/.claude/lessons.md` (all projects)
|
|
112
|
+
4. **Permanence** — Recurring patterns become rules in `CLAUDE.md`
|
|
56
113
|
|
|
57
|
-
|
|
114
|
+
The goal: fewer, sharper lessons over time — not an ever-growing list.
|
|
58
115
|
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
-
|
|
62
|
-
- PRD is the execution contract -- agents execute what was specified
|
|
116
|
+
## Compatible With GSD
|
|
117
|
+
|
|
118
|
+
Flow uses the same `.planning/` directory structure as [GSD](https://github.com/gsd-framework/gsd). You can use `/gsd:debug`, `/gsd:map-codebase`, and other GSD commands alongside Flow.
|
|
63
119
|
|
|
64
120
|
## Requirements
|
|
65
121
|
|
|
66
|
-
Claude Code CLI with skills support.
|
|
122
|
+
[Claude Code](https://docs.anthropic.com/en/docs/claude-code) CLI with skills support.
|
|
123
|
+
|
|
124
|
+
## Links
|
|
125
|
+
|
|
126
|
+
- [Changelog](CHANGELOG.md) — what changed in each version
|
|
127
|
+
- [Contributing](CONTRIBUTING.md) — how to report bugs, suggest features, submit PRs
|
|
128
|
+
- [Design](DESIGN.md) — architecture decisions and system design
|
|
129
|
+
|
|
130
|
+
## License
|
|
131
|
+
|
|
132
|
+
MIT
|
package/VERSION
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
0.
|
|
1
|
+
0.2.0
|
package/bin/install.js
CHANGED
|
@@ -1,11 +1,18 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
// Flow plugin installer for Claude Code
|
|
3
|
-
// Usage: npx flow-cc [--uninstall]
|
|
3
|
+
// Usage: npx flow-cc [--uninstall] [--verify]
|
|
4
4
|
|
|
5
5
|
const fs = require('fs');
|
|
6
6
|
const path = require('path');
|
|
7
7
|
const os = require('os');
|
|
8
8
|
|
|
9
|
+
// ---------- Node.js version check ----------
|
|
10
|
+
const nodeMajor = parseInt(process.versions.node.split('.')[0], 10);
|
|
11
|
+
if (nodeMajor < 18) {
|
|
12
|
+
console.error('Flow requires Node.js 18 or later. You have ' + process.version);
|
|
13
|
+
process.exit(1);
|
|
14
|
+
}
|
|
15
|
+
|
|
9
16
|
const homeDir = os.homedir();
|
|
10
17
|
const claudeDir = path.join(homeDir, '.claude');
|
|
11
18
|
const commandsDir = path.join(claudeDir, 'commands', 'flow');
|
|
@@ -21,6 +28,93 @@ const templatesDir = path.join(pkgRoot, 'templates');
|
|
|
21
28
|
const versionFile = path.join(pkgRoot, 'VERSION');
|
|
22
29
|
|
|
23
30
|
const uninstall = process.argv.includes('--uninstall') || process.argv.includes('-u');
|
|
31
|
+
const verify = process.argv.includes('--verify') || process.argv.includes('-v');
|
|
32
|
+
|
|
33
|
+
// ---------- Verify ----------
|
|
34
|
+
if (verify) {
|
|
35
|
+
console.log('Flow install health check:\n');
|
|
36
|
+
|
|
37
|
+
let passed = 0;
|
|
38
|
+
const total = 5;
|
|
39
|
+
|
|
40
|
+
// 1. Skills installed
|
|
41
|
+
try {
|
|
42
|
+
const files = fs.existsSync(commandsDir)
|
|
43
|
+
? fs.readdirSync(commandsDir).filter(f => f.endsWith('.md'))
|
|
44
|
+
: [];
|
|
45
|
+
if (files.length > 0) {
|
|
46
|
+
console.log(` \u2713 Skills installed (${files.length} files)`);
|
|
47
|
+
passed++;
|
|
48
|
+
} else {
|
|
49
|
+
console.log(' \u2717 Skills not installed (0 .md files in commands/flow/)');
|
|
50
|
+
}
|
|
51
|
+
} catch (e) {
|
|
52
|
+
console.log(' \u2717 Skills not installed (cannot read commands/flow/)');
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
// 2. Hooks installed
|
|
56
|
+
try {
|
|
57
|
+
const hookFiles = ['flow-check-update.js', 'flow-statusline.js'];
|
|
58
|
+
const found = hookFiles.filter(h => fs.existsSync(path.join(hooksDir, h)));
|
|
59
|
+
if (found.length === 2) {
|
|
60
|
+
console.log(' \u2713 Hooks installed (2 files)');
|
|
61
|
+
passed++;
|
|
62
|
+
} else {
|
|
63
|
+
console.log(` \u2717 Hooks incomplete (${found.length}/2 files)`);
|
|
64
|
+
}
|
|
65
|
+
} catch (e) {
|
|
66
|
+
console.log(' \u2717 Hooks not installed');
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
// 3. VERSION file
|
|
70
|
+
try {
|
|
71
|
+
const vPath = path.join(commandsDir, 'VERSION');
|
|
72
|
+
if (fs.existsSync(vPath)) {
|
|
73
|
+
const ver = fs.readFileSync(vPath, 'utf8').trim();
|
|
74
|
+
console.log(` \u2713 VERSION file present (${ver})`);
|
|
75
|
+
passed++;
|
|
76
|
+
} else {
|
|
77
|
+
console.log(' \u2717 VERSION file missing');
|
|
78
|
+
}
|
|
79
|
+
} catch (e) {
|
|
80
|
+
console.log(' \u2717 VERSION file missing');
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
// 4. Templates installed
|
|
84
|
+
try {
|
|
85
|
+
const tDir = path.join(commandsDir, 'templates');
|
|
86
|
+
const files = fs.existsSync(tDir) ? fs.readdirSync(tDir) : [];
|
|
87
|
+
if (files.length > 0) {
|
|
88
|
+
console.log(` \u2713 Templates installed (${files.length} files)`);
|
|
89
|
+
passed++;
|
|
90
|
+
} else {
|
|
91
|
+
console.log(' \u2717 Templates not installed (0 files)');
|
|
92
|
+
}
|
|
93
|
+
} catch (e) {
|
|
94
|
+
console.log(' \u2717 Templates not installed');
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
// 5. StatusLine configured
|
|
98
|
+
try {
|
|
99
|
+
if (fs.existsSync(settingsPath)) {
|
|
100
|
+
const settings = JSON.parse(fs.readFileSync(settingsPath, 'utf8'));
|
|
101
|
+
if (settings.statusLine && typeof settings.statusLine.command === 'string' &&
|
|
102
|
+
settings.statusLine.command.includes('flow-statusline')) {
|
|
103
|
+
console.log(' \u2713 StatusLine configured');
|
|
104
|
+
passed++;
|
|
105
|
+
} else {
|
|
106
|
+
console.log(' \u2717 StatusLine not configured');
|
|
107
|
+
}
|
|
108
|
+
} else {
|
|
109
|
+
console.log(' \u2717 StatusLine not configured (no settings.json)');
|
|
110
|
+
}
|
|
111
|
+
} catch (e) {
|
|
112
|
+
console.log(' \u2717 StatusLine not configured');
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
console.log(`\nResult: ${passed}/${total} checks passed`);
|
|
116
|
+
process.exit(passed === total ? 0 : 1);
|
|
117
|
+
}
|
|
24
118
|
|
|
25
119
|
// ---------- Uninstall ----------
|
|
26
120
|
if (uninstall) {
|
|
@@ -60,7 +154,7 @@ if (uninstall) {
|
|
|
60
154
|
console.log(' Removed statusLine from ~/.claude/settings.json');
|
|
61
155
|
}
|
|
62
156
|
} catch (e) {
|
|
63
|
-
// settings.json parse error
|
|
157
|
+
// settings.json parse error -- leave it alone
|
|
64
158
|
}
|
|
65
159
|
}
|
|
66
160
|
|
|
@@ -71,79 +165,175 @@ if (uninstall) {
|
|
|
71
165
|
// ---------- Install ----------
|
|
72
166
|
console.log('Installing Flow plugin...\n');
|
|
73
167
|
|
|
74
|
-
//
|
|
75
|
-
|
|
76
|
-
|
|
168
|
+
// ---------- Write permission check ----------
|
|
169
|
+
const permTestDir = fs.existsSync(claudeDir) ? claudeDir : path.dirname(claudeDir);
|
|
170
|
+
const permTestFile = path.join(permTestDir, '.flow-perm-test-' + process.pid);
|
|
171
|
+
try {
|
|
172
|
+
fs.writeFileSync(permTestFile, 'test');
|
|
173
|
+
fs.unlinkSync(permTestFile);
|
|
174
|
+
} catch (e) {
|
|
175
|
+
console.error('Cannot write to ' + claudeDir + ' \u2014 check permissions.');
|
|
176
|
+
process.exit(1);
|
|
77
177
|
}
|
|
78
178
|
|
|
79
|
-
//
|
|
80
|
-
const
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
179
|
+
// ---------- Rollback tracking ----------
|
|
180
|
+
const created = []; // paths created during install (files and dirs we created fresh)
|
|
181
|
+
|
|
182
|
+
function trackFile(filePath) {
|
|
183
|
+
created.push({ type: 'file', path: filePath });
|
|
84
184
|
}
|
|
85
|
-
console.log(` Installed ${skillFiles.length} skills → ~/.claude/commands/flow/`);
|
|
86
185
|
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
if (fs.existsSync(src)) {
|
|
92
|
-
fs.copyFileSync(src, path.join(hooksDir, hook));
|
|
186
|
+
function trackDir(dirPath) {
|
|
187
|
+
// Only track if we actually created it (didn't exist before)
|
|
188
|
+
if (!fs.existsSync(dirPath)) {
|
|
189
|
+
created.push({ type: 'dir', path: dirPath });
|
|
93
190
|
}
|
|
94
191
|
}
|
|
95
|
-
console.log(' Installed hooks → ~/.claude/hooks/');
|
|
96
192
|
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
fs.
|
|
104
|
-
if (fs.existsSync(
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
193
|
+
function rollback() {
|
|
194
|
+
console.error('\nRolling back partial install...');
|
|
195
|
+
for (let i = created.length - 1; i >= 0; i--) {
|
|
196
|
+
const item = created[i];
|
|
197
|
+
try {
|
|
198
|
+
if (item.type === 'file' && fs.existsSync(item.path)) {
|
|
199
|
+
fs.unlinkSync(item.path);
|
|
200
|
+
} else if (item.type === 'dir' && fs.existsSync(item.path)) {
|
|
201
|
+
fs.rmSync(item.path, { recursive: true });
|
|
202
|
+
}
|
|
203
|
+
} catch (e) {
|
|
204
|
+
// Best-effort cleanup
|
|
205
|
+
}
|
|
108
206
|
}
|
|
109
|
-
console.
|
|
207
|
+
console.error('Rollback complete.');
|
|
110
208
|
}
|
|
111
209
|
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
} catch (e) {
|
|
118
|
-
// Corrupted settings — start fresh but warn
|
|
119
|
-
console.log(' Warning: could not parse existing settings.json, preserving as backup');
|
|
120
|
-
fs.copyFileSync(settingsPath, settingsPath + '.bak');
|
|
210
|
+
try {
|
|
211
|
+
// 1. Create directories
|
|
212
|
+
for (const dir of [commandsDir, hooksDir, cacheDir]) {
|
|
213
|
+
trackDir(dir);
|
|
214
|
+
fs.mkdirSync(dir, { recursive: true });
|
|
121
215
|
}
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
//
|
|
134
|
-
const
|
|
135
|
-
|
|
216
|
+
|
|
217
|
+
// 2. Copy skills: skills/flow-*.md -> commands/flow/*.md (strip "flow-" prefix)
|
|
218
|
+
const skillFiles = fs.readdirSync(skillsDir).filter(f => f.startsWith('flow-') && f.endsWith('.md'));
|
|
219
|
+
for (const file of skillFiles) {
|
|
220
|
+
const dest = file.replace(/^flow-/, '');
|
|
221
|
+
const destPath = path.join(commandsDir, dest);
|
|
222
|
+
fs.copyFileSync(path.join(skillsDir, file), destPath);
|
|
223
|
+
trackFile(destPath);
|
|
224
|
+
}
|
|
225
|
+
console.log(` Installed ${skillFiles.length} skills \u2192 ~/.claude/commands/flow/`);
|
|
226
|
+
|
|
227
|
+
// 3. Copy hooks
|
|
228
|
+
const hookFiles = ['flow-check-update.js', 'flow-statusline.js'];
|
|
229
|
+
for (const hook of hookFiles) {
|
|
230
|
+
const src = path.join(srcHooksDir, hook);
|
|
231
|
+
if (fs.existsSync(src)) {
|
|
232
|
+
const destPath = path.join(hooksDir, hook);
|
|
233
|
+
fs.copyFileSync(src, destPath);
|
|
234
|
+
trackFile(destPath);
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
console.log(' Installed hooks \u2192 ~/.claude/hooks/');
|
|
238
|
+
|
|
239
|
+
// 4. Copy VERSION
|
|
240
|
+
const versionDest = path.join(commandsDir, 'VERSION');
|
|
241
|
+
fs.copyFileSync(versionFile, versionDest);
|
|
242
|
+
trackFile(versionDest);
|
|
243
|
+
console.log(' Installed VERSION \u2192 ~/.claude/commands/flow/VERSION');
|
|
244
|
+
|
|
245
|
+
// 5. Copy templates
|
|
246
|
+
const destTemplatesDir = path.join(commandsDir, 'templates');
|
|
247
|
+
trackDir(destTemplatesDir);
|
|
248
|
+
fs.mkdirSync(destTemplatesDir, { recursive: true });
|
|
249
|
+
if (fs.existsSync(templatesDir)) {
|
|
250
|
+
const templateFiles = fs.readdirSync(templatesDir);
|
|
251
|
+
for (const file of templateFiles) {
|
|
252
|
+
const destPath = path.join(destTemplatesDir, file);
|
|
253
|
+
fs.copyFileSync(path.join(templatesDir, file), destPath);
|
|
254
|
+
trackFile(destPath);
|
|
255
|
+
}
|
|
256
|
+
console.log(` Installed ${templateFiles.length} templates \u2192 ~/.claude/commands/flow/templates/`);
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
// 6. Merge statusLine into settings.json
|
|
260
|
+
let settings = {};
|
|
261
|
+
if (fs.existsSync(settingsPath)) {
|
|
262
|
+
try {
|
|
263
|
+
settings = JSON.parse(fs.readFileSync(settingsPath, 'utf8'));
|
|
264
|
+
} catch (e) {
|
|
265
|
+
// Corrupted settings -- start fresh but warn
|
|
266
|
+
console.log(' Warning: could not parse existing settings.json, preserving as backup');
|
|
267
|
+
fs.copyFileSync(settingsPath, settingsPath + '.bak');
|
|
268
|
+
}
|
|
269
|
+
}
|
|
270
|
+
settings.statusLine = {
|
|
271
|
+
type: 'command',
|
|
272
|
+
command: `node "${path.join(hooksDir, 'flow-statusline.js')}"`
|
|
273
|
+
};
|
|
274
|
+
fs.writeFileSync(settingsPath, JSON.stringify(settings, null, 2) + '\n');
|
|
275
|
+
trackFile(settingsPath);
|
|
276
|
+
console.log(' Configured statusLine in ~/.claude/settings.json');
|
|
277
|
+
|
|
278
|
+
// 7. Write .source breadcrumb (for dev/setup.sh compat)
|
|
279
|
+
const sourcePath = path.join(commandsDir, '.source');
|
|
280
|
+
fs.writeFileSync(sourcePath, pkgRoot + '\n');
|
|
281
|
+
trackFile(sourcePath);
|
|
282
|
+
|
|
283
|
+
// ---------- Post-install verification ----------
|
|
284
|
+
let warnings = 0;
|
|
285
|
+
|
|
286
|
+
// Check: at least 1 file in commandsDir
|
|
287
|
+
const installedSkills = fs.readdirSync(commandsDir).filter(f => f.endsWith('.md'));
|
|
288
|
+
if (installedSkills.length === 0) {
|
|
289
|
+
console.log(' Warning: no skill files found in commands/flow/');
|
|
290
|
+
warnings++;
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
// Check: both hook files
|
|
294
|
+
const installedHooks = hookFiles.filter(h => fs.existsSync(path.join(hooksDir, h)));
|
|
295
|
+
if (installedHooks.length < 2) {
|
|
296
|
+
console.log(` Warning: only ${installedHooks.length}/2 hook files installed`);
|
|
297
|
+
warnings++;
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
// Check: VERSION file
|
|
301
|
+
if (!fs.existsSync(path.join(commandsDir, 'VERSION'))) {
|
|
302
|
+
console.log(' Warning: VERSION file not found after install');
|
|
303
|
+
warnings++;
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
// Check: templates directory with at least 1 file
|
|
307
|
+
const tplDir = path.join(commandsDir, 'templates');
|
|
308
|
+
const tplFiles = fs.existsSync(tplDir) ? fs.readdirSync(tplDir) : [];
|
|
309
|
+
if (tplFiles.length === 0) {
|
|
310
|
+
console.log(' Warning: no template files found after install');
|
|
311
|
+
warnings++;
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
if (warnings > 0) {
|
|
315
|
+
console.log(` (${warnings} verification warning${warnings > 1 ? 's' : ''} — install may be incomplete)`);
|
|
316
|
+
}
|
|
317
|
+
|
|
318
|
+
// Done
|
|
319
|
+
const version = fs.readFileSync(versionFile, 'utf8').trim();
|
|
320
|
+
console.log(`
|
|
136
321
|
Flow v${version} installed successfully!
|
|
137
322
|
|
|
138
323
|
Commands available:
|
|
139
|
-
/flow:intro
|
|
140
|
-
/flow:init
|
|
141
|
-
/flow:spec
|
|
142
|
-
/flow:go
|
|
143
|
-
/flow:done
|
|
144
|
-
/flow:status
|
|
145
|
-
/flow:task
|
|
146
|
-
/flow:update
|
|
324
|
+
/flow:intro \u2014 Learn the Flow workflow
|
|
325
|
+
/flow:init \u2014 Start a new project or milestone
|
|
326
|
+
/flow:spec \u2014 Spec interview \u2192 executable PRD
|
|
327
|
+
/flow:go \u2014 Execute next phase with agent teams
|
|
328
|
+
/flow:done \u2014 Session-end documentation
|
|
329
|
+
/flow:status \u2014 Quick orientation
|
|
330
|
+
/flow:task \u2014 Lightweight task execution
|
|
331
|
+
/flow:update \u2014 Update Flow to latest version
|
|
147
332
|
|
|
148
333
|
Get started: run /flow:intro in any Claude Code session.
|
|
149
334
|
`);
|
|
335
|
+
} catch (err) {
|
|
336
|
+
rollback();
|
|
337
|
+
console.error('\nInstall failed: ' + err.message);
|
|
338
|
+
process.exit(1);
|
|
339
|
+
}
|
|
@@ -11,43 +11,90 @@ const homeDir = os.homedir();
|
|
|
11
11
|
const cacheDir = path.join(homeDir, '.claude', 'cache');
|
|
12
12
|
const cacheFile = path.join(cacheDir, 'flow-update-check.json');
|
|
13
13
|
const versionFile = path.join(homeDir, '.claude', 'commands', 'flow', 'VERSION');
|
|
14
|
+
const errorLog = path.join(homeDir, '.claude', 'hooks', 'flow-error.log');
|
|
14
15
|
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
16
|
+
function logError(context, err) {
|
|
17
|
+
try {
|
|
18
|
+
const line = `[${new Date().toISOString()}] flow-check-update: ${context}: ${err.message || err}\n`;
|
|
19
|
+
// Cap log at 50KB — truncate oldest entries
|
|
20
|
+
if (fs.existsSync(errorLog)) {
|
|
21
|
+
const stat = fs.statSync(errorLog);
|
|
22
|
+
if (stat.size > 50 * 1024) {
|
|
23
|
+
const content = fs.readFileSync(errorLog, 'utf8');
|
|
24
|
+
const lines = content.split('\n');
|
|
25
|
+
fs.writeFileSync(errorLog, lines.slice(Math.floor(lines.length / 2)).join('\n'));
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
fs.appendFileSync(errorLog, line);
|
|
29
|
+
} catch (_) {
|
|
30
|
+
// Logging must never throw
|
|
31
|
+
}
|
|
18
32
|
}
|
|
19
33
|
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
34
|
+
try {
|
|
35
|
+
// Ensure cache directory exists
|
|
36
|
+
if (!fs.existsSync(cacheDir)) {
|
|
37
|
+
fs.mkdirSync(cacheDir, { recursive: true });
|
|
38
|
+
}
|
|
24
39
|
|
|
25
|
-
|
|
26
|
-
const
|
|
40
|
+
// Run check in background (spawn detached process, windowsHide prevents console flash)
|
|
41
|
+
const child = spawn(process.execPath, ['-e', `
|
|
42
|
+
const fs = require('fs');
|
|
43
|
+
const { execSync } = require('child_process');
|
|
27
44
|
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
45
|
+
const cacheFile = ${JSON.stringify(cacheFile)};
|
|
46
|
+
const versionFile = ${JSON.stringify(versionFile)};
|
|
47
|
+
const errorLog = ${JSON.stringify(errorLog)};
|
|
48
|
+
|
|
49
|
+
function logError(context, err) {
|
|
50
|
+
try {
|
|
51
|
+
const line = '[' + new Date().toISOString() + '] flow-check-update(child): ' + context + ': ' + (err.message || err) + '\\n';
|
|
52
|
+
if (fs.existsSync(errorLog)) {
|
|
53
|
+
const stat = fs.statSync(errorLog);
|
|
54
|
+
if (stat.size > 50 * 1024) {
|
|
55
|
+
const content = fs.readFileSync(errorLog, 'utf8');
|
|
56
|
+
const lines = content.split('\\n');
|
|
57
|
+
fs.writeFileSync(errorLog, lines.slice(Math.floor(lines.length / 2)).join('\\n'));
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
fs.appendFileSync(errorLog, line);
|
|
61
|
+
} catch (_) {}
|
|
32
62
|
}
|
|
33
|
-
} catch (e) {}
|
|
34
63
|
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
64
|
+
try {
|
|
65
|
+
let installed = '0.0.0';
|
|
66
|
+
try {
|
|
67
|
+
if (fs.existsSync(versionFile)) {
|
|
68
|
+
installed = fs.readFileSync(versionFile, 'utf8').trim();
|
|
69
|
+
}
|
|
70
|
+
} catch (e) {
|
|
71
|
+
logError('read-version', e);
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
let latest = null;
|
|
75
|
+
try {
|
|
76
|
+
latest = execSync('npm view flow-cc version', { encoding: 'utf8', timeout: 10000, windowsHide: true }).trim();
|
|
77
|
+
} catch (e) {
|
|
78
|
+
logError('npm-view', e);
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
const result = {
|
|
82
|
+
update_available: latest && installed !== latest,
|
|
83
|
+
installed,
|
|
84
|
+
latest: latest || 'unknown',
|
|
85
|
+
checked: Math.floor(Date.now() / 1000)
|
|
86
|
+
};
|
|
87
|
+
|
|
88
|
+
fs.writeFileSync(cacheFile, JSON.stringify(result));
|
|
89
|
+
} catch (e) {
|
|
90
|
+
logError('main', e);
|
|
91
|
+
}
|
|
92
|
+
`], {
|
|
93
|
+
stdio: 'ignore',
|
|
94
|
+
windowsHide: true
|
|
95
|
+
});
|
|
96
|
+
|
|
97
|
+
child.unref();
|
|
98
|
+
} catch (e) {
|
|
99
|
+
logError('spawn', e);
|
|
100
|
+
}
|
package/hooks/flow-statusline.js
CHANGED
|
@@ -7,6 +7,25 @@ const path = require('path');
|
|
|
7
7
|
const os = require('os');
|
|
8
8
|
|
|
9
9
|
const homeDir = os.homedir();
|
|
10
|
+
const errorLog = path.join(homeDir, '.claude', 'hooks', 'flow-error.log');
|
|
11
|
+
|
|
12
|
+
function logError(context, err) {
|
|
13
|
+
try {
|
|
14
|
+
const line = `[${new Date().toISOString()}] flow-statusline: ${context}: ${err.message || err}\n`;
|
|
15
|
+
// Cap log at 50KB — truncate oldest entries
|
|
16
|
+
if (fs.existsSync(errorLog)) {
|
|
17
|
+
const stat = fs.statSync(errorLog);
|
|
18
|
+
if (stat.size > 50 * 1024) {
|
|
19
|
+
const content = fs.readFileSync(errorLog, 'utf8');
|
|
20
|
+
const lines = content.split('\n');
|
|
21
|
+
fs.writeFileSync(errorLog, lines.slice(Math.floor(lines.length / 2)).join('\n'));
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
fs.appendFileSync(errorLog, line);
|
|
25
|
+
} catch (_) {
|
|
26
|
+
// Logging must never throw
|
|
27
|
+
}
|
|
28
|
+
}
|
|
10
29
|
|
|
11
30
|
// Read JSON from stdin (Claude Code statusline protocol)
|
|
12
31
|
let input = '';
|
|
@@ -56,9 +75,13 @@ process.stdin.on('end', () => {
|
|
|
56
75
|
const todos = JSON.parse(fs.readFileSync(path.join(todosDir, files[0].name), 'utf8'));
|
|
57
76
|
const inProgress = todos.find(t => t.status === 'in_progress');
|
|
58
77
|
if (inProgress) task = inProgress.activeForm || '';
|
|
59
|
-
} catch (e) {
|
|
78
|
+
} catch (e) {
|
|
79
|
+
logError('parse-todos', e);
|
|
80
|
+
}
|
|
60
81
|
}
|
|
61
|
-
} catch (e) {
|
|
82
|
+
} catch (e) {
|
|
83
|
+
logError('read-todos', e);
|
|
84
|
+
}
|
|
62
85
|
}
|
|
63
86
|
|
|
64
87
|
// --- Flow update notification ---
|
|
@@ -78,6 +101,7 @@ process.stdin.on('end', () => {
|
|
|
78
101
|
shouldCheck = true;
|
|
79
102
|
}
|
|
80
103
|
} catch (e) {
|
|
104
|
+
logError('parse-cache', e);
|
|
81
105
|
shouldCheck = true;
|
|
82
106
|
}
|
|
83
107
|
} else {
|
|
@@ -96,7 +120,9 @@ process.stdin.on('end', () => {
|
|
|
96
120
|
});
|
|
97
121
|
child.unref();
|
|
98
122
|
}
|
|
99
|
-
} catch (e) {
|
|
123
|
+
} catch (e) {
|
|
124
|
+
logError('spawn-update-check', e);
|
|
125
|
+
}
|
|
100
126
|
}
|
|
101
127
|
|
|
102
128
|
// --- Output ---
|
|
@@ -107,6 +133,7 @@ process.stdin.on('end', () => {
|
|
|
107
133
|
process.stdout.write(`${flowUpdate}\x1b[2m${model}\x1b[0m \u2502 \x1b[2m${dirname}\x1b[0m${ctx}`);
|
|
108
134
|
}
|
|
109
135
|
} catch (e) {
|
|
136
|
+
logError('main', e);
|
|
110
137
|
// Silent fail — statusline must never crash
|
|
111
138
|
}
|
|
112
139
|
});
|
package/package.json
CHANGED
|
@@ -1,15 +1,40 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "flow-cc",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"description": "
|
|
3
|
+
"version": "0.2.0",
|
|
4
|
+
"description": "Structured workflow system for Claude Code — spec interviews, agent-team execution, session handoffs, compounding knowledge",
|
|
5
|
+
"author": "Troy Hoffman",
|
|
6
|
+
"license": "MIT",
|
|
7
|
+
"repository": {
|
|
8
|
+
"type": "git",
|
|
9
|
+
"url": "https://github.com/troyhoffman-oss/flow-plugin.git"
|
|
10
|
+
},
|
|
11
|
+
"homepage": "https://github.com/troyhoffman-oss/flow-plugin",
|
|
12
|
+
"bugs": {
|
|
13
|
+
"url": "https://github.com/troyhoffman-oss/flow-plugin/issues"
|
|
14
|
+
},
|
|
15
|
+
"keywords": [
|
|
16
|
+
"claude-code",
|
|
17
|
+
"claude",
|
|
18
|
+
"workflow",
|
|
19
|
+
"ai-agents",
|
|
20
|
+
"developer-tools",
|
|
21
|
+
"cli",
|
|
22
|
+
"skills",
|
|
23
|
+
"anthropic"
|
|
24
|
+
],
|
|
5
25
|
"bin": {
|
|
6
26
|
"flow-cc": "bin/install.js"
|
|
7
27
|
},
|
|
28
|
+
"engines": {
|
|
29
|
+
"node": ">=18"
|
|
30
|
+
},
|
|
8
31
|
"files": [
|
|
9
32
|
"bin",
|
|
10
33
|
"skills",
|
|
11
34
|
"hooks",
|
|
12
35
|
"templates",
|
|
13
|
-
"VERSION"
|
|
36
|
+
"VERSION",
|
|
37
|
+
"CHANGELOG.md",
|
|
38
|
+
"CONTRIBUTING.md"
|
|
14
39
|
]
|
|
15
40
|
}
|
package/skills/flow-done.md
CHANGED
|
@@ -65,6 +65,8 @@ Structure:
|
|
|
65
65
|
- Mark completed phases with completion date
|
|
66
66
|
- Ensure pending phases have enough detail that the next session can start with a one-line prompt
|
|
67
67
|
- **Archive check:** If the current milestone is fully complete:
|
|
68
|
+
- If `.planning/` does not exist, skip archiving entirely — there's nothing to archive
|
|
69
|
+
- Create `.planning/archive/` if it doesn't already exist (use `mkdir -p` or equivalent)
|
|
68
70
|
- Move milestone phase details to `.planning/archive/milestones-vX.md`
|
|
69
71
|
- Keep only the summary row in the ROADMAP milestone table
|
|
70
72
|
- Move `PRD.md` to `.planning/archive/PRD-vX.md`
|
package/skills/flow-spec.md
CHANGED
|
@@ -16,8 +16,9 @@ You are executing the `/flow:spec` skill. This is the KEYSTONE skill of the flow
|
|
|
16
16
|
2. Read `CLAUDE.md` — understand project rules and tech stack
|
|
17
17
|
3. Read `PRD.md` if it exists — check for existing spec to build on
|
|
18
18
|
4. **Codebase scan** (brownfield projects):
|
|
19
|
-
- Use Glob to
|
|
20
|
-
- Use Grep for
|
|
19
|
+
- **Size check first:** Use Glob with `**/*` to estimate total file count. If > 500 files, switch to focused mode (see below).
|
|
20
|
+
- **Standard mode (≤ 500 files):** Use Glob to find components, pages/routes, API endpoints, types, utilities, config files, database models. Use Grep for export patterns, route definitions, key function signatures. **Cap at 50 files sampled** — prioritize entry points, config, and type definitions.
|
|
21
|
+
- **Focused mode (> 500 files):** Scan ONLY: package.json/config files, entry points (index.ts, main.ts, app.ts), route definitions, database schema/models, and type definition files. Skip component trees, test files, and generated code entirely.
|
|
21
22
|
- Build internal summary: "Here's what exists that we can reuse"
|
|
22
23
|
5. Print a brief context summary to the user: "Here's what I found in the codebase: [key components, patterns, data layer]. Starting the spec interview."
|
|
23
24
|
|
package/skills/flow-update.md
CHANGED
|
@@ -46,14 +46,23 @@ If installed version equals latest version, print this and stop:
|
|
|
46
46
|
Flow is up to date (v<version>)
|
|
47
47
|
```
|
|
48
48
|
|
|
49
|
-
## Step 4:
|
|
49
|
+
## Step 4: Show what's new
|
|
50
50
|
|
|
51
|
-
|
|
51
|
+
Fetch the CHANGELOG.md from the Flow repo to show the user what changed:
|
|
52
|
+
|
|
53
|
+
1. Run: `npx -y -p flow-cc@<latest> node -e "const fs=require('fs'),p=require('path');try{console.log(fs.readFileSync(p.join(require.resolve('flow-cc/package.json'),'..','CHANGELOG.md'),'utf8'))}catch(e){console.log('CHANGELOG not available')}"`
|
|
54
|
+
2. Parse the output and extract only the section for `v<latest>` (from the `## [<latest>]` heading to the next `## [` heading or end of file)
|
|
55
|
+
3. Print:
|
|
52
56
|
|
|
53
57
|
```
|
|
54
58
|
Update available: v<installed> → v<latest>
|
|
59
|
+
|
|
60
|
+
Here's what's new in v<latest>:
|
|
61
|
+
<extracted changelog section>
|
|
55
62
|
```
|
|
56
63
|
|
|
64
|
+
If the CHANGELOG fetch fails, just print the version line without the changelog section. Don't let a missing changelog block the update.
|
|
65
|
+
|
|
57
66
|
Wait for user confirmation before proceeding.
|
|
58
67
|
|
|
59
68
|
## Step 5: Run update
|
|
@@ -5,6 +5,16 @@ Format: PATTERN → CAUSE → FIX → RULE
|
|
|
5
5
|
## Execution Patterns
|
|
6
6
|
<!-- Lessons about workflow, delegation, verification -->
|
|
7
7
|
|
|
8
|
+
<!-- EXAMPLE (replace with real lessons as you work):
|
|
9
|
+
|
|
10
|
+
### Agent context overflow on large files
|
|
11
|
+
- **PATTERN:** Spawned agent tried to read a 2000-line file and ran out of context before finishing its task
|
|
12
|
+
- **CAUSE:** Agent prompt didn't specify which lines/functions to read — it read the whole file
|
|
13
|
+
- **FIX:** Added explicit line ranges and function names to the agent prompt
|
|
14
|
+
- **RULE:** Always tell agents exactly which functions/sections to read. Never say "read file.ts" — say "read file.ts lines 50-120 (the handleSubmit function)"
|
|
15
|
+
|
|
16
|
+
END EXAMPLE -->
|
|
17
|
+
|
|
8
18
|
## Domain Knowledge
|
|
9
19
|
<!-- Lessons about business logic, data models, user behavior -->
|
|
10
20
|
|