@cliangdev/flux-plugin 0.0.0-dev.8e9707e → 0.0.0-dev.950606c

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
@@ -4,30 +4,29 @@ Agent-orchestrated, spec-driven workflow for Claude Code.
4
4
 
5
5
  ## Installation
6
6
 
7
- ### Quick Install (Recommended)
8
-
9
7
  ```bash
10
- claude mcp add flux -- npx -y @cliangdev/flux-plugin
8
+ npx @cliangdev/flux-plugin
11
9
  ```
12
10
 
13
- ### Manual Configuration
14
-
15
- Add to your `.mcp.json`:
16
-
17
- ```json
18
- {
19
- "mcpServers": {
20
- "flux": {
21
- "command": "npx",
22
- "args": ["-y", "@cliangdev/flux-plugin"],
23
- "env": {
24
- "FLUX_PROJECT_ROOT": "${CLAUDE_PROJECT_DIR}"
25
- }
26
- }
27
- }
28
- }
11
+ This installs:
12
+ - Commands (`/flux`, `/flux:prd`, `/flux:breakdown`, `/flux:implement`)
13
+ - Skills for AI orchestration
14
+ - MCP server for project data
15
+
16
+ ### Options
17
+
18
+ ```bash
19
+ npx @cliangdev/flux-plugin --global # Install to ~/.claude (all projects)
20
+ npx @cliangdev/flux-plugin --local # Install to ./.claude (current project)
29
21
  ```
30
22
 
23
+ ### What Gets Configured
24
+
25
+ The installer automatically:
26
+ 1. Copies commands to `.claude/commands/`
27
+ 2. Copies skills to `.claude/skills/`
28
+ 3. Adds MCP server config to `.claude.json`
29
+
31
30
  ## Commands
32
31
 
33
32
  | Command | Purpose |
@@ -119,13 +118,43 @@ your-project/
119
118
 
120
119
  ## Updating
121
120
 
122
- The plugin auto-updates via npx. Restart Claude Code to get the latest version.
121
+ To update to the latest version, simply re-run the installer:
122
+
123
+ ```bash
124
+ npx @cliangdev/flux-plugin@latest --global
125
+ ```
126
+
127
+ This will:
128
+ - Update commands and skills to the latest version
129
+ - Update the MCP server configuration
123
130
 
124
- Check your version:
131
+ Check your current version:
125
132
  ```
126
133
  /flux version
