FAQ
Common questions and behaviors that surprise operators the first time they run experiences import.
Does the AI regenerate my components on every run?
Yes — the generate step runs the LLM every time you start a fresh experiences import session, even when your source code has not changed. This is different from the AI auto-filter, which caches decisions per component and only re-runs when the source changes.
If you want to reuse a prior generation without invoking the agent again, replay a recorded run:
Does apply push delete components I no longer include?
Yes. apply push reconciles your Contentful space with the manifest you submit. Any component that exists in your target space but is not present in the manifest is deleted — including components you rejected at the scope gate or removed from an exported components.json.
Preview the diff with apply preview (or read the diff banner in the wizard’s Final review step) before pushing, to confirm the set of creates, updates, and deletes.
What’s the difference between atomic and composite mode?
An atomic import, the default, extracts your components as a flat list with no embedded-component hierarchy. A composite import reads the slot relationships between your components and imports a parent together with everything it slots, that nesting intact. Opt into composite mode with --composite, or with any composition flag, which implies it.
Use atomic when a flat list of components is enough. Use composite when your components embed other components and you want that hierarchy carried into Contentful. See Coded components.
My composite import won’t push, it reports a slot dependency cycle
A slot dependency cycle is a loop in the component hierarchy, where component A slots B, and B slots A, directly or through a longer chain such as Card → Media → Banner → Card. Contentful can’t create components with circular slot references, so the CLI blocks the push before it reaches Contentful and names the components in the loop.
Resolve the cycle before pushing, as described in the next question.
How do I break a slot dependency cycle?
You have three options in the wizard’s final review step:
- Break an edge from the cycles panel — open the break-cycle overlay from the cycles panel, pick a slot relationship to remove, and confirm. This deletes one allowed-component reference and clears the cycle without dropping any component.
- Break an edge in the field editor — open a component in the cycle and remove the offending entry from the allowed components of the slot that closes the loop. Same effect, edited by hand.
- Reject a member — reject one of the components in the cycle to remove it from the import along with the loop.
The recommended workflow is to accept the cycle members together into final review, then break an edge, from the cycles panel or by editing a slot in the field editor, so you keep every component and drop only the relationship that closed the loop.
On the headless path, pass --auto-reject-cycles to automatically exclude the components in a cycle and continue. See Slot dependency cycles.
I ran composite mode but the CLI found no hierarchy, why?
Composite mode reads the hierarchy from the typed slots your components declare, whether a React prop typed as ReactElement<ButtonProps>, a Svelte Snippet, or a @allowedComponents annotation. When your codebase does not declare slots this way, typed-slot extraction finds nothing, which is expected.
For codebases that do not declare typed slots, supply the hierarchy another way: author a composition map and pass it with --composition-map, or let a coding agent infer it with --composition-agent. See Where the hierarchy comes from.
My saved credentials aren’t being used — why?
Credentials resolve in a fixed order that depends on how you launched the CLI:
Interactive experiences import (the wizard): the values you entered in the wizard’s Credentials step during this run win, followed by values saved via experiences setup (on disk at ~/.config/experiences/credentials.json), followed by CONTENTFUL_SPACE_ID / CONTENTFUL_ENVIRONMENT_ID / CONTENTFUL_MANAGEMENT_TOKEN / EDS_HOST environment variables. Environment variables are only consulted when the saved value for that field is empty.
Headless / individual commands (apply preview, apply select, apply push, --push-from-run, --skip-*, and non-interactive experiences import): command-line flags win, then environment variables. Saved values from experiences setup are not consulted on the headless path — pass credentials via flags or environment variables.
When any of the CONTENTFUL_* or EDS_HOST env vars are set in your shell, experiences setup prints a warning so the shadowing behavior is visible. See Credential precedence for the full detail.
experiences import --modify shows the wrong space or environment
The modify entry pre-fills credentials from the recorded run’s last push target. If the recorded run has never been pushed successfully, that field is empty and the CLI falls back to experiences setup values on disk. If both are wrong, correct the values by editing ~/.config/experiences/credentials.json (or re-running experiences setup) before invoking --modify again.
A component I want is marked “failed” at the scope gate
The AI auto-filter batches component decisions to reduce the number of LLM calls. Occasionally a batched response omits a decision for one of the components in the batch — that component surfaces at the scope gate as failed in the AI-recommended-exclusions section and defaults to excluded. This is safe-by-default behavior; the CLI never silently includes a component the AI failed to classify.
To include a “failed” component, accept it manually at the scope gate (either individually or via accept-all).
My run is marked STALE — what does that mean?
Every recorded run stores short hashes — called fingerprints — of the source files at extraction time and the saved artifact files at save time. When you replay a run whose source or saved files have changed on disk since the run was recorded, the CLI compares the current files against the stored fingerprints, refuses with a STALE notice, and lists which files drifted. This protects against replays that no longer match the recorded manifest.
Re-extract with experiences import --project <path> for a fresh run, or bypass the check with --force:
The STALE column in experiences runs summarizes drift per recorded run.
I skipped credentials — can I push later?
Yes. When you press the skip key at the credentials step, the wizard runs in save-only mode: components.json and tokens.json are written to disk, the run is recorded as not pushed, and the prefetched generation is preserved. Push the recorded run later without re-generating:
Where’s the debug log?
experiences <command> --debug (or EDSI_DEBUG=1 experiences <command>) writes a JSONL trace of every decision — agent calls, tool calls, apply actions, filter decisions — to ~/.contentful/experience-design-system-cli/debug/<timestamp>-<command>.jsonl. Secrets are redacted. See Debug logging.
Why does extraction take so long on my machine?
experiences analyze extract parses component source files in parallel. Set EDS_EXTRACT_CONCURRENCY to control the parallelism (default 4, experiences setup offers to write 8). On machines with more CPU cores available, increasing this reduces wall-clock time:
The standalone experiences analyze select TUI overwrote my edits
Manual edits made in experiences analyze select are not guaranteed to survive downstream generation — the generation agent runs afterwards and re-derives component definitions from source. Use the wizard’s Final review step for edits you want preserved through save and push. See Run the pipeline step by step for context on the standalone TUI.
Do I have to use Claude? Can I use a different agent?
The CLI supports four coding agents: claude, codex, opencode, and cursor. Select a default with experiences setup and override per invocation with --agent <name>. --model <name> sets the model for the selected agent; each agent uses a default lightweight model when the flag is omitted. See Command reference.