moflo 4.6.5 → 4.6.6

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.
@@ -42,7 +42,7 @@ function loadStatusLineConfig() {
42
42
  show_adrs: true,
43
43
  show_agentdb: true,
44
44
  show_tests: true,
45
- mode: 'single-line',
45
+ mode: 'compact',
46
46
  };
47
47
 
48
48
  // Try moflo.yaml
@@ -159,38 +159,26 @@ function getGitInfo() {
159
159
  staged: 0, ahead: 0, behind: 0,
160
160
  };
161
161
 
162
- // Single shell: get user.name, branch, porcelain status, and upstream diff
163
- const script = [
164
- 'git config user.name 2>/dev/null || echo user',
165
- 'echo "---SEP---"',
166
- 'git branch --show-current 2>/dev/null',
167
- 'echo "---SEP---"',
168
- 'git status --porcelain 2>/dev/null',
169
- 'echo "---SEP---"',
170
- 'git rev-list --left-right --count HEAD...@{upstream} 2>/dev/null || echo "0 0"',
171
- ].join('; ');
172
-
173
- const raw = safeExec(`sh -c '${script}'`, 3000);
174
- if (!raw) return result;
175
-
176
- const parts = raw.split('---SEP---').map(s => s.trim());
177
- if (parts.length >= 4) {
178
- result.name = parts[0] || 'user';
179
- result.gitBranch = parts[1] || '';
180
-
181
- // Parse porcelain status
182
- if (parts[2]) {
183
- for (const line of parts[2].split('\n')) {
184
- if (!line || line.length < 2) continue;
185
- const x = line[0], y = line[1];
186
- if (x === '?' && y === '?') { result.untracked++; continue; }
187
- if (x !== ' ' && x !== '?') result.staged++;
188
- if (y !== ' ' && y !== '?') result.modified++;
189
- }
162
+ // Individual git calls (cross-platform sh -c fails on Windows)
163
+ result.name = safeExec('git config user.name', 2000) || 'user';
164
+ result.gitBranch = safeExec('git branch --show-current', 2000) || '';
165
+
166
+ // Parse porcelain status
167
+ const statusRaw = safeExec('git status --porcelain', 2000);
168
+ if (statusRaw) {
169
+ for (const line of statusRaw.split('\n')) {
170
+ if (!line || line.length < 2) continue;
171
+ const x = line[0], y = line[1];
172
+ if (x === '?' && y === '?') { result.untracked++; continue; }
173
+ if (x !== ' ' && x !== '?') result.staged++;
174
+ if (y !== ' ' && y !== '?') result.modified++;
190
175
  }
176
+ }
177
+
178
+ {
191
179
 
192
180
  // Parse ahead/behind
193
- const ab = (parts[3] || '0 0').split(/\s+/);
181
+ const ab = (safeExec('git rev-list --left-right --count HEAD...@{upstream}', 2000) || '0 0').split(/\s+/);
194
182
  result.ahead = parseInt(ab[0]) || 0;
195
183
  result.behind = parseInt(ab[1]) || 0;
196
184
  }
@@ -669,26 +657,16 @@ function generateStatusline() {
669
657
  }
670
658
 
671
659
  // Multi-line dashboard (for --dashboard flag)
660
+ // Respects show_* toggles from moflo.yaml status_line config
672
661
  function generateDashboard() {
673
662
  const git = getGitInfo();
674
- const modelName = getModelName();
675
- const progress = getV3Progress();
676
- const security = getSecurityStatus();
677
- const swarm = getSwarmStatus();
678
- const system = getSystemMetrics();
679
- const adrs = getADRStatus();
680
- const hooks = getHooksStatus();
681
- const agentdb = getAgentDBStats();
682
- const tests = getTestStats();
683
663
  const session = getSessionStats();
684
- const integration = getIntegrationStatus();
685
664
  const lines = [];
686
665
 
687
- // Header
666
+ // Header: branding + git
688
667
  let header = `${c.bold}${c.brightPurple}\u258A ${SL_CONFIG.branding}${c.reset}`;
689
- header += `${swarm.coordinationActive ? c.brightCyan : c.dim}\u25CF ${c.brightCyan}${git.name}${c.reset}`;
690
- if (git.gitBranch) {
691
- header += ` ${c.dim}\u2502${c.reset} ${c.brightBlue}\u23C7 ${git.gitBranch}${c.reset}`;
668
+ if (SL_CONFIG.show_git && git.gitBranch) {
669
+ header += ` ${c.brightBlue}\u23C7 ${git.gitBranch}${c.reset}`;
692
670
  const changes = git.modified + git.staged + git.untracked;
693
671
  if (changes > 0) {
694
672
  let ind = '';
@@ -700,82 +678,111 @@ function generateDashboard() {
700
678
  if (git.ahead > 0) header += ` ${c.brightGreen}\u2191${git.ahead}${c.reset}`;
701
679
  if (git.behind > 0) header += ` ${c.brightRed}\u2193${git.behind}${c.reset}`;
702
680
  }
703
- header += ` ${c.dim}\u2502${c.reset} ${c.purple}${modelName}${c.reset}`;
704
- if (session.duration) header += ` ${c.dim}\u2502${c.reset} ${c.cyan}\u23F1 ${session.duration}${c.reset}`;
681
+ if (SL_CONFIG.show_session && session.duration) {
682
+ header += ` ${c.dim}\u2502${c.reset} ${c.cyan}\u23F1 ${session.duration}${c.reset}`;
683
+ }
705
684
  lines.push(header);
706
685
 
707
686
  // Separator
708
- lines.push(`${c.dim}\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500${c.reset}`);
709
-
710
- // Line 1: DDD Domains + perf
711
- const domainsColor = progress.domainsCompleted >= 3 ? c.brightGreen : progress.domainsCompleted > 0 ? c.yellow : c.red;
712
- let perfIndicator;
713
- if (agentdb.hasHnsw && agentdb.vectorCount > 0) {
714
- const speedup = agentdb.vectorCount > 10000 ? '12500x' : agentdb.vectorCount > 1000 ? '150x' : '10x';
715
- perfIndicator = `${c.brightGreen}\u26A1 HNSW ${speedup}${c.reset}`;
716
- } else if (progress.patternsLearned > 0) {
717
- const pk = progress.patternsLearned >= 1000 ? `${(progress.patternsLearned / 1000).toFixed(1)}k` : String(progress.patternsLearned);
718
- perfIndicator = `${c.brightYellow}\uD83D\uDCDA ${pk} patterns${c.reset}`;
719
- } else {
720
- perfIndicator = `${c.dim}\u26A1 target: 150x-12500x${c.reset}`;
721
- }
722
- lines.push(
723
- `${c.brightCyan}\uD83C\uDFD7\uFE0F DDD Domains${c.reset} ${progressBar(progress.domainsCompleted, progress.totalDomains)} ` +
724
- `${domainsColor}${progress.domainsCompleted}${c.reset}/${c.brightWhite}${progress.totalDomains}${c.reset} ${perfIndicator}`
725
- );
726
-
727
- // Line 2: Swarm + Hooks + CVE + Memory + Intelligence
728
- const swarmInd = swarm.coordinationActive ? `${c.brightGreen}\u25C9${c.reset}` : `${c.dim}\u25CB${c.reset}`;
729
- const agentsColor = swarm.activeAgents > 0 ? c.brightGreen : c.red;
730
- const secIcon = security.status === 'CLEAN' ? '\uD83D\uDFE2' : security.status === 'IN_PROGRESS' ? '\uD83D\uDFE1' : '\uD83D\uDD34';
731
- const secColor = security.status === 'CLEAN' ? c.brightGreen : security.status === 'IN_PROGRESS' ? c.brightYellow : c.brightRed;
732
- const hooksColor = hooks.enabled > 0 ? c.brightGreen : c.dim;
733
- const intellColor = system.intelligencePct >= 80 ? c.brightGreen : system.intelligencePct >= 40 ? c.brightYellow : c.dim;
734
-
735
- lines.push(
736
- `${c.brightYellow}\uD83E\uDD16 Swarm${c.reset} ${swarmInd} [${agentsColor}${String(swarm.activeAgents).padStart(2)}${c.reset}/${c.brightWhite}${swarm.maxAgents}${c.reset}] ` +
737
- `${c.brightPurple}\uD83D\uDC65 ${system.subAgents}${c.reset} ` +
738
- `${c.brightBlue}\uD83E\uDE9D ${hooksColor}${hooks.enabled}${c.reset}/${c.brightWhite}${hooks.total}${c.reset} ` +
739
- `${secIcon} ${secColor}CVE ${security.cvesFixed}${c.reset}/${c.brightWhite}${security.totalCves}${c.reset} ` +
740
- `${c.brightCyan}\uD83D\uDCBE ${system.memoryMB}MB${c.reset} ` +
741
- `${intellColor}\uD83E\uDDE0 ${String(system.intelligencePct).padStart(3)}%${c.reset}`
742
- );
743
-
744
- // Line 3: Architecture
745
- const dddColor = progress.dddProgress >= 50 ? c.brightGreen : progress.dddProgress > 0 ? c.yellow : c.red;
746
- const adrColor = adrs.count > 0 ? (adrs.implemented === adrs.count ? c.brightGreen : c.yellow) : c.dim;
747
- const adrDisplay = adrs.compliance > 0 ? `${adrColor}\u25CF${adrs.compliance}%${c.reset}` : `${adrColor}\u25CF${adrs.implemented}/${adrs.count}${c.reset}`;
748
-
749
- lines.push(
750
- `${c.brightPurple}\uD83D\uDD27 Architecture${c.reset} ` +
751
- `${c.cyan}ADRs${c.reset} ${adrDisplay} ${c.dim}\u2502${c.reset} ` +
752
- `${c.cyan}DDD${c.reset} ${dddColor}\u25CF${String(progress.dddProgress).padStart(3)}%${c.reset} ${c.dim}\u2502${c.reset} ` +
753
- `${c.cyan}Security${c.reset} ${secColor}\u25CF${security.status}${c.reset}`
754
- );
755
-
756
- // Line 4: AgentDB, Tests, Integration
757
- const hnswInd = agentdb.hasHnsw ? `${c.brightGreen}\u26A1${c.reset}` : '';
758
- const sizeDisp = agentdb.dbSizeKB >= 1024 ? `${(agentdb.dbSizeKB / 1024).toFixed(1)}MB` : `${agentdb.dbSizeKB}KB`;
759
- const vectorColor = agentdb.vectorCount > 0 ? c.brightGreen : c.dim;
760
- const testColor = tests.testFiles > 0 ? c.brightGreen : c.dim;
761
-
762
- let integStr = '';
763
- if (integration.mcpServers.total > 0) {
764
- const mcpCol = integration.mcpServers.enabled === integration.mcpServers.total ? c.brightGreen :
765
- integration.mcpServers.enabled > 0 ? c.brightYellow : c.red;
766
- integStr += `${c.cyan}MCP${c.reset} ${mcpCol}\u25CF${integration.mcpServers.enabled}/${integration.mcpServers.total}${c.reset}`;
767
- }
768
- if (integration.hasDatabase) integStr += (integStr ? ' ' : '') + `${c.brightGreen}\u25C6${c.reset}DB`;
769
- if (integration.hasApi) integStr += (integStr ? ' ' : '') + `${c.brightGreen}\u25C6${c.reset}API`;
770
- if (!integStr) integStr = `${c.dim}\u25CF none${c.reset}`;
771
-
772
- lines.push(
773
- `${c.brightCyan}\uD83D\uDCCA AgentDB${c.reset} ` +
774
- `${c.cyan}Vectors${c.reset} ${vectorColor}\u25CF${agentdb.vectorCount}${hnswInd}${c.reset} ${c.dim}\u2502${c.reset} ` +
775
- `${c.cyan}Size${c.reset} ${c.brightWhite}${sizeDisp}${c.reset} ${c.dim}\u2502${c.reset} ` +
776
- `${c.cyan}Tests${c.reset} ${testColor}\u25CF${tests.testFiles}${c.reset} ${c.dim}(~${tests.testCases} cases)${c.reset} ${c.dim}\u2502${c.reset} ` +
777
- integStr
778
- );
687
+ lines.push(`${c.dim}${'─'.repeat(53)}${c.reset}`);
688
+
689
+ // Swarm line (if enabled)
690
+ if (SL_CONFIG.show_swarm) {
691
+ const swarm = getSwarmStatus();
692
+ const system = getSystemMetrics();
693
+ const swarmInd = swarm.coordinationActive ? `${c.brightGreen}\u25C9${c.reset}` : `${c.dim}\u25CB${c.reset}`;
694
+ const agentsColor = swarm.activeAgents > 0 ? c.brightGreen : c.red;
695
+ lines.push(
696
+ `${c.brightYellow}\uD83E\uDD16 Swarm${c.reset} ${swarmInd} [${agentsColor}${String(swarm.activeAgents).padStart(2)}${c.reset}/${c.brightWhite}${swarm.maxAgents}${c.reset}] ` +
697
+ `${c.brightPurple}\uD83D\uDC65 ${system.subAgents}${c.reset} ` +
698
+ `${c.brightCyan}\uD83D\uDCBE ${system.memoryMB}MB${c.reset}`
699
+ );
700
+ }
701
+
702
+ // AgentDB + MCP line (if either enabled)
703
+ if (SL_CONFIG.show_agentdb || SL_CONFIG.show_mcp) {
704
+ const parts = [];
705
+ if (SL_CONFIG.show_agentdb) {
706
+ const agentdb = getAgentDBStats();
707
+ const hnswInd = agentdb.hasHnsw ? `${c.brightGreen}\u26A1${c.reset}` : '';
708
+ const sizeDisp = agentdb.dbSizeKB >= 1024 ? `${(agentdb.dbSizeKB / 1024).toFixed(1)}MB` : `${agentdb.dbSizeKB}KB`;
709
+ const vectorColor = agentdb.vectorCount > 0 ? c.brightGreen : c.dim;
710
+ parts.push(`${c.cyan}Vectors${c.reset} ${vectorColor}\u25CF${agentdb.vectorCount}${hnswInd}${c.reset}`);
711
+ parts.push(`${c.cyan}Size${c.reset} ${c.brightWhite}${sizeDisp}${c.reset}`);
712
+ }
713
+ if (SL_CONFIG.show_mcp) {
714
+ const integration = getIntegrationStatus();
715
+ if (integration.mcpServers.total > 0) {
716
+ const mcpCol = integration.mcpServers.enabled === integration.mcpServers.total ? c.brightGreen :
717
+ integration.mcpServers.enabled > 0 ? c.brightYellow : c.red;
718
+ parts.push(`${c.cyan}MCP${c.reset} ${mcpCol}\u25CF${integration.mcpServers.enabled}/${integration.mcpServers.total}${c.reset}`);
719
+ }
720
+ if (integration.hasDatabase) parts.push(`${c.brightGreen}\u25C6${c.reset}DB`);
721
+ }
722
+ if (parts.length > 0) {
723
+ lines.push(`${c.brightCyan}\uD83D\uDCCA AgentDB${c.reset} ${parts.join(` ${c.dim}\u2502${c.reset} `)}`);
724
+ }
725
+ }
726
+
727
+ return lines.join('\n');
728
+ }
729
+
730
+ // Compact dashboard: header + single combined line
731
+ function generateCompactDashboard() {
732
+ const git = getGitInfo();
733
+ const session = getSessionStats();
734
+ const lines = [];
735
+
736
+ // Header: branding + git + session
737
+ let header = `${c.bold}${c.brightPurple}\u258A ${SL_CONFIG.branding}${c.reset}`;
738
+ if (SL_CONFIG.show_git && git.gitBranch) {
739
+ header += ` ${c.brightBlue}\u23C7 ${git.gitBranch}${c.reset}`;
740
+ const changes = git.modified + git.staged + git.untracked;
741
+ if (changes > 0) {
742
+ let ind = '';
743
+ if (git.staged > 0) ind += `${c.brightGreen}+${git.staged}${c.reset}`;
744
+ if (git.modified > 0) ind += `${c.brightYellow}~${git.modified}${c.reset}`;
745
+ if (git.untracked > 0) ind += `${c.dim}?${git.untracked}${c.reset}`;
746
+ header += ` ${ind}`;
747
+ }
748
+ if (git.ahead > 0) header += ` ${c.brightGreen}\u2191${git.ahead}${c.reset}`;
749
+ if (git.behind > 0) header += ` ${c.brightRed}\u2193${git.behind}${c.reset}`;
750
+ }
751
+ if (SL_CONFIG.show_session && session.duration) {
752
+ header += ` ${c.dim}\u2502${c.reset} ${c.cyan}\u23F1 ${session.duration}${c.reset}`;
753
+ }
754
+ lines.push(header);
755
+
756
+ // Combined swarm + agentdb + mcp line
757
+ const segments = [];
758
+ if (SL_CONFIG.show_swarm) {
759
+ const swarm = getSwarmStatus();
760
+ const swarmInd = swarm.coordinationActive ? `${c.brightGreen}\u25C9${c.reset}` : `${c.dim}\u25CB${c.reset}`;
761
+ const agentsColor = swarm.activeAgents > 0 ? c.brightGreen : c.red;
762
+ segments.push(
763
+ `${c.brightYellow}\uD83E\uDD16${c.reset} ${swarmInd}[${agentsColor}${swarm.activeAgents}${c.reset}/${c.brightWhite}${swarm.maxAgents}${c.reset}]`
764
+ );
765
+ }
766
+ if (SL_CONFIG.show_agentdb) {
767
+ const agentdb = getAgentDBStats();
768
+ const hnswInd = agentdb.hasHnsw ? `\u26A1` : '';
769
+ const sizeDisp = agentdb.dbSizeKB >= 1024 ? `${(agentdb.dbSizeKB / 1024).toFixed(1)}MB` : `${agentdb.dbSizeKB}KB`;
770
+ const vectorColor = agentdb.vectorCount > 0 ? c.brightGreen : c.dim;
771
+ segments.push(
772
+ `${c.brightCyan}\uD83D\uDCCA${c.reset} ${vectorColor}${agentdb.vectorCount}${hnswInd}${c.reset} ${c.dim}(${sizeDisp})${c.reset}`
773
+ );
774
+ }
775
+ if (SL_CONFIG.show_mcp) {
776
+ const integration = getIntegrationStatus();
777
+ if (integration.mcpServers.total > 0) {
778
+ const mcpCol = integration.mcpServers.enabled === integration.mcpServers.total ? c.brightGreen :
779
+ integration.mcpServers.enabled > 0 ? c.brightYellow : c.red;
780
+ segments.push(`${c.cyan}MCP${c.reset} ${mcpCol}\u25CF${integration.mcpServers.enabled}/${integration.mcpServers.total}${c.reset}`);
781
+ }
782
+ }
783
+ if (segments.length > 0) {
784
+ lines.push(segments.join(` ${c.dim}\u2502${c.reset} `));
785
+ }
779
786
 
780
787
  return lines.join('\n');
781
788
  }
@@ -801,8 +808,10 @@ function generateJSON() {
801
808
  // ─── Main ───────────────────────────────────────────────────────
802
809
  if (process.argv.includes('--json')) {
803
810
  console.log(JSON.stringify(generateJSON(), null, 2));
804
- } else if (process.argv.includes('--compact')) {
811
+ } else if (process.argv.includes('--json-compact')) {
805
812
  console.log(JSON.stringify(generateJSON()));
813
+ } else if (process.argv.includes('--compact') || SL_CONFIG.mode === 'compact') {
814
+ console.log(generateCompactDashboard());
806
815
  } else if (process.argv.includes('--dashboard') || SL_CONFIG.mode === 'dashboard') {
807
816
  console.log(generateDashboard());
808
817
  } else {
package/README.md CHANGED
@@ -4,9 +4,9 @@
4
4
 
5
5
  # MoFlo
6
6
 
7
- **An opinionated, maintained fork of [Ruflo/Claude Flow](https://github.com/ruvnet/ruflo) that just works.**
7
+ **An opinionated fork of [Ruflo/Claude Flow](https://github.com/ruvnet/ruflo), optimized for local development.**
8
8
 
9
- MoFlo adds automatic code and guidance cataloging along with memory gating on top of the original Claude Flow orchestration engine. Where the upstream project provides raw building blocks, MoFlo ships opinionated defaults — workflow gates that enforce memory-first patterns, semantic indexing that runs at session start, and learned routing that improves over time — so you get a productive setup from `flo init` without manual tuning.
9
+ MoFlo adds automatic code and guidance cataloging along with memory gating on top of the original Ruflo/Claude Flow orchestration engine. Where the upstream project provides raw building blocks, MoFlo ships opinionated defaults — workflow gates that enforce memory-first patterns, semantic indexing that runs at session start, and learned routing that improves over time — so you get a productive setup from `flo init` without manual tuning.
10
10
 
11
11
  Install it as a dev dependency and run `flo init`.
12
12
 
@@ -23,29 +23,82 @@ Install it as a dev dependency and run `flo init`.
23
23
  | **Context Tracking** | Monitors context window usage (FRESH → MODERATE → DEPLETED → CRITICAL) and advises accordingly. |
24
24
  | **Cross-Platform** | Works on macOS, Linux, and Windows. |
25
25
 
26
- ## Quick Start
26
+ ## Getting Started
27
+
28
+ ### 1. Install and init
27
29
 
28
30
  ```bash
29
- # Install as a dev dependency
30
31
  npm install --save-dev moflo
31
-
32
- # Initialize your project (generates config, hooks, skill, CLAUDE.md section)
33
32
  npx flo init
33
+ ```
34
+
35
+ `flo init` automatically scans your project to find where your guidance and code live, then writes the results into `moflo.yaml`. It looks for:
36
+
37
+ | What | Directories it checks | Default if none found |
38
+ |------|----------------------|----------------------|
39
+ | **Guidance** | `.claude/guidance`, `docs/guides`, `docs`, `architecture`, `adr`, `.cursor/rules` | `.claude/guidance` |
40
+ | **Source code** | `src`, `packages`, `lib`, `app`, `apps`, `services`, `server`, `client` | `src` |
41
+ | **Languages** | Scans detected source dirs for file extensions | `.ts`, `.tsx`, `.js`, `.jsx` |
42
+
43
+ It also generates:
34
44
 
35
- # Index your project's knowledge base
36
- npx flo memory index-guidance
37
- npx flo memory code-map
45
+ | Generated File | Purpose |
46
+ |----------------|---------|
47
+ | `moflo.yaml` | Project config with detected guidance/code locations |
48
+ | `.claude/settings.json` | Workflow gate hooks for Claude Code |
49
+ | `.claude/skills/flo/` | The `/flo` issue execution skill (also `/fl`) |
50
+ | `CLAUDE.md` section | Teaches Claude how to use MoFlo |
51
+ | `.gitignore` entries | Excludes MoFlo state directories |
38
52
 
39
- # Verify everything works
40
- npx flo doctor
53
+ In interactive mode (`flo init` without `--yes`), it shows what it found and lets you confirm or adjust before writing.
54
+
55
+ ### 2. Review your guidance and code settings
56
+
57
+ Open `moflo.yaml` to see what init detected. The two key sections:
58
+
59
+ **Guidance** — documentation that helps Claude understand your project (conventions, architecture, domain context):
60
+
61
+ ```yaml
62
+ guidance:
63
+ directories:
64
+ - .claude/guidance # project rules, patterns, conventions
65
+ - docs # general documentation
41
66
  ```
42
67
 
43
- That's it. `flo init` sets up everything:
44
- - `moflo.yaml` — project config (auto-detects source dirs, languages, guidance paths)
45
- - `.claude/settings.json` — workflow gate hooks
46
- - `.claude/skills/flo/` — the `/flo` issue execution skill (with `/fl` alias)
47
- - `CLAUDE.md` — appends a MoFlo workflow section so Claude knows how to use it
48
- - `.gitignore` adds state directories
68
+ **Code map** source files to index for "where does X live?" navigation:
69
+
70
+ ```yaml
71
+ code_map:
72
+ directories:
73
+ - src # your source code
74
+ - packages # shared packages (monorepo)
75
+ extensions: [".ts", ".tsx"]
76
+ exclude: [node_modules, dist, .next, coverage]
77
+ ```
78
+
79
+ MoFlo chunks your guidance files into semantic embeddings and indexes your code structure, so Claude searches your knowledge base before touching any files. Adjust these directories to match your project:
80
+
81
+ ```yaml
82
+ # Monorepo with shared docs
83
+ guidance:
84
+ directories: [.claude/guidance, docs, packages/shared/docs]
85
+ code_map:
86
+ directories: [packages, apps, libs]
87
+
88
+ # Backend + frontend
89
+ code_map:
90
+ directories: [server/src, client/src]
91
+ ```
92
+
93
+ ### 3. Index and verify
94
+
95
+ ```bash
96
+ npx flo memory index-guidance # Index your guidance docs
97
+ npx flo memory code-map # Index your code structure
98
+ npx flo doctor # Verify everything works
99
+ ```
100
+
101
+ Both indexes run automatically at session start after this, so you only need to run them manually on first setup or after major structural changes.
49
102
 
50
103
  ## Commands
51
104
 
@@ -120,21 +173,22 @@ flo doctor # Health check
120
173
  flo --version # Show version
121
174
  ```
122
175
 
123
- ## Configuration
124
176
 
125
- `flo init` generates a `moflo.yaml` at your project root:
177
+ ## Full Configuration Reference
178
+
179
+ `flo init` generates a `moflo.yaml` at your project root. Here's the complete set of options:
126
180
 
127
181
  ```yaml
128
182
  project:
129
183
  name: "my-project"
130
184
 
131
185
  guidance:
132
- directories: [.claude/guidance] # Where your knowledge docs live
186
+ directories: [.claude/guidance]
133
187
  namespace: guidance
134
188
 
135
189
  code_map:
136
- directories: [src, packages] # Source dirs to index
137
- extensions: [".ts", ".tsx"] # Auto-detected from your project
190
+ directories: [src, packages]
191
+ extensions: [".ts", ".tsx"]
138
192
  exclude: [node_modules, dist]
139
193
  namespace: code-map
140
194
 
@@ -147,42 +201,36 @@ auto_index:
147
201
  guidance: true # Auto-index docs on session start
148
202
  code_map: true # Auto-index code on session start
149
203
 
150
- # Hook toggles (all on by default — disable to slim down)
151
204
  hooks:
152
205
  pre_edit: true # Track file edits for learning
153
- post_edit: true # Record edit outcomes, train neural patterns
154
- pre_task: true # Get agent routing before task spawn
206
+ post_edit: true # Record edit outcomes
207
+ pre_task: true # Agent routing before task spawn
155
208
  post_task: true # Record task results for learning
156
209
  gate: true # Workflow gate enforcement
157
- route: true # Intelligent task routing on each prompt
210
+ route: true # Intelligent task routing
158
211
  stop_hook: true # Session-end persistence
159
212
  session_restore: true # Restore session state on start
160
- notification: true # Hook into Claude Code notifications
161
213
 
162
214
  models:
163
- default: opus # General tasks
164
- research: sonnet # Research/exploration agents
165
- review: opus # Code review agents
166
- test: sonnet # Test-writing agents
215
+ default: opus
216
+ research: sonnet
217
+ review: opus
218
+ test: sonnet
167
219
 
168
- # Optional: intelligent model routing (off by default)
169
220
  model_routing:
170
- enabled: false # Set to true to enable
221
+ enabled: false # Set to true for automatic model selection
171
222
  confidence_threshold: 0.85
172
223
  cost_optimization: true
173
224
  circuit_breaker: true
174
225
 
175
- # Status line display
176
226
  status_line:
177
227
  enabled: true
178
- branding: "Moflo V4"
179
- mode: single-line # single-line or dashboard
228
+ branding: "MoFlo V4"
229
+ mode: compact # single-line, compact, or dashboard
180
230
  show_git: true
181
- show_model: true
182
231
  show_session: true
183
- show_intelligence: true
184
232
  show_swarm: true
185
- show_hooks: true
233
+ show_agentdb: true
186
234
  show_mcp: true
187
235
  ```
188
236
 
@@ -228,13 +276,54 @@ MoFlo installs Claude Code hooks that run on every tool call. Together, these ga
228
276
 
229
277
  All gates are configurable via `moflo.yaml` — you can disable any individual hook if it doesn't suit your workflow.
230
278
 
231
- ### The Task System
279
+ ### Intelligent Agent Routing
280
+
281
+ MoFlo ships with 12 built-in task patterns that map common work to the right agent type:
282
+
283
+ | Pattern | Keywords | Primary Agent |
284
+ |---------|----------|---------------|
285
+ | security-task | auth, password, encryption, CVE | security-architect |
286
+ | testing-task | test, spec, coverage, e2e | tester |
287
+ | database-task | schema, migration, SQL, ORM | architect |
288
+ | feature-task | implement, add, create, build | architect → coder |
289
+ | bugfix-task | bug, fix, error, crash, debug | coder |
290
+ | api-task | endpoint, REST, route, handler | architect → coder |
291
+ | ... | | *(12 patterns total)* |
292
+
293
+ When you route a task (`flo hooks route --task "..."` or via MCP), MoFlo runs semantic similarity against these patterns using HNSW vector search and returns a ranked recommendation with confidence scores.
294
+
295
+ **The routing gets smarter over time.** Every time a task completes successfully, MoFlo's post-task hook records the outcome — the full task description, which agent handled it, and whether it succeeded. These learned patterns are combined with the built-in seeds on every future route call. Because learned patterns contain rich task descriptions (not just short keywords), they discriminate better as they accumulate.
232
296
 
233
- MoFlo integrates Claude Code's native Task tool with its own coordination layer:
297
+ Routing outcomes are stored in `.claude-flow/routing-outcomes.json` and persist across sessions. You can inspect them with `flo hooks patterns` or transfer them between projects with `flo hooks transfer`.
234
298
 
235
- 1. **Pre-task hook** — Before a sub-agent spawns, MoFlo records what's about to happen and can inject context (prior learnings, routing recommendations) into the agent's prompt.
236
- 2. **Post-task hook** — After a sub-agent completes, MoFlo records the outcome. Successful patterns are stored in the memory database for future reference. Failed patterns feed into the routing circuit breaker.
237
- 3. **The `/flo` skill** Wraps the entire lifecycle of a GitHub issue: research the issue enhance the ticket implement the solution run tests → simplify the code create a PR. Each phase can use sub-agents, and all learning feeds back into memory.
299
+ ### The Two-Layer Task System
300
+
301
+ MoFlo doesn't replace your AI client's task system it wraps it. Your client (Claude Code, Cursor, or any MCP-capable tool) handles spawning agents and running code. MoFlo adds a coordination layer on top that handles memory, routing, and learning.
302
+
303
+ ```
304
+ ┌──────────────────────────────────────────────────┐
305
+ │ YOUR AI CLIENT (Execution Layer) │
306
+ │ Spawns agents, runs code, streams output │
307
+ │ TaskCreate → Agent → TaskUpdate → results │
308
+ ├──────────────────────────────────────────────────┤
309
+ │ MOFLO (Knowledge Layer) │
310
+ │ Routes tasks, gates agent spawns, stores │
311
+ │ patterns, learns from outcomes │
312
+ └──────────────────────────────────────────────────┘
313
+ ```
314
+
315
+ Here's how a typical task flows through both layers:
316
+
317
+ 1. **MoFlo routes** — Before work starts, MoFlo analyzes the prompt and recommends an agent type and model tier via hook or MCP tool.
318
+ 2. **MoFlo gates** — Before an agent can spawn, MoFlo verifies that memory was searched and a task was registered. This prevents blind exploration.
319
+ 3. **Your client executes** — The actual agent runs through your client's native task system. MoFlo doesn't manage the agent — your client handles execution, output, and completion.
320
+ 4. **MoFlo learns** — After the agent finishes, MoFlo records what worked (or didn't) in its memory database. Successful patterns feed into future routing.
321
+
322
+ The key insight: **your client handles execution, MoFlo handles knowledge.** Your client is good at spawning agents and running code. MoFlo is good at remembering what happened, routing to the right agent, and ensuring prior knowledge is checked before exploring from scratch.
323
+
324
+ For complex work, MoFlo structures tasks into waves — a research wave discovers context, then an implementation wave acts on it — with dependencies tracked through both the client's task system and MoFlo's coordination layer. The full integration pattern is documented in `.claude/guidance/task-swarm-integration.md`.
325
+
326
+ The `/flo` skill ties both systems together for GitHub issues — driving a full workflow (research → enhance → implement → test → simplify → PR) with your client's agents for execution and MoFlo's memory for continuity.
238
327
 
239
328
  ### Memory & Knowledge Storage
240
329
 
@@ -262,18 +351,10 @@ When `flo init` runs, it appends a workflow section to your CLAUDE.md that teach
262
351
 
263
352
  ## Architecture
264
353
 
265
- MoFlo is a maintained fork of [ruflo 3.x](https://github.com/ruvnet/ruflo) with:
266
-
267
- - **3 patches applied to TypeScript source** (no more monkey-patching node_modules):
268
- - 384-dim domain-aware embeddings for consistent CLI ↔ MCP search
269
- - `windowsHide: true` on all spawn/exec calls (Windows UX)
270
- - Routing learned patterns (task outcomes feed back into routing)
271
354
  - **7 standalone bin scripts** shipped with npm: `flo-search`, `flo-embeddings`, `flo-index`, `flo-codemap`, `flo-learn`, `flo-setup`, plus the main `flo` CLI
272
355
  - **Project config system**: `moflo.yaml` for per-project settings
273
356
  - **One-stop init**: `flo init` generates everything needed for OOTB operation
274
357
 
275
- Upstream remote preserved for cherry-picking future ruflo fixes.
276
-
277
358
  ## License
278
359
 
279
360
  MIT (inherited from [upstream](https://github.com/ruvnet/ruflo))
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "moflo",
3
- "version": "4.6.5",
3
+ "version": "4.6.6",
4
4
  "description": "MoFlo — AI agent orchestration for Claude Code. Forked from ruflo/claude-flow with patches applied to source, plus feature-level orchestration.",
5
5
  "main": "dist/index.js",
6
6
  "type": "module",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@moflo/cli",
3
- "version": "4.6.5",
3
+ "version": "4.6.6",
4
4
  "type": "module",
5
5
  "description": "MoFlo CLI — AI agent orchestration with specialized agents, swarm coordination, MCP server, self-learning hooks, and vector memory for Claude Code",
6
6
  "main": "dist/src/index.js",