Skip to content

Commit 0f2ead5

Browse files
KyleAMathewsclaudeautofix-ci[bot]
authored
feat: replace bin.intent detection with tanstack-intent keyword (#81)
* feat: replace bin.intent detection with tanstack-intent keyword Replace the bin shim-based package detection in library-scanner with a simpler check for the "tanstack-intent" keyword in the keywords array. Remove the entire add-library-bin command and bin shim generation system, since the keyword already existed for registry discovery and now serves both purposes. Also fix collectPackagingWarnings to not warn about !skills/_artifacts in monorepo packages (matching edit-package-json behavior), and add dedicated test coverage for keyword addition in runEditPackageJson. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * chore: add changeset for keyword-based detection Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * ci: apply automated fixes * fix: keep legacy bin.intent fallback for backwards compatibility Packages already published with bin.intent but without the tanstack-intent keyword would silently lose transitive skill discovery. Keep both signals during the transition period. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * ci: apply automated fixes * style: alphabetize import members in setup.test.ts Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com> Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
1 parent 9447688 commit 0f2ead5

13 files changed

Lines changed: 180 additions & 357 deletions

File tree

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'@tanstack/intent': patch
3+
---
4+
5+
Replace bin.intent detection with tanstack-intent keyword check for package discovery. Remove the `add-library-bin` command and bin shim generation system — packages are now identified by having `"tanstack-intent"` in their keywords array, which was already required for registry discovery. Also fix `collectPackagingWarnings` to skip the `!skills/_artifacts` warning for monorepo packages.

docs/cli/intent-scaffold.md

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,6 @@ The prompt also includes a post-generation checklist:
3030
- Commit generated `skills/` and `skills/_artifacts/`
3131
- Ensure `@tanstack/intent` is in `devDependencies`
3232
- Run setup commands as needed:
33-
- `npx @tanstack/intent@latest add-library-bin`
3433
- `npx @tanstack/intent@latest edit-package-json`
3534
- `npx @tanstack/intent@latest setup-github-actions`
3635

docs/cli/intent-setup.md

Lines changed: 6 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -3,32 +3,25 @@ title: setup commands
33
id: intent-setup
44
---
55

6-
Intent exposes setup as three separate commands.
6+
Intent exposes setup as two separate commands.
77

88
```bash
9-
npx @tanstack/intent@latest add-library-bin
109
npx @tanstack/intent@latest edit-package-json
1110
npx @tanstack/intent@latest setup-github-actions
1211
```
1312

1413
## Commands
1514

16-
- `add-library-bin`: create a package-local `intent` shim in `bin/`
1715
- `edit-package-json`: add or normalize `package.json` entries needed to publish skills
1816
- `setup-github-actions`: copy workflow templates to `.github/workflows`
1917

2018
## What each command changes
2119

22-
- `add-library-bin`
23-
- Creates `bin/intent.js` when `package.json.type` is `module`, otherwise `bin/intent.mjs`
24-
- If either shim already exists, command skips creation
25-
- Shim imports `@tanstack/intent/intent-library`
2620
- `edit-package-json`
2721
- Requires a valid `package.json` in current directory
28-
- Ensures `bin.intent` points to `./bin/intent.<ext>`
22+
- Ensures `keywords` includes `tanstack-intent`
2923
- Ensures `files` includes required publish entries
30-
- Preserves existing indentation and existing `bin` entries
31-
- Converts string shorthand `bin` to object when needed
24+
- Preserves existing indentation
3225
- `setup-github-actions`
3326
- Copies templates from `@tanstack/intent/meta/templates/workflows` to `.github/workflows`
3427
- Applies variable substitution for `PACKAGE_NAME`, `REPO`, `DOCS_PATH`, `SRC_PATH`
@@ -38,8 +31,8 @@ npx @tanstack/intent@latest setup-github-actions
3831

3932
`edit-package-json` enforces different `files` sets based on package location:
4033

41-
- Monorepo package: `skills`, `bin`
42-
- Non-monorepo package: `skills`, `bin`, `!skills/_artifacts`
34+
- Monorepo package: `skills`
35+
- Non-monorepo package: `skills`, `!skills/_artifacts`
4336

4437
## Common errors
4538

@@ -48,7 +41,7 @@ npx @tanstack/intent@latest setup-github-actions
4841

4942
## Notes
5043

51-
- `add-library-bin` and `setup-github-actions` skip existing files
44+
- `setup-github-actions` skips existing files
5245

5346
## Related
5447

docs/cli/intent-validate.md

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -37,11 +37,9 @@ If `<dir>/_artifacts` exists, it also validates artifacts:
3737
Packaging warnings are always computed from `package.json` in the current working directory:
3838

3939
- `@tanstack/intent` missing from `devDependencies`
40-
- Missing `bin.intent` entry
41-
- Missing shim (`bin/intent.js` or `bin/intent.mjs`)
40+
- Missing `tanstack-intent` in keywords array
4241
- Missing `files` entries when `files` array exists:
4342
- `skills`
44-
- `bin`
4543
- `!skills/_artifacts`
4644

4745
Warnings are informational; they are printed on both pass and fail paths.

docs/getting-started/quick-start-maintainers.md

Lines changed: 2 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -22,9 +22,6 @@ Or run commands without installing:
2222
npx @tanstack/intent@latest scaffold
2323
```
2424

25-
> [!WARNING]
26-
> When using `npx` or `bunx`, always include `@latest`. Intent-enabled libraries ship a local `intent` binary shim, and without `@latest`, your package manager may resolve to that shim instead of the real CLI.
27-
2825
---
2926

3027
## Initial Setup (With Agent)
@@ -101,9 +98,6 @@ Artifacts enforce a consistent skill structure across versions, making it easier
10198
Run these commands to prepare your package for skill publishing:
10299

103100
```bash
104-
# Generate the bin shim that consumers use for discovery
105-
npx @tanstack/intent@latest add-library-bin
106-
107101
# Update package.json with required fields
108102
npx @tanstack/intent@latest edit-package-json
109103

@@ -113,11 +107,9 @@ npx @tanstack/intent@latest setup-github-actions
113107

114108
**What these do:**
115109

116-
- `add-library-bin` creates `bin/intent.js` or `bin/intent.mjs` — a shim that lets consumers run `npx your-package intent` to access Intent CLI features
117110
- `edit-package-json` adds:
118-
- `intent` field in package.json with version, repo, and docs metadata
119-
- `bin.intent` entry pointing to the shim
120-
- `files` array entries for `skills/` and `bin/`
111+
- `tanstack-intent` keyword (used for package detection and registry discovery)
112+
- `files` array entries for `skills/`
121113
- For single packages: also adds `!skills/_artifacts` to exclude artifacts from npm
122114
- For monorepos: skips the artifacts exclusion (artifacts live at repo root)
123115
- `setup-github-actions` copies workflow templates to `.github/workflows/` for automated validation and staleness checking

packages/intent/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@tanstack/intent",
3-
"version": "0.0.19",
3+
"version": "0.0.20",
44
"description": "Ship compositional knowledge for AI coding agents alongside your npm packages",
55
"license": "MIT",
66
"type": "module",

packages/intent/src/cli.ts

Lines changed: 35 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -244,17 +244,9 @@ function collectPackagingWarnings(root: string): Array<string> {
244244
warnings.push('@tanstack/intent is not in devDependencies')
245245
}
246246

247-
const bin = pkgJson.bin as Record<string, string> | undefined
248-
if (!bin?.intent) {
249-
warnings.push('Missing "bin": { "intent": ... } entry in package.json')
250-
}
251-
252-
const shimJs = join(root, 'bin', 'intent.js')
253-
const shimMjs = join(root, 'bin', 'intent.mjs')
254-
if (!existsSync(shimJs) && !existsSync(shimMjs)) {
255-
warnings.push(
256-
'No bin/intent.js or bin/intent.mjs shim found (run: npx @tanstack/intent add-library-bin)',
257-
)
247+
const keywords = pkgJson.keywords
248+
if (!Array.isArray(keywords) || !keywords.includes('tanstack-intent')) {
249+
warnings.push('Missing "tanstack-intent" in keywords array')
258250
}
259251

260252
const files = pkgJson.files as Array<string> | undefined
@@ -264,12 +256,32 @@ function collectPackagingWarnings(root: string): Array<string> {
264256
'"skills" is not in the "files" array — skills won\'t be published',
265257
)
266258
}
267-
if (!files.includes('bin')) {
268-
warnings.push(
269-
'"bin" is not in the "files" array — shim won\'t be published',
270-
)
271-
}
272-
if (!files.includes('!skills/_artifacts')) {
259+
260+
// Only warn about !skills/_artifacts for non-monorepo packages.
261+
// In monorepos, artifacts live at the repo root, so the negation
262+
// pattern is intentionally omitted by edit-package-json.
263+
const isMonorepoPkg = (() => {
264+
let dir = join(root, '..')
265+
for (let i = 0; i < 5; i++) {
266+
const parentPkg = join(dir, 'package.json')
267+
if (existsSync(parentPkg)) {
268+
try {
269+
const parent = JSON.parse(readFileSync(parentPkg, 'utf8'))
270+
return (
271+
Array.isArray(parent.workspaces) || parent.workspaces?.packages
272+
)
273+
} catch {
274+
return false
275+
}
276+
}
277+
const next = dirname(dir)
278+
if (next === dir) break
279+
dir = next
280+
}
281+
return false
282+
})()
283+
284+
if (!isMonorepoPkg && !files.includes('!skills/_artifacts')) {
273285
warnings.push(
274286
'"!skills/_artifacts" is not in the "files" array — artifacts will be published unnecessarily',
275287
)
@@ -557,11 +569,10 @@ This produces: individual SKILL.md files.
557569
558570
1. Run \`intent validate\` in each package directory
559571
2. Commit skills/ and artifacts
560-
3. For each publishable package, run: \`npx @tanstack/intent add-library-bin\`
561-
4. For each publishable package, run: \`npx @tanstack/intent edit-package-json\`
562-
5. Ensure each package has \`@tanstack/intent\` as a devDependency
563-
6. Create a \`skill:<skill-name>\` label on the GitHub repo for each skill (use \`gh label create\`)
564-
7. Add a README note: "If you use an AI agent, run \`npx @tanstack/intent@latest install\`"
572+
3. For each publishable package, run: \`npx @tanstack/intent edit-package-json\`
573+
4. Ensure each package has \`@tanstack/intent\` as a devDependency
574+
5. Create a \`skill:<skill-name>\` label on the GitHub repo for each skill (use \`gh label create\`)
575+
6. Add a README note: "If you use an AI agent, run \`npx @tanstack/intent@latest install\`"
565576
`
566577

567578
console.log(prompt)
@@ -579,8 +590,7 @@ Usage:
579590
intent validate [<dir>] Validate skill files (default: skills/)
580591
intent install Print a skill that guides your coding agent to set up skill-to-task mappings
581592
intent scaffold Print maintainer scaffold prompt
582-
intent add-library-bin Generate bin/intent.{js,mjs} bridge file
583-
intent edit-package-json Wire package.json (files, bin) for skill publishing
593+
intent edit-package-json Wire package.json (files, keywords) for skill publishing
584594
intent setup-github-actions Copy CI workflow templates to .github/workflows/
585595
intent stale [dir] [--json] Check skills for staleness`
586596

@@ -618,12 +628,9 @@ Examples:
618628
intent stale
619629
intent stale packages/query
620630
intent stale --json`,
621-
'add-library-bin': `intent add-library-bin
622-
623-
Generate bin/intent.{js,mjs} bridge files for publishable packages.`,
624631
'edit-package-json': `intent edit-package-json
625632
626-
Update package.json files so skills and shims are published.`,
633+
Update package.json files so skills are published.`,
627634
'setup-github-actions': `intent setup-github-actions
628635
629636
Copy Intent CI workflow templates into .github/workflows/.`,
@@ -719,11 +726,6 @@ export async function main(argv: Array<string> = process.argv.slice(2)) {
719726
}
720727
return 0
721728
}
722-
case 'add-library-bin': {
723-
const { runAddLibraryBinAll } = await import('./setup.js')
724-
runAddLibraryBinAll(process.cwd())
725-
return 0
726-
}
727729
case 'edit-package-json': {
728730
const { runEditPackageJsonAll } = await import('./setup.js')
729731
runEditPackageJsonAll(process.cwd())

packages/intent/src/index.ts

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -17,13 +17,8 @@ export {
1717
parseFrontmatter,
1818
resolveDepDir,
1919
} from './utils.js'
20-
export {
21-
runAddLibraryBin,
22-
runEditPackageJson,
23-
runSetupGithubActions,
24-
} from './setup.js'
20+
export { runEditPackageJson, runSetupGithubActions } from './setup.js'
2521
export type {
26-
AddLibraryBinResult,
2722
EditPackageJsonResult,
2823
SetupGithubActionsResult,
2924
} from './setup.js'

packages/intent/src/library-scanner.ts

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -42,10 +42,22 @@ function findHomeDir(scriptPath: string): string | null {
4242
}
4343
}
4444

45-
function hasIntentBin(pkg: Record<string, unknown>): boolean {
45+
function isIntentPackage(pkg: Record<string, unknown>): boolean {
46+
const keywords = pkg.keywords
47+
if (Array.isArray(keywords) && keywords.includes('tanstack-intent')) {
48+
return true
49+
}
50+
// Legacy fallback: packages published before the keyword-based detection
51+
// change may only have bin.intent. Keep this until a breaking release.
4652
const bin = pkg.bin
47-
if (!bin || typeof bin !== 'object') return false
48-
return 'intent' in (bin as Record<string, unknown>)
53+
if (
54+
bin &&
55+
typeof bin === 'object' &&
56+
'intent' in (bin as Record<string, unknown>)
57+
) {
58+
return true
59+
}
60+
return false
4961
}
5062

5163
function discoverSkills(skillsDir: string): Array<SkillEntry> {
@@ -134,7 +146,7 @@ export async function scanLibrary(
134146
const depDir = resolveDepDir(depName, dir)
135147
if (!depDir) continue
136148
const depPkg = readPkgJson(depDir)
137-
if (depPkg && hasIntentBin(depPkg)) {
149+
if (depPkg && isIntentPackage(depPkg)) {
138150
processPackage(depName, depDir)
139151
}
140152
}

0 commit comments

Comments
 (0)