@pleaseai/ast-grep-config는 코딩 에이전트가 코드베이스를 쉽게 탐색하도록 돕는 ast-grep 규칙 모음입니다. 공개 심볼은 이름으로 찾을 수 있어야 하고, 에러 타입은 지정된 파일에 모으며, 소스 파일 안에 테스트를 두지 않습니다. TypeScript, Dart, Kotlin, Java, Rust에 대해 ADR-0022의 2층(구조 규칙)을 집행합니다.
모든 규칙은 **경고(warning)**로 배포됩니다. 직접 규칙의 심각도를 올리지 않는 한 빌드를 막지 않습니다.
설치
bun add -D @pleaseai/ast-grep-config @ast-grep/clipnpm add -D @pleaseai/ast-grep-config @ast-grep/clinpm install -D @pleaseai/ast-grep-config @ast-grep/cliast-grep 바이너리는 peer dependency인 @ast-grep/cli가 제공합니다. 프로젝트의 bin 경로에 ast-grep이 잡히도록 이 패키지와 함께 설치하세요.
bun을 쓴다면 trustedDependencies에 @ast-grep/cli를 추가해 postinstall 단계가 실행되게 하세요. 그렇지 않으면 ast-grep을 실행할 때마다 대체 경로 경고가 출력됩니다(please-style check는 영향을 받지 않습니다).
{
"trustedDependencies": ["@ast-grep/cli"]
}사용법
프로젝트의 sgconfig.yml이 규칙 디렉터리를 가리키게 합니다.
ruleDirs:
- node_modules/@pleaseai/ast-grep-config/rulesbunx ast-grep scan설정 파일을 따로 두지 않고 패키지의 설정을 바로 쓸 수도 있습니다.
bunx ast-grep scan -c node_modules/@pleaseai/ast-grep-config/sgconfig.yml다섯 가지 원칙
| Slug | 원칙 |
|---|---|
code-greppable-public-symbols |
공개 심볼은 이름 있는 선언으로 정의하고 노출해, 이름 검색 한 번으로 정의와 사용처를 모두 찾는다. |
code-filename-matches-primary-symbol |
공개 심볼이 하나인 파일은 언어의 파일 이름 규약으로 정규화했을 때 그 심볼 이름과 일치한다. |
code-error-types-in-dedicated-module |
모듈의 에러 타입은 지정된 에러 파일이나 패키지에 모은다. |
test-path-derivable-from-source |
테스트는 툴체인이 정한 테스트 루트 아래, 대상 소스 경로를 미러링한 위치에 둔다. |
test-helpers-in-dedicated-location |
여러 테스트가 공유하는 헬퍼는 지정된 위치에 둔다. |
검사는 두 층으로 나뉩니다.
- 2층 — 이 패키지의 ast-grep 규칙으로,
ast-grep scan으로 실행합니다. - 3층 — ast-grep이 보지 못하는 것(파일 이름, 테스트 경로, 헬퍼 공유 여부)을 맡는 경로 검사기
please-style check입니다. 이 패키지의extract/디렉터리에 있는 추출 규칙을 실행합니다.extract/는ruleDirs에 들어 있지 않으므로ast-grep scan출력에는 나타나지 않습니다.
규칙
| 규칙 | Slug | 언어 |
|---|---|---|
ts-no-default-export |
code-greppable-public-symbols |
TypeScript |
tsx-no-default-export |
code-greppable-public-symbols |
TSX |
rust-no-glob-reexport |
code-greppable-public-symbols |
Rust |
ts-error-outside-errors-file |
code-error-types-in-dedicated-module |
TypeScript |
tsx-error-outside-errors-file |
code-error-types-in-dedicated-module |
TSX |
dart-error-outside-errors-file |
code-error-types-in-dedicated-module |
Dart |
kotlin-error-outside-errors-file |
code-error-types-in-dedicated-module |
Kotlin |
java-error-outside-error-package |
code-error-types-in-dedicated-module |
Java |
rust-error-outside-error-file |
code-error-types-in-dedicated-module |
Rust |
ts-no-in-source-test |
test-path-derivable-from-source |
TypeScript |
tsx-no-in-source-test |
test-path-derivable-from-source |
TSX |
규칙마다 옆에 README가 있고, 규칙의 이유, 틀린 예와 올바른 예, 위반을 고치는 단계를 적어 두었습니다(영문). 경고 메시지에 slug와 node_modules 안의 README 경로가 들어 있어 에이전트가 메시지만 보고도 위반을 고칠 수 있습니다.
[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.mddefault export 금지
ts-no-default-export와 tsx-no-default-export는 export default …, export { foo as default }, export { default } from './x'를 잡아냅니다. default import는 가져오는 쪽마다 로컬 이름을 마음대로 정할 수 있어서, 선언 이름으로 검색하면 그런 import 위치를 놓칩니다. named import는 내보낸 이름을 반드시 적어야 합니다.
// 틀린 예
export default class UserService {}
// 올바른 예
export class UserService {}glob 재export 금지
rust-no-glob-reexport는 가시성 수식어(pub, pub(crate), pub(super))가 붙은 use 중 *가 들어간 것을 잡아냅니다. use super::*; 같은 비공개 glob import는 대상이 아닙니다. glob을 지금 내보내는 항목의 명시적 목록으로 바꾸세요.
// 틀린 예
pub use crate::model::*;
// 올바른 예
pub use crate::model::{Account, User};에러 타입은 전용 모듈에
ast-grep에는 타입 정보가 없으므로 에러 규칙은 이름으로 판단합니다. 클래스 기반 언어에서는 상위 타입 이름이 Error 또는 Exception으로 끝나거나, 자신의 이름이 Error 또는 Exception으로 끝나면서 상위 타입도 있는 클래스가 대상입니다.
- TypeScript / TSX:
extends로 지정한 상위 클래스만 확인합니다.implements는 대상이 아니며, 이름이*Error/*Exception인 클래스는extends절이 있을 때만 대상입니다. - Java: 상위 클래스만 확인합니다(
Throwable도 포함).implements는 대상이 아닙니다. - Dart: 상위 클래스 또는 구현한 타입을 확인합니다. 이름이
*Error/*Exception인 클래스는 상위 클래스 또는implements절이 있어야 합니다. - Kotlin: 모든 상위 타입을 확인하며(
Throwable도 포함)class와object선언이 대상입니다.
Rust는 이름이 Error로 끝나는(Exception은 제외) struct/enum, #[derive(…Error)]가 붙은 struct/enum, 그리고 모든 impl Error for T(std::error::Error, core::error::Error 포함)를 잡아냅니다. 에러 타입을 두는 위치는 언어마다 다릅니다.
| 언어 | 에러 타입 위치 | 함께 제외되는 경로 |
|---|---|---|
| TypeScript / TSX | 모듈 디렉터리의 errors.ts |
*.d.ts, *.test.*, *.spec.*, test/, tests/, __tests__/ |
| Dart / Flutter | 라이브러리 디렉터리의 errors.dart |
*_test.dart, test/, integration_test/, test_driver/ |
| Kotlin | 패키지 디렉터리의 Errors.kt |
src/test/, src/testFixtures/, 이름이 Test로 끝나는 소스 세트 |
| Java | 모듈 아래 error/ 하위 패키지 |
src/test/, src/testFixtures/, src/androidTest/ |
| Rust | 모듈 루트 옆 error.rs(또는 error/ 모듈) |
tests/ 아래 통합 테스트 |
검사하는 것은 위치뿐입니다. 에러 파일에 헬퍼나 import가 있어도 됩니다.
소스 내 테스트 금지
ts-no-in-source-test와 tsx-no-in-source-test는 Vitest in-source 테스트(if (import.meta.vitest) { … })를 잡아냅니다. test/** glob으로 찾을 수 없고, 프로덕션 빌드에서 제거하려면 번들러 define이 필요하기 때문입니다. 블록을 패키지 테스트 루트 아래, 소스 경로를 미러링한 테스트 파일로 옮기세요. src/math/add.ts라면 test/math/add.test.ts가 됩니다.
프레임워크 파일
프레임워크가 형태를 정하는 파일은 ts-no-default-export와 tsx-no-default-export의 ignores 목록으로만 제외합니다.
- 타입 선언:
*.d.ts,*.d.mts,*.d.cts - 설정 파일:
*.config.ts와*.config.*.ts(예:vite.config.prod.ts)..mts,.cts,.tsx형태도 포함합니다 - Storybook story(
*.stories.ts,*.stories.tsx등),.vitepress/,.storybook/ - Nuxt 4:
app/pages/,app/layouts/,app/middleware/,app/plugins/, 그리고app/app.config.ts,app/router.options.ts - Nitro:
server/api/,server/routes/,server/middleware/,server/plugins/,server/tasks/
전체 목록은 ts-no-default-export.yml과 tsx-no-default-export.yml에 있습니다. 다른 규칙은 이 경로를 제외하지 않습니다. 단, 타입 선언 파일은 ts-error-outside-errors-file과 tsx-error-outside-errors-file에서도 제외됩니다.
app/ 없이 루트에 pages/, layouts/, middleware/, plugins/를 두는 Nuxt 3 구조는 제외하지 않습니다. **/plugins/** 같은 glob은 이름이 plugins인 무관한 디렉터리까지 모두 제외해 버리기 때문입니다. ast-grep은 배포된 규칙의 ignores를 덮어쓸 수 없으므로 명령줄에서 규칙 범위를 좁히세요. 기본 스캔에서는 두 규칙을 끄고, 프레임워크 디렉터리를 제외한 채 한 번 더 실행합니다.
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'CI와 에이전트가 같은 명령을 실행하도록 두 명령을 하나의 패키지 스크립트(예: lint:structure)에 넣으세요. Nuxt 4의 app/ 구조로 옮기면 이 두 단계 대신 일반 ast-grep scan을 한 번 실행하세요. 첫 번째 명령만 남기면 두 규칙이 모든 파일에서 꺼집니다.
호환성
@ast-grep/cli^0.45.3- Node.js
>=22.0.0