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
12 changes: 12 additions & 0 deletions .changeset/lean-intent-skill-guidance.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
---
'@tanstack/create': patch
---

Wire TanStack Intent up in on-demand discovery mode instead of writing the full
skill-to-task mapping table into `AGENTS.md`. Generated projects previously got
an `install --map` block listing every skill for every installed package — 99
lines in a default app, growing with each add-on — which every agent re-read on
every invocation. Plain `install` emits a 10-line pointer telling the agent to
run `intent list` and `intent load <package>#<skill>` when a task actually calls
for one. The "next steps" output now shows those two commands, rendered for the
project's package manager.
3 changes: 2 additions & 1 deletion packages/create/src/create-app.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { formatCommand } from './utils.js'
import { writeConfigFileToEnvironment } from './config-file.js'
import {
getPackageManagerScriptCommand,
intentCommand,
packageManagerInstall,
translateExecuteCommand,
} from './package-manager.js'
Expand Down Expand Up @@ -414,7 +415,7 @@ function buildNextSteps(options: Options): string {
}
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"`,
`Working with an AI agent? Your agent config (AGENTS.md / CLAUDE.md) was wired up by TanStack Intent\nso your agent can discover skills for the libraries you installed, on demand:\n • ${intentCommand(options.packageManager, ['list'])}\n • ${intentCommand(options.packageManager, ['load', '<package>#<skill>'])}\nTry 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"`,
)
}

Expand Down
10 changes: 6 additions & 4 deletions packages/create/src/edge-create-app.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,10 @@ import { basenamePath, joinPaths, normalizePath } from './edge-path.js'
import { resolvePackageJSONLatest } from './npm-resolver.js'
import { writeConfigFileToEnvironment } from './edge-config-file.js'
import {
INTENT_PACKAGE,
getPackageManagerExecuteCommand,
getPackageManagerScriptCommand,
intentCommand,
packageManagerInstall,
translateExecuteCommand,
} from './package-manager.js'
Expand Down Expand Up @@ -258,13 +260,13 @@ async function setupIntent(
environment.startStep({
id: 'setup-intent',
type: 'command',
message: 'Setting up TanStack Intent skill mappings...',
message: 'Setting up TanStack Intent skill discovery...',
})

const { command, args } = getPackageManagerExecuteCommand(
options.packageManager,
'@tanstack/intent',
['install', '--map'],
INTENT_PACKAGE,
['install'],
)
await environment.execute(command, args, normalizePath(targetDir))
environment.finishStep('setup-intent', 'TanStack Intent configured')
Expand Down Expand Up @@ -532,7 +534,7 @@ function buildNextSteps(options: Options): string {
}
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"`,
`Working with an AI agent? Your agent config (AGENTS.md / CLAUDE.md) was wired up by TanStack Intent\nso your agent can discover skills for the libraries you installed, on demand:\n - ${intentCommand(options.packageManager, ['list'])}\n - ${intentCommand(options.packageManager, ['load', '<package>#<skill>'])}\nTry 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"`,
)
}

Expand Down
16 changes: 10 additions & 6 deletions packages/create/src/integrations/intent.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
import { resolve } from 'node:path'

import { packageManagerExecute } from '../package-manager.js'
import {
INTENT_PACKAGE,
intentCommand,
packageManagerExecute,
} from '../package-manager.js'

import type { Environment, Options } from '../types.js'

Expand All @@ -14,20 +18,20 @@ export async function setupIntent(
}

const s = environment.spinner()
s.start('Setting up TanStack Intent skill mappings...')
s.start('Setting up TanStack Intent skill discovery...')
environment.startStep({
id: 'setup-intent',
type: 'command',
message: 'Setting up TanStack Intent skill mappings...',
message: 'Setting up TanStack Intent skill discovery...',
})

