feat(init): detect agent/CI environments and skip interactive prompts#1264
feat(init): detect agent/CI environments and skip interactive prompts#1264
Conversation
Uses `std-env` v4's `isAgent`, `isCI`, and `hasTTY` to automatically detect when the CLI is run non-interactively (AI agents, CI pipelines, piped input) and apply sensible defaults instead of hanging on prompts. Adds two explicit flags for opt-in: - `--defaults` / `-y`: accept all defaults (like `npm init -y`) - `--no-interactive`: same, more explicit for scripting contexts When non-interactive mode is detected, the CLI: - Logs the reason (agent name, CI, no TTY, or flag) - Displays a full options reference — including all available templates fetched live — so agents can discover flags and re-run with custom settings - Auto-selects: template=minimal, dir=template's defaultDir, package manager=detected or npm, gitInit=false, modules=skipped - Fails fast (instead of hanging) when the target directory already exists, instructing the caller to pass `--force` All existing interactive behaviour is preserved when a TTY is present and none of the new flags are set. https://claude.ai/code/session_01LsDZBSg7peDmxh6QW33ag8
- Move detectCurrentPackageManager() before template load so package manager is known upfront - Compute all effective defaults (template, dir, pm, gitInit, install, modules) before any action is taken and display them together in a 'Proceeding with:' section at the bottom of the options note - Show all available templates with the default marked (← default) - Fix module examples to use @nuxt/content,@nuxt/ui,@nuxt/image - Remove scattered 'Auto-selected X' log lines — they are now covered by the single consolidated note - Simplify the non-interactive module-skip branch https://claude.ai/code/session_01LsDZBSg7peDmxh6QW33ag8
When running non-interactively (agent/CI/no-TTY) without a project directory, show the available options note then exit cleanly instead of proceeding with defaults. The agent reads the output, chooses the right flags, and re-runs with an explicit <dir>. nuxi init → shows options, exits (no project created) nuxi init my-app → creates my-app with defaults nuxi init my-app -t v3 → creates my-app with v3 template https://claude.ai/code/session_01LsDZBSg7peDmxh6QW33ag8
commit: |
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Organization UI Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (1)
🚧 Files skipped from review as they are similar to previous changes (1)
📝 WalkthroughWalkthroughAdds Estimated code review effort🎯 3 (Moderate) | ⏱️ ~20 minutes 🚥 Pre-merge checks | ✅ 3✅ Passed checks (3 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 1
🧹 Nitpick comments (1)
packages/nuxi/src/commands/init.ts (1)
174-223: Consider centralizing resolved defaults to avoid drift between “note” and execution paths.Effective values are computed in the note block and then re-derived later for actual execution. A single
resolvedOptionsobject would reduce maintenance risk.Also applies to: 236-240, 271-276, 443-448, 465-469
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@packages/nuxi/src/commands/init.ts` around lines 174 - 223, Create a single resolvedOptions object (e.g. { template, dir, packageManager, gitInit, install, modules, offline, force }) computed once in init.ts and replace the duplicated local computations (the variables effectiveTemplate, effectiveDir, effectivePM, effectiveGitInit, effectiveInstall, effectiveModules) so both the non-interactive "note" block and the later execution paths reuse the same resolvedOptions; update all referenced sites (the note block and the other duplicated ranges you flagged around lines 236-240, 271-276, 443-448, 465-469) to read from resolvedOptions to avoid drift and ensure consistent defaults across the codepaths.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@packages/nuxi/src/commands/init.ts`:
- Around line 130-135: The multiline boolean assignment for const
isNonInteractive (and the other multiline boolean expression further down) has
inconsistent indentation that breaks ESLint; reformat these expressions so
continuation lines are consistently indented — either align each boolean operand
under the first operand or wrap the RHS in parentheses and indent each
subsequent line one level (e.g., two spaces or one tab) so the operators (||)
and the operands line up consistently; update the lines that contain
isNonInteractive and the similar boolean block near the later expression to
match the project's multiline indentation style.
---
Nitpick comments:
In `@packages/nuxi/src/commands/init.ts`:
- Around line 174-223: Create a single resolvedOptions object (e.g. { template,
dir, packageManager, gitInit, install, modules, offline, force }) computed once
in init.ts and replace the duplicated local computations (the variables
effectiveTemplate, effectiveDir, effectivePM, effectiveGitInit,
effectiveInstall, effectiveModules) so both the non-interactive "note" block and
the later execution paths reuse the same resolvedOptions; update all referenced
sites (the note block and the other duplicated ranges you flagged around lines
236-240, 271-276, 443-448, 465-469) to read from resolvedOptions to avoid drift
and ensure consistent defaults across the codepaths.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: dfda46aa-f2f3-4a95-b0f4-36571b8806e5
📒 Files selected for processing (1)
packages/nuxi/src/commands/init.ts
…ndition The original condition (!template || !dir) already covers every case where templates need to be loaded for prompts or the options note. Adding isNonInteractive caused an unnecessary network fetch when an agent provided both --template and dir (only to populate a template list in the note that wasn't needed). The 'Proceeding with:' section in the note still works correctly without it. https://claude.ai/code/session_01LsDZBSg7peDmxh6QW33ag8
There was a problem hiding this comment.
Actionable comments posted: 1
🧹 Nitpick comments (1)
packages/nuxi/src/commands/init.ts (1)
188-189: Consider extracting the string 'false' coercion pattern.The
(ctx.args.gitInit as unknown) === 'false'pattern appears multiple times (here, line 465, line 487). A small helper liketoBool(value)could reduce duplication and clarify intent.♻️ Optional: Extract helper function
// Add near the top of the file or in a shared utils function parseBoolArg(value: unknown): boolean | undefined { if (value === 'false') return false if (value === 'true') return true return value as boolean | undefined }🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@packages/nuxi/src/commands/init.ts` around lines 188 - 189, The code duplicates a string-'false' coercion pattern when computing effectiveGitInit and effectiveInstall; extract a small helper (e.g., parseBoolArg or toBool) that accepts unknown and returns boolean | undefined by mapping 'false'->false, 'true'->true and otherwise returning the value as boolean | undefined, then replace the inline checks in effectiveGitInit and effectiveInstall (and any other occurrences like the ones noted around lines using ctx.args.gitInit / ctx.args.install) to call that helper to reduce duplication and clarify intent.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@packages/nuxi/src/commands/init.ts`:
- Around line 274-276: The if-branch that sets dir = defaultDir when
isNonInteractive is unreachable and should be removed; locate the conditional
using isNonInteractive and dir (the block "if (isNonInteractive) { dir =
defaultDir }") in the init command and delete that branch so the code flow
relies on the existing early-exit behavior around ctx.args.dir, or if you intend
non-interactive to auto-select a directory instead, adjust the earlier
early-exit logic that checks ctx.args.dir rather than keeping this unreachable
fallback.
---
Nitpick comments:
In `@packages/nuxi/src/commands/init.ts`:
- Around line 188-189: The code duplicates a string-'false' coercion pattern
when computing effectiveGitInit and effectiveInstall; extract a small helper
(e.g., parseBoolArg or toBool) that accepts unknown and returns boolean |
undefined by mapping 'false'->false, 'true'->true and otherwise returning the
value as boolean | undefined, then replace the inline checks in effectiveGitInit
and effectiveInstall (and any other occurrences like the ones noted around lines
using ctx.args.gitInit / ctx.args.install) to call that helper to reduce
duplication and clarify intent.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: 3ee15017-9503-4ce1-a8d1-f4ac2d4094fc
📒 Files selected for processing (1)
packages/nuxi/src/commands/init.ts
| if (isNonInteractive) { | ||
| dir = defaultDir | ||
| } |
There was a problem hiding this comment.
Unreachable code: this branch can never execute.
In non-interactive mode, if ctx.args.dir is empty (the '' default), the code exits early at lines 230-233. Therefore, the isNonInteractive branch here for dir === '' is dead code since we'd never reach this point with an empty dir in non-interactive mode.
This doesn't break anything but adds confusion. Consider removing this branch or adjusting the early exit logic if you want non-interactive mode to auto-select a directory.
🧹 Proposed fix: Remove unreachable branch
let dir = ctx.args.dir
if (dir === '') {
const defaultDir = availableTemplates[templateName]?.defaultDir || 'nuxt-app'
- if (isNonInteractive) {
- dir = defaultDir
- }
- else {
- const result = await text({
- message: 'Where would you like to create your project?',
- placeholder: `./${defaultDir}`,
- defaultValue: defaultDir,
- })
-
- if (isCancel(result)) {
- cancel('Operation cancelled.')
- process.exit(1)
- }
-
- dir = result
- }
+ // In non-interactive mode, we exit early at line 230-233 if no dir provided
+ const result = await text({
+ message: 'Where would you like to create your project?',
+ placeholder: `./${defaultDir}`,
+ defaultValue: defaultDir,
+ })
+
+ if (isCancel(result)) {
+ cancel('Operation cancelled.')
+ process.exit(1)
+ }
+
+ dir = result
}📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| if (isNonInteractive) { | |
| dir = defaultDir | |
| } | |
| let dir = ctx.args.dir | |
| if (dir === '') { | |
| const defaultDir = availableTemplates[templateName]?.defaultDir || 'nuxt-app' | |
| // In non-interactive mode, we exit early at line 230-233 if no dir provided | |
| const result = await text({ | |
| message: 'Where would you like to create your project?', | |
| placeholder: `./${defaultDir}`, | |
| defaultValue: defaultDir, | |
| }) | |
| if (isCancel(result)) { | |
| cancel('Operation cancelled.') | |
| process.exit(1) | |
| } | |
| dir = result | |
| } |
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@packages/nuxi/src/commands/init.ts` around lines 274 - 276, The if-branch
that sets dir = defaultDir when isNonInteractive is unreachable and should be
removed; locate the conditional using isNonInteractive and dir (the block "if
(isNonInteractive) { dir = defaultDir }") in the init command and delete that
branch so the code flow relies on the existing early-exit behavior around
ctx.args.dir, or if you intend non-interactive to auto-select a directory
instead, adjust the earlier early-exit logic that checks ctx.args.dir rather
than keeping this unreachable fallback.
📦 Bundle Size Comparison📈 nuxi
📈 nuxt-cli
📈 create-nuxt
|
Uses
std-envv4'sisAgent,isCI, andhasTTYto automaticallydetect when the CLI is run non-interactively (AI agents, CI pipelines,
piped input) and apply sensible defaults instead of hanging on prompts.
Adds two explicit flags for opt-in:
--defaults/-y: accept all defaults (likenpm init -y)--no-interactive: same, more explicit for scripting contextsWhen non-interactive mode is detected, the CLI:
fetched live — so agents can discover flags and re-run with custom
settings
manager=detected or npm, gitInit=false, modules=skipped
exists, instructing the caller to pass
--forceAll existing interactive behaviour is preserved when a TTY is present
and none of the new flags are set.
https://claude.ai/code/session_01LsDZBSg7peDmxh6QW33ag8