claude-flow 3.59.10 → 3.59.12
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/proven-config.json +1 -1
- package/.claude/skills/pair-programming/SKILL.md +72 -61
- package/package.json +1 -1
- package/v3/@claude-flow/cli/catalog-manifest.json +2 -2
- package/v3/@claude-flow/cli/dist/src/commands/appliance-advanced.js +5 -5
- package/v3/@claude-flow/cli/dist/src/commands/appliance.js +6 -3
- package/v3/@claude-flow/cli/dist/src/commands/index.d.ts +1 -0
- package/v3/@claude-flow/cli/dist/src/commands/index.js +7 -3
- package/v3/@claude-flow/cli/dist/src/commands/pair.d.ts +46 -0
- package/v3/@claude-flow/cli/dist/src/commands/pair.js +303 -0
- package/v3/@claude-flow/cli/package.json +1 -1
|
@@ -19,10 +19,21 @@ This skill provides professional pair programming capabilities with AI assistanc
|
|
|
19
19
|
- **Code Review**: Security scanning, performance analysis, best practice enforcement
|
|
20
20
|
- **Session Persistence**: Auto-save, recovery, export, and sharing
|
|
21
21
|
|
|
22
|
+
## How Claude Code Uses This
|
|
23
|
+
|
|
24
|
+
The CLI holds the session state; Claude Code reads it. There is no REPL to type into.
|
|
25
|
+
|
|
26
|
+
1. At the start of every turn run `ruflo pair status --json`. If `active` is `false`, this skill is dormant.
|
|
27
|
+
2. Follow `mode` and `aiRole`. As **driver** you write the code and the human reviews. As **navigator** you review and suggest and never edit unless asked. `tdd`, `review`, `mentor` and `debug` refine that behaviour as described below.
|
|
28
|
+
3. When `switchDue` is `true`, run `ruflo pair switch`, announce the swap, and continue in the new role.
|
|
29
|
+
4. Change mode mid-session with `ruflo pair mode <mode>`. The human can run the same commands from their shell.
|
|
30
|
+
|
|
31
|
+
State lives in `.claude-flow/sessions/pair/current.json`. `ruflo pair end` archives it to `history.jsonl` next to it.
|
|
32
|
+
|
|
22
33
|
## Prerequisites
|
|
23
34
|
|
|
24
35
|
**Required:**
|
|
25
|
-
-
|
|
36
|
+
- Ruflo CLI installed (`npm install -g ruflo`), which provides the `ruflo pair` command
|
|
26
37
|
- Git repository (optional but recommended)
|
|
27
38
|
|
|
28
39
|
**Recommended:**
|
|
@@ -35,13 +46,13 @@ This skill provides professional pair programming capabilities with AI assistanc
|
|
|
35
46
|
### Basic Session
|
|
36
47
|
```bash
|
|
37
48
|
# Start simple pair programming
|
|
38
|
-
|
|
49
|
+
ruflo pair start
|
|
39
50
|
```
|
|
40
51
|
|
|
41
52
|
### TDD Session
|
|
42
53
|
```bash
|
|
43
54
|
# Test-driven development
|
|
44
|
-
|
|
55
|
+
ruflo pair start \
|
|
45
56
|
--mode tdd \
|
|
46
57
|
--test-first \
|
|
47
58
|
--coverage 90
|
|
@@ -56,23 +67,23 @@ claude-flow pair --start \
|
|
|
56
67
|
#### Starting Sessions
|
|
57
68
|
```bash
|
|
58
69
|
# Basic start
|
|
59
|
-
|
|
70
|
+
ruflo pair start
|
|
60
71
|
|
|
61
72
|
# Expert refactoring session
|
|
62
|
-
|
|
73
|
+
ruflo pair start \
|
|
63
74
|
--agent senior-dev \
|
|
64
75
|
--focus refactor \
|
|
65
76
|
--verify \
|
|
66
77
|
--threshold 0.98
|
|
67
78
|
|
|
68
79
|
# Debugging session
|
|
69
|
-
|
|
80
|
+
ruflo pair start \
|
|
70
81
|
--agent debugger-expert \
|
|
71
82
|
--focus debug \
|
|
72
83
|
--review
|
|
73
84
|
|
|
74
85
|
# Learning session
|
|
75
|
-
|
|
86
|
+
ruflo pair start \
|
|
76
87
|
--mode mentor \
|
|
77
88
|
--pace slow \
|
|
78
89
|
--examples
|
|
@@ -81,10 +92,10 @@ claude-flow pair --start \
|
|
|
81
92
|
#### Session Management
|
|
82
93
|
```bash
|
|
83
94
|
# Check status
|
|
84
|
-
|
|
95
|
+
ruflo pair status
|
|
85
96
|
|
|
86
97
|
# View history
|
|
87
|
-
|
|
98
|
+
ruflo pair history
|
|
88
99
|
|
|
89
100
|
# Pause session
|
|
90
101
|
/pause [--reason <reason>]
|
|
@@ -93,7 +104,7 @@ claude-flow pair --history
|
|
|
93
104
|
/resume
|
|
94
105
|
|
|
95
106
|
# End session
|
|
96
|
-
|
|
107
|
+
ruflo pair end [--save] [--report]
|
|
97
108
|
```
|
|
98
109
|
|
|
99
110
|
### Available Modes
|
|
@@ -102,7 +113,7 @@ claude-flow pair --end [--save] [--report]
|
|
|
102
113
|
You write code while AI provides guidance.
|
|
103
114
|
|
|
104
115
|
```bash
|
|
105
|
-
|
|
116
|
+
ruflo pair start --mode driver
|
|
106
117
|
```
|
|
107
118
|
|
|
108
119
|
**Your Responsibilities:**
|
|
@@ -137,7 +148,7 @@ claude-flow pair --start --mode driver
|
|
|
137
148
|
AI writes code while you provide direction.
|
|
138
149
|
|
|
139
150
|
```bash
|
|
140
|
-
|
|
151
|
+
ruflo pair start --mode navigator
|
|
141
152
|
```
|
|
142
153
|
|
|
143
154
|
**Your Responsibilities:**
|
|
@@ -173,13 +184,13 @@ Automatically alternates roles at intervals.
|
|
|
173
184
|
|
|
174
185
|
```bash
|
|
175
186
|
# Default 10-minute intervals
|
|
176
|
-
|
|
187
|
+
ruflo pair start --mode switch
|
|
177
188
|
|
|
178
189
|
# 5-minute intervals (rapid)
|
|
179
|
-
|
|
190
|
+
ruflo pair start --mode switch --interval 5m
|
|
180
191
|
|
|
181
192
|
# 15-minute intervals (deep focus)
|
|
182
|
-
|
|
193
|
+
ruflo pair start --mode switch --interval 15m
|
|
183
194
|
```
|
|
184
195
|
|
|
185
196
|
**Handoff Process:**
|
|
@@ -199,7 +210,7 @@ claude-flow pair --start --mode switch --interval 15m
|
|
|
199
210
|
|
|
200
211
|
**TDD Mode** - Test-Driven Development:
|
|
201
212
|
```bash
|
|
202
|
-
|
|
213
|
+
ruflo pair start \
|
|
203
214
|
--mode tdd \
|
|
204
215
|
--test-first \
|
|
205
216
|
--coverage 100
|
|
@@ -208,7 +219,7 @@ Workflow: Write failing test → Implement → Refactor → Repeat
|
|
|
208
219
|
|
|
209
220
|
**Review Mode** - Continuous code review:
|
|
210
221
|
```bash
|
|
211
|
-
|
|
222
|
+
ruflo pair start \
|
|
212
223
|
--mode review \
|
|
213
224
|
--strict \
|
|
214
225
|
--security
|
|
@@ -217,7 +228,7 @@ Features: Real-time feedback, security scanning, performance analysis
|
|
|
217
228
|
|
|
218
229
|
**Mentor Mode** - Learning-focused:
|
|
219
230
|
```bash
|
|
220
|
-
|
|
231
|
+
ruflo pair start \
|
|
221
232
|
--mode mentor \
|
|
222
233
|
--explain-all \
|
|
223
234
|
--pace slow
|
|
@@ -226,7 +237,7 @@ Features: Detailed explanations, step-by-step guidance, pattern teaching
|
|
|
226
237
|
|
|
227
238
|
**Debug Mode** - Problem-solving:
|
|
228
239
|
```bash
|
|
229
|
-
|
|
240
|
+
ruflo pair start \
|
|
230
241
|
--mode debug \
|
|
231
242
|
--verbose \
|
|
232
243
|
--trace
|
|
@@ -559,19 +570,19 @@ Create `.claude-flow/pair-config.json`:
|
|
|
559
570
|
#### CLI Configuration
|
|
560
571
|
```bash
|
|
561
572
|
# Set configuration
|
|
562
|
-
|
|
563
|
-
|
|
573
|
+
ruflo pair config set defaultMode switch
|
|
574
|
+
ruflo pair config set verification.threshold 0.98
|
|
564
575
|
|
|
565
576
|
# Get configuration
|
|
566
|
-
|
|
567
|
-
|
|
577
|
+
ruflo pair config get
|
|
578
|
+
ruflo pair config get defaultMode
|
|
568
579
|
|
|
569
580
|
# Export/Import
|
|
570
|
-
|
|
571
|
-
|
|
581
|
+
ruflo pair config export > config.json
|
|
582
|
+
ruflo pair config import config.json
|
|
572
583
|
|
|
573
584
|
# Reset
|
|
574
|
-
|
|
585
|
+
ruflo pair config reset
|
|
575
586
|
```
|
|
576
587
|
|
|
577
588
|
#### Profile Management
|
|
@@ -580,17 +591,17 @@ Create reusable profiles:
|
|
|
580
591
|
|
|
581
592
|
```bash
|
|
582
593
|
# Create profile
|
|
583
|
-
|
|
594
|
+
ruflo pair profile create refactoring \
|
|
584
595
|
--mode driver \
|
|
585
596
|
--verify true \
|
|
586
597
|
--threshold 0.98 \
|
|
587
598
|
--focus refactor
|
|
588
599
|
|
|
589
600
|
# Use profile
|
|
590
|
-
|
|
601
|
+
ruflo pair start --profile refactoring
|
|
591
602
|
|
|
592
603
|
# List profiles
|
|
593
|
-
|
|
604
|
+
ruflo pair profile list
|
|
594
605
|
```
|
|
595
606
|
|
|
596
607
|
Profile configuration:
|
|
@@ -629,7 +640,7 @@ Implementing user authentication with JWT tokens:
|
|
|
629
640
|
|
|
630
641
|
```bash
|
|
631
642
|
# Session setup
|
|
632
|
-
|
|
643
|
+
ruflo pair start \
|
|
633
644
|
--mode switch \
|
|
634
645
|
--agent senior-dev \
|
|
635
646
|
--focus implement \
|
|
@@ -676,7 +687,7 @@ Debugging a memory leak in Node.js:
|
|
|
676
687
|
|
|
677
688
|
```bash
|
|
678
689
|
# Session setup
|
|
679
|
-
|
|
690
|
+
ruflo pair start \
|
|
680
691
|
--mode navigator \
|
|
681
692
|
--agent debugger-expert \
|
|
682
693
|
--focus debug \
|
|
@@ -717,7 +728,7 @@ Building shopping cart with test-driven development:
|
|
|
717
728
|
|
|
718
729
|
```bash
|
|
719
730
|
# Session setup
|
|
720
|
-
|
|
731
|
+
ruflo pair start \
|
|
721
732
|
--mode tdd \
|
|
722
733
|
--agent tdd-specialist \
|
|
723
734
|
--test-first
|
|
@@ -759,7 +770,7 @@ Modernizing legacy code:
|
|
|
759
770
|
|
|
760
771
|
```bash
|
|
761
772
|
# Session setup
|
|
762
|
-
|
|
773
|
+
ruflo pair start \
|
|
763
774
|
--mode driver \
|
|
764
775
|
--focus refactor \
|
|
765
776
|
--verify \
|
|
@@ -807,7 +818,7 @@ Optimizing slow React application:
|
|
|
807
818
|
|
|
808
819
|
```bash
|
|
809
820
|
# Session setup
|
|
810
|
-
|
|
821
|
+
ruflo pair start \
|
|
811
822
|
--mode switch \
|
|
812
823
|
--agent performance-expert \
|
|
813
824
|
--focus optimize \
|
|
@@ -852,7 +863,7 @@ Building RESTful API with Express:
|
|
|
852
863
|
|
|
853
864
|
```bash
|
|
854
865
|
# Session setup
|
|
855
|
-
|
|
866
|
+
ruflo pair start \
|
|
856
867
|
--mode navigator \
|
|
857
868
|
--agent backend-expert \
|
|
858
869
|
--focus implement \
|
|
@@ -897,28 +908,28 @@ claude-flow pair --start \
|
|
|
897
908
|
|
|
898
909
|
```bash
|
|
899
910
|
# Refactoring template
|
|
900
|
-
|
|
911
|
+
ruflo pair --template refactor
|
|
901
912
|
# Focus: Code improvement
|
|
902
913
|
# Verification: High (0.98)
|
|
903
914
|
# Testing: After each change
|
|
904
915
|
# Review: Continuous
|
|
905
916
|
|
|
906
917
|
# Feature template
|
|
907
|
-
|
|
918
|
+
ruflo pair --template feature
|
|
908
919
|
# Focus: Implementation
|
|
909
920
|
# Verification: Standard (0.95)
|
|
910
921
|
# Testing: On completion
|
|
911
922
|
# Review: Pre-commit
|
|
912
923
|
|
|
913
924
|
# Debug template
|
|
914
|
-
|
|
925
|
+
ruflo pair --template debug
|
|
915
926
|
# Focus: Problem solving
|
|
916
927
|
# Verification: Moderate (0.90)
|
|
917
928
|
# Testing: Regression tests
|
|
918
929
|
# Review: Root cause
|
|
919
930
|
|
|
920
931
|
# Learning template
|
|
921
|
-
|
|
932
|
+
ruflo pair --template learn
|
|
922
933
|
# Mode: Mentor
|
|
923
934
|
# Pace: Slow
|
|
924
935
|
# Explanations: Detailed
|
|
@@ -930,7 +941,7 @@ claude-flow pair --template learn
|
|
|
930
941
|
#### Session Status
|
|
931
942
|
|
|
932
943
|
```bash
|
|
933
|
-
|
|
944
|
+
ruflo pair status
|
|
934
945
|
```
|
|
935
946
|
|
|
936
947
|
**Output:**
|
|
@@ -962,7 +973,7 @@ Next Switch: in 3 minutes
|
|
|
962
973
|
#### Session History
|
|
963
974
|
|
|
964
975
|
```bash
|
|
965
|
-
|
|
976
|
+
ruflo pair history
|
|
966
977
|
```
|
|
967
978
|
|
|
968
979
|
**Output:**
|
|
@@ -993,32 +1004,32 @@ claude-flow pair --history
|
|
|
993
1004
|
|
|
994
1005
|
```bash
|
|
995
1006
|
# Save session
|
|
996
|
-
|
|
1007
|
+
ruflo pair --save [--name <name>]
|
|
997
1008
|
|
|
998
1009
|
# Load session
|
|
999
|
-
|
|
1010
|
+
ruflo pair --load <session-id>
|
|
1000
1011
|
|
|
1001
1012
|
# Export session
|
|
1002
|
-
|
|
1013
|
+
ruflo pair --export <session-id> [--format json|md]
|
|
1003
1014
|
|
|
1004
1015
|
# Generate report
|
|
1005
|
-
|
|
1016
|
+
ruflo pair --report <session-id>
|
|
1006
1017
|
```
|
|
1007
1018
|
|
|
1008
1019
|
#### Background Sessions
|
|
1009
1020
|
|
|
1010
1021
|
```bash
|
|
1011
1022
|
# Start in background
|
|
1012
|
-
|
|
1023
|
+
ruflo pair start --background
|
|
1013
1024
|
|
|
1014
1025
|
# Monitor background session
|
|
1015
|
-
|
|
1026
|
+
ruflo pair --monitor
|
|
1016
1027
|
|
|
1017
1028
|
# Attach to background session
|
|
1018
|
-
|
|
1029
|
+
ruflo pair --attach <session-id>
|
|
1019
1030
|
|
|
1020
1031
|
# End background session
|
|
1021
|
-
|
|
1032
|
+
ruflo pair end <session-id>
|
|
1022
1033
|
```
|
|
1023
1034
|
|
|
1024
1035
|
### Advanced Features
|
|
@@ -1054,30 +1065,30 @@ Use custom commands:
|
|
|
1054
1065
|
|
|
1055
1066
|
```bash
|
|
1056
1067
|
# Start with recording
|
|
1057
|
-
|
|
1068
|
+
ruflo pair start --record
|
|
1058
1069
|
|
|
1059
1070
|
# Replay session
|
|
1060
|
-
|
|
1071
|
+
ruflo pair --replay <session-id>
|
|
1061
1072
|
|
|
1062
1073
|
# Session analytics
|
|
1063
|
-
|
|
1074
|
+
ruflo pair --analytics <session-id>
|
|
1064
1075
|
```
|
|
1065
1076
|
|
|
1066
1077
|
#### Integration Options
|
|
1067
1078
|
|
|
1068
1079
|
**With Git:**
|
|
1069
1080
|
```bash
|
|
1070
|
-
|
|
1081
|
+
ruflo pair start --git --auto-commit
|
|
1071
1082
|
```
|
|
1072
1083
|
|
|
1073
1084
|
**With CI/CD:**
|
|
1074
1085
|
```bash
|
|
1075
|
-
|
|
1086
|
+
ruflo pair start --ci --non-interactive
|
|
1076
1087
|
```
|
|
1077
1088
|
|
|
1078
1089
|
**With IDE:**
|
|
1079
1090
|
```bash
|
|
1080
|
-
|
|
1091
|
+
ruflo pair start --ide vscode
|
|
1081
1092
|
```
|
|
1082
1093
|
|
|
1083
1094
|
### Best Practices
|
|
@@ -1131,7 +1142,7 @@ claude-flow pair --start --ide vscode
|
|
|
1131
1142
|
- Validate JSON syntax
|
|
1132
1143
|
- Check file permissions
|
|
1133
1144
|
- Review priority order (CLI > env > project > user > global)
|
|
1134
|
-
- Run `
|
|
1145
|
+
- Run `ruflo pair config validate`
|
|
1135
1146
|
|
|
1136
1147
|
### Quality Metrics
|
|
1137
1148
|
|
|
@@ -1195,8 +1206,8 @@ Default shortcuts:
|
|
|
1195
1206
|
|
|
1196
1207
|
### Related Commands
|
|
1197
1208
|
|
|
1198
|
-
- `
|
|
1199
|
-
- `
|
|
1200
|
-
- `
|
|
1201
|
-
- `
|
|
1202
|
-
- `
|
|
1209
|
+
- `ruflo pair --help` - Show help
|
|
1210
|
+
- `ruflo pair config` - Manage configuration
|
|
1211
|
+
- `ruflo pair profile` - Manage profiles
|
|
1212
|
+
- `ruflo pair templates` - List templates
|
|
1213
|
+
- `ruflo pair agents` - List available agents
|
package/package.json
CHANGED
|
@@ -47,8 +47,8 @@ export const signCommand = {
|
|
|
47
47
|
action: async (ctx) => {
|
|
48
48
|
const file = ctx.flags.file;
|
|
49
49
|
const keyPath = ctx.flags.key;
|
|
50
|
-
const genKeys = ctx.flags
|
|
51
|
-
const keyDir = ctx.flags
|
|
50
|
+
const genKeys = ctx.flags.generateKeys;
|
|
51
|
+
const keyDir = ctx.flags.keyDir || '.rvfa-keys';
|
|
52
52
|
const signer = ctx.flags.signer;
|
|
53
53
|
if (!file)
|
|
54
54
|
return fail('--file is required');
|
|
@@ -184,14 +184,14 @@ export const updateAppCommand = {
|
|
|
184
184
|
});
|
|
185
185
|
}
|
|
186
186
|
let pubKey;
|
|
187
|
-
if (ctx.flags
|
|
188
|
-
const pkPath = ctx.flags
|
|
187
|
+
if (ctx.flags.publicKey) {
|
|
188
|
+
const pkPath = ctx.flags.publicKey;
|
|
189
189
|
if (!(await requireFile(pkPath)))
|
|
190
190
|
return { success: false, exitCode: 1 };
|
|
191
191
|
pubKey = fs.readFileSync(pkPath);
|
|
192
192
|
}
|
|
193
193
|
const result = await dist.RvfaPatcher.applyPatch(file, patchBuf, {
|
|
194
|
-
backup:
|
|
194
|
+
backup: ctx.flags.backup !== false,
|
|
195
195
|
verify: true,
|
|
196
196
|
publicKey: pubKey,
|
|
197
197
|
});
|
|
@@ -70,7 +70,7 @@ const buildCommand = {
|
|
|
70
70
|
const outputPath = ctx.flags.output || 'ruflo.rvf';
|
|
71
71
|
const arch = ctx.flags.arch || 'x86_64';
|
|
72
72
|
const models = ctx.flags.models || [];
|
|
73
|
-
const apiKeysPath = ctx.flags
|
|
73
|
+
const apiKeysPath = ctx.flags.apiKeys;
|
|
74
74
|
header('RVFA Appliance Builder');
|
|
75
75
|
output.printInfo(`Profile: ${output.highlight(profile)}`);
|
|
76
76
|
output.printInfo(`Arch: ${arch}`);
|
|
@@ -92,7 +92,10 @@ const buildCommand = {
|
|
|
92
92
|
if (apiKeysPath)
|
|
93
93
|
steps.splice(steps.length - 1, 0, 'Sealing API key vault');
|
|
94
94
|
try {
|
|
95
|
-
const builder = new RvfaBuilder({
|
|
95
|
+
const builder = new RvfaBuilder({
|
|
96
|
+
profile, output: outputPath, arch, apiKeys: apiKeysPath,
|
|
97
|
+
models: models.length > 0 ? models : undefined,
|
|
98
|
+
});
|
|
96
99
|
await runSteps(steps);
|
|
97
100
|
const result = await builder.build();
|
|
98
101
|
const duration = ((Date.now() - startTime) / 1000).toFixed(1);
|
|
@@ -108,7 +111,7 @@ const buildCommand = {
|
|
|
108
111
|
}
|
|
109
112
|
output.writeln();
|
|
110
113
|
output.printSuccess(`Appliance written to ${output.bold(outputPath)}`);
|
|
111
|
-
output.printInfo(`Total size: ${output.bold(fmtSize(result.
|
|
114
|
+
output.printInfo(`Total size: ${output.bold(fmtSize(result.size))} Duration: ${duration}s`);
|
|
112
115
|
return { success: true, data: result };
|
|
113
116
|
}
|
|
114
117
|
catch (err) {
|
|
@@ -46,6 +46,7 @@ export declare function getGuidanceCommand(): Promise<Command | undefined>;
|
|
|
46
46
|
export declare function getApplianceCommand(): Promise<Command | undefined>;
|
|
47
47
|
export declare function getCleanupCommand(): Promise<Command | undefined>;
|
|
48
48
|
export declare function getAutopilotCommand(): Promise<Command | undefined>;
|
|
49
|
+
export declare function getPairCommand(): Promise<Command | undefined>;
|
|
49
50
|
export declare function getTransportCommand(): Promise<Command | undefined>;
|
|
50
51
|
/**
|
|
51
52
|
* Core commands loaded synchronously (available immediately)
|
|
@@ -70,6 +70,9 @@ const commandLoaders = {
|
|
|
70
70
|
'transfer-store': () => import('./transfer-store.js'),
|
|
71
71
|
cleanup: () => import('./cleanup.js'),
|
|
72
72
|
autopilot: () => import('./autopilot.js'),
|
|
73
|
+
// Pair programming session state (restores the v2 `pair` command the
|
|
74
|
+
// bundled pair-programming skill depends on)
|
|
75
|
+
pair: () => import('./pair.js'),
|
|
73
76
|
// GAIA Benchmark Harness (ADR-133)
|
|
74
77
|
'gaia-bench': () => import('./gaia-bench.js'),
|
|
75
78
|
// MetaHarness integration (ADR-150) — dispatcher over plugins/ruflo-metaharness/
|
|
@@ -203,6 +206,7 @@ export async function getGuidanceCommand() { return loadCommand('guidance'); }
|
|
|
203
206
|
export async function getApplianceCommand() { return loadCommand('appliance'); }
|
|
204
207
|
export async function getCleanupCommand() { return loadCommand('cleanup'); }
|
|
205
208
|
export async function getAutopilotCommand() { return loadCommand('autopilot'); }
|
|
209
|
+
export async function getPairCommand() { return loadCommand('pair'); }
|
|
206
210
|
export async function getTransportCommand() { return loadCommand('transport'); }
|
|
207
211
|
/**
|
|
208
212
|
* Core commands loaded synchronously (available immediately)
|
|
@@ -249,14 +253,14 @@ export const commandsByCategory = {
|
|
|
249
253
|
* Use this for help display and full command listings.
|
|
250
254
|
*/
|
|
251
255
|
export async function getCommandsByCategory() {
|
|
252
|
-
const [daemonCmd, doctorCmd, embeddingsCmd, neuralCmd, performanceCmd, securityCmd, ruvectorCmd, hiveMindCmd, configCmd, completionsCmd, migrateCmd, workflowCmd, analyzeCmd, routeCmd, progressCmd, providersCmd, pluginsCmd, deploymentCmd, claimsCmd, issuesCmd, updateCmd, processCmd, guidanceCmd, applianceCmd, cleanupCmd, autopilotCmd, policyCmd,] = await Promise.all([
|
|
256
|
+
const [daemonCmd, doctorCmd, embeddingsCmd, neuralCmd, performanceCmd, securityCmd, ruvectorCmd, hiveMindCmd, configCmd, completionsCmd, migrateCmd, workflowCmd, analyzeCmd, routeCmd, progressCmd, providersCmd, pluginsCmd, deploymentCmd, claimsCmd, issuesCmd, updateCmd, processCmd, guidanceCmd, applianceCmd, cleanupCmd, autopilotCmd, policyCmd, pairCmd,] = await Promise.all([
|
|
253
257
|
loadCommand('daemon'), loadCommand('doctor'), loadCommand('embeddings'), loadCommand('neural'),
|
|
254
258
|
loadCommand('performance'), loadCommand('security'), loadCommand('ruvector'), loadCommand('hive-mind'),
|
|
255
259
|
loadCommand('config'), loadCommand('completions'), loadCommand('migrate'), loadCommand('workflow'),
|
|
256
260
|
loadCommand('analyze'), loadCommand('route'), loadCommand('progress'), loadCommand('providers'),
|
|
257
261
|
loadCommand('plugins'), loadCommand('deployment'), loadCommand('claims'), loadCommand('issues'),
|
|
258
262
|
loadCommand('update'), loadCommand('process'), loadCommand('guidance'), loadCommand('appliance'),
|
|
259
|
-
loadCommand('cleanup'), loadCommand('autopilot'), loadCommand('policy'),
|
|
263
|
+
loadCommand('cleanup'), loadCommand('autopilot'), loadCommand('policy'), loadCommand('pair'),
|
|
260
264
|
]);
|
|
261
265
|
return {
|
|
262
266
|
primary: [
|
|
@@ -270,7 +274,7 @@ export async function getCommandsByCategory() {
|
|
|
270
274
|
].filter(Boolean),
|
|
271
275
|
utility: [
|
|
272
276
|
configCmd, doctorCmd, daemonCmd, completionsCmd,
|
|
273
|
-
migrateCmd, workflowCmd,
|
|
277
|
+
migrateCmd, workflowCmd, pairCmd,
|
|
274
278
|
].filter(Boolean),
|
|
275
279
|
analysis: [
|
|
276
280
|
analyzeCmd, routeCmd, progressCmd,
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `ruflo pair` — pair programming session state.
|
|
3
|
+
*
|
|
4
|
+
* The bundled `pair-programming` skill has told Claude Code to run
|
|
5
|
+
* `claude-flow pair --start --mode tdd` since v2, but the v3 CLI never
|
|
6
|
+
* shipped the command, so the skill's modes could not be activated or
|
|
7
|
+
* switched. This restores a minimal, non-interactive version: the session
|
|
8
|
+
* (mode, who currently drives, when roles last swapped) lives in
|
|
9
|
+
* `.claude-flow/sessions/pair/current.json` in the project so both the human
|
|
10
|
+
* and the agent can read it between turns. There is no REPL — Claude Code
|
|
11
|
+
* cannot type into one — the agent reads `pair status --json` and behaves
|
|
12
|
+
* according to the recorded mode and role.
|
|
13
|
+
*
|
|
14
|
+
* Legacy v2 spellings (`pair --start`, `--status`, `--end`, `--history`)
|
|
15
|
+
* still work so existing skill docs and muscle memory keep functioning.
|
|
16
|
+
*/
|
|
17
|
+
import type { Command } from '../types.js';
|
|
18
|
+
export declare const PAIR_MODES: {
|
|
19
|
+
readonly driver: "AI writes the code, human reviews and steers";
|
|
20
|
+
readonly navigator: "Human writes the code, AI reviews and suggests";
|
|
21
|
+
readonly switch: "Roles swap every --interval (default 10m)";
|
|
22
|
+
readonly tdd: "Red-green-refactor; AI writes failing tests first";
|
|
23
|
+
readonly review: "Read-only review of existing code, no edits without approval";
|
|
24
|
+
readonly mentor: "AI explains every step and asks before acting";
|
|
25
|
+
readonly debug: "Hypothesis-driven debugging; AI reproduces before fixing";
|
|
26
|
+
};
|
|
27
|
+
export type PairMode = keyof typeof PAIR_MODES;
|
|
28
|
+
export type PairRole = 'driver' | 'navigator';
|
|
29
|
+
export interface PairSession {
|
|
30
|
+
id: string;
|
|
31
|
+
mode: PairMode;
|
|
32
|
+
/** Who currently types. Always refers to the AI's role. */
|
|
33
|
+
aiRole: PairRole;
|
|
34
|
+
switchIntervalMinutes: number | null;
|
|
35
|
+
startedAt: string;
|
|
36
|
+
lastSwitchAt: string;
|
|
37
|
+
switches: number;
|
|
38
|
+
endedAt?: string;
|
|
39
|
+
}
|
|
40
|
+
export declare function readSession(cwd: string): PairSession | null;
|
|
41
|
+
export declare function readHistory(cwd: string): PairSession[];
|
|
42
|
+
/** Accepts `10`, `10m`, `1h`, `90s`; returns minutes or null when unparseable. */
|
|
43
|
+
export declare function parseIntervalMinutes(raw: unknown): number | null;
|
|
44
|
+
export declare const pairCommand: Command;
|
|
45
|
+
export default pairCommand;
|
|
46
|
+
//# sourceMappingURL=pair.d.ts.map
|
|
@@ -0,0 +1,303 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `ruflo pair` — pair programming session state.
|
|
3
|
+
*
|
|
4
|
+
* The bundled `pair-programming` skill has told Claude Code to run
|
|
5
|
+
* `claude-flow pair --start --mode tdd` since v2, but the v3 CLI never
|
|
6
|
+
* shipped the command, so the skill's modes could not be activated or
|
|
7
|
+
* switched. This restores a minimal, non-interactive version: the session
|
|
8
|
+
* (mode, who currently drives, when roles last swapped) lives in
|
|
9
|
+
* `.claude-flow/sessions/pair/current.json` in the project so both the human
|
|
10
|
+
* and the agent can read it between turns. There is no REPL — Claude Code
|
|
11
|
+
* cannot type into one — the agent reads `pair status --json` and behaves
|
|
12
|
+
* according to the recorded mode and role.
|
|
13
|
+
*
|
|
14
|
+
* Legacy v2 spellings (`pair --start`, `--status`, `--end`, `--history`)
|
|
15
|
+
* still work so existing skill docs and muscle memory keep functioning.
|
|
16
|
+
*/
|
|
17
|
+
import * as fs from 'node:fs';
|
|
18
|
+
import * as path from 'node:path';
|
|
19
|
+
import { output } from '../output.js';
|
|
20
|
+
export const PAIR_MODES = {
|
|
21
|
+
driver: 'AI writes the code, human reviews and steers',
|
|
22
|
+
navigator: 'Human writes the code, AI reviews and suggests',
|
|
23
|
+
switch: 'Roles swap every --interval (default 10m)',
|
|
24
|
+
tdd: 'Red-green-refactor; AI writes failing tests first',
|
|
25
|
+
review: 'Read-only review of existing code, no edits without approval',
|
|
26
|
+
mentor: 'AI explains every step and asks before acting',
|
|
27
|
+
debug: 'Hypothesis-driven debugging; AI reproduces before fixing',
|
|
28
|
+
};
|
|
29
|
+
const SESSION_DIR = ['.claude-flow', 'sessions', 'pair'];
|
|
30
|
+
const DEFAULT_SWITCH_INTERVAL_MINUTES = 10;
|
|
31
|
+
function sessionDir(cwd) {
|
|
32
|
+
return path.join(cwd, ...SESSION_DIR);
|
|
33
|
+
}
|
|
34
|
+
function currentPath(cwd) {
|
|
35
|
+
return path.join(sessionDir(cwd), 'current.json');
|
|
36
|
+
}
|
|
37
|
+
function historyPath(cwd) {
|
|
38
|
+
return path.join(sessionDir(cwd), 'history.jsonl');
|
|
39
|
+
}
|
|
40
|
+
export function readSession(cwd) {
|
|
41
|
+
try {
|
|
42
|
+
return JSON.parse(fs.readFileSync(currentPath(cwd), 'utf-8'));
|
|
43
|
+
}
|
|
44
|
+
catch {
|
|
45
|
+
return null;
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
function writeSession(cwd, session) {
|
|
49
|
+
fs.mkdirSync(sessionDir(cwd), { recursive: true });
|
|
50
|
+
const tmp = currentPath(cwd) + '.tmp-' + process.pid;
|
|
51
|
+
fs.writeFileSync(tmp, JSON.stringify(session, null, 2) + '\n', 'utf-8');
|
|
52
|
+
fs.renameSync(tmp, currentPath(cwd));
|
|
53
|
+
}
|
|
54
|
+
export function readHistory(cwd) {
|
|
55
|
+
try {
|
|
56
|
+
return fs.readFileSync(historyPath(cwd), 'utf-8')
|
|
57
|
+
.split('\n')
|
|
58
|
+
.filter(Boolean)
|
|
59
|
+
.map(line => JSON.parse(line));
|
|
60
|
+
}
|
|
61
|
+
catch {
|
|
62
|
+
return [];
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
/** Accepts `10`, `10m`, `1h`, `90s`; returns minutes or null when unparseable. */
|
|
66
|
+
export function parseIntervalMinutes(raw) {
|
|
67
|
+
if (raw === undefined || raw === null || raw === '')
|
|
68
|
+
return null;
|
|
69
|
+
if (typeof raw === 'number')
|
|
70
|
+
return raw > 0 ? raw : null;
|
|
71
|
+
const match = /^(\d+(?:\.\d+)?)\s*(s|m|h)?$/i.exec(String(raw).trim());
|
|
72
|
+
if (!match)
|
|
73
|
+
return null;
|
|
74
|
+
const value = parseFloat(match[1]);
|
|
75
|
+
const unit = (match[2] ?? 'm').toLowerCase();
|
|
76
|
+
const minutes = unit === 'h' ? value * 60 : unit === 's' ? value / 60 : value;
|
|
77
|
+
return minutes > 0 ? minutes : null;
|
|
78
|
+
}
|
|
79
|
+
function isMode(value) {
|
|
80
|
+
return typeof value === 'string' && value in PAIR_MODES;
|
|
81
|
+
}
|
|
82
|
+
function otherRole(role) {
|
|
83
|
+
return role === 'driver' ? 'navigator' : 'driver';
|
|
84
|
+
}
|
|
85
|
+
/** Default AI role implied by a mode, used when --role is not given. */
|
|
86
|
+
function defaultRoleFor(mode) {
|
|
87
|
+
return mode === 'navigator' || mode === 'review' ? 'navigator' : 'driver';
|
|
88
|
+
}
|
|
89
|
+
function switchDue(session, now) {
|
|
90
|
+
if (session.mode !== 'switch' || !session.switchIntervalMinutes)
|
|
91
|
+
return false;
|
|
92
|
+
const elapsedMinutes = (now.getTime() - new Date(session.lastSwitchAt).getTime()) / 60_000;
|
|
93
|
+
return elapsedMinutes >= session.switchIntervalMinutes;
|
|
94
|
+
}
|
|
95
|
+
function describe(session, now) {
|
|
96
|
+
return {
|
|
97
|
+
...session,
|
|
98
|
+
modeDescription: PAIR_MODES[session.mode],
|
|
99
|
+
humanRole: otherRole(session.aiRole),
|
|
100
|
+
switchDue: switchDue(session, now),
|
|
101
|
+
};
|
|
102
|
+
}
|
|
103
|
+
function printSession(session, now) {
|
|
104
|
+
output.writeln(`Session: ${session.id}`);
|
|
105
|
+
output.writeln(`Mode: ${session.mode} — ${PAIR_MODES[session.mode]}`);
|
|
106
|
+
output.writeln(`AI role: ${session.aiRole} (human: ${otherRole(session.aiRole)})`);
|
|
107
|
+
if (session.switchIntervalMinutes) {
|
|
108
|
+
output.writeln(`Interval: every ${session.switchIntervalMinutes}m, ${session.switches} switch(es) so far`);
|
|
109
|
+
if (switchDue(session, now))
|
|
110
|
+
output.printWarning('Role switch is due — run `ruflo pair switch`.');
|
|
111
|
+
}
|
|
112
|
+
output.writeln(`Started: ${session.startedAt}`);
|
|
113
|
+
}
|
|
114
|
+
function noSession(ctx) {
|
|
115
|
+
if (ctx.flags.json)
|
|
116
|
+
output.printJson({ active: false });
|
|
117
|
+
else
|
|
118
|
+
output.writeln('No active pair session. Start one with `ruflo pair start --mode <mode>`.');
|
|
119
|
+
return { success: true, data: { active: false } };
|
|
120
|
+
}
|
|
121
|
+
async function startAction(ctx) {
|
|
122
|
+
// `pair start tdd` and `pair start --mode tdd` both work; a bare word wins
|
|
123
|
+
// over the option default so it is never silently ignored.
|
|
124
|
+
const mode = ctx.args[0] ?? ctx.flags.mode ?? 'driver';
|
|
125
|
+
if (!isMode(mode)) {
|
|
126
|
+
output.printError(`Unknown mode "${String(mode)}". Choose one of: ${Object.keys(PAIR_MODES).join(', ')}`);
|
|
127
|
+
return { success: false, exitCode: 1 };
|
|
128
|
+
}
|
|
129
|
+
const existing = readSession(ctx.cwd);
|
|
130
|
+
if (existing) {
|
|
131
|
+
output.printError(`A pair session is already active (${existing.id}). End it first with \`ruflo pair end\`.`);
|
|
132
|
+
return { success: false, exitCode: 1, data: describe(existing, new Date()) };
|
|
133
|
+
}
|
|
134
|
+
const interval = ctx.flags.interval !== undefined ? parseIntervalMinutes(ctx.flags.interval) : null;
|
|
135
|
+
if (ctx.flags.interval !== undefined && interval === null) {
|
|
136
|
+
output.printError(`Invalid --interval "${String(ctx.flags.interval)}". Use e.g. 10m, 90s or 1h.`);
|
|
137
|
+
return { success: false, exitCode: 1 };
|
|
138
|
+
}
|
|
139
|
+
const role = ctx.flags.role;
|
|
140
|
+
const now = new Date();
|
|
141
|
+
const session = {
|
|
142
|
+
id: `pair_${now.getTime()}`,
|
|
143
|
+
mode,
|
|
144
|
+
aiRole: role === 'driver' || role === 'navigator' ? role : defaultRoleFor(mode),
|
|
145
|
+
switchIntervalMinutes: mode === 'switch' ? (interval ?? DEFAULT_SWITCH_INTERVAL_MINUTES) : interval,
|
|
146
|
+
startedAt: now.toISOString(),
|
|
147
|
+
lastSwitchAt: now.toISOString(),
|
|
148
|
+
switches: 0,
|
|
149
|
+
};
|
|
150
|
+
writeSession(ctx.cwd, session);
|
|
151
|
+
if (ctx.flags.json)
|
|
152
|
+
output.printJson(describe(session, now));
|
|
153
|
+
else {
|
|
154
|
+
output.printSuccess('Pair session started.');
|
|
155
|
+
printSession(session, now);
|
|
156
|
+
}
|
|
157
|
+
return { success: true, data: describe(session, now) };
|
|
158
|
+
}
|
|
159
|
+
const startSub = {
|
|
160
|
+
name: 'start',
|
|
161
|
+
description: 'Start a pair programming session',
|
|
162
|
+
options: [
|
|
163
|
+
{ name: 'mode', short: 'm', description: 'Collaboration mode', type: 'string', default: 'driver', choices: Object.keys(PAIR_MODES) },
|
|
164
|
+
{ name: 'role', description: "AI's starting role (defaults from mode)", type: 'string', choices: ['driver', 'navigator'] },
|
|
165
|
+
{ name: 'interval', short: 'i', description: 'Role switch interval for switch mode (e.g. 10m, 1h)', type: 'string' },
|
|
166
|
+
{ name: 'json', description: 'Output as JSON', type: 'boolean', default: false },
|
|
167
|
+
],
|
|
168
|
+
action: startAction,
|
|
169
|
+
};
|
|
170
|
+
async function statusAction(ctx) {
|
|
171
|
+
const session = readSession(ctx.cwd);
|
|
172
|
+
if (!session)
|
|
173
|
+
return noSession(ctx);
|
|
174
|
+
const now = new Date();
|
|
175
|
+
if (ctx.flags.json)
|
|
176
|
+
output.printJson({ active: true, ...describe(session, now) });
|
|
177
|
+
else
|
|
178
|
+
printSession(session, now);
|
|
179
|
+
return { success: true, data: { active: true, ...describe(session, now) } };
|
|
180
|
+
}
|
|
181
|
+
const statusSub = {
|
|
182
|
+
name: 'status',
|
|
183
|
+
description: 'Show the active pair session',
|
|
184
|
+
options: [{ name: 'json', description: 'Output as JSON', type: 'boolean', default: false }],
|
|
185
|
+
action: statusAction,
|
|
186
|
+
};
|
|
187
|
+
async function switchAction(ctx) {
|
|
188
|
+
const session = readSession(ctx.cwd);
|
|
189
|
+
if (!session)
|
|
190
|
+
return noSession(ctx);
|
|
191
|
+
const now = new Date();
|
|
192
|
+
session.aiRole = otherRole(session.aiRole);
|
|
193
|
+
session.lastSwitchAt = now.toISOString();
|
|
194
|
+
session.switches += 1;
|
|
195
|
+
writeSession(ctx.cwd, session);
|
|
196
|
+
if (ctx.flags.json)
|
|
197
|
+
output.printJson(describe(session, now));
|
|
198
|
+
else
|
|
199
|
+
output.printSuccess(`Switched — AI is now ${session.aiRole}, human is ${otherRole(session.aiRole)}.`);
|
|
200
|
+
return { success: true, data: describe(session, now) };
|
|
201
|
+
}
|
|
202
|
+
const switchSub = {
|
|
203
|
+
name: 'switch',
|
|
204
|
+
description: 'Swap driver and navigator roles',
|
|
205
|
+
options: [{ name: 'json', description: 'Output as JSON', type: 'boolean', default: false }],
|
|
206
|
+
action: switchAction,
|
|
207
|
+
};
|
|
208
|
+
async function modeAction(ctx) {
|
|
209
|
+
const session = readSession(ctx.cwd);
|
|
210
|
+
if (!session)
|
|
211
|
+
return noSession(ctx);
|
|
212
|
+
const mode = ctx.args[0];
|
|
213
|
+
if (!isMode(mode)) {
|
|
214
|
+
output.printError(`Usage: ruflo pair mode <${Object.keys(PAIR_MODES).join('|')}>`);
|
|
215
|
+
return { success: false, exitCode: 1 };
|
|
216
|
+
}
|
|
217
|
+
const now = new Date();
|
|
218
|
+
session.mode = mode;
|
|
219
|
+
if (mode === 'switch' && !session.switchIntervalMinutes) {
|
|
220
|
+
session.switchIntervalMinutes = DEFAULT_SWITCH_INTERVAL_MINUTES;
|
|
221
|
+
session.lastSwitchAt = now.toISOString();
|
|
222
|
+
}
|
|
223
|
+
writeSession(ctx.cwd, session);
|
|
224
|
+
if (ctx.flags.json)
|
|
225
|
+
output.printJson(describe(session, now));
|
|
226
|
+
else
|
|
227
|
+
output.printSuccess(`Mode changed to ${mode} — ${PAIR_MODES[mode]}.`);
|
|
228
|
+
return { success: true, data: describe(session, now) };
|
|
229
|
+
}
|
|
230
|
+
const modeSub = {
|
|
231
|
+
name: 'mode',
|
|
232
|
+
description: 'Change the mode of the active session: ruflo pair mode <mode>',
|
|
233
|
+
options: [{ name: 'json', description: 'Output as JSON', type: 'boolean', default: false }],
|
|
234
|
+
action: modeAction,
|
|
235
|
+
};
|
|
236
|
+
async function endAction(ctx) {
|
|
237
|
+
const session = readSession(ctx.cwd);
|
|
238
|
+
if (!session)
|
|
239
|
+
return noSession(ctx);
|
|
240
|
+
session.endedAt = new Date().toISOString();
|
|
241
|
+
fs.appendFileSync(historyPath(ctx.cwd), JSON.stringify(session) + '\n', 'utf-8');
|
|
242
|
+
fs.rmSync(currentPath(ctx.cwd), { force: true });
|
|
243
|
+
if (ctx.flags.json)
|
|
244
|
+
output.printJson(session);
|
|
245
|
+
else
|
|
246
|
+
output.printSuccess(`Pair session ${session.id} ended after ${session.switches} role switch(es).`);
|
|
247
|
+
return { success: true, data: session };
|
|
248
|
+
}
|
|
249
|
+
const endSub = {
|
|
250
|
+
name: 'end',
|
|
251
|
+
description: 'End the active session and append it to the history',
|
|
252
|
+
options: [{ name: 'json', description: 'Output as JSON', type: 'boolean', default: false }],
|
|
253
|
+
action: endAction,
|
|
254
|
+
};
|
|
255
|
+
async function historyAction(ctx) {
|
|
256
|
+
const history = readHistory(ctx.cwd);
|
|
257
|
+
if (ctx.flags.json)
|
|
258
|
+
output.printJson(history);
|
|
259
|
+
else if (history.length === 0)
|
|
260
|
+
output.writeln('No past pair sessions.');
|
|
261
|
+
else
|
|
262
|
+
for (const s of history)
|
|
263
|
+
output.writeln(`${s.id} ${s.mode.padEnd(9)} ${s.startedAt} → ${s.endedAt ?? '?'} (${s.switches} switches)`);
|
|
264
|
+
return { success: true, data: history };
|
|
265
|
+
}
|
|
266
|
+
const historySub = {
|
|
267
|
+
name: 'history',
|
|
268
|
+
description: 'List past pair sessions',
|
|
269
|
+
options: [{ name: 'json', description: 'Output as JSON', type: 'boolean', default: false }],
|
|
270
|
+
action: historyAction,
|
|
271
|
+
};
|
|
272
|
+
export const pairCommand = {
|
|
273
|
+
name: 'pair',
|
|
274
|
+
description: 'Pair programming session: modes, driver/navigator roles, switching',
|
|
275
|
+
subcommands: [startSub, statusSub, switchSub, modeSub, endSub, historySub],
|
|
276
|
+
// Top-level flags kept for the v2 spelling used throughout the skill docs.
|
|
277
|
+
options: [
|
|
278
|
+
{ name: 'start', description: 'Alias for `pair start`', type: 'boolean', default: false },
|
|
279
|
+
{ name: 'status', description: 'Alias for `pair status`', type: 'boolean', default: false },
|
|
280
|
+
{ name: 'end', description: 'Alias for `pair end`', type: 'boolean', default: false },
|
|
281
|
+
{ name: 'history', description: 'Alias for `pair history`', type: 'boolean', default: false },
|
|
282
|
+
...(startSub.options ?? []),
|
|
283
|
+
],
|
|
284
|
+
examples: [
|
|
285
|
+
{ command: 'ruflo pair start --mode tdd', description: 'Start a test-first session with the AI driving' },
|
|
286
|
+
{ command: 'ruflo pair start --mode switch --interval 15m', description: 'Swap roles every 15 minutes' },
|
|
287
|
+
{ command: 'ruflo pair status --json', description: 'Machine-readable state for the agent to read each turn' },
|
|
288
|
+
{ command: 'ruflo pair switch', description: 'Swap driver and navigator now' },
|
|
289
|
+
{ command: 'ruflo pair mode review', description: 'Change mode mid-session' },
|
|
290
|
+
{ command: 'ruflo pair end', description: 'End the session and record it in the history' },
|
|
291
|
+
],
|
|
292
|
+
action: async (ctx) => {
|
|
293
|
+
if (ctx.flags.start)
|
|
294
|
+
return startAction(ctx);
|
|
295
|
+
if (ctx.flags.end)
|
|
296
|
+
return endAction(ctx);
|
|
297
|
+
if (ctx.flags.history)
|
|
298
|
+
return historyAction(ctx);
|
|
299
|
+
return statusAction(ctx);
|
|
300
|
+
},
|
|
301
|
+
};
|
|
302
|
+
export default pairCommand;
|
|
303
|
+
//# sourceMappingURL=pair.js.map
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@claude-flow/cli",
|
|
3
|
-
"version": "3.59.
|
|
3
|
+
"version": "3.59.12",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "Ruflo CLI - Enterprise AI agent orchestration with 60+ specialized agents, swarm coordination, MCP server, self-learning hooks, and vector memory for Claude Code",
|
|
6
6
|
"main": "dist/src/index.js",
|