@tanstack/intent 0.0.10 → 0.0.13

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,23 +1,23 @@
1
1
  # @tanstack/intent
2
2
 
3
- Ship compositional knowledge for AI coding agents alongside your npm packages.
3
+ A CLI for library maintainers to generate, validate, and ship [Agent Skills](https://agentskills.io) alongside their npm packages.
4
4
 
5
5
  ## The problem
6
6
 
7
7
  Your docs are good. Your types are solid. Your agent still gets it wrong.
8
8
 
9
- Docs target humans who browse. Types check individual API calls but can't encode intent. Training data snapshots the ecosystem as it _was_, mixing versions without flagging which applies. Once a breaking change ships, models contain _both_ versions forever with no way to disambiguate.
9
+ Docs target humans who browse. Types check individual API calls but can't encode intent. Training data snapshots the ecosystem as it _was_, mixing versions with no way to tell which applies. Once a breaking change ships, models develop a permanent split-brain — training data contains _both_ versions forever with no way to disambiguate.
10
10
 
11
11
  The ecosystem already moves toward agent-readable knowledge — Cursor rules, CLAUDE.md files, skills directories. But delivery is stuck in copy-paste: hunt for a community-maintained rules file, paste it into your config, repeat for every tool. No versioning, no update path, no staleness signal.
12
12
 
13
- ## Skills: the fourth artifact
13
+ ## Skills: versioned knowledge in npm
14
14
 
15
- You ship code, docs, and types. Skills are the fourth artifactknowledge encoded for the thing writing most of your code.
16
-
17
- Skills are npm packages of knowledge — encoding how tools compose, which patterns fit which goals, and what to avoid. When a library ships skills using `@tanstack/intent`, that knowledge travels with the tool via `npm update` — not the model's training cutoff. Versioned knowledge the maintainer owns, updated when the package updates.
15
+ A skill is a short, versioned document that tells agents how to use a specific capability of your library — correct patterns, common mistakes, and when to apply them. Skills ship inside your npm package and travel with the tool via `npm update` not the model's training cutoff, not community-maintained rules files, not prompt snippets in READMEs. Versioned knowledge the maintainer owns, updated when the package updates.
18
16
 
19
17
  Each skill declares its source docs. When those docs change, the CLI flags the skill for review. One source of truth, one derived artifact that stays in sync.
20
18
 
19
+ The [Agent Skills spec](https://agentskills.io) is an open standard already adopted by VS Code, GitHub Copilot, OpenAI Codex, Cursor, Claude Code, Goose, Amp, and others.
20
+
21
21
  ## Quick Start
22
22
 
23
23
  ### For library consumers
@@ -28,7 +28,7 @@ Set up skill-to-task mappings in your project's agent config files (CLAUDE.md, .
28
28
  npx @tanstack/intent install
29
29
  ```
30
30
 
31
- No per-library setup. No hunting for rules files. Install the package, run `intent install`, and the agent understands the tool. Update the package, and skills update too.
31
+ No per-library setup. No hunting for rules files. Install the package, run `npx @tanstack/intent install`, and the agent understands the tool. Update the package, and skills update too.
32
32
 
33
33
  List available skills from installed packages:
34
34
 
@@ -44,7 +44,7 @@ Generate skills for your library by telling your AI coding agent to run:
44
44
  npx @tanstack/intent scaffold
45
45
  ```
46
46
 
47
- This prints a prompt that walks the agent through domain discovery, skill tree generation, and skill creation — one step at a time with your review at each stage.
47
+ This walks the agent through domain discovery, skill tree generation, and skill creation — one step at a time with your review at each stage.
48
48
 
49
49
  Validate your skill files:
50
50
 
@@ -61,27 +61,27 @@ npx @tanstack/intent stale
61
61
  Copy CI workflow templates into your repo so validation and staleness checks run on every push:
62
62
 
63
63
  ```bash
64
- npx @tanstack/intent setup
64
+ npx @tanstack/intent setup-github-actions
65
65
  ```
66
66
 
67
67
  ## Keeping skills current
68
68
 
69
- The real risk with any derived artifact is staleness. `intent stale` flags skills whose source docs have changed, and CI templates catch drift before it ships.
69
+ The real risk with any derived artifact is staleness. `npx @tanstack/intent stale` flags skills whose source docs have changed, and CI templates catch drift before it ships.
70
70
 
71
- The feedback loop runs both directions. `intent feedback` lets users submit structured reports when a skill produces wrong output — which skill, which version, what broke. That context flows back to the maintainer, and the fix ships to everyone on the next `npm update`.
71
+ The feedback loop runs both directions. `npx @tanstack/intent feedback` lets users submit structured reports when a skill produces wrong output — which skill, which version, what broke. That context flows back to the maintainer, and the fix ships to everyone on the next `npm update`. Every support interaction produces an artifact that prevents the same class of problem for all future users — not just the one who reported it.
72
72
 
73
73
  ## CLI Commands
74
74
 
75
- | Command | Description |
76
- | ----------------------- | --------------------------------------------------- |
77
- | `intent install` | Set up skill-to-task mappings in agent config files |
78
- | `intent list [--json]` | Discover intent-enabled packages |
79
- | `intent meta` | List meta-skills for library maintainers |
80
- | `intent scaffold` | Print the guided skill generation prompt |
81
- | `intent validate [dir]` | Validate SKILL.md files |
82
- | `intent setup` | Copy CI templates, generate shim, create labels |
83
- | `intent stale [--json]` | Check skills for version drift |
84
- | `intent feedback` | Submit skill feedback |
75
+ | Command | Description |
76
+ | ------------------------------------------- | --------------------------------------------------- |
77
+ | `npx @tanstack/intent install` | Set up skill-to-task mappings in agent config files |
78
+ | `npx @tanstack/intent list [--json]` | Discover intent-enabled packages |
79
+ | `npx @tanstack/intent meta` | List meta-skills for library maintainers |
80
+ | `npx @tanstack/intent scaffold` | Print the guided skill generation prompt |
81
+ | `npx @tanstack/intent validate [dir]` | Validate SKILL.md files |
82
+ | `npx @tanstack/intent setup-github-actions` | Copy CI templates into your repo |
83
+ | `npx @tanstack/intent stale [--json]` | Check skills for version drift |
84
+ | `npx @tanstack/intent feedback` | Submit skill feedback |
85
85
 
86
86
  ## License
87
87
 
package/dist/cli.mjs CHANGED
@@ -1,6 +1,6 @@
1
1
  #!/usr/bin/env node
2
2
  import { n as parseFrontmatter, t as findSkillFiles } from "./utils-DH3jY3CI.mjs";
3
- import { t as scanForIntents } from "./scanner-OmHt14bs.mjs";
3
+ import { t as scanForIntents } from "./scanner-dIYdkHQ1.mjs";
4
4
  import { n as printSkillTree, r as printTable, t as computeSkillNameWidth } from "./display-D_XzuGnu.mjs";
5
5
  import { existsSync, readFileSync, readdirSync } from "node:fs";
6
6
  import { dirname, join, relative, sep } from "node:path";
@@ -65,12 +65,33 @@ async function cmdList(args) {
65
65
  for (const w of result.warnings) console.log(` ⚠ ${w}`);
66
66
  }
67
67
  }
68
- function cmdMeta() {
68
+ function cmdMeta(args) {
69
69
  const metaDir = getMetaDir();
70
70
  if (!existsSync(metaDir)) {
71
71
  console.error("Meta-skills directory not found.");
72
72
  process.exit(1);
73
73
  }
74
+ if (args.length > 0) {
75
+ const name = args[0];
76
+ if (name.includes("..") || name.includes("/") || name.includes("\\")) {
77
+ console.error(`Invalid meta-skill name: "${name}"`);
78
+ process.exit(1);
79
+ }
80
+ const skillFile = join(metaDir, name, "SKILL.md");
81
+ if (!existsSync(skillFile)) {
82
+ console.error(`Meta-skill "${name}" not found.`);
83
+ console.error(`Run \`npx @tanstack/intent meta\` to list available meta-skills.`);
84
+ process.exit(1);
85
+ }
86
+ try {
87
+ console.log(readFileSync(skillFile, "utf8"));
88
+ } catch (err) {
89
+ const msg = err instanceof Error ? err.message : String(err);
90
+ console.error(`Failed to read meta-skill "${name}": ${msg}`);
91
+ process.exit(1);
92
+ }
93
+ return;
94
+ }
74
95
  const entries = readdirSync(metaDir, { withFileTypes: true }).filter((e) => e.isDirectory()).filter((e) => existsSync(join(metaDir, e.name, "SKILL.md")));
75
96
  if (entries.length === 0) {
76
97
  console.log("No meta-skills found.");
@@ -101,7 +122,7 @@ function collectPackagingWarnings(root) {
101
122
  if (!pkgJson.bin?.intent) warnings.push("Missing \"bin\": { \"intent\": ... } entry in package.json");
102
123
  const shimJs = join(root, "bin", "intent.js");
103
124
  const shimMjs = join(root, "bin", "intent.mjs");
104
- if (!existsSync(shimJs) && !existsSync(shimMjs)) warnings.push("No bin/intent.js or bin/intent.mjs shim found (run: npx @tanstack/intent setup --shim)");
125
+ if (!existsSync(shimJs) && !existsSync(shimMjs)) warnings.push("No bin/intent.js or bin/intent.mjs shim found (run: npx @tanstack/intent add-library-bin)");
105
126
  const files = pkgJson.files;
106
127
  if (Array.isArray(files)) {
107
128
  if (!files.includes("skills")) warnings.push("\"skills\" is not in the \"files\" array — skills won't be published");
@@ -287,12 +308,11 @@ This produces: individual SKILL.md files.
287
308
 
288
309
  1. Run \`npx @tanstack/intent validate\` in each package directory
289
310
  2. Commit skills/ and artifacts
290
- 3. For each publishable package, run: \`npx @tanstack/intent setup --shim\`
291
- 4. Ensure each package has \`@tanstack/intent\` as a devDependency
292
- 5. Add \`"skills"\`, \`"bin"\` to the \`"files"\` array in each package.json
293
- 6. Add \`"!skills/_artifacts"\` to exclude artifacts from publishing
294
- 7. Create a \`feedback:<skill-name>\` label on the GitHub repo for each skill (use \`gh label create\`)
295
- 8. Add a README note: "If you use an AI agent, run \`npx @tanstack/intent install\`"
311
+ 3. For each publishable package, run: \`npx @tanstack/intent add-library-bin\`
312
+ 4. For each publishable package, run: \`npx @tanstack/intent edit-package-json\`
313
+ 5. Ensure each package has \`@tanstack/intent\` as a devDependency
314
+ 6. Create a \`skill:<skill-name>\` label on the GitHub repo for each skill (use \`gh label create\`)
315
+ 7. Add a README note: "If you use an AI agent, run \`npx @tanstack/intent install\`"
296
316
  `;
297
317
  console.log(prompt);
298
318
  }
@@ -300,11 +320,13 @@ const USAGE = `TanStack Intent CLI
300
320
 
301
321
  Usage:
302
322
  intent list [--json] Discover intent-enabled packages
303
- intent meta List meta-skills for maintainers
323
+ intent meta [name] List meta-skills, or print one by name
304
324
  intent validate [<dir>] Validate skill files (default: skills/)
305
325
  intent install Print a skill that guides your coding agent to set up skill-to-task mappings
306
326
  intent scaffold Print maintainer scaffold prompt
307
- intent setup [--workflows] [--shim] [--all] Copy CI templates and generate shim
327
+ intent add-library-bin Generate bin/intent.{js,mjs} bridge file
328
+ intent edit-package-json Wire package.json (files, bin) for skill publishing
329
+ intent setup-github-actions Copy CI workflow templates to .github/workflows/
308
330
  intent stale Check skills for staleness`;
309
331
  const command = process.argv[2];
310
332
  const commandArgs = process.argv.slice(3);
@@ -313,7 +335,7 @@ switch (command) {
313
335
  await cmdList(commandArgs);
314
336
  break;
315
337
  case "meta":
316
- cmdMeta();
338
+ cmdMeta(commandArgs);
317
339
  break;
318
340
  case "validate":
319
341
  cmdValidate(commandArgs);
@@ -371,7 +393,7 @@ skills:
371
393
  break;
372
394
  case "stale": {
373
395
  const { checkStaleness } = await import("./staleness-B5gUj7FR.mjs");
374
- const { scanForIntents: scanStale } = await import("./scanner-DkShtCWX.mjs");
396
+ const { scanForIntents: scanStale } = await import("./scanner-DQeiZRzp.mjs");
375
397
  let staleResult;
376
398
  try {
377
399
  staleResult = await scanStale();
@@ -402,9 +424,19 @@ skills:
402
424
  }
403
425
  break;
404
426
  }
405
- case "setup": {
406
- const { runSetup } = await import("./setup.mjs");
407
- runSetup(process.cwd(), getMetaDir(), commandArgs);
427
+ case "add-library-bin": {
428
+ const { runAddLibraryBin } = await import("./setup.mjs");
429
+ runAddLibraryBin(process.cwd());
430
+ break;
431
+ }
432
+ case "edit-package-json": {
433
+ const { runEditPackageJson } = await import("./setup.mjs");
434
+ runEditPackageJson(process.cwd());
435
+ break;
436
+ }
437
+ case "setup-github-actions": {
438
+ const { runSetupGithubActions } = await import("./setup.mjs");
439
+ runSetupGithubActions(process.cwd(), getMetaDir());
408
440
  break;
409
441
  }
410
442
  default:
package/dist/index.d.mts CHANGED
@@ -1,5 +1,5 @@
1
1
  import { a as IntentProjectConfig, c as ScanResult, d as StalenessReport, i as IntentPackage, l as SkillEntry, n as FeedbackPayload, o as MetaFeedbackPayload, r as IntentConfig, s as MetaSkillName, t as AgentName, u as SkillStaleness } from "./types-BmnI8kFB.mjs";
2
- import { n as runSetup } from "./setup-BJ4giTKA.mjs";
2
+ import { a as runEditPackageJson, i as runAddLibraryBin, n as EditPackageJsonResult, o as runSetupGithubActions, r as SetupGithubActionsResult, t as AddLibraryBinResult } from "./setup-CANkTz55.mjs";
3
3
 
4
4
  //#region src/scanner.d.ts
5
5
  declare function scanForIntents(root?: string): Promise<ScanResult>;
@@ -44,4 +44,4 @@ declare function findSkillFiles(dir: string): string[];
44
44
  */
45
45
  declare function parseFrontmatter(filePath: string): Record<string, unknown> | null;
46
46
  //#endregion
47
- export { type AgentName, type FeedbackPayload, type IntentConfig, type IntentPackage, type IntentProjectConfig, type MetaFeedbackPayload, type MetaSkillName, type ScanResult, type SkillEntry, type SkillStaleness, type StalenessReport, checkStaleness, containsSecrets, findSkillFiles, hasGhCli, metaToMarkdown, parseFrontmatter, resolveFrequency, runSetup, scanForIntents, submitFeedback, submitMetaFeedback, toMarkdown, validateMetaPayload, validatePayload };
47
+ export { type AddLibraryBinResult, type AgentName, type EditPackageJsonResult, type FeedbackPayload, type IntentConfig, type IntentPackage, type IntentProjectConfig, type MetaFeedbackPayload, type MetaSkillName, type ScanResult, type SetupGithubActionsResult, type SkillEntry, type SkillStaleness, type StalenessReport, checkStaleness, containsSecrets, findSkillFiles, hasGhCli, metaToMarkdown, parseFrontmatter, resolveFrequency, runAddLibraryBin, runEditPackageJson, runSetupGithubActions, scanForIntents, submitFeedback, submitMetaFeedback, toMarkdown, validateMetaPayload, validatePayload };
package/dist/index.mjs CHANGED
@@ -1,7 +1,7 @@
1
1
  import { n as parseFrontmatter, t as findSkillFiles } from "./utils-DH3jY3CI.mjs";
2
- import { t as scanForIntents } from "./scanner-OmHt14bs.mjs";
2
+ import { t as scanForIntents } from "./scanner-dIYdkHQ1.mjs";
3
3
  import { t as checkStaleness } from "./staleness-lP6B0O4z.mjs";
4
- import { t as runSetup } from "./setup-DGvdyKEq.mjs";
4
+ import { n as runEditPackageJson, r as runSetupGithubActions, t as runAddLibraryBin } from "./setup-BYOg-Ii-.mjs";
5
5
  import { readFileSync, writeFileSync } from "node:fs";
6
6
  import { join } from "node:path";
7
7
  import { execFileSync, execSync } from "node:child_process";
@@ -212,7 +212,7 @@ function submitMetaFeedback(payload, opts) {
212
212
  "--title",
213
213
  `Meta-Skill Feedback: ${payload.metaSkill} (${payload.userRating})`,
214
214
  "--label",
215
- `feedback:${payload.metaSkill}`,
215
+ `skill:${payload.metaSkill}`,
216
216
  "--body",
217
217
  "-"
218
218
  ], {
@@ -246,4 +246,4 @@ function submitMetaFeedback(payload, opts) {
246
246
  }
247
247
 
248
248
  //#endregion
249
- export { checkStaleness, containsSecrets, findSkillFiles, hasGhCli, metaToMarkdown, parseFrontmatter, resolveFrequency, runSetup, scanForIntents, submitFeedback, submitMetaFeedback, toMarkdown, validateMetaPayload, validatePayload };
249
+ export { checkStaleness, containsSecrets, findSkillFiles, hasGhCli, metaToMarkdown, parseFrontmatter, resolveFrequency, runAddLibraryBin, runEditPackageJson, runSetupGithubActions, scanForIntents, submitFeedback, submitMetaFeedback, toMarkdown, validateMetaPayload, validatePayload };
@@ -0,0 +1,4 @@
1
+ import "./utils-DH3jY3CI.mjs";
2
+ import { t as scanForIntents } from "./scanner-dIYdkHQ1.mjs";
3
+
4
+ export { scanForIntents };
@@ -125,7 +125,7 @@ async function scanForIntents(root) {
125
125
  };
126
126
  }
127
127
  for (const entry of topEntries) {
128
- if (!entry.isDirectory()) continue;
128
+ if (!entry.isDirectory() && !entry.isSymbolicLink()) continue;
129
129
  const dirPath = join(nodeModulesDir, entry.name);
130
130
  if (entry.name.startsWith("@")) {
131
131
  let scopedEntries;
@@ -138,7 +138,7 @@ async function scanForIntents(root) {
138
138
  continue;
139
139
  }
140
140
  for (const scoped of scopedEntries) {
141
- if (!scoped.isDirectory()) continue;
141
+ if (!scoped.isDirectory() && !scoped.isSymbolicLink()) continue;
142
142
  packageDirs.push({ dirPath: join(dirPath, scoped.name) });
143
143
  }
144
144
  } else if (!entry.name.startsWith(".")) packageDirs.push({ dirPath });
@@ -0,0 +1,197 @@
1
+ import { existsSync, mkdirSync, readFileSync, readdirSync, writeFileSync } from "node:fs";
2
+ import { join } from "node:path";
3
+
4
+ //#region src/setup.ts
5
+ function detectVars(root) {
6
+ const pkgPath = join(root, "package.json");
7
+ let pkgJson = {};
8
+ try {
9
+ pkgJson = JSON.parse(readFileSync(pkgPath, "utf8"));
10
+ } catch (err) {
11
+ if (!(err && typeof err === "object" && "code" in err && err.code === "ENOENT")) console.error(`Warning: could not read ${pkgPath}: ${err instanceof Error ? err.message : err}`);
12
+ }
13
+ const name = typeof pkgJson.name === "string" ? pkgJson.name : "unknown";
14
+ const intent = pkgJson.intent;
15
+ const repo = typeof intent?.repo === "string" ? intent.repo : name.replace(/^@/, "").replace(/\//, "/");
16
+ const docs = typeof intent?.docs === "string" ? intent.docs : "docs/";
17
+ let srcPath = `packages/${name.replace(/^@[^/]+\//, "")}/src/**`;
18
+ if (existsSync(join(root, "src"))) srcPath = "src/**";
19
+ return {
20
+ PACKAGE_NAME: name,
21
+ REPO: repo,
22
+ DOCS_PATH: docs.endsWith("**") ? docs : docs.replace(/\/$/, "") + "/**",
23
+ SRC_PATH: srcPath
24
+ };
25
+ }
26
+ function applyVars(content, vars) {
27
+ return content.replace(/\{\{PACKAGE_NAME\}\}/g, vars.PACKAGE_NAME).replace(/\{\{REPO\}\}/g, vars.REPO).replace(/\{\{DOCS_PATH\}\}/g, vars.DOCS_PATH).replace(/\{\{SRC_PATH\}\}/g, vars.SRC_PATH);
28
+ }
29
+ function copyTemplates(srcDir, destDir, vars) {
30
+ const copied = [];
31
+ const skipped = [];
32
+ if (!existsSync(srcDir)) return {
33
+ copied,
34
+ skipped
35
+ };
36
+ mkdirSync(destDir, { recursive: true });
37
+ for (const entry of readdirSync(srcDir)) {
38
+ const srcPath = join(srcDir, entry);
39
+ const destPath = join(destDir, entry);
40
+ if (existsSync(destPath)) {
41
+ skipped.push(destPath);
42
+ continue;
43
+ }
44
+ writeFileSync(destPath, applyVars(readFileSync(srcPath, "utf8"), vars));
45
+ copied.push(destPath);
46
+ }
47
+ return {
48
+ copied,
49
+ skipped
50
+ };
51
+ }
52
+ function getShimContent(ext) {
53
+ return `#!/usr/bin/env node
54
+ // Auto-generated by @tanstack/intent setup
55
+ // Exposes the intent end-user CLI for consumers of this library.
56
+ // Commit this file, then add to your package.json:
57
+ // "bin": { "intent": "./bin/intent.${ext}" }
58
+ await import('@tanstack/intent/intent-library')
59
+ `;
60
+ }
61
+ function detectShimExtension(root) {
62
+ try {
63
+ if (JSON.parse(readFileSync(join(root, "package.json"), "utf8")).type === "module") return "js";
64
+ } catch (err) {
65
+ if (!(err && typeof err === "object" && "code" in err && err.code === "ENOENT")) console.error(`Warning: could not read package.json: ${err instanceof Error ? err.message : err}`);
66
+ }
67
+ return "mjs";
68
+ }
69
+ function findExistingShim(root) {
70
+ const shimJs = join(root, "bin", "intent.js");
71
+ if (existsSync(shimJs)) return shimJs;
72
+ const shimMjs = join(root, "bin", "intent.mjs");
73
+ if (existsSync(shimMjs)) return shimMjs;
74
+ return null;
75
+ }
76
+ function runAddLibraryBin(root) {
77
+ const result = {
78
+ shim: null,
79
+ skipped: null
80
+ };
81
+ const existingShim = findExistingShim(root);
82
+ if (existingShim) {
83
+ result.skipped = existingShim;
84
+ console.log(` Already exists: ${existingShim}`);
85
+ return result;
86
+ }
87
+ const ext = detectShimExtension(root);
88
+ const shimPath = join(root, "bin", `intent.${ext}`);
89
+ mkdirSync(join(root, "bin"), { recursive: true });
90
+ writeFileSync(shimPath, getShimContent(ext));
91
+ result.shim = shimPath;
92
+ console.log(`✓ Generated intent shim: ${shimPath}`);
93
+ console.log(`\n Run \`npx @tanstack/intent edit-package-json\` to wire package.json.`);
94
+ return result;
95
+ }
96
+ function runEditPackageJson(root) {
97
+ const result = {
98
+ added: [],
99
+ alreadyPresent: []
100
+ };
101
+ const pkgPath = join(root, "package.json");
102
+ if (!existsSync(pkgPath)) {
103
+ console.error("No package.json found in " + root);
104
+ process.exitCode = 1;
105
+ return result;
106
+ }
107
+ const raw = readFileSync(pkgPath, "utf8");
108
+ let pkg;
109
+ try {
110
+ pkg = JSON.parse(raw);
111
+ } catch (err) {
112
+ const detail = err instanceof SyntaxError ? err.message : String(err);
113
+ console.error(`Failed to parse ${pkgPath}: ${detail}`);
114
+ return result;
115
+ }
116
+ const indentMatch = raw.match(/^(\s+)"/m);
117
+ const indentSize = indentMatch?.[1] ? indentMatch[1].length : 2;
118
+ if (!Array.isArray(pkg.files)) pkg.files = [];
119
+ const files = pkg.files;
120
+ const requiredFiles = (() => {
121
+ let dir = join(root, "..");
122
+ for (let i = 0; i < 5; i++) {
123
+ const parentPkg = join(dir, "package.json");
124
+ if (existsSync(parentPkg)) {
125
+ try {
126
+ const parent = JSON.parse(readFileSync(parentPkg, "utf8"));
127
+ if (Array.isArray(parent.workspaces) || parent.workspaces?.packages) return true;
128
+ } catch {}
129
+ return false;
130
+ }
131
+ const next = join(dir, "..");
132
+ if (next === dir) break;
133
+ dir = next;
134
+ }
135
+ return false;
136
+ })() ? ["skills", "bin"] : [
137
+ "skills",
138
+ "bin",
139
+ "!skills/_artifacts"
140
+ ];
141
+ for (const entry of requiredFiles) if (files.includes(entry)) result.alreadyPresent.push(`files: "${entry}"`);
142
+ else {
143
+ files.push(entry);
144
+ result.added.push(`files: "${entry}"`);
145
+ }
146
+ const existingShim = findExistingShim(root);
147
+ let ext;
148
+ if (existingShim) ext = existingShim.endsWith(".mjs") ? "mjs" : "js";
149
+ else ext = pkg.type === "module" ? "js" : "mjs";
150
+ const shimRelative = `./bin/intent.${ext}`;
151
+ if (typeof pkg.bin === "object" && pkg.bin !== null) {
152
+ const binObj = pkg.bin;
153
+ if (binObj.intent) result.alreadyPresent.push(`bin.intent`);
154
+ else {
155
+ binObj.intent = shimRelative;
156
+ result.added.push(`bin.intent: "${shimRelative}"`);
157
+ }
158
+ } else if (!pkg.bin) {
159
+ pkg.bin = { intent: shimRelative };
160
+ result.added.push(`bin.intent: "${shimRelative}"`);
161
+ } else if (typeof pkg.bin === "string") {
162
+ const pkgName = typeof pkg.name === "string" ? pkg.name.replace(/^@[^/]+\//, "") : "unknown";
163
+ pkg.bin = {
164
+ [pkgName]: pkg.bin,
165
+ intent: shimRelative
166
+ };
167
+ result.added.push(`bin.intent: "${shimRelative}" (converted bin from string to object)`);
168
+ }
169
+ writeFileSync(pkgPath, JSON.stringify(pkg, null, indentSize) + "\n");
170
+ for (const a of result.added) console.log(`✓ Added ${a}`);
171
+ for (const a of result.alreadyPresent) console.log(` Already present: ${a}`);
172
+ return result;
173
+ }
174
+ function runSetupGithubActions(root, metaDir) {
175
+ const vars = detectVars(root);
176
+ const result = {
177
+ workflows: [],
178
+ skipped: []
179
+ };
180
+ const { copied, skipped } = copyTemplates(join(metaDir, "templates", "workflows"), join(root, ".github", "workflows"), vars);
181
+ result.workflows = copied;
182
+ result.skipped = skipped;
183
+ for (const f of result.workflows) console.log(`✓ Copied workflow: ${f}`);
184
+ for (const f of result.skipped) console.log(` Already exists: ${f}`);
185
+ if (result.workflows.length === 0 && result.skipped.length === 0) console.log("No templates directory found. Is @tanstack/intent installed?");
186
+ else if (result.workflows.length > 0) {
187
+ console.log(`\nTemplate variables applied:`);
188
+ console.log(` Package: ${vars.PACKAGE_NAME}`);
189
+ console.log(` Repo: ${vars.REPO}`);
190
+ console.log(` Docs: ${vars.DOCS_PATH}`);
191
+ console.log(` Src: ${vars.SRC_PATH}`);
192
+ }
193
+ return result;
194
+ }
195
+
196
+ //#endregion
197
+ export { runEditPackageJson as n, runSetupGithubActions as r, runAddLibraryBin as t };
@@ -0,0 +1,18 @@
1
+ //#region src/setup.d.ts
2
+ interface AddLibraryBinResult {
3
+ shim: string | null;
4
+ skipped: string | null;
5
+ }
6
+ interface EditPackageJsonResult {
7
+ added: string[];
8
+ alreadyPresent: string[];
9
+ }
10
+ interface SetupGithubActionsResult {
11
+ workflows: string[];
12
+ skipped: string[];
13
+ }
14
+ declare function runAddLibraryBin(root: string): AddLibraryBinResult;
15
+ declare function runEditPackageJson(root: string): EditPackageJsonResult;
16
+ declare function runSetupGithubActions(root: string, metaDir: string): SetupGithubActionsResult;
17
+ //#endregion
18
+ export { runEditPackageJson as a, runAddLibraryBin as i, EditPackageJsonResult as n, runSetupGithubActions as o, SetupGithubActionsResult as r, AddLibraryBinResult as t };
package/dist/setup.d.mts CHANGED
@@ -1,2 +1,2 @@
1
- import { n as runSetup, t as SetupResult } from "./setup-BJ4giTKA.mjs";
2
- export { SetupResult, runSetup };
1
+ import { a as runEditPackageJson, i as runAddLibraryBin, n as EditPackageJsonResult, o as runSetupGithubActions, r as SetupGithubActionsResult, t as AddLibraryBinResult } from "./setup-CANkTz55.mjs";
2
+ export { AddLibraryBinResult, EditPackageJsonResult, SetupGithubActionsResult, runAddLibraryBin, runEditPackageJson, runSetupGithubActions };
package/dist/setup.mjs CHANGED
@@ -1,3 +1,3 @@
1
- import { t as runSetup } from "./setup-DGvdyKEq.mjs";
1
+ import { n as runEditPackageJson, r as runSetupGithubActions, t as runAddLibraryBin } from "./setup-BYOg-Ii-.mjs";
2
2
 
3
- export { runSetup };
3
+ export { runAddLibraryBin, runEditPackageJson, runSetupGithubActions };
@@ -42,9 +42,12 @@ path applies (see below).
42
42
 
43
43
  ### Lightweight path (small libraries)
44
44
 
45
- After Phase 1, if the library has **fewer than 5 client-facing skill
46
- areas** (e.g. a focused utility library, a single-purpose tool, or a
47
- library with only 2–3 distinct developer tasks), use a compressed flow:
45
+ After Phase 1, decide whether the library warrants the full five-phase
46
+ flow or the compressed flow below. This is a judgment call lean toward
47
+ full discovery unless the library is obviously small (single-purpose
48
+ utility, 2–3 distinct developer tasks max). Use a compressed flow when
49
+ the skill surface is small enough that two interview rounds would be
50
+ redundant:
48
51
 
49
52
  1. **Phase 1** — Quick scan (same as full flow)
50
53
  2. **Phase 2+4 combined** — Single interview round. Combine the
@@ -59,6 +62,42 @@ The lightweight path produces identical output artifacts (domain_map.yaml
59
62
  and skill_spec.md). It just avoids two separate interview rounds when the
60
63
  library is small enough that one round covers everything.
61
64
 
65
+ ### Hard rules — interview phases are mandatory and interactive
66
+
67
+ These rules override any other reasoning. No exceptions.
68
+
69
+ 1. **Phases 2 and 4 are interactive interviews conducted with the
70
+ maintainer.** You must ask the questions specified in each sub-section
71
+ and wait for the maintainer's response before continuing. Documentation,
72
+ source code, and other automated analysis are NOT substitutes for the
73
+ maintainer's answers.
74
+ 2. **Every question in Phases 2 and 4 must be asked as an open-ended
75
+ question and sent as a message to the maintainer.** You must then
76
+ STOP and WAIT for their reply. Do not answer your own questions. Do
77
+ not infer answers from documentation. Do not skip questions because
78
+ you believe you already know the answer.
79
+ 3. **Do not convert open-ended questions into multiple-choice,
80
+ yes/no, or confirmation prompts.** The question templates in each
81
+ sub-section are open-ended by design. Present them as open-ended
82
+ questions. The maintainer's unprompted answers surface knowledge that
83
+ pre-structured options suppress.
84
+ 4. **Minimum question counts are enforced.** Each sub-section specifies
85
+ a question count range (e.g. "2–4 questions"). You must ask at least
86
+ the minimum number. Asking zero questions in any sub-section is a
87
+ protocol violation.
88
+ 5. **STOP gates are mandatory.** At the boundaries marked `── STOP ──`
89
+ below, you must halt execution and wait for the maintainer's response
90
+ or acknowledgment before proceeding. Do not continue past a STOP gate
91
+ in the same message.
92
+ 6. **If the maintainer asks to skip an interview phase**, explain the
93
+ value of the phase and what will be lost. Proceed with skipping only
94
+ if they confirm a second time.
95
+ 7. **Rich documentation makes interviews MORE valuable, not less.**
96
+ When docs are comprehensive, the interview surfaces what docs miss:
97
+ implicit knowledge, AI-specific failure modes, undocumented tradeoffs,
98
+ and the maintainer's prioritization of what matters most. Never
99
+ rationalize skipping interviews because documentation is thorough.
100
+
62
101
  ---
63
102
 
64
103
  ## Phase 1 — Quick scan (autonomous, ~10 minutes)
@@ -105,20 +144,37 @@ Log (but do not group yet):
105
144
  - Which frameworks it supports
106
145
  - Any existing skill files, agent configs, or intents
107
146
  - Whether the library is a monorepo and which packages matter
147
+ - Peer dependency constraints — read `peerDependencies` and
148
+ `peerDependenciesMeta` from each client-facing package.json to
149
+ understand version ranges and optional integrations early
150
+
151
+ Present your initial impressions to the maintainer as a brief summary
152
+ (3–5 bullets). This orients them on what you found and primes them for
153
+ the interview.
154
+
155
+ **── STOP ── Do not proceed to Phase 2 until the maintainer has
156
+ acknowledged your summary or responded.**
108
157
 
109
158
  ---
110
159
 
111
- ## Phase 2 — High-level interview
160
+ ## Phase 2 — High-level interview (interactive — requires maintainer)
112
161
 
113
162
  The maintainer's mental model of developer tasks IS the skill map. Your
114
163
  job in this phase is to extract it — not to propose your own structure.
115
164
 
165
+ You must ask the questions below to the maintainer and wait for their
166
+ responses. Do not infer answers from documentation or source code.
167
+
116
168
  ### Rules for Phase 2
117
169
 
118
170
  1. One topic per message for open-ended questions. You may batch 2–3
119
171
  yes/no or short-confirmation questions together.
120
- 2. Take notes silently. Do not summarize back unless asked.
121
- 3. If the maintainer gives a short answer, probe deeper before moving on.
172
+ 2. Ask each question as written (you may adapt phrasing to context, but
173
+ keep questions open-ended never convert to multiple-choice).
174
+ 3. Wait for the maintainer's response after each question before asking
175
+ the next.
176
+ 4. Take notes silently. Do not summarize back unless asked.
177
+ 5. If the maintainer gives a short answer, probe deeper before moving on.
122
178
 
123
179
  ### 2a — Developer tasks (2–4 questions)
124
180
 
@@ -135,6 +191,13 @@ Follow up to enumerate distinct tasks:
135
191
  > things like 'set up the client', 'implement auth', 'debug sync issues'
136
192
  > — each one a separate moment where they'd want focused guidance."
137
193
 
194
+ For monorepo libraries, also ask about cross-package tasks:
195
+
196
+ > "Are there tasks that touch multiple packages in your monorepo? For
197
+ > example, a getting-started flow that requires imports from both the
198
+ > client and server packages? I want to make sure skills that span
199
+ > package boundaries are captured correctly."
200
+
138
201
  ### 2b — Developer journeys (1–2 questions)
139
202
 
140
203
  Surface lifecycle/journey skills that cross-cut task areas:
@@ -144,13 +207,22 @@ Surface lifecycle/journey skills that cross-cut task areas:
144
207
  > a migrate-from-v4 walkthrough. Which of these exist in your docs
145
208
  > or would be valuable as standalone skills?"
146
209
 
147
- ### 2c — Composition and ecosystem (1–2 questions)
210
+ ### 2c — Composition and ecosystem (1–3 questions)
148
211
 
149
212
  > "Which other libraries does yours compose with most often? Are there
150
213
  > integration patterns important enough to warrant their own skill —
151
214
  > for example, using your library with [framework/ORM/router]?"
152
215
 
153
- ### 2d Confirm initial skill map
216
+ > "Are there tasks that developers might expect your library to handle,
217
+ > but that are actually handled by a companion library? Which tasks
218
+ > should we explicitly exclude from your library's skills?"
219
+
220
+ ### 2d — Exclude experimental features (1 question)
221
+
222
+ > "Are there any features that are experimental, unstable, or not yet
223
+ > ready to document for agents? We'll exclude these from the skill set."
224
+
225
+ ### 2e — Confirm initial skill map
154
226
 
155
227
  Synthesize what you heard into a proposed skill list and present it:
156
228
 
@@ -158,6 +230,9 @@ Synthesize what you heard into a proposed skill list and present it:
158
230
  > [enumerate skills with one-line descriptions]. Does this match how
159
231
  > you think about your library? What would you add, remove, or rename?"
160
232
 
233
+ **── STOP ── Do not proceed to Phase 3 until the maintainer has
234
+ reviewed and confirmed (or corrected) the skill list.**
235
+
161
236
  ---
162
237
 
163
238
  ## Phase 3 — Deep read (autonomous)
@@ -170,7 +245,14 @@ gotchas.
170
245
 
171
246
  Read in this order. Each step builds context for the next.
172
247
 
173
- 1. **Every narrative guide** the how-to content, not API reference tables
248
+ Before starting, list every file in the docs directory (and subdirectories).
249
+ Use this list as a checklist — every narrative file must be read. Do not
250
+ sample a subset and extrapolate.
251
+
252
+ 1. **Narrative guides** — read as many as needed to build confidence in
253
+ your understanding. Prioritize getting-started, migration, and guides
254
+ covering the skill areas from Phase 2. Skip exhaustive reading of large
255
+ online-only doc sets.
174
256
  2. **Migration guides** — highest-yield source for failure modes; every
175
257
  breaking change is exactly what agents trained on older versions produce
176
258
  3. **API reference** — scan for exports, type signatures, option shapes
@@ -417,20 +499,35 @@ Present the draft to the maintainer before starting Phase 4:
417
499
  > [N] skills and [M] failure modes. I've flagged [K] specific gaps where
418
500
  > I need your input."
419
501
 
502
+ Include the full draft domain_map.yaml in your message so the maintainer
503
+ can review it. Also include a checklist of all docs files you read.
504
+
505
+ **── STOP ── Do not proceed to Phase 4 until the maintainer has
506
+ reviewed the draft and responded. Their feedback on the draft informs
507
+ the detail interview questions.**
508
+
420
509
  ---
421
510
 
422
- ## Phase 4 — Detail interview (builds on Phase 1–3)
511
+ ## Phase 4 — Detail interview (interactive requires maintainer)
423
512
 
424
513
  You have the maintainer's task map and a deep read. The interview now
425
514
  fills gaps, validates your understanding, and surfaces implicit knowledge.
426
515
 
516
+ You must ask the questions below to the maintainer and wait for their
517
+ responses. Do not infer answers from documentation or source code —
518
+ even for gaps you think you can answer from your reading.
519
+
427
520
  ### Rules for Phase 4
428
521
 
429
522
  1. One topic per message for open-ended questions. You may batch 2–3
430
523
  yes/no or short-confirmation questions together.
431
- 2. Each question must reference something specific from your reading.
432
- 3. If the maintainer gives a short answer, probe deeper before moving on.
433
- 4. Take notes silently. Do not summarize back unless asked.
524
+ 2. Ask each question as written (you may adapt phrasing to context, but
525
+ keep questions open-ended never convert to multiple-choice).
526
+ 3. Each question must reference something specific from your reading.
527
+ 4. Wait for the maintainer's response after each question before asking
528
+ the next.
529
+ 5. If the maintainer gives a short answer, probe deeper before moving on.
530
+ 6. Take notes silently. Do not summarize back unless asked.
434
531
 
435
532
  ### 4a — Draft review (2–3 questions)
436
533
 
@@ -538,6 +635,10 @@ Merge interview findings into the draft. For each interview answer:
538
635
  4. If it reveals a new skill — add it
539
636
  5. If it fills a gap — remove from gaps section
540
637
 
638
+ Validate the domain_map.yaml by parsing it with a YAML parser. Check for
639
+ duplicate keys, invalid syntax, and structural correctness. Fix any issues
640
+ before presenting the final artifact.
641
+
541
642
  Update `status: draft` to `status: reviewed`.
542
643
 
543
644
  ---
@@ -580,6 +681,9 @@ skills:
580
681
  domain: '[parent domain slug]'
581
682
  description: '[what a developer is doing — matches a specific task/moment]'
582
683
  type: '[core | framework | lifecycle | composition]'
684
+ packages: # required for monorepo; omit for single-package libraries
685
+ - '[primary package name]'
686
+ - '[secondary package name, if skill spans multiple packages]'
583
687
  covers:
584
688
  - '[API/hook/concept 1]'
585
689
  - '[API/hook/concept 2]'
@@ -710,6 +814,11 @@ not promotional.]
710
814
  | ------------------------------------- | -------------------------------------------------------------------------- |
711
815
  | Quick scan before interview | Never interview without at least reading README and package structure |
712
816
  | High-level interview before deep read | The maintainer's task map informs what you read deeply |
817
+ | **Interview phases are interactive** | Phases 2 and 4 require sending questions to the maintainer and waiting |
818
+ | **Docs are not a substitute** | Documentation cannot replace maintainer answers — even comprehensive docs |
819
+ | **Open-ended questions stay open** | Never convert interview questions to multiple-choice or yes/no |
820
+ | **Minimum question counts enforced** | Each sub-section's minimum count must be met; zero questions = violation |
821
+ | **STOP gates are mandatory** | Do not proceed past a STOP gate without maintainer response |
713
822
  | Batch only confirmations | Yes/no questions may batch 2–3; open-ended questions get their own message |
714
823
  | Questions reference findings | No generic questions — cite what you found |
715
824
  | Skills are task-focused | Each skill matches a developer moment, not a conceptual area |
@@ -719,6 +828,7 @@ not promotional.]
719
828
  | No marketing prose | Library description is factual, not promotional |
720
829
  | domain_map.yaml is valid YAML | Parseable by any YAML parser |
721
830
  | Draft before detail interview | Present draft for review before Phase 4 |
831
+ | **Draft reviewed before Phase 4** | Maintainer must acknowledge or respond to draft before detail interview |
722
832
  | Agent-specific failures probed | Always ask AI-agent-specific questions in Phase 4c |
723
833
  | Compositions discovered from code | Scan peer deps and examples before asking composition questions |
724
834
  | Cross-skill failure modes tagged | Failure modes spanning skills list all relevant slugs |
@@ -727,6 +837,7 @@ not promotional.]
727
837
  | Dense surfaces flagged | Topics with >10 patterns noted as reference_candidates |
728
838
  | Lifecycle skills considered | Suggest journey skills when docs have the material |
729
839
  | Cross-references mapped | Skills that illuminate each other get "See also" pointers |
840
+ | **All docs files read** | List docs directory contents and read every narrative file — no sampling |
730
841
 
731
842
  ---
732
843
 
@@ -736,49 +847,16 @@ This skill is designed to produce consistent results across Claude, GPT-4+,
736
847
  Gemini, and open-source models. To achieve this:
737
848
 
738
849
  - All instructions use imperative sentences, not suggestions
850
+ - Interview phases use explicit STOP gates to prevent models from
851
+ continuing autonomously past interactive checkpoints
852
+ - Hard rules at the top override any model tendency to rationalize
853
+ skipping interactive phases when documentation is available
854
+ - Open-ended questions are explicitly protected from conversion to
855
+ multiple-choice or confirmation prompts, which models default to
856
+ when they have enough context to pre-populate answers
739
857
  - Output formats use YAML (universally parsed) and Markdown tables
740
858
  (universally rendered)
741
859
  - Examples use concrete values, not placeholders like "[your value here]"
742
860
  - Section boundaries use Markdown headers (##) for navigation and --- for
743
861
  phase separation
744
862
  - No model-specific features (no XML tags in output, no tool_use assumptions)
745
-
746
- ---
747
-
748
- ## Meta-skill feedback (alpha default)
749
-
750
- After finalizing artifacts, create or update a single Markdown feedback draft
751
- for all three meta skills used in scaffolding. Use this exact template and
752
- fill only the **Domain Discovery** section now. Leave the other sections in
753
- place for later steps to complete.
754
-
755
- ```
756
- # Intent Meta Skill Feedback
757
-
758
- ## Domain Discovery
759
- - What worked well:
760
- - What was confusing or missing:
761
- - Suggestions for improvement:
762
- - Overall rating: good | mixed | bad
763
-
764
- ## Tree Generator
765
- - What worked well:
766
- - What was confusing or missing:
767
- - Suggestions for improvement:
768
- - Overall rating: good | mixed | bad
769
-
770
- ## Generate Skill
771
- - What worked well:
772
- - What was confusing or missing:
773
- - Suggestions for improvement:
774
- - Overall rating: good | mixed | bad
775
-
776
- ## Context (optional)
777
- - Library:
778
- - Repo:
779
- - Docs:
780
- - Notes:
781
- ```
782
-
783
- Do not submit feedback yet. Tell the maintainer to carry this draft forward
784
- to the next meta skill step.
@@ -17,13 +17,29 @@ Run this at the end of any session where you loaded one or more SKILL.md files.
17
17
  The goal is to capture what worked, what didn't, and what was missing — so skill
18
18
  maintainers can improve future versions.
19
19
 
20
+ This skill also covers **meta-skill feedback** — feedback about the scaffolding
21
+ process itself. When invoked after running domain-discovery, tree-generator, and
22
+ generate-skill, treat those three meta skills as the "skills" being evaluated.
23
+ Capture what worked and what didn't in each scaffolding phase so the meta skills
24
+ can be improved.
25
+
20
26
  ---
21
27
 
22
28
  ## Phase 1 — Automated Signal Collection
23
29
 
24
30
  Review your own session transcript. No human interaction needed yet.
25
31
 
26
- ### 1a: Gap detection
32
+ ### 1a: Skills inventory
33
+
34
+ Before analyzing gaps and errors, inventory all skills that were available
35
+ during the session:
36
+
37
+ - **Loaded and used:** Skills you read and actively followed.
38
+ - **Available but not loaded:** Skills that were installed (discoverable via
39
+ `intent list`) but you never read. This is important — many issues stem from
40
+ the agent not loading the right skill, not from the skill itself being wrong.
41
+
42
+ ### 1b: Gap detection
27
43
 
28
44
  Identify moments where the skill was silent and you had to bridge the gap
29
45
  yourself — via code reading, search, trial-and-error, or general knowledge.
@@ -34,7 +50,7 @@ For each gap, note:
34
50
  - What the skill should have told you
35
51
  - How you solved it (code reading, web search, guessing)
36
52
 
37
- ### 1b: Error/correction tracking
53
+ ### 1c: Error/correction tracking
38
54
 
39
55
  Identify moments where the skill prescribed an approach that produced an error.
40
56
 
@@ -44,7 +60,7 @@ For each error, note:
44
60
  - The error or incorrect behavior that resulted
45
61
  - The fix you applied
46
62
 
47
- ### 1c: Human intervention events
63
+ ### 1d: Human intervention events
48
64
 
49
65
  Identify moments where the human clarified, corrected, or overrode your approach.
50
66
 
@@ -54,7 +70,7 @@ For each intervention, note:
54
70
  - What the human said or changed
55
71
  - Whether the skill could have prevented this
56
72
 
57
- ### 1d: Step duration anomalies
73
+ ### 1e: Step duration anomalies
58
74
 
59
75
  Identify steps that consumed disproportionate effort compared to their apparent
60
76
  complexity. These signal that the skill should provide a template, snippet, or
@@ -101,21 +117,31 @@ referenced.
101
117
 
102
118
  [one-sentence summary of what the human asked you to do]
103
119
 
120
+ ## Skills Inventory
121
+
122
+ **Loaded and used:**
123
+
124
+ - [list each skill the agent read and actively followed during the session]
125
+
126
+ **Available but not loaded:**
127
+
128
+ - [list skills that were installed/available but the agent never read]
129
+
104
130
  ## What Worked
105
131
 
106
132
  [patterns/instructions from the skill that were accurate and helpful]
107
133
 
108
134
  ## What Failed
109
135
 
110
- [from 1b — skill instructions that produced errors]
136
+ [from 1c — skill instructions that produced errors]
111
137
 
112
138
  ## Missing
113
139
 
114
- [from 1a — gaps where the skill should have covered]
140
+ [from 1b — gaps where the skill should have covered]
115
141
 
116
142
  ## Self-Corrections
117
143
 
118
- [from 1b fixes + 1c human interventions, combined]
144
+ [from 1c fixes + 1d human interventions, combined]
119
145
 
120
146
  ## User Comments
121
147
 
@@ -130,10 +156,11 @@ referenced.
130
156
  | Package | The npm package the skill lives in (e.g. `@tanstack/query-intent`) |
131
157
  | Skill version | Frontmatter `metadata.version` or `library_version` |
132
158
  | Task | Summarize the human's original request in one sentence |
159
+ | Skills Inventory | Which skills were loaded vs. available but not loaded (see below) |
133
160
  | What Worked | List skill sections/patterns that were correct and useful |
134
- | What Failed | From 1b — skill instructions that produced errors |
135
- | Missing | From 1a — gaps where the skill was silent |
136
- | Self-Corrections | From 1b fixes + 1c human interventions, combined |
161
+ | What Failed | From 1c — skill instructions that produced errors |
162
+ | Missing | From 1b — gaps where the skill was silent |
163
+ | Self-Corrections | From 1c fixes + 1d human interventions, combined |
137
164
  | Rating | From Phase 2 sentiment analysis or explicit rating |
138
165
  | User Comments | From Phase 2 answers, keep brief |
139
166
 
@@ -171,7 +198,7 @@ not contain project-specific details. Before submission:
171
198
  Submit directly as a GitHub issue:
172
199
 
173
200
  ```bash
174
- gh issue create --repo [owner/repo] --title "Skill Feedback: [skill-name] ([rating])" --label "feedback:[skill-name]" --body-file intent-feedback.md
201
+ gh issue create --repo [owner/repo] --title "Skill Feedback: [skill-name] ([rating])" --label "skill:[skill-name]" --body-file intent-feedback.md
175
202
  ```
176
203
 
177
204
  If the label doesn't exist, omit the `--label` flag — don't let a missing
@@ -79,6 +79,15 @@ skill-tree-generator for the full spec of each type.
79
79
 
80
80
  ---
81
81
 
82
+ ### Subagent guidance for batch generation
83
+
84
+ When generating multiple skills, spawn a separate subagent for each skill
85
+ (or per-package group). Each subagent receives the domain_map.yaml,
86
+ skill_tree.yaml, and the source docs relevant to its skill. This prevents
87
+ context bleed between skills and allows parallel generation.
88
+
89
+ ---
90
+
82
91
  ## Step 2 — Extract content from sources
83
92
 
84
93
  **Line budget:** Each SKILL.md must stay under 500 lines. Before writing,
@@ -319,6 +328,10 @@ Run every check before outputting. Fix any failures.
319
328
 
320
329
  ## Step 6 — Output
321
330
 
331
+ Before generating, ask the maintainer: "Would you like to review each skill
332
+ individually before I generate the next one, or should I generate all skills
333
+ and you review them together?" Respect their preference.
334
+
322
335
  Output the complete SKILL.md file content. If reference files are needed,
323
336
  output those as well with their relative paths.
324
337
 
@@ -381,48 +394,9 @@ Output is consumed by all major AI coding agents. To ensure consistency:
381
394
 
382
395
  ---
383
396
 
384
- ## Meta-skill feedback (alpha default)
385
-
386
- After generating the first iteration of skills, complete a single Markdown
387
- feedback draft for all three meta skills used in scaffolding. If a draft
388
- exists from previous steps, keep it and fill the **Generate Skill** section.
389
- If no draft exists, create it using this exact template.
390
-
391
- ```
392
-
393
- # Intent Meta Skill Feedback
394
-
395
- ## Domain Discovery
396
-
397
- - What worked well:
398
- - What was confusing or missing:
399
- - Suggestions for improvement:
400
- - Overall rating: good | mixed | bad
401
-
402
- ## Tree Generator
403
-
404
- - What worked well:
405
- - What was confusing or missing:
406
- - Suggestions for improvement:
407
- - Overall rating: good | mixed | bad
408
-
409
- ## Generate Skill
410
-
411
- - What worked well:
412
- - What was confusing or missing:
413
- - Suggestions for improvement:
414
- - Overall rating: good | mixed | bad
415
-
416
- ## Context (optional)
417
-
418
- - Library:
419
- - Repo:
420
- - Docs:
421
- - Notes:
422
-
423
- ```
397
+ ## Meta-skill feedback
424
398
 
425
- Ask the maintainer if they want to edit the feedback. Then ask if you should
426
- send it as a GitHub issue to TanStack/intent. Use the issue title:
427
- `[meta-feedback] intent meta skill`. Only submit if they confirm.
399
+ After generating all skills, run the `skill-feedback-collection` skill to
400
+ capture feedback about the scaffolding process (domain-discovery,
401
+ tree-generator, and generate-skill).
428
402
  ```
@@ -274,14 +274,9 @@ packages/
274
274
  │ └── package.json # Add "skills" to files array
275
275
  ```
276
276
 
277
- Add `"skills"` to each package's `files` array in `package.json` so
278
- skill files are included in the published npm tarball:
279
-
280
- ```json
281
- {
282
- "files": ["dist", "src", "skills"]
283
- }
284
- ```
277
+ Run `intent edit-package-json` to wire each package's `package.json`
278
+ automatically (adds `"skills"`, `"bin"`, and `"!skills/_artifacts"` to the
279
+ `files` array, and adds the `bin` entry if missing).
285
280
 
286
281
  ### Step 2 — Write the core skill
287
282
 
@@ -852,41 +847,3 @@ When updating:
852
847
  3. CHANGELOG.md entry
853
848
 
854
849
  ---
855
-
856
- ## Meta-skill feedback (alpha default)
857
-
858
- After producing the skill tree artifact, update a single Markdown feedback
859
- draft for all three meta skills used in scaffolding. If a draft exists from
860
- Domain Discovery, keep it and fill only the **Tree Generator** section. If
861
- no draft exists, create it using this exact template.
862
-
863
- ```
864
- # Intent Meta Skill Feedback
865
-
866
- ## Domain Discovery
867
- - What worked well:
868
- - What was confusing or missing:
869
- - Suggestions for improvement:
870
- - Overall rating: good | mixed | bad
871
-
872
- ## Tree Generator
873
- - What worked well:
874
- - What was confusing or missing:
875
- - Suggestions for improvement:
876
- - Overall rating: good | mixed | bad
877
-
878
- ## Generate Skill
879
- - What worked well:
880
- - What was confusing or missing:
881
- - Suggestions for improvement:
882
- - Overall rating: good | mixed | bad
883
-
884
- ## Context (optional)
885
- - Library:
886
- - Repo:
887
- - Docs:
888
- - Notes:
889
- ```
890
-
891
- Do not submit feedback yet. Carry this draft forward to the generate-skill
892
- step.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tanstack/intent",
3
- "version": "0.0.10",
3
+ "version": "0.0.13",
4
4
  "description": "Ship compositional knowledge for AI coding agents alongside your npm packages",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -1,4 +0,0 @@
1
- import "./utils-DH3jY3CI.mjs";
2
- import { t as scanForIntents } from "./scanner-OmHt14bs.mjs";
3
-
4
- export { scanForIntents };
@@ -1,9 +0,0 @@
1
- //#region src/setup.d.ts
2
- interface SetupResult {
3
- workflows: string[];
4
- skipped: string[];
5
- shim: string | null;
6
- }
7
- declare function runSetup(root: string, metaDir: string, args: string[]): SetupResult;
8
- //#endregion
9
- export { runSetup as n, SetupResult as t };
@@ -1,125 +0,0 @@
1
- import { existsSync, mkdirSync, readFileSync, readdirSync, writeFileSync } from "node:fs";
2
- import { join } from "node:path";
3
-
4
- //#region src/setup.ts
5
- function detectVars(root) {
6
- const pkgPath = join(root, "package.json");
7
- let pkgJson = {};
8
- try {
9
- pkgJson = JSON.parse(readFileSync(pkgPath, "utf8"));
10
- } catch {}
11
- const name = typeof pkgJson.name === "string" ? pkgJson.name : "unknown";
12
- const intent = pkgJson.intent;
13
- const repo = typeof intent?.repo === "string" ? intent.repo : name.replace(/^@/, "").replace(/\//, "/");
14
- const docs = typeof intent?.docs === "string" ? intent.docs : "docs/";
15
- let srcPath = `packages/${name.replace(/^@[^/]+\//, "")}/src/**`;
16
- if (existsSync(join(root, "src"))) srcPath = "src/**";
17
- return {
18
- PACKAGE_NAME: name,
19
- REPO: repo,
20
- DOCS_PATH: docs.endsWith("**") ? docs : docs.replace(/\/$/, "") + "/**",
21
- SRC_PATH: srcPath
22
- };
23
- }
24
- function applyVars(content, vars) {
25
- return content.replace(/\{\{PACKAGE_NAME\}\}/g, vars.PACKAGE_NAME).replace(/\{\{REPO\}\}/g, vars.REPO).replace(/\{\{DOCS_PATH\}\}/g, vars.DOCS_PATH).replace(/\{\{SRC_PATH\}\}/g, vars.SRC_PATH);
26
- }
27
- function copyTemplates(srcDir, destDir, vars) {
28
- const copied = [];
29
- const skipped = [];
30
- if (!existsSync(srcDir)) return {
31
- copied,
32
- skipped
33
- };
34
- mkdirSync(destDir, { recursive: true });
35
- for (const entry of readdirSync(srcDir)) {
36
- const srcPath = join(srcDir, entry);
37
- const destPath = join(destDir, entry);
38
- if (existsSync(destPath)) {
39
- skipped.push(destPath);
40
- continue;
41
- }
42
- writeFileSync(destPath, applyVars(readFileSync(srcPath, "utf8"), vars));
43
- copied.push(destPath);
44
- }
45
- return {
46
- copied,
47
- skipped
48
- };
49
- }
50
- function getShimContent(ext) {
51
- return `#!/usr/bin/env node
52
- // Auto-generated by @tanstack/intent setup
53
- // Exposes the intent end-user CLI for consumers of this library.
54
- // Commit this file, then add to your package.json:
55
- // "bin": { "intent": "./bin/intent.${ext}" }
56
- await import('@tanstack/intent/intent-library')
57
- `;
58
- }
59
- function detectShimExtension(root) {
60
- try {
61
- if (JSON.parse(readFileSync(join(root, "package.json"), "utf8")).type === "module") return "js";
62
- } catch {}
63
- return "mjs";
64
- }
65
- function findExistingShim(root) {
66
- const shimJs = join(root, "bin", "intent.js");
67
- if (existsSync(shimJs)) return shimJs;
68
- const shimMjs = join(root, "bin", "intent.mjs");
69
- if (existsSync(shimMjs)) return shimMjs;
70
- return null;
71
- }
72
- function generateShim(root, result) {
73
- const existingShim = findExistingShim(root);
74
- if (existingShim) {
75
- result.skipped.push(existingShim);
76
- return;
77
- }
78
- const ext = detectShimExtension(root);
79
- const shimPath = join(root, "bin", `intent.${ext}`);
80
- mkdirSync(join(root, "bin"), { recursive: true });
81
- writeFileSync(shimPath, getShimContent(ext));
82
- result.shim = shimPath;
83
- }
84
- function runSetup(root, metaDir, args) {
85
- const doAll = args.includes("--all");
86
- const doWorkflows = doAll || args.includes("--workflows");
87
- const doShim = doAll || args.includes("--shim");
88
- const noFlagsGiven = !doWorkflows && !doShim;
89
- const installWorkflows = doWorkflows || noFlagsGiven;
90
- const installShim = doShim || noFlagsGiven;
91
- const vars = detectVars(root);
92
- const result = {
93
- workflows: [],
94
- skipped: [],
95
- shim: null
96
- };
97
- const templatesDir = join(metaDir, "templates");
98
- if (installWorkflows) {
99
- const { copied, skipped } = copyTemplates(join(templatesDir, "workflows"), join(root, ".github", "workflows"), vars);
100
- result.workflows = copied;
101
- result.skipped.push(...skipped);
102
- }
103
- if (installShim) generateShim(root, result);
104
- for (const f of result.workflows) console.log(`✓ Copied workflow: ${f}`);
105
- for (const f of result.skipped) console.log(` Already exists: ${f}`);
106
- if (result.shim) {
107
- const shimRelative = result.shim.replace(root + "/", "./");
108
- console.log(`✓ Generated intent shim: ${result.shim}`);
109
- console.log(`\n Add to your package.json:`);
110
- console.log(` "bin": { "intent": "${shimRelative}" }`);
111
- console.log(`\n Add "bin" to your package.json "files" array.`);
112
- }
113
- if (result.workflows.length === 0 && result.shim === null && result.skipped.length === 0) console.log("No templates directory found. Is @tanstack/intent installed?");
114
- else if (result.workflows.length > 0) {
115
- console.log(`\nTemplate variables applied:`);
116
- console.log(` Package: ${vars.PACKAGE_NAME}`);
117
- console.log(` Repo: ${vars.REPO}`);
118
- console.log(` Docs: ${vars.DOCS_PATH}`);
119
- console.log(` Src: ${vars.SRC_PATH}`);
120
- }
121
- return result;
122
- }
123
-
124
- //#endregion
125
- export { runSetup as t };