From 22454706d4639a75fbd19b1a78ae8c8e7c907ba3 Mon Sep 17 00:00:00 2001 From: Claude Date: Thu, 30 Apr 2026 21:57:28 +0000 Subject: [PATCH 1/3] feat(cli): auto-install TanStack Intent during scaffolding Run `npx @tanstack/intent install` after `tanstack create` and `tanstack add`, gated by a new `--intent` / `--no-intent` flag (default on). Failures are reported as warnings so they don't block scaffolding. https://claude.ai/code/session_01KZU2LM3E8hncoXxZguUu8P --- packages/cli/src/cli.ts | 22 ++++++++- packages/cli/src/command-line.ts | 1 + packages/cli/src/dev-watch.ts | 1 + packages/cli/src/types.ts | 1 + packages/create/src/add-to-app.ts | 7 +++ packages/create/src/create-app.ts | 3 ++ packages/create/src/custom-add-ons/shared.ts | 2 + packages/create/src/integrations/intent.ts | 47 ++++++++++++++++++++ packages/create/src/types.ts | 1 + 9 files changed, 84 insertions(+), 1 deletion(-) create mode 100644 packages/create/src/integrations/intent.ts diff --git a/packages/cli/src/cli.ts b/packages/cli/src/cli.ts index 31815a13..164a1f5f 100644 --- a/packages/cli/src/cli.ts +++ b/packages/cli/src/cli.ts @@ -183,6 +183,7 @@ function getCreateTelemetryProperties(projectName: string, options: CliOptions) framework: options.framework ? sanitizeId(options.framework) : undefined, git: options.git, install: options.install !== false, + intent: options.intent !== false, interactive: !!options.interactive, json: !!options.json, non_interactive: !!options.nonInteractive || !!options.yes, @@ -221,6 +222,7 @@ function getResolvedCreateTelemetryProperties( framework: sanitizeId(finalOptions.framework.id), git: finalOptions.git, install: finalOptions.install !== false, + intent: finalOptions.intent, package_manager: finalOptions.packageManager, router_only: !!cliOptions.routerOnly, toolchain: toolchain ? sanitizeId(toolchain.id) : undefined, @@ -875,6 +877,14 @@ export function cli({ .option('--json', 'output JSON for automation', false) .option('--git', 'create a git repository') .option('--no-git', 'do not create a git repository') + .option( + '--intent', + 'set up TanStack Intent skill mappings for coding agents', + ) + .option( + '--no-intent', + 'skip TanStack Intent setup', + ) .option( '--target-dir ', 'the target directory for the application root', @@ -1441,7 +1451,15 @@ Remove your node_modules directory and package lock file and re-install.`, 'Name of the add-ons (or add-ons separated by spaces or commas)', ) .option('--forced', 'Force the add-on to be added', false) - .action(async (addOns: Array, options: { forced: boolean }) => { + .option( + '--intent', + 'set up TanStack Intent skill mappings for coding agents', + ) + .option( + '--no-intent', + 'skip TanStack Intent setup', + ) + .action(async (addOns: Array, options: { forced: boolean; intent?: boolean }) => { try { await runWithTelemetry( 'add', @@ -1472,6 +1490,7 @@ Remove your node_modules directory and package lock file and re-install.`, if (selectedAddOns.length) { await addToApp(environment, selectedAddOns, resolve(process.cwd()), { forced: options.forced, + intent: options.intent, }) } return @@ -1484,6 +1503,7 @@ Remove your node_modules directory and package lock file and re-install.`, }) await addToApp(environment, parsedAddOns, resolve(process.cwd()), { forced: options.forced, + intent: options.intent, }) }, ) diff --git a/packages/cli/src/command-line.ts b/packages/cli/src/command-line.ts index ebf080b5..08fd3dc7 100644 --- a/packages/cli/src/command-line.ts +++ b/packages/cli/src/command-line.ts @@ -546,6 +546,7 @@ export async function normalizeOptions( DEFAULT_PACKAGE_MANAGER, git: cliOptions.git ?? true, install: cliOptions.install, + intent: cliOptions.intent ?? true, chosenAddOns, addOnOptions: { ...populateAddOnOptionsDefaults(chosenAddOns), diff --git a/packages/cli/src/dev-watch.ts b/packages/cli/src/dev-watch.ts index d03768e4..92062892 100644 --- a/packages/cli/src/dev-watch.ts +++ b/packages/cli/src/dev-watch.ts @@ -272,6 +272,7 @@ export class DevWatchManager { targetDir: this.tempDir, git: false, install: packageMetadataChanged, + intent: false, } // Show package installation indicator if needed diff --git a/packages/cli/src/types.ts b/packages/cli/src/types.ts index d27a0f3b..e736cf0b 100644 --- a/packages/cli/src/types.ts +++ b/packages/cli/src/types.ts @@ -20,6 +20,7 @@ export interface CliOptions { devWatch?: string runDev?: boolean install?: boolean + intent?: boolean addOnConfig?: string force?: boolean routerOnly?: boolean diff --git a/packages/create/src/add-to-app.ts b/packages/create/src/add-to-app.ts index 371aad0c..af4e224a 100644 --- a/packages/create/src/add-to-app.ts +++ b/packages/create/src/add-to-app.ts @@ -18,6 +18,7 @@ import { import { mergePackageJSON } from './package-json.js' import { runSpecialSteps } from './special-steps/index.js' import { loadStarter } from './custom-add-ons/starter.js' +import { setupIntent } from './integrations/intent.js' import type { Environment, Options } from './types.js' import type { PersistedOptions } from './config-file.js' @@ -54,6 +55,7 @@ async function createOptions( ]), targetDir, starter, + intent: json.intent ?? false, } as Options } @@ -230,6 +232,7 @@ export async function addToApp( cwd: string, options?: { forced?: boolean + intent?: boolean }, ) { const persistedOptions = await getCurrentConfiguration(environment, cwd) @@ -318,6 +321,10 @@ export async function addToApp( await runNewCommands(environment, persistedOptions, cwd, output) + const intent = options?.intent ?? persistedOptions.intent ?? true + newOptions.intent = intent + await setupIntent(environment, cwd, newOptions) + environment.startStep({ id: 'write-config-file', type: 'file', diff --git a/packages/create/src/create-app.ts b/packages/create/src/create-app.ts index 6551ce8c..a0cc4d50 100644 --- a/packages/create/src/create-app.ts +++ b/packages/create/src/create-app.ts @@ -13,6 +13,7 @@ import { resolvePackageJSONLatest } from './npm-resolver.js' import { createTemplateFile } from './template-file.js' import { installShadcnComponents } from './integrations/shadcn.js' import { setupGit } from './integrations/git.js' +import { setupIntent } from './integrations/intent.js' import { runSpecialSteps } from './special-steps/index.js' import type { Environment, FileBundleHandler, Options } from './types.js' @@ -294,6 +295,8 @@ async function runCommandsAndInstallDependencies( } await installShadcnComponents(environment, options.targetDir, options) + + await setupIntent(environment, options.targetDir, options) } async function seedEnvValues(environment: Environment, options: Options) { diff --git a/packages/create/src/custom-add-ons/shared.ts b/packages/create/src/custom-add-ons/shared.ts index 3edccfba..d0b1d9e2 100644 --- a/packages/create/src/custom-add-ons/shared.ts +++ b/packages/create/src/custom-add-ons/shared.ts @@ -82,6 +82,7 @@ export async function createAppOptionsFromPersisted( starter: json.starter ? await loadStarter(json.starter) : undefined, chosenAddOns, addOnOptions: populateAddOnOptionsDefaults(chosenAddOns), + intent: json.intent ?? false, } } @@ -103,6 +104,7 @@ export function createSerializedOptionsFromPersisted( framework: json.framework, starter: json.starter, addOnOptions: {}, + intent: json.intent ?? false, } } diff --git a/packages/create/src/integrations/intent.ts b/packages/create/src/integrations/intent.ts new file mode 100644 index 00000000..d9da4368 --- /dev/null +++ b/packages/create/src/integrations/intent.ts @@ -0,0 +1,47 @@ +import { resolve } from 'node:path' + +import { packageManagerExecute } from '../package-manager.js' + +import type { Environment, Options } from '../types.js' + +export async function setupIntent( + environment: Environment, + targetDir: string, + options: Options, +) { + if (!options.intent) { + return + } + + const s = environment.spinner() + s.start('Setting up TanStack Intent skill mappings...') + environment.startStep({ + id: 'setup-intent', + type: 'command', + message: 'Setting up TanStack Intent skill mappings...', + }) + + try { + await packageManagerExecute( + environment, + resolve(targetDir), + options.packageManager, + '@tanstack/intent', + ['install', '--yes'], + ) + environment.finishStep('setup-intent', 'TanStack Intent configured') + s.stop('TanStack Intent configured') + } catch (error) { + const message = + error instanceof Error ? error.message : 'Unknown error' + environment.finishStep( + 'setup-intent', + `TanStack Intent setup skipped: ${message}`, + ) + s.stop('TanStack Intent setup skipped') + environment.warn( + 'TanStack Intent setup failed', + `Continuing without it. You can run it later with: npx @tanstack/intent install\n\n${message}`, + ) + } +} diff --git a/packages/create/src/types.ts b/packages/create/src/types.ts index a36cfb06..3f385510 100644 --- a/packages/create/src/types.ts +++ b/packages/create/src/types.ts @@ -214,6 +214,7 @@ export interface Options { packageManager: PackageManager git: boolean install?: boolean + intent: boolean chosenAddOns: Array addOnOptions: Record> From 78b7ed59e787e677735f600050738ea92991e777 Mon Sep 17 00:00:00 2001 From: Claude Date: Fri, 1 May 2026 17:57:48 +0000 Subject: [PATCH 2/3] fix(cli): drop unsupported --yes flag from intent install The intent CLI already runs non-interactively, no extra flag needed. https://claude.ai/code/session_01KZU2LM3E8hncoXxZguUu8P --- packages/create/src/integrations/intent.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/create/src/integrations/intent.ts b/packages/create/src/integrations/intent.ts index d9da4368..208078e3 100644 --- a/packages/create/src/integrations/intent.ts +++ b/packages/create/src/integrations/intent.ts @@ -27,7 +27,7 @@ export async function setupIntent( resolve(targetDir), options.packageManager, '@tanstack/intent', - ['install', '--yes'], + ['install'], ) environment.finishStep('setup-intent', 'TanStack Intent configured') s.stop('TanStack Intent configured') From bd9385c47f2e23e99fec8dd11689ddf2deac573c Mon Sep 17 00:00:00 2001 From: Claude Date: Fri, 1 May 2026 18:58:39 +0000 Subject: [PATCH 3/3] chore: add changeset for intent auto-install https://claude.ai/code/session_01KZU2LM3E8hncoXxZguUu8P --- .changeset/intent-auto-install.md | 13 +++++++++++++ 1 file changed, 13 insertions(+) create mode 100644 .changeset/intent-auto-install.md diff --git a/.changeset/intent-auto-install.md b/.changeset/intent-auto-install.md new file mode 100644 index 00000000..0b9ea9b1 --- /dev/null +++ b/.changeset/intent-auto-install.md @@ -0,0 +1,13 @@ +--- +'@tanstack/cli': minor +'@tanstack/create': minor +--- + +feat(cli): auto-install TanStack Intent during scaffolding + +`tanstack create` and `tanstack add` now run `npx @tanstack/intent install` +after dependency installation, wiring up skill mappings for coding agents. +The behavior is controlled by a new `--intent` / `--no-intent` flag (default +on) and persists to `.cta.json` so subsequent `add` invocations honor the +original choice. Failures are surfaced as warnings instead of aborting the +scaffold.