@contentful/experience-design-system-cli 2.35.0-alpha.0 → 2.35.0

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.
Files changed (85) hide show
  1. package/README.md +65 -83
  2. package/dist/package.json +2 -1
  3. package/dist/src/analyze/composition/interchange-schema.d.ts +4 -24
  4. package/dist/src/analyze/composition/resolve-mapping-cli.d.ts +2 -11
  5. package/dist/src/analyze/composition/resolve-mapping.d.ts +5 -7
  6. package/dist/src/analyze/extract-command.d.ts +4 -0
  7. package/dist/src/analyze/select/tui/components/FieldEditor.d.ts +3 -1
  8. package/dist/src/analyze/select/tui/components/FinalizeDialog.d.ts +2 -2
  9. package/dist/src/analyze/select/tui/components/GroupedSidebar.d.ts +3 -0
  10. package/dist/src/analyze/select/tui/components/HelpOverlay.d.ts +2 -0
  11. package/dist/src/analyze/select/tui/components/Sidebar.d.ts +2 -1
  12. package/dist/src/analyze/select/tui/hooks/scroll-offset.d.ts +4 -3
  13. package/dist/src/analyze/select/tui/hooks/useImmediateInput.d.ts +1 -1
  14. package/dist/src/credentials-store.d.ts +3 -23
  15. package/dist/src/doctor/checks.d.ts +5 -0
  16. package/dist/src/doctor/command.d.ts +2 -0
  17. package/dist/src/doctor/report.d.ts +7 -0
  18. package/dist/src/import/agent-model-resolve.d.ts +8 -4
  19. package/dist/src/import/composition-options.d.ts +0 -2
  20. package/dist/src/import/tui/WizardApp.d.ts +21 -4
  21. package/dist/src/import/tui/components/CompactControlBar.d.ts +4 -0
  22. package/dist/src/import/tui/components/ReviewStatus.d.ts +0 -5
  23. package/dist/src/import/tui/hooks/review-input.d.ts +1 -1
  24. package/dist/src/import/tui/lineage-layout.d.ts +18 -25
  25. package/dist/src/import/tui/run-selection-agent.d.ts +9 -0
  26. package/dist/src/import/tui/scope-gate-columns.d.ts +14 -8
  27. package/dist/src/import/tui/steps/CredentialsStep.d.ts +4 -1
  28. package/dist/src/import/tui/steps/GateStep.d.ts +1 -1
  29. package/dist/src/import/tui/steps/GenerateReviewStep.d.ts +14 -3
  30. package/dist/src/import/tui/steps/RunningStep.d.ts +12 -1
  31. package/dist/src/import/tui/steps/ScopeGateStep.d.ts +1 -1
  32. package/dist/src/import/tui/steps/WizardPreviewStep.d.ts +2 -2
  33. package/dist/src/import/tui/wizard-state-transitions.d.ts +5 -7
  34. package/dist/src/index.js +24979 -23985
  35. package/dist/src/lib/agent-definitions.d.ts +14 -0
  36. package/dist/src/lib/agent-model-options.d.ts +4 -4
  37. package/dist/src/lib/command-options.d.ts +0 -1
  38. package/dist/src/lib/debug-logger.d.ts +1 -9
  39. package/dist/src/lib/debug-preamble.d.ts +1 -8
  40. package/dist/src/program.d.ts +3 -3
  41. package/dist/src/runs/store.d.ts +0 -5
  42. package/dist/src/session/db.d.ts +32 -2
  43. package/dist/src/setup/SetupScreen.d.ts +28 -0
  44. package/dist/src/setup/SetupStepper.d.ts +7 -0
  45. package/dist/src/setup/command.d.ts +1 -7
  46. package/dist/src/setup/lib/checks.d.ts +57 -0
  47. package/dist/src/setup/lib/shell.d.ts +12 -0
  48. package/dist/src/setup/steps/CodingAgentScreen.d.ts +20 -0
  49. package/dist/src/setup/steps/ContentfulCredentialsScreen.d.ts +11 -0
  50. package/dist/src/setup/steps/StepLayout.d.ts +20 -0
  51. package/dist/src/setup/steps/preferences/AnalyticsScreen.d.ts +5 -0
  52. package/dist/src/setup/steps/preferences/BooleanInput.d.ts +21 -0
  53. package/dist/src/setup/steps/preferences/ColorPreferenceScreen.d.ts +5 -0
  54. package/dist/src/setup/steps/preferences/CustomPromptScreen.d.ts +14 -0
  55. package/dist/src/setup/steps/preferences/DebugLogsScreen.d.ts +5 -0
  56. package/dist/src/setup/steps/preferences/PreferencesMenu.d.ts +26 -0
  57. package/dist/src/setup/steps/prerequisites/PrerequisitesScreen.d.ts +16 -0
  58. package/dist/src/setup/steps/prerequisites/build.d.ts +2 -0
  59. package/dist/src/setup/steps/prerequisites/deps.d.ts +33 -0
  60. package/dist/src/setup/steps/prerequisites/index.d.ts +4 -0
  61. package/dist/src/setup/steps/prerequisites/node.d.ts +2 -0
  62. package/dist/src/setup/steps/prerequisites/pnpm.d.ts +2 -0
  63. package/dist/src/tui/render-with-goodbye.d.ts +7 -0
  64. package/dist/src/tui/use-terminal-size.d.ts +6 -0
  65. package/dist/src/tui/windowed-panel.d.ts +37 -0
  66. package/package.json +7 -6
  67. package/skills/generate-components.md +99 -65
  68. package/dist/src/analyze/select/tui/components/LineagePanel.d.ts +0 -14
  69. package/dist/src/import/strip-allowed-components.d.ts +0 -18
  70. package/dist/src/import/tui/final-review-host.d.ts +0 -8
  71. package/dist/src/import/tui/hooks/useLineage.d.ts +0 -32
  72. package/dist/src/import/tui/lineage-input.d.ts +0 -18
  73. package/dist/src/import/tui/push-decision-gate-helpers.d.ts +0 -8
  74. package/dist/src/import/tui/review-step-props.d.ts +0 -13
  75. package/dist/src/import/tui/scope-gate-host.d.ts +0 -21
  76. package/dist/src/import/tui/steps/AtomicGenerateReviewStep.d.ts +0 -28
  77. package/dist/src/import/tui/steps/AtomicScopeGateStep.d.ts +0 -3
  78. package/dist/src/import/tui/steps/PushDecisionGateStep.d.ts +0 -12
  79. package/dist/src/import/tui/steps/useTerminalColumns.d.ts +0 -1
  80. package/dist/src/lib/composition-mode.d.ts +0 -21
  81. package/dist/src/runs/save-conflict.d.ts +0 -8
  82. package/dist/src/setup/analytics-prompt.d.ts +0 -13
  83. package/dist/src/setup/composition-mode-prompt.d.ts +0 -14
  84. package/dist/src/setup/debug-mode-prompt.d.ts +0 -11
  85. package/dist/src/setup/prompt-helpers.d.ts +0 -1
