Repository navigation
docs: add ast-grep-config documentation page #50
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from all commits
Commits
Show all changes
10 commits
Select commit
Hold shift + click to select a range
d2d714f
docs: add ast-grep-config documentation page
amondnet ebbbe11
docs: add ast-grep-config section to README
amondnet 6506810
docs: make README package headings unique
amondnet 71b9c6d
docs(ast-grep-config): describe error rule matching conditions accura…
amondnet 29dda57
docs(ast-grep-config): list error rule matching per language and cove…
amondnet 1cb4431
docs(ast-grep-config): scope framework file exemptions to default-exp…
amondnet 34bb8ad
docs(ast-grep-config): narrow framework exemption note to framework d…
amondnet 5d5a756
docs(ast-grep-config): call out the shared *.d.ts exemption in framew…
amondnet 783749f
chore(docs): apply AI code review suggestions to ast-grep-config fram…
amondnet 0883773
chore(docs): clarify Nuxt 4 migration replaces both workaround comman…
amondnet File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,184 @@ | ||
| --- | ||
| title: "ast-grep Config" | ||
| description: "ast-grep rules that keep a codebase navigable for coding agents." | ||
| sidebar: | ||
| order: 5 | ||
| --- | ||
| `@pleaseai/ast-grep-config` is a set of [ast-grep](https://ast-grep.github.io/) rules that keep a codebase navigable for coding agents: public symbols you can find by name, error types in a designated file, and no tests inside source files. It enforces layer 2 (structural rules) of [ADR-0022](https://github.com/chatbot-pf/engineering-standards/blob/main/docs/adr/0022-agent-navigable-code-organization-standard.md) for TypeScript, Dart, Kotlin, Java, and Rust. | ||
|
|
||
| Every rule ships as a **warning**. Nothing here fails a build unless you raise a rule's severity in your own config. | ||
|
|
||
| ## Installation | ||
|
|
||
| <CodeGroup titles={["bun", "pnpm", "npm"]}> | ||
|
|
||
| ```bash | ||
| bun add -D @pleaseai/ast-grep-config @ast-grep/cli | ||
| ``` | ||
|
|
||
| ```bash | ||
| pnpm add -D @pleaseai/ast-grep-config @ast-grep/cli | ||
| ``` | ||
|
|
||
| ```bash | ||
| npm install -D @pleaseai/ast-grep-config @ast-grep/cli | ||
| ``` | ||
|
|
||
| </CodeGroup> | ||
|
|
||
| [`@ast-grep/cli`](https://ast-grep.github.io/) is a peer dependency that provides the `ast-grep` binary. Install it next to this package so `ast-grep` is on your project's bin path. | ||
|
|
||
| With bun, add `@ast-grep/cli` to `trustedDependencies` so its postinstall step runs. Otherwise `ast-grep` prints a fallback warning on every call (`please-style check` is unaffected). | ||
|
|
||
| ```json title="package.json" | ||
| { | ||
| "trustedDependencies": ["@ast-grep/cli"] | ||
| } | ||
| ``` | ||
|
|
||
| <Aside type="tip" href="/en/cli"> | ||
|
|
||
| Run `bunx @pleaseai/code-style init` and select **ast-grep** — the CLI installs both packages and writes `sgconfig.yml` for you. | ||
|
|
||
| </Aside> | ||
|
|
||
| ## Usage | ||
|
|
||
| Point your project's `sgconfig.yml` at the rules: | ||
|
|
||
| ```yaml title="sgconfig.yml" | ||
| ruleDirs: | ||
| - node_modules/@pleaseai/ast-grep-config/rules | ||
| ``` | ||
|
|
||
| ```bash | ||
| bunx ast-grep scan | ||
| ``` | ||
|
|
||
| Or scan with the package's own config without adding one: | ||
|
|
||
| ```bash | ||
| bunx ast-grep scan -c node_modules/@pleaseai/ast-grep-config/sgconfig.yml | ||
| ``` | ||
|
|
||
| ## The Five Principles | ||
|
|
||
| | Slug | Principle | | ||
| | --- | --- | | ||
| | `code-greppable-public-symbols` | Public symbols are named declarations, so one name search finds the definition and every use. | | ||
| | `code-filename-matches-primary-symbol` | A file with one public symbol is named after it (normalized to the language's file-name convention). | | ||
| | `code-error-types-in-dedicated-module` | A module's error types live in its designated error file or package. | | ||
| | `test-path-derivable-from-source` | Tests live under the toolchain's test root, at a path mirrored from the source they test. | | ||
| | `test-helpers-in-dedicated-location` | Helpers shared by several tests live in the designated helper location. | | ||
|
|
||
| The checks run in two layers: | ||
|
|
||
| - **Layer 2** — the ast-grep rules in this package, run with `ast-grep scan`. | ||
| - **Layer 3** — [`please-style check`](/en/cli#check), a path checker for what ast-grep cannot see (file names, test paths, and which helpers are shared). It runs the extraction rules in this package's `extract/` directory. `extract/` is not listed in `ruleDirs`, so its matches never appear in `ast-grep scan` output. | ||
|
|
||
| ## Rules | ||
|
|
||
| | Rule | Slug | Language | | ||
| | --- | --- | --- | | ||
| | [`ts-no-default-export`](https://github.com/pleaseai/code-style/blob/main/packages/ast-grep-config/rules/typescript/ts-no-default-export.md) | `code-greppable-public-symbols` | TypeScript | | ||
| | [`tsx-no-default-export`](https://github.com/pleaseai/code-style/blob/main/packages/ast-grep-config/rules/tsx/tsx-no-default-export.md) | `code-greppable-public-symbols` | TSX | | ||
| | [`rust-no-glob-reexport`](https://github.com/pleaseai/code-style/blob/main/packages/ast-grep-config/rules/rust/rust-no-glob-reexport.md) | `code-greppable-public-symbols` | Rust | | ||
| | [`ts-error-outside-errors-file`](https://github.com/pleaseai/code-style/blob/main/packages/ast-grep-config/rules/typescript/ts-error-outside-errors-file.md) | `code-error-types-in-dedicated-module` | TypeScript | | ||
| | [`tsx-error-outside-errors-file`](https://github.com/pleaseai/code-style/blob/main/packages/ast-grep-config/rules/tsx/tsx-error-outside-errors-file.md) | `code-error-types-in-dedicated-module` | TSX | | ||
| | [`dart-error-outside-errors-file`](https://github.com/pleaseai/code-style/blob/main/packages/ast-grep-config/rules/dart/dart-error-outside-errors-file.md) | `code-error-types-in-dedicated-module` | Dart | | ||
| | [`kotlin-error-outside-errors-file`](https://github.com/pleaseai/code-style/blob/main/packages/ast-grep-config/rules/kotlin/kotlin-error-outside-errors-file.md) | `code-error-types-in-dedicated-module` | Kotlin | | ||
| | [`java-error-outside-error-package`](https://github.com/pleaseai/code-style/blob/main/packages/ast-grep-config/rules/java/java-error-outside-error-package.md) | `code-error-types-in-dedicated-module` | Java | | ||
| | [`rust-error-outside-error-file`](https://github.com/pleaseai/code-style/blob/main/packages/ast-grep-config/rules/rust/rust-error-outside-error-file.md) | `code-error-types-in-dedicated-module` | Rust | | ||
| | [`ts-no-in-source-test`](https://github.com/pleaseai/code-style/blob/main/packages/ast-grep-config/rules/typescript/ts-no-in-source-test.md) | `test-path-derivable-from-source` | TypeScript | | ||
| | [`tsx-no-in-source-test`](https://github.com/pleaseai/code-style/blob/main/packages/ast-grep-config/rules/tsx/tsx-no-in-source-test.md) | `test-path-derivable-from-source` | TSX | | ||
|
|
||
| Each rule has a README next to it with the reason, a wrong and a right example, and the steps to fix a violation. The warning message names the slug and the README path inside `node_modules`, so an agent can fix the violation from the message alone: | ||
|
|
||
| ```text | ||
| [code-greppable-public-symbols] Default export hides the symbol's name from | ||
| grep. Export a named declaration instead. Fix guide: | ||
| node_modules/@pleaseai/ast-grep-config/rules/typescript/ts-no-default-export.md | ||
| ``` | ||
|
|
||
| ### No default exports | ||
|
|
||
| `ts-no-default-export` and `tsx-no-default-export` flag `export default …`, `export { foo as default }`, and `export { default } from './x'`. A default import lets every importer pick its own local name, so a search for the declaration's name misses those import sites. A named import must mention the exported name. | ||
|
|
||
| ```ts | ||
| // Wrong | ||
| export default class UserService {} | ||
|
|
||
| // Right | ||
| export class UserService {} | ||
| ``` | ||
|
|
||
| ### No glob re-exports | ||
|
|
||
| `rust-no-glob-reexport` flags any `use` with a visibility modifier (`pub`, `pub(crate)`, `pub(super)`) that contains a `*`. Private glob imports such as `use super::*;` are not matched. Replace the glob with an explicit list of the items it exports today: | ||
|
|
||
| ```rust | ||
| // Wrong | ||
| pub use crate::model::*; | ||
|
|
||
| // Right | ||
| pub use crate::model::{Account, User}; | ||
| ``` | ||
|
|
||
| ### Error types in a dedicated module | ||
|
|
||
| ast-grep has no type information, so the error rules match by name. For the class-based languages, a class is flagged when its supertype ends in `Error` or `Exception`, or when its own name ends in `Error` or `Exception` and it also has a supertype: | ||
|
|
||
| - TypeScript / TSX: the `extends` superclass only. `implements` does not match, and a class named `*Error` or `*Exception` is flagged only when it has an `extends` clause. | ||
| - Java: the superclass only (`Throwable` also counts). `implements` does not match. | ||
| - Dart: the superclass or any implemented type. A class named `*Error` or `*Exception` needs a superclass or `implements` clause. | ||
| - Kotlin: any supertype (`Throwable` also counts), on `class` and `object` declarations. | ||
|
|
||
| Rust flags a `struct` or `enum` whose name ends in `Error` (not `Exception`) or that has `#[derive(…Error)]`, plus any `impl Error for T` (including `std::error::Error` and `core::error::Error`). Each language has its own designated location: | ||
|
|
||
| | Language | Error types live in | Also exempt | | ||
| | --- | --- | --- | | ||
| | TypeScript / TSX | `errors.ts` in the module directory | `*.d.ts`, `*.test.*`, `*.spec.*`, `test/`, `tests/`, `__tests__/` | | ||
| | Dart / Flutter | `errors.dart` in the library directory | `*_test.dart`, `test/`, `integration_test/`, `test_driver/` | | ||
| | Kotlin | `Errors.kt` in the package directory | `src/test/`, `src/testFixtures/`, source sets ending in `Test` | | ||
| | Java | an `error/` subpackage of the module | `src/test/`, `src/testFixtures/`, `src/androidTest/` | | ||
| | Rust | `error.rs` next to the module root (or an `error/` module) | integration tests under `tests/` | | ||
|
|
||
| Only the location is checked — the error file may contain helpers and imports. | ||
|
|
||
| ### No in-source tests | ||
|
|
||
| `ts-no-in-source-test` and `tsx-no-in-source-test` flag Vitest [in-source tests](https://vitest.dev/guide/in-source.html) (`if (import.meta.vitest) { … }`). A `test/**` glob cannot find them, and production builds need a bundler `define` to strip them. Move the block into a test file under the package's test root, at a path mirrored from the source: `src/math/add.ts` becomes `test/math/add.test.ts`. | ||
|
|
||
| ## Framework Files | ||
|
|
||
| Files whose shape a framework dictates are excluded from `ts-no-default-export` and `tsx-no-default-export` through their `ignores` lists: | ||
|
|
||
| - Type declarations: `*.d.ts`, `*.d.mts`, `*.d.cts` | ||
| - Config files: `*.config.ts` and `*.config.*.ts` (for example `vite.config.prod.ts`), in their `.mts`, `.cts`, and `.tsx` forms too | ||
| - Storybook stories (`*.stories.ts`, `*.stories.tsx`, …), `.vitepress/`, and `.storybook/` | ||
| - Nuxt 4: `app/pages/`, `app/layouts/`, `app/middleware/`, `app/plugins/`, plus `app/app.config.ts` and `app/router.options.ts` | ||
| - Nitro: `server/api/`, `server/routes/`, `server/middleware/`, `server/plugins/`, `server/tasks/` | ||
|
|
||
| The full lists are in [`ts-no-default-export.yml`](https://github.com/pleaseai/code-style/blob/main/packages/ast-grep-config/rules/typescript/ts-no-default-export.yml) and [`tsx-no-default-export.yml`](https://github.com/pleaseai/code-style/blob/main/packages/ast-grep-config/rules/tsx/tsx-no-default-export.yml). No other rule exempts these paths, except type declarations, which `ts-error-outside-errors-file` and `tsx-error-outside-errors-file` also skip. | ||
|
|
||
| Nuxt 3 root directories (`pages/`, `layouts/`, `middleware/`, and `plugins/` without `app/`) are **not** excluded: a glob such as `**/plugins/**` would also exempt every unrelated directory named `plugins`. ast-grep cannot override a shipped rule's `ignores`, so scope the rules from the command line instead — turn them off in the main scan and run them once more with your framework directories excluded: | ||
|
|
||
| ```bash | ||
| ast-grep scan --off=ts-no-default-export --off=tsx-no-default-export | ||
| ast-grep scan --filter '^(ts|tsx)-no-default-export$' \ | ||
| --globs '!pages/**' --globs '!layouts/**' \ | ||
| --globs '!middleware/**' --globs '!plugins/**' --globs '!app.config.ts' | ||
| ``` | ||
|
|
||
| Put both commands in one package script (for example `lint:structure`) so CI and agents run the same thing. After migrating to the Nuxt 4 `app/` layout, replace the two-step workaround with a single plain `ast-grep scan`. Keeping only the first command would leave both rules turned off for every file. | ||
|
|
||
| <Aside type="caution"> | ||
|
|
||
| Do not add `ast-grep-ignore` comments to silence a rule — they are suppressions that review flags. If a framework requires a default export somewhere else, propose the path for the allowlist in `@pleaseai/ast-grep-config`. | ||
|
|
||
| </Aside> | ||
|
|
||
| ## Compatibility | ||
|
|
||
| - `@ast-grep/cli` `^0.45.3` | ||
| - Node.js `>=22.0.0` | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.