@tanstack/intent 0.0.20 → 0.0.23

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/dist/cli.d.mts CHANGED
@@ -1,6 +1,5 @@
1
1
  #!/usr/bin/env node
2
2
  //#region src/cli.d.ts
3
- declare const USAGE = "TanStack Intent CLI\n\nUsage:\n intent list [--json] Discover intent-enabled packages\n intent meta [name] List meta-skills, or print one by name\n intent validate [<dir>] Validate skill files (default: skills/)\n intent install Print a skill that guides your coding agent to set up skill-to-task mappings\n intent scaffold Print maintainer scaffold prompt\n intent add-library-bin Generate bin/intent.{js,mjs} bridge file\n intent edit-package-json Wire package.json (files, bin) for skill publishing\n intent setup-github-actions Copy CI workflow templates to .github/workflows/\n intent stale [dir] [--json] Check skills for staleness";
4
3
  declare function main(argv?: Array<string>): Promise<number>;
5
4
  //#endregion
6
- export { USAGE, main };
5
+ export { main };
package/dist/cli.mjs CHANGED
@@ -1,35 +1,72 @@
1
1
  #!/usr/bin/env node
2
- import { t as INSTALL_PROMPT } from "./install-prompt-C0M-U3WZ.mjs";
2
+ import { n as runInstallCommand } from "./install-BHbA_wkb.mjs";
3
3
  import { existsSync, readFileSync, readdirSync, realpathSync } from "node:fs";
4
4
  import { dirname, join, relative, sep } from "node:path";
5
5
  import { fileURLToPath } from "node:url";
6
+ import { cac } from "cac";
6
7
 
7
- //#region src/cli.ts
8
- function getMetaDir() {
9
- return join(dirname(fileURLToPath(import.meta.url)), "..", "meta");
10
- }
8
+ //#region src/cli-error.ts
9
+ const CLI_FAILURE = Symbol("CliFailure");
11
10
  function fail(message, exitCode = 1) {
12
11
  throw {
12
+ [CLI_FAILURE]: true,
13
13
  message,
14
14
  exitCode
15
15
  };
16
16
  }
17
17
  function isCliFailure(value) {
18
- return !!value && typeof value === "object" && "message" in value && typeof value.message === "string" && "exitCode" in value && typeof value.exitCode === "number";
18
+ return !!value && typeof value === "object" && CLI_FAILURE in value;
19
+ }
20
+
21
+ //#endregion
22
+ //#region src/cli-support.ts
23
+ function printWarnings(warnings) {
24
+ if (warnings.length === 0) return;
25
+ console.log("Warnings:");
26
+ for (const warning of warnings) console.log(` ⚠ ${warning}`);
27
+ }
28
+ function getMetaDir() {
29
+ return join(dirname(fileURLToPath(import.meta.url)), "..", "meta");
19
30
  }
20
31
  async function scanIntentsOrFail() {
21
- const { scanForIntents } = await import("./scanner-BHPl60jH.mjs");
32
+ const { scanForIntents } = await import("./scanner-CsDGCRDm.mjs");
22
33
  try {
23
- return await scanForIntents();
34
+ return scanForIntents();
24
35
  } catch (err) {
25
- fail(err.message);
36
+ fail(err instanceof Error ? err.message : String(err));
26
37
  }
27
38
  }
