claude-flow 3.42.3 → 3.42.4
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/.claude/agents/MIGRATION_SUMMARY.md +221 -221
- package/.claude/agents/analysis/analyze-code-quality.md +57 -57
- package/.claude/agents/analysis/code-analyzer.md +188 -188
- package/.claude/agents/analysis/code-review/analyze-code-quality.md +57 -57
- package/.claude/agents/architecture/system-design/arch-system-design.md +35 -35
- package/.claude/agents/base-template-generator.md +41 -41
- package/.claude/agents/consensus/byzantine-coordinator.md +42 -42
- package/.claude/agents/consensus/crdt-synchronizer.md +976 -976
- package/.claude/agents/consensus/gossip-coordinator.md +42 -42
- package/.claude/agents/consensus/performance-benchmarker.md +830 -830
- package/.claude/agents/consensus/quorum-manager.md +802 -802
- package/.claude/agents/consensus/raft-manager.md +42 -42
- package/.claude/agents/consensus/security-manager.md +601 -601
- package/.claude/agents/core/coder.md +254 -254
- package/.claude/agents/core/planner.md +151 -151
- package/.claude/agents/core/researcher.md +173 -173
- package/.claude/agents/core/reviewer.md +308 -308
- package/.claude/agents/core/tester.md +299 -299
- package/.claude/agents/custom/test-long-runner.md +43 -43
- package/.claude/agents/data/ml/data-ml-model.md +75 -75
- package/.claude/agents/database-specialist.md +9 -9
- package/.claude/agents/development/backend/dev-backend-api.md +28 -28
- package/.claude/agents/development/dev-backend-api.md +177 -177
- package/.claude/agents/devops/ci-cd/ops-cicd-github.md +51 -51
- package/.claude/agents/documentation/api-docs/docs-api-openapi.md +62 -62
- package/.claude/agents/dual-mode/codex-coordinator.md +206 -206
- package/.claude/agents/dual-mode/codex-worker.md +190 -190
- package/.claude/agents/dual-mode/dual-orchestrator.md +253 -253
- package/.claude/agents/flow-nexus/app-store.md +87 -87
- package/.claude/agents/flow-nexus/authentication.md +68 -68
- package/.claude/agents/flow-nexus/challenges.md +80 -80
- package/.claude/agents/flow-nexus/neural-network.md +87 -87
- package/.claude/agents/flow-nexus/payments.md +82 -82
- package/.claude/agents/flow-nexus/sandbox.md +75 -75
- package/.claude/agents/flow-nexus/swarm.md +75 -75
- package/.claude/agents/flow-nexus/user-tools.md +95 -95
- package/.claude/agents/flow-nexus/workflow.md +83 -83
- package/.claude/agents/github/code-review-swarm.md +520 -520
- package/.claude/agents/github/github-modes.md +153 -153
- package/.claude/agents/github/issue-tracker.md +298 -298
- package/.claude/agents/github/multi-repo-swarm.md +524 -524
- package/.claude/agents/github/pr-manager.md +162 -162
- package/.claude/agents/github/project-board-sync.md +477 -477
- package/.claude/agents/github/release-manager.md +337 -337
- package/.claude/agents/github/release-swarm.md +550 -550
- package/.claude/agents/github/repo-architect.md +364 -364
- package/.claude/agents/github/swarm-issue.md +550 -550
- package/.claude/agents/github/swarm-pr.md +401 -401
- package/.claude/agents/github/sync-coordinator.md +424 -424
- package/.claude/agents/github/workflow-automation.md +604 -604
- package/.claude/agents/goal/agent.md +816 -816
- package/.claude/agents/goal/code-goal-planner.md +444 -444
- package/.claude/agents/goal/goal-planner.md +167 -167
- package/.claude/agents/hive-mind/collective-intelligence-coordinator.md +128 -128
- package/.claude/agents/hive-mind/queen-coordinator.md +201 -201
- package/.claude/agents/hive-mind/scout-explorer.md +240 -240
- package/.claude/agents/hive-mind/swarm-memory-manager.md +191 -191
- package/.claude/agents/hive-mind/worker-specialist.md +215 -215
- package/.claude/agents/neural/safla-neural.md +73 -73
- package/.claude/agents/optimization/benchmark-suite.md +662 -662
- package/.claude/agents/optimization/load-balancer.md +428 -428
- package/.claude/agents/optimization/performance-monitor.md +669 -669
- package/.claude/agents/optimization/resource-allocator.md +671 -671
- package/.claude/agents/optimization/topology-optimizer.md +805 -805
- package/.claude/agents/payments/agentic-payments.md +126 -126
- package/.claude/agents/project-coordinator.md +8 -8
- package/.claude/agents/python-specialist.md +9 -9
- package/.claude/agents/reasoning/agent.md +816 -816
- package/.claude/agents/reasoning/goal-planner.md +72 -72
- package/.claude/agents/security-auditor.md +9 -9
- package/.claude/agents/sona/sona-learning-optimizer.md +65 -65
- package/.claude/agents/sparc/architecture.md +452 -452
- package/.claude/agents/sparc/pseudocode.md +298 -298
- package/.claude/agents/sparc/refinement.md +503 -503
- package/.claude/agents/sparc/specification.md +257 -257
- package/.claude/agents/specialized/mobile/spec-mobile-react-native.md +87 -87
- package/.claude/agents/sublinear/consensus-coordinator.md +337 -337
- package/.claude/agents/sublinear/matrix-optimizer.md +184 -184
- package/.claude/agents/sublinear/pagerank-analyzer.md +298 -298
- package/.claude/agents/sublinear/performance-optimizer.md +367 -367
- package/.claude/agents/sublinear/trading-predictor.md +245 -245
- package/.claude/agents/swarm/adaptive-coordinator.md +363 -363
- package/.claude/agents/swarm/hierarchical-coordinator.md +299 -299
- package/.claude/agents/swarm/mesh-coordinator.md +362 -362
- package/.claude/agents/templates/automation-smart-agent.md +184 -184
- package/.claude/agents/templates/coordinator-swarm-init.md +82 -82
- package/.claude/agents/templates/github-pr-manager.md +154 -154
- package/.claude/agents/templates/implementer-sparc-coder.md +242 -242
- package/.claude/agents/templates/memory-coordinator.md +162 -162
- package/.claude/agents/templates/migration-plan.md +723 -723
- package/.claude/agents/templates/orchestrator-task.md +119 -119
- package/.claude/agents/templates/performance-analyzer.md +178 -178
- package/.claude/agents/templates/sparc-coordinator.md +162 -162
- package/.claude/agents/testing/production-validator.md +372 -372
- package/.claude/agents/testing/tdd-london-swarm.md +221 -221
- package/.claude/agents/testing/unit/tdd-london-swarm.md +221 -221
- package/.claude/agents/testing/validation/production-validator.md +372 -372
- package/.claude/agents/typescript-specialist.md +9 -9
- package/.claude/agents/v3/database-specialist.md +9 -9
- package/.claude/agents/v3/project-coordinator.md +8 -8
- package/.claude/agents/v3/python-specialist.md +9 -9
- package/.claude/agents/v3/test-architect.md +9 -9
- package/.claude/agents/v3/typescript-specialist.md +9 -9
- package/.claude/agents/v3/v3-integration-architect.md +311 -311
- package/.claude/agents/v3/v3-memory-specialist.md +280 -280
- package/.claude/agents/v3/v3-performance-engineer.md +362 -362
- package/.claude/agents/v3/v3-queen-coordinator.md +62 -62
- package/.claude/agents/v3/v3-security-architect.md +139 -139
- package/.claude/checkpoints/1767754460.json +8 -8
- package/.claude/commands/agents/README.md +10 -10
- package/.claude/commands/agents/agent-capabilities.md +21 -21
- package/.claude/commands/agents/agent-coordination.md +28 -28
- package/.claude/commands/agents/agent-spawning.md +28 -28
- package/.claude/commands/agents/agent-types.md +26 -26
- package/.claude/commands/analysis/COMMAND_COMPLIANCE_REPORT.md +53 -53
- package/.claude/commands/analysis/README.md +9 -9
- package/.claude/commands/analysis/bottleneck-detect.md +162 -162
- package/.claude/commands/analysis/performance-bottlenecks.md +58 -58
- package/.claude/commands/analysis/performance-report.md +25 -25
- package/.claude/commands/analysis/token-efficiency.md +44 -44
- package/.claude/commands/analysis/token-usage.md +25 -25
- package/.claude/commands/automation/README.md +9 -9
- package/.claude/commands/automation/auto-agent.md +122 -122
- package/.claude/commands/automation/self-healing.md +105 -105
- package/.claude/commands/automation/session-memory.md +89 -89
- package/.claude/commands/automation/smart-agents.md +72 -72
- package/.claude/commands/automation/smart-spawn.md +25 -25
- package/.claude/commands/automation/workflow-select.md +25 -25
- package/.claude/commands/claude-flow-help.md +103 -103
- package/.claude/commands/claude-flow-memory.md +107 -107
- package/.claude/commands/claude-flow-swarm.md +205 -205
- package/.claude/commands/coordination/README.md +9 -9
- package/.claude/commands/coordination/agent-spawn.md +25 -25
- package/.claude/commands/coordination/init.md +44 -44
- package/.claude/commands/coordination/orchestrate.md +43 -43
- package/.claude/commands/coordination/spawn.md +45 -45
- package/.claude/commands/coordination/swarm-init.md +85 -85
- package/.claude/commands/coordination/task-orchestrate.md +25 -25
- package/.claude/commands/flow-nexus/app-store.md +123 -123
- package/.claude/commands/flow-nexus/challenges.md +119 -119
- package/.claude/commands/flow-nexus/login-registration.md +64 -64
- package/.claude/commands/flow-nexus/neural-network.md +133 -133
- package/.claude/commands/flow-nexus/payments.md +115 -115
- package/.claude/commands/flow-nexus/sandbox.md +82 -82
- package/.claude/commands/flow-nexus/swarm.md +86 -86
- package/.claude/commands/flow-nexus/user-tools.md +151 -151
- package/.claude/commands/flow-nexus/workflow.md +114 -114
- package/.claude/commands/github/README.md +11 -11
- package/.claude/commands/github/code-review-swarm.md +513 -513
- package/.claude/commands/github/code-review.md +25 -25
- package/.claude/commands/github/github-modes.md +146 -146
- package/.claude/commands/github/github-swarm.md +121 -121
- package/.claude/commands/github/issue-tracker.md +291 -291
- package/.claude/commands/github/issue-triage.md +25 -25
- package/.claude/commands/github/multi-repo-swarm.md +518 -518
- package/.claude/commands/github/pr-enhance.md +26 -26
- package/.claude/commands/github/pr-manager.md +169 -169
- package/.claude/commands/github/project-board-sync.md +470 -470
- package/.claude/commands/github/release-manager.md +337 -337
- package/.claude/commands/github/release-swarm.md +543 -543
- package/.claude/commands/github/repo-analyze.md +25 -25
- package/.claude/commands/github/repo-architect.md +366 -366
- package/.claude/commands/github/swarm-issue.md +481 -481
- package/.claude/commands/github/swarm-pr.md +284 -284
- package/.claude/commands/github/sync-coordinator.md +300 -300
- package/.claude/commands/github/workflow-automation.md +441 -441
- package/.claude/commands/hive-mind/README.md +17 -17
- package/.claude/commands/hive-mind/hive-mind-consensus.md +8 -8
- package/.claude/commands/hive-mind/hive-mind-init.md +18 -18
- package/.claude/commands/hive-mind/hive-mind-memory.md +8 -8
- package/.claude/commands/hive-mind/hive-mind-metrics.md +8 -8
- package/.claude/commands/hive-mind/hive-mind-resume.md +8 -8
- package/.claude/commands/hive-mind/hive-mind-sessions.md +8 -8
- package/.claude/commands/hive-mind/hive-mind-spawn.md +21 -21
- package/.claude/commands/hive-mind/hive-mind-status.md +8 -8
- package/.claude/commands/hive-mind/hive-mind-stop.md +8 -8
- package/.claude/commands/hive-mind/hive-mind-wizard.md +8 -8
- package/.claude/commands/hive-mind/hive-mind.md +27 -27
- package/.claude/commands/hooks/README.md +11 -11
- package/.claude/commands/hooks/overview.md +57 -57
- package/.claude/commands/hooks/post-edit.md +117 -117
- package/.claude/commands/hooks/post-task.md +112 -112
- package/.claude/commands/hooks/pre-edit.md +113 -113
- package/.claude/commands/hooks/pre-task.md +111 -111
- package/.claude/commands/hooks/session-end.md +118 -118
- package/.claude/commands/hooks/setup.md +102 -102
- package/.claude/commands/memory/README.md +9 -9
- package/.claude/commands/memory/memory-persist.md +25 -25
- package/.claude/commands/memory/memory-search.md +25 -25
- package/.claude/commands/memory/memory-usage.md +25 -25
- package/.claude/commands/memory/neural.md +47 -47
- package/.claude/commands/monitoring/README.md +9 -9
- package/.claude/commands/monitoring/agent-metrics.md +25 -25
- package/.claude/commands/monitoring/agents.md +44 -44
- package/.claude/commands/monitoring/real-time-view.md +25 -25
- package/.claude/commands/monitoring/status.md +46 -46
- package/.claude/commands/monitoring/swarm-monitor.md +25 -25
- package/.claude/commands/optimization/README.md +9 -9
- package/.claude/commands/optimization/auto-topology.md +61 -61
- package/.claude/commands/optimization/cache-manage.md +25 -25
- package/.claude/commands/optimization/parallel-execute.md +25 -25
- package/.claude/commands/optimization/parallel-execution.md +49 -49
- package/.claude/commands/optimization/topology-optimize.md +25 -25
- package/.claude/commands/pair/README.md +260 -260
- package/.claude/commands/pair/commands.md +545 -545
- package/.claude/commands/pair/config.md +509 -509
- package/.claude/commands/pair/examples.md +511 -511
- package/.claude/commands/pair/modes.md +347 -347
- package/.claude/commands/pair/session.md +406 -406
- package/.claude/commands/pair/start.md +208 -208
- package/.claude/commands/sparc/analyzer.md +51 -51
- package/.claude/commands/sparc/architect.md +53 -53
- package/.claude/commands/sparc/ask.md +97 -97
- package/.claude/commands/sparc/batch-executor.md +54 -54
- package/.claude/commands/sparc/code.md +89 -89
- package/.claude/commands/sparc/coder.md +54 -54
- package/.claude/commands/sparc/debug.md +83 -83
- package/.claude/commands/sparc/debugger.md +54 -54
- package/.claude/commands/sparc/designer.md +53 -53
- package/.claude/commands/sparc/devops.md +109 -109
- package/.claude/commands/sparc/docs-writer.md +80 -80
- package/.claude/commands/sparc/documenter.md +54 -54
- package/.claude/commands/sparc/innovator.md +54 -54
- package/.claude/commands/sparc/integration.md +83 -83
- package/.claude/commands/sparc/mcp.md +117 -117
- package/.claude/commands/sparc/memory-manager.md +54 -54
- package/.claude/commands/sparc/optimizer.md +54 -54
- package/.claude/commands/sparc/orchestrator.md +131 -131
- package/.claude/commands/sparc/post-deployment-monitoring-mode.md +83 -83
- package/.claude/commands/sparc/refinement-optimization-mode.md +83 -83
- package/.claude/commands/sparc/researcher.md +54 -54
- package/.claude/commands/sparc/reviewer.md +54 -54
- package/.claude/commands/sparc/security-review.md +80 -80
- package/.claude/commands/sparc/sparc-modes.md +174 -174
- package/.claude/commands/sparc/sparc.md +111 -111
- package/.claude/commands/sparc/spec-pseudocode.md +80 -80
- package/.claude/commands/sparc/supabase-admin.md +348 -348
- package/.claude/commands/sparc/swarm-coordinator.md +54 -54
- package/.claude/commands/sparc/tdd.md +54 -54
- package/.claude/commands/sparc/tester.md +54 -54
- package/.claude/commands/sparc/tutorial.md +79 -79
- package/.claude/commands/sparc/workflow-manager.md +54 -54
- package/.claude/commands/sparc.md +166 -166
- package/.claude/commands/stream-chain/pipeline.md +120 -120
- package/.claude/commands/stream-chain/run.md +69 -69
- package/.claude/commands/swarm/README.md +15 -15
- package/.claude/commands/swarm/analysis.md +95 -95
- package/.claude/commands/swarm/development.md +96 -96
- package/.claude/commands/swarm/examples.md +168 -168
- package/.claude/commands/swarm/maintenance.md +102 -102
- package/.claude/commands/swarm/optimization.md +117 -117
- package/.claude/commands/swarm/research.md +136 -136
- package/.claude/commands/swarm/swarm-analysis.md +8 -8
- package/.claude/commands/swarm/swarm-background.md +8 -8
- package/.claude/commands/swarm/swarm-init.md +19 -19
- package/.claude/commands/swarm/swarm-modes.md +8 -8
- package/.claude/commands/swarm/swarm-monitor.md +8 -8
- package/.claude/commands/swarm/swarm-spawn.md +19 -19
- package/.claude/commands/swarm/swarm-status.md +8 -8
- package/.claude/commands/swarm/swarm-strategies.md +8 -8
- package/.claude/commands/swarm/swarm.md +27 -27
- package/.claude/commands/swarm/testing.md +131 -131
- package/.claude/commands/training/README.md +9 -9
- package/.claude/commands/training/model-update.md +25 -25
- package/.claude/commands/training/neural-patterns.md +73 -73
- package/.claude/commands/training/neural-train.md +25 -25
- package/.claude/commands/training/pattern-learn.md +25 -25
- package/.claude/commands/training/specialization.md +62 -62
- package/.claude/commands/truth/start.md +142 -142
- package/.claude/commands/verify/check.md +49 -49
- package/.claude/commands/verify/start.md +127 -127
- package/.claude/commands/workflows/README.md +9 -9
- package/.claude/commands/workflows/development.md +77 -77
- package/.claude/commands/workflows/research.md +62 -62
- package/.claude/commands/workflows/workflow-create.md +25 -25
- package/.claude/commands/workflows/workflow-execute.md +25 -25
- package/.claude/commands/workflows/workflow-export.md +25 -25
- package/.claude/config/v3-dependency-optimization.json +265 -265
- package/.claude/config/v3-performance-targets.json +250 -250
- package/.claude/helpers/.LOCKED +2 -2
- package/.claude/helpers/README.md +96 -96
- package/.claude/helpers/adr-compliance.sh +186 -186
- package/.claude/helpers/aggressive-microcompact.mjs +36 -36
- package/.claude/helpers/auto-commit.sh +178 -178
- package/.claude/helpers/auto-memory-hook.mjs +430 -430
- package/.claude/helpers/checkpoint-manager.sh +251 -251
- package/.claude/helpers/context-persistence-hook.mjs +2001 -2001
- package/.claude/helpers/daemon-manager.sh +252 -252
- package/.claude/helpers/ddd-tracker.sh +144 -144
- package/.claude/helpers/github-safe.js +156 -156
- package/.claude/helpers/github-setup.sh +45 -45
- package/.claude/helpers/guidance-hook.sh +13 -13
- package/.claude/helpers/guidance-hooks.sh +102 -102
- package/.claude/helpers/health-monitor.sh +108 -108
- package/.claude/helpers/hook-handler.cjs +606 -606
- package/.claude/helpers/intelligence.cjs +1169 -1169
- package/.claude/helpers/learning-hooks.sh +329 -329
- package/.claude/helpers/learning-optimizer.sh +127 -127
- package/.claude/helpers/learning-service.mjs +1144 -1144
- package/.claude/helpers/memory.cjs +84 -84
- package/.claude/helpers/metrics-db.mjs +503 -503
- package/.claude/helpers/patch-aggressive-prune.mjs +184 -184
- package/.claude/helpers/pattern-consolidator.sh +86 -86
- package/.claude/helpers/perf-worker.sh +160 -160
- package/.claude/helpers/quick-start.sh +19 -19
- package/.claude/helpers/router.cjs +62 -62
- package/.claude/helpers/security-scanner.sh +127 -127
- package/.claude/helpers/session.cjs +125 -125
- package/.claude/helpers/setup-mcp.sh +18 -18
- package/.claude/helpers/standard-checkpoint-hooks.sh +189 -189
- package/.claude/helpers/statusline.cjs +0 -0
- package/.claude/helpers/swarm-comms.sh +353 -353
- package/.claude/helpers/swarm-hooks.sh +761 -761
- package/.claude/helpers/swarm-monitor.sh +210 -210
- package/.claude/helpers/sync-v3-metrics.sh +245 -245
- package/.claude/helpers/update-v3-progress.sh +165 -165
- package/.claude/helpers/v3-quick-status.sh +57 -57
- package/.claude/helpers/v3.sh +110 -110
- package/.claude/helpers/validate-v3-config.sh +215 -215
- package/.claude/helpers/worker-manager.sh +170 -170
- package/.claude/mcp.json +12 -12
- package/.claude/settings.json +284 -284
- package/.claude/settings.json.bak +526 -526
- package/.claude/skills/agentdb-advanced/SKILL.md +550 -550
- package/.claude/skills/agentdb-learning/SKILL.md +545 -545
- package/.claude/skills/agentdb-memory-patterns/SKILL.md +339 -339
- package/.claude/skills/agentdb-optimization/SKILL.md +509 -509
- package/.claude/skills/agentdb-vector-search/SKILL.md +339 -339
- package/.claude/skills/agentic-jujutsu/SKILL.md +645 -645
- package/.claude/skills/browser/SKILL.md +204 -204
- package/.claude/skills/dual-mode/README.md +71 -71
- package/.claude/skills/dual-mode/dual-collect.md +103 -103
- package/.claude/skills/dual-mode/dual-coordinate.md +85 -85
- package/.claude/skills/dual-mode/dual-spawn.md +81 -81
- package/.claude/skills/flow-nexus-neural/SKILL.md +727 -727
- package/.claude/skills/flow-nexus-platform/SKILL.md +1154 -1154
- package/.claude/skills/flow-nexus-swarm/SKILL.md +604 -604
- package/.claude/skills/github-code-review/SKILL.md +1125 -1125
- package/.claude/skills/github-multi-repo/SKILL.md +862 -862
- package/.claude/skills/github-project-management/SKILL.md +1262 -1262
- package/.claude/skills/github-release-management/SKILL.md +1064 -1064
- package/.claude/skills/github-workflow-automation/SKILL.md +1047 -1047
- package/.claude/skills/hive-mind-advanced/SKILL.md +709 -709
- package/.claude/skills/hooks-automation/SKILL.md +1201 -1201
- package/.claude/skills/pair-programming/SKILL.md +1202 -1202
- package/.claude/skills/performance-analysis/SKILL.md +560 -560
- package/.claude/skills/reasoningbank-agentdb/SKILL.md +446 -446
- package/.claude/skills/reasoningbank-intelligence/SKILL.md +201 -201
- package/.claude/skills/skill-builder/SKILL.md +910 -910
- package/.claude/skills/sparc-methodology/SKILL.md +1106 -1106
- package/.claude/skills/stream-chain/SKILL.md +560 -560
- package/.claude/skills/swarm-advanced/SKILL.md +970 -970
- package/.claude/skills/swarm-orchestration/SKILL.md +179 -179
- package/.claude/skills/v3-cli-modernization/SKILL.md +871 -871
- package/.claude/skills/v3-core-implementation/SKILL.md +796 -796
- package/.claude/skills/v3-ddd-architecture/SKILL.md +441 -441
- package/.claude/skills/v3-integration-deep/SKILL.md +240 -240
- package/.claude/skills/v3-mcp-optimization/SKILL.md +776 -776
- package/.claude/skills/v3-memory-unification/SKILL.md +173 -173
- package/.claude/skills/v3-performance-optimization/SKILL.md +389 -389
- package/.claude/skills/v3-security-overhaul/SKILL.md +81 -81
- package/.claude/skills/v3-swarm-coordination/SKILL.md +339 -339
- package/.claude/skills/verification-quality/SKILL.md +691 -691
- package/.claude/skills/worker-benchmarks/SKILL.md +129 -129
- package/.claude/skills/worker-integration/SKILL.md +147 -147
- package/.claude/statusline-command.sh +176 -176
- package/.claude/statusline.mjs +109 -109
- package/.claude/statusline.sh +431 -431
- package/.claude/workflows/full-system-test.js +65 -65
- package/.claude/workflows/intelligence-system-hardening.js +120 -120
- package/.claude/workflows/plugin-contract-audit.js +91 -91
- package/.claude-plugin/README.md +720 -720
- package/.claude-plugin/docs/INSTALLATION.md +261 -261
- package/.claude-plugin/docs/PLUGIN_SUMMARY.md +361 -361
- package/.claude-plugin/docs/QUICKSTART.md +361 -361
- package/.claude-plugin/docs/STRUCTURE.md +128 -128
- package/.claude-plugin/hooks/hooks.json +77 -77
- package/.claude-plugin/marketplace.json +204 -204
- package/.claude-plugin/plugin.json +71 -71
- package/.claude-plugin/scripts/install.sh +234 -234
- package/.claude-plugin/scripts/ruflo-hook.cjs +304 -304
- package/.claude-plugin/scripts/ruflo-hook.sh +52 -52
- package/.claude-plugin/scripts/uninstall.sh +36 -36
- package/.claude-plugin/scripts/verify.sh +108 -108
- package/LICENSE +21 -21
- package/README.md +422 -422
- package/bin/cli.js +11 -11
- package/bin/npx-repair.js +7 -7
- package/bin/npx-safe-launch.js +9 -9
- package/node_modules/@claude-flow/codex/.agents/skills/github-automation/SKILL.md +32 -32
- package/node_modules/@claude-flow/codex/.agents/skills/memory-management/SKILL.md +45 -45
- package/node_modules/@claude-flow/codex/.agents/skills/performance-analysis/SKILL.md +32 -32
- package/node_modules/@claude-flow/codex/.agents/skills/security-audit/SKILL.md +46 -46
- package/node_modules/@claude-flow/codex/.agents/skills/sparc-methodology/SKILL.md +46 -46
- package/node_modules/@claude-flow/codex/.agents/skills/swarm-orchestration/SKILL.md +53 -53
- package/node_modules/@claude-flow/codex/README.md +1044 -1044
- package/node_modules/@claude-flow/codex/dist/dual-mode/orchestrator.js +13 -13
- package/node_modules/@claude-flow/codex/dist/generators/agents-md.js +664 -664
- package/node_modules/@claude-flow/codex/dist/generators/config-toml.js +455 -455
- package/node_modules/@claude-flow/codex/dist/generators/skill-md.js +45 -45
- package/node_modules/@claude-flow/codex/dist/initializer.js +167 -167
- package/node_modules/@claude-flow/codex/dist/templates/index.js +15 -15
- package/node_modules/@claude-flow/mcp/README.md +429 -429
- package/node_modules/@claude-flow/plugin-agent-federation/README.md +49 -49
- package/node_modules/@claude-flow/security/README.md +292 -292
- package/node_modules/@claude-flow/security/dist/credential-generator.js +9 -9
- package/node_modules/@claude-flow/security/dist/input-validator.d.ts +6 -6
- package/node_modules/@claude-flow/security/dist/oauth/callback-server.js +9 -9
- package/package.json +222 -222
- package/v3/@claude-flow/cli/README.md +422 -422
- package/v3/@claude-flow/cli/bin/cli.js +338 -338
- package/v3/@claude-flow/cli/bin/mcp-server.js +224 -224
- package/v3/@claude-flow/cli/bin/preinstall.cjs +2 -2
- package/v3/@claude-flow/cli/catalog-manifest.json +2 -2
- package/v3/@claude-flow/cli/dist/src/benchmarks/gaia-critic.js +24 -24
- package/v3/@claude-flow/cli/dist/src/business-pods/bbs-budget-tracker.js +53 -53
- package/v3/@claude-flow/cli/dist/src/commands/completions.js +409 -409
- package/v3/@claude-flow/cli/dist/src/commands/daemon.js +44 -44
- package/v3/@claude-flow/cli/dist/src/commands/doctor.js +4 -4
- package/v3/@claude-flow/cli/dist/src/commands/embeddings.js +26 -26
- package/v3/@claude-flow/cli/dist/src/commands/hive-mind.js +97 -97
- package/v3/@claude-flow/cli/dist/src/commands/hooks.js +9 -9
- package/v3/@claude-flow/cli/dist/src/commands/init.js +75 -75
- package/v3/@claude-flow/cli/dist/src/commands/ruvector/backup.js +23 -23
- package/v3/@claude-flow/cli/dist/src/commands/ruvector/benchmark.js +31 -31
- package/v3/@claude-flow/cli/dist/src/commands/ruvector/import.js +14 -14
- package/v3/@claude-flow/cli/dist/src/commands/ruvector/init.js +115 -115
- package/v3/@claude-flow/cli/dist/src/commands/ruvector/migrate.js +99 -99
- package/v3/@claude-flow/cli/dist/src/commands/ruvector/optimize.js +51 -51
- package/v3/@claude-flow/cli/dist/src/commands/ruvector/setup.js +624 -624
- package/v3/@claude-flow/cli/dist/src/commands/ruvector/status.js +38 -38
- package/v3/@claude-flow/cli/dist/src/config/proven-config.js +2 -2
- package/v3/@claude-flow/cli/dist/src/init/claudemd-generator.js +273 -273
- package/v3/@claude-flow/cli/dist/src/init/executor.js +453 -453
- package/v3/@claude-flow/cli/dist/src/init/helper-signing.js +2 -2
- package/v3/@claude-flow/cli/dist/src/init/helpers-generator.js +917 -917
- package/v3/@claude-flow/cli/dist/src/init/statusline-generator.js +24 -24
- package/v3/@claude-flow/cli/dist/src/mcp-tools/agentdb-tools.js +15 -15
- package/v3/@claude-flow/cli/dist/src/mcp-tools/browser-intent-tools.js +19 -19
- package/v3/@claude-flow/cli/dist/src/mcp-tools/memory-tools.js +6 -4
- package/v3/@claude-flow/cli/dist/src/mcp-tools/seraphina-tools.js +4 -4
- package/v3/@claude-flow/cli/dist/src/memory/graph-edge-writer.js +22 -22
- package/v3/@claude-flow/cli/dist/src/memory/memory-bridge.js +114 -114
- package/v3/@claude-flow/cli/dist/src/memory/memory-initializer.js +416 -416
- package/v3/@claude-flow/cli/dist/src/memory/rabitq-index.js +5 -5
- package/v3/@claude-flow/cli/dist/src/proxy/verify.js +2 -2
- package/v3/@claude-flow/cli/dist/src/runtime/headless.js +28 -28
- package/v3/@claude-flow/cli/dist/src/services/distill-tuning.js +7 -7
- package/v3/@claude-flow/cli/dist/src/services/headless-worker-executor.js +84 -84
- package/v3/@claude-flow/cli/dist/src/services/memory-distillation.js +18 -18
- package/v3/@claude-flow/cli/dist/src/transfer/deploy-seraphine.js +23 -23
- package/v3/@claude-flow/cli/package.json +181 -181
- package/v3/@claude-flow/guidance/README.md +1195 -1195
- package/v3/@claude-flow/guidance/package.json +198 -198
- package/v3/@claude-flow/shared/README.md +323 -323
- package/v3/@claude-flow/shared/dist/events/event-store.js +31 -31
- package/v3/@claude-flow/shared/dist/hooks/safety/git-commit.js +3 -3
- package/v3/@claude-flow/shared/package.json +43 -43
- package/v3/README.md +493 -493
- package/.claude/.proven-config-version +0 -1
- package/.claude/proven-config.json +0 -42
- package/v3/@claude-flow/cli/dist/src/ruvector/diskann-backend.d.ts +0 -78
- package/v3/@claude-flow/cli/dist/src/ruvector/diskann-backend.js +0 -310
|
@@ -1,304 +1,304 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
/**
|
|
3
|
-
* ruflo-hook.cjs — cross-platform Node.js port of ruflo-hook.sh (#2132)
|
|
4
|
-
*
|
|
5
|
-
* The bash shim (ruflo-hook.sh) works on Mac/Linux but fails on native
|
|
6
|
-
* Windows (exit 126 — "cannot execute binary file"). This .cjs shim
|
|
7
|
-
* provides identical behaviour via Node.js child_process so Windows users
|
|
8
|
-
* get working hooks without WSL or Git Bash.
|
|
9
|
-
*
|
|
10
|
-
* Mac/Linux continue to use ruflo-hook.sh via the plugin hooks.json files
|
|
11
|
-
* (unchanged). On Windows, ruflo init writes a .claude/settings.json that
|
|
12
|
-
* overrides those entries with node-based equivalents pointing here.
|
|
13
|
-
*
|
|
14
|
-
* Behaviour mirrors ruflo-hook.sh:
|
|
15
|
-
* 1. Reads hook JSON payload from stdin.
|
|
16
|
-
* 2. Prefers a locally installed `ruflo` or `claude-flow` binary.
|
|
17
|
-
* 3. Falls back to `npx --prefer-offline ruflo@latest`.
|
|
18
|
-
* 4. Always exits 0 — hook subcommands are best-effort telemetry.
|
|
19
|
-
* 5. Swallows all stderr — nothing should surface to Claude Code.
|
|
20
|
-
*
|
|
21
|
-
* Usage: node ruflo-hook.cjs <hook-subcommand> [args...]
|
|
22
|
-
* e.g. node ruflo-hook.cjs post-edit --file "x.ts" --train-patterns
|
|
23
|
-
*/
|
|
24
|
-
|
|
25
|
-
'use strict';
|
|
26
|
-
|
|
27
|
-
const { spawnSync } = require('child_process');
|
|
28
|
-
const fs = require('fs');
|
|
29
|
-
const path = require('path');
|
|
30
|
-
|
|
31
|
-
/** Exit 0 unconditionally — hooks must never block a turn */
|
|
32
|
-
function done() {
|
|
33
|
-
process.exit(0);
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
/** Resolve stdin to a JSON object, or null if not parseable */
|
|
37
|
-
function readStdinJson() {
|
|
38
|
-
try {
|
|
39
|
-
let buf = '';
|
|
40
|
-
// Read synchronously — hooks fire synchronously in Claude Code
|
|
41
|
-
const fd = fs.openSync('/dev/stdin', 'r');
|
|
42
|
-
const chunk = Buffer.alloc(64 * 1024);
|
|
43
|
-
let bytesRead;
|
|
44
|
-
while ((bytesRead = fs.readSync(fd, chunk, 0, chunk.length, null)) > 0) {
|
|
45
|
-
buf += chunk.slice(0, bytesRead).toString('utf8');
|
|
46
|
-
}
|
|
47
|
-
fs.closeSync(fd);
|
|
48
|
-
return buf.trim() ? JSON.parse(buf) : null;
|
|
49
|
-
} catch {
|
|
50
|
-
return null;
|
|
51
|
-
}
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
/** Read stdin via process.stdin in sync mode (Windows-safe alternative) */
|
|
55
|
-
function readStdinSync() {
|
|
56
|
-
try {
|
|
57
|
-
// On Windows /dev/stdin doesn't exist; use fd 0 directly
|
|
58
|
-
const chunk = Buffer.alloc(64 * 1024);
|
|
59
|
-
let buf = '';
|
|
60
|
-
let bytesRead;
|
|
61
|
-
while (true) {
|
|
62
|
-
try {
|
|
63
|
-
bytesRead = fs.readSync(0 /* STDIN_FILENO */, chunk, 0, chunk.length, null);
|
|
64
|
-
if (bytesRead === 0) break;
|
|
65
|
-
buf += chunk.slice(0, bytesRead).toString('utf8');
|
|
66
|
-
} catch {
|
|
67
|
-
break;
|
|
68
|
-
}
|
|
69
|
-
}
|
|
70
|
-
return buf.trim() ? JSON.parse(buf) : null;
|
|
71
|
-
} catch {
|
|
72
|
-
return null;
|
|
73
|
-
}
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
/** Case-insensitive env lookup — Windows env keys are not case-stable. */
|
|
77
|
-
function envValue(env, name) {
|
|
78
|
-
const key = Object.keys(env).find((c) => c.toLowerCase() === name.toLowerCase());
|
|
79
|
-
return key ? env[key] : undefined;
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
/**
|
|
83
|
-
* Locate a command on PATH using fs only.
|
|
84
|
-
*
|
|
85
|
-
* Deliberately NOT `execSync('where ...')` / `command -v`: that spawns a
|
|
86
|
-
* shell on every hook invocation, which is both the thing this file is
|
|
87
|
-
* trying to get away from and a per-turn cost. Taking `env` and `platform`
|
|
88
|
-
* as arguments is what lets the Windows branch be exercised from a
|
|
89
|
-
* Linux/macOS CI run — see the Windows argv tests.
|
|
90
|
-
*/
|
|
91
|
-
function resolveCommandPath(command, env = process.env, platform = process.platform) {
|
|
92
|
-
const hasSeparator = command.includes('/') || command.includes('\\');
|
|
93
|
-
const dirs = hasSeparator
|
|
94
|
-
? ['']
|
|
95
|
-
: (envValue(env, 'PATH') || '').split(platform === 'win32' ? ';' : path.delimiter);
|
|
96
|
-
const hasExtension = path.extname(command) !== '';
|
|
97
|
-
const extensions = platform === 'win32' && !(hasSeparator && hasExtension)
|
|
98
|
-
? (envValue(env, 'PATHEXT') || '.COM;.EXE;.BAT;.CMD').split(';')
|
|
99
|
-
: [''];
|
|
100
|
-
for (const dir of dirs) {
|
|
101
|
-
for (const ext of extensions) {
|
|
102
|
-
const base = path.resolve(dir || '.', command);
|
|
103
|
-
const candidates = ext
|
|
104
|
-
? [base + ext.toLowerCase(), base + ext.toUpperCase()]
|
|
105
|
-
: [base];
|
|
106
|
-
for (const file of candidates) {
|
|
107
|
-
try {
|
|
108
|
-
fs.accessSync(file, platform === 'win32' ? fs.constants.F_OK : fs.constants.X_OK);
|
|
109
|
-
if (fs.statSync(file).isFile()) return file;
|
|
110
|
-
} catch { /* keep searching */ }
|
|
111
|
-
}
|
|
112
|
-
}
|
|
113
|
-
}
|
|
114
|
-
return null;
|
|
115
|
-
}
|
|
116
|
-
|
|
117
|
-
/**
|
|
118
|
-
* Map an npm-generated Windows shim (ruflo.cmd / npx.cmd / …) to the .js
|
|
119
|
-
* entrypoint it would have run, so it can be executed as `node <entry>`
|
|
120
|
-
* with no shell.
|
|
121
|
-
*
|
|
122
|
-
* Handles both npm layouts: a global prefix (`<prefix>/ruflo.cmd` beside
|
|
123
|
-
* `<prefix>/node_modules/ruflo`) and a local one (`node_modules/.bin/ruflo.cmd`
|
|
124
|
-
* beside `node_modules/ruflo`). `npx` lives in the `npm` package, hence the
|
|
125
|
-
* command→package mapping rather than assuming they match.
|
|
126
|
-
*
|
|
127
|
-
* The entrypoint comes from the package's own `bin` field, never a guessed
|
|
128
|
-
* filename, and is required to resolve inside the package directory — a
|
|
129
|
-
* manifest pointing outside it is refused rather than followed.
|
|
130
|
-
*/
|
|
131
|
-
function resolveNpmShim(shimPath) {
|
|
132
|
-
const command = path.basename(shimPath, path.extname(shimPath)).toLowerCase();
|
|
133
|
-
const packageName = command === 'npx' ? 'npm' : command;
|
|
134
|
-
if (!['ruflo', 'claude-flow', 'npm'].includes(packageName)) return null;
|
|
135
|
-
try {
|
|
136
|
-
const shimDir = path.dirname(shimPath);
|
|
137
|
-
const packageDir = path.basename(shimDir).toLowerCase() === '.bin'
|
|
138
|
-
? path.resolve(shimDir, '..', packageName)
|
|
139
|
-
: path.resolve(shimDir, 'node_modules', packageName);
|
|
140
|
-
const manifest = JSON.parse(fs.readFileSync(path.join(packageDir, 'package.json'), 'utf8'));
|
|
141
|
-
const declared = typeof manifest.bin === 'string' ? manifest.bin : manifest.bin?.[command];
|
|
142
|
-
if (typeof declared !== 'string') return null;
|
|
143
|
-
const canonicalPackageDir = fs.realpathSync(packageDir);
|
|
144
|
-
const canonicalEntry = fs.realpathSync(path.resolve(packageDir, declared));
|
|
145
|
-
const relativeEntry = path.relative(canonicalPackageDir, canonicalEntry);
|
|
146
|
-
if (relativeEntry.startsWith('..' + path.sep) || path.isAbsolute(relativeEntry)) return null;
|
|
147
|
-
if (!fs.statSync(canonicalEntry).isFile()) return null;
|
|
148
|
-
return { command: process.execPath, args: [canonicalEntry] };
|
|
149
|
-
} catch { return null; }
|
|
150
|
-
}
|
|
151
|
-
|
|
152
|
-
/**
|
|
153
|
-
* Decide how to run `bin` without a shell. Returns {command, args}, or null
|
|
154
|
-
* when no shell-free invocation could be identified (Windows shim that is
|
|
155
|
-
* not an npm package entry) — the caller then falls back to the escaped
|
|
156
|
-
* cmd.exe path rather than dropping the hook.
|
|
157
|
-
*/
|
|
158
|
-
function resolveInvocation(bin, binArgs, options = {}) {
|
|
159
|
-
const env = options.env || process.env;
|
|
160
|
-
const platform = options.platform || process.platform;
|
|
161
|
-
const commandPath = resolveCommandPath(bin, env, platform);
|
|
162
|
-
if (!commandPath) return null;
|
|
163
|
-
if (platform === 'win32' && /\.(?:cmd|bat|ps1)$/i.test(commandPath)) {
|
|
164
|
-
const npmBin = resolveNpmShim(commandPath);
|
|
165
|
-
return npmBin ? { command: npmBin.command, args: [...npmBin.args, ...binArgs] } : null;
|
|
166
|
-
}
|
|
167
|
-
return { command: commandPath, args: binArgs };
|
|
168
|
-
}
|
|
169
|
-
|
|
170
|
-
/**
|
|
171
|
-
* Escape one argv element so it survives BOTH parsers a Windows shell:true
|
|
172
|
-
* spawn puts it through before the target CLI ever sees it:
|
|
173
|
-
* 1. cmd.exe's own line tokenizer, which still scans for & | < > ^ % ! " ( )
|
|
174
|
-
* even inside a per-argument quoted segment — quoting alone does not
|
|
175
|
-
* shield cmd.exe metacharacters, and this runs a SECOND time when the
|
|
176
|
-
* resolved binary is itself a .cmd shim (npm's `ruflo`/`claude-flow`/
|
|
177
|
-
* `npx` global installs on Windows), because launching a .cmd file is
|
|
178
|
-
* cmd.exe re-invoking itself on the command line.
|
|
179
|
-
* 2. The eventual CommandLineToArgvW argv parse in the target process,
|
|
180
|
-
* which needs backslash-before-quote sequences doubled and the value
|
|
181
|
-
* quoted so it lands as ONE argument.
|
|
182
|
-
* Without this, a hook-derived value (e.g. a Bash tool's `command`, or a
|
|
183
|
-
* file path) containing a shell metacharacter can be reinterpreted as a
|
|
184
|
-
* separate command / redirection instead of reaching the CLI as literal
|
|
185
|
-
* data — this is the class of bug in CVE-2024-27980 (Node's own .bat/.cmd
|
|
186
|
-
* argument-injection advisory). Algorithm: https://qntm.org/cmd, the same
|
|
187
|
-
* reference the `cross-spawn` package's Windows escaping is built from.
|
|
188
|
-
*
|
|
189
|
-
* Byte-identical to plugins/ruflo-core/scripts/ruflo-hook.cjs so the four
|
|
190
|
-
* copies can be diffed against each other. This is the fallback, not the
|
|
191
|
-
* primary defence: resolveInvocation() above is preferred because it removes
|
|
192
|
-
* cmd.exe from the chain entirely rather than out-guessing its tokenizer.
|
|
193
|
-
*/
|
|
194
|
-
function escapeCmdArg(arg) {
|
|
195
|
-
let s = String(arg);
|
|
196
|
-
s = s.replace(/(\\*)"/g, '$1$1\\"').replace(/(\\*)$/, '$1$1');
|
|
197
|
-
s = `"${s}"`;
|
|
198
|
-
return s.replace(/[()%!^"<>&|;,]/g, '^$&');
|
|
199
|
-
}
|
|
200
|
-
|
|
201
|
-
/** Build the argv for the ruflo/claude-flow/npx invocation */
|
|
202
|
-
function buildArgs(subcommand, extraArgs) {
|
|
203
|
-
// The `hooks` word is prepended here, matching ruflo-hook.sh convention.
|
|
204
|
-
return ['hooks', subcommand, ...extraArgs];
|
|
205
|
-
}
|
|
206
|
-
|
|
207
|
-
/**
|
|
208
|
-
* Spawn the CLI with the hook subcommand.
|
|
209
|
-
* Passes the raw stdin payload as the child's stdin so the CLI can read
|
|
210
|
-
* the hook event JSON if needed (same as the bash pipe).
|
|
211
|
-
*
|
|
212
|
-
* Returns true on success (exit 0), false otherwise.
|
|
213
|
-
*/
|
|
214
|
-
function invokeHook(bin, binArgs, hookArgs, stdinData, options = {}) {
|
|
215
|
-
const env = options.env || process.env;
|
|
216
|
-
const platform = options.platform || process.platform;
|
|
217
|
-
const spawnOpts = {
|
|
218
|
-
input: stdinData || '',
|
|
219
|
-
encoding: 'utf8',
|
|
220
|
-
stdio: ['pipe', 'ignore', 'ignore'],
|
|
221
|
-
timeout: 30_000,
|
|
222
|
-
env,
|
|
223
|
-
};
|
|
224
|
-
|
|
225
|
-
// Layer 1: no shell. CreateProcess/execve receives the argv array
|
|
226
|
-
// verbatim, so nothing in it can be reinterpreted as syntax.
|
|
227
|
-
const invocation = resolveInvocation(bin, binArgs, { env, platform });
|
|
228
|
-
if (invocation) {
|
|
229
|
-
const result = spawnSync(invocation.command, [...invocation.args, ...hookArgs], {
|
|
230
|
-
...spawnOpts,
|
|
231
|
-
shell: false,
|
|
232
|
-
});
|
|
233
|
-
return result.status === 0;
|
|
234
|
-
}
|
|
235
|
-
|
|
236
|
-
// Layer 2: Windows shim we could not map to an entrypoint. cmd.exe is
|
|
237
|
-
// unavoidable here (CreateProcess cannot launch a .cmd, and Node has
|
|
238
|
-
// refused to since CVE-2024-27980), so every element is escaped. Losing
|
|
239
|
-
// the hook entirely would be the wrong trade — telemetry is best-effort,
|
|
240
|
-
// but silently doing nothing hides breakage.
|
|
241
|
-
const useShell = platform === 'win32';
|
|
242
|
-
const args = [...binArgs, ...hookArgs];
|
|
243
|
-
const result = spawnSync(
|
|
244
|
-
useShell ? escapeCmdArg(bin) : bin,
|
|
245
|
-
useShell ? args.map(escapeCmdArg) : args,
|
|
246
|
-
{ ...spawnOpts, shell: useShell },
|
|
247
|
-
);
|
|
248
|
-
return result.status === 0;
|
|
249
|
-
}
|
|
250
|
-
|
|
251
|
-
function main() {
|
|
252
|
-
const args = process.argv.slice(2);
|
|
253
|
-
if (args.length === 0) {
|
|
254
|
-
// No subcommand — no-op, same as bash version
|
|
255
|
-
done();
|
|
256
|
-
}
|
|
257
|
-
|
|
258
|
-
const [subcommand, ...rest] = args;
|
|
259
|
-
|
|
260
|
-
// Read stdin (the hook event payload) — best effort
|
|
261
|
-
let stdinData = '';
|
|
262
|
-
try {
|
|
263
|
-
stdinData = fs.readFileSync(0 /* fd 0 = stdin */, 'utf8');
|
|
264
|
-
} catch {
|
|
265
|
-
// stdin may not be available when invoked directly for testing
|
|
266
|
-
stdinData = '';
|
|
267
|
-
}
|
|
268
|
-
|
|
269
|
-
const hookArgs = buildArgs(subcommand, rest);
|
|
270
|
-
|
|
271
|
-
// Priority 1: locally installed ruflo binary
|
|
272
|
-
if (resolveCommandPath('ruflo')) {
|
|
273
|
-
invokeHook('ruflo', [], hookArgs, stdinData);
|
|
274
|
-
done();
|
|
275
|
-
}
|
|
276
|
-
|
|
277
|
-
// Priority 2: locally installed claude-flow binary
|
|
278
|
-
if (resolveCommandPath('claude-flow')) {
|
|
279
|
-
invokeHook('claude-flow', [], hookArgs, stdinData);
|
|
280
|
-
done();
|
|
281
|
-
}
|
|
282
|
-
|
|
283
|
-
// Priority 3: npx --prefer-offline fallback (avoids cold registry resolve).
|
|
284
|
-
//
|
|
285
|
-
// SKIP this when RUFLO_HOOK_SKIP_NPX=1 — used by CI smokes that test
|
|
286
|
-
// the shim's *control flow* without exercising npm install network paths.
|
|
287
|
-
// Without the skip, npx can take 30+s on a cold runner (no warm cache,
|
|
288
|
-
// no offline tarball), exceeding the smoke's 15s timeout and producing
|
|
289
|
-
// a spurious failure even though the shim itself works correctly.
|
|
290
|
-
// The bash version doesn't hit this because it backgrounded the work.
|
|
291
|
-
if (process.env.RUFLO_HOOK_SKIP_NPX !== '1') {
|
|
292
|
-
invokeHook('npx', ['--prefer-offline', '--yes', 'ruflo@latest'], hookArgs, stdinData);
|
|
293
|
-
}
|
|
294
|
-
|
|
295
|
-
done();
|
|
296
|
-
}
|
|
297
|
-
|
|
298
|
-
// Test seam: the Windows argv suite require()s this file to drive resolveInvocation()
|
|
299
|
-
// and invokeHook() with a simulated { platform: 'win32', env } — which is how
|
|
300
|
-
// the Windows branch is proved from a Linux/macOS CI run. hooks.json always
|
|
301
|
-
// invokes this file directly, so main() runs unconditionally otherwise.
|
|
302
|
-
if (!globalThis.__RUFLO_HOOK_IMPORT_ONLY__) main();
|
|
303
|
-
|
|
304
|
-
module.exports = { invokeHook, resolveCommandPath, resolveInvocation, resolveNpmShim, escapeCmdArg };
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* ruflo-hook.cjs — cross-platform Node.js port of ruflo-hook.sh (#2132)
|
|
4
|
+
*
|
|
5
|
+
* The bash shim (ruflo-hook.sh) works on Mac/Linux but fails on native
|
|
6
|
+
* Windows (exit 126 — "cannot execute binary file"). This .cjs shim
|
|
7
|
+
* provides identical behaviour via Node.js child_process so Windows users
|
|
8
|
+
* get working hooks without WSL or Git Bash.
|
|
9
|
+
*
|
|
10
|
+
* Mac/Linux continue to use ruflo-hook.sh via the plugin hooks.json files
|
|
11
|
+
* (unchanged). On Windows, ruflo init writes a .claude/settings.json that
|
|
12
|
+
* overrides those entries with node-based equivalents pointing here.
|
|
13
|
+
*
|
|
14
|
+
* Behaviour mirrors ruflo-hook.sh:
|
|
15
|
+
* 1. Reads hook JSON payload from stdin.
|
|
16
|
+
* 2. Prefers a locally installed `ruflo` or `claude-flow` binary.
|
|
17
|
+
* 3. Falls back to `npx --prefer-offline ruflo@latest`.
|
|
18
|
+
* 4. Always exits 0 — hook subcommands are best-effort telemetry.
|
|
19
|
+
* 5. Swallows all stderr — nothing should surface to Claude Code.
|
|
20
|
+
*
|
|
21
|
+
* Usage: node ruflo-hook.cjs <hook-subcommand> [args...]
|
|
22
|
+
* e.g. node ruflo-hook.cjs post-edit --file "x.ts" --train-patterns
|
|
23
|
+
*/
|
|
24
|
+
|
|
25
|
+
'use strict';
|
|
26
|
+
|
|
27
|
+
const { spawnSync } = require('child_process');
|
|
28
|
+
const fs = require('fs');
|
|
29
|
+
const path = require('path');
|
|
30
|
+
|
|
31
|
+
/** Exit 0 unconditionally — hooks must never block a turn */
|
|
32
|
+
function done() {
|
|
33
|
+
process.exit(0);
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
/** Resolve stdin to a JSON object, or null if not parseable */
|
|
37
|
+
function readStdinJson() {
|
|
38
|
+
try {
|
|
39
|
+
let buf = '';
|
|
40
|
+
// Read synchronously — hooks fire synchronously in Claude Code
|
|
41
|
+
const fd = fs.openSync('/dev/stdin', 'r');
|
|
42
|
+
const chunk = Buffer.alloc(64 * 1024);
|
|
43
|
+
let bytesRead;
|
|
44
|
+
while ((bytesRead = fs.readSync(fd, chunk, 0, chunk.length, null)) > 0) {
|
|
45
|
+
buf += chunk.slice(0, bytesRead).toString('utf8');
|
|
46
|
+
}
|
|
47
|
+
fs.closeSync(fd);
|
|
48
|
+
return buf.trim() ? JSON.parse(buf) : null;
|
|
49
|
+
} catch {
|
|
50
|
+
return null;
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
/** Read stdin via process.stdin in sync mode (Windows-safe alternative) */
|
|
55
|
+
function readStdinSync() {
|
|
56
|
+
try {
|
|
57
|
+
// On Windows /dev/stdin doesn't exist; use fd 0 directly
|
|
58
|
+
const chunk = Buffer.alloc(64 * 1024);
|
|
59
|
+
let buf = '';
|
|
60
|
+
let bytesRead;
|
|
61
|
+
while (true) {
|
|
62
|
+
try {
|
|
63
|
+
bytesRead = fs.readSync(0 /* STDIN_FILENO */, chunk, 0, chunk.length, null);
|
|
64
|
+
if (bytesRead === 0) break;
|
|
65
|
+
buf += chunk.slice(0, bytesRead).toString('utf8');
|
|
66
|
+
} catch {
|
|
67
|
+
break;
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
return buf.trim() ? JSON.parse(buf) : null;
|
|
71
|
+
} catch {
|
|
72
|
+
return null;
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
/** Case-insensitive env lookup — Windows env keys are not case-stable. */
|
|
77
|
+
function envValue(env, name) {
|
|
78
|
+
const key = Object.keys(env).find((c) => c.toLowerCase() === name.toLowerCase());
|
|
79
|
+
return key ? env[key] : undefined;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
/**
|
|
83
|
+
* Locate a command on PATH using fs only.
|
|
84
|
+
*
|
|
85
|
+
* Deliberately NOT `execSync('where ...')` / `command -v`: that spawns a
|
|
86
|
+
* shell on every hook invocation, which is both the thing this file is
|
|
87
|
+
* trying to get away from and a per-turn cost. Taking `env` and `platform`
|
|
88
|
+
* as arguments is what lets the Windows branch be exercised from a
|
|
89
|
+
* Linux/macOS CI run — see the Windows argv tests.
|
|
90
|
+
*/
|
|
91
|
+
function resolveCommandPath(command, env = process.env, platform = process.platform) {
|
|
92
|
+
const hasSeparator = command.includes('/') || command.includes('\\');
|
|
93
|
+
const dirs = hasSeparator
|
|
94
|
+
? ['']
|
|
95
|
+
: (envValue(env, 'PATH') || '').split(platform === 'win32' ? ';' : path.delimiter);
|
|
96
|
+
const hasExtension = path.extname(command) !== '';
|
|
97
|
+
const extensions = platform === 'win32' && !(hasSeparator && hasExtension)
|
|
98
|
+
? (envValue(env, 'PATHEXT') || '.COM;.EXE;.BAT;.CMD').split(';')
|
|
99
|
+
: [''];
|
|
100
|
+
for (const dir of dirs) {
|
|
101
|
+
for (const ext of extensions) {
|
|
102
|
+
const base = path.resolve(dir || '.', command);
|
|
103
|
+
const candidates = ext
|
|
104
|
+
? [base + ext.toLowerCase(), base + ext.toUpperCase()]
|
|
105
|
+
: [base];
|
|
106
|
+
for (const file of candidates) {
|
|
107
|
+
try {
|
|
108
|
+
fs.accessSync(file, platform === 'win32' ? fs.constants.F_OK : fs.constants.X_OK);
|
|
109
|
+
if (fs.statSync(file).isFile()) return file;
|
|
110
|
+
} catch { /* keep searching */ }
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
return null;
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
/**
|
|
118
|
+
* Map an npm-generated Windows shim (ruflo.cmd / npx.cmd / …) to the .js
|
|
119
|
+
* entrypoint it would have run, so it can be executed as `node <entry>`
|
|
120
|
+
* with no shell.
|
|
121
|
+
*
|
|
122
|
+
* Handles both npm layouts: a global prefix (`<prefix>/ruflo.cmd` beside
|
|
123
|
+
* `<prefix>/node_modules/ruflo`) and a local one (`node_modules/.bin/ruflo.cmd`
|
|
124
|
+
* beside `node_modules/ruflo`). `npx` lives in the `npm` package, hence the
|
|
125
|
+
* command→package mapping rather than assuming they match.
|
|
126
|
+
*
|
|
127
|
+
* The entrypoint comes from the package's own `bin` field, never a guessed
|
|
128
|
+
* filename, and is required to resolve inside the package directory — a
|
|
129
|
+
* manifest pointing outside it is refused rather than followed.
|
|
130
|
+
*/
|
|
131
|
+
function resolveNpmShim(shimPath) {
|
|
132
|
+
const command = path.basename(shimPath, path.extname(shimPath)).toLowerCase();
|
|
133
|
+
const packageName = command === 'npx' ? 'npm' : command;
|
|
134
|
+
if (!['ruflo', 'claude-flow', 'npm'].includes(packageName)) return null;
|
|
135
|
+
try {
|
|
136
|
+
const shimDir = path.dirname(shimPath);
|
|
137
|
+
const packageDir = path.basename(shimDir).toLowerCase() === '.bin'
|
|
138
|
+
? path.resolve(shimDir, '..', packageName)
|
|
139
|
+
: path.resolve(shimDir, 'node_modules', packageName);
|
|
140
|
+
const manifest = JSON.parse(fs.readFileSync(path.join(packageDir, 'package.json'), 'utf8'));
|
|
141
|
+
const declared = typeof manifest.bin === 'string' ? manifest.bin : manifest.bin?.[command];
|
|
142
|
+
if (typeof declared !== 'string') return null;
|
|
143
|
+
const canonicalPackageDir = fs.realpathSync(packageDir);
|
|
144
|
+
const canonicalEntry = fs.realpathSync(path.resolve(packageDir, declared));
|
|
145
|
+
const relativeEntry = path.relative(canonicalPackageDir, canonicalEntry);
|
|
146
|
+
if (relativeEntry.startsWith('..' + path.sep) || path.isAbsolute(relativeEntry)) return null;
|
|
147
|
+
if (!fs.statSync(canonicalEntry).isFile()) return null;
|
|
148
|
+
return { command: process.execPath, args: [canonicalEntry] };
|
|
149
|
+
} catch { return null; }
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
/**
|
|
153
|
+
* Decide how to run `bin` without a shell. Returns {command, args}, or null
|
|
154
|
+
* when no shell-free invocation could be identified (Windows shim that is
|
|
155
|
+
* not an npm package entry) — the caller then falls back to the escaped
|
|
156
|
+
* cmd.exe path rather than dropping the hook.
|
|
157
|
+
*/
|
|
158
|
+
function resolveInvocation(bin, binArgs, options = {}) {
|
|
159
|
+
const env = options.env || process.env;
|
|
160
|
+
const platform = options.platform || process.platform;
|
|
161
|
+
const commandPath = resolveCommandPath(bin, env, platform);
|
|
162
|
+
if (!commandPath) return null;
|
|
163
|
+
if (platform === 'win32' && /\.(?:cmd|bat|ps1)$/i.test(commandPath)) {
|
|
164
|
+
const npmBin = resolveNpmShim(commandPath);
|
|
165
|
+
return npmBin ? { command: npmBin.command, args: [...npmBin.args, ...binArgs] } : null;
|
|
166
|
+
}
|
|
167
|
+
return { command: commandPath, args: binArgs };
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
/**
|
|
171
|
+
* Escape one argv element so it survives BOTH parsers a Windows shell:true
|
|
172
|
+
* spawn puts it through before the target CLI ever sees it:
|
|
173
|
+
* 1. cmd.exe's own line tokenizer, which still scans for & | < > ^ % ! " ( )
|
|
174
|
+
* even inside a per-argument quoted segment — quoting alone does not
|
|
175
|
+
* shield cmd.exe metacharacters, and this runs a SECOND time when the
|
|
176
|
+
* resolved binary is itself a .cmd shim (npm's `ruflo`/`claude-flow`/
|
|
177
|
+
* `npx` global installs on Windows), because launching a .cmd file is
|
|
178
|
+
* cmd.exe re-invoking itself on the command line.
|
|
179
|
+
* 2. The eventual CommandLineToArgvW argv parse in the target process,
|
|
180
|
+
* which needs backslash-before-quote sequences doubled and the value
|
|
181
|
+
* quoted so it lands as ONE argument.
|
|
182
|
+
* Without this, a hook-derived value (e.g. a Bash tool's `command`, or a
|
|
183
|
+
* file path) containing a shell metacharacter can be reinterpreted as a
|
|
184
|
+
* separate command / redirection instead of reaching the CLI as literal
|
|
185
|
+
* data — this is the class of bug in CVE-2024-27980 (Node's own .bat/.cmd
|
|
186
|
+
* argument-injection advisory). Algorithm: https://qntm.org/cmd, the same
|
|
187
|
+
* reference the `cross-spawn` package's Windows escaping is built from.
|
|
188
|
+
*
|
|
189
|
+
* Byte-identical to plugins/ruflo-core/scripts/ruflo-hook.cjs so the four
|
|
190
|
+
* copies can be diffed against each other. This is the fallback, not the
|
|
191
|
+
* primary defence: resolveInvocation() above is preferred because it removes
|
|
192
|
+
* cmd.exe from the chain entirely rather than out-guessing its tokenizer.
|
|
193
|
+
*/
|
|
194
|
+
function escapeCmdArg(arg) {
|
|
195
|
+
let s = String(arg);
|
|
196
|
+
s = s.replace(/(\\*)"/g, '$1$1\\"').replace(/(\\*)$/, '$1$1');
|
|
197
|
+
s = `"${s}"`;
|
|
198
|
+
return s.replace(/[()%!^"<>&|;,]/g, '^$&');
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
/** Build the argv for the ruflo/claude-flow/npx invocation */
|
|
202
|
+
function buildArgs(subcommand, extraArgs) {
|
|
203
|
+
// The `hooks` word is prepended here, matching ruflo-hook.sh convention.
|
|
204
|
+
return ['hooks', subcommand, ...extraArgs];
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
/**
|
|
208
|
+
* Spawn the CLI with the hook subcommand.
|
|
209
|
+
* Passes the raw stdin payload as the child's stdin so the CLI can read
|
|
210
|
+
* the hook event JSON if needed (same as the bash pipe).
|
|
211
|
+
*
|
|
212
|
+
* Returns true on success (exit 0), false otherwise.
|
|
213
|
+
*/
|
|
214
|
+
function invokeHook(bin, binArgs, hookArgs, stdinData, options = {}) {
|
|
215
|
+
const env = options.env || process.env;
|
|
216
|
+
const platform = options.platform || process.platform;
|
|
217
|
+
const spawnOpts = {
|
|
218
|
+
input: stdinData || '',
|
|
219
|
+
encoding: 'utf8',
|
|
220
|
+
stdio: ['pipe', 'ignore', 'ignore'],
|
|
221
|
+
timeout: 30_000,
|
|
222
|
+
env,
|
|
223
|
+
};
|
|
224
|
+
|
|
225
|
+
// Layer 1: no shell. CreateProcess/execve receives the argv array
|
|
226
|
+
// verbatim, so nothing in it can be reinterpreted as syntax.
|
|
227
|
+
const invocation = resolveInvocation(bin, binArgs, { env, platform });
|
|
228
|
+
if (invocation) {
|
|
229
|
+
const result = spawnSync(invocation.command, [...invocation.args, ...hookArgs], {
|
|
230
|
+
...spawnOpts,
|
|
231
|
+
shell: false,
|
|
232
|
+
});
|
|
233
|
+
return result.status === 0;
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
// Layer 2: Windows shim we could not map to an entrypoint. cmd.exe is
|
|
237
|
+
// unavoidable here (CreateProcess cannot launch a .cmd, and Node has
|
|
238
|
+
// refused to since CVE-2024-27980), so every element is escaped. Losing
|
|
239
|
+
// the hook entirely would be the wrong trade — telemetry is best-effort,
|
|
240
|
+
// but silently doing nothing hides breakage.
|
|
241
|
+
const useShell = platform === 'win32';
|
|
242
|
+
const args = [...binArgs, ...hookArgs];
|
|
243
|
+
const result = spawnSync(
|
|
244
|
+
useShell ? escapeCmdArg(bin) : bin,
|
|
245
|
+
useShell ? args.map(escapeCmdArg) : args,
|
|
246
|
+
{ ...spawnOpts, shell: useShell },
|
|
247
|
+
);
|
|
248
|
+
return result.status === 0;
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
function main() {
|
|
252
|
+
const args = process.argv.slice(2);
|
|
253
|
+
if (args.length === 0) {
|
|
254
|
+
// No subcommand — no-op, same as bash version
|
|
255
|
+
done();
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
const [subcommand, ...rest] = args;
|
|
259
|
+
|
|
260
|
+
// Read stdin (the hook event payload) — best effort
|
|
261
|
+
let stdinData = '';
|
|
262
|
+
try {
|
|
263
|
+
stdinData = fs.readFileSync(0 /* fd 0 = stdin */, 'utf8');
|
|
264
|
+
} catch {
|
|
265
|
+
// stdin may not be available when invoked directly for testing
|
|
266
|
+
stdinData = '';
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
const hookArgs = buildArgs(subcommand, rest);
|
|
270
|
+
|
|
271
|
+
// Priority 1: locally installed ruflo binary
|
|
272
|
+
if (resolveCommandPath('ruflo')) {
|
|
273
|
+
invokeHook('ruflo', [], hookArgs, stdinData);
|
|
274
|
+
done();
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
// Priority 2: locally installed claude-flow binary
|
|
278
|
+
if (resolveCommandPath('claude-flow')) {
|
|
279
|
+
invokeHook('claude-flow', [], hookArgs, stdinData);
|
|
280
|
+
done();
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
// Priority 3: npx --prefer-offline fallback (avoids cold registry resolve).
|
|
284
|
+
//
|
|
285
|
+
// SKIP this when RUFLO_HOOK_SKIP_NPX=1 — used by CI smokes that test
|
|
286
|
+
// the shim's *control flow* without exercising npm install network paths.
|
|
287
|
+
// Without the skip, npx can take 30+s on a cold runner (no warm cache,
|
|
288
|
+
// no offline tarball), exceeding the smoke's 15s timeout and producing
|
|
289
|
+
// a spurious failure even though the shim itself works correctly.
|
|
290
|
+
// The bash version doesn't hit this because it backgrounded the work.
|
|
291
|
+
if (process.env.RUFLO_HOOK_SKIP_NPX !== '1') {
|
|
292
|
+
invokeHook('npx', ['--prefer-offline', '--yes', 'ruflo@latest'], hookArgs, stdinData);
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
done();
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
// Test seam: the Windows argv suite require()s this file to drive resolveInvocation()
|
|
299
|
+
// and invokeHook() with a simulated { platform: 'win32', env } — which is how
|
|
300
|
+
// the Windows branch is proved from a Linux/macOS CI run. hooks.json always
|
|
301
|
+
// invokes this file directly, so main() runs unconditionally otherwise.
|
|
302
|
+
if (!globalThis.__RUFLO_HOOK_IMPORT_ONLY__) main();
|
|
303
|
+
|
|
304
|
+
module.exports = { invokeHook, resolveCommandPath, resolveInvocation, resolveNpmShim, escapeCmdArg };
|