diff --git a/.changeset/kind-bears-visit.md b/.changeset/kind-bears-visit.md new file mode 100644 index 00000000..26b630cb --- /dev/null +++ b/.changeset/kind-bears-visit.md @@ -0,0 +1,5 @@ +--- +'@tanstack/intent': patch +--- + +Include package-manager-specific load commands in SessionStart skill catalogs and clarify that Intent skills are not native agent skills. diff --git a/packages/intent/src/hooks/install.ts b/packages/intent/src/hooks/install.ts index 9b2ebeb5..a7513daa 100644 --- a/packages/intent/src/hooks/install.ts +++ b/packages/intent/src/hooks/install.ts @@ -65,6 +65,10 @@ export function buildHookRunnerScript( detectPackageManager(), 'list --json --no-notices', ), + loadCommand = formatIntentCommand( + detectPackageManager(), + 'load #', + ), ): string { const editTools = [...EDIT_TOOLS_BY_AGENT[agent]].sort() @@ -78,6 +82,7 @@ import { performance } from 'node:perf_hooks' const AGENT = ${JSON.stringify(agent)} const CATALOG_COMMAND = ${JSON.stringify(catalogCommand)} +const LOAD_COMMAND = ${JSON.stringify(loadCommand)} const EDIT_TOOLS = new Set(${JSON.stringify(editTools)}) const GATE_DENY_REASON = ${JSON.stringify(GATE_DENY_REASON)} const INTENT_COMMAND_PATTERN = /(?:^|&&|\\|\\||;|\\|)\\s*((?:bunx\\s+@tanstack\\/intent(?:@latest)?)|(?:pnpm\\s+exec\\s+intent)|(?:pnpm\\s+dlx\\s+@tanstack\\/intent(?:@latest)?)|(?:npx\\s+@tanstack\\/intent(?:@latest)?)|(?:yarn\\s+dlx\\s+@tanstack\\/intent(?:@latest)?)|(?:intent))\\s+(list|load)(?:\\s+([^\\s|;&]+))?/i @@ -168,6 +173,9 @@ function formatSessionCatalog(result) { return [ 'TanStack Intent skills are available in this repository.', '', + 'These are Intent skills, not native agent skills.', + 'Load a matching skill with: \`' + LOAD_COMMAND + '\`.', + '', 'Before substantial work, check whether one listed skill clearly matches the user task. If one clearly matches, load that full skill guidance with the Intent CLI before proceeding.', '', 'If no skill clearly matches, continue normally. Do not load a skill just to improve phrasing or gather nonessential context.', @@ -352,13 +360,18 @@ function installAgentHook({ homeDir, root, }) + const packageManager = detectPackageManager(root) const catalogCommand = formatIntentCommand( - detectPackageManager(root), + packageManager, 'list --json --no-notices', ) + const loadCommand = formatIntentCommand( + packageManager, + 'load #', + ) const scriptStatus = writeIfChanged( scriptPath, - buildHookRunnerScript(agent, catalogCommand), + buildHookRunnerScript(agent, catalogCommand, loadCommand), ) const configStatus = updateJsonConfig(configPath, (config) => upsertAdapterHooks({ diff --git a/packages/intent/tests/hooks-install.test.ts b/packages/intent/tests/hooks-install.test.ts index 44dafaa3..3b2c93fb 100644 --- a/packages/intent/tests/hooks-install.test.ts +++ b/packages/intent/tests/hooks-install.test.ts @@ -388,6 +388,8 @@ describe('hook installer', () => { (agent) => { const root = tempRoot(`intent-hooks-session-catalog-${agent}-`) const catalogCommand = writeFakeIntentListCommand(root) + const loadCommand = + 'pnpm dlx @tanstack/intent@latest load #' const scriptPath = join( root, '.intent', @@ -395,7 +397,10 @@ describe('hook installer', () => { `intent-${agent}-gate.mjs`, ) mkdirSync(join(root, '.intent', 'hooks'), { recursive: true }) - writeFileSync(scriptPath, buildHookRunnerScript(agent, catalogCommand)) + writeFileSync( + scriptPath, + buildHookRunnerScript(agent, catalogCommand, loadCommand), + ) const result = runHookScript(scriptPath, { cwd: root, @@ -415,7 +420,10 @@ describe('hook installer', () => { '- @tanstack/router#routing: Router routing guidance', ) expect(context).toContain('load that full skill guidance') - expect(context).not.toContain('intent load ') + expect(context).toContain( + 'These are Intent skills, not native agent skills.', + ) + expect(context).toContain(`Load a matching skill with: \`${loadCommand}\`.`) if (agent !== 'copilot') { expect(output.hookSpecificOutput.hookEventName).toBe('SessionStart') }