cflx 0.5.8

Conflux – a spec-driven parallel coding orchestrator that runs AI agents on git worktrees
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
# Conflux

[![Rust](https://img.shields.io/badge/rust-1.70%2B-orange.svg)](https://www.rust-lang.org/)
[![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](LICENSE)

Automates the OpenSpec change workflow (list → dependency analysis → apply → archive). Orchestrates `openspec` and AI coding agents to process changes autonomously.

## Features

- 🖥️ **Interactive TUI**: Default mode with real-time progress dashboard
- 🤖 **Automated Workflow**: Automatically processes OpenSpec changes from detection to archival
- 🧠 **LLM Dependency Analysis**: Uses AI agents to intelligently analyze and order changes
- 📊 **Real-time Progress**: Visual progress bars showing overall and per-change status
- 🔌 **Multi-Agent Support**: Works with Claude Code, OpenCode, and Codex
- 🪝 **Lifecycle Hooks**: Configurable hooks for custom actions at each workflow stage
-**Parallel Execution**: Process multiple independent changes simultaneously using Git worktrees
- 🌐 **Web Monitoring**: Optional HTTP server with REST API and WebSocket for remote monitoring

## Architecture

```
┌─────────────────────────────────────────────┐
│     cflx (Rust CLI)        │
├─────────────────────────────────────────────┤
│  CLI → Orchestrator → State Manager         │
│    ↓        ↓              ↓                │
│  OpenSpec  AI Agent    Progress Display     │
│            (Claude/OpenCode/Codex)          │
└─────────────────────────────────────────────┘
```

## Quick Start

```bash
# 1. Install
cargo install --path .

# 2. Initialize configuration (Claude Code agent by default)
cflx init

# 3. Launch the interactive TUI (default entry point)
cflx

# Or run headless (non-interactive)
cflx run
```

For other templates:

```bash
cflx init --template opencode
cflx init --template codex
```

## Usage

### Golden Path: Quick Start

```bash
# Step 1: Generate configuration for your AI agent (Claude Code by default)
cflx init

# Step 2: Edit the generated .cflx.jsonc to configure your agent
vim .cflx.jsonc

# Step 3a: Launch the interactive TUI to review and process changes
cflx

# Step 3b: Or run in headless (non-interactive) mode
cflx run
```

### Interactive TUI (Primary Interface)

The primary way to use the orchestrator is through the interactive TUI dashboard:

```bash
cflx
```

The TUI provides:
- Real-time change status visualization
- Progress tracking for all pending changes
- Keyboard navigation and controls
- Worktree management view

#### TUI Change States

Changes have a **selection/queue** state.

**Checkbox Display:**
| Symbol | State | Description |
|--------|-------|-------------|
| `[ ]` | Not selected | Not marked for processing |
| `[x]` | Selected (reserved) | Will be queued when F5 is pressed |

**Queue Status (shown in Running mode):**
| Status | Description |
|--------|-------------|
| `[not queued]` | Not in the execution queue (can be toggled dynamically while running) |
| `[queued]` | Waiting to be processed |
| `[blocked]` | Blocked by unresolved dependencies |
| `[merge wait]` | Waiting for merge resolution (use `M` to trigger resolve) |
| `[resolve pending]` | Resolve requested, waiting for execution to start (UI actions are restricted) |
| `[applying]` | Applying (spinner + progress% / iteration when available) |
| `[accepting]` | Acceptance/tests (spinner, iteration when available) |
| `[archiving]` | Archiving (spinner, iteration when available) |
| `[resolving]` | Resolving (spinner, iteration when available) |
| `[archived]` | Archived successfully |
| `[merged]` | Merged to base branch (parallel mode only) |
| `[error]` | Processing failed |

**Workflow:**
1. **Select mode (header shows `[Ready]`)**: Use `Space` to toggle the execution mark (`selected`)
2. Press `F5` to start processing - all execution-marked changes become `queued`
3. **Running mode (header shows `[Running N]`)**: `queued``applying` → (optional `accepting`) → `archiving``archived` (parallel mode may also show `merge wait`/`resolving`/`merged`)

#### Header Status

| Display | Meaning |
|---------|---------|
| `[Ready]` | Selection/idle (`AppMode::Select`) |
| `[Running N]` | Active processing, where N counts `applying`/`accepting`/`archiving`/`resolving` |

#### TUI Key Bindings

**Changes View:**

| Key | Select (`[Ready]`) | Running (/Stopping) | Stopped (/Error) |
|-----|-------------------|--------------------|------------------|
| `↑/↓` or `j/k` | Navigate list | Navigate list | Navigate list |
| `Tab` | Switch to Worktrees view | Switch to Worktrees view | Switch to Worktrees view |
| `Space` | Toggle execution mark only | Add/remove from dynamic queue (`not queued``queued`) | Toggle execution mark for `not queued` only |
| `e` | Open editor | Open editor | Open editor |
| `w` | Show QR code* | Show QR code* | Show QR code* |
| `M` | Resolve when status is `merge wait` | Resolve when status is `merge wait` | Resolve when status is `merge wait` |
| `F5` | Start processing | (In Stopping: cancel stop) | Resume (Stopped) / Retry (Error) |
| `=` | Toggle parallel mode | - | Toggle parallel mode |
| `Esc` | - | Stop (1st: graceful, 2nd: force) | - |
| `PageUp/Down` | (When logs are shown) scroll logs | Scroll logs | Scroll logs |
| `Home/End` | (When logs are shown) top/bottom | Top/bottom | Top/bottom |
| `Ctrl+C` | Quit | Quit | Quit |

**Worktrees View:**

| Key | Action | Description |
|-----|--------|-------------|
| `Tab` | Switch to Changes view | Return to main changes list |
| `↑/↓` or `j/k` | Navigate worktrees | Move between worktree entries |
| `+` | Create new worktree | Creates new worktree with unique branch name |
| `D` | Delete worktree | Remove non-main, non-processing worktree |
| `M` | Merge to base branch | Merge current worktree branch (conflict-free only) |
| `e` | Open editor | Open editor in worktree directory |
| `Enter` | Open shell | Runs only when `worktree_command` is configured |
| `Ctrl+C` | Quit | Exit application |

*QR code is only available when web monitoring is enabled (`--web` flag). Press any key to close the QR popup.

### TUI Worktree View

The TUI includes a dedicated Worktree View for managing git worktrees directly from the interface.

**Key Features:**

- **View Switching**: Press `Tab` to switch between Changes and Worktrees views
- **Worktree List**: Displays all worktrees with path (basename), branch name, and status
- **Conflict Detection**: Automatically checks for merge conflicts in parallel (background)
- **Branch Merge**: Merge worktree branches to base with `M` key (conflict-free only)
- **Worktree Management**: Create (`+`), delete (`D`), open editor (`e`), open shell (`Enter`)

**Workflow:**

1. **Switch to Worktrees View**: Press `Tab` from Changes view
   - Loads worktree list with conflict detection (runs in parallel)
   - Display format: `<worktree-path> → <branch-name> [STATUS] [⚠conflicts]`

2. **Navigate Worktrees**: Use ``/`` or `j`/`k` keys
   - Main worktree shown with `[MAIN]` indicator (green)
   - Detached HEAD shown with `[DETACHED]` indicator
   - Conflicts shown with `⚠<count>` badge (red)

3. **Merge Branch**: Press `M` (only enabled when safe)
   - Validates: not main worktree, not detached HEAD, no conflicts
   - Executes: `git merge --no-ff --no-edit <branch>` in base repository
   - On success: Shows success log, refreshes worktree list
   - On failure: Shows error popup with details

4. **Create Worktree**: Press `+`
   - Generates unique branch name: `ws-session-<timestamp>`
   - Creates worktree with new branch (not detached HEAD)
   - Requires `worktree_command` config option

5. **Delete Worktree**: Press `D` (only for non-main, non-processing worktrees)
   - Shows confirmation dialog (`Y` to confirm, `N`/`Esc` to cancel)
   - Removes worktree directory and updates list

6. **Open Editor/Shell**: Press `e` or `Enter`
   - `e`: Opens editor in worktree directory (respects `$EDITOR`)
   - `Enter`: Runs `worktree_command` in worktree (e.g., opens shell)

**Conflict Detection:**

- Runs automatically when switching to Worktrees view
- Checks each non-main, non-detached worktree in parallel using `git merge --no-commit --no-ff`
- Detects conflicts without modifying working tree (uses `git merge --abort`)
- Displays conflict count as `⚠<count>` badge in red
- Updates every 5 seconds (auto-refresh) in background
- Disables `M` key when conflicts detected

**Performance:**

- Parallel conflict checking: Uses async concurrent execution
- Typical performance: 4 worktrees checked in < 1 second
- Non-blocking: Conflict checks run asynchronously, TUI remains responsive
- Fallback: On check failure, assumes no conflict info (safe default)

### Initialize Configuration

Generate a configuration file for your preferred AI agent:

```bash
# Default: Claude Code template
cflx init

# OpenCode template
cflx init --template opencode

# Codex template
cflx init --template codex

# Overwrite existing config
cflx init --force
```

Available templates: `claude` (default), `opencode`, `codex`

### Run Orchestration (Non-Interactive)

Process all pending changes in headless mode:

```bash
cflx run
```

Process specific changes (single or multiple):

```bash
# Single change
cflx run --change add-feature-x

# Multiple changes (comma-separated)
cflx run --change add-feature-x,fix-bug-y,refactor-z
```

Custom configuration file:

```bash
cflx run --config /path/to/config.jsonc
```

## How It Works

### Main Loop

```
1. List changes via openspec list
   2. Select next change
   • Priority 1: 100% complete (ready for archive)
   • Priority 2: LLM dependency analysis
   • Priority 3: Highest progress (fallback)
   3. Process change
   • If complete: openspec archive
   • If incomplete: AI agent applies next task
   4. Update state and repeat
```

### Dependency Analysis

The orchestrator uses an AI agent to analyze dependencies:

```
// Prompt sent to LLM
"Select the next change to execute from the following OpenSpec changes.

Changes:
- add-feature-x (2/5 tasks, 40.0%)
- fix-bug-y (5/5 tasks, 100.0%)
- refactor-z (0/3 tasks, 0.0%)

Selection criteria:
1. No dependencies, or dependencies are completed
2. Higher progress (continuity)
3. Consider dependencies inferred from names

Output only the change ID on a single line."
```

## Configuration

### Agent Configuration File (JSONC)

The orchestrator supports configurable agent commands via JSONC configuration files.
This allows you to use different AI tools (Claude Code, OpenCode, Codex, etc.) without code changes.

**Configuration file locations** (in order of priority):
1. `.cflx.jsonc` (project root)
2. `~/.config/cflx/config.jsonc` (global)
3. Custom path via `--config` option

**Example configuration (Claude Code):**

```jsonc
{
  // Command to analyze dependencies and select next change
  "analyze_command": "claude --dangerously-skip-permissions --verbose --output-format stream-json -p '{prompt}'",

  // Command to apply a change (supports {change_id} and {prompt} placeholders)
  "apply_command": "claude --dangerously-skip-permissions --verbose --output-format stream-json -p '/openspec:apply {change_id} {prompt}'",

  // Command to run acceptance tests after apply (supports {change_id} and {prompt} placeholders)
  "acceptance_command": "claude --dangerously-skip-permissions --verbose --output-format stream-json -p '/openspec:accept {change_id} {prompt}'",

  // Command to archive a completed change (supports {change_id} and {prompt} placeholders)
  "archive_command": "claude --dangerously-skip-permissions --verbose --output-format stream-json -p '/openspec:archive {change_id} {prompt}'",

  // Command to resolve merge conflicts (supports {prompt} placeholder)
  "resolve_command": "claude --dangerously-skip-permissions --verbose --output-format stream-json -p '{prompt}'",

  // System prompt for apply command (injected into {prompt} placeholder)
  "apply_prompt": "スコープ外タスクは削除せよ。ユーザを待つもしくはユーザによるタスクは削除せよ。",

  // System prompt for acceptance command (injected into {prompt} placeholder)
  "acceptance_prompt": "",

  // Controls how the acceptance {prompt} is constructed
  // - "full": include hardcoded acceptance system prompt + diff/history context (default)
  // - "context_only": only include change metadata + diff/history context
  // Use "context_only" when your acceptance_command uses a command template with fixed instructions
  "acceptance_prompt_mode": "full",

  // Maximum number of acceptance CONTINUE retries before treating as FAIL (default: 10)
  "acceptance_max_continues": 10,

  // System prompt for archive command (injected into {prompt} placeholder)
  "archive_prompt": "",

  // Command to create a proposal worktree from TUI (+ key)
  // Supports {workspace_dir} and {repo_root} placeholders
  "worktree_command": "claude --dangerously-skip-permissions --verbose -p '/openspec:proposal --worktree {workspace_dir}'",

  // Lifecycle hooks (optional)
  "hooks": {
    // "pre_apply": "echo 'Starting {change_id}'",
    // "post_apply": "echo 'Completed {change_id}'"
  }
}
```

**Logging configuration:**

```jsonc
{
  "logging": {
    "suppress_repetitive_debug": true,
    "summary_interval_secs": 60
  }
}
```

- `suppress_repetitive_debug`: suppress repeated debug logs when state is unchanged (default: true)
- `summary_interval_secs`: emit summary logs every N seconds, set to 0 to disable (default: 60)

**Placeholders:**

| Placeholder | Description | Used in |
|-------------|-------------|---------|
| `{change_id}` | The change ID being processed | apply_command, acceptance_command, archive_command |
| `{prompt}` | System prompt for agent commands | apply_command, acceptance_command, archive_command, resolve_command, analyze_command |
| `{workspace_dir}` | New worktree path for proposals | worktree_command |
| `{repo_root}` | Repository root path | worktree_command |

**System Prompts:**

| Config Key | Description | Default |
|------------|-------------|---------|
| `apply_prompt` | Prompt injected into apply_command's `{prompt}` | (includes path context) |
| `acceptance_prompt` | Prompt injected into acceptance_command's `{prompt}` | (empty) |
| `archive_prompt` | Prompt injected into archive_command's `{prompt}` | (empty) |

**Quick start:**

```bash
# Generate configuration with init command
cflx init

# Or copy the example configuration
cp .cflx.jsonc.example .cflx.jsonc

# Edit to customize settings
vim .cflx.jsonc

# Run with the configuration
cflx
```

### Hooks Configuration

You can configure hooks to run commands at various stages of the orchestration process.
Hooks are defined in the `hooks` section of the configuration file.

```jsonc
{
  "hooks": {
    // Simple string format (uses default settings)
    "on_start": "echo 'Orchestrator started'",

    // Object format (with detailed settings)
    "post_apply": {
      "command": "cargo test",
      "continue_on_failure": false,  // Stop orchestration if command fails
      "timeout": 300                 // Timeout in seconds
    },

    // Run lifecycle hooks
    "on_start": "echo 'Starting orchestration with {total_changes} changes'",
    "on_finish": "echo 'Finished with status: {status}'",
    "on_error": "echo 'Error in {change_id}: {error}' >> errors.log",

    // Change lifecycle hooks
    "on_change_start": "echo 'Starting {change_id}'",
    "pre_apply": "echo 'Applying {change_id} (attempt {apply_count})'",
    "post_apply": "cargo test",
    "on_change_complete": "echo '{change_id} is 100% complete'",
    "pre_archive": "cargo clippy -- -D warnings",
    "post_archive": "echo '{change_id} archived successfully'",
    "on_change_end": "echo 'Finished processing {change_id}'",

    // TUI-only hooks (user interaction)
    "on_queue_add": "echo 'Added {change_id} to queue'",
    "on_queue_remove": "echo 'Removed {change_id} from queue'"
  }
}
```

**Available Hooks:**

*Run lifecycle hooks:*

| Hook Name | Trigger | Description |
|-----------|---------|-------------|
| `on_start` | Start | Orchestrator starts |
| `on_finish` | Finish | Orchestrator completes (success or limit) |
| `on_error` | Error | When an error occurs during apply or archive |

*Change lifecycle hooks:*

| Hook Name | Trigger | Description |
|-----------|---------|-------------|
| `on_change_start` | Change Start | When processing begins for a new change |
| `pre_apply` | Before Apply | Before applying a change |
| `post_apply` | After Apply | After successfully applying a change |
| `on_change_complete` | Task 100% | When a change reaches 100% task completion |
| `pre_archive` | Before Archive | Before archiving a change |
| `post_archive` | After Archive | After successfully archiving a change |
| `on_change_end` | Change End | After a change is successfully archived |

*TUI-only hooks (user interaction):*

| Hook Name | Trigger | Description |
|-----------|---------|-------------|
| `on_queue_add` | Queue Add | When user adds a change to queue (Space key) |
| `on_queue_remove` | Queue Remove | When user removes a change from queue (Space key) |

**Placeholders:**

| Placeholder | Description |
|-------------|-------------|
| `{change_id}` | Current Change ID |
| `{changes_processed}` | Number of changes processed so far |
| `{total_changes}` | Total number of changes in initial snapshot |
| `{remaining_changes}` | Remaining changes in queue |
| `{apply_count}` | Number of apply attempts for current change |
| `{completed_tasks}` | Number of completed tasks for current change |
| `{total_tasks}` | Total number of tasks for current change |
| `{status}` | Finish status (completed/iteration_limit) |
| `{error}` | Error message |

**Environment Variables:**

Hooks receive context via environment variables:
`OPENSPEC_CHANGE_ID`, `OPENSPEC_CHANGES_PROCESSED`, `OPENSPEC_TOTAL_CHANGES`, `OPENSPEC_REMAINING_CHANGES`, `OPENSPEC_APPLY_COUNT`, `OPENSPEC_COMPLETED_TASKS`, `OPENSPEC_TOTAL_TASKS`, `OPENSPEC_STATUS`, `OPENSPEC_ERROR`, `OPENSPEC_DRY_RUN`

### Environment Variables

| Variable | Description | Default |
|----------|-------------|---------|
| `OPENSPEC_CMD` | OpenSpec command (can include arguments) | `npx @fission-ai/openspec@latest` |
| `RUST_LOG` | Logging level | (none) |

Example:

```bash
# Use a custom openspec installation
export OPENSPEC_CMD="/usr/local/bin/openspec"
cflx

# Use a specific version via npx
export OPENSPEC_CMD="npx @fission-ai/openspec@1.2.3"
cflx
```

### Command-line Options

```
Usage: cflx [OPTIONS] [COMMAND]

Commands:
  run              Run the OpenSpec change orchestration loop (non-interactive)
  tui              Launch the interactive TUI dashboard
  init             Initialize a new configuration file
  check-conflicts  Check for conflicts between spec delta files across changes
  server           Start the multi-project server daemon
  service          Manage `cflx server` as a background service

Options:
  -c, --config <PATH>          Path to custom configuration file (JSONC format)
  --web                        Enable web monitoring server for remote status viewing
  --web-port <PORT>            Port for web monitoring server (default: 0 = auto-assign by OS)
  --web-bind <ADDR>            Bind address for web monitoring server (default: 127.0.0.1)
  --server <URL>               Connect TUI to a remote Conflux server (e.g., http://host:39876)
  --server-token <TOKEN>       Bearer token for remote server authentication
  --server-token-env <VAR>     Environment variable holding the bearer token
  -h, --help                   Print help
  -V, --version                Print version
```

**Run subcommand options:**
```
Options:
  --change <ID,...>         Process only specified changes (comma-separated)
  -c, --config <PATH>       Custom configuration file path (JSONC)
  --parallel                Enable parallel execution mode
  --max-concurrent <N>      Maximum concurrent workspaces (default: 3)
  --vcs <BACKEND>           VCS backend: auto or git (default: auto)
  --no-resume               Disable workspace resume (always create new workspaces)
  --dry-run                 Preview parallelization groups without executing
  --max-iterations <N>      Maximum number of orchestration loop iterations (0 = no limit)
  --web                     Enable web monitoring server
  --web-port <PORT>         Web server port (default: 0 = auto-assign by OS)
  --web-bind <ADDR>         Web server bind address (default: 127.0.0.1)
```

**TUI options:**

The TUI (default mode, `cflx` or `cflx tui`) also supports web monitoring options:

```bash
# TUI with web monitoring
cflx --web

# Custom port and bind address
cflx --web --web-port 9000 --web-bind 0.0.0.0
```

### Parallel Execution

The orchestrator supports parallel execution of independent changes using Git worktrees.

**VCS Backend Selection:**

| Backend | Description | Requirements |
|---------|-------------|--------------|
| `auto` | Auto-detect Git repository | Git repository with clean working directory |
| `git` | Use Git worktrees | Git repository with clean working directory |

**Usage:**

```bash
# Auto-detect VCS backend (default)
cflx run --parallel

# Force Git worktrees
cflx run --parallel --vcs git

# Preview parallelization groups without executing
cflx run --parallel --dry-run

# Limit concurrent workspaces
cflx run --parallel --max-concurrent 5
```

**Configuration:**

You can also set the VCS backend in your configuration file:

```jsonc
{
  // VCS backend for parallel execution: "auto" or "git"
  "vcs_backend": "auto",

  // Maximum concurrent workspaces
  "max_concurrent_workspaces": 3
}
```

**Git Requirements:**

When using Git worktrees:
- Working directory must be clean (no uncommitted changes)
- Each change runs in an isolated worktree with its own branch
- Changes are merged back sequentially after completion

**Workspace Resume:**

By default, the orchestrator automatically detects and reuses existing workspaces from interrupted runs. This allows you to resume work from where you left off without losing progress.

- When a workspace is found for a change ID, it is reused instead of creating a new one
- If multiple workspaces exist for the same change, the newest one is used and older ones are cleaned up
- Use `--no-resume` to disable this behavior and always create fresh workspaces

```bash
# Resume from existing workspaces (default behavior)
cflx run --parallel

# Always create new workspaces (discard any existing work)
cflx run --parallel --no-resume
```

**Workspace State Detection (Idempotent Resume):**

The orchestrator detects the current state of each workspace to ensure idempotent execution. When resuming, workspaces are classified into one of five states:

| State | Description | Action Taken |
|-------|-------------|--------------|
| **Created** | New workspace, no commits yet | Start apply from beginning |
| **Applying** | WIP commits exist, apply in progress | Resume apply from next iteration |
| **Applied** | Apply complete (`Apply: <change_id>` commit exists) | Skip apply, run archive only |
| **Archived** | Archive complete (`Archive: <change_id>` commit exists) | Skip apply/archive, run merge only |
| **Merged** | Already merged to main branch | Skip all operations, cleanup workspace |

This state detection ensures that:
- Running the orchestrator multiple times on the same workspace is safe and produces the same result (idempotency)
- Manually archived or merged changes are detected and handled correctly
- Interrupted operations resume from the correct step
- No duplicate work is performed

**State Detection Examples:**

```bash
# Interrupted during apply - resumes from where it left off
$ cflx run --parallel
# Workspace state: Applying (iteration 3/5)
# Action: Resume apply from iteration 4

# Manually archived a change - skips apply/archive
$ cflx run --parallel
# Workspace state: Archived
# Action: Skip apply/archive, merge to main only

# Already merged to main - cleanup only
$ cflx run --parallel
# Workspace state: Merged
# Action: Skip all operations, cleanup workspace
```

### Command Execution Queue

The orchestrator includes a command execution queue that prevents resource conflicts and handles transient errors when running multiple AI agent commands in parallel.

**Features:**

1. **Staggered Start**: Commands are started with a configurable delay to prevent simultaneous resource access
2. **Automatic Retry**: Commands that fail due to transient errors (module resolution, network issues, etc.) are automatically retried

**Configuration:**

```jsonc
{
  // Delay between command executions (milliseconds)
  // Default: 2000 (2 seconds)
  "command_queue_stagger_delay_ms": 2000,

  // Maximum number of retries for failed commands
  // Default: 2
  "command_queue_max_retries": 2,

  // Delay between retries (milliseconds)
  // Default: 5000 (5 seconds)
  "command_queue_retry_delay_ms": 5000,

  // Retry if execution duration is under this threshold (seconds)
  // Short-running failures often indicate environment/startup issues
  // Default: 5
  "command_queue_retry_if_duration_under_secs": 5,

  // Error patterns that trigger automatic retry (regex)
  // Default: module resolution, registry, and lock errors
  "command_queue_retry_patterns": [
    "Cannot find module",
    "ResolveMessage:",
    "ENOTFOUND registry\\.npmjs\\.org",
    "ETIMEDOUT.*registry",
    "EBADF.*lock",
    "Lock acquisition failed"
  ]
}
```

**How It Works:**

- **Staggered Start**: Each command waits for a minimum delay since the last command started, preventing simultaneous access to shared resources (e.g., `~/.cache/opencode/node_modules`)
- **Retry Logic**: Commands are retried if they:
  - Match a configured error pattern (e.g., "Cannot find module"), OR
  - Exit quickly (< 5 seconds by default), indicating a startup/environment issue
- **No Retry**: Commands that run for a long time (> 5 seconds) and don't match error patterns are not retried, as they likely failed due to logical errors

**Example - Preventing Module Resolution Conflicts:**

```bash
# Without queue: Multiple commands start simultaneously
# → Conflict: All try to update node_modules at once
# → Result: "Cannot find module" errors

# With queue (default): Commands start 2 seconds apart
# → First command updates node_modules
# → Subsequent commands use stable environment
# → Result: No conflicts
```

**Example - Handling Transient Network Errors:**

```bash
# Error: ETIMEDOUT registry.npmjs.org
# → Matches retry pattern
# → Automatically retried after 5 seconds
# → Usually succeeds on retry
```

### Web Monitoring

The orchestrator supports an optional HTTP server for remote monitoring of orchestration progress via web browser.

**Usage:**

```bash
# Enable web monitoring with TUI (OS auto-assigns an available port)
cflx --web

# Custom port and bind address
cflx --web --web-port 9000 --web-bind 0.0.0.0

# With headless run mode
cflx run --web
```

When using the default port (0), the OS automatically assigns an available port.
The actual bound address is logged when the server starts.

**Features:**

- **Dashboard UI**: View progress at `http://localhost:8080/`
- **Real-time updates**: WebSocket connection for live progress updates
- **REST API**: Query state programmatically
- **QR Code Popup**: Press `w` in the TUI to display a QR code for quick mobile access to the dashboard

**REST API Endpoints:**

| Endpoint | Method | Description |
|----------|--------|-------------|
| `/api/health` | GET | Health check |
| `/api/state` | GET | Full orchestrator state |
| `/api/changes` | GET | List all changes with progress |
| `/api/changes/{id}` | GET | Details for a specific change |

For complete API specifications, see the [OpenAPI documentation](docs/openapi.yaml).

**WebSocket:**

Connect to `ws://localhost:8080/ws` for real-time state updates. Messages are JSON with the following format:

```json
{
  "type": "state_update",
  "timestamp": "2024-01-12T10:30:00Z",
  "changes": [
    {
      "id": "add-feature",
      "completed_tasks": 3,
      "total_tasks": 10,
      "progress_percent": 30.0,
      "status": "in_progress"
    }
  ]
}
```

**Dashboard Overview:**

The web dashboard provides a visual overview of orchestration progress:

```
┌─────────────────────────────────────────────────────────────────┐
│  OpenSpec Orchestrator                           ● Connected    │
├─────────────────────────────────────────────────────────────────┤
│  ┌─────────┐  ┌─────────┐  ┌─────────┐  ┌─────────┐            │
│  │    5    │  │    2    │  │    1    │  │    2    │            │
│  │  Total  │  │Complete │  │Progress │  │ Pending │            │
│  └─────────┘  └─────────┘  └─────────┘  └─────────┘            │
├─────────────────────────────────────────────────────────────────┤
│                                                                 │
│  ┌─────────────────────────────────────────────────────────┐   │
│  │ add-feature-auth                    [IN_PROGRESS]           │
│  │ ████████████████░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░  40%    │   │
│  │ 4/10 tasks                                               │   │
│  └─────────────────────────────────────────────────────────┘   │
│                                                                 │
│  ┌─────────────────────────────────────────────────────────┐   │
│  │ fix-login-bug                       [COMPLETE]              │
│  │ ████████████████████████████████████████████████  100%  │   │
│  │ 5/5 tasks                                                │   │
│  └─────────────────────────────────────────────────────────┘   │
│                                                                 │
│  ┌─────────────────────────────────────────────────────────┐   │
│  │ refactor-api                        [PENDING]               │
│  │ ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░  0%    │   │
│  │ 0/8 tasks                                                │   │
│  └─────────────────────────────────────────────────────────┘   │
│                                                                 │
├─────────────────────────────────────────────────────────────────┤
│  Last updated: 2024-01-12 10:30:00                              │
└─────────────────────────────────────────────────────────────────┘
```

**Dashboard Features:**

- **Stats Bar**: Shows total, completed, in-progress, and pending change counts
- **Change Cards**: Each change displays ID, progress status, and progress bar
- **Real-time Updates**: Progress updates automatically via WebSocket connection
- **Connection Status**: Shows current WebSocket connection state (Connected/Disconnected)
- **Responsive Design**: Works on desktop and mobile browsers

**Web Monitoring Troubleshooting:**

| Issue | Solution |
|-------|----------|
| "Address already in use" | Use `--web-port 0` (default) to let the OS auto-assign an available port, or specify a specific unused port |
| Dashboard not loading | Ensure `--web` flag is enabled. Verify the URL includes the correct port |
| WebSocket disconnects frequently | Check network stability. The dashboard auto-reconnects on disconnection |
| Changes not updating | Refresh the page or check that the orchestrator is actively processing |
| Cannot access from another device | Use `--web-bind 0.0.0.0` to allow external connections (local network only) |
| CORS errors in browser console | This is normal for cross-origin requests; the server handles CORS headers |

### Background Service

Use `cflx service` to install and manage `cflx server` as a user-level background service.

- macOS: `launchd` user agent
- Linux: `systemd --user` service
- Windows: Scheduled Task

```
cflx service <install|uninstall|status|start|stop|restart>
```

Examples:

```bash
# Install and enable the service
cflx service install

# Start or restart the background server
cflx service start
cflx service restart

# Check service status
cflx service status

# Stop or remove the service
cflx service stop
cflx service uninstall
```

Notes:

- `install`, `start`, and `restart` validate the effective global `server` configuration before touching the service manager.
- macOS writes a plist under `~/Library/LaunchAgents/com.conflux.cflx-server.plist`.
- Linux writes a unit file under `~/.config/systemd/user/cflx-server.service`.
- Configure persistent server settings in your global config file before installing, for example `~/.config/cflx/config.jsonc`.

**Init subcommand options:**
```
Options:
  -t, --template <TEMPLATE>  Template to use [default: claude] [possible values: claude, opencode, codex]
  -f, --force                Overwrite existing configuration file
```

**Check-conflicts subcommand options:**
```
Options:
  -j, --json  Output results in JSON format
```

**Install-skills subcommand:**

Install bundled agent skills from the repository's `skills/` directory into the standard `.agents/skills` location.

```
cflx install-skills [--global]
```

Options:
```
  --global  Install into global scope (~/.agents/skills) instead of project scope (./.agents/skills)
```

Examples:
```bash
# Install bundled skills (project scope -> ./.agents/skills)
cflx install-skills

# Install bundled skills (global scope -> ~/.agents/skills)
cflx install-skills --global
```

Skills are discovered from the repository's top-level `skills/` directory. Each skill must have a `SKILL.md` file with `name` and `description` frontmatter fields. A lock file (`.agents/.skill-lock.json` or `~/.agents/.skill-lock.json`) is updated after each install to track installed skill versions.

Priority: CLI argument > Environment variable > Default value

## Error Handling

| Error | Behavior |
|-------|----------|
| Agent command fails | Retry 3 times, then mark as failed |
| Apply command fails | Mark change as failed, continue with others |
| Archive command fails | Mark change as failed, continue with others |
| LLM analysis fails | Fall back to progress-based selection |
| All changes fail | Exit with error |

## Troubleshooting

### "No changes found"

- Run `openspec list` to verify changes exist
- Check that you're in the correct directory

### "Agent command failed"

- Verify your AI agent is installed (e.g., `which claude`)
- Test manually: `claude -p "echo test"`
- Check your configuration file: `.cflx.jsonc`

### "All changes failed"

- Check logs for specific errors
- Try processing a single change: `--change <id>`

## Installation

```bash
cargo install cflx
```

This will build and install the orchestrator to your Cargo bin directory (typically `~/.cargo/bin`).

## Documentation

| Document | Description |
|----------|-------------|
| [Usage Examples]docs/guides/USAGE.md | Quick start and usage examples |
| [Contributing Guide]CONTRIBUTING.md | Local development setup and contributor workflow |
| [Development Guide]docs/guides/DEVELOPMENT.md | Build instructions and project structure |
| [Release Guide]docs/guides/RELEASE.md | How to create releases |
| [API Specification]docs/openapi.yaml | OpenAPI spec for web monitoring |

Internal documentation (parallel execution audit) is available in `docs/audit/`.

## Future Enhancements

- [ ] State persistence for recovery and resumption
- [x] Parallel execution for independent changes (using Git worktrees)
- [ ] Slack/Discord notifications
- [ ] Maximum iteration limit (prevent infinite loops)
- [ ] Manual priority override
- [ ] Enhanced dry-run with execution plan
- [ ] Web UI for monitoring

## License

MIT

## Contributing

Contributions are welcome. See [CONTRIBUTING.md](CONTRIBUTING.md) for local setup, Git hooks, and repository structure.