@mhd-ghaith-abtah/flow 0.7.2-beta.0 → 0.8.0-beta.1

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/CHANGELOG.md CHANGED
@@ -6,6 +6,58 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
6
6
 
7
7
  ## [Unreleased]
8
8
 
9
+ ## [0.8.0-beta.1] — 2026-05-23
10
+
11
+ ### Added
12
+ - **`flow install-skills` command** — closes the bootstrap gap between npm install and Claude Code slash command discovery. After `npm install -g @mhd-ghaith-abtah/flow@beta`, run `flow install-skills` to symlink the four `skills/flow-*` directories into `~/.claude/skills/` (or `<project>/.claude/skills/` with `--scope project` for the team-commit pattern; `--scope both` for both). Idempotent (skips already-correctly-linked targets); refuses to clobber real directories at the target without `--force`; replaces wrong-source symlinks silently. 9 new tests covering home/project/both scopes, refusal-without-force, force-replace, dry-run, idempotent re-run, and wrong-source-symlink replacement. README + docs/usage.md updated with the corrected bootstrap order (`npm install -g` → `flow install-skills` → `/flow-init`).
13
+
14
+ ## [0.8.0-beta.0] — 2026-05-23
15
+
16
+ ### Added
17
+ - **E6-006 — `flow init --yes` headless orchestrator + integration tests** — closes E6. `lib/init/orchestrate.js` chains `detect()` → `askAll()` (pre-populated answers short-circuit each prompt) → upstream dispatchers (bmad → ecc → caveman, halt-on-error by default, `--continue-on-error` to override) → MCP registration → optional BMad migration → `scaffold()` (writes `flow.config.yaml` + `docs/flow/{stories,journeys,retros,archive}` + `sprint.yaml` + `deferred.md` + `install-state.json`). `lib/init/scaffold.js` exports pure `buildFlowConfig(plan)` and `scaffold(plan, opts)` with `--force` overwrite + skip-existing semantics; `defaultAnswersForProfile(catalog, profile, overrides)` resolves a profile into a complete Answers object so non-interactive callers (CI, tests) drive the full chain without firing any prompt. `lib/commands/init.js` rewritten: outside Claude Code with `--yes` → runs the orchestrator end-to-end and prints a manifest; outside Claude Code without `--yes` → prints both paths (headless vs slash-command); inside Claude Code → nudges to `/flow-init` slash command (skill workflow still owns the interactive ceremony per ROADMAP principle #6). README install section updated with the new headless flow. 13 new tests across orchestrate (chain logic, scope override threading, BMad migration trigger) + scaffold (file content shape, force/skip behavior, dryRun manifest); orchestrate tests deliberately stay `dryRun: true` to avoid shelling out (each upstream dispatcher would otherwise `npx`-fetch real network packages). 156/156 pass (was 143, +13).
18
+
19
+ ### Added
20
+ - **E6-005 — `flow sprint <subcommand>` CLI** — pure-YAML headless port of the non-LLM `/flow-sprint` subcommands. Six subcommands wired: `add` (append a story with explicit id/title/epic + optional tags/why/issue/status), `next` (flip first backlog story to doing, stamp `started_at`), `status` (grouped-by-epic render with per-epic and overall counts; `--json` for scriptable output), `done <id>` (flip to done, stamp `completed_at`, append `--note` to notes array; refuses non-review/doing sources without `--force`), `deferred` (parse + render `docs/flow/deferred.md`), `import-bmad` (wraps `migrate-bmad.js` — same backup/rollback semantics). Round-trip preservation: `lib/sprint/store.js` uses yaml's Document API rather than parse+stringify so comments + ordering survive each mutation. Operations live in `lib/sprint/operations.js` as pure functions (addStory, nextStory, setStatus, summarize, parseDeferred); `lib/commands/sprint.js` is the thin CLI shell on top. Wired into `bin/flow.js` USAGE + dispatch + yargs string/boolean lists (new flags: `--id`, `--title`, `--epic`, `--tags`, `--why`, `--issue`, `--note`, `--project`, `--status`, `--force`). LLM-driven `retro` and `scope-review` stay slash-command-only per ROADMAP principle #6 (one source of truth per behavior). 21 new tests (143/143 pass) covering happy paths, duplicate-id rejection, unknown-epic rejection, missing-field validation, --force semantics, note appending, round-trip comment preservation, --epic restriction for next, orphan-epic bucket in summarize, and parseDeferred open-vs-resolved separation.
21
+
22
+ ### Added
23
+ - **E6-004 — `lib/init/migrate-bmad.js` BMad → Flow migration** — headless port of `/flow-init` step 11. Public surface: `findBmadState(cwd)`, `parseBmadStories(yaml)`, `parseBmadDeferred(md)`, `backupBmadState(state, ts)`, `migrate(cwd, opts)`, `rollback(cwd, ts)`. Migration writes `docs/flow/sprint.yaml` + per-story stubs under `docs/flow/stories/` + `docs/flow/deferred.md`. Backup-first: every source file gets a `.flow-backup-<ts>` copy before any write; if backup fails, halt before any mutation; if parse/write fails, automatic rollback restores backups + removes the produced `docs/flow/` tree (only when it didn't pre-exist — pre-existing Flow content survives rollback via a sentinel-file check). BMad status → Flow status mapping (`in-progress → doing`, `ready-for-dev → backlog`, etc.) with backlog as the unknown-value fallback so migration is non-lossy. Handles both flat-map and nested `stories:` shapes in BMad's sprint-status. `_bmad/` is intentionally left in place so BMad slash commands keep working post-migration. 15 new tests covering parse edge cases (nested shape, unknown statuses, non-story keys), backup creation, end-to-end migration with stub generation + status mapping verification, malformed-input rollback path, and pre-existing-docs/flow preservation. 122/122 pass.
24
+
25
+ ### Added
26
+ - **E6-003 — `lib/init/mcp.js` MCP dispatcher** — headless port of `/flow-init` step 9. Exports `buildCommand(mcp)` (pure), `isInstalled(mcp, opts)` (probes `claude mcp list`), `install(mcp, opts)`, `installAll(mcps, opts)`, `resolveMcps(catalog, ids)`. Idempotent by default: skips MCPs that already appear in `claude mcp list` unless `force=true`. Auth handling stays out of the dispatcher — it surfaces `requiredEnv` (for `api_token` MCPs) and `authInstructions` (for `oauth_browser`) in the result so the orchestrator can route secrets to whatever store the user picked at Q9, and `flow doctor` can reuse the same module to report MCP state without touching secrets. State record carries `auth`, `scope`, and `auth_state: 'pending'` for oauth flows so doctor knows when an MCP isn't usable yet. 8 new tests covering tokenization, resolveMcps unknown-id throw, auth=none / oauth_browser / api_token paths, and installAll sequencing. 107/107 pass.
27
+
28
+ ### Added
29
+ - **E6-002 — `lib/init/upstreams/{bmad,ecc,caveman}.js` + `common.js` dispatchers** — pure `buildCommand(plan)` + async `install(plan, opts)` for each upstream. BMad assembles `npx bmad-method install --tools claude-code --yes --modules a,b,c` from the curated subset. ECC resolves an `installer_path` from local candidates first then falls back to the github-pinned `npx -y -p "github:affaan-m/ECC#98bd5174" ecc-install`; routes `--target` via the E7-003 `target_by_scope` map (`user → claude`, `project → claude-project`). Caveman runs the fork-pinned `npx -y "github:mhd-ghaith-abtah/caveman#flow-pin-v0.1"` and honors `FLOW_INSPECT_INSTALL_SCRIPTS=1` by halting before execution (returns `inspect_only: true` in the state record + a hint at how to review the fork). All three short-circuit on `subset === 'none'` so the orchestrator can call them uniformly. State records include `install_scope` (ECC), `fork_tag` + `upstream_pr` (Caveman), and `modules` (BMad) so `flow doctor` can read them. 18 new tests cover command shape, target routing, `--with`/`--without` plumbing, missing-target throw, inspect-only skip path, and `subset=none` no-op. 99/99 pass.
30
+
31
+ ### Added
32
+ - **E6-001 — `lib/init/detect.js` + `lib/init/questions.js` + `lib/init/recommendation.js`** — port of the `/flow-init` skill workflow's project-detection and Q&A primitives into pure Node modules. `detect()` returns a typed `Detection` (git root, package manager, primary stack, framework, BMad/ECC/Caveman presence with versions, existing MCPs, available CLIs, flow-already-configured). `recommendProfile(detection)` picks one of `minimal | mini | standard | team` from the detected shape with a one-line reason. `questions.js` exports `askProfile`, `askIssueTracker`, `askPr`, `askE2e`, `askVerify`, `askBmadSubset`, `askEccSubset`, `askEccScope`, `askCavemanSubset`, `askMigrateBmad`, `askSecretsStore`, and `askAll` (composed flow). All prompts use `@inquirer/prompts` and short-circuit on pre-populated answers so `--yes`-style zero-question installs can drive the same code path. 19 new tests covering detection edge cases (bare dir, lockfile variants, framework, CLAUDE.md, ECC user-scope + project-scope + collision, BMad version parse, Caveman plugin-cache + legacy hook detection) and the recommendation decision tree. Tests 81/81 pass (was 62). Foundation for E6-002 → E6-006.
33
+
34
+ ### Added
35
+ - **E7-004 — `flow doctor` probe for ECC scope collision** — new `Collisions` section in the doctor report. Detects when ECC content exists at BOTH `~/.claude/rules/ecc` and `<cwd>/.claude/rules/ecc` (the scenario where a user switched `--ecc-scope` without uninstalling the prior scope's content). Severity `⚠` (exit 1) because both scopes loading the same skill set into Claude Code at once is confusing and skill-resolution order is undefined. The fix-hint reads `install_scope` from `install-state.json` to identify which directory is the *active* one and suggests `rm -rf <stale_dir>`; falls back to a "set the scope first via /flow-init or --ecc-scope, then clean up" message when no scope is recorded. Cheap probe (two `existsSync` calls), runs on every `flow doctor`. 3 new tests covering collision-detected / no-collision / unknown-scope hint. 62/62 pass.
36
+
37
+ ### Changed
38
+ - **E7-005 — Profiles + README documented for the ECC scope option** — `docs/profiles.md` gained an "ECC scope" column in the at-a-glance table, a per-profile `ECC install scope` line under each profile (`user` for mini/standard/minimal/default, `project` for team), and a new "ECC install scope" section explaining the 3-layer resolution (catalog default → profile → `--ecc-scope` CLI override). README FAQ caveat updated to describe shipped behavior (was: "ships in v0.8 once E7-002 → E7-005 land"; now: "team defaults to project, others to user, override via `--ecc-scope`"). E7 epic body of work (E7-001 upstream PR + E7-002 catalog plumbing + E7-002.5 CLI flag + E7-003 install consumer + E7-005 docs) now ends.
39
+
40
+ ### Added
41
+ - **E7-003 — Install path consumes the scope flag** — `catalog.yaml > upstreams.ecc.installer` gained `target_arg` + `target_by_scope` (`user → claude`, `project → claude-project`). `base_args` is now scope-agnostic (was `--target claude` hardcoded). `/flow-init` skill workflow updated to compose the install command from `target_arg` + `target_by_scope[ecc_install_scope]` and record `install_scope` + `target` in install-state. `flow doctor --repair-upstream ecc` now reads the recorded scope and emits the right install command (project-scope users get `--target claude-project` + `<projectRoot>/.claude/rules` paths; user-scope unchanged). Also fixed the doctor command's stale `npx @everything-claude-code/ecc install --target claude` reference — same bug as the catalog `cmd_fallback` typo, now resolved by reusing the post-merge github pin. 1 new test for project-scope routing; existing test extended with scope assertion. 59/59 pass.
42
+ - **`--ecc-scope <user|project>` CLI flag** — explicit override on top of the profile default for `flow plan` and `flow install`. Lets users pick a non-default scope without authoring a new profile (e.g. `flow install --profile team --ecc-scope user` or `flow plan --profile mini --ecc-scope project`). Throws on invalid value so typos like `--ecc-scope=projet` fail loud instead of silently falling through to the profile default. 4 new tests covering override directions + typo guard.
43
+ - **E7-002 — Catalog `ecc_install_scope` plumbing** — `upstreams.ecc.install_scope_default` (defaults to `user`) and per-profile `ecc_install_scope` (`user|project`) flow through `resolveProfile` so the resolved profile exposes the scope to downstream consumers. `team` profile now declares `ecc_install_scope: project`; `minimal`/`mini`/`standard` inherit `user`. `flow plan` surfaces the scope next to the ECC subset (e.g. `ECC: flow-essentials-plus-tdd (scope: project)`). Schema + JSDoc updated. Data plumbing only — E7-003 will consume the field to swap `--target claude` → `--target claude-project` at install time. 3 new tests (54/54 pass).
44
+
45
+ ### Changed
46
+ - **ECC installer pinned to post-merge github commit** — `catalog.yaml` ECC `cmd_fallback` now `npx -y -p "github:affaan-m/ECC#98bd5174" ecc-install` (was a broken `npx @everything-claude-code/ecc install` reference — wrong package name, returned 404). The pin targets the merge commit of affaan-m/ECC#2006 (`claude-project` install target) so Flow can route the team profile to project-scope ECC. ECC npm `latest` is currently `ecc-universal@1.10.0` (2026-04-15), which predates the merge by ~36 days, so the npm package would NOT have the target. New catalog fields: `upstream_npm_package`, `upstream_npm_latest`, `upstream_npm_status`, `pinned_commit`. Will swap back to `npx ecc-universal install` once affaan-m cuts a `2.x` release. Also fixed stale `installer_path_candidates` entries (removed a global-npm path that referenced the bogus package name; added `~/development/personal/ecc-fork/install.sh` for contributors with a local clone). README FAQ updated with the distribution caveat.
47
+ - **Caveman installer swapped to a temporary fork pin** — `catalog.yaml` Caveman `installer.cmd` now `npx -y "github:mhd-ghaith-abtah/caveman#flow-pin-v0.1"` (was upstream curl-pipe-bash). The fork carries the project-scope gating patches from JuliusBrussee/caveman#407 applied on top of upstream `main`. Reason: upstream Caveman has a ~134-PR backlog with ~5 merges/month, so waiting for #407 to land would block Flow's team profile for months. The fork is documented as temporary in `catalog.yaml` (new fields: `upstream_repo`, `upstream_pr`, `fork_status`) with an explicit swap-back plan. Doctor probe shows the fork status so users know when upstream merges. README updates the FAQ + "Upstream contributions" section to reflect the conditional compose-vs-fork strategy.
48
+
49
+ ### Added
50
+ - **Upstream ECC PR merged** — [affaan-m/ECC#2006](https://github.com/affaan-m/ECC/pull/2006) adds a `claude-project` install target (project-scope ECC), symmetric with the existing user-scope `claude` target. Closes the install-target matrix for Claude Code (now 7 project-scope + 4 home-scope adapters) and removes the need for Flow's `HOME=$PROJECT/.flow-vendor` shim. Closes E7-001. Unblocks E7-002 → E7-005 (catalog scope flag, init wiring, doctor probe, docs).
51
+ - **Flow published to npm** as [`@mhd-ghaith-abtah/flow@0.7.2-beta.0`](https://www.npmjs.com/package/@mhd-ghaith-abtah/flow). End-to-end smoke clean: local install, global install (`flow` on PATH), `npx -y @mhd-ghaith-abtah/flow@beta`, all four profiles resolve, `flow doctor` probes catalog + state + adapters + upstreams. 78 transitive deps, 81 kB tarball. Closes E1-002 (the last open BLOCKING story from the v0.6.1 review handoff).
52
+
53
+ ### Changed
54
+ - README gained an FAQ entry on per-project ECC installs (via the merged `claude-project` target) and a new "Upstream contributions" subsection under Credits listing ECC #2006 (merged) and Caveman #407 (in review).
55
+ - README Install section refreshed for the npm publish — now shows four paths (`/flow-init` slash command, `npm install -g @mhd-ghaith-abtah/flow@beta`, `npx -y @mhd-ghaith-abtah/flow@beta`, clone for development). Status block updated from "not yet published" to "published as beta, soaking before latest promotion".
56
+
57
+ ### Added
58
+ - `ROADMAP.md` — multi-epic arc through v0.7.x (stabilize) → v0.8 (npx-first + ECC project-scope) → v0.9 (multi-agent) → v1.0 (stable). Explicit out-of-scope guardrails (no multi-repo orchestration, no SaaS, no LLM provider abstraction, etc.). Decision log appended as design calls land. Linked from README FAQ.
59
+ - Sprint backlog gained 24 forward-looking stories under new epics E6 (npx-first install), E7 (ECC project-scope), E8 (multi-agent, demand-gated), E9 (beta soak). E7-001 (ECC upstream PR) is marked `ready` — next actionable item.
60
+
9
61
  ## [0.7.2-beta.0] — 2026-05-19
10
62
 
11
63
  ### Changed
package/README.md CHANGED
@@ -20,19 +20,31 @@ Existing per-story workflows are token-heavy. BMad's create-story re-reads epics
20
20
 
21
21
  ## Install
22
22
 
23
- > **Status (v0.7.0):** the `npx` install path is not yet published to npm. The headless CLI (`node bin/flow.js plan / install / doctor / add / remove / uninstall`) is fully working from a clone. Slash commands are the recommended primary path. `npx @mhd-ghaith-abtah/flow init` lands once the package is published; tracked as E1-002 in `docs/flow/sprint.yaml`.
23
+ > **Status (v0.7.2-beta.0, published 2026-05-19):** Flow is live on npm as a **beta channel**. Stable `latest` will be promoted from beta after a soak period. Expect minor breaking changes between beta releases until then.
24
24
 
25
25
  ```bash
26
- # Inside Claude Code (recommended)
27
- /flow-init
26
+ # 1. Install the Node CLI + bootstrap the Claude Code surface
27
+ npm install -g @mhd-ghaith-abtah/flow@beta
28
+ flow install-skills # one-time; symlinks 4 skills into ~/.claude/skills/
28
29
 
29
- # Headless (works today against a clone — npm publish pending)
30
+ # 2. Then EITHER (interactive):
31
+ /flow-init # inside Claude Code
32
+
33
+ # OR (headless, no Claude Code needed):
34
+ flow init --profile standard --yes # chains detect → upstreams → MCPs → scaffold
35
+
36
+ # Useful at any point:
37
+ flow plan --profile standard # preview without executing
38
+ flow doctor # health check
39
+
40
+ # Dev clone (contributors):
30
41
  git clone https://github.com/mhd-ghaith-abtah/flow.git
31
- cd flow && npm install && tools/dev-link.sh
32
- flow plan --profile standard
42
+ cd flow && npm install && tools/dev-link.sh # dev-mode equivalent of install-skills + PATH link
33
43
  ```
34
44
 
35
- The slash-command path runs the same interactive installer. It detects your project shape, asks ~8 questions, then:
45
+ The `flow install-skills` step is what makes `/flow-init` resolve in Claude Code — npm puts the package in your global node_modules, but Claude Code only scans `~/.claude/skills/`. After install-skills, both paths (interactive slash or headless CLI) reach the same orchestrator and write the same files. Override individual knobs via `--ecc-scope`, `--bmad-subset`, `--ecc-subset`. Full guide: [docs/usage.md](docs/usage.md).
46
+
47
+ The installer detects your project shape, then:
36
48
  - Installs Flow's four skills (`flow-init`, `flow-sprint`, `flow-story`, `flow-doctor`)
37
49
  - Optionally invokes `npx bmad-method install` with a curated module list
38
50
  - Optionally invokes ECC's `install.sh` with a curated profile
@@ -44,6 +56,8 @@ The slash-command path runs the same interactive installer. It detects your proj
44
56
 
45
57
  ## Quickstart
46
58
 
59
+ > **Want every option in one place?** See the long-form [Usage Guide](docs/usage.md) — installation paths, daily workflow, sprint commands, profiles, ECC scope, maintenance, uninstall, full CLI reference, common scenarios (recipe book), and troubleshooting. The block below is the 30-second version.
60
+
47
61
  ```bash
48
62
  $ /flow-init # one time per project
49
63
  $ /flow-sprint add "First story" --epic E1 --tags ui # add a story
@@ -66,14 +80,14 @@ All three are mode flags on the same skills, not different code paths.
66
80
 
67
81
  Pick one per category in `flow.config.yaml`:
68
82
 
69
- | Category | v0.1 adapters |
83
+ | Category | Available |
70
84
  |---|---|
71
85
  | Issue tracker | `linear`, `github-issues`, `none` |
72
86
  | PR platform | `github`, `none` |
73
87
  | E2E | `playwright-mcp`, `none` |
74
88
  | Verify | `make`, `pnpm`, `custom` |
75
89
 
76
- More coming in v0.2: `jira`, `notion`, `plain`, `gitlab`, `bitbucket`, `cypress`, `slack`, `discord`.
90
+ Additional adapters (Jira, Notion, Plain, GitLab, Bitbucket, Cypress, Slack, Discord, etc.) land when a real user surfaces a concrete use case — see Flow's [validate-demand-before-building principle](ROADMAP.md#guiding-principles). The adapter contract in `adapters/<family>/<name>/_interface.md` is small (one YAML manifest + a handful of skill workflows) so PRs are welcome.
77
91
 
78
92
  ## Architecture
79
93
 
@@ -124,7 +138,10 @@ ECC owns the per-story primitives (`/plan`, `/prp-implement`, `/code-review`, `/
124
138
  Yes for now — Flow expects it. Caveman compresses Claude's responses ~75% in `full` mode, which is what makes mini-profile's 20k-tokens-per-story claim realistic. `/flow-init` installs it automatically with the right registration (see `tools/fix-caveman-shrink.sh` if the MCP proxy gets mis-registered).
125
139
 
126
140
  **Caveman is now active in every Claude Code session, even my non-Flow projects. Can I scope it?**
127
- Caveman's `SessionStart` hook activates globally by default. Native project-scope gating is shipping upstream via [JuliusBrussee/caveman#407](https://github.com/JuliusBrussee/caveman/pull/407) (filed and reviewed by Flow's maintainer; awaiting upstream merge). The PR adds `.caveman-enable` / `.caveman-disable` marker files, a `CAVEMAN_PROJECT_SCOPE` env var, and config-driven `projectScope.allow[]` / `deny[]` lists. To opt into allowlist mode today, set `~/.config/caveman/config.json` to `{"defaultMode": "off"}` Caveman stays silent everywhere except projects with `.caveman-enable` in their root. Flow's `/flow-init` drops that marker automatically, so Flow-managed projects keep working. `/flow-doctor` surfaces a probe for "Caveman active outside a Flow project" until the PR merges.
141
+ Yes, in Flow-managed projects this works out of the box. Flow installs Caveman from a **temporary fork** ([mhd-ghaith-abtah/caveman @ `flow-pin-v0.1`](https://github.com/mhd-ghaith-abtah/caveman/tree/flow-pin-v0.1)) that carries the project-scope gating patches from [JuliusBrussee/caveman#407](https://github.com/JuliusBrussee/caveman/pull/407) on top of upstream `main`. The fork exists because upstream Caveman has a ~134-PR review backlog with ~5 merges/month — waiting for #407 to merge would block Flow for months. **When #407 merges upstream, Flow swaps the catalog back to `JuliusBrussee/caveman` and deletes the fork.** The `.caveman-enable` marker Flow drops in your project root works identically against upstream and the fork, so the swap is a no-op at the project level. To opt into project-scope gating in non-Flow projects today, you can either install Caveman from the same fork tag or set `~/.config/caveman/config.json` to `{"defaultMode": "off"}` and rely on the markers globally. `/flow-doctor` surfaces a probe for "Caveman fork in use track upstream PR #407" so you know when to expect the swap.
142
+
143
+ **Can I install ECC per-project instead of into `~/.claude/`?**
144
+ Yes — the `claude-project` install target merged into ECC's `main` via [affaan-m/ECC#2006](https://github.com/affaan-m/ECC/pull/2006) on 2026-05-19 (filed and merged same-day by Flow's maintainer). Pass `--target claude-project` and ECC lands under `<projectRoot>/.claude/rules/ecc` + `<projectRoot>/.claude/skills/ecc` instead of `~/.claude/`. Symmetric with `--target claude` (home-scope) — same namespacing, same locale handling, no breaking change. **Profile defaults (shipped 2026-05-20):** `team` defaults to project-scope; `mini`/`standard`/`minimal` default to user-scope. Override via `flow plan --profile <name> --ecc-scope <user|project>` or `flow install --profile <name> --ecc-scope <user|project>` — typos like `--ecc-scope=projet` fail loud instead of silently falling through to the profile default. **Distribution caveat:** the current ECC npm `latest` is `ecc-universal@1.10.0` (2026-04-15), which predates the merge by ~36 days, so `npx ecc-universal` will NOT have the target yet. Flow's catalog pins to the post-merge commit via `npx -y -p "github:affaan-m/ECC#98bd5174" ecc-install` until affaan-m cuts the next ECC release (`2.0.0`) — at which point we swap back to the npm package. Useful for monorepos, polyglot workspaces, or teams that want ECC scoped per-repo without contaminating the developer's global Claude Code config.
128
145
 
129
146
  **Which profile should I pick?**
130
147
  - `mini` — solo, single repo, light review, no formal PR process → ~20k/story
@@ -134,7 +151,7 @@ Caveman's `SessionStart` hook activates globally by default. Native project-scop
134
151
  You can swap profiles with `/flow-init --update --profile <name>` — it's just a different bundle, not a different codepath.
135
152
 
136
153
  **What if I don't use GitHub?**
137
- Pick `adapter:pr-none` during `/flow-init` and configure `verify` + `e2e` to whatever you do use. GitLab + Bitbucket adapters are planned for v0.2.
154
+ Pick `adapter:pr-none` during `/flow-init` and configure `verify` + `e2e` to whatever you do use. GitLab and Bitbucket PR adapters are unscheduled the adapter contract is small enough to ship one in a weekend, and PRs are welcome (see `adapters/pr/<name>/_interface.md`).
138
155
 
139
156
  **How do I upgrade Flow?**
140
157
  `/flow-init --update` is idempotent. It re-detects project shape, diffs against `install-state.json`, and applies only the deltas. Upstream installers (BMad / ECC / Caveman) are re-invoked only when their pinned subset changes.
@@ -148,6 +165,9 @@ Yes — it's intentionally team-shared (adapter choices, review policy, verify c
148
165
  **Where do I report bugs?**
149
166
  [github.com/mhd-ghaith-abtah/flow/issues](https://github.com/mhd-ghaith-abtah/flow/issues). Run `/flow-doctor` first — it surfaces known-bug patterns automatically.
150
167
 
168
+ **What's the roadmap?**
169
+ See [ROADMAP.md](ROADMAP.md). v0.7.x is stabilization, v0.8 is npx-first install + ECC project-scope, v0.9 is multi-agent (Codex / Cline / Cursor / 30+ others). Explicit out-of-scope list there too.
170
+
151
171
  ## Credits
152
172
 
153
173
  Flow stands on:
@@ -157,6 +177,17 @@ Flow stands on:
157
177
  - **[spec-kit](https://github.com/github/spec-kit)** by GitHub — spec-driven development pattern
158
178
  - **[AI Dev Tasks](https://github.com/snarktank/ai-dev-tasks)** by snarktank — lean PRD + tasks pattern
159
179
 
180
+ ### Upstream strategy
181
+
182
+ Flow's preference is to send features upstream rather than fork. When upstream is responsive, we contribute. When upstream is bandwidth-constrained, we maintain a **transparent temporary fork with an explicit deprecation plan**.
183
+
184
+ Active and historical contributions:
185
+
186
+ - **[affaan-m/ECC#2006](https://github.com/affaan-m/ECC/pull/2006)** — `claude-project` install target (project-scope ECC). **Merged 2026-05-19.** Closes the install-target matrix for Claude Code and removes the need for `HOME=$PROJECT/...` shims. Same-day review and merge by maintainer.
187
+ - **[JuliusBrussee/caveman#407](https://github.com/JuliusBrussee/caveman/pull/407)** — project-scope gating via marker files, env var, and allow/deny lists. *Filed 2026-05-19. Sitting in a ~134-PR backlog at ~5 merges/month, so Flow ships a **temporary fork** ([mhd-ghaith-abtah/caveman @ `flow-pin-v0.1`](https://github.com/mhd-ghaith-abtah/caveman/tree/flow-pin-v0.1)) with the patches applied. Catalog will swap back to upstream the day #407 merges.*
188
+
189
+ This is the rule: **compose over reinvention, contribute when accepted, fork transparently with a swap-back plan when contribution is blocked.** Forks are documented in `catalog.yaml` with `upstream_repo` + `upstream_pr` + `fork_status` fields so the deprecation path is auditable.
190
+
160
191
  ## License
161
192
 
162
193
  MIT
@@ -76,7 +76,7 @@ Uses the Playwright MCP server. Runs an interactive browser session, executes jo
76
76
 
77
77
  ## screenshot_diff(baseline_path, current_path)
78
78
 
79
- Optional — v0.1 returns `{ diff_pct: null, note: "not implemented" }`. v0.2 will use `pixelmatch` or `odiff`.
79
+ Optional — currently returns `{ diff_pct: null, note: "not implemented" }`. A real pixel-diff (likely `pixelmatch` or `odiff`) is unscheduled; PRs welcome. Until then, callers should treat a `null` diff_pct as "skip the diff gate".
80
80
 
81
81
  ## Failure handling
82
82
 
@@ -36,7 +36,7 @@ Called before `transition_to_done`. Confirm the linked PR is actually merged so
36
36
 
37
37
  ## Config keys
38
38
 
39
- Adapters declare the keys they need in `flow.config.yaml > integrations.issue_tracker.*`. The Flow installer prompts for these at first install or when the adapter is swapped in via `flow adapter swap`.
39
+ Adapters declare the keys they need in `flow.config.yaml > integrations.issue_tracker.*`. The Flow installer prompts for these at first install or when the adapter is swapped via `flow add adapter:issue-tracker-<id>` (or a hand-edit of `flow.config.yaml`).
40
40
 
41
41
  ## Failure handling
42
42
 
@@ -14,7 +14,7 @@ Runs `make verify` (or another target). Standard for repos that wrap their build
14
14
 
15
15
  ## precheck
16
16
 
17
- 1. `test -f Makefile` → if false, halt: "No Makefile at repo root. Either create one with a `{{target}}:` target or switch to `flow adapter swap verify pnpm` / `custom`."
17
+ 1. `test -f Makefile` → if false, halt: "No Makefile at repo root. Either create one with a `{{target}}:` target or switch via `flow add adapter:verify-pnpm` / `flow add adapter:verify-custom`."
18
18
  2. `grep -q '^{{target}}:' Makefile` → if false, halt: "Makefile is present but has no `{{target}}:` target."
19
19
 
20
20
  ## run
package/bin/flow.js CHANGED
@@ -24,6 +24,7 @@ ${chalk.bold('Usage:')}
24
24
  ${chalk.bold('Commands:')}
25
25
  init Interactive first-time setup (same as /flow-init in Claude Code)
26
26
  install Non-interactive install with flags
27
+ install-skills Symlink Flow skills into ~/.claude/skills/ (bootstrap)
27
28
  plan Dry-run: show the resolved install plan
28
29
  status What's installed where
29
30
  doctor [--mcp <id>] Health check
@@ -34,13 +35,14 @@ ${chalk.bold('Commands:')}
34
35
  list-components [--family X] List available components
35
36
  list-mcps List MCP servers Flow tracks
36
37
  mcp <add|remove|reauth> ... Manage MCP servers
37
- adapter <swap|list> ... Manage active adapters
38
+ sprint <subcommand> ... Sprint state ops: add | next | status | done | deferred | import-bmad
38
39
  help [command] Show help
39
40
 
40
41
  ${chalk.bold('Common flags:')}
41
42
  --profile <name> mini | standard | team | minimal | full
42
43
  --bmad-subset <name> none | planning-only | planning-plus-research | creative-thinking | test-architecture | full | passthrough
43
44
  --ecc-subset <name> none | flow-essentials | flow-essentials-plus-tdd | security-heavy | research-heavy | use-ecc-default | passthrough
45
+ --ecc-scope <user|project> Override the profile's ECC install scope (user = ~/.claude/, project = ./.claude/)
44
46
  --with <component> Add a component on top of the profile
45
47
  --without <component> Remove a component from the profile
46
48
  --scope home|project|both Install scope (default: both)
@@ -67,8 +69,8 @@ Version ${PKG.version} · ${chalk.dim(PKG.homepage)}
67
69
  `;
68
70
 
69
71
  const COMMANDS = [
70
- 'init', 'install', 'plan', 'status', 'doctor', 'add', 'remove', 'uninstall',
71
- 'list-profiles', 'list-components', 'list-mcps', 'mcp', 'adapter', 'help', 'version', '--version'
72
+ 'init', 'install', 'install-skills', 'plan', 'status', 'doctor', 'add', 'remove', 'uninstall',
73
+ 'list-profiles', 'list-components', 'list-mcps', 'mcp', 'sprint', 'help', 'version', '--version'
72
74
  ];
73
75
 
74
76
  async function main() {
@@ -94,8 +96,8 @@ async function main() {
94
96
  // Parse remaining args. Note: no global `scope` default — each command sets
95
97
  // its own (install: both; uninstall: project, for safety).
96
98
  const args = yargsParser(argv.slice(1), {
97
- string: ['profile', 'bmad-subset', 'ecc-subset', 'with', 'without', 'scope', 'catalog-source', 'mcp', 'family', 'repair-upstream'],
98
- boolean: ['dry-run', 'json', 'yes', 'execute', 'remove-stories', 'remove-backups', 'archive-unused', 'migrate-bmad', 'verbose'],
99
+ string: ['profile', 'bmad-subset', 'ecc-subset', 'ecc-scope', 'with', 'without', 'scope', 'catalog-source', 'mcp', 'family', 'repair-upstream', 'id', 'title', 'epic', 'tags', 'why', 'issue', 'note', 'project', 'status'],
100
+ boolean: ['dry-run', 'json', 'yes', 'execute', 'remove-stories', 'remove-backups', 'remove-project-ecc', 'archive-unused', 'migrate-bmad', 'verbose', 'force', 'continue-on-error', 'repair', 'update'],
99
101
  array: ['with', 'without'],
100
102
  alias: { y: 'yes' }
101
103
  });
package/catalog.yaml CHANGED
@@ -225,17 +225,45 @@ upstreams:
225
225
 
226
226
  ecc:
227
227
  name: "Everything Claude Code"
228
- repo: "https://github.com/affaan-m/everything-claude-code"
228
+ # Pinned to a post-merge commit on ECC main so users get the
229
+ # `claude-project` install target (merged via affaan-m/ECC#2006 on
230
+ # 2026-05-19). Current ECC npm `latest` is 1.10.0 (2026-04-15) and
231
+ # predates the merge by ~36 days, so npm install would NOT have the
232
+ # target until affaan-m cuts the next release (2.0.0).
233
+ # SWAP PLAN: when ecc-universal@2.x lands on npm, switch
234
+ # `cmd_fallback` to `npx ecc-universal install` and pin a version.
235
+ # install_scope_default — where ECC lands when a profile doesn't override:
236
+ # - "user" → ~/.claude/rules/ecc + ~/.claude/skills/ecc (legacy default)
237
+ # - "project" → <projectRoot>/.claude/rules/ecc + .../skills/ecc
238
+ # Per-profile override lives at profiles.<name>.ecc_install_scope.
239
+ # E7-003 will wire this into base_args so --target swaps to
240
+ # claude-project when scope == "project". Today's E7-002 only plumbs
241
+ # the data through profile resolution.
242
+ install_scope_default: "user"
243
+ repo: "https://github.com/affaan-m/ECC"
244
+ upstream_npm_package: "ecc-universal"
245
+ upstream_npm_latest: "1.10.0"
246
+ upstream_npm_status: "predates claude-project merge; github pin used until 2.x publishes"
247
+ pinned_commit: "98bd5174"
229
248
  detect:
230
249
  check_cmd: "test -d ~/.claude/rules/common"
231
250
  version_path: "~/.claude/rules/VERSION"
232
251
  installer_path_candidates:
252
+ # Local dev paths — if a contributor has ECC cloned locally we use
253
+ # it. Otherwise fall through to cmd_fallback (github npx pin).
233
254
  - "~/dev-tools/everything-claude-code/install.sh"
234
- - "/usr/local/lib/node_modules/@everything-claude-code/ecc/install.sh"
255
+ - "~/development/personal/ecc-fork/install.sh"
235
256
  installer:
236
257
  cmd: "{installer_path}"
237
- cmd_fallback: "npx @everything-claude-code/ecc install"
238
- base_args: "--target claude"
258
+ cmd_fallback: "npx -y -p \"github:affaan-m/ECC#98bd5174\" ecc-install"
259
+ # base_args is scope-agnostic now. Callers must prepend the
260
+ # `--target <id>` flag chosen via `target_by_scope[ecc_install_scope]`.
261
+ # Kept empty so a future shared arg (e.g. --yes) has somewhere to live.
262
+ base_args: ""
263
+ target_arg: "--target"
264
+ target_by_scope:
265
+ user: claude # ~/.claude/{rules,skills}/ecc
266
+ project: claude-project # <projectRoot>/.claude/{rules,skills}/ecc
239
267
  profile_arg: "--profile"
240
268
  with_arg: "--with"
241
269
  without_arg: "--without"
@@ -270,8 +298,21 @@ upstreams:
270
298
 
271
299
  caveman:
272
300
  name: "Caveman"
273
- repo: "https://github.com/JuliusBrussee/caveman"
274
- description: "Output-compression layer for Claude Code (~46% input, ~75% output token savings). Flow expects Caveman to be active so its outputs stay tight."
301
+ # TEMPORARY FORK NOTICE
302
+ # ---------------------
303
+ # Flow currently installs Caveman from a patched fork pinned at
304
+ # github:mhd-ghaith-abtah/caveman#flow-pin-v0.1. The fork carries the
305
+ # project-scope gating patches from JuliusBrussee/caveman#407 (filed
306
+ # 2026-05-19, sitting in a ~134-PR upstream backlog with ~5 merges/month).
307
+ # The upstream repo is the source of truth; the fork tracks `main` and
308
+ # applies only the gating delta on top.
309
+ # SWAP PLAN: when #407 merges upstream, flip `repo` + `installer.cmd`
310
+ # back to JuliusBrussee/caveman and delete this notice (E2-006 ↻).
311
+ repo: "https://github.com/mhd-ghaith-abtah/caveman"
312
+ upstream_repo: "https://github.com/JuliusBrussee/caveman"
313
+ upstream_pr: "https://github.com/JuliusBrussee/caveman/pull/407"
314
+ fork_status: "temporary — pending upstream merge of #407"
315
+ description: "Output-compression layer for Claude Code (~46% input, ~75% output token savings). Flow expects Caveman to be active so its outputs stay tight. Installed from a Flow-maintained fork until project-scope gating lands upstream."
275
316
  detect:
276
317
  # Current Caveman installer routes via Claude Code's plugin marketplace —
277
318
  # files land under ~/.claude/plugins/cache/caveman/, NOT the legacy
@@ -280,12 +321,16 @@ upstreams:
280
321
  check_cmd: "find $HOME/.claude/plugins -path '*caveman*SKILL.md' -print -quit 2>/dev/null | grep -q . || test -f $HOME/.claude/skills/caveman/SKILL.md || test -f $HOME/.claude/hooks/caveman-config.js"
281
322
  hooks_cmd: "ls $HOME/.claude/hooks/caveman-* 2>/dev/null"
282
323
  installer:
283
- cmd: "curl -fsSL https://raw.githubusercontent.com/JuliusBrussee/caveman/main/install.sh | bash"
324
+ # Pinned to a stable tag on the Flow-maintained fork. The tag carries the
325
+ # #407 gating patches applied on top of upstream main. To inspect before
326
+ # running, set $FLOW_INSPECT_INSTALL_SCRIPTS=1 and Flow will download +
327
+ # diff against upstream first.
328
+ cmd: "npx -y \"github:mhd-ghaith-abtah/caveman#flow-pin-v0.1\""
284
329
  # Mirror of detect.check_cmd — succeeds for either the plugin-marketplace
285
330
  # layout (current) or the legacy ~/.claude/skills/caveman/ layout (older
286
331
  # installer releases). Verifies "the install landed somewhere we can find".
287
332
  verify_after_cmd: "find $HOME/.claude/plugins -path '*caveman*SKILL.md' -print -quit 2>/dev/null | grep -q . || test -f $HOME/.claude/skills/caveman/SKILL.md || test -f $HOME/.claude/hooks/caveman-config.js"
288
- security_note: "Caveman ships only via curl-pipe-bash. Flow will surface this and ask for confirmation unless --yes is passed. To inspect the script before running, set $FLOW_INSPECT_INSTALL_SCRIPTS=1 Flow will download to /tmp first, pause for review, then execute."
333
+ security_note: "Caveman installs via npx from a Flow-maintained fork (pinned tag flow-pin-v0.1). Fork = upstream main + JuliusBrussee/caveman#407 patches. Flow will surface this and ask for confirmation unless --yes is passed. To inspect the fork's source before running: gh repo view mhd-ghaith-abtah/caveman --branch flow-pin-v0.1 OR set $FLOW_INSPECT_INSTALL_SCRIPTS=1."
289
334
  available_modes: [lite, full, ultra, wenyan]
290
335
  curated_subsets:
291
336
  none:
@@ -356,6 +401,10 @@ profiles:
356
401
  bmad_subset: full
357
402
  ecc_subset: flow-essentials-plus-tdd
358
403
  caveman_subset: full
404
+ # team-profile default: ECC lands per-project so each Flow-managed repo
405
+ # gets its own ECC selection without contaminating ~/.claude/. Becomes
406
+ # active once E7-003 wires the scope flag into the install command.
407
+ ecc_install_scope: project
359
408
  # Note: review.use_separate_model is set to true in the generated
360
409
  # flow.config.yaml for this profile (spawns one reviewer with a different
361
410
  # model for fresh perspective). The previous `features` block here
package/docs/adapters.md CHANGED
@@ -1,8 +1,8 @@
1
1
  # Adapters
2
2
 
3
- Flow's per-category adapter system lets you swap integrations without changing any skill code. There are four adapter families today; more land in v0.2.
3
+ Flow's per-category adapter system lets you swap integrations without changing any skill code. There are four adapter families today; additional adapters and families land when there's a concrete use case (see Flow's [validate-demand-before-building principle](../ROADMAP.md#guiding-principles)).
4
4
 
5
- ## Families + v0.1 options
5
+ ## Families + available picks
6
6
 
7
7
  | Family | Picks | What it does |
8
8
  |---|---|---|
@@ -11,7 +11,7 @@ Flow's per-category adapter system lets you swap integrations without changing a
11
11
  | `e2e` | `playwright-mcp`, `none` | End-to-end test driver — run journeys, capture artifacts |
12
12
  | `verify` | `make`, `pnpm`, `custom` | Verify command — typecheck + lint + unit tests in one |
13
13
 
14
- Coming in v0.2: `jira`, `notion`, `plain` (issue-tracker); `gitlab`, `bitbucket` (pr); `cypress` (e2e); `slack`, `discord` (notification — new family).
14
+ **Likely-but-unscheduled** (PRs welcome — the adapter contract is small): Jira, Notion, Plain (issue-tracker); GitLab, Bitbucket (pr); Cypress (e2e); Slack, Discord (notification — would be a new family). None of these are on the roadmap today; the adapter contract in `adapters/<family>/<name>/_interface.md` is small enough that a contributor can ship one in a weekend.
15
15
 
16
16
  ## Picking adapters
17
17
 
@@ -54,8 +54,11 @@ Each adapter is a markdown file with sections for each operation in the family's
54
54
 
55
55
  ## Swapping after install
56
56
 
57
+ Two supported paths:
58
+
57
59
  ```
58
- flow adapter swap pr github-issues # not yet implemented in v0.7
60
+ flow add adapter:pr-github-issues
61
+ flow remove adapter:pr-github
59
62
  ```
60
63
 
61
64
  Or hand-edit `flow.config.yaml`:
package/docs/profiles.md CHANGED
@@ -4,12 +4,12 @@ Profiles are named bundles that pick the right adapters + upstream subsets + MCP
4
4
 
5
5
  ## At a glance
6
6
 
7
- | Profile | Best for | Tokens/story | Review | E2E | PR | Issue tracker |
8
- |---|---|---:|---|---|---|---|
9
- | `mini` | Solo, one repo, light review | ~20k | `code-review` only | none | GitHub | GitHub Issues |
10
- | `standard` | Solo/small team, formal review | ~40k | `code-review` + language reviewer + security on risk tags | Playwright MCP | GitHub | GitHub Issues |
11
- | `team` | Multi-repo, multi-LLM review | ~60k | + adversarial + edge-case + separate-model reviewer | Playwright MCP | GitHub (sibling PRs) | Linear |
12
- | `minimal` | Bare Flow, no upstreams | <10k | none | none | none | none |
7
+ | Profile | Best for | Tokens/story | Review | E2E | PR | Issue tracker | ECC scope |
8
+ |---|---|---:|---|---|---|---|---|
9
+ | `mini` | Solo, one repo, light review | ~20k | `code-review` only | none | GitHub | GitHub Issues | user |
10
+ | `standard` | Solo/small team, formal review | ~40k | `code-review` + language reviewer + security on risk tags | Playwright MCP | GitHub | GitHub Issues | user |
11
+ | `team` | Multi-repo, multi-LLM review | ~60k | + adversarial + edge-case + separate-model reviewer | Playwright MCP | GitHub (sibling PRs) | Linear | **project** |
12
+ | `minimal` | Bare Flow, no upstreams | <10k | none | none | none | none | user |
13
13
 
14
14
  ## What each profile changes
15
15
 
@@ -19,6 +19,7 @@ Profiles are named bundles that pick the right adapters + upstream subsets + MCP
19
19
  - **MCPs:** none
20
20
  - **BMad subset:** `none`
21
21
  - **ECC subset:** `none`
22
+ - **ECC install scope:** `user` (inherits the catalog default — no scope-relevant ECC content is installed at `none` anyway)
22
23
  - **Caveman:** `full`
23
24
 
24
25
  Just `sprint.yaml` + story files. No upstream integration. Useful when you want Flow's state model without any of the per-story machinery.
@@ -30,6 +31,7 @@ Extends `minimal`. Adds:
30
31
  - **Adapters:** `issue-tracker-github-issues`, `pr-github`, `verify-make`
31
32
  - **MCPs:** `context7`
32
33
  - **ECC subset:** `flow-essentials` (just `/plan`, `/prp-implement`, `/code-review`, `/update-docs`)
34
+ - **ECC install scope:** `user` (lands under `~/.claude/{rules,skills}/ecc` — shared across all your projects)
33
35
 
34
36
  What you get: full per-story orchestration through `/flow-story` with the lightest possible review. No E2E, no language-specific reviewers, no adversarial reviewers.
35
37
 
@@ -41,6 +43,7 @@ Extends `mini`. Adds:
41
43
  - **MCPs:** + `playwright`
42
44
  - **BMad subset:** `planning-only` (PRD, architecture, epic generation; no per-story BMad re-reads)
43
45
  - **ECC subset:** `flow-essentials-plus-tdd` (adds `/tdd` and TDD harness)
46
+ - **ECC install scope:** `user` (inherited from `mini` — same `~/.claude/{rules,skills}/ecc` mount)
44
47
 
45
48
  What you get: full orchestration + E2E coverage for tagged stories + BMad planning artifacts on demand.
46
49
 
@@ -51,12 +54,38 @@ Extends `standard`. Adds:
51
54
  - **Adapters:** overrides `issue-tracker-github-issues` → `issue-tracker-linear`
52
55
  - **MCPs:** + `linear`
53
56
  - **BMad subset:** `full`
57
+ - **ECC install scope:** `project` (lands under `<projectRoot>/.claude/{rules,skills}/ecc` so each Flow-managed repo keeps its own ECC selection; nothing bleeds into the developer's global `~/.claude/`)
54
58
  - **Review:** `use_separate_model: true` — spawns one reviewer with a different model (e.g., Sonnet alongside Opus) for cross-model perspective on tagged-risky stories
55
59
 
56
60
  What you get: full orchestration + Linear-driven sprint sync + cross-model code review on high-risk stories.
57
61
 
58
62
  > **What you don't get (despite earlier docs promising it):** multi-repo coordinated sibling PRs and per-adapter-call audit logs. Those were aspirational features in the team-profile description through v0.7.0 with zero implementation behind them. Stripped on 2026-05-19 (sprint story E5-007). Read-only multi-repo awareness (story-id touches N repos → aggregate PR status) is tracked as a deferred backlog item; surface a real use case and we'll design it properly.
59
63
 
64
+ ## ECC install scope
65
+
66
+ Where ECC's rules + skills land on disk. Two values:
67
+
68
+ | Scope | Install root | Use case |
69
+ |---|---|---|
70
+ | `user` | `~/.claude/rules/ecc` + `~/.claude/skills/ecc` | Solo dev or single primary project — ECC is shared across every Claude Code session on the machine |
71
+ | `project` | `<projectRoot>/.claude/rules/ecc` + `<projectRoot>/.claude/skills/ecc` | Multi-project, polyglot, or team setups — each Flow-managed repo keeps its own ECC selection without bleeding into `~/.claude/` |
72
+
73
+ Resolved scope per layer (later wins):
74
+
75
+ 1. **Catalog default** — `upstreams.ecc.install_scope_default: user` in `catalog.yaml`. Fallback when nothing else applies.
76
+ 2. **Profile** — each profile's `ecc_install_scope` field. `team` is the only stock profile that overrides to `project`; the rest inherit `user`.
77
+ 3. **CLI flag** — `--ecc-scope <user|project>` on `flow plan` and `flow install`. Highest priority. Typos like `--ecc-scope=projet` fail loud.
78
+
79
+ ```
80
+ flow plan --profile team # team default → project
81
+ flow plan --profile team --ecc-scope user # explicit override → user
82
+ flow plan --profile mini --ecc-scope project # explicit override → project
83
+ ```
84
+
85
+ Under the hood, the scope picks the ECC installer's `--target` flag: `user` → `--target claude`, `project` → `--target claude-project`. The `claude-project` target merged into ECC via [affaan-m/ECC#2006](https://github.com/affaan-m/ECC/pull/2006) on 2026-05-19; Flow's catalog pins to that commit (`npx -y -p "github:affaan-m/ECC#98bd5174" ecc-install`) until ECC publishes `ecc-universal@2.x` to npm (current latest is `1.10.0`, which predates the merge).
86
+
87
+ `/flow-doctor --repair-upstream ecc` reads the recorded scope from `install-state.json` and emits the right rules-dir + `--target` arg in its repair instructions — no manual translation needed.
88
+
60
89
  ## Swapping profiles
61
90
 
62
91
  ```