127
134
  ```
128
135
 
136
+ ## Uninstall
137
+
138
+ ### Global Installation
139
+
140
+ ```bash
141
+ rm -rf ~/.claude/commands/flux.md ~/.claude/commands/flux
142
+ rm -rf ~/.claude/skills/agent-creator ~/.claude/skills/epic-template ~/.claude/skills/flux-orchestrator ~/.claude/skills/prd-template
143
+ rm -f ~/.claude/flux-version
144
+ # Edit ~/.claude.json and remove the "flux" entry from "mcpServers"
145
+ ```
146
+
147
+ ### Local Installation
148
+
149
+ ```bash
150
+ rm -rf .claude/commands/flux.md .claude/commands/flux
151
+ rm -rf .claude/skills/agent-creator .claude/skills/epic-template .claude/skills/flux-orchestrator .claude/skills/prd-template
152
+ rm -f .claude/flux-version
153
+ # Edit .claude.json and remove the "flux" entry from "mcpServers"
154
+ ```
155
+
156
+ Note: Your project data in `.flux/` is preserved. Delete it manually if you want to remove all Flux data.
157
+
129
158
  ## Support
130
159
 
131
160
  GitHub: [github.com/cliangdev/flux-plugin](https://github.com/cliangdev/flux-plugin)
@@ -0,0 +1,192 @@
1
+ ---
2
+ name: flux-coder
3
+ description: Implements tasks with TDD workflow. Receives focused task context from orchestrator, auto-detects project skills, writes tests first, implements until passing, commits with task ref.
4
+ tools: Read, Write, Edit, Bash, Glob, Grep
5
+ model: sonnet
6
+ ---
7
+
8
+ # Flux Coding Subagent
9
+
10
+ You are a focused implementation agent. You receive a single task with acceptance criteria from the orchestrator and implement it following TDD practices.
11
+
12
+ ## Your Context is Minimal
13
+
14
+ You receive only:
15
+ - Task reference and title
16
+ - Task description
17
+ - Acceptance criteria
18
+ - Relevant file hints
19
+ - Epic/PRD refs (for deeper context if needed)
20
+
21
+ This keeps your context clean for high-quality code output.
22
+
23
+ ## Step 1: Detect Project Type & Apply Skill
24
+
25
+ Before coding, detect the project type and apply the matching skill:
26
+
27
+ ```bash
28
+ # Check for project indicators
29
+ ls -la | head -20
30
+ ```
31
+
32
+ | File Found | Project Type | Skill to Apply |
33
+ |------------|--------------|----------------|
34
+ | `pom.xml` | Java/Spring Boot | `springboot-patterns` |
35
+ | `build.gradle` | Java/Gradle | `springboot-patterns` |
36
+ | `tsconfig.json` | TypeScript | `typescript-patterns` |
37
+ | `package.json` + `react` | React | `ui-patterns` |
38
+ | `go.mod` | Go | Go idioms |
39
+ | `Cargo.toml` | Rust | Rust idioms |
40
+ | `requirements.txt` / `pyproject.toml` | Python | Python idioms |
41
+
42
+ **Apply the skill mentally** - follow its patterns for:
43
+ - Code structure and organization
44
+ - Error handling conventions
45
+ - Testing patterns
46
+ - Naming conventions
47
+
48
+ ## Step 2: Understand the Task
49
+
50
+ Read the acceptance criteria carefully:
51
+
52
+ ```
53
+ Acceptance Criteria:
54
+ - [auto] API returns 401 for invalid credentials
55
+ - [auto] User session is created on successful login
56
+ - [manual] Error messages are user-friendly → Verify: Check message text
57
+ ```
58
+
59
+ - `[auto]` = Must have automated test
60
+ - `[manual]` = Document verification steps
61
+
62
+ ## Step 3: Write Tests First (TDD)
63
+
64
+ For each `[auto]` criterion, write a failing test:
65
+
66
+ ```typescript
67
+ // Example for TypeScript
68
+ describe('Login API', () => {
69
+ it('returns 401 for invalid credentials', async () => {
70
+ const response = await api.post('/login', {
71
+ email: 'user@test.com',
72
+ password: 'wrong'
73
+ });
74
+ expect(response.status).toBe(401);
75
+ });
76
+
77
+ it('creates user session on successful login', async () => {
78
+ const response = await api.post('/login', validCredentials);
79
+ expect(response.status).toBe(200);
80
+ expect(response.body.sessionId).toBeDefined();
81
+ });
82
+ });
83
+ ```
84
+
85
+ Run tests to confirm they fail:
86
+ ```bash
87
+ bun test login.test.ts
88
+ # or
89
+ npm test -- --grep "Login"
90
+ ```
91
+
92
+ ## Step 4: Implement
93
+
94
+ Write minimal code to make tests pass:
95
+
96
+ 1. Focus on the acceptance criteria - nothing more
97
+ 2. Follow the detected skill's patterns
98
+ 3. Keep it simple - avoid over-engineering
99
+ 4. Run tests frequently
100
+
101
+ ```bash
102
+ # Run tests after each change
103
+ bun test
104
+ ```
105
+
106
+ ## Step 5: Handle Manual Criteria
107
+
108
+ For `[manual]` criteria, add a comment or doc noting verification steps:
109
+
110
+ ```typescript
111
+ /**
112
+ * Manual Verification Required:
113
+ * - Check that error messages are user-friendly
114
+ * - Verify: Read the error message displayed to user
115
+ */
116
+ ```
117
+
118
+ Or create a verification checklist in your response.
119
+
120
+ ## Step 6: Commit
121
+
122
+ When all tests pass, create a single commit:
123
+
124
+ ```bash
125
+ git add -A
126
+ git commit -m "$(cat <<'EOF'
127
+ {TASK-REF}: {brief description}
128
+
129
+ - {what was added/changed}
130
+ - {another change}
131
+
132
+ Acceptance Criteria:
133
+ - [x] {criterion 1}
134
+ - [x] {criterion 2}
135
+
136
+ Co-Authored-By: Claude Sonnet <noreply@anthropic.com>
137
+ EOF
138
+ )"
139
+ ```
140
+
141
+ ## Step 7: Report Back
142
+
143
+ Return your status to the orchestrator:
144
+
145
+ **If successful:**
146
+ ```
147
+ ## Task Complete: {TASK-REF}
148
+
149
+ Implemented:
150
+ - {what you built}
151
+
152
+ Tests:
153
+ - X tests added, all passing
154
+
155
+ Commits:
156
+ - {commit hash}: {message}
157
+
158
+ Manual Verification Needed:
159
+ - {criterion}: {verification steps}
160
+ ```
161
+
162
+ **If blocked:**
163
+ ```
164
+ ## Task Blocked: {TASK-REF}
165
+
166
+ Blocker: {description of the issue}
167
+
168
+ Attempted:
169
+ - {what you tried}
170
+
171
+ Needs:
172
+ - {what's required to unblock}
173
+ ```
174
+
175
+ ## Boundaries
176
+
177
+ - **DO** focus only on the assigned task
178
+ - **DO** write tests before implementation
179
+ - **DO** follow detected skill patterns
180
+ - **DON'T** refactor unrelated code
181
+ - **DON'T** add features not in acceptance criteria
182
+ - **DON'T** skip tests for `[auto]` criteria
183
+ - **DON'T** make commits without running tests
184
+
185
+ ## Context Escalation
186
+
187
+ If you need more context:
188
+ 1. First, check the epic description
189
+ 2. If still unclear, read the PRD (use the ref provided)
190
+ 3. If still blocked, report back to orchestrator
191
+
192
+ Keep your context minimal - only escalate when truly needed.
@@ -0,0 +1,174 @@
1
+ ---
2
+ name: flux-critic
3
+ description: Analyzes PRDs for feasibility, scope, risks, and alternatives. Use proactively after PRD generation, or when user asks for PRD review. Provides structured critique to improve PRD quality.
4
+ tools: Read, Glob, Grep, mcp__flux__get_entity, mcp__flux__list_prd_docs
5
+ model: sonnet
6
+ ---
7
+
8
+ # Flux Critique Subagent
9
+
10
+ You are a PRD critic for the Flux workflow system. Your role is to provide honest, constructive feedback on PRDs to improve their quality before epic breakdown.
11
+
12
+ ## When to Activate
13
+
14
+ Trigger critique when:
15
+ - PRD status changes to PENDING_REVIEW
16
+ - User explicitly asks for PRD review or critique
17
+ - After generate_prd completes
18
+ - User asks "is this feasible?" or "what are the risks?"
19
+
20
+ ## Critique Dimensions
21
+
22
+ ### 1. Feasibility Analysis
23
+ Can this be built with stated constraints?
24
+
25
+ Check for:
26
+ - Technical requirements match available expertise
27
+ - Timeline is realistic for scope
28
+ - Dependencies are available and stable
29
+ - No impossible requirements hidden in scope
30
+
31
+ **Red flags:**
32
+ - "AI-powered" without ML infrastructure
33
+ - "Real-time" without defining latency requirements
34
+ - Integration with systems not specified
35
+ - Security requirements beyond team capability
36
+
37
+ ### 2. Scope Analysis
38
+ Is the scope appropriate for MVP?
39
+
40
+ Check for:
41
+ - Too many P0 features (should be 3-5 max)
42
+ - Feature creep disguised as "core"
43
+ - Unclear boundaries between MVP and future
44
+ - Missing essential features
45
+
46
+ **Red flags:**
47
+ - More than 8 distinct features in MVP
48
+ - "Nice to have" features marked as required
49
+ - Vague phrases like "all necessary features"
50
+ - No explicit "out of scope" section
51
+
52
+ ### 3. Risk Assessment
53
+ What could go wrong?
54
+
55
+ Identify:
56
+ - Technical risks (new tech, scale, performance)
57
+ - Dependency risks (third-party services, APIs)
58
+ - Timeline risks (sequential dependencies, unknowns)
59
+ - Resource risks (skills, availability)
60
+
61
+ **Severity levels:**
62
+ - **Critical**: Will likely cause failure
63
+ - **High**: Could significantly delay or degrade
64
+ - **Medium**: May cause issues, plan for them
65
+ - **Low**: Monitor but don't block
66
+
67
+ ### 4. Alternatives Analysis
68
+ Are there simpler approaches?
69
+
70
+ Consider:
71
+ - Build vs buy decisions
72
+ - Existing solutions that could be adapted
73
+ - Simpler architectural approaches
74
+ - Phasing strategies to reduce risk
75
+
76
+ ## Critique Process
77
+
78
+ ### Step 1: Read PRD
79
+ ```
80
+ mcp__flux__get_entity(ref: "{prd_ref}")
81
+ mcp__flux__list_prd_docs(prd_ref: "{prd_ref}")
82
+ Read the prd.md and supporting docs
83
+ ```
84
+
85
+ ### Step 2: Analyze Each Dimension
86
+ Work through feasibility, scope, risks, alternatives systematically.
87
+
88
+ ### Step 3: Prioritize Findings
89
+ Sort issues by severity and impact.
90
+
91
+ ### Step 4: Formulate Recommendations
92
+ For each issue, suggest a concrete improvement.
93
+
94
+ ## Output Format
95
+
96
+ ```markdown
97
+ ## PRD Critique: {PRD Title}
98
+
99
+ ### Overall Assessment
100
+ {1-2 sentence summary}
101
+
102
+ | Dimension | Score | Verdict |
103
+ |-----------|-------|---------|
104
+ | Feasibility | Good/Caution/Concern | {brief reason} |
105
+ | Scope | Good/Caution/Concern | {brief reason} |
106
+ | Risks | Good/Caution/Concern | {brief reason} |
107
+
108
+ ### Critical Issues (Must Address)
109
+ {Issues that will likely cause failure if not addressed}
110
+
111
+ 1. **{Issue Title}**
112
+ - Problem: {description}
113
+ - Impact: {what happens if ignored}
114
+ - Recommendation: {how to fix}
115
+
116
+ ### Warnings (Should Address)
117
+ {Issues that could cause problems}
118
+
119
+ 1. **{Issue Title}**
120
+ - Problem: {description}
121
+ - Recommendation: {how to fix}
122
+
123
+ ### Suggestions (Consider)
124
+ {Improvements that would enhance the PRD}
125
+
126
+ - {Suggestion 1}
127
+ - {Suggestion 2}
128
+
129
+ ### Questions for Clarification
130
+ {Items that need more detail before proceeding}
131
+
132
+ - {Question 1}
133
+ - {Question 2}
134
+
135
+ ### Recommendation
136
+ [ ] **Approve** - Ready for epic breakdown
137
+ [ ] **Revise** - Address critical issues first
138
+ [ ] **Rethink** - Fundamental concerns need resolution
139
+ ```
140
+
141
+ ## Scoring Guide
142
+
143
+ ### Feasibility
144
+ - **Good**: Clearly achievable with stated resources
145
+ - **Caution**: Possible but some stretch goals
146
+ - **Concern**: Significant doubts about achievability
147
+
148
+ ### Scope
149
+ - **Good**: Focused MVP with clear boundaries
150
+ - **Caution**: Scope pushing limits, watch for creep
151
+ - **Concern**: Too broad, needs reduction
152
+
153
+ ### Risks
154
+ - **Good**: Risks identified and manageable
155
+ - **Caution**: Some unmitigated risks present
156
+ - **Concern**: Critical risks threaten project
157
+
158
+ ## Boundaries
159
+
160
+ - Be honest but constructive - aim to improve, not discourage
161
+ - Don't criticize style, focus on substance
162
+ - Don't suggest adding features, only removing or clarifying
163
+ - If something is genuinely good, say so
164
+ - Don't assume malice in unclear requirements
165
+
166
+ ## Completion
167
+
168
+ Critique is complete when:
169
+ - All four dimensions analyzed
170
+ - Issues prioritized by severity
171
+ - Actionable recommendations provided
172
+ - Overall recommendation given
173
+
174
+ After outputting critique, offer to discuss any point in detail or help revise the PRD.
@@ -0,0 +1,146 @@
1
+ ---
2
+ name: flux-researcher
3
+ description: Researches unfamiliar technologies, libraries, and APIs. Use proactively when user mentions tech that may need investigation during PRD interviews, or when explicitly asked to research something. Auto-triggers when confidence < 70%.
4
+ tools: WebFetch, WebSearch, Read, mcp__context7__resolve-library-id, mcp__context7__query-docs
5
+ model: sonnet
6
+ ---
7
+
8
+ # Flux Research Subagent
9
+
10
+ You are a technology research specialist for the Flux workflow system. Your role is to gather accurate, up-to-date information about technologies mentioned during PRD creation and planning.
11
+
12
+ ## When to Activate
13
+
14
+ Trigger research when:
15
+ - User mentions a library, framework, or API you're uncertain about
16
+ - User explicitly asks "research X" or "what is X?"
17
+ - User asks about comparisons ("X vs Y")
18
+ - During interview if user mentions unfamiliar tech stack
19
+ - Confidence in technical recommendation < 70%
20
+
21
+ ## Research Process
22
+
23
+ ### Step 1: Identify Questions
24
+ What do we need to know?
25
+ - What is this technology?
26
+ - What problems does it solve?
27
+ - Is it actively maintained?
28
+ - What are the alternatives?
29
+ - How does it fit the user's context?
30
+
31
+ ### Step 2: Library Documentation (Context7)
32
+ For libraries and frameworks:
33
+
34
+ 1. **Resolve library ID:**
35
+ ```
36
+ mcp__context7__resolve-library-id
37
+ - libraryName: "{library name}"
38
+ - query: "{what the user is trying to accomplish}"
39
+ ```
40
+
41
+ 2. **Query docs:**
42
+ ```
43
+ mcp__context7__query-docs
44
+ - libraryId: "{resolved id}"
45
+ - query: "{specific question about usage}"
46
+ ```
47
+
48
+ Context7 provides up-to-date documentation with code examples.
49
+
50
+ ### Step 3: Web Research
51
+ For broader context:
52
+
53
+ 1. **WebSearch** for:
54
+ - "{library} vs alternatives 2024"
55
+ - "{library} production use cases"
56
+ - "{library} getting started"
57
+
58
+ 2. **WebFetch** on:
59
+ - Official documentation sites
60
+ - GitHub repository (check stars, recent commits)
61
+ - Comparison articles from reputable sources
62
+
63
+ ### Step 4: Synthesize
64
+ Combine findings into actionable insights relevant to the user's project.
65
+
66
+ ## Output Format
67
+
68
+ ```markdown
69
+ ## Research: {Technology Name}
70
+
71
+ ### What It Is
72
+ {1-2 sentence description}
73
+
74
+ ### Key Features
75
+ - {Feature 1}: {brief explanation}
76
+ - {Feature 2}: {brief explanation}
77
+ - {Feature 3}: {brief explanation}
78
+
79
+ ### Pros
80
+ - {Advantage 1}
81
+ - {Advantage 2}
82
+
83
+ ### Cons
84
+ - {Disadvantage 1}
85
+ - {Disadvantage 2}
86
+
87
+ ### Alternatives
88
+ | Alternative | Comparison |
89
+ |-------------|------------|
90
+ | {Alt 1} | {How it differs} |
91
+ | {Alt 2} | {How it differs} |
92
+
93
+ ### Recommendation
94
+ {Based on user's context, should they use this? Why or why not?}
95
+
96
+ ### Quick Start
97
+ {If relevant, brief code example or getting started steps}
98
+
99
+ ### Sources
100
+ - [{Source 1 title}]({url})
101
+ - [{Source 2 title}]({url})
102
+ ```
103
+
104
+ ## Context-Specific Research
105
+
106
+ ### For Web Applications
107
+ Focus on:
108
+ - Frontend framework compatibility
109
+ - Bundle size considerations
110
+ - SSR/SSG support
111
+ - Developer experience
112
+
113
+ ### For CLI Tools
114
+ Focus on:
115
+ - Runtime requirements (Node, Bun, etc.)
116
+ - Cross-platform support
117
+ - Dependency footprint
118
+
119
+ ### For APIs/Backend
120
+ Focus on:
121
+ - Performance characteristics
122
+ - Database compatibility
123
+ - Authentication options
124
+ - Deployment requirements
125
+
126
+ ### For Mobile Apps
127
+ Focus on:
128
+ - Native vs cross-platform
129
+ - Platform-specific limitations
130
+ - Performance on mobile devices
131
+
132
+ ## Boundaries
133
+
134
+ - Do NOT make up information - if unsure, say so
135
+ - Do NOT recommend against something without evidence
136
+ - Do NOT fetch more than 5 web pages per research task
137
+ - If research is inconclusive, present what you found and ask for clarification
138
+
139
+ ## Completion
140
+
141
+ Research is complete when:
142
+ - Core questions are answered
143
+ - User has enough info to make a decision
144
+ - Sources are cited
145
+
146
+ Output your findings in the format above, then offer to dive deeper on any aspect.
@@ -0,0 +1,149 @@
1
+ ---
2
+ name: flux-verifier
3
+ description: Verifies acceptance criteria coverage after implementation. Supports scope from multiple PRDs to a single epic. Runs tests, checks AC coverage, and generates concise verification reports.
4
+ tools: Read, Bash, Grep, Glob, mcp__flux__get_entity, mcp__flux__query_entities, mcp__flux__mark_criteria_met
5
+ model: haiku
6
+ ---
7
+
8
+ # Flux Verification Subagent
9
+
10
+ You are a quality verification agent. You verify that acceptance criteria are properly covered after implementation.
11
+
12
+ ## Scope
13
+
14
+ Verification can run at different levels:
15
+
16
+ | Scope | When | What's Verified |
17
+ |-------|------|-----------------|
18
+ | Multiple PRDs | `tag:phase-3` implementation complete | All epics across PRDs |
19
+ | Single PRD | PRD implementation complete | All epics in PRD |
20
+ | Single Epic | Epic tasks complete | All tasks in epic |
21
+
22
+ ## Verification Process
23
+
24
+ ### Step 1: Gather Data
25
+
26
+ Based on scope, fetch all relevant criteria:
27
+
28
+ ```typescript
29
+ // For PRD(s)
30
+ for (const prd of prds) {
31
+ const epics = query_entities({ type: 'epic', prd_ref: prd.ref })
32
+ // get tasks and criteria for each
33
+ }
34
+
35
+ // For single epic
36
+ get_entity({ ref: epicRef, include: ['tasks', 'criteria'] })
37
+ ```
38
+
39
+ ### Step 2: Run Tests
40
+
41
+ ```bash
42
+ # Run full test suite
43
+ bun test
44
+ # or
45
+ npm test
46
+ ```
47
+
48
+ Capture: pass/fail count, any failures.
49
+
50
+ ### Step 3: Categorize & Count Criteria
51
+
52
+ ```
53
+ [auto] criteria → must have passing test
54
+ [manual] criteria → needs user verification
55
+ ```
56
+
57
+ ### Step 4: Generate Report
58
+
59
+ **Keep it concise.** One-line summary per epic, details only for issues.
60
+
61
+ ```markdown
62
+ ## Verification Report
63
+
64
+ **Scope:** {PRD ref(s) or Epic ref}
65
+ **Tests:** ✅ 42 passed | ❌ 0 failed
66
+
67
+ | Epic | Auto | Manual | Status |
68
+ |------|------|--------|--------|
69
+ | FP-E14 | 8/8 ✅ | 2 pending | READY |
70
+ | FP-E15 | 5/6 ⚠️ | 1 pending | NEEDS_FIX |
71
+
72
+ ### Issues
73
+ - FP-E15: Missing test for "validates email format"
74
+
75
+ ### Manual Verification Checklist
76
+ - [ ] FP-E14: Error messages are user-friendly → Check message clarity
77
+ - [ ] FP-E14: UI renders on mobile → Test on phone
78
+ - [ ] FP-E15: Loading feels smooth → Test on slow network
79
+
80
+ ### Suggested Manual Test Cases
81
+
82
+ For criteria without explicit verification steps:
83
+
84
+ 1. **"User can cancel operation"**
85
+ - Start a long operation
86
+ - Press Cancel or Ctrl+C
87
+ - Verify operation stops and state is clean
88
+
89
+ 2. **"Form validates correctly"**
90
+ - Submit empty form → expect validation errors
91
+ - Submit with invalid email → expect email error
92
+ - Submit valid data → expect success
93
+
94
+ ### Recommendation
95
+ {READY | NEEDS_FIX | BLOCKED}: {one-line reason}
96
+ ```
97
+
98
+ ## Suggesting Manual Test Cases
99
+
100
+ When `[manual]` criteria lack explicit verification steps (no `→ Verify:`), suggest test cases:
101
+
102
+ | Criterion Pattern | Suggested Test |
103
+ |-------------------|----------------|
104
+ | "renders correctly" | Visual check on target device/browser |
105
+ | "feels smooth/fast" | Test on slow network/device |
106
+ | "user-friendly" | Have someone unfamiliar try it |
107
+ | "accessible" | Test with screen reader, keyboard nav |
108
+ | "works offline" | Disable network, test functionality |
109
+ | "handles errors" | Trigger error conditions, check recovery |
110
+
111
+ ## Marking Criteria Met
112
+
113
+ ```typescript
114
+ // Only auto-mark [auto] criteria when tests pass
115
+ mark_criteria_met({ criteria_id: criterionId })
116
+ ```
117
+
118
+ Leave `[manual]` criteria for user to confirm after verification.
119
+
120
+ ## Output to Orchestrator
121
+
122
+ **Concise format:**
123
+
124
+ ```
125
+ ## Verification: {PASSED | NEEDS_FIX | BLOCKED}
126
+
127
+ Tests: 42/42 ✅
128
+ Auto AC: 15/16 (1 missing test)
129
+ Manual AC: 4 pending
130
+
131
+ Issues:
132
+ - {issue 1}
133
+
134
+ Manual Checklist:
135
+ - [ ] {item 1}
136
+ - [ ] {item 2}
137
+
138
+ Suggested Tests:
139
+ - {suggestion if no explicit steps}
140
+ ```
141
+
142
+ ## Boundaries
143
+
144
+ - **DO** run tests and report results
145
+ - **DO** keep reports concise
146
+ - **DO** suggest manual test cases when steps are missing
147
+ - **DON'T** mark manual criteria as met
148
+ - **DON'T** write new tests or modify code
149
+ - **DON'T** generate verbose reports - be brief
@@ -0,0 +1,235 @@
1
+ #!/usr/bin/env node
2
+
3
+ const fs = require("fs");
4
+ const path = require("path");
5
+ const os = require("os");
6
+ const readline = require("readline");
7
+
8
+ const args = process.argv.slice(2);
9
+
10
+ if (args[0] === "serve") {
11
+ import("../dist/server/index.js").catch((err) => {
12
+ console.error("Failed to start Flux MCP server:", err.message);
13
+ process.exit(1);
14
+ });
15
+ } else {
16
+ runInstaller();
17
+ }
18
+
19
+ function runInstaller() {
20
+ const cyan = "\x1b[36m";
21
+ const green = "\x1b[32m";
22
+ const yellow = "\x1b[33m";
23
+ const dim = "\x1b[2m";
24
+ const reset = "\x1b[0m";
25
+ const pkg = require("../package.json");
26
+
27
+ const banner = `
28
+ ${cyan} ███████╗██╗ ██╗ ██╗██╗ ██╗
29
+ ██╔════╝██║ ██║ ██║╚██╗██╔╝
30
+ █████╗ ██║ ██║ ██║ ╚███╔╝
31
+ ██╔══╝ ██║ ██║ ██║ ██╔██╗
32
+ ██║ ███████╗╚██████╔╝██╔╝ ██╗
33
+ ╚═╝ ╚══════╝ ╚═════╝ ╚═╝ ╚═╝${reset}
34
+
35
+ Flux Plugin ${dim}v${pkg.version}${reset}
36
+ AI-first workflow orchestration for Claude Code
37
+ `;
38
+
39
+ const hasGlobal = args.includes("--global") || args.includes("-g");
40
+ const hasLocal = args.includes("--local") || args.includes("-l");
41
+ const hasHelp = args.includes("--help") || args.includes("-h");
42
+
43
+ console.log(banner);
44
+
45
+ if (hasHelp) {
46
+ console.log(` ${yellow}Usage:${reset} npx @cliangdev/flux-plugin [options]
47
+
48
+ ${yellow}Options:${reset}
49
+ ${cyan}-g, --global${reset} Install globally (to ~/.claude)
50
+ ${cyan}-l, --local${reset} Install locally (to ./.claude in current directory)
51
+ ${cyan}-h, --help${reset} Show this help message
52
+
53
+ ${yellow}Examples:${reset}
54
+ ${dim}# Interactive installation${reset}
55
+ npx @cliangdev/flux-plugin
56
+
57
+ ${dim}# Install globally (all projects)${reset}
58
+ npx @cliangdev/flux-plugin --global
59
+
60
+ ${dim}# Install locally (current project only)${reset}
61
+ npx @cliangdev/flux-plugin --local
62
+ `);
63
+ process.exit(0);
64
+ }
65
+
66
+ function copyDir(src, dest) {
67
+ fs.mkdirSync(dest, { recursive: true });
68
+ const entries = fs.readdirSync(src, { withFileTypes: true });
69
+
70
+ for (const entry of entries) {
71
+ const srcPath = path.join(src, entry.name);
72
+ const destPath = path.join(dest, entry.name);
73
+
74
+ if (entry.isDirectory()) {
75
+ copyDir(srcPath, destPath);
76
+ } else {
77
+ fs.copyFileSync(srcPath, destPath);
78
+ }
79
+ }
80
+ }
81
+
82
+ function readJson(filePath) {
83
+ if (fs.existsSync(filePath)) {
84
+ try {
85
+ return JSON.parse(fs.readFileSync(filePath, "utf8"));
86
+ } catch {
87
+ return {};
88
+ }
89
+ }
90
+ return {};
91
+ }
92
+
93
+ function writeJson(filePath, data) {
94
+ fs.writeFileSync(filePath, JSON.stringify(data, null, 2) + "\n");
95
+ }
96
+
97
+ function install(isGlobal) {
98
+ const src = path.join(__dirname, "..");
99
+ const claudeDir = isGlobal
100
+ ? path.join(os.homedir(), ".claude")
101
+ : path.join(process.cwd(), ".claude");
102
+ const locationLabel = isGlobal ? "~/.claude" : "./.claude";
103
+
104
+ console.log(` Installing to ${cyan}${locationLabel}${reset}\n`);
105
+
106
+ fs.mkdirSync(claudeDir, { recursive: true });
107
+
108
+ const commandsSrc = path.join(src, "commands");
109
+ if (fs.existsSync(commandsSrc)) {
110
+ const commandsDest = path.join(claudeDir, "commands");
111
+ const fluxSubDir = path.join(commandsDest, "flux");
112
+ fs.mkdirSync(fluxSubDir, { recursive: true });
113
+
114
+ const commandFiles = fs.readdirSync(commandsSrc);
115
+ for (const file of commandFiles) {
116
+ if (file.endsWith(".md")) {
117
+ const name = file.replace(".md", "");
118
+ if (name === "flux") {
119
+ fs.copyFileSync(
120
+ path.join(commandsSrc, file),
121
+ path.join(commandsDest, file)
122
+ );
123
+ console.log(` ${green}✓${reset} Installed command: /flux`);
124
+ } else {
125
+ fs.copyFileSync(
126
+ path.join(commandsSrc, file),
127
+ path.join(fluxSubDir, file)
128
+ );
129
+ console.log(` ${green}✓${reset} Installed command: /flux:${name}`);
130
+ }
131
+ }
132
+ }
133
+ }
134
+
135
+ const skillsSrc = path.join(src, "skills");
136
+ if (fs.existsSync(skillsSrc)) {
137
+ const skillsDest = path.join(claudeDir, "skills");
138
+ fs.mkdirSync(skillsDest, { recursive: true });
139
+
140
+ const skillDirs = fs.readdirSync(skillsSrc, { withFileTypes: true });
141
+ for (const dir of skillDirs) {
142
+ if (dir.isDirectory()) {
143
+ copyDir(
144
+ path.join(skillsSrc, dir.name),
145
+ path.join(skillsDest, dir.name)
146
+ );
147
+ console.log(` ${green}✓${reset} Installed skill: ${dir.name}`);
148
+ }
149
+ }
150
+ }
151
+
152
+ const agentsSrc = path.join(src, "agents");
153
+ if (fs.existsSync(agentsSrc)) {
154
+ const agentsDest = path.join(claudeDir, "agents");
155
+ fs.mkdirSync(agentsDest, { recursive: true });
156
+
157
+ const agentFiles = fs.readdirSync(agentsSrc);
158
+ for (const file of agentFiles) {
159
+ if (file.endsWith(".md")) {
160
+ fs.copyFileSync(
161
+ path.join(agentsSrc, file),
162
+ path.join(agentsDest, file)
163
+ );
164
+ const name = file.replace(".md", "");
165
+ console.log(` ${green}✓${reset} Installed agent: ${name}`);
166
+ }
167
+ }
168
+ }
169
+
170
+ const mcpConfigPath = isGlobal
171
+ ? path.join(os.homedir(), ".claude.json")
172
+ : path.join(process.cwd(), ".mcp.json");
173
+
174
+ const mcpConfig = readJson(mcpConfigPath);
175
+
176
+ if (!mcpConfig.mcpServers) {
177
+ mcpConfig.mcpServers = {};
178
+ }
179
+
180
+ mcpConfig.mcpServers.flux = {
181
+ command: "npx",
182
+ args: ["-y", "@cliangdev/flux-plugin", "serve"],
183
+ };
184
+
185
+ writeJson(mcpConfigPath, mcpConfig);
186
+ console.log(
187
+ ` ${green}✓${reset} Configured MCP server in ${isGlobal ? "~/.claude.json" : "./.mcp.json"}`
188
+ );
189
+
190
+ const versionFile = path.join(claudeDir, "flux-version");
191
+ fs.writeFileSync(versionFile, pkg.version);
192
+
193
+ console.log(`
194
+ ${green}Done!${reset} Restart Claude Code and run ${cyan}/flux${reset} to get started.
195
+
196
+ ${dim}Commands available:${reset}
197
+ /flux - Project status and guidance
198
+ /flux:prd - Create or refine PRDs
199
+ /flux:breakdown - Break PRDs into epics and tasks
200
+ /flux:implement - Implement tasks with TDD
201
+
202
+ ${dim}Learn more:${reset} https://github.com/cliangdev/flux-plugin
203
+ `);
204
+ }
205
+
206
+ function promptLocation() {
207
+ const rl = readline.createInterface({
208
+ input: process.stdin,
209
+ output: process.stdout,
210
+ });
211
+
212
+ console.log(` ${yellow}Where would you like to install?${reset}
213
+
214
+ ${cyan}1${reset}) Global ${dim}(~/.claude)${reset} - available in all projects
215
+ ${cyan}2${reset}) Local ${dim}(./.claude)${reset} - this project only
216
+ `);
217
+
218
+ rl.question(` Choice ${dim}[1]${reset}: `, (answer) => {
219
+ rl.close();
220
+ const choice = answer.trim() || "1";
221
+ install(choice !== "2");
222
+ });
223
+ }
224
+
225
+ if (hasGlobal && hasLocal) {
226
+ console.error(` ${yellow}Cannot specify both --global and --local${reset}`);
227
+ process.exit(1);
228
+ } else if (hasGlobal) {
229
+ install(true);
230
+ } else if (hasLocal) {
231
+ install(false);
232
+ } else {
233
+ promptLocation();
234
+ }
235
+ }
@@ -1,4 +1,5 @@
1
1
  ---
2
+ name: flux:breakdown
2
3
  description: Break approved PRD into dependency-ordered epics and tasks
3
4
  allowed-tools: mcp__flux__*, Read, AskUserQuestion
4
5
  ---
package/commands/flux.md CHANGED
@@ -1,4 +1,5 @@
1
1
  ---
2
+ name: flux
2
3
  description: AI-first workflow orchestration for spec-driven development
3
4
  allowed-tools: mcp__flux__*
4
5
  ---
@@ -1,4 +1,5 @@
1
1
  ---
2
+ name: flux:implement
2
3
  description: Implement epics and tasks with orchestrator/subagent architecture
3
4
  allowed-tools: mcp__flux__*, Read, Bash, Task, AskUserQuestion
4
5
  ---
package/commands/prd.md CHANGED
@@ -1,4 +1,5 @@
1
1
  ---
2
+ name: flux:prd
2
3
  description: Create or refine PRDs through guided interview
3
4
  allowed-tools: mcp__flux__*, AskUserQuestion
4
5
  ---
@@ -22481,7 +22481,6 @@ var config2 = {
22481
22481
  };
22482
22482
 
22483
22483
  // src/server/db/index.ts
22484
- import { Database } from "bun:sqlite";
22485
22484
  import { existsSync as existsSync2, mkdirSync } from "node:fs";
22486
22485
 
22487
22486
  // src/server/utils/logger.ts
@@ -22584,6 +22583,43 @@ CREATE INDEX IF NOT EXISTS idx_tasks_status ON tasks(status);
22584
22583
  CREATE INDEX IF NOT EXISTS idx_criteria_parent ON acceptance_criteria(parent_type, parent_id);
22585
22584
  `;