try {
await packageManagerExecute(
environment,
resolve(targetDir),
options.packageManager,
'@tanstack/intent',
['install', '--map'],
INTENT_PACKAGE,
['install'],
)
environment.finishStep('setup-intent', 'TanStack Intent configured')
s.stop('TanStack Intent configured')
Expand All @@ -41,7 +45,7 @@ export async function setupIntent(
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}`,
`Continuing without it. You can run it later with: ${intentCommand(options.packageManager, ['install'])}\n\n${message}`,
)
}
}
14 changes: 14 additions & 0 deletions packages/create/src/package-manager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,20 @@ export function getPackageManagerExecuteCommand(
}
}

export const INTENT_PACKAGE = '@tanstack/intent'

export function intentCommand(
packageManager: PackageManager,
args: Array<string>,
) {
const { command, args: commandArgs } = getPackageManagerExecuteCommand(
packageManager,
INTENT_PACKAGE,
args,
)
return [command, ...commandArgs].join(' ')
}
Comment on lines +64 to +76

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
rg -n 'nodeModulesDir|node_modules|SUPPORTED_PACKAGE_MANAGERS|deno' packages/create

Repository: TanStack/cli

Length of output: 5169


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== package-manager.ts =="
sed -n '1,170p' packages/create/src/package-manager.ts | cat -n

echo
echo "== relevant references to INTENT/expect commands =="
rg -n "INTENT|intentonCommand|intentCommand|list|load|npm:.*intent|command: 'intent'" packages/create/src packages/create/tests || true

echo
echo "== template/deno files mentioning nodeModulesDir or deno config =="
rg -n "nodeModulesDir|allow-net|allow-env|allow-read|allow-run|allow-write|`@tanstack/intent`|deno.lock" packages/create/src packages/create/tests -g '!*assets/**' || true

Repository: TanStack/cli

Length of output: 50368


🌐 Web query:

TanStack Intent Deno npm interop node_modules support deno run npm:

💡 Result:

Deno provides native support for npm packages, including TanStack libraries, through npm specifiers (e.g., npm:@tanstack/react-query) [1][2][3]. You do not need a node_modules directory by default [1][2][4]. NPM Interop and node_modules Support: - Default Behavior: By default, Deno resolves npm packages from a central global cache, which keeps your project directory clean and avoids the creation of a node_modules folder [5][6][4]. - Opt-in node_modules: Some packages or tools (like certain bundlers) require a node_modules directory [6][7][4]. You can enable this behavior by setting "nodeModulesDir": "auto" in your deno.json configuration file or by using the --node-modules-dir flag when running commands [8][6][7]. - Running with npm: When using npm specifiers (e.g., deno run npm:package), Deno automatically handles the download and resolution of dependencies [1][4]. If you have a package.json file present in your project, Deno defaults to creating a local node_modules directory, though this can be controlled via configuration [6][2][9]. TanStack Support: - TanStack libraries are fully compatible with Deno's npm specifier system [3][10]. Official Deno documentation and community contributions confirm that you can install and use packages like @tanstack/react-query directly via deno install npm:@tanstack/react-query or by referencing them in your imports [3][10]. Summary of Configuration: - To use npm packages without node_modules: Use the default Deno behavior (no extra configuration needed) [5][4]. - To force node_modules creation: Set "nodeModulesDir": "auto" in deno.json [6][7]. - For existing Node.js projects: You can run them in Deno by referencing dependencies in package.json and optionally setting the node_modules mode to manual or auto depending on your requirements [5][6][4].

Citations:


🌐 Web query:

TanStack Intent Deno Deno.run permissions --allow-net allow-env allow-read

💡 Result:

TanStack Intent is a CLI tool designed to ship and consume AI agent skills via npm packages [1][2]. While TanStack Intent lists Deno as a supported environment, it currently operates on a best-effort basis requiring npm interop with node_modules support enabled [3][4]. Regarding your query on Deno APIs and permissions: 1. Deno.run Deprecation: The Deno.run API is deprecated and has been soft-removed in Deno 2 [5][6]. You should replace it with the Deno.Command API [5][7]. - Example migration: // Instead of Deno.run const process = new Deno.Command("command_name", { args: ["arg1"], stdout: "piped", }); const { success, stdout } = await process.output; 2. Deno Permissions: To use APIs that require net, env, read, or run access, you must explicitly grant these permissions at runtime using command-line flags [8][9]. - Flag usage: - --allow-net: Grants network access (can be scoped to specific hosts) [8][10]. - --allow-env: Grants access to environment variables (can be scoped to specific variables) [8][10]. - --allow-read: Grants file system read access (can be scoped to specific paths) [8][10]. - --allow-run: Required for executing subprocesses, such as when using Deno.Command [8][11]. To grant all these permissions at once for a script, you can use: deno run --allow-net --allow-env --allow-read --allow-run script.ts For stricter security, it is highly recommended to scope these permissions (e.g., --allow-read=./data or --allow-net=example.com) rather than granting full access [9].

Citations:


Add explicit Deno guidance for TanStack Intent.

intentCommand returns deno run npm:@tanstack/intent ..., which works with Deno npm specifiers, but TanStack Intent documents Deno as best-effort and requiring npm interop with node_modules support. Add install/create guidance that Deno needs nodeModulesDir: "auto" in deno.json or --node-modules-dir/--allow-install, and any permissions the Deno CLI may need.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/create/src/package-manager.ts` around lines 64 - 76, Update
intentCommand to include explicit Deno guidance alongside the generated command:
document that TanStack Intent’s Deno support is best-effort, requires npm
interoperability with node_modules enabled via deno.json nodeModulesDir: "auto"
or the relevant --node-modules-dir/--allow-install flags, and may require the
permissions needed by the Deno CLI.

Source: MCP tools


export function getPackageManagerInstallCommand(
packagerManager: PackageManager,
pkg?: string,
Expand Down