package/README.md CHANGED
@@ -6,11 +6,11 @@ CLI for extracting, reviewing, generating, validating, and pushing Contentful Ex
6
6
 
7
7
  The package installs three equivalent binaries:
8
8
 
9
- | Binary | Notes |
10
- | ------------------------------- | -------------------------------------------------------------------- |
11
- | `experiences` | Preferred entry point — short and operator-facing |
12
- | `exo` | Shorthand for Experience Orchestration |
13
- | `experience-design-system-cli` | Full name; used in CI / scripts where clarity matters |
9
+ | Binary | Notes |
10
+ | ------------------------------ | ----------------------------------------------------- |
11
+ | `experiences` | Preferred entry point — short and operator-facing |
12
+ | `exo` | Shorthand for Experience Orchestration |
13
+ | `experience-design-system-cli` | Full name; used in CI / scripts where clarity matters |
14
14
 
15
15
  The rest of this README uses `experiences`.
16
16
 
@@ -18,11 +18,13 @@ The rest of this README uses `experiences`.
18
18
 
19
19
  The CLI has two primary workflows:
20
20
 
21
- 1. **`experiences import`** — the wizard. Drives the full pipeline (extract → AI select → scope-gate → internal generation → final-review → save/push) from a single command in a full-screen interactive TUI. **This is the recommended path for almost everyone.**
21
+ 1. **`experiences import`** — the wizard. Drives the full pipeline (extract → AI select → scope-gate → generation → final-review → save and push) from a single command in a full-screen interactive TUI. **This is the recommended path for almost everyone.**
22
22
 
23
- 2. **`experiences apply`** — applies generated component and token definitions to Contentful.
23
+ 2. **`experiences apply <file>`** — applies a CDF file of component and token definitions to Contentful.
24
24
 
25
- The import wizard owns extraction, selection, generation, validation, and apply orchestration internally; those implementation stages are not exposed as standalone commands.
25
+ `experiences setup` and `experiences doctor` configure and check your environment. `experiences importv2` launches the newer v2 TUI, and `experiences build` rebuilds a local checkout and re-links the binaries.
26
+
27
+ The import wizard owns extraction, selection, generation, validation, and apply orchestration internally; those implementation stages are not exposed as public commands. Hidden internal commands (`__extract`, `__generate`, `map tokens`, `print`) are what the wizard runs in subprocesses.
26
28
 
27
29
  All intermediate data flows through a local SQLite session database (`~/.contentful/experience-design-system-cli/pipeline.db`). No JSON files are written between steps — each pipeline step reads its inputs from the session and writes its outputs back to it.
28
30
 
