-
-
Notifications
You must be signed in to change notification settings - Fork 166
fix(cli): default to interactive mode and add missing prompts #435
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,12 @@ | ||
| --- | ||
| '@tanstack/cli': patch | ||
| --- | ||
|
|
||
| Fix interactive mode not prompting for all options. | ||
|
|
||
| - Default to interactive mode. Previously, `tanstack create my-app` silently applied defaults for framework, deployment, and install. Opt out with `--yes` / `--non-interactive`. | ||
| - Add framework selection prompt when the CLI supports multiple frameworks and no `--framework` flag is passed. | ||
| - Add "install dependencies now?" prompt when `--no-install` is not passed. | ||
| - Show deployment adapter prompt by default (previously required `showDeploymentOptions: true`). | ||
| - Honor `forcedDeployment` as the default selection in the deployment prompt, so deprecated aliases keep a sensible default. | ||
| - Preserve explicit `--add-ons` arrays instead of overwriting them with the interactive sentinel. |
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -3,6 +3,7 @@ import { intro } from '@clack/prompts' | |||||||||||||||||||||||||||
| import { | ||||||||||||||||||||||||||||
| finalizeAddOns, | ||||||||||||||||||||||||||||
| getFrameworkById, | ||||||||||||||||||||||||||||
| getFrameworks, | ||||||||||||||||||||||||||||
| getPackageManager, | ||||||||||||||||||||||||||||
| loadStarter, | ||||||||||||||||||||||||||||
| populateAddOnOptionsDefaults, | ||||||||||||||||||||||||||||
|
|
@@ -16,7 +17,9 @@ import { | |||||||||||||||||||||||||||
| selectAddOns, | ||||||||||||||||||||||||||||
| selectDeployment, | ||||||||||||||||||||||||||||
| selectExamples, | ||||||||||||||||||||||||||||
| selectFramework, | ||||||||||||||||||||||||||||
| selectGit, | ||||||||||||||||||||||||||||
| selectInstall, | ||||||||||||||||||||||||||||
| selectPackageManager, | ||||||||||||||||||||||||||||
| selectTemplate, | ||||||||||||||||||||||||||||
| selectToolchain, | ||||||||||||||||||||||||||||
|
|
@@ -39,15 +42,31 @@ export async function promptForCreateOptions( | |||||||||||||||||||||||||||
| cliOptions: CliOptions, | ||||||||||||||||||||||||||||
| { | ||||||||||||||||||||||||||||
| forcedAddOns = [], | ||||||||||||||||||||||||||||
| showDeploymentOptions = false, | ||||||||||||||||||||||||||||
| forcedDeployment, | ||||||||||||||||||||||||||||
| showDeploymentOptions = true, | ||||||||||||||||||||||||||||
| defaultFrameworkId, | ||||||||||||||||||||||||||||
| }: { | ||||||||||||||||||||||||||||
| forcedAddOns?: Array<string> | ||||||||||||||||||||||||||||
| forcedDeployment?: string | ||||||||||||||||||||||||||||
| showDeploymentOptions?: boolean | ||||||||||||||||||||||||||||
| defaultFrameworkId?: string | ||||||||||||||||||||||||||||
| }, | ||||||||||||||||||||||||||||
| ): Promise<Required<Options> | undefined> { | ||||||||||||||||||||||||||||
| const options = {} as Required<Options> | ||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||
| options.framework = getFrameworkById(cliOptions.framework || 'react')! | ||||||||||||||||||||||||||||
| if (cliOptions.framework) { | ||||||||||||||||||||||||||||
| options.framework = getFrameworkById(cliOptions.framework)! | ||||||||||||||||||||||||||||
| } else { | ||||||||||||||||||||||||||||
| const availableFrameworks = getFrameworks() | ||||||||||||||||||||||||||||
| if (defaultFrameworkId || availableFrameworks.length <= 1) { | ||||||||||||||||||||||||||||
| options.framework = getFrameworkById(defaultFrameworkId || 'react')! | ||||||||||||||||||||||||||||
| } else { | ||||||||||||||||||||||||||||
|
Comment on lines
+61
to
+63
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Auto-pick the lone available framework instead of hard-coding When there is exactly one available framework and Suggested fix- if (defaultFrameworkId || availableFrameworks.length <= 1) {
- options.framework = getFrameworkById(defaultFrameworkId || 'react')!
- } else {
+ if (defaultFrameworkId) {
+ options.framework = getFrameworkById(defaultFrameworkId)!
+ } else if (availableFrameworks.length === 1) {
+ options.framework = availableFrameworks[0]!
+ } else {
options.framework = await selectFramework(
availableFrameworks,
defaultFrameworkId,
)
}📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents |
||||||||||||||||||||||||||||
| options.framework = await selectFramework( | ||||||||||||||||||||||||||||
| availableFrameworks, | ||||||||||||||||||||||||||||
| defaultFrameworkId, | ||||||||||||||||||||||||||||
| ) | ||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||
| // Validate project name | ||||||||||||||||||||||||||||
| if (cliOptions.projectName) { | ||||||||||||||||||||||||||||
|
|
@@ -130,11 +149,20 @@ export async function promptForCreateOptions( | |||||||||||||||||||||||||||
| ) | ||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||
| // Deployment selection | ||||||||||||||||||||||||||||
| const deployment = showDeploymentOptions | ||||||||||||||||||||||||||||
| ? routerOnly | ||||||||||||||||||||||||||||
| ? undefined | ||||||||||||||||||||||||||||
| : await selectDeployment(options.framework, cliOptions.deployment) | ||||||||||||||||||||||||||||
| : undefined | ||||||||||||||||||||||||||||
| let deployment: string | undefined | ||||||||||||||||||||||||||||
| if (routerOnly) { | ||||||||||||||||||||||||||||
| deployment = undefined | ||||||||||||||||||||||||||||
| } else if (cliOptions.deployment) { | ||||||||||||||||||||||||||||
| deployment = cliOptions.deployment | ||||||||||||||||||||||||||||
| } else if (showDeploymentOptions) { | ||||||||||||||||||||||||||||
| deployment = await selectDeployment( | ||||||||||||||||||||||||||||
| options.framework, | ||||||||||||||||||||||||||||
| cliOptions.deployment, | ||||||||||||||||||||||||||||
| forcedDeployment, | ||||||||||||||||||||||||||||
| ) | ||||||||||||||||||||||||||||
| } else { | ||||||||||||||||||||||||||||
| deployment = forcedDeployment | ||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||
| // Add-ons selection | ||||||||||||||||||||||||||||
| const addOns: Set<string> = new Set() | ||||||||||||||||||||||||||||
|
|
@@ -226,9 +254,7 @@ export async function promptForCreateOptions( | |||||||||||||||||||||||||||
| envVarValues | ||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||
| options.git = cliOptions.git ?? (await selectGit()) | ||||||||||||||||||||||||||||
| if (cliOptions.install === false) { | ||||||||||||||||||||||||||||
| options.install = false | ||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||
| options.install = cliOptions.install ?? (await selectInstall()) | ||||||||||||||||||||||||||||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🧩 Analysis chain🌐 Web query:
💡 Result: In Commander.js, an option defined only as --no-install (a negatable boolean option defined alone) has the value true when the user does not pass the flag. This is the documented behavior for negatable boolean options: "You can define a boolean option long name with a leading no- to set the option value to false when used. Defined alone, this also makes the option true by default." The option name is install, so without --no-install the value is true (install), and with --no-install it is false (no install). This behavior has been consistent since at least v4 and remains in the latest documentation (v14+). If both --install and --no-install were defined, the default would be undefined unless explicitly set. Citations:
🏁 Script executed: #!/bin/bash
# Check the install option definition in cli.ts
echo "=== Checking cli.ts for install flag definition ==="
if [ -f "packages/cli/src/cli.ts" ]; then
grep -n "install" packages/cli/src/cli.ts | head -20
else
echo "File not found: packages/cli/src/cli.ts"
fiRepository: TanStack/cli Length of output: 580 🏁 Script executed: #!/bin/bash
# Check options.ts around line 257
echo "=== Checking options.ts around line 257 ==="
if [ -f "packages/cli/src/options.ts" ]; then
wc -l packages/cli/src/options.ts
echo ""
sed -n '250,265p' packages/cli/src/options.ts
else
echo "File not found: packages/cli/src/options.ts"
fiRepository: TanStack/cli Length of output: 552
The Commander.js option at You need either:
🤖 Prompt for AI Agents |
||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||
| if (starter) { | ||||||||||||||||||||||||||||
| options.starter = starter | ||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Preserving
--add-onsarrays here also suppresses later add-on config/env-var prompts.After this change,
Array.isArray(cliOptions.addOns)no longer means “non-interactive”.packages/cli/src/options.tsstill uses that check to skippromptForAddOnOptions()andpromptForEnvVars(), so an interactive run liketanstack create my-app --add-ons authwill silently take defaults and can miss required env vars.🤖 Prompt for AI Agents