22586
22585
 
22586
+ // src/server/db/sqlite.ts
22587
+ var isBun = typeof process !== "undefined" && !!process.versions?.bun;
22588
+ var DatabaseImpl;
22589
+ if (isBun) {
22590
+ const { Database: BunDatabase } = await import("bun:sqlite");
22591
+ DatabaseImpl = BunDatabase;
22592
+ } else {
22593
+ const BetterSqlite3 = (await import("better-sqlite3")).default;
22594
+
22595
+ class BetterSqlite3Wrapper {
22596
+ db;
22597
+ constructor(path) {
22598
+ this.db = new BetterSqlite3(path);
22599
+ }
22600
+ query(sql) {
22601
+ const stmt = this.db.prepare(sql);
22602
+ return {
22603
+ get: (...params) => stmt.get(...params),
22604
+ all: (...params) => stmt.all(...params),
22605
+ run: (...params) => {
22606
+ stmt.run(...params);
22607
+ }
22608
+ };
22609
+ }
22610
+ exec(sql) {
22611
+ this.db.exec(sql);
22612
+ }
22613
+ run(sql) {
22614
+ this.db.exec(sql);
22615
+ }
22616
+ close() {
22617
+ this.db.close();
22618
+ }
22619
+ }
22620
+ DatabaseImpl = BetterSqlite3Wrapper;
22621
+ }
22622
+
22587
22623
  // src/server/db/ids.ts
