Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/exclude-adds-to-defaults.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'onsystem': minor
---

`exclude` adds to the defaults instead of replacing them. A config whose `exclude` lists folders without repeating the defaults now also leaves out tests and stories (`*.test.tsx`, `*.stories.tsx`, `__tests__`, `__stories__` and `__mocks__` folders) and `.d.ts` files, which it checked before. To check one of them again, add the default with `!` in front (`"!**/*.{test,spec,stories}.{ts,tsx,js,jsx}"`), or pass `--include-tests` to check tests and stories for one run; a `!` pattern that names no default gets a warning. A design-system package's `exclude` adds to the defaults for finding its own components too.
7 changes: 7 additions & 0 deletions .changeset/registry-aware-zero-config.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
---
'onsystem': minor
---

Zero config reads the folders `npx shadcn add` copies other registries' code into as read-only design systems, next to `components/ui`: for each registry in the `registries` of `components.json`, the folder of that name under the `components` alias (`@signoff-ui` → `components/signoff-ui`, `@ai-elements` → `components/ai-elements`). Before, that code was checked as the app's own: in VoltAgent's chatbot starter, which the corpus now checks, 11 of the 14 findings of `check .` were in `components/ai-elements`, and the next `shadcn add` could bring findings in registry files nobody edited, which failed `check` and the GitHub Action. Now `check`, the Claude Code hook, the ESLint plugin and the Action skip those files, as they skip `components/ui`; `search_components`, `get_component` and `list_components` find their components, and `get_component` says which registry one was installed from and that changes to it belong upstream; and the app's code is checked against them, so `<DiffReview tone="danger">` or `<Message.Header>` is a finding, and so is an icon-only registry button without a name. None of them is suggested in place of a native element, and the helpers in a folder's `lib/` (signoff-ui's `Img` and icons) are left out of `list_components` and `search_components`. `inspect` names the folders on its `detected` line, and `inspect --explain` says why each was read or not. A folder is not read when the app's components come from a workspace package imported through its `exports`, and code a registry copies loose into `components/` is still checked as the app's. `init` names those folders on its "Found the design system" line instead of a note of its own.

