Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 20 additions & 3 deletions packages/create/src/create-app.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ import { isBase64, isDemoFilePath } from './file-helpers.js'
import { formatCommand } from './utils.js'
import { writeConfigFileToEnvironment } from './config-file.js'
import {
getPackageManagerExecuteCommand,
getPackageManagerInstallCommand,
getPackageManagerScriptCommand,
packageManagerInstall,
translateExecuteCommand,
Expand Down Expand Up @@ -413,9 +415,24 @@ function buildNextSteps(options: Options): string {
sections.push(`Docs for the integrations you picked:\n${docLines.join('\n')}`)
}
if (options.intent) {
sections.push(
`Working with an AI agent? Your agent config (AGENTS.md / CLAUDE.md) was wired up by TanStack Intent\nwith explicit skill mappings for the libraries you installed. Try asking your agent:\n • "migrate this Next.js page to TanStack Start"\n • "add a protected /dashboard route"\n • "show me how to use TanStack Router search params"`,
)
if (options.install === false) {
const installCommand = formatCommand(
getPackageManagerInstallCommand(options.packageManager),
)
const intentCommand = formatCommand(
getPackageManagerExecuteCommand(options.packageManager, '@tanstack/intent', [
'install',
'--map',
]),
)
sections.push(
`Working with an AI agent? TanStack Intent was skipped because dependency installation was\nskipped, so no agent config (AGENTS.md / CLAUDE.md) was written. After installing dependencies,\nwire it up with:\n % ${installCommand}\n % ${intentCommand}`,
)
} else {
sections.push(
`Working with an AI agent? Your agent config (AGENTS.md / CLAUDE.md) was wired up by TanStack Intent\nwith explicit skill mappings for the libraries you installed. Try asking your agent:\n • "migrate this Next.js page to TanStack Start"\n • "add a protected /dashboard route"\n • "show me how to use TanStack Router search params"`,
)
}
}

return sections.length > 0 ? `\nNext steps:\n\n${sections.join('\n\n')}\n` : ''
Expand Down
35 changes: 32 additions & 3 deletions packages/create/src/edge-create-app.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import { resolvePackageJSONLatest } from './npm-resolver.js'
import { writeConfigFileToEnvironment } from './edge-config-file.js'
import {
getPackageManagerExecuteCommand,
getPackageManagerInstallCommand,
getPackageManagerScriptCommand,
packageManagerInstall,
translateExecuteCommand,
Expand Down Expand Up @@ -255,6 +256,19 @@ async function setupIntent(
return
}

if (options.install === false) {
environment.startStep({
id: 'setup-intent',
type: 'info',
message: 'Skipping TanStack Intent setup...',
})
environment.finishStep(
'setup-intent',
'TanStack Intent setup skipped: no dependencies installed yet',
)
return
}

environment.startStep({
id: 'setup-intent',
type: 'command',
Expand Down Expand Up @@ -531,9 +545,24 @@ function buildNextSteps(options: Options): string {
sections.push(`Docs for the integrations you picked:\n${docLines.join('\n')}`)
}
if (options.intent) {
sections.push(
`Working with an AI agent? Your agent config (AGENTS.md / CLAUDE.md) was wired up by TanStack Intent\nwith explicit skill mappings for the libraries you installed. Try asking your agent:\n - "migrate this Next.js page to TanStack Start"\n - "add a protected /dashboard route"\n - "show me how to use TanStack Router search params"`,
)
if (options.install === false) {
const installCommand = formatCommand(
getPackageManagerInstallCommand(options.packageManager),
)
const intentCommand = formatCommand(
getPackageManagerExecuteCommand(options.packageManager, '@tanstack/intent', [
'install',
'--map',
]),
)
sections.push(
`Working with an AI agent? TanStack Intent was skipped because dependency installation was\nskipped, so no agent config (AGENTS.md / CLAUDE.md) was written. After installing dependencies,\nwire it up with:\n % ${installCommand}\n % ${intentCommand}`,
)
} else {
sections.push(
`Working with an AI agent? Your agent config (AGENTS.md / CLAUDE.md) was wired up by TanStack Intent\nwith explicit skill mappings for the libraries you installed. Try asking your agent:\n - "migrate this Next.js page to TanStack Start"\n - "add a protected /dashboard route"\n - "show me how to use TanStack Router search params"`,
)
}
}

return sections.length > 0 ? `\nNext steps:\n\n${sections.join('\n\n')}\n` : ''
Expand Down
16 changes: 16 additions & 0 deletions packages/create/src/integrations/intent.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,22 @@ export async function setupIntent(
return
}

if (options.install === false) {
const s = environment.spinner()
s.start('Skipping TanStack Intent setup...')
environment.startStep({
id: 'setup-intent',
type: 'info',
message: 'Skipping TanStack Intent setup...',
})
environment.finishStep(
'setup-intent',
'TanStack Intent setup skipped: no dependencies installed yet',
)
s.stop('TanStack Intent setup skipped: no dependencies installed yet')
return
}

const s = environment.spinner()
s.start('Setting up TanStack Intent skill mappings...')
environment.startStep({
Expand Down
42 changes: 42 additions & 0 deletions packages/create/tests/create-app.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,48 @@ describe('createApp', () => {
})
})

it('skips intent setup and reports the follow-up when dependency install is skipped', async () => {
const { environment, output } = createMemoryEnvironment()
let outro = ''
environment.outro = (message: string) => {
outro = message
}
await createApp(environment, {
...simpleOptions,
intent: true,
install: false,
})

expect(output.commands).not.toContainEqual({
command: 'pnpm',
args: ['dlx', '@tanstack/intent', 'install', '--map'],
})
expect(outro).not.toContain('was wired up by TanStack Intent')
expect(outro).toContain('TanStack Intent was skipped')
expect(outro).toContain('pnpm install')
expect(outro).toContain('pnpm dlx @tanstack/intent install --map')
})

it('sets up intent and reports the agent config when dependencies are installed', async () => {
const { environment, output } = createMemoryEnvironment()
let outro = ''
environment.outro = (message: string) => {
outro = message
}
await createApp(environment, {
...simpleOptions,
intent: true,
install: true,
})

expect(output.commands).toContainEqual({
command: 'pnpm',
args: ['dlx', '@tanstack/intent', 'install', '--map'],
})
expect(outro).toContain('was wired up by TanStack Intent')
expect(outro).not.toContain('TanStack Intent was skipped')
})

it('should create an app - with a add-on', async () => {
const { environment, output } = createMemoryEnvironment()
await createApp(environment, {
Expand Down
69 changes: 69 additions & 0 deletions packages/create/tests/integrations/intent.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
import { describe, expect, it } from 'vitest'

import { createMemoryEnvironment } from '../../src/environment.js'
import { setupIntent } from '../../src/integrations/intent.js'

import type { Options } from '../../src/types.js'

describe('intent', () => {
it('should skip if intent is not enabled', async () => {
const { environment, output } = createMemoryEnvironment()
environment.startRun()
await setupIntent(environment, '/test', {
packageManager: 'pnpm',
intent: false,
projectName: 'test',
typescript: true,
spinner: () => ({
start: () => {},
stop: () => {},
}),
} as unknown as Options)
environment.finishRun()

expect(output.commands).toEqual([])
})

it('should run the intent install command when dependencies are installed', async () => {
const { environment, output } = createMemoryEnvironment()
environment.startRun()
await setupIntent(environment, '/test', {
packageManager: 'pnpm',
intent: true,
install: true,
projectName: 'test',
typescript: true,
spinner: () => ({
start: () => {},
stop: () => {},
}),
} as unknown as Options)
environment.finishRun()

expect(output.commands).toEqual([
{
command: 'pnpm',
args: ['dlx', '@tanstack/intent', 'install', '--map'],
},
])
})

it('should skip the intent install command when dependency install is skipped', async () => {
const { environment, output } = createMemoryEnvironment()
environment.startRun()
await setupIntent(environment, '/test', {
packageManager: 'pnpm',
intent: true,
install: false,
projectName: 'test',
typescript: true,
spinner: () => ({
start: () => {},
stop: () => {},
}),
} as unknown as Options)
environment.finishRun()

expect(output.commands).toEqual([])
})
})