22588
22624
  function generateId(prefix = "") {
22589
22625
  const timestamp = Date.now().toString(36);
@@ -22686,7 +22722,7 @@ function initDb() {
22686
22722
  mkdirSync(config2.fluxPath, { recursive: true });
22687
22723
  }
22688
22724
  logger.info(`Opening database: ${config2.dbPath}`);
22689
- db = new Database(config2.dbPath);
22725
+ db = new DatabaseImpl(config2.dbPath);
22690
22726
  db.run("PRAGMA foreign_keys = ON");
22691
22727
  db.exec(SCHEMA);
22692
22728
  logger.info("Database initialized successfully");
@@ -86184,14 +86220,7 @@ var getStatsTool = {
86184
86220
  handler: handler8
86185
86221
  };
86186
86222
  // src/version.ts
86187
- import { readFileSync as readFileSync6 } from "node:fs";
86188
- import { dirname as dirname2, join as join2 } from "node:path";
86189
- import { fileURLToPath } from "node:url";
86190
- var __filename2 = fileURLToPath(import.meta.url);
86191
- var __dirname2 = dirname2(__filename2);
86192
- var packageJsonPath = join2(__dirname2, "..", "package.json");
86193
- var packageJson = JSON.parse(readFileSync6(packageJsonPath, "utf-8"));
86194
- var VERSION = packageJson.version;
86223
+ var VERSION = "0.1.0";
86195
86224
 
86196
86225
  // src/server/tools/get-version.ts
86197
86226
  var inputSchema10 = exports_external.object({});
@@ -86208,15 +86237,15 @@ var getVersionTool = {
86208
86237
  handler: handler9
86209
86238
  };
86210
86239
  // src/server/tools/init-project.ts
86211
- import { existsSync as existsSync8, mkdirSync as mkdirSync4, readFileSync as readFileSync7, writeFileSync as writeFileSync4 } from "node:fs";
86212
- import { dirname as dirname3, join as join3 } from "node:path";
86240
+ import { existsSync as existsSync8, mkdirSync as mkdirSync4, readFileSync as readFileSync6, writeFileSync as writeFileSync4 } from "node:fs";
86241
+ import { dirname as dirname2, join as join2 } from "node:path";
86213
86242
  function getStatusLineBinaryPath() {
86214
- const thisDir = dirname3(new URL(import.meta.url).pathname);
86215
- return join3(thisDir, "..", "..", "..", "bin", "flux-status");
86243
+ const thisDir = dirname2(new URL(import.meta.url).pathname);
86244
+ return join2(thisDir, "..", "..", "..", "bin", "flux-status");
86216
86245
  }
86217
86246
  function setupClaudeSettings(projectRoot) {
86218
- const claudeDir = join3(projectRoot, ".claude");
86219
- const settingsPath = join3(claudeDir, "settings.local.json");
86247
+ const claudeDir = join2(projectRoot, ".claude");
86248
+ const settingsPath = join2(claudeDir, "settings.local.json");
86220
86249
  const statusBinaryPath = getStatusLineBinaryPath();
86221
86250
  if (!existsSync8(statusBinaryPath)) {
86222
86251
  return;
@@ -86227,7 +86256,7 @@ function setupClaudeSettings(projectRoot) {
86227
86256
  let settings = {};
86228
86257
  if (existsSync8(settingsPath)) {
86229
86258
  try {
86230
- settings = JSON.parse(readFileSync7(settingsPath, "utf-8"));
86259
+ settings = JSON.parse(readFileSync6(settingsPath, "utf-8"));
86231
86260
  } catch {
86232
86261
  settings = {};
86233
86262
  }
@@ -86393,7 +86422,7 @@ var queryEntitiesTool = {
86393
86422
  handler: handler11
86394
86423
  };
86395
86424
  // src/server/tools/render-status.ts
86396
- import { existsSync as existsSync9, readFileSync as readFileSync8 } from "node:fs";
86425
+ import { existsSync as existsSync9, readFileSync as readFileSync7 } from "node:fs";
86397
86426
 
86398
86427
  // src/utils/display.ts
86399
86428
  function renderProgressBar(percentage, width) {
@@ -86506,7 +86535,7 @@ function getProjectInfo() {
86506
86535
  return null;
86507
86536
  }
86508
86537
  try {
86509
- const content = readFileSync8(config2.projectJsonPath, "utf-8");
86538
+ const content = readFileSync7(config2.projectJsonPath, "utf-8");
86510
86539
  const project = JSON.parse(content);
86511
86540
  return {
86512
86541
  name: project.name || "Unnamed Project",
package/manifest.json ADDED
@@ -0,0 +1,15 @@
1
+ {
2
+ "$schema": "./manifest.schema.json",
3
+ "version": "1.0.0",
4
+ "structure": {
5
+ "commands": ["flux.md", "prd.md", "breakdown.md", "implement.md"],
6
+ "skills": [
7
+ "agent-creator",
8
+ "epic-template",
9
+ "flux-orchestrator",
10
+ "prd-template"
11
+ ],
12
+ "agents": ["coder.md", "critic.md", "researcher.md", "verifier.md"],
13
+ "hooks": []
14
+ }
15
+ }
package/package.json CHANGED
@@ -1,25 +1,29 @@
1
1
  {
2
2
  "name": "@cliangdev/flux-plugin",
3
- "version": "0.0.0-dev.8e9707e",
3
+ "version": "0.0.0-dev.950606c",
4
4
  "description": "Claude Code plugin for AI-first workflow orchestration with MCP server",
5
5
  "type": "module",
6
6
  "main": "./dist/server/index.js",
7
7
  "bin": {
8
- "flux-plugin": "./dist/server/index.js"
8
+ "flux-plugin": "./bin/install.cjs"
9
9
  },
10
10
  "files": [
11
+ "bin/",
11
12
  "dist/",
12
13
  "skills/",
13
- "commands/"
14
+ "commands/",
15
+ "agents/",
16
+ "manifest.json"
14
17
  ],
15
18
  "scripts": {
16
19
  "dev": "bun run src/server/index.ts",
17
- "build": "bun build src/server/index.ts --outdir dist/server --target node",
20
+ "build": "bun build src/server/index.ts --outdir dist/server --target node --external better-sqlite3",
18
21
  "postbuild": "node -e \"const fs=require('fs');const f='dist/server/index.js';const c=fs.readFileSync(f,'utf-8');if(!c.startsWith('#!/usr/bin/env node')){fs.writeFileSync(f,'#!/usr/bin/env node\\n'+c)}\"",
19
22
  "build:compile": "bun build --compile --outfile bin/flux-server src/server/index.ts && bun build --compile --outfile bin/flux-status src/status-line/index.ts",
20
23
  "build:compile:server": "bun build --compile --outfile bin/flux-server src/server/index.ts",
21
24
  "build:compile:status": "bun build --compile --outfile bin/flux-status src/status-line/index.ts",
22
- "prepublishOnly": "bun run build",
25
+ "validate": "node scripts/validate-structure.cjs",
26
+ "prepublishOnly": "bun run validate && bun run build",
23
27
  "test": "bun test",
24
28
  "test:linear-description": "bun run src/server/adapters/__tests__/linear-description-test.ts",
25
29
  "typecheck": "tsc --noEmit",
@@ -47,12 +51,14 @@
47
51
  "license": "MIT",
48
52
  "devDependencies": {
49
53
  "@biomejs/biome": "^2.3.11",
54
+ "@types/better-sqlite3": "^7.6.13",
50
55
  "@types/bun": "^1.3.6",
51
56
  "typescript": "^5.0.0"
52
57
  },
53
58
  "dependencies": {
54
59
  "@linear/sdk": "^70.0.0",
55
60
  "@modelcontextprotocol/sdk": "^1.25.2",
61
+ "better-sqlite3": "^12.6.2",
56
62
  "chalk": "^5.4.1",
57
63
  "zod": "^4.3.5"
58
64
  },
@@ -1,5 +1,7 @@
1
1
  ---
2
+ name: flux:agent-creator
2
3
  description: Guide for creating effective subagents. Use when users want to create a new agent that extends Claude's capabilities with specialized knowledge, workflows, or tool integrations.
4
+ user-invocable: false
3
5
  ---
4
6
 
5
7
  # Agent Creator Skill
@@ -1,5 +1,7 @@
1
1
  ---
2
+ name: flux:epic-template
2
3
  description: Epic and task structure patterns for Flux. Use when breaking PRDs into epics and tasks. Epics should be self-contained with clear acceptance criteria.
4
+ user-invocable: false
3
5
  ---
4
6
 
5
7
  # Epic Template Skill
@@ -1,5 +1,7 @@
1
1
  ---
2
+ name: flux:flux-orchestrator
2
3
  description: Orchestrates Flux workflows based on project context
4
+ user-invocable: false
3
5
  ---
4
6
 
5
7
  # Flux Orchestrator Skill
@@ -1,5 +1,7 @@
1
1
  ---
2
+ name: flux:prd-template
2
3
  description: PRD structure and patterns for Flux. Use when creating or refining product requirement documents. PRDs should be concise for humans but detailed enough for AI agents to implement.
4
+ user-invocable: false
3
5
  ---
4
6
 
5
7
  # PRD Template Skill