Skip to content

Commit 665370e

Browse files
Notice Suppression & Persistent Exclude Management (#157)
* changeset * format * add no notices option * exclude command * changeset * fix knip error * ci: apply automated fixes --------- Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
1 parent 0e9d30e commit 665370e

15 files changed

Lines changed: 554 additions & 46 deletions

File tree

.changeset/crisp-flies-mate.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
---
2+
'@tanstack/intent': minor
3+
---
4+
5+
Add `package.json#intent.skills` source allowlisting to gate which discovered packages can contribute skills.
6+
7+
`intent.exclude` now supports skill-level matching (for example `@scope/pkg#skill-id` and globs), and policy filtering is applied consistently across `intent list`, `intent load`, `intent install`, and `intent stale`. Notices are surfaced separately from warnings to keep command output machine-safe.

.changeset/green-dingos-refuse.md

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
---
2+
'@tanstack/intent': minor
3+
---
4+
5+
Add a persistent `intent exclude` command for managing `package.json#intent.exclude` (`list`, `add`, `remove`), and document it in the CLI/config guides.
6+
7+
Add notice suppression controls for automation:
8+
9+
- `--no-notices` on `intent list` and `intent install`
10+
- `INTENT_NO_NOTICES=1` environment variable
11+
12+
Remove one-off CLI exclude flags from command surfaces (`list/load --exclude`); excludes are now managed via `package.json#intent.exclude` and `intent exclude`.

docs/cli/intent-exclude.md

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
---
2+
title: intent exclude
3+
id: intent-exclude
4+
---
5+
6+
`intent exclude` manages `package.json#intent.exclude` entries.
7+
8+
```bash
9+
npx @tanstack/intent@latest exclude [list|add|remove] [pattern] [--json]
10+
```
11+
12+
## Options
13+
14+
- `--json`: print the configured exclude patterns as JSON
15+
16+
## Actions
17+
18+
1. `list` (default): print current excludes
19+
2. `add <pattern>`: append one exclude pattern
20+
3. `remove <pattern>`: remove one exclude pattern
21+
22+
## Examples
23+
24+
```bash
25+
npx @tanstack/intent@latest exclude
26+
npx @tanstack/intent@latest exclude list --json
27+
npx @tanstack/intent@latest exclude add @tanstack/router#experimental-*
28+
npx @tanstack/intent@latest exclude remove @tanstack/router#experimental-*
29+
```
30+
31+
## Behavior
32+
33+
- Reads and writes the current working directory `package.json`
34+
- Creates `intent.exclude` when missing
35+
- Keeps existing excludes and appends new patterns in order
36+
- Validates pattern syntax before writing
37+
- Refuses invalid `package.json` structures for `intent` and `intent.exclude`
38+
39+
## Related
40+
41+
- [Configuration](../concepts/configuration)
42+
- [intent list](./intent-list)
43+
- [intent load](./intent-load)

docs/cli/intent-install.md

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ id: intent-install
66
`intent install` creates or updates an `intent-skills` guidance block in a project guidance file.
77

88
```bash
9-
npx @tanstack/intent@latest install [--map] [--dry-run] [--print-prompt] [--global] [--global-only]
9+
npx @tanstack/intent@latest install [--map] [--dry-run] [--print-prompt] [--global] [--global-only] [--no-notices]
1010
```
1111

1212
## Options
@@ -16,6 +16,7 @@ npx @tanstack/intent@latest install [--map] [--dry-run] [--print-prompt] [--glob
1616
- `--print-prompt`: print the agent setup prompt instead of writing files
1717
- `--global`: include global packages after project packages when `--map` is passed
1818
- `--global-only`: install mappings from global packages only when `--map` is passed
19+
- `--no-notices`: suppress non-critical notices on stderr
1920

2021
## Behavior
2122

@@ -75,6 +76,8 @@ skills:
7576
- Placement tip: `Tip: Keep the intent-skills block near the top of AGENTS.md so agents read it before task-specific instructions.`
7677
- No actionable skills in `--map` mode: `No intent-enabled skills found.`
7778

79+
To suppress trust and migration notices in automation, pass `--no-notices`.
80+
7881
## Related
7982

8083
- [intent list](./intent-list)

docs/cli/intent-list.md

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,30 +6,31 @@ id: intent-list
66
`intent list` discovers skill-enabled packages and prints available skills.
77

88
```bash
9-
npx @tanstack/intent@latest list [--json] [--debug] [--exclude <pattern>] [--global] [--global-only]
9+
npx @tanstack/intent@latest list [--json] [--debug] [--global] [--global-only] [--no-notices]
1010
```
1111

1212
## Options
1313

1414
- `--json`: print JSON instead of text output
1515
- `--debug`: print discovery debug details to stderr
16-
- `--exclude <pattern>`: exclude package names matching a simple glob; can be passed more than once
1716
- `--global`: include global packages after project packages
1817
- `--global-only`: list global packages only
18+
- `--no-notices`: suppress non-critical notices on stderr
1919

2020
## What you get
2121

2222
- Scans project and workspace dependencies for intent-enabled packages and skills
2323
- Surfaces packages permitted by `package.json#intent.skills` (see [Allowlist](#allowlist))
2424
- Includes global packages only when `--global` or `--global-only` is passed
2525
- Includes warnings from discovery
26-
- Excludes packages and skills matched by package.json `intent.exclude` or `--exclude`
26+
- Excludes packages and skills matched by package.json `intent.exclude`
2727
- Prints debug details to stderr when `--debug` is passed
2828
- If no packages are discovered, prints `No intent-enabled packages found.`
2929
- Summary line with package count and skill count
3030
- Package table columns: `PACKAGE`, `SOURCE`, `VERSION`, `SKILLS`
3131
- Skill tree grouped by package
3232
- Optional warnings section (`⚠ ...` per warning)
33+
- Optional notices section on stderr (`ℹ ...` per notice), suppressed by `--no-notices`
3334

3435
`SOURCE` is a lightweight indicator showing whether the selected package came from local discovery or explicit global scanning.
3536
When both local and global packages are scanned, local packages take precedence.
@@ -113,7 +114,8 @@ A package that ships skills but is not listed is dropped. When packages are drop
113114
## Excludes
114115

115116
Package excludes are hard filters for packages that should not be used in a repo, applied after the allowlist.
116-
Intent reads `intent.exclude` arrays from package.json files while walking from the workspace or project root to the current working directory, then appends any `--exclude` flags.
117+
Intent reads `intent.exclude` arrays from package.json files while walking from the workspace or project root to the current working directory.
118+
Manage persistent excludes with `intent exclude add|remove|list`.
117119

118120
```json
119121
{

docs/cli/intent-load.md

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,15 +6,14 @@ id: intent-load
66
`intent load` loads a compact skill identity from the current install and prints the matching `SKILL.md` content.
77

88
```bash
9-
npx @tanstack/intent@latest load <package>#<skill> [--path] [--json] [--debug] [--exclude <pattern>] [--global] [--global-only]
9+
npx @tanstack/intent@latest load <package>#<skill> [--path] [--json] [--debug] [--global] [--global-only]
1010
```
1111

1212
## Options
1313

1414
- `--path`: print the resolved skill path instead of the file content
1515
- `--json`: print structured JSON with metadata and content
1616
- `--debug`: print resolution debug details to stderr
17-
- `--exclude <pattern>`: exclude a package or skill matching a simple glob; can be passed more than once
1817
- `--global`: load from project packages first, then global packages
1918
- `--global-only`: load from global packages only
2019

@@ -24,7 +23,7 @@ npx @tanstack/intent@latest load <package>#<skill> [--path] [--json] [--debug] [
2423
- Scans project-local packages by default
2524
- Includes global packages only when `--global` or `--global-only` is passed
2625
- Refuses before scanning when the target package is not permitted by `package.json#intent.skills`
27-
- Refuses before scanning when the target package or skill matches `intent.exclude` or `--exclude`
26+
- Refuses before scanning when the target package or skill matches `intent.exclude`
2827
- Prefers local packages when `--global` is used and the same package exists locally and globally
2928
- Accepts an unambiguous short skill name when a package-prefixed skill exists
3029
- Prints raw `SKILL.md` content by default

docs/concepts/configuration.md

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,9 +46,28 @@ A package that ships skills but is not listed is dropped. When packages are drop
4646

4747
A project that has not set `intent.skills` keeps working. Intent surfaces every discovered package and prints the deprecation notice described under the absent form. Nothing breaks. Add an allowlist when you are ready, before a future version requires one. Run `intent list` to confirm which packages are surfaced.
4848

49+
### Suppressing notices temporarily
50+
51+
Use `--no-notices` to suppress non-critical notices on stderr for one run:
52+
53+
```bash
54+
npx @tanstack/intent@latest list --no-notices
55+
npx @tanstack/intent@latest install --map --no-notices
56+
```
57+
58+
For CI or wrapper scripts, set `INTENT_NO_NOTICES=1` to suppress notices without changing command arguments.
59+
4960
## `intent.exclude`
5061

51-
`intent.exclude` removes packages or individual skills after the allowlist resolves. It also accepts the `--exclude <pattern>` flag on `list` and `load` for one-off runs.
62+
`intent.exclude` removes packages or individual skills after the allowlist resolves.
63+
64+
Use `intent exclude` to manage this list from the CLI:
65+
66+
```bash
67+
npx @tanstack/intent@latest exclude add @tanstack/router#experimental-*
68+
npx @tanstack/intent@latest exclude remove @tanstack/router#experimental-*
69+
npx @tanstack/intent@latest exclude list
70+
```
5271

5372
```json
5473
{

docs/config.json

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,10 @@
4747
"label": "intent install",
4848
"to": "cli/intent-install"
4949
},
50+
{
51+
"label": "intent exclude",
52+
"to": "cli/intent-exclude"
53+
},
5054
{
5155
"label": "intent list",
5256
"to": "cli/intent-list"

packages/intent/src/cli-output.ts

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,27 @@ export function printWarnings(warnings: Array<string>): void {
77
}
88
}
99

10-
export function printNotices(notices: Array<string>): void {
10+
export interface NoticeOutputOptions {
11+
noNotices?: boolean
12+
}
13+
14+
const TRUE_LIKE_VALUES = new Set(['1', 'true', 'yes', 'on'])
15+
16+
function envSuppressesNotices(): boolean {
17+
const value = process.env.INTENT_NO_NOTICES?.trim().toLowerCase()
18+
return value ? TRUE_LIKE_VALUES.has(value) : false
19+
}
20+
21+
function shouldSuppressNotices(options: NoticeOutputOptions = {}): boolean {
22+
return options.noNotices === true || envSuppressesNotices()
23+
}
24+
25+
export function printNotices(
26+
notices: Array<string>,
27+
options: NoticeOutputOptions = {},
28+
): void {
1129
if (notices.length === 0) return
30+
if (shouldSuppressNotices(options)) return
1231

1332
console.error('Notices:')
1433
for (const notice of notices) {

packages/intent/src/cli-support.ts

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,10 @@ export { printNotices, printWarnings } from './cli-output.js'
1010

1111
export interface GlobalScanFlags {
1212
debug?: boolean
13-
exclude?: string | Array<string>
1413
global?: boolean
1514
globalOnly?: boolean
15+
notices?: boolean
16+
noNotices?: boolean
1617
}
1718

1819
export interface StaleTargetResult {
@@ -89,16 +90,17 @@ export function coreOptionsFromGlobalFlags(
8990

9091
return {
9192
debug: options.debug,
92-
exclude: Array.isArray(options.exclude)
93-
? options.exclude
94-
: options.exclude
95-
? [options.exclude]
96-
: undefined,
9793
global: options.global,
9894
globalOnly: options.globalOnly,
9995
}
10096
}
10197

98+
export function noticeOptionsFromGlobalFlags(options: GlobalScanFlags): {
99+
noNotices?: boolean
100+
} {
101+
return { noNotices: options.noNotices || options.notices === false }
102+
}
103+
102104
function formatDebugValue(value: string | number | Array<string>): string {
103105
if (Array.isArray(value)) {
104106
return value.length > 0 ? value.join(', ') : '(none)'

0 commit comments

Comments
 (0)