28
- function printWarnings(warnings) {
29
- if (warnings.length === 0) return;
30
- console.log("Warnings:");
31
- for (const warning of warnings) console.log(` ⚠ ${warning}`);
39
+ function readPackageName(root) {
40
+ try {
41
+ const pkgJson = JSON.parse(readFileSync(join(root, "package.json"), "utf8"));
42
+ return typeof pkgJson.name === "string" ? pkgJson.name : relative(process.cwd(), root) || "unknown";
43
+ } catch {
44
+ return relative(process.cwd(), root) || "unknown";
45
+ }
46
+ }
47
+ async function resolveStaleTargets(targetDir) {
48
+ const resolvedRoot = targetDir ? join(process.cwd(), targetDir) : process.cwd();
49
+ const { checkStaleness } = await import("./staleness-Dr5-5wj5.mjs");
50
+ if (existsSync(join(resolvedRoot, "skills"))) return { reports: [await checkStaleness(resolvedRoot, readPackageName(resolvedRoot))] };
51
+ const { findPackagesWithSkills, findWorkspaceRoot } = await import("./setup.mjs");
52
+ const workspaceRoot = findWorkspaceRoot(resolvedRoot);
53
+ if (workspaceRoot) {
54
+ const packageDirs = findPackagesWithSkills(workspaceRoot);
55
+ if (packageDirs.length > 0) return { reports: await Promise.all(packageDirs.map((packageDir) => checkStaleness(packageDir, readPackageName(packageDir)))) };
56
+ }
57
+ const staleResult = await scanIntentsOrFail();
58
+ return { reports: await Promise.all(staleResult.packages.map((pkg) => checkStaleness(pkg.packageRoot, pkg.name))) };
32
59
  }
60
+
61
+ //#endregion
62
+ //#region src/commands/edit-package-json.ts
63
+ async function runEditPackageJsonCommand(root) {
64
+ const { runEditPackageJsonAll } = await import("./setup.mjs");
65
+ runEditPackageJsonAll(root);
66
+ }
67
+
68
+ //#endregion
69
+ //#region src/commands/list.ts
33
70
  function formatScanCoverage(result) {
34
71
  const coverage = [];
35
72
  if (result.nodeModules.local.scanned) coverage.push("project node_modules");
@@ -49,24 +86,10 @@ function printVersionConflicts(result) {
49
86
  console.log();
50
87
  }
51
88
  }
52
- function buildValidationFailure(errors, warnings) {
53
- const lines = [
54
- "",
55
- `❌ Validation failed with ${errors.length} error(s):`,
56
- ""
57
- ];
58
- for (const { file, message } of errors) lines.push(` ${file}: ${message}`);
59
- if (warnings.length > 0) {
60
- lines.push("", "⚠ Packaging warnings:");
61
- for (const warning of warnings) lines.push(` ${warning}`);
62
- }
63
- return lines.join("\n");
64
- }
65
- async function cmdList(args) {
89
+ async function runListCommand(options, scanIntentsOrFail$1) {
66
90
  const { computeSkillNameWidth, printSkillTree, printTable } = await import("./display-CuCDLPP_.mjs");
67
- const jsonOutput = args.includes("--json");
68
- const result = await scanIntentsOrFail();
69
- if (jsonOutput) {
91
+ const result = await scanIntentsOrFail$1();
92
+ if (options.json) {
70
93
  console.log(JSON.stringify(result, null, 2));
71
94
  return;
72
95
  }
@@ -80,7 +103,7 @@ async function cmdList(args) {
80
103
  }
81
104
  return;
82
105
  }
83
- const totalSkills = result.packages.reduce((sum, p) => sum + p.skills.length, 0);
106
+ const totalSkills = result.packages.reduce((sum, pkg) => sum + pkg.skills.length, 0);
84
107
  console.log(`\n${result.packages.length} intent-enabled packages, ${totalSkills} skills (${result.packageManager})\n`);
85
108
  if (scanCoverage) console.log(`Scanned: ${scanCoverage}${result.nodeModules.global.scanned ? " (local packages take precedence)" : ""}\n`);
86
109
  printTable([
@@ -95,8 +118,8 @@ async function cmdList(args) {
95
118
  pkg.intent.requires?.join(", ") || "–"
96
119
  ]));
97
120
  printVersionConflicts(result);
98
- const nameWidth = computeSkillNameWidth(result.packages.map((p) => p.skills));
99
- const showTypes = result.packages.some((p) => p.skills.some((s) => s.type));
121
+ const nameWidth = computeSkillNameWidth(result.packages.map((pkg) => pkg.skills));
122
+ const showTypes = result.packages.some((pkg) => pkg.skills.some((skill) => skill.type));
100
123
  console.log(`\nSkills:\n`);
101
124
  for (const pkg of result.packages) {
102
125
  console.log(` ${pkg.name}`);
@@ -106,18 +129,18 @@ async function cmdList(args) {
106
129
  });
107
130
  console.log();
108
131
  }
109
- console.log(`Feedback:`);
110
- console.log(` Submit feedback on skill usage to help maintainers improve the skills.`);
111
- console.log(` Load: node_modules/@tanstack/intent/meta/feedback-collection/SKILL.md`);
132
+ console.log("Feedback:");
133
+ console.log(" Submit feedback on skill usage to help maintainers improve the skills.");
134
+ console.log(" Load: node_modules/@tanstack/intent/meta/feedback-collection/SKILL.md");
112
135
  console.log();
113
136
  printWarnings(result.warnings);
114
137
  }
115
- async function cmdMeta(args) {
116
- const { parseFrontmatter } = await import("./utils-D7OKi0Rn.mjs");
117
- const metaDir = getMetaDir();
138
+
139
+ //#endregion
140
+ //#region src/commands/meta.ts
141
+ async function runMetaCommand(name, metaDir) {
118
142
  if (!existsSync(metaDir)) fail("Meta-skills directory not found.");
119
- if (args.length > 0) {
120
- const name = args[0];
143
+ if (name) {
121
144
  if (name.includes("..") || name.includes("/") || name.includes("\\")) fail(`Invalid meta-skill name: "${name}"`);
122
145
  const skillFile = join(metaDir, name, "SKILL.md");
123
146
  if (!existsSync(skillFile)) fail(`Meta-skill "${name}" not found. Run \`intent meta\` to list available meta-skills.`);
@@ -128,7 +151,8 @@ async function cmdMeta(args) {
128
151
  }
129
152
  return;
130
153
  }
131
- const entries = readdirSync(metaDir, { withFileTypes: true }).filter((e) => e.isDirectory()).filter((e) => existsSync(join(metaDir, e.name, "SKILL.md")));
154
+ const { parseFrontmatter } = await import("./utils-D7OKi0Rn.mjs");
155
+ const entries = readdirSync(metaDir, { withFileTypes: true }).filter((entry) => entry.isDirectory()).filter((entry) => existsSync(join(metaDir, entry.name, "SKILL.md")));
132
156
  if (entries.length === 0) {
133
157
  console.log("No meta-skills found.");
134
158
  return;
@@ -138,11 +162,145 @@ async function cmdMeta(args) {
138
162
  const fm = parseFrontmatter(join(metaDir, entry.name, "SKILL.md"));
139
163
  let description = "";
140
164
  if (typeof fm?.description === "string") description = fm.description.replace(/\s+/g, " ").trim();
141
- const shortDesc = description.length > 60 ? description.slice(0, 57) + "..." : description;
165
+ const shortDesc = description.length > 60 ? `${description.slice(0, 57)}...` : description;
142
166
  console.log(` ${entry.name.padEnd(28)} ${shortDesc}`);
143
167
  }
144
- console.log(`\nUsage: load the SKILL.md into your AI agent conversation.`);
145
- console.log(`Path: node_modules/@tanstack/intent/meta/<name>/SKILL.md`);
168
+ console.log("\nUsage: load the SKILL.md into your AI agent conversation.");
169
+ console.log("Path: node_modules/@tanstack/intent/meta/<name>/SKILL.md");
170
+ }
171
+
172
+ //#endregion
173
+ //#region src/commands/scaffold.ts
174
+ function runScaffoldCommand(metaDir) {
175
+ function metaSkillPath(name) {
176
+ return join(metaDir, name, "SKILL.md");
177
+ }
178
+ const prompt = `You are helping a library maintainer scaffold Intent skills.
179
+
180
+ Run the three meta skills below **one at a time, in order**. For each step:
181
+ 1. Load the SKILL.md file specified
182
+ 2. Follow its instructions completely
183
+ 3. Present outputs to the maintainer for review
184
+ 4. Do NOT proceed to the next step until the maintainer confirms
185
+
186
+ ## Before you start
187
+
188
+ Gather this context yourself (do not ask the maintainer — agents should never
189
+ ask for information they can discover):
190
+ 1. Read package.json for library name, repository URL, and homepage/docs URL
191
+ 2. Detect if this is a monorepo (look for workspaces field, packages/ directory, lerna.json)
192
+ 3. Use skills/ as the default skills root
193
+ 4. For monorepos:
194
+ - Domain map artifacts go at the REPO ROOT: _artifacts/
195
+ - Skills go INSIDE EACH PACKAGE: packages/<pkg>/skills/
196
+ - Identify which packages are client-facing (usually client SDKs and primary framework adapters)
197
+
198
+ ---
199
+
200
+ ## Step 1 — Domain Discovery
201
+
202
+ Load and follow: ${metaSkillPath("domain-discovery")}
203
+
204
+ This produces: domain_map.yaml and skill_spec.md in the artifacts directory.
205
+ Domain discovery covers the WHOLE library (one domain map even for monorepos).
206
+
207
+ **STOP. Review outputs with the maintainer before continuing.**
208
+
209
+ ---
210
+
211
+ ## Step 2 — Tree Generator
212
+
213
+ Load and follow: ${metaSkillPath("tree-generator")}
214
+
215
+ This produces: skill_tree.yaml in the artifacts directory.
216
+ For monorepos, each skill entry should include a \`package\` field.
217
+
218
+ **STOP. Review outputs with the maintainer before continuing.**
219
+
220
+ ---
221
+
222
+ ## Step 3 — Generate Skills
223
+
224
+ Load and follow: ${metaSkillPath("generate-skill")}
225
+
226
+ This produces: individual SKILL.md files.
227
+ - Single-repo: skills/<domain>/<skill>/SKILL.md
228
+ - Monorepo: packages/<pkg>/skills/<domain>/<skill>/SKILL.md
229
+
230
+ ---
231
+
232
+ ## After all skills are generated
233
+
234
+ 1. Run \`intent validate\` in each package directory
235
+ 2. Commit skills/ and artifacts
236
+ 3. For each publishable package, run: \`npx @tanstack/intent edit-package-json\`
237
+ 4. Ensure each package has \`@tanstack/intent\` as a devDependency
238
+ 5. Create a \`skill:<skill-name>\` label on the GitHub repo for each skill (use \`gh label create\`)
239
+ 6. Add a README note: "If you use an AI agent, run \`npx @tanstack/intent@latest install\`"
240
+ `;
241
+ console.log(prompt);
242
+ }
243
+
244
+ //#endregion
245
+ //#region src/commands/setup-github-actions.ts
246
+ async function runSetupGithubActionsCommand(root, metaDir) {
247
+ const { runSetupGithubActions } = await import("./setup.mjs");
248
+ runSetupGithubActions(root, metaDir);
249
+ }
250
+
251
+ //#endregion
252
+ //#region src/commands/stale.ts
253
+ async function runStaleCommand(targetDir, options, resolveStaleTargets$1) {
254
+ const { reports } = await resolveStaleTargets$1(targetDir);
255
+ if (reports.length === 0) {
256
+ console.log("No intent-enabled packages found.");
257
+ return;
258
+ }
259
+ if (options.json) {
260
+ console.log(JSON.stringify(reports, null, 2));
261
+ return;
262
+ }
263
+ for (const report of reports) {
264
+ const driftLabel = report.versionDrift ? ` [${report.versionDrift} drift]` : "";
265
+ const vLabel = report.skillVersion && report.currentVersion ? ` (${report.skillVersion} → ${report.currentVersion})` : "";
266
+ console.log(`${report.library}${vLabel}${driftLabel}`);
267
+ const stale = report.skills.filter((skill) => skill.needsReview);
268
+ if (stale.length === 0) console.log(" All skills up-to-date");
269
+ else for (const skill of stale) console.log(` ⚠ ${skill.name}: ${skill.reasons.join(", ")}`);
270
+ console.log();
271
+ }
272
+ }
273
+
274
+ //#endregion
275
+ //#region src/commands/validate.ts
276
+ function buildValidationFailure(errors, warnings) {
277
+ const lines = [
278
+ "",
279
+ `❌ Validation failed with ${errors.length} error(s):`,
280
+ ""
281
+ ];
282
+ for (const { file, message } of errors) lines.push(` ${file}: ${message}`);
283
+ if (warnings.length > 0) {
284
+ lines.push("", "⚠ Packaging warnings:");
285
+ for (const warning of warnings) lines.push(` ${warning}`);
286
+ }
287
+ return lines.join("\n");
288
+ }
289
+ function isInsideMonorepo(root) {
290
+ let dir = join(root, "..");
291
+ for (let i = 0; i < 5; i++) {
292
+ const parentPkg = join(dir, "package.json");
293
+ if (existsSync(parentPkg)) try {
294
+ const parent = JSON.parse(readFileSync(parentPkg, "utf8"));
295
+ return Array.isArray(parent.workspaces) || parent.workspaces?.packages;
296
+ } catch {
297
+ return false;
298
+ }
299
+ const next = dirname(dir);
300
+ if (next === dir) break;
301
+ dir = next;
302
+ }
303
+ return false;
146
304
  }
147
305
  function collectPackagingWarnings(root) {
148
306
  const pkgJsonPath = join(root, "package.json");
@@ -155,15 +313,12 @@ function collectPackagingWarnings(root) {
155
313
  }
156
314
  const warnings = [];
157
315
  if (!pkgJson.devDependencies?.["@tanstack/intent"]) warnings.push("@tanstack/intent is not in devDependencies");
158
- if (!pkgJson.bin?.intent) warnings.push("Missing \"bin\": { \"intent\": ... } entry in package.json");
159
- const shimJs = join(root, "bin", "intent.js");
160
- const shimMjs = join(root, "bin", "intent.mjs");
161
- if (!existsSync(shimJs) && !existsSync(shimMjs)) warnings.push("No bin/intent.js or bin/intent.mjs shim found (run: npx @tanstack/intent add-library-bin)");
316
+ const keywords = pkgJson.keywords;
317
+ if (!Array.isArray(keywords) || !keywords.includes("tanstack-intent")) warnings.push("Missing \"tanstack-intent\" in keywords array");
162
318
  const files = pkgJson.files;
163
319
  if (Array.isArray(files)) {
164
320
  if (!files.includes("skills")) warnings.push("\"skills\" is not in the \"files\" array — skills won't be published");
165
- if (!files.includes("bin")) warnings.push("\"bin\" is not in the \"files\" array — shim won't be published");
166
- if (!files.includes("!skills/_artifacts")) warnings.push("\"!skills/_artifacts\" is not in the \"files\" array — artifacts will be published unnecessarily");
321
+ if (!isInsideMonorepo(root) && !files.includes("!skills/_artifacts")) warnings.push("\"!skills/_artifacts\" is not in the \"files\" array — artifacts will be published unnecessarily");
167
322
  }
168
323
  return warnings;
169
324
  }
@@ -176,30 +331,9 @@ function resolvePackageRoot(startDir) {
176
331
  dir = next;
177
332
  }
178
333
  }
179
- function readPackageName(root) {
180
- try {
181
- const pkgJson = JSON.parse(readFileSync(join(root, "package.json"), "utf8"));
182
- return typeof pkgJson.name === "string" ? pkgJson.name : relative(process.cwd(), root) || "unknown";
183
- } catch {
184
- return relative(process.cwd(), root) || "unknown";
185
- }
186
- }
187
- async function resolveStaleTargets(targetDir) {
188
- const resolvedRoot = targetDir ? join(process.cwd(), targetDir) : process.cwd();
189
- const { checkStaleness } = await import("./staleness-Dr5-5wj5.mjs");
190
- if (existsSync(join(resolvedRoot, "skills"))) return { reports: [await checkStaleness(resolvedRoot, readPackageName(resolvedRoot))] };
191
- const { findPackagesWithSkills, findWorkspaceRoot } = await import("./setup.mjs");
192
- const workspaceRoot = findWorkspaceRoot(resolvedRoot);
193
- if (workspaceRoot) {
194
- const packageDirs = findPackagesWithSkills(workspaceRoot);
195
- if (packageDirs.length > 0) return { reports: await Promise.all(packageDirs.map((packageDir) => checkStaleness(packageDir, readPackageName(packageDir)))) };
196
- }
197
- const staleResult = await scanIntentsOrFail();
198
- return { reports: await Promise.all(staleResult.packages.map((pkg) => checkStaleness(pkg.packageRoot, pkg.name))) };
199
- }
200
- async function cmdValidate(args) {
334
+ async function runValidateCommand(dir) {
201
335
  const [{ parse: parseYaml }, { findSkillFiles }] = await Promise.all([import("yaml"), import("./utils-D7OKi0Rn.mjs")]);
202
- const targetDir = args[0] ?? "skills";
336
+ const targetDir = dir ?? "skills";
203
337
  const skillsDir = join(process.cwd(), targetDir);
204
338
  const packageRoot = resolvePackageRoot(skillsDir);
205
339
  if (!existsSync(skillsDir)) fail(`Skills directory not found: ${skillsDir}`);
@@ -227,10 +361,11 @@ async function cmdValidate(args) {
227
361
  let fm;
228
362
  try {
229
363
  fm = parseYaml(match[1]);
230
- } catch {
364
+ } catch (err) {
365
+ const detail = err instanceof Error ? err.message : String(err);
231
366
  errors.push({
232
367
  file: rel,
233
- message: "Invalid YAML frontmatter"
368
+ message: `Invalid YAML frontmatter: ${detail}`
234
369
  });
235
370
  continue;
236
371
  }
@@ -287,10 +422,11 @@ async function cmdValidate(args) {
287
422
  }
288
423
  if (fileName.endsWith(".yaml")) try {
289
424
  parseYaml(content);
290
- } catch {
425
+ } catch (err) {
426
+ const detail = err instanceof Error ? err.message : String(err);
291
427
  errors.push({
292
428
  file: relative(process.cwd(), artifactPath),
293
- message: "Invalid YAML in artifact file"
429
+ message: `Invalid YAML in artifact file: ${detail}`
294
430
  });
295
431
  }
296
432
  }
@@ -300,221 +436,76 @@ async function cmdValidate(args) {
300
436
  if (warnings.length > 0) console.log();
301
437
  printWarnings(warnings);
302
438
  }
303
- function cmdScaffold() {
304
- const metaDir = getMetaDir();
305
- const metaSkillPath = (name) => join(metaDir, name, "SKILL.md");
306
- const prompt = `You are helping a library maintainer scaffold Intent skills.
307
-
308
- Run the three meta skills below **one at a time, in order**. For each step:
309
- 1. Load the SKILL.md file specified
310
- 2. Follow its instructions completely
311
- 3. Present outputs to the maintainer for review
312
- 4. Do NOT proceed to the next step until the maintainer confirms
313
-
314
- ## Before you start
315
-
316
- Gather this context yourself (do not ask the maintainer — agents should never
317
- ask for information they can discover):
318
- 1. Read package.json for library name, repository URL, and homepage/docs URL
319
- 2. Detect if this is a monorepo (look for workspaces field, packages/ directory, lerna.json)
320
- 3. Use skills/ as the default skills root
321
- 4. For monorepos:
322
- - Domain map artifacts go at the REPO ROOT: _artifacts/
323
- - Skills go INSIDE EACH PACKAGE: packages/<pkg>/skills/
324
- - Identify which packages are client-facing (usually client SDKs and primary framework adapters)
325
-
326
- ---
327
-
328
- ## Step 1 — Domain Discovery
329
-
330
- Load and follow: ${metaSkillPath("domain-discovery")}
331
-
332
- This produces: domain_map.yaml and skill_spec.md in the artifacts directory.
333
- Domain discovery covers the WHOLE library (one domain map even for monorepos).
334
-
335
- **STOP. Review outputs with the maintainer before continuing.**
336
-
337
- ---
338
-
339
- ## Step 2 — Tree Generator
340
-
341
- Load and follow: ${metaSkillPath("tree-generator")}
342
-
343
- This produces: skill_tree.yaml in the artifacts directory.
344
- For monorepos, each skill entry should include a \`package\` field.
345
-
346
- **STOP. Review outputs with the maintainer before continuing.**
347
-
348
- ---
349
-
350
- ## Step 3 — Generate Skills
351
-
352
- Load and follow: ${metaSkillPath("generate-skill")}
353
-
354
- This produces: individual SKILL.md files.
355
- - Single-repo: skills/<domain>/<skill>/SKILL.md
356
- - Monorepo: packages/<pkg>/skills/<domain>/<skill>/SKILL.md
357
-
358
- ---
359
-
360
- ## After all skills are generated
361
-
362
- 1. Run \`intent validate\` in each package directory
363
- 2. Commit skills/ and artifacts
364
- 3. For each publishable package, run: \`npx @tanstack/intent add-library-bin\`
365
- 4. For each publishable package, run: \`npx @tanstack/intent edit-package-json\`
366
- 5. Ensure each package has \`@tanstack/intent\` as a devDependency
367
- 6. Create a \`skill:<skill-name>\` label on the GitHub repo for each skill (use \`gh label create\`)
368
- 7. Add a README note: "If you use an AI agent, run \`npx @tanstack/intent@latest install\`"
369
- `;
370
- console.log(prompt);
371
- }
372
- const USAGE = `TanStack Intent CLI
373
-
374
- Usage:
375
- intent list [--json] Discover intent-enabled packages
376
- intent meta [name] List meta-skills, or print one by name
377
- intent validate [<dir>] Validate skill files (default: skills/)
378
- intent install Print a skill that guides your coding agent to set up skill-to-task mappings
379
- intent scaffold Print maintainer scaffold prompt
380
- intent add-library-bin Generate bin/intent.{js,mjs} bridge file
381
- intent edit-package-json Wire package.json (files, bin) for skill publishing
382
- intent setup-github-actions Copy CI workflow templates to .github/workflows/
383
- intent stale [dir] [--json] Check skills for staleness`;
384
- const HELP_BY_COMMAND = {
385
- list: `${USAGE}
386
-
387
- Examples:
388
- intent list
389
- intent list --json`,
390
- meta: `intent meta [name]
391
-
392
- List shipped meta-skills, or print a single meta-skill by name.
393
-
394
- Examples:
395
- intent meta
396
- intent meta domain-discovery`,
397
- validate: `intent validate [dir]
398
-
399
- Validate SKILL.md files in the target directory.
400
-
401
- Examples:
402
- intent validate
403
- intent validate packages/query/skills`,
404
- install: `intent install
405
-
406
- Print the install prompt used to set up skill-to-task mappings.`,
407
- scaffold: `intent scaffold
408
-
409
- Print the guided maintainer prompt for generating skills.`,
410
- stale: `intent stale [dir] [--json]
411
-
412
- Check installed skills for version and source drift.
413
439
 
414
- Examples:
415
- intent stale
416
- intent stale packages/query
417
- intent stale --json`,
418
- "add-library-bin": `intent add-library-bin
419
-
420
- Generate bin/intent.{js,mjs} bridge files for publishable packages.`,
421
- "edit-package-json": `intent edit-package-json
422
-
423
- Update package.json files so skills and shims are published.`,
424
- "setup-github-actions": `intent setup-github-actions
425
-
426
- Copy Intent CI workflow templates into .github/workflows/.`
427
- };
428
- function isHelpFlag(arg) {
429
- return arg === "-h" || arg === "--help";
430
- }
431
- function printHelp(command) {
432
- if (!command) {
433
- console.log(`${USAGE}
434
-
435
- Run \`intent help <command>\` for details on a specific command.`);
436
- return;
437
- }
438
- console.log(HELP_BY_COMMAND[command] ?? USAGE);
440
+ //#endregion
441
+ //#region src/cli.ts
442
+ function createCli() {
443
+ const cli = cac("intent");
444
+ cli.usage("<command> [options]");
445
+ cli.command("list", "Discover intent-enabled packages").usage("list [--json]").option("--json", "Output JSON").example("list").example("list --json").action(async (options) => {
446
+ await runListCommand(options, scanIntentsOrFail);
447
+ });
448
+ cli.command("meta [name]", "List meta-skills, or print one by name").usage("meta [name]").example("meta").example("meta domain-discovery").action(async (name) => {
449
+ await runMetaCommand(name, getMetaDir());
450
+ });
451
+ cli.command("validate [dir]", "Validate skill files").usage("validate [dir]").example("validate").example("validate packages/query/skills").action(async (dir) => {
452
+ await runValidateCommand(dir);
453
+ });
454
+ cli.command("install", "Print a skill that guides your coding agent to set up skill-to-task mappings").usage("install").action(() => {
455
+ runInstallCommand();
456
+ });
457
+ cli.command("scaffold", "Print maintainer scaffold prompt").usage("scaffold").action(() => {
458
+ runScaffoldCommand(getMetaDir());
459
+ });
460
+ cli.command("stale [dir]", "Check skills for staleness").usage("stale [dir] [--json]").option("--json", "Output JSON").example("stale").example("stale packages/query").example("stale --json").action(async (targetDir, options) => {
461
+ await runStaleCommand(targetDir, options, resolveStaleTargets);
462
+ });
463
+ cli.command("edit-package-json", "Update package.json files so skills are published").usage("edit-package-json").action(async () => {
464
+ await runEditPackageJsonCommand(process.cwd());
465
+ });
466
+ cli.command("setup-github-actions", "Copy Intent CI workflow templates into .github/workflows/").usage("setup-github-actions").action(async () => {
467
+ await runSetupGithubActionsCommand(process.cwd(), getMetaDir());
468
+ });
469
+ cli.command("help [command]", "Display help for a command").action((commandName) => {
470
+ if (!commandName) {
471
+ cli.outputHelp();
472
+ return;
473
+ }
474
+ const command = cli.commands.find((candidate) => candidate.isMatched(commandName));
475
+ if (!command) fail(`Unknown command: ${commandName}`);
476
+ command.outputHelp();
477
+ });
478
+ cli.help();
479
+ return cli;
439
480
  }
440
481
  async function main(argv = process.argv.slice(2)) {
441
- const command = argv[0];
442
- const commandArgs = argv.slice(1);
443
482
  try {
444
- if (!command || isHelpFlag(command)) {
445
- printHelp();
446
- return 0;
447
- }
448
- if (command === "help") {
449
- printHelp(commandArgs[0]);
483
+ const cli = createCli();
484
+ if (argv.length === 0) {
485
+ cli.outputHelp();
450
486
  return 0;
451
487
  }
452
- if (isHelpFlag(commandArgs[0])) {
453
- printHelp(command);
454
- return 0;
455
- }
456
- switch (command) {
457
- case "list":
458
- await cmdList(commandArgs);
459
- return 0;
460
- case "meta":
461
- await cmdMeta(commandArgs);
462
- return 0;
463
- case "validate":
464
- await cmdValidate(commandArgs);
465
- return 0;
466
- case "install":
467
- console.log(INSTALL_PROMPT);
468
- return 0;
469
- case "scaffold":
470
- cmdScaffold();
471
- return 0;
472
- case "stale": {
473
- const jsonStale = commandArgs.includes("--json");
474
- const { reports } = await resolveStaleTargets(commandArgs.find((arg) => !arg.startsWith("-")));
475
- if (reports.length === 0) {
476
- console.log("No intent-enabled packages found.");
477
- return 0;
478
- }
479
- if (jsonStale) {
480
- console.log(JSON.stringify(reports, null, 2));
481
- return 0;
482
- }
483
- for (const report of reports) {
484
- const driftLabel = report.versionDrift ? ` [${report.versionDrift} drift]` : "";
485
- const vLabel = report.skillVersion && report.currentVersion ? ` (${report.skillVersion} → ${report.currentVersion})` : "";
486
- console.log(`${report.library}${vLabel}${driftLabel}`);
487
- const stale = report.skills.filter((s) => s.needsReview);
488
- if (stale.length === 0) console.log(" All skills up-to-date");
489
- else for (const skill of stale) console.log(` ⚠ ${skill.name}: ${skill.reasons.join(", ")}`);
490
- console.log();
491
- }
492
- return 0;
493
- }
494
- case "add-library-bin": {
495
- const { runAddLibraryBinAll } = await import("./setup.mjs");
496
- runAddLibraryBinAll(process.cwd());
497
- return 0;
498
- }
499
- case "edit-package-json": {
500
- const { runEditPackageJsonAll } = await import("./setup.mjs");
501
- runEditPackageJsonAll(process.cwd());
502
- return 0;
503
- }
504
- case "setup-github-actions": {
505
- const { runSetupGithubActions } = await import("./setup.mjs");
506
- runSetupGithubActions(process.cwd(), getMetaDir());
507
- return 0;
508
- }
509
- default:
510
- printHelp();
511
- return command ? 1 : 0;
488
+ cli.parse([
489
+ "intent",
490
+ "intent",
491
+ ...argv
492
+ ], { run: false });
493
+ if (cli.options.help) return 0;
494
+ if (!cli.matchedCommand) {
495
+ cli.outputHelp();
496
+ return 1;
512
497
  }
498
+ await cli.runMatchedCommand();
499
+ return 0;
513
500
  } catch (err) {
514
501
  if (isCliFailure(err)) {
515
502
  console.error(err.message);
516
503
  return err.exitCode;
517
504
  }
505
+ if (err instanceof Error) {
506
+ console.error(err.message);
507
+ return 1;
508
+ }
518
509
  throw err;
519
510
  }
520
511
  }
@@ -528,4 +519,4 @@ if (isMain) {
528
519
  }
529
520
 
530
521
  //#endregion
531
- export { USAGE, main };
522
+ export { main };
package/dist/index.d.mts CHANGED
@@ -1,8 +1,8 @@
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-ddLtccfV.mjs";
2
- import { d as runEditPackageJson, i as SetupGithubActionsResult, l as runAddLibraryBin, n as EditPackageJsonResult, p as runSetupGithubActions, t as AddLibraryBinResult } from "./setup-B-zdCBu4.mjs";
2
+ import { c as runEditPackageJson, r as SetupGithubActionsResult, t as EditPackageJsonResult, u as runSetupGithubActions } from "./setup-BNBVotfR.mjs";
3
3
 
4
4
  //#region src/scanner.d.ts
5
- declare function scanForIntents(root?: string): Promise<ScanResult>;
5
+ declare function scanForIntents(root?: string): ScanResult;
6
6
  //#endregion
7
7
  //#region src/staleness.d.ts
8
8
  declare function checkStaleness(packageDir: string, packageName?: string): Promise<StalenessReport>;
@@ -55,4 +55,4 @@ declare function resolveDepDir(depName: string, parentDir: string): string | nul
55
55
  */
56
56
  declare function parseFrontmatter(filePath: string): Record<string, unknown> | null;
57
57
  //#endregion
58
- 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, getDeps, hasGhCli, metaToMarkdown, parseFrontmatter, resolveDepDir, resolveFrequency, runAddLibraryBin, runEditPackageJson, runSetupGithubActions, scanForIntents, submitFeedback, submitMetaFeedback, toMarkdown, validateMetaPayload, validatePayload };
58
+ export { 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, getDeps, hasGhCli, metaToMarkdown, parseFrontmatter, resolveDepDir, resolveFrequency, runEditPackageJson, runSetupGithubActions, scanForIntents, submitFeedback, submitMetaFeedback, toMarkdown, validateMetaPayload, validatePayload };
package/dist/index.mjs CHANGED
@@ -1,6 +1,6 @@
1
1
  import { a as parseFrontmatter, n as findSkillFiles, o as resolveDepDir, r as getDeps } from "./utils-BfjM1mQe.mjs";
2
- import { a as runAddLibraryBin, l as runSetupGithubActions, s as runEditPackageJson } from "./setup-mGV2dZrq.mjs";
3
- import { t as scanForIntents } from "./scanner-DVepyEwz.mjs";
2
+ import { a as runEditPackageJson, s as runSetupGithubActions } from "./setup-Nyfl1KTS.mjs";
3
+ import { t as scanForIntents } from "./scanner-BCgNt-oI.mjs";
4
4
  import { t as checkStaleness } from "./staleness-DZKvsLVq.mjs";
5
5
  import { readFileSync, writeFileSync } from "node:fs";
6
6
  import { join } from "node:path";
@@ -269,4 +269,4 @@ function submitMetaFeedback(payload, opts) {
269
269
  }
270
270
 
271
271
  //#endregion
272
- export { checkStaleness, containsSecrets, findSkillFiles, getDeps, hasGhCli, metaToMarkdown, parseFrontmatter, resolveDepDir, resolveFrequency, runAddLibraryBin, runEditPackageJson, runSetupGithubActions, scanForIntents, submitFeedback, submitMetaFeedback, toMarkdown, validateMetaPayload, validatePayload };
272
+ export { checkStaleness, containsSecrets, findSkillFiles, getDeps, hasGhCli, metaToMarkdown, parseFrontmatter, resolveDepDir, resolveFrequency, runEditPackageJson, runSetupGithubActions, scanForIntents, submitFeedback, submitMetaFeedback, toMarkdown, validateMetaPayload, validatePayload };
@@ -1,4 +1,4 @@
1
- //#region src/install-prompt.ts
1
+ //#region src/commands/install.ts
2
2
  const INSTALL_PROMPT = `You are an AI assistant helping a developer set up skill-to-task mappings for their project.
3
3
 
4
4
  Follow these steps in order:
@@ -54,6 +54,9 @@ skills:
54
54
  - Keep entries concise - this block is read on every agent task
55
55
  - Preserve all content outside the block tags unchanged
56
56
  - If the user is on Deno, note that this setup is best-effort today and relies on npm interop`;
57
+ function runInstallCommand() {
58
+ console.log(INSTALL_PROMPT);
59
+ }
57
60
 
58
61
  //#endregion
59
- export { INSTALL_PROMPT as t };
62
+ export { runInstallCommand as n, INSTALL_PROMPT as t };
@@ -1,14 +1,14 @@
1
1
  #!/usr/bin/env node
2
2
  import "./utils-BfjM1mQe.mjs";
3
- import { t as INSTALL_PROMPT } from "./install-prompt-C0M-U3WZ.mjs";
3
+ import { t as INSTALL_PROMPT } from "./install-BHbA_wkb.mjs";
4
4
  import { n as printSkillTree, r as printTable, t as computeSkillNameWidth } from "./display-DhsUxNJW.mjs";
5
- import { t as scanLibrary } from "./library-scanner-DBOEhfm8.mjs";
5
+ import { t as scanLibrary } from "./library-scanner-DlWy8VeZ.mjs";
6
6
 
7
7
  //#region src/intent-library.ts
8
- async function cmdList() {
8
+ function cmdList() {
9
9
  let result;
10
10
  try {
11
- result = await scanLibrary(process.argv[1]);
11
+ result = scanLibrary(process.argv[1]);
12
12
  } catch (err) {
13
13
  console.error(err.message);
14
14
  process.exit(1);
@@ -65,7 +65,7 @@ const command = process.argv[2];
65
65
  switch (command) {
66
66
  case "list":
67
67
  case void 0:
68
- await cmdList();
68
+ cmdList();
69
69
  break;
70
70
  case "install":
71
71
  cmdInstall();
@@ -19,10 +19,12 @@ function findHomeDir(scriptPath) {
19
19
  dir = parent;
20
20
  }
21
21
  }
22
- function hasIntentBin(pkg) {
22
+ function isIntentPackage(pkg) {
23
+ const keywords = pkg.keywords;
24
+ if (Array.isArray(keywords) && keywords.includes("tanstack-intent")) return true;
23
25
  const bin = pkg.bin;
24
- if (!bin || typeof bin !== "object") return false;
25
- return "intent" in bin;
26
+ if (bin && typeof bin === "object" && "intent" in bin) return true;
27
+ return false;
26
28
  }
27
29
  function discoverSkills(skillsDir) {
28
30
  const skills = [];
@@ -57,7 +59,7 @@ function discoverSkills(skillsDir) {
57
59
  walk(skillsDir);
58
60
  return skills;
59
61
  }
60
- async function scanLibrary(scriptPath, _projectRoot) {
62
+ function scanLibrary(scriptPath, _projectRoot) {
61
63
  const packages = [];
62
64
  const warnings = [];
63
65
  const visited = /* @__PURE__ */ new Set();
@@ -91,7 +93,7 @@ async function scanLibrary(scriptPath, _projectRoot) {
91
93
  const depDir = resolveDepDir(depName, dir);
92
94
  if (!depDir) continue;
93
95
  const depPkg = readPkgJson(depDir);
94
- if (depPkg && hasIntentBin(depPkg)) processPackage(depName, depDir);
96
+ if (depPkg && isIntentPackage(depPkg)) processPackage(depName, depDir);
95
97
  }
96
98
  }
97
99
  processPackage(homeName, homeDir);
@@ -11,6 +11,6 @@ interface LibraryScanResult {
11
11
  packages: Array<LibraryPackage>;
12
12
  warnings: Array<string>;
13
13
  }
14
- declare function scanLibrary(scriptPath: string, _projectRoot?: string): Promise<LibraryScanResult>;
14
+ declare function scanLibrary(scriptPath: string, _projectRoot?: string): LibraryScanResult;
15
15
  //#endregion
16
16
  export { LibraryPackage, LibraryScanResult, scanLibrary };
@@ -1,4 +1,4 @@
1
1
  import "./utils-BfjM1mQe.mjs";
2
- import { t as scanLibrary } from "./library-scanner-DBOEhfm8.mjs";
2
+ import { t as scanLibrary } from "./library-scanner-DlWy8VeZ.mjs";
3
3
 
4
4
  export { scanLibrary };
@@ -1,5 +1,5 @@
1
1
  import { a as parseFrontmatter, i as listNodeModulesPackageDirs, o as resolveDepDir, r as getDeps, t as detectGlobalNodeModules } from "./utils-BfjM1mQe.mjs";
2
- import { i as resolveWorkspacePackages, n as findWorkspaceRoot, r as readWorkspacePatterns } from "./setup-mGV2dZrq.mjs";
2
+ import { i as resolveWorkspacePackages, n as findWorkspaceRoot, r as readWorkspacePatterns } from "./setup-Nyfl1KTS.mjs";
3
3
  import { existsSync, readFileSync, readdirSync } from "node:fs";
4
4
  import { join, relative, sep } from "node:path";
5
5
 
@@ -169,7 +169,7 @@ function toVersionConflict(packageName, variants, chosen) {
169
169
  variants
170
170
  };
171
171
  }
172
- async function scanForIntents(root) {
172
+ function scanForIntents(root) {
173
173
  const projectRoot = root ?? process.cwd();
174
174
  const packageManager = detectPackageManager(projectRoot);
175
175
  const nodeModulesDir = join(projectRoot, "node_modules");
@@ -0,0 +1,5 @@
1
+ import "./utils-BfjM1mQe.mjs";
2
+ import "./setup-Nyfl1KTS.mjs";
3
+ import { t as scanForIntents } from "./scanner-BCgNt-oI.mjs";
4
+
5
+ export { scanForIntents };
@@ -1,8 +1,4 @@
1
1
  //#region src/setup.d.ts
2
- interface AddLibraryBinResult {
3
- shim: string | null;
4
- skipped: string | null;
5
- }
6
2
  interface EditPackageJsonResult {
7
3
  added: Array<string>;
8
4
  alreadyPresent: Array<string>;
@@ -15,7 +11,6 @@ interface MonorepoResult<T> {
15
11
  package: string;
16
12
  result: T;
17
13
  }
18
- declare function runAddLibraryBin(root: string): AddLibraryBinResult;
19
14
  declare function runEditPackageJson(root: string): EditPackageJsonResult;
20
15
  declare function readWorkspacePatterns(root: string): Array<string> | null;
21
16
  /**
@@ -30,7 +25,6 @@ declare function findWorkspaceRoot(start: string): string | null;
30
25
  */
31
26
  declare function findPackagesWithSkills(root: string): Array<string>;
32
27
  declare function runEditPackageJsonAll(root: string): Array<MonorepoResult<EditPackageJsonResult>> | EditPackageJsonResult;
33
- declare function runAddLibraryBinAll(root: string): Array<MonorepoResult<AddLibraryBinResult>> | AddLibraryBinResult;
34
28
  declare function runSetupGithubActions(root: string, metaDir: string): SetupGithubActionsResult;
35
29
  //#endregion
36
- export { findPackagesWithSkills as a, resolveWorkspacePackages as c, runEditPackageJson as d, runEditPackageJsonAll as f, SetupGithubActionsResult as i, runAddLibraryBin as l, EditPackageJsonResult as n, findWorkspaceRoot as o, runSetupGithubActions as p, MonorepoResult as r, readWorkspacePatterns as s, AddLibraryBinResult as t, runAddLibraryBinAll as u };
30
+ export { findWorkspaceRoot as a, runEditPackageJson as c, findPackagesWithSkills as i, runEditPackageJsonAll as l, MonorepoResult as n, readWorkspacePatterns as o, SetupGithubActionsResult as r, resolveWorkspacePackages as s, EditPackageJsonResult as t, runSetupGithubActions as u };
@@ -4,6 +4,19 @@ import { basename, join, relative } from "node:path";
4
4
  import { parse } from "yaml";
5
5
 
6
6
  //#region src/setup.ts
7
+ function isGenericWorkspaceName(name, root) {
8
+ const normalized = name.trim().toLowerCase();
9
+ return normalized.length === 0 || normalized === "unknown" || normalized === "root" || normalized === "workspace" || normalized === "monorepo" || normalized === basename(root).toLowerCase();
10
+ }
11
+ function deriveWorkspacePackageName(root, repo, packageDirs) {
12
+ const repoName = repo.split("/").filter(Boolean).pop() || basename(root);
13
+ for (const packageDir of packageDirs) {
14
+ const pkgJson = readPackageJson(packageDir);
15
+ const pkgName = typeof pkgJson.name === "string" ? pkgJson.name : null;
16
+ if (pkgName?.startsWith("@")) return `${pkgName.split("/")[0]}/${repoName}`;
17
+ }
18
+ return repoName;
19
+ }
7
20
  function readPackageJson(root) {
8
21
  const pkgPath = join(root, "package.json");
9
22
  try {
@@ -41,19 +54,22 @@ function buildWatchPaths(root, packageDirs) {
41
54
  }
42
55
  function detectVars(root, packageDirs) {
43
56
  const pkgJson = readPackageJson(root);
44
- const name = typeof pkgJson.name === "string" ? pkgJson.name : "unknown";
57
+ const rawName = typeof pkgJson.name === "string" ? pkgJson.name : "unknown";
45
58
  const docs = typeof pkgJson.intent?.docs === "string" ? pkgJson.intent.docs : "docs/";
46
- const repo = detectRepo(pkgJson, name.replace(/^@/, "").replace(/\//, "/"));
47
59
  const isMonorepo = packageDirs !== void 0;
48
- const packageLabel = isMonorepo && name === "unknown" ? `${basename(root)} workspace` : name;
49
- let srcPath = `packages/${name.replace(/^@[^/]+\//, "")}/src/**`;
50
- if (existsSync(join(root, "src"))) srcPath = "src/**";
60
+ const repo = detectRepo(pkgJson, detectRepo((packageDirs?.[0] ? readPackageJson(packageDirs[0]) : null) ?? {}, basename(root)));
61
+ let packageName = rawName;
62
+ if (isMonorepo && isGenericWorkspaceName(rawName, root)) packageName = deriveWorkspacePackageName(root, repo, packageDirs);
63
+ const shortName = packageName.replace(/^@[^/]+\//, "");
64
+ let srcPath = isMonorepo ? "packages/*/src/**" : `packages/${shortName}/src/**`;
65
+ if (!isMonorepo && existsSync(join(root, "src"))) srcPath = "src/**";
66
+ const docsPath = isMonorepo ? "packages/*/docs/**" : docs;
51
67
  return {
52
- PACKAGE_NAME: name,
53
- PACKAGE_LABEL: packageLabel,
54
- PAYLOAD_PACKAGE: packageLabel,
68
+ PACKAGE_NAME: packageName,
69
+ PACKAGE_LABEL: packageName,
70
+ PAYLOAD_PACKAGE: packageName,
55
71
  REPO: repo,
56
- DOCS_PATH: docs.endsWith("**") ? docs : docs.replace(/\/$/, "") + "/**",
72
+ DOCS_PATH: docsPath.endsWith("**") ? docsPath : docsPath.replace(/\/$/, "") + "/**",
57
73
  SRC_PATH: srcPath,
58
74
  WATCH_PATHS: isMonorepo ? buildWatchPaths(root, packageDirs) : ` - '${docs.endsWith("**") ? docs : docs.replace(/\/$/, "") + "/**"}'\n - '${srcPath}'`
59
75
  };
@@ -86,64 +102,6 @@ function copyTemplates(srcDir, destDir, vars) {
86
102
  skipped
87
103
  };
88
104
  }
89
- function getShimContent(ext) {
90
- return `#!/usr/bin/env node
91
- // Auto-generated by @tanstack/intent setup
92
- // Exposes the intent end-user CLI for consumers of this library.
93
- // Commit this file, then add to your package.json:
94
- // "bin": { "intent": "./bin/intent.${ext}" }
95
- try {
96
- await import('@tanstack/intent/intent-library')
97
- } catch (e) {
98
- if (e?.code === 'ERR_MODULE_NOT_FOUND' || e?.code === 'MODULE_NOT_FOUND') {
99
- console.error('@tanstack/intent is not installed.')
100
- console.error('')
101
- console.error('Install it as a dev dependency:')
102
- console.error(' npm add -D @tanstack/intent')
103
- console.error('')
104
- console.error('Or run directly:')
105
- console.error(' npx @tanstack/intent@latest list')
106
- process.exit(1)
107
- }
108
- throw e
109
- }
110
- `;
111
- }
112
- function detectShimExtension(root) {
113
- try {
114
- if (JSON.parse(readFileSync(join(root, "package.json"), "utf8")).type === "module") return "js";
115
- } catch (err) {
116
- 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}`);
117
- }
118
- return "mjs";
119
- }
120
- function findExistingShim(root) {
121
- const shimJs = join(root, "bin", "intent.js");
122
- if (existsSync(shimJs)) return shimJs;
123
- const shimMjs = join(root, "bin", "intent.mjs");
124
- if (existsSync(shimMjs)) return shimMjs;
125
- return null;
126
- }
127
- function runAddLibraryBin(root) {
128
- const result = {
129
- shim: null,
130
- skipped: null
131
- };
132
- const existingShim = findExistingShim(root);
133
- if (existingShim) {
134
- result.skipped = existingShim;
135
- console.log(` Already exists: ${existingShim}`);
136
- return result;
137
- }
138
- const ext = detectShimExtension(root);
139
- const shimPath = join(root, "bin", `intent.${ext}`);
140
- mkdirSync(join(root, "bin"), { recursive: true });
141
- writeFileSync(shimPath, getShimContent(ext));
142
- result.shim = shimPath;
143
- console.log(`✓ Generated intent shim: ${shimPath}`);
144
- console.log(`\n Run \`npx @tanstack/intent edit-package-json\` to wire package.json.`);
145
- return result;
146
- }
147
105
  function runEditPackageJson(root) {
148
106
  const result = {
149
107
  added: [],
@@ -168,10 +126,10 @@ function runEditPackageJson(root) {
168
126
  const indentSize = indentMatch?.[1] ? indentMatch[1].length : 2;
169
127
  if (!Array.isArray(pkg.keywords)) pkg.keywords = [];
170
128
  const keywords = pkg.keywords;
171
- for (const kw of ["tanstack-intent"]) if (keywords.includes(kw)) result.alreadyPresent.push(`keywords: "${kw}"`);
129
+ if (keywords.includes("tanstack-intent")) result.alreadyPresent.push("keywords: \"tanstack-intent\"");
172
130
  else {
173
- keywords.push(kw);
174
- result.added.push(`keywords: "${kw}"`);
131
+ keywords.push("tanstack-intent");
132
+ result.added.push("keywords: \"tanstack-intent\"");
175
133
  }
176
134
  if (!Array.isArray(pkg.files)) pkg.files = [];
177
135
  const files = pkg.files;
@@ -191,39 +149,12 @@ function runEditPackageJson(root) {
191
149
  dir = next;
192
150
  }
193
151
  return false;
194
- })() ? ["skills", "bin"] : [
195
- "skills",
196
- "bin",
197
- "!skills/_artifacts"
198
- ];
152
+ })() ? ["skills"] : ["skills", "!skills/_artifacts"];
199
153
  for (const entry of requiredFiles) if (files.includes(entry)) result.alreadyPresent.push(`files: "${entry}"`);
200
154
  else {
201
155
  files.push(entry);
202
156
  result.added.push(`files: "${entry}"`);
203
157
  }
204
- const existingShim = findExistingShim(root);
205
- let ext;
206
- if (existingShim) ext = existingShim.endsWith(".mjs") ? "mjs" : "js";
207
- else ext = pkg.type === "module" ? "js" : "mjs";
208
- const shimRelative = `./bin/intent.${ext}`;
209
- if (typeof pkg.bin === "object" && pkg.bin !== null) {
210
- const binObj = pkg.bin;
211
- if (binObj.intent) result.alreadyPresent.push(`bin.intent`);
212
- else {
213
- binObj.intent = shimRelative;
214
- result.added.push(`bin.intent: "${shimRelative}"`);
215
- }
216
- } else if (!pkg.bin) {
217
- pkg.bin = { intent: shimRelative };
218
- result.added.push(`bin.intent: "${shimRelative}"`);
219
- } else if (typeof pkg.bin === "string") {
220
- const pkgName = typeof pkg.name === "string" ? pkg.name.replace(/^@[^/]+\//, "") : "unknown";
221
- pkg.bin = {
222
- [pkgName]: pkg.bin,
223
- intent: shimRelative
224
- };
225
- result.added.push(`bin.intent: "${shimRelative}" (converted bin from string to object)`);
226
- }
227
158
  writeFileSync(pkgPath, JSON.stringify(pkg, null, indentSize) + "\n");
228
159
  for (const a of result.added) console.log(`✓ Added ${a}`);
229
160
  for (const a of result.alreadyPresent) console.log(` Already present: ${a}`);
@@ -337,9 +268,6 @@ function runForEachPackage(root, runOne) {
337
268
  function runEditPackageJsonAll(root) {
338
269
  return runForEachPackage(root, runEditPackageJson);
339
270
  }
340
- function runAddLibraryBinAll(root) {
341
- return runForEachPackage(root, runAddLibraryBin);
342
- }
343
271
  function runSetupGithubActions(root, metaDir) {
344
272
  const workspaceRoot = findWorkspaceRoot(root) ?? root;
345
273
  const packageDirs = findPackagesWithSkills(workspaceRoot);
@@ -364,4 +292,4 @@ function runSetupGithubActions(root, metaDir) {
364
292
  }
365
293
 
366
294
  //#endregion
367
- export { runAddLibraryBin as a, runEditPackageJsonAll as c, resolveWorkspacePackages as i, runSetupGithubActions as l, findWorkspaceRoot as n, runAddLibraryBinAll as o, readWorkspacePatterns as r, runEditPackageJson as s, findPackagesWithSkills as t };
295
+ export { runEditPackageJson as a, resolveWorkspacePackages as i, findWorkspaceRoot as n, runEditPackageJsonAll as o, readWorkspacePatterns as r, runSetupGithubActions as s, findPackagesWithSkills as t };
package/dist/setup.d.mts CHANGED
@@ -1,2 +1,2 @@
1
- import { a as findPackagesWithSkills, c as resolveWorkspacePackages, d as runEditPackageJson, f as runEditPackageJsonAll, i as SetupGithubActionsResult, l as runAddLibraryBin, n as EditPackageJsonResult, o as findWorkspaceRoot, p as runSetupGithubActions, r as MonorepoResult, s as readWorkspacePatterns, t as AddLibraryBinResult, u as runAddLibraryBinAll } from "./setup-B-zdCBu4.mjs";
2
- export { AddLibraryBinResult, EditPackageJsonResult, MonorepoResult, SetupGithubActionsResult, findPackagesWithSkills, findWorkspaceRoot, readWorkspacePatterns, resolveWorkspacePackages, runAddLibraryBin, runAddLibraryBinAll, runEditPackageJson, runEditPackageJsonAll, runSetupGithubActions };
1
+ import { a as findWorkspaceRoot, c as runEditPackageJson, i as findPackagesWithSkills, l as runEditPackageJsonAll, n as MonorepoResult, o as readWorkspacePatterns, r as SetupGithubActionsResult, s as resolveWorkspacePackages, t as EditPackageJsonResult, u as runSetupGithubActions } from "./setup-BNBVotfR.mjs";
2
+ export { EditPackageJsonResult, MonorepoResult, SetupGithubActionsResult, findPackagesWithSkills, findWorkspaceRoot, readWorkspacePatterns, resolveWorkspacePackages, runEditPackageJson, runEditPackageJsonAll, runSetupGithubActions };
package/dist/setup.mjs CHANGED
@@ -1,4 +1,4 @@
1
1
  import "./utils-BfjM1mQe.mjs";
2
- import { a as runAddLibraryBin, c as runEditPackageJsonAll, i as resolveWorkspacePackages, l as runSetupGithubActions, n as findWorkspaceRoot, o as runAddLibraryBinAll, r as readWorkspacePatterns, s as runEditPackageJson, t as findPackagesWithSkills } from "./setup-mGV2dZrq.mjs";
2
+ import { a as runEditPackageJson, i as resolveWorkspacePackages, n as findWorkspaceRoot, o as runEditPackageJsonAll, r as readWorkspacePatterns, s as runSetupGithubActions, t as findPackagesWithSkills } from "./setup-Nyfl1KTS.mjs";
3
3
 
4
- export { findPackagesWithSkills, findWorkspaceRoot, readWorkspacePatterns, resolveWorkspacePackages, runAddLibraryBin, runAddLibraryBinAll, runEditPackageJson, runEditPackageJsonAll, runSetupGithubActions };
4
+ export { findPackagesWithSkills, findWorkspaceRoot, readWorkspacePatterns, resolveWorkspacePackages, runEditPackageJson, runEditPackageJsonAll, runSetupGithubActions };
@@ -1,11 +1,10 @@
1
1
  # notify-intent.yml — Drop this into your library repo's .github/workflows/
2
2
  #
3
- # Fires a repository_dispatch event to TanStack/intent whenever docs or
4
- # source files change on merge to main. This triggers the skill staleness
5
- # check workflow in the intent repo.
3
+ # Fires a repository_dispatch event whenever docs or source files change
4
+ # on merge to main. This triggers the skill staleness check workflow.
6
5
  #
7
6
  # Requirements:
8
- # - A fine-grained PAT with contents:write on TanStack/intent stored
7
+ # - A fine-grained PAT with contents:write on this repository stored
9
8
  # as the INTENT_NOTIFY_TOKEN repository secret.
10
9
  #
11
10
  # Template variables (replaced by `intent setup`):
@@ -13,7 +12,7 @@
13
12
  # {{DOCS_PATH}} — e.g. docs/**
14
13
  # {{SRC_PATH}} — e.g. packages/query-core/src/**
15
14
 
16
- name: Notify Intent
15
+ name: Trigger Skill Review
17
16
 
18
17
  on:
19
18
  push:
@@ -24,7 +23,7 @@ on:
24
23
 
25
24
  jobs:
26
25
  notify:
27
- name: Notify TanStack Intent
26
+ name: Trigger Skill Review
28
27
  runs-on: ubuntu-latest
29
28
  steps:
30
29
  - name: Checkout
@@ -42,7 +41,7 @@ jobs:
42
41
  uses: peter-evans/repository-dispatch@v3
43
42
  with:
44
43
  token: ${{ secrets.INTENT_NOTIFY_TOKEN }}
45
- repository: TanStack/intent
44
+ repository: ${{ github.repository }}
46
45
  event-type: skill-check
47
46
  client-payload: |
48
47
  {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tanstack/intent",
3
- "version": "0.0.20",
3
+ "version": "0.0.23",
4
4
  "description": "Ship compositional knowledge for AI coding agents alongside your npm packages",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -27,6 +27,7 @@
27
27
  "meta"
28
28
  ],
29
29
  "dependencies": {
30
+ "cac": "^6.7.14",
30
31
  "yaml": "^2.7.0"
31
32
  },
32
33
  "devDependencies": {
@@ -37,6 +38,7 @@
37
38
  "scripts": {
38
39
  "prepack": "npm run build",
39
40
  "build": "tsdown src/index.ts src/cli.ts src/setup.ts src/intent-library.ts src/library-scanner.ts --format esm --dts",
41
+ "test:smoke": "pnpm run build && node dist/cli.mjs --help > /dev/null",
40
42
  "test:lib": "vitest run --exclude 'tests/integration/**'",
41
43
  "test:integration": "vitest run tests/integration/",
42
44
  "test:types": "tsc --noEmit"
@@ -1,5 +0,0 @@
1
- import "./utils-BfjM1mQe.mjs";
2
- import "./setup-mGV2dZrq.mjs";
3
- import { t as scanForIntents } from "./scanner-DVepyEwz.mjs";
4
-
5
- export { scanForIntents };