A config that lists such a folder in `components`, as `init` writes it, reads it the same way: its components are no longer suggested for native elements (signoff-ui's `Img` for an `<img>`); map one in `elements` to have it suggested. A folder that `components.json` names in no `registries` entry is read as before.
13 changes: 13 additions & 0 deletions corpus/repos.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,19 @@
"sha": "c2f8235e1f3ea903ad8b7f61447c4f74164b5c58",
"runs": [{ "name": "chatbot", "cwd": ".", "check": ["app", "components"] }]
},
{
"name": "voltagent",
"url": "https://github.com/VoltAgent/voltagent",
"sha": "72a46c76b4507e1f98b41d5050a92bd30587eb70",
"paths": ["examples/next-js-chatbot-starter-template"],
"runs": [
{
"name": "voltagent-chatbot",
"cwd": "examples/next-js-chatbot-starter-template",
"check": ["."]
}
]
},
{
"name": "shadcn-ui",
"url": "https://github.com/shadcn-ui/ui",
Expand Down
31 changes: 30 additions & 1 deletion corpus/snapshot.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"$comment": "Written by `node scripts/corpus.mjs --update`. Counts per run and rule; `labels` records which labelled findings were reported.",
"version": "0.6.0",
"version": "0.7.0",
"runs": {
"saas-starter": {
"inspect": {
Expand Down Expand Up @@ -70,6 +70,35 @@
}
}
},
"voltagent-chatbot": {
"inspect": {
"detected": "components.json (ui: @/components/ui → components/ui); from shadcn registries, read-only: components/ai-elements (@ai-elements, 31 files)",
"files": "49 component files, 1 token file, 0 docs",
"components": 53,
"parts": 208,
"tokens": {
"color": 36,
"typography": 2,
"radius": 8,
"spacing": 1
},
"warnings": 0
},
"files": 3,
"flagged": 1,
"rules": {
"icon-button-accessible-name": {
"errors": 1,
"warnings": 0,
"fixes": 0
},
"no-hardcoded-color": {
"errors": 0,
"warnings": 3,
"fixes": 0
}
}
},
"shadcn-website": {
"inspect": {
"detected": "components.json (ui: @/registry/new-york-v4/ui → registry/new-york-v4/ui)",
Expand Down
2 changes: 1 addition & 1 deletion docs/ci.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

The check that runs after each edit in Claude Code also gates every pull request, whoever or whatever wrote it. `onsystem check` runs the same rules as `check_ui` and exits 1 on errors (or on more than `--max-warnings` warnings). It skips the design system's own component files, the ones `components` matches: they implement the scale and the primitives the rules enforce, so a fresh shadcn/ui project's `p-[3px]` is not a finding. `--include-design-system`, or `"includeDesignSystem": true` in the config, lints them too.

In folders and globs, `check` also leaves out tests and stories (`*.test.tsx`, `*.spec.tsx`, `*.stories.tsx`, and whatever is in `__tests__`, `__stories__` and `__mocks__` folders; `--include-tests` checks them), or what the config's `exclude` lists in their place ([a list replaces them](configuration.md#config-file)), and what git ignores (through `git check-ignore`, so nested `.gitignore` files count); a file named outright is always checked. Only JS and TS files are (`.tsx`, `.jsx`, `.ts`, `.js` and their `.mts`, `.cts`, `.mjs` and `.cjs` forms): the CSS, Markdown and JSON that `check $(git diff --name-only)` names or `check "**/*"` matches are skipped, as `check_ui` refuses them. A file that renders an image or an email is not checked, since tokens and classes don't apply there: one that imports `next/og`, `@vercel/og`, `satori` or `@react-email/*`, a Next.js `opengraph-image`, `twitter-image`, `icon` or `apple-icon` route, or a file in an `og` folder. The summary line counts what was left out. Code installed from a shadcn registry is checked as your own until the config sets it apart: [code from shadcn registries](configuration.md#code-from-shadcn-registries).
In folders and globs, `check` also leaves out tests and stories (`*.test.tsx`, `*.spec.tsx`, `*.stories.tsx`, and whatever is in `__tests__`, `__stories__` and `__mocks__` folders; `--include-tests` checks them), what the config's `exclude` adds to them ([`exclude`](configuration.md#config-file)), and what git ignores (through `git check-ignore`, so nested `.gitignore` files count); a file named outright is always checked. Only JS and TS files are (`.tsx`, `.jsx`, `.ts`, `.js` and their `.mts`, `.cts`, `.mjs` and `.cjs` forms): the CSS, Markdown and JSON that `check $(git diff --name-only)` names or `check "**/*"` matches are skipped, as `check_ui` refuses them. A file that renders an image or an email is not checked, since tokens and classes don't apply there: one that imports `next/og`, `@vercel/og`, `satori` or `@react-email/*`, a Next.js `opengraph-image`, `twitter-image`, `icon` or `apple-icon` route, or a file in an `og` folder. The summary line counts what was left out. Code that `npx shadcn add` copied into the folder of a registry `components.json` names is skipped like `components/ui`; other registry code is checked as your own until the config sets it apart: [code from shadcn registries](configuration.md#code-from-shadcn-registries).

A folder stands for the `.tsx` and `.jsx` files in it. A JavaScript app can write its JSX in `.js` files (Next.js's JavaScript template has `app/page.js`): `check` names those it left out and gives the command that checks them, such as `check . "**/*.js"`. A `.js` file over 512 KB or named `*.min.js` is taken for a bundle and not looked at. With the [GitHub Action](required-check.md), list the glob in `paths` without quotes, `paths: . **/*.js`: the action passes each path as it is, with no shell.

Expand Down
Loading
Loading