@@ -32,21 +34,14 @@ All intermediate data flows through a local SQLite session database (`~/.content
32
34
 
33
35
  A **composite component** is one that renders other components inside it — a `Card` that slots a `Button` and an `Icon`, a `Tabs` that slots `Tab` panels. When you import composite components, the CLI can populate each slot's `$allowedComponents` so the parent→child relationships survive into Contentful.
34
36
 
35
- ### Atomic vs. composite
36
-
37
- Imports are **atomic by default** — flat components, no embedded hierarchy. This is the right choice when you just want each component registered on its own. Opt into hierarchy resolution with `--composite` (or any composition flag, which implies it).
38
-
39
- | Mode | Flag | Behavior |
40
- |---|---|---|
41
- | Atomic | default | Flat import; composition stripped before push |
42
- | Composite | `--composite` | Resolve and import the parent→child hierarchy |
37
+ All imports use composite mode: embedded-component relationships are resolved and preserved in the generated CDF.
43
38
 
44
39
  ### How composition is resolved
45
40
 
46
- Under `--composite`, relationships are resolved from the highest-confidence source available, in this precedence order:
41
+ Relationships are resolved from the highest-confidence source available, in this precedence order:
47
42
 
48
43
  1. **Typed slots (code)** — slots the source already declares, e.g. React `ReactElement<XProps>` / `children`, Svelte `Snippet<[XProps]>`, or an explicit `@allowedComponents` JSDoc tag. Fully deterministic; picked up automatically.
49
- 2. **Agent** — direct edge emission for codebases that encode composition in *code patterns* rather than typed slots (common in real-world design systems). It is enabled automatically in composite mode and only runs when the deterministic sources above find nothing.
44
+ 2. **Agent** — direct edge emission for codebases that encode composition in _code patterns_ rather than typed slots (common in real-world design systems). It is enabled automatically in composite mode and only runs when the deterministic sources above find nothing.
50
45
 
51
46
  When more than one source speaks to the same relationship, the higher-precedence one wins (**code slots > agent**).
52
47
 
@@ -55,7 +50,7 @@ When more than one source speaks to the same relationship, the higher-precedence
55
50
  The composition agent emits one structured edge per relationship. The CLI validates component names and merges those edges with deterministic sources by provenance and precedence.
56
51
 
57
52
  - `--no-cache` — ignore caches and re-resolve composition from scratch, forcing the agent to run.
58
- - `--agent <name>` — which coding agent authors the parser (`claude`, `codex`, `opencode`, `cursor`, `copilot`).
53
+ - `--agent <name>` — which coding agent runs composition, and the rest of the wizard's agent stages (`claude`, `codex`, `opencode`, `cursor`, `copilot`).
59
54
  - `--prompt composition=<file-or-text>` — override the composition stage's prompt.
60
55
 
61
56
  Because the agent path spawns a coding agent, it adds latency and cost and is best-effort.
@@ -72,13 +67,13 @@ If the resolved graph contains a circular slot dependency (A slots B, B slots A)
72
67
 
73
68
  The import wizard's generation steps require a coding agent CLI in your `$PATH`. Choose one:
74
69
 
75
- | Agent | Install | Auth |
76
- |---|---|---|
77
- | **Claude Code** (`claude`) | `npm install -g @anthropic-ai/claude-code` | `claude login` (browser OAuth) **or** set `ANTHROPIC_API_KEY` |
78
- | **OpenAI Codex** (`codex`) | `npm install -g @openai/codex` | Set `OPENAI_API_KEY` |
79
- | **OpenCode** (`opencode`) | `npm install -g opencode-ai` | Configure via `opencode auth` (supports multiple providers) |
80
- | **Cursor** (`cursor`) | Install [Cursor](https://cursor.com) | Sign in to Cursor; exposes `cursor-agent` binary |
81
- | **GitHub Copilot** (`copilot`) | `npm install -g @github/copilot` | Run `copilot` once to complete GitHub OAuth login. Free plan uses Auto model selection by default. Paid plans can pin a specific model via `EDS_AGENT_MODEL_COPILOT=<model-id>` (e.g. `claude-sonnet-4.6`) |
70
+ | Agent | Install | Auth |
71
+ | ------------------------------ | ------------------------------------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
72
+ | **Claude Code** (`claude`) | `npm install -g @anthropic-ai/claude-code` | `claude login` (browser OAuth) **or** set `ANTHROPIC_API_KEY` |
73
+ | **OpenAI Codex** (`codex`) | `npm install -g @openai/codex` | Set `OPENAI_API_KEY` |
74
+ | **OpenCode** (`opencode`) | `npm install -g opencode-ai` | Configure via `opencode auth` (supports multiple providers) |
75
+ | **Cursor** (`cursor`) | Install [Cursor](https://cursor.com) | Sign in to Cursor; exposes `cursor-agent` binary |
76
+ | **GitHub Copilot** (`copilot`) | `npm install -g @github/copilot` | Run `copilot` once to complete GitHub OAuth login. Free plan uses Auto model selection by default. Paid plans can pin a specific model via `EDS_AGENT_MODEL_COPILOT=<model-id>` (e.g. `claude-sonnet-4.6`) |
82
77
 
83
78
  The CLI invokes the agent non-interactively in a subprocess. If the binary is not found in `$PATH`, the command exits 1 and prints manual fallback instructions.
84
79
 
@@ -86,7 +81,7 @@ The CLI invokes the agent non-interactively in a subprocess. If the binary is no
86
81
 
87
82
  ### Contentful credentials
88
83
 
89
- `apply` and `import` (when pushing) require access to a Contentful space. Set these environment variables or pass the equivalent flags:
84
+ `apply` and `import` (when pushing) require access to a Contentful space. Configure these environment variables or run `experiences setup`:
90
85
 
91
86
  ```bash
92
87
  export CONTENTFUL_MANAGEMENT_TOKEN=<your-cma-token> # required
@@ -96,7 +91,7 @@ export CONTENTFUL_ENVIRONMENT_ID=master # required
96
91
 
97
92
  Or run `experiences setup` once and they get saved to `credentials.json` and pre-filled in the wizard.
98
93
 
99
- In the wizard's credentials step you can press `[s] Skip` to save-only without pushing — useful when you want a checked-in `components.json` without a live push.
94
+ In the wizard's credentials step you can press `[s] Skip` to save-only without pushing — useful when you want a checked-in combined CDF file without a live push.
100
95
 
101
96
  ---
102
97
 
@@ -110,38 +105,40 @@ experiences import [flags]
110
105
 
111
106
  ### Wizard step machine
112
107
 
108
+ The order below is the normal path. The first step depends on how the wizard is started: `--project` jumps straight to `token-input`, and `--tokens` jumps to `path-validation` (with `--project`) or `credentials` (without it).
109
+
113
110
  ```
114
- welcome
111
+ welcome — project path
115
112
  ↓
116
- extracting — runs analyze extract (atomic by default; resolves composition
117
- under --composite, see below); spawns internal generation in parallel (prefetch)
113
+ token-input — optional raw token file; Enter on an empty field skips
114
+ ↓ (token-generation and token-reuse-gate run here when a file is given)
115
+ path-validation — confirms the project path and how many files will be scanned
118
116
  ↓
119
- [auto-filter] — analyze select-agent runs automatically
117
+ credentials — space ID, environment, CMA token and API host, prefilled from
118
+ `experiences setup`; press [s] to skip and save files only
120
119
  ↓
121
- scope-gate — single human review gate: confirm AI selection, toggle components
120
+ extracting — composite relationships enabled; the selection agent runs here
121
+ once components are extracted
122
122
  ↓
123
- credentials — operator reviews the prefilled space-id / env / token (internal generation is already running)
124
- press [s] Skip to save-only without pushing
123
+ scope-gate — single human review gate: confirm the AI selection, toggle components
125
124
  ↓
126
- final-review — minimum-viable port of the JsonEditor; edit names, $description,
127
- $default, $allowedComponents per slot, $values, source/rationale panels
125
+ generating — component generation, then token mapping when a token file was given
128
126
  ↓
129
- preview — diff vs. live Contentful
127
+ final-review — edit names, $description, $default, $allowedComponents per slot,
128
+ $values, with source and rationale panels
130
129
  ↓
131
- push-decision-gate — choose Save AND push (default) or one of the alternatives
130
+ path-prompt — where to save `components.json` (and `tokens.json`)
132
131
  ↓
133
- pushing → done — push emits a Contentful webapp view URL for the imported components
132
+ previewing → preview-gate — diff against live Contentful; confirm to push
133
+ ↓
134
+ pushing → done — the push emits a Contentful webapp view URL for the imported components
134
135
  ```
135
136
 
136
- There is now a single human review gate (`scope-gate`) before generation; the legacy two-step extract-review + select-review flow has been collapsed.
137
-
138
- ### Configurable AI auto-filter
137
+ There is a single human review gate (`scope-gate`) before generation. Choosing to skip credentials still saves the files; it bypasses the preview and refuses to push.
139
138
 
140
- The auto-filter (`analyze select-agent` invoked before scope-gate) is on by default; the value selected in setup is persisted to `credentials.json` so subsequent runs default to your saved preference.
139
+ ### Save and push
141
140
 
142
- ### Save-and-push default
143
-
144
- The push-decision-gate defaults to **save AND push**: it writes `components.json` and `tokens.json` to disk *and* pushes to Contentful in one step.
141
+ After final-review the wizard always saves one combined `components.json` CDF (components and design tokens) and then, unless credentials were skipped, previews the diff and pushes it to Contentful. The wizard records each saved run in `~/.config/experiences/runs.json`.
145
142
 
146
143
  ### Custom skill prompts
147
144
 
@@ -149,54 +146,41 @@ Custom `.md` skill prompt paths can be saved via `experiences setup`; the CLI em
149
146
 
150
147
  ### Flag reference — `experiences import`
151
148
 
152
- | Flag | Default | Description |
153
- | --------------------------------- | -------------------------------------- | ------------------------------------------------------------------------------------------------------------ |
154
- | `--project <path>` | `.` | Project root to analyze |
155
- | `--agent <name>` | saved by setup / `claude` | Agent for `analyze select-agent` and internal generation |
156
- | `--model <name>` | agent default | Model name |
157
- | `--composite` | — | Import the embedded-component hierarchy (any composition flag implies this) |
158
- | `--composition-map <path>` | — | Consume a hand-authored parent→children interchange map (implies `--composite`) |
159
- | `--prompt <stage=value>` | — | Override a stage prompt (repeatable); value is a file path or literal text, e.g. `--prompt composition=./p.md` |
160
- | `--skip-map-tokens` | — | Skip the `map tokens` step between internal generation and apply |
161
- | `--no-cache` | cache on | Bypass extract/select/internal-generation/map-tokens/composition caches and force re-run |
149
+ | Flag | Default | Description |
150
+ | ------------------------ | ------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
151
+ | `--project <path>` | `.` | Project root to analyze |
152
+ | `--tokens <path>` | — | Raw token source file (SCSS, CSS variables, JS/TS, Style Dictionary, …) to classify and import alongside components; skips the interactive token prompt |
153
+ | `--agent <name>` | saved by setup / `claude` | Coding agent, with an optional model as `agent:model` or `"agent model"` |
154
+ | `--prompt <stage=value>` | — | Override a stage prompt (repeatable); value is a file path or literal text, e.g. `--prompt select=./p.md`. Stages used today: `composition`, `select`, `map-tokens` |
155
+ | `--no-cache` | cache on | Re-run all steps instead of reusing cached results |
162
156
 
163
- ### `--model` and `--agent` overrides
157
+ `--model`, `--composition-map`, `--skip-map-tokens` and `--raw-tokens` were removed from `import`. Unknown flags are rejected. Pass the model through `--agent` instead, and use `--tokens` for a token file.
164
158
 
165
- `--model <name>` overrides the stored model for this run. The resolution order is:
159
+ ### Choosing the agent and model
166
160
 
167
- 1. `--model <name>` flag
168
- 2. `model` field saved in `~/.config/experiences/credentials.json`
169
- 3. Built-in default for the chosen agent
161
+ `--agent` accepts `claude`, `codex`, `opencode`, `cursor` or `copilot`, optionally followed by a model: `--agent claude:sonnet` or `--agent "claude sonnet"`. The agent resolves in this order:
170
162
 
171
- `--agent <name>` works the same way and is a fully functional wizard override — earlier releases plumbed the flag but the commander default shadowed it; the flag now wins over the saved value as expected.
163
+ 1. `--agent <name>` flag
164
+ 2. `agent` field saved in `~/.config/experiences/credentials.json` by `experiences setup`
165
+ 3. Built-in default, `claude`
172
166
 
173
- ---
174
-
175
- ### `print components` / `print tokens` / `print validate`
176
-
177
- Unchanged from prior releases.
178
-
179
- ```bash
180
- experiences print components [--session <id>] [--out <path>]
181
- experiences print tokens [--session <id>] [--out <path>]
182
- experiences print validate [--components <path>] [--tokens <path>]
183
- ```
184
-
185
- `print validate` exits `0` on success, `1` on validation errors.
167
+ The model resolves the same way: the model part of `--agent`, then the `agentModel` field in `credentials.json`, then the agent's own lightweight default. You can also set a model per agent with `EDS_AGENT_MODEL_<AGENT>` (for example `EDS_AGENT_MODEL_CLAUDE`).
186
168
 
187
169
  ---
188
170
 
189
171
  ### `apply`
190
172
 
191
- This command is the non-wizard route to the same diff and push logic. Its flag surface is unchanged.
173
+ This command is the non-wizard route to the same diff and push logic. It accepts one CDF file containing all component and design token definitions.
192
174
 
193
175
  `apply` emits a Contentful webapp view URL for the imported components in its JSON summary (`viewUrl`) so callers can deep-link into the management UI after a successful push.
194
176
 
177
+ Design tokens are read from the same CDF file, so there is no separate token flag.
178
+
195
179
  ```bash
196
- experiences apply
180
+ experiences apply <file>
197
181
  ```
198
182
 
199
- Shared flags: `--components`, `--tokens`. `apply` is interactive and loads credentials from `experiences setup` or environment variables. Remote ComponentTypes and DesignTokens missing from the pushed manifest are always skipped.
183
+ `apply` is interactive and loads credentials from `experiences setup` or environment variables. Remote ComponentTypes and DesignTokens missing from the pushed manifest are always skipped.
200
184
 
201
185
  Design tokens are written first (component types may reference token kinds). Each entity write is recorded in the session database atomically — interrupted pushes resume from where they left off.
202
186
 
@@ -210,9 +194,7 @@ All pipeline state is stored in `~/.contentful/experience-design-system-cli/pipe
210
194
 
211
195
  ## Terminal Compatibility
212
196
 
213
- - Minimum 60 columns required for the wizard and the `analyze select` TUI
214
- - 80+ columns recommended for full sidebar + detail view
215
- - 120+ columns required to show the source code panel in `analyze select`
197
+ - The scope-gate step shows two columns at 100 or more terminal columns and one column below that; a wider terminal is more comfortable for the final-review editor
216
198
  - `NO_COLOR=1` suppresses all ANSI color output
217
199
  - Interactive views require both stdin and stdout to be TTYs and stdin to support raw mode.
218
200
  - On Windows, use Windows Terminal with PowerShell. Older ConEmu and cmd.exe hosts may not provide the raw-mode support the interactive UI needs.
@@ -235,7 +217,7 @@ What may be included:
235
217
 
236
218
  You can turn this off two ways:
237
219
 
238
- - Persistently: run `experiences setup` and answer "yes" at the analytics prompt. This writes an opt-out to `~/.config/experiences/credentials.json` that persists across invocations until you change it again — it will not silently re-enable itself.
220
+ - Persistently: run `experiences setup`, open **Usage analytics** and choose "Don't share usage data". This writes `analyticsDisabled: true` to `~/.config/experiences/credentials.json`, which persists across invocations until you change it again — it will not silently re-enable itself.
239
221
  - Per invocation:
240
222
 
241
223
  ```bash
package/dist/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@contentful/experience-design-system-cli",
3
- "version": "2.35.0-alpha.0",
3
+ "version": "2.35.0",
4
4
  "description": "Contentful Experiences design system import CLI",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -40,6 +40,7 @@
40
40
  "dependencies": {
41
41
  "@contentful/experience-design-system-cli-v2": "workspace:*",
42
42
  "@contentful/experience-design-system-types": "workspace:*",
43
+ "@inkjs/ui": "^2.0.0",
43
44
  "@segment/analytics-node": "^3.0.0",
44
45
  "@vue/compiler-sfc": "^3.5.31",
45
46
  "commander": "^13.1.0",
@@ -1,17 +1,11 @@
1
1
  /**
2
2
  * The CLI-owned composition interchange format (spec T1).
3
3
  *
4
- * Two views of the same data:
5
- * - `InterchangeMap` — the human-authored / on-disk `{ version, groups }`
6
- * shape (parent → children), consumed by the composition-map option.
7
- * `--composition-map` consumes and the resolver can emit.
8
- * - `CompositionEdge[]` — the flat internal runtime view, one edge per
9
- * parent→child relationship, carrying optional `slot` (T7), `confidence`,
10
- * and `provenance`. Easier to merge/dedupe across sources (T2).
11
- *
12
- * This module owns both shapes and the converters between them.
4
+ * `CompositionEdge[]` is the flat internal runtime view, one edge per
5
+ * parent→child relationship, carrying optional `slot` (T7), `confidence`,
6
+ * and `provenance`. It is easier to merge and dedupe across sources (T2).
13
7
  */
14
- export type EdgeProvenance = 'user' | 'typed-slot' | 'structural' | 'manifest' | 'doc' | `adapter:${string}` | 'agent';
8
+ export type EdgeProvenance = 'typed-slot' | 'structural' | 'manifest' | 'doc' | `adapter:${string}` | 'agent';
15
9
  export type CompositionEdge = {
16
10
  parent: string;
17
11
  child: string;
@@ -21,17 +15,3 @@ export type CompositionEdge = {
21
15
  confidence?: number;
22
16
  provenance: EdgeProvenance;
23
17
  };
24
- export type InterchangeMap = {
25
- version: 1;
26
- groups: Record<string, string[]>;
27
- };
28
- export type ValidateResult = {
29
- valid: true;
30
- map: InterchangeMap;
31
- } | {
32
- valid: false;
33
- errors: string[];
34
- };
35
- export declare function validateInterchangeMap(input: unknown): ValidateResult;
36
- export declare function groupsToEdges(map: InterchangeMap, provenance: EdgeProvenance): CompositionEdge[];
37
- export declare function edgesToGroups(edges: CompositionEdge[]): InterchangeMap;
@@ -1,18 +1,9 @@
1
- import { type InterchangeMap } from './interchange-schema.js';
2
1
  export type CompositionCliOptions = {
3
- /** `--composition-map <path>` — hand-authored interchange file. */
4
- compositionMap?: string;
5
2
  /** `--composition-refresh` — force edge emission to run even over resolved residue. */
6
3
  compositionRefresh?: boolean;
4
+ /** `--no-cache` — force the composition agent to rerun with the rest of the pipeline. */
5
+ noCache?: boolean;
7
6
  };
8
- export type LoadUserMapResult = {
9
- ok: true;
10
- map: InterchangeMap;
11
- } | {
12
- ok: false;
13
- error: string;
14
- };
15
- export declare function loadUserMap(path: string): Promise<LoadUserMapResult>;
16
7
  export type ResolvedCompositionSources = {
17
8
  forceAgent: boolean;
18
9
  };
@@ -1,9 +1,8 @@
1
1
  import type { RawComponentDefinition } from '../../types.js';
2
- import { type CompositionEdge, type InterchangeMap } from './interchange-schema.js';
2
+ import type { CompositionEdge } from './interchange-schema.js';
3
3
  import { type EdgeConflict } from './merge-edges.js';
4
4
  export type ResolveMappingResult = {
5
5
  components: RawComponentDefinition[];
6
- userMap?: InterchangeMap;
7
6
  edges: CompositionEdge[];
8
7
  conflicts: EdgeConflict[];
9
8
  warnings: string[];
@@ -11,9 +10,9 @@ export type ResolveMappingResult = {
11
10
  /**
12
11
  * Orchestrate composition-edge acquisition and enrichment.
13
12
  *
14
- * Sources by rank: user map (1) > typed-slot / "code slots" (2) > structural
15
- * usage evidence (3) > manifest (4) > doc (5) > adapter-resolved / extraEdges
16
- * (6) > edge-emitting agent (7). Manifest/doc edges are computed deterministically outside
13
+ * Sources by rank: typed-slot / "code slots" (2) > structural usage evidence
14
+ * (3) > manifest (4) > doc (5) > adapter-resolved / extraEdges (6) >
15
+ * edge-emitting agent (7). Manifest/doc edges are computed deterministically outside
17
16
  * this function (see manifest-doc-evidence.ts) and joined via `extraEdges`.
18
17
  * ALL sources — including the code slots already on the incoming components —
19
18
  * are fed into one ranked merge and unioned; non-conflicting edges from every
@@ -28,7 +27,6 @@ export type ResolveMappingResult = {
28
27
  */
29
28
  export declare function resolveMapping(input: {
30
29
  components: RawComponentDefinition[];
31
- userMap?: InterchangeMap;
32
30
  forceAgent?: boolean;
33
31
  files: Array<{
34
32
  path: string;
@@ -55,7 +53,7 @@ export declare function resolveMapping(input: {
55
53
  /**
56
54
  * Pre-resolved edges from an external source (e.g. manifest or documentation)
57
55
  * path). They join the ranked merge at their own provenance rank alongside
58
- * code slots and the user map.
56
+ * code slots and other automatic mapping sources.
59
57
  */
60
58
  extraEdges?: CompositionEdge[];
61
59
  }): Promise<ResolveMappingResult>;
@@ -1,3 +1,7 @@
1
1
  import type { Command } from 'commander';
2
+ export declare function resolveExtractNoCache(opts: {
3
+ cache?: boolean;
4
+ noCache?: boolean;
5
+ }): boolean;
2
6
  export declare function collectSourceFiles(directory: string, onProgress?: (scannedCount: number) => void): Promise<string[]>;
3
7
  export declare function registerInternalExtractCommand(program: Command): void;
@@ -17,6 +17,7 @@ export type FieldEditorProps = {
17
17
  value: string;
18
18
  width: number;
19
19
  height: number;
20
+ fixedHeight?: boolean;
20
21
  active?: boolean;
21
22
  onChange: (value: string) => void;
22
23
  onSave: () => void;
@@ -40,6 +41,7 @@ export type FieldEditorProps = {
40
41
  name: string;
41
42
  };
42
43
  showHiddenProps?: boolean;
44
+ showInlineRationales?: boolean;
43
45
  };
44
46
  export declare function simulateGraphWithCandidate(projectSlotGraph: ComponentSlotInfo[], selfName: string, currentSlots: {
45
47
  name: string;
@@ -58,5 +60,5 @@ export declare function computeAllowedComponentReplacementCandidates(projectSlot
58
60
  name: string;
59
61
  allowedComponents: string[];
60
62
  }[], targetSlotName: string, replaceIndex: number): string[];
61
- export declare function FieldEditor({ value, width, height, active, onChange, onSave, onDiscard, onExit, metadata, onTogglePropRationale, propRationaleKey, onToggleComponentRationale, componentRationaleKey, onToggleSourceExternal, onTextEntryActiveChange, projectSlotGraph, currentComponentName, onDirtyChange, discardTrigger, initialFocusTarget, showHiddenProps, }: FieldEditorProps): React.ReactElement;
63
+ export declare function FieldEditor({ value, width, height, fixedHeight, active, onChange, onSave, onDiscard, onExit, metadata, onTogglePropRationale, propRationaleKey, onToggleComponentRationale, componentRationaleKey, onToggleSourceExternal, onTextEntryActiveChange, projectSlotGraph, currentComponentName, onDirtyChange, discardTrigger, initialFocusTarget, showHiddenProps, showInlineRationales, }: FieldEditorProps): React.ReactElement;
62
64
  export {};
@@ -1,6 +1,6 @@
1
1
  import React from 'react';
2
2
  import type { ComponentTypeSummary } from '@contentful/experience-design-system-types';
3
- /** Max removed-component lines shown at once; the rest scroll with j/k.
3
+ /** Max removed-component lines shown at once; the rest scroll with arrow keys.
4
4
  * Exported so the parent's scroll-offset clamping stays in sync. */
5
5
  export declare const FINALIZE_REMOVED_WINDOW = 6;
6
6
  type FinalizeDialogProps = {
@@ -15,7 +15,7 @@ type FinalizeDialogProps = {
15
15
  /** Status of the accepted-set preview fired when the dialog opened. While
16
16
  * 'running', the deletion section shows a spinner instead of a (stale) list. */
17
17
  previewStatus?: 'idle' | 'running' | 'done' | 'error';
18
- /** Scroll offset into the removed list (owned by the parent; j/k adjust it). */
18
+ /** Scroll offset into the removed list (owned by the parent; arrow keys adjust it). */
19
19
  removedScrollOffset?: number;
20
20
  };
21
21
  export declare function FinalizeDialog({ accepted, rejected, needsReview, onConfirm, onCancel, removed, previewStatus, removedScrollOffset, }: FinalizeDialogProps): React.ReactElement;
@@ -17,6 +17,9 @@ export interface GroupedSidebarProps {
17
17
  expandedGroups: Set<string>;
18
18
  onToggleExpanded: (rootName: string) => void;
19
19
  width: number;
20
+ height?: number;
21
+ title?: string;
22
+ wrapLabels?: boolean;
20
23
  focused: boolean;
21
24
  renderStatusByKey?: Map<string, RenderStatus>;
22
25
  previewAnnotationByKey?: Map<string, PreviewAnnotation>;
@@ -10,10 +10,12 @@ type HelpOverlayProps = {
10
10
  mode: 'analyze' | 'validate' | 'review';
11
11
  sections?: undefined;
12
12
  onClose: () => void;
13
+ handleInput?: boolean;
13
14
  } | {
14
15
  mode?: undefined;
15
16
  sections: HelpSection[];
16
17
  onClose: () => void;
18
+ handleInput?: boolean;
17
19
  };
18
20
  export declare function HelpOverlay(props: HelpOverlayProps): React.ReactElement;
19
21
  export {};
@@ -7,8 +7,9 @@ export type PreviewBadgeValue = {
7
7
  bold?: boolean;
8
8
  dim?: boolean;
9
9
  };
10
- export declare function PreviewBadge({ badge }: {
10
+ export declare function PreviewBadge({ badge, highlighted, }: {
11
11
  badge: PreviewBadgeValue | null;
12
+ highlighted?: boolean;
12
13
  }): React.ReactElement;
13
14
  type SidebarProps = {
14
15
  components: ReviewComponentSummary[];
@@ -8,15 +8,16 @@
8
8
  * binding (caller should NOT update state in that case).
9
9
  *
10
10
  * Supported bindings:
11
- * - j / downArrow → +1 line
12
- * - k / upArrow → -1 line
11
+ * - downArrow → +1 line
12
+ * - upArrow → -1 line
13
13
  * - Ctrl+d → +half-page (floor(panelHeight / 2))
14
14
  * - Ctrl+u → -half-page
15
15
  * - PageDown → +panelHeight
16
16
  * - PageUp → -panelHeight
17
17
  * - G → jump to maxOffset
18
18
  *
19
- * `g` (single-tap) and `gg` (double-tap → jump to 0) are handled separately
19
+ * `j`/`k` are intentionally not handled here because they are field-navigation
20
+ * keys in the editor. `g` (single-tap) and `gg` (double-tap → jump to 0) are handled separately
20
21
  * by the caller via a pending-flag ref, since they need transient state.
21
22
  */
22
23
  export type ScrollKeyState = {
@@ -16,4 +16,4 @@ export type ImmediateInputKey = {
16
16
  meta: boolean;
17
17
  };
18
18
  export type ImmediateInputHandler = (input: string, key: ImmediateInputKey) => void;
19
- export declare function useImmediateInput(handler: ImmediateInputHandler): void;
19
+ export declare function useImmediateInput(handler: ImmediateInputHandler, enabled?: boolean): void;
@@ -1,4 +1,3 @@
1
- import { type CompositionMode } from './lib/composition-mode.js';
2
1
  export type ExperiencesCredentials = {
3
2
  spaceId: string;
4
3
  environmentId: string;
@@ -8,31 +7,12 @@ export type ExperiencesCredentials = {
8
7
  agentModel?: string;
9
8
  /** Feature 8: persisted custom prompt path for `generate components`. */
10
9
  generatePromptPath?: string;
11
- /** Feature: default debug-mode (writes JSONL trace of every decision) for all commands. */
10
+ /** Write JSONL trace of every command decision to ~/.contentful/experience-design-system-cli/debug/. */
12
11
  debug?: boolean;
13
- /** Persisted opt-out for anonymous CLI usage analytics, set via `experiences setup`. */
12
+ /** Print plain text with no color; an exported NO_COLOR still wins. */
13
+ noColor?: boolean;
14
14
  analyticsDisabled?: boolean;
15
- /**
16
- * Feature (atomic mode): default composition mode. `atomic` (default) imports
17
- * flat components with no embedded-component hierarchy; `composite` opts into
18
- * the slot-graph machinery. Resolved `flag > env > this > default`.
19
- */
20
- compositionMode?: CompositionMode;
21
15
  };
22
- /**
23
- * Read persisted Contentful credentials.
24
- *
25
- * Precedence (INTEG-4410): what the operator saved on disk via
26
- * `experiences setup` or the wizard's credentials step wins over ambient
27
- * `CONTENTFUL_*` / `EDS_HOST` env vars. Env vars are still consulted as a
28
- * fallback when the field on disk is missing or empty — this preserves
29
- * back-compat for CI / scripts that only export env and never call setup.
30
- *
31
- * The pre-INTEG-4410 order (env-first) silently shadowed saved values, so
32
- * operators who saved a different space via setup kept seeing the env one
33
- * pre-filled in the wizard. The saved value now wins; the env fallback only
34
- * fires when the on-disk field is empty.
35
- */
36
16
  export declare function readExperiencesCredentials(): Promise<ExperiencesCredentials>;
37
17
  export declare function writeExperiencesCredentials(creds: ExperiencesCredentials): Promise<void>;
38
18
  export declare function experiencesCredentialsPath(): string;
@@ -0,0 +1,5 @@
1
+ export declare function reportNode(): Promise<boolean>;
2
+ export declare function reportPnpm(pkgRoot: string): Promise<boolean>;
3
+ export declare function reportDependencies(pkgRoot: string): Promise<boolean>;
4
+ export declare function reportBuild(pkgRoot: string): Promise<boolean>;
5
+ export declare function reportAgent(): Promise<boolean>;
@@ -0,0 +1,2 @@
1
+ import type { Command } from 'commander';
2
+ export declare function registerDoctorCommand(program: Command): void;
@@ -0,0 +1,7 @@
1
+ export declare function ok(msg: string): void;
2
+ export declare function fail(msg: string): void;
3
+ export declare function warn(msg: string): void;
4
+ export declare function info(msg: string): void;
5
+ export declare function section(title: string): void;
6
+ /** Echo the first `limit` lines of a failed command's stderr. */
7
+ export declare function infoStderr(stderr: string, limit: number): void;
@@ -1,11 +1,11 @@
1
1
  /**
2
- * Resolution chain for `--agent` and `--model` overrides on `experiences import`.
2
+ * Resolution chain for the combined `--agent` override on `experiences import`.
3
3
  *
4
4
  * The wizard path previously hard-defaulted `--agent` to `'claude'` at the
5
5
  * commander layer, which (a) shadowed the stored `credentials.json` value when
6
6
  * the user passed no flag, and (b) made it impossible to distinguish "user
7
- * explicitly passed --agent claude" from "user passed nothing". `--model` was
8
- * registered but never threaded into the wizard subprocesses at all.
7
+ * explicitly passed --agent claude" from "user passed nothing". The combined
8
+ * flag accepts either `agent:model` or `agent model`.
9
9
  *
10
10
  * These helpers produce the resolved values to feed into `WizardApp` /
11
11
  * the import wizard:
@@ -15,9 +15,13 @@
15
15
  * `experiences setup`) is used.
16
16
  * 3. Otherwise, the built-in default (currently `'claude'`) is used for
17
17
  * the agent. Model has no default — agents pick a small/fast model
18
- * themselves when `--model` is omitted.
18
+ * themselves when no model is included in `--agent`.
19
19
  */
20
20
  /** Built-in fallback agent when neither a flag nor a stored preference is set. */
21
21
  export declare const DEFAULT_AGENT = "claude";
22
+ export declare function parseAgentModel(value: string | undefined): {
23
+ agent?: string;
24
+ model?: string;
25
+ };
22
26
  export declare function resolveAgent(flagValue: string | undefined, storedValue: string | undefined): string;
23
27
  export declare function resolveModel(flagValue: string | undefined, storedValue: string | undefined): string | undefined;
@@ -1,9 +1,7 @@
1
1
  export type CompositionOptionInput = {
2
- compositionMap?: string;
3
2
  prompt?: string[];
4
3
  };
5
4
  export type CompositionForwardingOptions = {
6
- compositionMap?: string;
7
5
  promptOverrides?: string[];
8
6
  };
9
7
  export declare function buildCompositionForwardingOptions(options: CompositionOptionInput): CompositionForwardingOptions;