bmad-orchestrator
Orchestrates BMAD workflows for structured AI-driven development. Routes work across Analysis, Planning, Solutioning, and Implementation phases with TEA (Task-Execute-Architect) cycles for structured execution.
Packaged view
This page reorganizes the original catalog entry around fit, installability, and workflow context first. The original raw source lives below.
Install command
npx @skill-hub/cli install supercent-io-skills-template-bmad-orchestrator
Repository
Skill path: .agent-skills/bmad-orchestrator
Orchestrates BMAD workflows for structured AI-driven development. Routes work across Analysis, Planning, Solutioning, and Implementation phases with TEA (Task-Execute-Architect) cycles for structured execution.
Open repositoryBest for
Primary workflow: Research & Ops.
Technical facets: Full Stack, Data / AI.
Target audience: everyone.
License: Unknown.
Original source
Catalog source: SkillHub Club.
Repository owner: supercent-io.
This is still a mirrored public skill entry. Review the repository before installing into production workflows.
What it helps with
- Install bmad-orchestrator into Claude Code, Codex CLI, Gemini CLI, or OpenCode workflows
- Review https://github.com/supercent-io/skills-template before adding bmad-orchestrator to shared team environments
- Use bmad-orchestrator for development workflows
Works across
Favorites: 0.
Sub-skills: 0.
Aggregator: No.
Original source / Raw SKILL.md
---
name: bmad-orchestrator
description: Orchestrates BMAD workflows for structured AI-driven development. Routes work across Analysis, Planning, Solutioning, and Implementation phases with TEA (Task-Execute-Architect) cycles for structured execution.
allowed-tools: Read Write Bash Grep Glob
metadata:
tags: bmad, orchestrator, workflow, planning, implementation, tea, ssd
platforms: Claude, Gemini, Codex, OpenCode
keyword: bmad
version: 1.3.0
source: user-installed skill
---
# bmad-orchestrator — BMAD Workflow Orchestration with SSD
## When to use this skill
- Initializing BMAD in a new project (with or without SSD)
- Running structured TEA cycles within each BMAD phase
- Checking and resuming BMAD/SSD workflow status
- Routing work across Analysis, Planning, Solutioning, and Implementation
- Managing structured handoff and cross-phase traceability between phases
---
## What is SSD (Structured System Design)?
SSD is a meta-framework that embeds **TEA cycles** within each BMAD phase, transforming phase execution from "produce a document" into a structured loop:
```
T → Task: Decompose the phase into concrete tasks with assigned agents
E → Execute: Run tasks in parallel via multi-agent team execution
A → Architect: Validate outputs for coherence, completeness, and cross-phase traceability
```
Each BMAD phase becomes an independent TEA cycle. The architect validation step produces a `PASS`, `PASS_WITH_WARNINGS`, `REVISE`, or `FAIL` verdict. Only after `PASS` (or `PASS_WITH_WARNINGS`) does the human review gate (plannotator) open. This ensures automated structural correctness before human review.
### SSD vs. Standard BMAD
| Aspect | Standard BMAD | BMAD + SSD |
|--------|--------------|------------|
| Phase execution | Document production (opaque) | TEA cycle: Decompose → Execute → Validate |
| Task decomposition | None | Explicit per-phase task lists with agent assignments |
| Execution surface | Manual / single-agent | Multi-agent Team execution (`/team`) |
| Validation | Human plannotator review | Automated architect review → then plannotator |
| Cross-phase traceability | None | Requirement coverage matrix per phase transition |
| State tracking | `bmm-workflow-status.yaml` | + `.omc/state/ssd-state.json` with task-level granularity |
---
## Installation
```bash
npx skills add https://github.com/akillness/oh-my-skills --skill bmad-orchestrator
```
## Notes for Codex Usage
`bmad-orchestrator`'s default execution path is Claude Code.
To run the same flow directly in Codex, we recommend operating BMAD stages via a higher-level orchestration path such as `omx`/`ohmg`.
---
## Control Model
BMAD phase routing uses the same three-layer abstraction as JEO:
- `settings`: platform-specific runtime configuration such as Claude hooks, Codex/Gemini instructions, and MCP setup
- `rules`: phase constraints such as "do not advance before the current phase document is approved" and "do not reopen the same unchanged phase document for review"
- `hooks`: platform callbacks such as Claude `ExitPlanMode`, Codex `notify`, or Gemini `AfterAgent`
For BMAD phase gates, the intended rule is strict:
- Review the current phase document before moving forward
- If the document hash has not changed since the last terminal review result, do not relaunch plannotator
- Only a revised document resets the gate and permits another review cycle
- **With SSD**: plannotator gate requires `architect_verdict: "PASS"` or `"PASS_WITH_WARNINGS"` in `ssd-state.json` before opening
---
## Platform Support Status
| Platform | Current support mode | Requirements |
|---|---|---|
| Gemini CLI | Native (recommended) | Register the `bmad` keyword, then run `/workflow-init` |
| Claude Code | Native (recommended) | Install skill + `remember` pattern |
| OpenCode | Orchestration integration | Use an `omx`/`ohmg`-style bridge |
| Codex | Orchestration integration | Use an `omx`/`ohmg`-style bridge |
---
## Standard BMAD Commands
```text
/workflow-init [--ssd]
/workflow-status
```
Typical flow:
1. Run `/workflow-init` to bootstrap BMAD config (add `--ssd` to also initialize SSD state).
2. Move through phases: Analysis → Planning → Solutioning → Implementation.
3. Run `/workflow-status` any time to inspect current phase and progress.
| Action | Command |
|--------|---------|
| Initialize BMAD | `/workflow-init` |
| Initialize BMAD + SSD | `/workflow-init --ssd` |
| Check BMAD/SSD status | `/workflow-status` |
---
## SSD Commands (TEA Integration)
Use these commands to run structured TEA cycles within each BMAD phase:
| Command | TEA Step | Purpose |
|---------|----------|---------|
| `/ssd-init` | Setup | Initialize `.omc/state/ssd-state.json` alongside BMAD (called automatically by `/workflow-init --ssd`) |
| `/ssd-decompose` | **T**ask | Decompose current phase into concrete tasks with agent assignments |
| `/ssd-execute` | **E**xecute | Dispatch decomposed tasks to agents via `/team` (multi-agent parallel execution) |
| `/ssd-validate` | **A**rchitect | Validate phase outputs for coherence, completeness, and cross-phase traceability |
| `/ssd-cycle` | T+E+A | Run the full TEA cycle for the current phase (decompose → execute → validate) |
| `/ssd-advance` | Transition | Advance to next phase after TEA cycle passes architect validation |
| `/ssd-status` | Status | Show SSD-enriched status: phase + TEA step + task progress + validation verdict |
### SSD Full Flow
```
/workflow-init --ssd
|
v
┌─────────────────────────────────────────────────────┐
│ PHASE N TEA CYCLE │
│ │
│ /ssd-decompose (or /ssd-cycle for full auto) │
│ | │
│ v │
│ [T] Task decomposition │
│ planner/analyst produces task list │
│ → ssd-state.json phases[N].tasks updated │
│ | │
│ v │
│ /ssd-execute │
│ | │
│ v │
│ [E] Multi-agent execution via /team │
│ TeamCreate → TaskCreate per subtask │
│ Agents: executor, analyst, designer, │
│ test-engineer, security-reviewer… │
│ → docs/ssd/phase-N/ artifacts produced │
│ → Phase document assembled from artifacts │
│ | │
│ v │
│ /ssd-validate │
│ | │
│ v │
│ [A] Architect validation │
│ fabric -p bmad_ssd_phase_review │
│ (fallback: architect agent via TaskCreate) │
│ | │
│ ├── PASS ──────────→ plannotator review │
│ │ | │
│ │ ┌────┴────┐ │
│ │ │ Approve │ Req Changes │
│ │ └────┬────┘ | │
│ │ | Loop to [E] │
│ │ v with feedback │
│ │ /ssd-advance │
│ │ → phase N+1 │
│ │ │
│ ├── PASS_WITH_WARNINGS → plannotator (warned) │
│ │ │
│ ├── REVISE → targeted re-execute specific │
│ │ tasks, then re-validate │
│ │ │
│ └── FAIL → full re-execute with changes, │
│ then re-validate │
│ (max 3 cycles, then escalate) │
└─────────────────────────────────────────────────────┘
```
---
## TEA Per-Phase Mapping
### Phase 1: Analysis
| TEA Step | Action | Agents | Output |
|----------|--------|--------|--------|
| **Task** | Decompose into: market research, user persona definition, competitive landscape, value proposition, constraint identification | `explore` (haiku) + `analyst` (opus) | Task list in `ssd-state.json` |
| **Execute** | Run tasks in parallel: research, persona, competitive data | `document-specialist`, `analyst`, `scientist` via Team | `docs/ssd/phase-1/*.md` |
| **Architect** | Validate: personas match value prop? Constraints conflict? Competitive gap real? | `architect` (opus) + fabric `bmad_ssd_phase_review` | Coherence report + PASS/FAIL/REVISE |
### Phase 2: Planning
| TEA Step | Action | Agents | Output |
|----------|--------|--------|--------|
| **Task** | Decompose into: functional requirements, non-functional requirements, user stories, acceptance criteria, UX specification | `planner` (opus) | Task list |
| **Execute** | Write functional/non-functional reqs from product brief; produce UX flows; draft acceptance criteria | `analyst`, `designer`, `test-engineer` via Team | PRD sections |
| **Architect** | Validate: requirements trace to product brief? Acceptance criteria testable? UX covers all user stories? | `architect` (opus) + fabric `bmad_ssd_phase_review` | Traceability matrix + verdict |
### Phase 3: Solutioning
| TEA Step | Action | Agents | Output |
|----------|--------|--------|--------|
| **Task** | Decompose into: component design, API contracts, data model, integration design, security design, performance design, technology selection | `architect` (opus) | Task list |
| **Execute** | Component/integration design; security design; performance design; technology evaluation | `architect`, `security-reviewer`, `quality-reviewer`, `document-specialist` via Team | Architecture sections |
| **Architect** | Validate: architecture fulfills PRD? API contracts consistent with user stories? Security design matches threat model? Run cross-phase traceability. | `architect` (opus) + `critic` (opus) + fabric `bmad_ssd_phase_review` | Architecture review + requirement coverage matrix |
### Phase 4: Implementation
| TEA Step | Action | Agents | Output |
|----------|--------|--------|--------|
| **Task** | Decompose sprint: epics → stories → implementation tasks (code, test, docs) | `planner` (opus) | Sprint plan with task breakdown |
| **Execute** | Implement code; write tests; update docs; resolve build issues | `executor`, `test-engineer`, `writer`, `build-fixer` via Team | Code, tests, docs per story |
| **Architect** | Validate: implementation matches architecture? Tests cover acceptance criteria? API contract honored? | `verifier` (sonnet) + `code-reviewer` (opus) + fabric `bmad_ssd_phase_review` | Implementation coherence report |
---
## Fabric Pattern: `bmad_ssd_phase_review`
Install this custom pattern for automated architect validation:
```bash
mkdir -p ~/.config/fabric/patterns/bmad_ssd_phase_review
cat > ~/.config/fabric/patterns/bmad_ssd_phase_review/system.md << 'EOF'
# IDENTITY AND PURPOSE
You are an expert system architect performing a structured phase review for the BMAD Structured System Design (SSD) framework. Your job is to validate that a phase document is internally coherent, externally consistent with prior phase artifacts, and complete enough to advance to the next phase.
Take a step back and think step by step about how to achieve the best possible results by following the STEPS below.
# STEPS
1. IDENTIFY the current BMAD phase (Analysis, Planning, Solutioning, Implementation) from the input metadata.
2. PARSE the phase document and extract all claims, requirements, design decisions, and deliverables.
3. INTERNAL COHERENCE CHECK:
- Are there contradictory statements within the document?
- Are all sections complete (no TODOs, placeholders, or TBDs)?
- Do quantitative claims have justification?
4. CROSS-PHASE TRACEABILITY CHECK (if prior phase artifacts are provided):
- Phase 2 (Planning): Does every PRD requirement trace to a product brief goal?
- Phase 3 (Solutioning): Does the architecture address every PRD functional requirement?
- Phase 4 (Implementation): Does every story map to an architecture component?
- Flag any orphaned items.
5. COMPLETENESS CHECK against BMAD level expectations:
- Level 0-1: Minimal viable coverage
- Level 2: Full requirement coverage with acceptance criteria
- Level 3: Comprehensive with integration points and risk analysis
- Level 4: Enterprise-grade with security, performance, and infrastructure coverage
6. RISK ASSESSMENT:
- Identify assumptions that could invalidate the phase output
- Flag unresolved dependencies
- Note scope creep relative to prior phase boundaries
7. PRODUCE a structured verdict.
# OUTPUT INSTRUCTIONS
- Output valid Markdown only.
- Begin with a `## Verdict` section: one of `PASS`, `PASS_WITH_WARNINGS`, `FAIL`, or `REVISE`.
- Follow with `## Internal Coherence` (findings with line references).
- Follow with `## Cross-Phase Traceability` (coverage matrix if applicable).
- Follow with `## Completeness` (missing sections or underspecified areas).
- Follow with `## Risks` (ranked by severity: critical, high, medium, low).
- Follow with `## Required Changes` (concrete, actionable items if verdict is FAIL or REVISE).
- Do not include warnings, disclaimers, or caveats outside the structured sections.
# INPUT
INPUT:
EOF
```
Usage in `/ssd-validate`:
```bash
# Pipe current phase doc + prior artifacts for cross-phase validation
{
echo "--- CURRENT PHASE DOCUMENT ---"
cat "$CURRENT_DOC"
echo "--- PRIOR PHASE ARTIFACTS ---"
for prior in "${PRIOR_DOCS[@]}"; do
echo "--- $(basename "$prior") ---"
cat "$prior"
done
} | fabric -p bmad_ssd_phase_review --stream > docs/ssd/phase-N/architect-review.md
# Phase 3 example: validate architecture against PRD
cat docs/architecture-myapp-2026-03-16.md | \
fabric -p bmad_ssd_phase_review \
--context "$(cat docs/prd-myapp-2026-03-16.md)" \
--stream
```
If `fabric` is not installed, `/ssd-validate` falls back to an `architect` agent:
```text
# In Claude Code session:
ssd validate — run architect review on the current phase document before advancing
```
---
## SSD State File Schema
Location: `.omc/state/ssd-state.json`
```json
{
"version": "1.0.0",
"project_name": "myapp",
"project_level": 2,
"active": true,
"current_phase": 2,
"created_at": "2026-03-16T10:00:00Z",
"updated_at": "2026-03-16T14:30:00Z",
"phases": {
"1": {
"name": "analysis",
"tea_step": "complete",
"tasks": {
"decomposed_at": "2026-03-16T10:05:00Z",
"items": [
{
"id": "p1-t1",
"name": "Market research",
"agent": "document-specialist",
"model": "sonnet",
"status": "completed",
"output_path": "docs/ssd/phase-1/market-research.md"
}
]
},
"architect_review": {
"verdict": "PASS",
"method": "fabric",
"pattern": "bmad_ssd_phase_review",
"report_path": "docs/ssd/phase-1/architect-review.md",
"reviewed_at": "2026-03-16T11:00:00Z"
},
"plannotator_review": {
"status": "approved",
"reviewed_at": "2026-03-16T11:30:00Z",
"document_hash": "abc123"
}
},
"2": {
"name": "planning",
"tea_step": "execute",
"tasks": {
"items": [
{
"id": "p2-t1",
"name": "Functional requirements extraction",
"agent": "analyst",
"model": "opus",
"status": "in_progress"
}
]
},
"architect_review": null,
"plannotator_review": null
}
},
"cross_phase_traceability": {
"phase_1_to_2": { "validated": true, "coverage": 1.0, "orphaned_items": [] },
"phase_2_to_3": { "validated": false },
"phase_3_to_4": { "validated": false }
}
}
```
**`tea_step` values**: `null` → `decompose` → `execute` → `validate` → `complete`
---
## plannotator Integration (Phase Review Gate)
Each BMAD phase produces a key document (PRD, Tech Spec, Architecture). Before transitioning to the next phase, review that document with **plannotator**.
**With SSD enabled**, plannotator only opens after `/ssd-validate` produces `architect_verdict: "PASS"` or `"PASS_WITH_WARNINGS"`. This ensures automated structural correctness before human review.
### Phase Review Pattern
```bash
# After /prd → docs/prd-myapp-2026-03-16.md is created
# With SSD: run /ssd-validate first, then phase-gate-review.sh
bash scripts/phase-gate-review.sh docs/prd-myapp-2026-03-16.md "PRD Review: myapp"
# After /architecture → docs/architecture-myapp-2026-03-16.md is created
bash scripts/phase-gate-review.sh docs/architecture-myapp-2026-03-16.md "Architecture Review: myapp"
```
Or submit the plan directly from your AI session:
```text
# In Claude Code after /prd completes:
planno — review the PRD before we proceed to Phase 3
```
### Phase Gate Flow (with SSD)
```
/prd completes → docs/prd-myapp.md created
↓
/ssd-validate runs (automated architect review)
↓ fabric -p bmad_ssd_phase_review
↓
PASS/PASS_WITH_WARNINGS?
↓ yes
phase-gate-review.sh opens plannotator UI
↓
[Approve] [Request Changes]
↓ ↓
Obsidian saved Agent revises doc
ssd-state updated /ssd-execute (targeted)
then /ssd-validate again
↓
/ssd-advance → Phase 3
```
### Quick Reference
| Phase | Document | Gate |
|-------|----------|------|
| Phase 1 → 2 | Product Brief | `bash scripts/phase-gate-review.sh docs/product-brief-*.md` |
| Phase 2 → 3 | PRD / Tech Spec | `bash scripts/phase-gate-review.sh docs/prd-*.md` |
| Phase 3 → 4 | Architecture | `bash scripts/phase-gate-review.sh docs/architecture-*.md` |
| Phase 4 done | Sprint Plan | `bash scripts/phase-gate-review.sh docs/sprint-status.yaml` |
---
## Integration with `/team` (OMC)
`/ssd-execute` maps directly to OMC's Team staged pipeline. When you run `/ssd-execute`:
1. Reads `ssd-state.json` for the current phase's task list
2. Calls `TeamCreate` with team name `ssd-phase-{N}-{project}`
3. Creates tasks via `TaskCreate` with agent routing from the TEA per-phase table
4. Monitors via `TaskList` until all tasks reach terminal state
5. Writes outputs to `docs/ssd/phase-{N}/`
6. Updates `ssd-state.json` with execution results
```text
# Trigger SSD execution for current phase (Claude Code)
ssd execute — run phase 2 planning tasks with multi-agent team
```
Or use directly with Team:
```text
/team 4:analyst "Execute BMAD Phase 2 planning: functional requirements, non-functional requirements, user stories, acceptance criteria based on product brief at docs/product-brief-myapp.md"
```
---
## Quick Start with SSD
```bash
# 1. Initialize BMAD with SSD enabled
/workflow-init --ssd
# 2. Run full TEA cycle for Phase 1 (Analysis)
/ssd-cycle
# 3. Check status after cycle
/ssd-status
# 4. When architect validates PASS, human review opens automatically
# (plannotator UI launches)
# 5. After approval, advance to Phase 2
/ssd-advance
# 6. Repeat for each phase
/ssd-cycle # Phase 2: Planning
/ssd-cycle # Phase 3: Solutioning
/ssd-cycle # Phase 4: Implementation
```
---
## Obsidian Save Format
Approved phase documents are saved to your Obsidian vault:
```yaml
---
created: 2026-03-16T10:00:00Z
source: plannotator
tags: [bmad, ssd, phase-2, prd, myapp]
ssd_architect_verdict: PASS
ssd_tea_cycle: 1
---
[[BMAD Plans]]
# PRD: myapp
...
```
---
## TOON Format Hook
If `~/.claude/hooks/toon-inject.mjs` is installed, the skill catalog is automatically injected into every prompt. See [bmad-orchestrator SKILL.md — TOON Format Integration] for details.
---
## Referenced Files
> The following files are referenced in this skill and included for context.
### scripts/phase-gate-review.sh
```bash
#!/bin/bash
# BMAD Phase Gate Review
# Submits a phase document to plannotator for review before phase transition.
# On approval, updates bmm-workflow-status.yaml and records Obsidian save path.
#
# Usage:
# bash scripts/phase-gate-review.sh <doc-file> [title]
#
# Examples:
# bash scripts/phase-gate-review.sh docs/prd-myapp-2026-02-22.md "PRD Review: myapp"
# bash scripts/phase-gate-review.sh docs/architecture-myapp-2026-02-22.md
set -e
# ── Args ──────────────────────────────────────────────────────────────────────
DOC_FILE="${1:-}"
TITLE="${2:-}"
if [ -z "$DOC_FILE" ]; then
echo "Usage: bash scripts/phase-gate-review.sh <doc-file> [title]"
echo ""
echo "Examples:"
echo " bash scripts/phase-gate-review.sh docs/prd-myapp-2026-02-22.md \"PRD Review: myapp\""
echo " bash scripts/phase-gate-review.sh docs/architecture-myapp-2026-02-22.md"
exit 1
fi
if [ ! -f "$DOC_FILE" ]; then
echo "Error: Document not found: $DOC_FILE"
exit 1
fi
# ── Defaults ──────────────────────────────────────────────────────────────────
BASENAME=$(basename "$DOC_FILE" .md)
TITLE="${TITLE:-Phase Review: $BASENAME}"
# Detect project name from config or dirname
PROJECT_NAME="project"
if [ -f "bmad/config.yaml" ]; then
if command -v yq &>/dev/null; then
PROJECT_NAME=$(yq eval '.project_name' bmad/config.yaml 2>/dev/null || echo "project")
else
PROJECT_NAME=$(grep "project_name:" bmad/config.yaml 2>/dev/null | head -1 | sed 's/.*: *"\?\([^"]*\)"\?/\1/' | tr -d '"' || echo "project")
fi
fi
# Detect phase from filename
PHASE_TAG="bmad"
if echo "$DOC_FILE" | grep -qi "product-brief\|brainstorm\|research"; then
PHASE_TAG="bmad,phase-1"
elif echo "$DOC_FILE" | grep -qi "prd\|tech-spec\|ux-design"; then
PHASE_TAG="bmad,phase-2"
elif echo "$DOC_FILE" | grep -qi "architecture\|solutioning"; then
PHASE_TAG="bmad,phase-3"
elif echo "$DOC_FILE" | grep -qi "sprint\|story\|dev"; then
PHASE_TAG="bmad,phase-4"
fi
# ── Colors ────────────────────────────────────────────────────────────────────
BLUE='\033[0;34m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
RED='\033[0;31m'
NC='\033[0m'
echo ""
echo -e "${BLUE}╔════════════════════════════════════════════╗${NC}"
echo -e "${BLUE}║ BMAD Phase Gate Review ║${NC}"
echo -e "${BLUE}╚════════════════════════════════════════════╝${NC}"
echo ""
echo -e "${BLUE}Document:${NC} $DOC_FILE"
echo -e "${BLUE}Title:${NC} $TITLE"
echo -e "${BLUE}Project:${NC} $PROJECT_NAME"
echo -e "${BLUE}Tags:${NC} $PHASE_TAG,$PROJECT_NAME"
echo ""
# ── Check plannotator ─────────────────────────────────────────────────────────
if ! command -v plannotator &>/dev/null; then
echo -e "${YELLOW}Warning: plannotator CLI not found.${NC}"
echo "Install: bash scripts/install.sh (from plannotator skill)"
echo ""
echo -e "${YELLOW}Manual review fallback:${NC}"
echo " Open the document and review manually, then update bmm-workflow-status.yaml"
echo ""
echo " Skipping plannotator gate — proceeding without review."
exit 0
fi
# ── Submit to plannotator ─────────────────────────────────────────────────────
echo -e "${BLUE}Submitting to plannotator...${NC}"
DOC_CONTENT=$(cat "$DOC_FILE")
# Submit via plannotator CLI (opens browser UI)
echo "$DOC_CONTENT" | plannotator submit \
--title "$TITLE" \
--stdin 2>/dev/null || {
# Fallback: use python3 to pipe content
python3 -c "
import sys, subprocess
content = open('$DOC_FILE').read()
proc = subprocess.run(
['plannotator', 'submit', '--title', '$TITLE', '--stdin'],
input=content.encode(),
capture_output=True
)
sys.exit(proc.returncode)
" 2>/dev/null || {
echo -e "${YELLOW}Could not auto-submit. Open plannotator manually:${NC}"
echo " plannotator"
echo " Then paste the content of: $DOC_FILE"
exit 0
}
}
# ── Update workflow status ─────────────────────────────────────────────────────
STATUS_FILE="docs/bmm-workflow-status.yaml"
WORKFLOW_NAME="$BASENAME"
# Extract workflow name by matching filename against bmm-workflow-status.yaml
# Handles hyphenated names like product-brief, tech-spec, ux-design
find_workflow_name() {
local doc_basename
doc_basename=$(basename "$DOC_FILE" .md)
local status_yaml="$STATUS_FILE"
if [ ! -f "$status_yaml" ]; then
echo ""
return
fi
if command -v yq &>/dev/null; then
# yq: find the name whose entry matches any leading segment of the filename
yq eval '.workflow_status[].name' "$status_yaml" 2>/dev/null | while IFS= read -r name; do
if [[ "$doc_basename" == "$name"* ]]; then
echo "$name"
return
fi
done | head -1
else
# python3 fallback: parse YAML names with grep/sed, no external modules needed
python3 - <<PYEOF 2>/dev/null
import os, re
status_yaml = "$status_yaml"
doc_basename = "$doc_basename"
try:
with open(status_yaml) as f:
content = f.read()
names = re.findall(r"""^\s*-\s+name:\s*["']?([^"'\n]+)["']?""", content, re.MULTILINE)
for name in names:
name = name.strip()
if doc_basename.startswith(name):
print(name)
break
except Exception:
pass
PYEOF
fi
}
WORKFLOW_NAME=$(find_workflow_name)
# Fallback: strip trailing date/project suffix (e.g., product-brief-myapp-2026 -> product-brief)
if [[ -z "$WORKFLOW_NAME" ]]; then
WORKFLOW_NAME=$(echo "$BASENAME" | sed 's/-[0-9]\{4\}[^-]*$//' | sed 's/-[a-zA-Z0-9]*$//')
fi
# Final fallback: original single-field cut
if [[ -z "$WORKFLOW_NAME" ]]; then
WORKFLOW_NAME=$(echo "$BASENAME" | cut -d'-' -f1)
fi
if [ -f "$STATUS_FILE" ]; then
echo ""
echo -e "${GREEN}Updating workflow status...${NC}"
TIMESTAMP=$(date -u +"%Y-%m-%dT%H:%M:%SZ")
# Update last_updated timestamp
if command -v yq &>/dev/null; then
yq eval ".last_updated = \"$TIMESTAMP\"" -i "$STATUS_FILE" 2>/dev/null || true
yq eval "(.workflow_status[] | select(.name == \"$WORKFLOW_NAME\") | .plannotator_review) = \"approved\"" \
-i "$STATUS_FILE" 2>/dev/null || true
yq eval "(.workflow_status[] | select(.name == \"$WORKFLOW_NAME\") | .reviewed_at) = \"$TIMESTAMP\"" \
-i "$STATUS_FILE" 2>/dev/null || true
else
echo -e "${YELLOW}Note: Install yq for automatic status update${NC}"
echo " brew install yq"
echo ""
echo " Manually update $STATUS_FILE:"
echo " plannotator_review: \"approved\""
echo " reviewed_at: \"$TIMESTAMP\""
fi
fi
echo ""
echo -e "${GREEN}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}"
echo -e "${GREEN}Phase gate review submitted.${NC}"
echo ""
echo "Next steps:"
echo " 1. Review and annotate in the plannotator UI"
echo " 2. Click Approve (saves to your enabled destination: Obsidian or Bear)"
echo " 3. Proceed to next BMAD phase"
echo ""
```
---
## Skill Companion Files
> Additional files collected from the skill directory layout.
### scripts/check-status.sh
```bash
#!/bin/bash
# BMAD Workflow Status Checker
# Reads and displays current workflow status from YAML file
set -e # Exit on error
# Color output
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
GRAY='\033[0;37m'
NC='\033[0m' # No Color
# Default paths
CONFIG_FILE="bmad/config.yaml"
STATUS_FILE="docs/bmm-workflow-status.yaml"
# Check if project is initialized
if [ ! -f "$CONFIG_FILE" ]; then
echo -e "${RED}Error: BMAD not initialized in this project${NC}"
echo -e "${YELLOW}Run /workflow-init to initialize BMAD${NC}"
exit 1
fi
# Read output folder from config if available
if command -v yq &> /dev/null; then
OUTPUT_FOLDER=$(yq eval '.output_folder' "$CONFIG_FILE" 2>/dev/null || echo "docs")
STATUS_FILE="${OUTPUT_FOLDER}/bmm-workflow-status.yaml"
elif grep -q "output_folder:" "$CONFIG_FILE"; then
OUTPUT_FOLDER=$(grep "output_folder:" "$CONFIG_FILE" | sed 's/.*: *"\?\([^"]*\)"\?/\1/' | tr -d '"')
STATUS_FILE="${OUTPUT_FOLDER}/bmm-workflow-status.yaml"
fi
# Check if status file exists
if [ ! -f "$STATUS_FILE" ]; then
echo -e "${RED}Error: Workflow status file not found: ${STATUS_FILE}${NC}"
echo -e "${YELLOW}Run /workflow-init to create status file${NC}"
exit 1
fi
# Parse config for project info
PROJECT_NAME="Unknown"
PROJECT_TYPE="Unknown"
PROJECT_LEVEL="Unknown"
if command -v yq &> /dev/null; then
# Use yq if available for proper YAML parsing
PROJECT_NAME=$(yq eval '.project_name' "$STATUS_FILE" 2>/dev/null || echo "Unknown")
PROJECT_TYPE=$(yq eval '.project_type' "$STATUS_FILE" 2>/dev/null || echo "Unknown")
PROJECT_LEVEL=$(yq eval '.project_level' "$STATUS_FILE" 2>/dev/null || echo "Unknown")
else
# Fallback to grep/sed
if grep -q "project_name:" "$STATUS_FILE"; then
PROJECT_NAME=$(grep "project_name:" "$STATUS_FILE" | head -1 | sed 's/.*: *"\?\([^"]*\)"\?/\1/' | tr -d '"')
fi
if grep -q "project_type:" "$STATUS_FILE"; then
PROJECT_TYPE=$(grep "project_type:" "$STATUS_FILE" | head -1 | sed 's/.*: *"\?\([^"]*\)"\?/\1/' | tr -d '"')
fi
if grep -q "project_level:" "$STATUS_FILE"; then
PROJECT_LEVEL=$(grep "project_level:" "$STATUS_FILE" | head -1 | sed 's/.*: *//;s/ *#.*//')
fi
fi
# Display header
echo ""
echo -e "${BLUE}╔════════════════════════════════════════════════╗${NC}"
echo -e "${BLUE}║ BMAD Workflow Status Report ║${NC}"
echo -e "${BLUE}╚════════════════════════════════════════════════╝${NC}"
echo ""
echo -e "${BLUE}Project:${NC} ${PROJECT_NAME}"
echo -e "${BLUE}Type:${NC} ${PROJECT_TYPE}"
echo -e "${BLUE}Level:${NC} ${PROJECT_LEVEL}"
echo ""
# Function to parse workflow status
parse_workflows() {
local current_phase=0
local phase_complete=true
local recommended_workflow=""
local phase_1_complete=true
local phase_2_complete=false
local phase_3_complete=false
local phase_4_started=false
# Headers
echo -e "${GREEN}Phase 1: Analysis${NC} (Optional)"
# Parse workflows using python3 to avoid nested while loop stdin consumption bug
while IFS='|' read -r name phase status command; do
# Print phase headers
if [ "$phase" != "$current_phase" ]; then
current_phase=$phase
echo ""
case $phase in
2)
echo -e "${GREEN}Phase 2: Planning${NC} (Required)"
;;
3)
echo -e "${GREEN}Phase 3: Solutioning${NC} (Conditional)"
;;
4)
echo -e "${GREEN}Phase 4: Implementation${NC} (Required)"
;;
esac
fi
# Determine status icon and color
if [[ $status == /* ]] || [[ $status == docs/* ]]; then
# Completed - has file path
echo -e " ${GREEN}✓${NC} ${name} ${GRAY}(${status})${NC}"
# Track phase completion
case $phase in
2) phase_2_complete=true ;;
3) phase_3_complete=true ;;
4) phase_4_started=true ;;
esac
elif [[ $status == "required" ]]; then
echo -e " ${YELLOW}⚠${NC} ${name} ${YELLOW}(required - NOT STARTED)${NC}"
if [ -z "$recommended_workflow" ]; then
recommended_workflow="$command"
fi
phase_complete=false
elif [[ $status == "recommended" ]]; then
echo -e " ${BLUE}→${NC} ${name} ${BLUE}(recommended)${NC}"
if [ -z "$recommended_workflow" ]; then
recommended_workflow="$command"
fi
elif [[ $status == "skipped" ]]; then
echo -e " ${GRAY}-${NC} ${name} ${GRAY}(skipped)${NC}"
else
echo -e " ${GRAY}-${NC} ${name} ${GRAY}(${status})${NC}"
fi
done < <(python3 -c "
import sys
with open(sys.argv[1]) as f:
content = f.read()
workflows = []
current = {}
in_workflows = False
for line in content.split('\n'):
stripped = line.strip()
if stripped == 'workflow_status:':
in_workflows = True
continue
if not in_workflows:
continue
if stripped.startswith('- name:'):
if current:
workflows.append(current)
current = {'name': stripped[7:].strip().strip('\"')}
elif current and stripped.startswith('phase:'):
current['phase'] = stripped[6:].strip().strip('\"')
elif current and stripped.startswith('status:'):
current['status'] = stripped[7:].strip().strip('\"')
elif current and stripped.startswith('command:'):
current['command'] = stripped[8:].strip().strip('\"')
elif current and stripped.startswith('description:'):
current['description'] = stripped[12:].strip().strip('\"')
if current:
workflows.append(current)
for wf in workflows:
name = wf.get('name', '')
phase = wf.get('phase', '')
status = wf.get('status', '')
command = wf.get('command', '')
print(f'{name}|{phase}|{status}|{command}')
" "$STATUS_FILE" 2>/dev/null)
# Recommendations
echo ""
echo -e "${BLUE}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}"
if [ -n "$recommended_workflow" ]; then
echo ""
echo -e "${YELLOW}Recommended next step:${NC}"
echo -e " Run ${GREEN}${recommended_workflow}${NC} to continue"
else
echo ""
echo -e "${GREEN}All required workflows complete!${NC}"
if [ "$phase_4_started" = true ]; then
echo -e "Continue with ${GREEN}/dev-story${NC} to implement stories"
else
echo -e "Start implementation with ${GREEN}/sprint-planning${NC}"
fi
fi
echo ""
}
# Parse and display workflows
parse_workflows
# Display legend
echo -e "${GRAY}Legend:${NC}"
echo -e " ${GREEN}✓${NC} Completed ${YELLOW}⚠${NC} Required ${BLUE}→${NC} Recommended ${GRAY}-${NC} Optional"
echo ""
```
### scripts/init-project.sh
```bash
#!/bin/bash
# BMAD Project Initialization Script
# Creates BMAD directory structure and configuration files
set -e # Exit on error
# Color output
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
NC='\033[0m' # No Color
# Default values
PROJECT_NAME=""
PROJECT_TYPE=""
PROJECT_LEVEL=""
OUTPUT_FOLDER="docs"
SKILL_PATH="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
# Parse command line arguments
while [[ $# -gt 0 ]]; do
case $1 in
--name)
PROJECT_NAME="$2"
shift 2
;;
--type)
PROJECT_TYPE="$2"
shift 2
;;
--level)
PROJECT_LEVEL="$2"
shift 2
;;
--output)
OUTPUT_FOLDER="$2"
shift 2
;;
-h|--help)
echo "Usage: $0 --name <project-name> --type <project-type> --level <0-4> [--output <folder>]"
echo ""
echo "Options:"
echo " --name Project name (required)"
echo " --type Project type: web-app, mobile-app, api, game, library, other (required)"
echo " --level Project level: 0-4 (required)"
echo " --output Output folder for documents (default: docs)"
echo " -h, --help Show this help message"
echo ""
echo "Example:"
echo " $0 --name MyApp --type web-app --level 2"
exit 0
;;
*)
echo -e "${RED}Error: Unknown option $1${NC}"
exit 1
;;
esac
done
# Interactive mode if parameters not provided
if [ -z "$PROJECT_NAME" ]; then
echo -e "${BLUE}Enter project name:${NC}"
read -r PROJECT_NAME
fi
if [ -z "$PROJECT_TYPE" ]; then
echo -e "${BLUE}Enter project type (web-app, mobile-app, api, game, library, other):${NC}"
read -r PROJECT_TYPE
fi
if [ -z "$PROJECT_LEVEL" ]; then
echo -e "${BLUE}Enter project level (0-4):${NC}"
echo " 0 - Single atomic change (1 story)"
echo " 1 - Small feature (1-10 stories)"
echo " 2 - Medium feature set (5-15 stories)"
echo " 3 - Complex integration (12-40 stories)"
echo " 4 - Enterprise expansion (40+ stories)"
read -r PROJECT_LEVEL
fi
# Validate inputs
if [ -z "$PROJECT_NAME" ] || [ -z "$PROJECT_TYPE" ] || [ -z "$PROJECT_LEVEL" ]; then
echo -e "${RED}Error: Project name, type, and level are required${NC}"
exit 1
fi
# Validate project level
if ! [[ "$PROJECT_LEVEL" =~ ^[0-4]$ ]]; then
echo -e "${RED}Error: Project level must be 0-4${NC}"
exit 1
fi
# Validate project type
valid_types=("web-app" "mobile-app" "api" "game" "library" "other")
if [[ ! " ${valid_types[@]} " =~ " ${PROJECT_TYPE} " ]]; then
echo -e "${YELLOW}Warning: Unknown project type '${PROJECT_TYPE}'. Valid types: ${valid_types[*]}${NC}"
echo -e "${YELLOW}Continuing anyway...${NC}"
fi
echo -e "${GREEN}Initializing BMAD for project: ${PROJECT_NAME}${NC}"
echo ""
# Create directory structure
echo -e "${BLUE}Creating directory structure...${NC}"
mkdir -p bmad/agent-overrides
mkdir -p "${OUTPUT_FOLDER}/stories"
mkdir -p .claude/commands/bmad
echo -e "${GREEN}✓ Directories created${NC}"
# Determine conditional workflow statuses based on project level
if [ "$PROJECT_LEVEL" -ge 2 ]; then
PRD_STATUS="required"
else
if [ "$PROJECT_LEVEL" -eq 1 ]; then
PRD_STATUS="recommended"
else
PRD_STATUS="optional"
fi
fi
if [ "$PROJECT_LEVEL" -le 1 ]; then
TECH_SPEC_STATUS="required"
else
TECH_SPEC_STATUS="optional"
fi
if [ "$PROJECT_LEVEL" -ge 2 ]; then
ARCHITECTURE_STATUS="required"
else
ARCHITECTURE_STATUS="optional"
fi
# Generate timestamp
TIMESTAMP=$(date -u +"%Y-%m-%dT%H:%M:%SZ")
# Create project config from template
echo -e "${BLUE}Creating project configuration...${NC}"
CONFIG_TEMPLATE="${SKILL_PATH}/templates/config.template.yaml"
CONFIG_OUTPUT="bmad/config.yaml"
if [ -f "$CONFIG_TEMPLATE" ]; then
# Use template if available
sed -e "s/{{PROJECT_NAME}}/${PROJECT_NAME}/g" \
-e "s/{{PROJECT_TYPE}}/${PROJECT_TYPE}/g" \
-e "s/{{PROJECT_LEVEL}}/${PROJECT_LEVEL}/g" \
-e "s/{{TIMESTAMP}}/${TIMESTAMP}/g" \
"$CONFIG_TEMPLATE" > "$CONFIG_OUTPUT"
else
# Fallback: create minimal config
cat > "$CONFIG_OUTPUT" <<EOF
# BMAD Method v6 - Project Configuration
# Generated: ${TIMESTAMP}
bmad_version: "6.0.0"
project_name: "${PROJECT_NAME}"
project_type: "${PROJECT_TYPE}"
project_level: ${PROJECT_LEVEL}
output_folder: "${OUTPUT_FOLDER}"
stories_folder: "${OUTPUT_FOLDER}/stories"
communication_language: "English"
document_output_language: "English"
EOF
fi
echo -e "${GREEN}✓ Created: ${CONFIG_OUTPUT}${NC}"
# Create workflow status from template
echo -e "${BLUE}Creating workflow status file...${NC}"
STATUS_TEMPLATE="${SKILL_PATH}/templates/workflow-status.template.yaml"
STATUS_OUTPUT="${OUTPUT_FOLDER}/bmm-workflow-status.yaml"
if [ -f "$STATUS_TEMPLATE" ]; then
# Use template if available
sed -e "s/{{PROJECT_NAME}}/${PROJECT_NAME}/g" \
-e "s/{{PROJECT_TYPE}}/${PROJECT_TYPE}/g" \
-e "s/{{PROJECT_LEVEL}}/${PROJECT_LEVEL}/g" \
-e "s/{{TIMESTAMP}}/${TIMESTAMP}/g" \
-e "s/{{PRD_STATUS}}/${PRD_STATUS}/g" \
-e "s/{{TECH_SPEC_STATUS}}/${TECH_SPEC_STATUS}/g" \
-e "s/{{ARCHITECTURE_STATUS}}/${ARCHITECTURE_STATUS}/g" \
"$STATUS_TEMPLATE" > "$STATUS_OUTPUT"
else
# Fallback: create minimal status file
cat > "$STATUS_OUTPUT" <<EOF
# BMAD Method Workflow Status
# Generated: ${TIMESTAMP}
project_name: "${PROJECT_NAME}"
project_type: "${PROJECT_TYPE}"
project_level: ${PROJECT_LEVEL}
last_updated: "${TIMESTAMP}"
workflow_status:
- name: prd
phase: 2
status: "${PRD_STATUS}"
description: "Product Requirements Document"
- name: tech-spec
phase: 2
status: "${TECH_SPEC_STATUS}"
description: "Technical Specification"
- name: architecture
phase: 3
status: "${ARCHITECTURE_STATUS}"
description: "System architecture design"
- name: sprint-planning
phase: 4
status: "required"
description: "Sprint planning and story creation"
EOF
fi
echo -e "${GREEN}✓ Created: ${STATUS_OUTPUT}${NC}"
# Summary
echo ""
echo -e "${GREEN}╔════════════════════════════════════════════════╗${NC}"
echo -e "${GREEN}║ BMAD Method Initialized Successfully! ║${NC}"
echo -e "${GREEN}╔════════════════════════════════════════════════╗${NC}"
echo ""
echo -e "${BLUE}Project:${NC} ${PROJECT_NAME}"
echo -e "${BLUE}Type:${NC} ${PROJECT_TYPE}"
echo -e "${BLUE}Level:${NC} ${PROJECT_LEVEL}"
echo ""
echo -e "${BLUE}Configuration:${NC} ${CONFIG_OUTPUT}"
echo -e "${BLUE}Status tracking:${NC} ${STATUS_OUTPUT}"
echo ""
# Recommend next step based on project level
echo -e "${YELLOW}Recommended next step:${NC}"
if [ "$PROJECT_LEVEL" -ge 2 ]; then
echo -e " Start with ${GREEN}/product-brief${NC} to define your product vision"
echo -e " Then create ${GREEN}/prd${NC} for detailed requirements"
else
if [ "$PROJECT_LEVEL" -eq 1 ]; then
echo -e " Start with ${GREEN}/product-brief${NC} (recommended) or ${GREEN}/tech-spec${NC}"
else
echo -e " Start with ${GREEN}/tech-spec${NC} to define your implementation"
fi
fi
echo ""
echo -e "${BLUE}Check status anytime with:${NC} /workflow-status"
echo ""
```
### scripts/install.sh
```bash
#!/bin/bash
# BMAD Orchestrator — One-Command Setup
# Installs plannotator CLI and configures BMAD + plannotator integration.
#
# Usage:
# bash scripts/install.sh # Interactive setup
# bash scripts/install.sh --skip-plannotator # BMAD only (no plannotator)
# bash scripts/install.sh --init-project # Also initialize BMAD in current project
# bash scripts/install.sh --dry-run # Preview what would happen
set -e
# ── Colors ────────────────────────────────────────────────────────────────────
BLUE='\033[0;34m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
RED='\033[0;31m'
GRAY='\033[0;37m'
BOLD='\033[1m'
NC='\033[0m'
# ── Flags ─────────────────────────────────────────────────────────────────────
SKIP_PLANNOTATOR=false
INIT_PROJECT=false
DRY_RUN=false
for arg in "$@"; do
case $arg in
--skip-plannotator) SKIP_PLANNOTATOR=true ;;
--init-project) INIT_PROJECT=true ;;
--dry-run) DRY_RUN=true ;;
-h|--help)
echo "Usage: bash scripts/install.sh [options]"
echo ""
echo "Options:"
echo " --skip-plannotator Set up BMAD only, skip plannotator install"
echo " --init-project Also initialize BMAD in the current project"
echo " --dry-run Preview steps without making changes"
echo " -h, --help Show this help"
exit 0
;;
esac
done
# ── Header ────────────────────────────────────────────────────────────────────
echo ""
echo -e "${BLUE}${BOLD}╔══════════════════════════════════════════════════╗${NC}"
echo -e "${BLUE}${BOLD}║ BMAD Orchestrator — Setup ║${NC}"
echo -e "${BLUE}${BOLD}║ BMAD Method v6 + plannotator integration ║${NC}"
echo -e "${BLUE}${BOLD}╚══════════════════════════════════════════════════╝${NC}"
echo ""
if [ "$DRY_RUN" = true ]; then
echo -e "${YELLOW}[DRY RUN] No changes will be made.${NC}"
echo ""
fi
# ── Step 1: Check plannotator ─────────────────────────────────────────────────
echo -e "${BOLD}Step 1: plannotator CLI${NC}"
echo ""
if [ "$SKIP_PLANNOTATOR" = true ]; then
echo -e " ${GRAY}Skipping plannotator (--skip-plannotator)${NC}"
PLANNOTATOR_OK=false
elif command -v plannotator &>/dev/null; then
PLANNOTATOR_VERSION=$(plannotator --version 2>/dev/null || echo "installed")
echo -e " ${GREEN}✓ plannotator already installed${NC} (${PLANNOTATOR_VERSION})"
PLANNOTATOR_OK=true
else
echo -e " ${YELLOW}plannotator not found. Installing...${NC}"
echo ""
if [ "$DRY_RUN" = true ]; then
echo -e " ${GRAY}[DRY RUN] Would run: curl -sSfL https://plannotator.ai/install.sh | sh${NC}"
PLANNOTATOR_OK=false
else
# Install plannotator
if curl -sSfL https://plannotator.ai/install.sh | sh; then
echo ""
echo -e " ${GREEN}✓ plannotator installed${NC}"
PLANNOTATOR_OK=true
# Reload PATH so plannotator is found immediately
export PATH="$HOME/.local/bin:$HOME/bin:$PATH"
else
echo ""
echo -e " ${RED}✗ plannotator install failed.${NC}"
echo -e " ${GRAY} Manual install: https://plannotator.ai${NC}"
PLANNOTATOR_OK=false
fi
fi
fi
echo ""
# ── Resolve skill directory (used in Steps 2 and 3) ──────────────────────────
SKILL_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
# ── Step 2: Set up Claude Code hook ──────────────────────────────────────────
echo -e "${BOLD}Step 2: plannotator Hook (Claude Code)${NC}"
echo ""
HOOK_SCRIPT="${SKILL_DIR}/../plannotator/scripts/setup-hook.sh"
if [ "$PLANNOTATOR_OK" = false ]; then
echo -e " ${GRAY}Skipping hook setup (plannotator not installed)${NC}"
elif [ ! -f "$HOOK_SCRIPT" ]; then
echo -e " ${YELLOW}plannotator skill not found at expected path.${NC}"
echo -e " ${GRAY} Install plannotator skill first:${NC}"
echo -e " ${GRAY} npx skills add https://github.com/akillness/oh-my-skills --skill plannotator${NC}"
echo ""
echo -e " ${GRAY} Then run hook setup manually:${NC}"
echo -e " ${GRAY} bash .agent-skills/plannotator/scripts/setup-hook.sh${NC}"
else
if [ "$DRY_RUN" = true ]; then
echo -e " ${GRAY}[DRY RUN] Would run: bash $HOOK_SCRIPT${NC}"
else
echo -e " ${BLUE}Configuring Claude Code ExitPlanMode hook...${NC}"
bash "$HOOK_SCRIPT" && echo -e " ${GREEN}✓ Hook configured${NC}" || \
echo -e " ${YELLOW}⚠ Hook setup skipped (may already be configured)${NC}"
fi
fi
echo ""
# ── Step 3: Verify BMAD scripts are executable ────────────────────────────────
echo -e "${BOLD}Step 3: BMAD Scripts${NC}"
echo ""
SCRIPTS=(
"scripts/install.sh"
"scripts/init-project.sh"
"scripts/check-status.sh"
"scripts/phase-gate-review.sh"
"scripts/validate-config.sh"
)
for script in "${SCRIPTS[@]}"; do
SCRIPT_PATH="${SKILL_DIR}/${script}"
if [ -f "$SCRIPT_PATH" ]; then
if [ "$DRY_RUN" = false ]; then
chmod +x "$SCRIPT_PATH"
fi
echo -e " ${GREEN}✓${NC} ${script}"
else
echo -e " ${GRAY}-${NC} ${script} ${GRAY}(not found)${NC}"
fi
done
echo ""
# ── Step 4: Optional project initialization ───────────────────────────────────
if [ "$INIT_PROJECT" = true ]; then
echo -e "${BOLD}Step 4: Initialize BMAD in Current Project${NC}"
echo ""
INIT_SCRIPT="${SKILL_DIR}/scripts/init-project.sh"
if [ -f "$INIT_SCRIPT" ]; then
if [ "$DRY_RUN" = true ]; then
echo -e " ${GRAY}[DRY RUN] Would run: bash $INIT_SCRIPT${NC}"
else
bash "$INIT_SCRIPT"
fi
else
echo -e " ${RED}✗ init-project.sh not found${NC}"
fi
echo ""
fi
# ── Summary ───────────────────────────────────────────────────────────────────
echo -e "${GREEN}${BOLD}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}"
echo -e "${GREEN}${BOLD} Setup complete!${NC}"
echo ""
echo -e "${BOLD}What's configured:${NC}"
if [ "$PLANNOTATOR_OK" = true ]; then
echo -e " ${GREEN}✓${NC} plannotator CLI — visual plan review"
echo -e " ${GREEN}✓${NC} Claude Code hook — auto-review on ExitPlanMode"
fi
echo -e " ${GREEN}✓${NC} BMAD scripts — workflow orchestration"
echo ""
echo -e "${BOLD}Next steps:${NC}"
echo ""
if [ "$INIT_PROJECT" = false ]; then
echo -e " ${BLUE}1. Initialize BMAD in your project:${NC}"
echo -e " ${YELLOW}/workflow-init${NC} ← run this in your AI session"
echo ""
fi
echo -e " ${BLUE}$([ "$INIT_PROJECT" = true ] && echo 1 || echo 2). Start your first phase:${NC}"
echo -e " ${YELLOW}/workflow-status${NC} ← see what's recommended next"
echo ""
echo -e " ${BLUE}$([ "$INIT_PROJECT" = true ] && echo 2 || echo 3). Review each phase document before advancing:${NC}"
echo -e " ${GRAY}bash scripts/phase-gate-review.sh docs/prd-*.md${NC}"
echo ""
if [ "$PLANNOTATOR_OK" = true ]; then
echo -e " ${BLUE}$([ "$INIT_PROJECT" = true ] && echo 3 || echo 4). Restart Claude Code${NC} so the hook takes effect."
echo ""
fi
echo -e "${GRAY}Full guide: cat .agent-skills/bmad-orchestrator/SETUP.md${NC}"
echo ""
```
### scripts/validate-config.sh
```bash
#!/bin/bash
# BMAD Configuration Validator
# Validates YAML configuration files for syntax and required fields
set -e # Exit on error
# Color output
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
NC='\033[0m' # No Color
# Default file to validate
CONFIG_FILE="${1:-bmad/config.yaml}"
# Check if file exists
if [ ! -f "$CONFIG_FILE" ]; then
echo -e "${RED}Error: File not found: ${CONFIG_FILE}${NC}"
exit 1
fi
echo -e "${BLUE}Validating YAML configuration: ${CONFIG_FILE}${NC}"
echo ""
# Track validation status
ERRORS=0
WARNINGS=0
# Function to report error
error() {
echo -e "${RED}✗ ERROR:${NC} $1"
((ERRORS++))
}
# Function to report warning
warning() {
echo -e "${YELLOW}⚠ WARNING:${NC} $1"
((WARNINGS++))
}
# Function to report success
success() {
echo -e "${GREEN}✓${NC} $1"
}
# Check if yq is available for proper YAML parsing
HAS_YQ=false
if command -v yq &> /dev/null; then
HAS_YQ=true
echo -e "${GREEN}✓ yq found - using proper YAML parser${NC}"
else
echo -e "${YELLOW}⚠ yq not found - using basic validation${NC}"
echo -e "${GRAY} Install yq for better validation: https://github.com/mikefarah/yq${NC}"
fi
echo ""
# Test 1: YAML Syntax
echo -e "${BLUE}Test 1: YAML Syntax${NC}"
if [ "$HAS_YQ" = true ]; then
if yq eval '.' "$CONFIG_FILE" > /dev/null 2>&1; then
success "Valid YAML syntax"
else
error "Invalid YAML syntax"
yq eval '.' "$CONFIG_FILE" 2>&1 | head -5
fi
else
# Basic syntax check
if grep -q "^[^#]" "$CONFIG_FILE"; then
success "File contains content"
else
error "File appears empty or only contains comments"
fi
fi
echo ""
# Determine config type
CONFIG_TYPE="unknown"
if grep -q "project_name:" "$CONFIG_FILE"; then
CONFIG_TYPE="project"
elif grep -q "user_name:" "$CONFIG_FILE"; then
CONFIG_TYPE="global"
fi
echo -e "${BLUE}Configuration type: ${CONFIG_TYPE}${NC}"
echo ""
# Test 2: Required Fields (Project Config)
if [ "$CONFIG_TYPE" = "project" ]; then
echo -e "${BLUE}Test 2: Required Fields (Project Config)${NC}"
# Check project_name
if grep -q "^project_name:" "$CONFIG_FILE"; then
PROJECT_NAME=$(grep "^project_name:" "$CONFIG_FILE" | sed 's/.*: *"\?\([^"]*\)"\?/\1/' | tr -d '"')
if [ -n "$PROJECT_NAME" ]; then
success "project_name: ${PROJECT_NAME}"
else
error "project_name is empty"
fi
else
error "Missing required field: project_name"
fi
# Check project_type
if grep -q "^project_type:" "$CONFIG_FILE"; then
PROJECT_TYPE=$(grep "^project_type:" "$CONFIG_FILE" | sed 's/.*: *"\?\([^"]*\)"\?/\1/' | tr -d '"')
if [ -n "$PROJECT_TYPE" ]; then
success "project_type: ${PROJECT_TYPE}"
# Validate project type
valid_types=("web-app" "mobile-app" "api" "game" "library" "other")
if [[ ! " ${valid_types[@]} " =~ " ${PROJECT_TYPE} " ]]; then
warning "Unknown project_type '${PROJECT_TYPE}'. Valid: ${valid_types[*]}"
fi
else
error "project_type is empty"
fi
else
error "Missing required field: project_type"
fi
# Check project_level
if grep -q "^project_level:" "$CONFIG_FILE"; then
PROJECT_LEVEL=$(grep "^project_level:" "$CONFIG_FILE" | sed 's/.*: *//;s/ *#.*//')
if [ -n "$PROJECT_LEVEL" ]; then
success "project_level: ${PROJECT_LEVEL}"
# Validate level is 0-4
if ! [[ "$PROJECT_LEVEL" =~ ^[0-4]$ ]]; then
error "project_level must be 0-4, got: ${PROJECT_LEVEL}"
fi
else
error "project_level is empty"
fi
else
error "Missing required field: project_level"
fi
echo ""
fi
# Test 3: Optional but Recommended Fields
echo -e "${BLUE}Test 3: Optional Fields${NC}"
# Check output_folder
if grep -q "^output_folder:" "$CONFIG_FILE"; then
OUTPUT_FOLDER=$(grep "^output_folder:" "$CONFIG_FILE" | sed 's/.*: *"\?\([^"]*\)"\?/\1/' | tr -d '"')
success "output_folder: ${OUTPUT_FOLDER}"
else
warning "output_folder not specified (will default to 'docs')"
fi
# Check communication_language
if grep -q "^communication_language:" "$CONFIG_FILE"; then
COMM_LANG=$(grep "^communication_language:" "$CONFIG_FILE" | sed 's/.*: *"\?\([^"]*\)"\?/\1/' | tr -d '"')
success "communication_language: ${COMM_LANG}"
else
warning "communication_language not specified (will default to 'English')"
fi
echo ""
# Test 4: BMAD Version
echo -e "${BLUE}Test 4: Version Check${NC}"
if grep -q "^bmad_version:" "$CONFIG_FILE" || grep -q "^version:" "$CONFIG_FILE"; then
VERSION=$(grep -E "^(bmad_version|version):" "$CONFIG_FILE" | head -1 | sed 's/.*: *"\?\([^"]*\)"\?/\1/' | tr -d '"')
success "BMAD version: ${VERSION}"
# Check if version is current
if [[ "$VERSION" == "6.0.0" ]]; then
success "Running latest BMAD version"
else
warning "BMAD version ${VERSION} detected. Current version is 6.0.0"
fi
else
warning "No version specified"
fi
echo ""
# Test 5: File Permissions
echo -e "${BLUE}Test 5: File Permissions${NC}"
if [ -r "$CONFIG_FILE" ]; then
success "File is readable"
else
error "File is not readable"
fi
if [ -w "$CONFIG_FILE" ]; then
success "File is writable"
else
warning "File is not writable (updates may fail)"
fi
echo ""
# Test 6: Referenced Folders (if project config)
if [ "$CONFIG_TYPE" = "project" ]; then
echo -e "${BLUE}Test 6: Referenced Folders${NC}"
# Check if output folder exists
if [ -n "$OUTPUT_FOLDER" ]; then
if [ -d "$OUTPUT_FOLDER" ]; then
success "Output folder exists: ${OUTPUT_FOLDER}"
else
warning "Output folder does not exist: ${OUTPUT_FOLDER}"
echo -e " ${GRAY}Run /workflow-init to create it${NC}"
fi
fi
# Check if bmad folder exists
if [ -d "bmad" ]; then
success "BMAD config folder exists: bmad/"
else
warning "BMAD config folder does not exist: bmad/"
fi
# Check for workflow status file
STATUS_FILE="${OUTPUT_FOLDER:-docs}/bmm-workflow-status.yaml"
if [ -f "$STATUS_FILE" ]; then
success "Workflow status file exists: ${STATUS_FILE}"
else
warning "Workflow status file not found: ${STATUS_FILE}"
echo -e " ${GRAY}Run /workflow-init to create it${NC}"
fi
echo ""
fi
# Summary
echo -e "${BLUE}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}"
echo ""
if [ $ERRORS -eq 0 ] && [ $WARNINGS -eq 0 ]; then
echo -e "${GREEN}✓ Validation passed with no errors or warnings!${NC}"
exit 0
elif [ $ERRORS -eq 0 ]; then
echo -e "${YELLOW}⚠ Validation passed with ${WARNINGS} warning(s)${NC}"
echo -e "${GRAY} Configuration is valid but has recommendations${NC}"
exit 0
else
echo -e "${RED}✗ Validation failed with ${ERRORS} error(s) and ${WARNINGS} warning(s)${NC}"
echo -e "${GRAY} Please fix errors before proceeding${NC}"
exit 1
fi
```