Skip to content
Draft
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
15 changes: 15 additions & 0 deletions .github/workflows/release-please.yml
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ jobs:
code-style-released: ${{ steps.release.outputs['packages/cli--release_created'] }}
ast-grep-config-released: ${{ steps.release.outputs['packages/ast-grep-config--release_created'] }}
editorconfig-released: ${{ steps.release.outputs['packages/editorconfig--release_created'] }}
bun-lint-config-released: ${{ steps.release.outputs['packages/bun-lint-config--release_created'] }}
steps:
- uses: actions/create-github-app-token@64ab729a6294000f5aa4a4bc0b73d1f32bc45510 # v3.3.0
id: app-token
Expand Down Expand Up @@ -167,6 +168,20 @@ jobs:
npm publish pleaseai-editorconfig-*.tgz --provenance --access public
fi

- name: Publish @pleaseai/bun-lint-config
if: ${{ !cancelled() && (github.event_name == 'workflow_dispatch' || needs.release-please.outputs.bun-lint-config-released == 'true') }}
working-directory: packages/bun-lint-config
run: |
VERSION=$(node -p "require('./package.json').version")
if [ "$VERSION" = "0.0.0" ]; then
echo "⚠ @pleaseai/bun-lint-config has not been released yet (0.0.0), skipping"
elif npm view "@pleaseai/bun-lint-config@$VERSION" version 2>/dev/null; then
echo "⚠ @pleaseai/bun-lint-config@$VERSION already published, skipping"
else
bun pm pack
npm publish pleaseai-bun-lint-config-*.tgz --provenance --access public
fi

# No build step: the package ships YAML rules and READMEs as-is.
- name: Publish @pleaseai/ast-grep-config
id: publish-ast-grep-config
Expand Down
3 changes: 2 additions & 1 deletion .release-please-manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,6 @@
"packages/perttier-config": "0.1.0",
"packages/cli": "0.1.1",
"packages/ast-grep-config": "0.1.0",
"packages/editorconfig": "0.0.2"
"packages/editorconfig": "0.0.2",
"packages/bun-lint-config": "0.0.0"
}
2 changes: 2 additions & 0 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ Monorepo providing shared code style configurations for PleaseAI projects.
| `@pleaseai/prettier-config` | `packages/perttier-config` | none (JSON only) |
| `@pleaseai/editorconfig` | `packages/editorconfig` | none (static file) |
| `@pleaseai/ast-grep-config` | `packages/ast-grep-config` | none (ast-grep YAML rules) |
| `@pleaseai/bun-lint-config` | `packages/bun-lint-config` | none (committed, generated `lint.toml`) |

## Commands

Expand All @@ -36,6 +37,7 @@ Monorepo providing shared code style configurations for PleaseAI projects.
- `packages/eslint-config/src/package-json.ts` exports `eslint-plugin-package-json` configs
- Root `eslint.config.ts` dogfoods `@pleaseai/eslint-config`
- `packages/ast-grep-config` holds the ADR-0022 (engineering-standards) layer-2 ast-grep rules in `rules/<lang>/<id>.yml` (each with a sibling `<id>.md` README, rule tests in `rule-tests/`) and the layer-3 extraction rules in `extract/` (never in `ruleDirs`); `@ast-grep/cli` is a peer. Run `bun run test` in the package (`ast-grep test` + the e2e sgconfig test)
- `packages/bun-lint-config` ships `lint.toml`, the `bunfig.toml` `[lint]` tables generated from `@pleaseai/eslint-config` (`canonicalPluginNames: true`) by `bun run generate` (`src/generate.ts`), keeping only the rules in `builtin-rules.json` (plus the rules `src/rule-map.ts` maps onto a native rule, whose target the source owns), a committed snapshot of `bun lint`'s native rules (`BUN_LINT_BIN=<canary bun> bun run update-rules`). A test fails when `lint.toml` is stale, so regenerate after changing eslint-config. The CLI's `bun-lint-config` tool writes it into `bunfig.toml` as a marker block
- `packages/cli/src/check/` is the `please-style check` path checker (layer 3). It resolves the `@ast-grep/cli` binary from the checked project first, then from the CLI's own install (`src/check/ast-grep.ts`), and the `extract/` rules from the CLI's own `@pleaseai/ast-grep-config` copy first (the project's copy is a last resort). `@pleaseai/ast-grep-config` is a regular `dependency` of the CLI; `@ast-grep/cli` is an optional peer of both packages (never a `dependency`, so installs do not download the native binary), installed explicitly only when the user selects the ast-grep tool. Tests live in `packages/cli/test/` mirroring `src/`, shared helpers in `test/test-utils/` (the CLI dogfoods its own rule)

## Code Style
Expand Down
9 changes: 9 additions & 0 deletions README.ko.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ PleaseAI 프로젝트를 위한 공유 코드 스타일 설정 모노레포 —
| [`@pleaseai/prettier-config`](./packages/perttier-config) | 공유 Prettier 설정 (JSON) |
| [`@pleaseai/editorconfig`](./packages/editorconfig) | 일관된 에디터 설정을 위한 공유 `.editorconfig` |
| [`@pleaseai/ast-grep-config`](./packages/ast-grep-config) | 에이전트가 탐색하기 쉬운 코드 배치를 위한 ast-grep 규칙 (ADR-0022). 경로 검사기는 `please-style check` |
| [`@pleaseai/bun-lint-config`](./packages/bun-lint-config) | `@pleaseai/eslint-config`의 규칙 가운데 `bun lint`가 네이티브로 실행하는 규칙을 담은 `bunfig.toml`의 `[lint]` 테이블 |

## `@pleaseai/eslint-config`

Expand Down Expand Up @@ -79,6 +80,14 @@ bunx ast-grep scan

모든 규칙은 경고(warning)로 배포됩니다. 규칙 목록과 위반을 고치는 방법은 [ast-grep Config 가이드](https://code-style.pages.dev/ko/ast-grep-config)를 참고하세요.

## `@pleaseai/bun-lint-config`

```sh
bunx @pleaseai/code-style init # bun-lint-config 선택
```

`init`은 `bun lint`(Bun canary)용으로 패키지의 `lint.toml`을 `bunfig.toml`에 씁니다. 포함 범위와 직접 복사하는 방법은 [bun lint Config 가이드](https://code-style.pages.dev/ko/bun-lint-config)를 참고하세요.

## 개발

로컬에서 저장소를 설정하고 빌드·린트하는 방법은 [CONTRIBUTING.md의 Getting started](./CONTRIBUTING.md#getting-started)(영문)를 따르세요.
Expand Down
9 changes: 9 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ See the [code-style documentation site](https://code-style.pages.dev) for full g
| [`@pleaseai/prettier-config`](./packages/perttier-config) | Shared Prettier config (JSON) |
| [`@pleaseai/editorconfig`](./packages/editorconfig) | Shared `.editorconfig` for consistent editor settings |
| [`@pleaseai/ast-grep-config`](./packages/ast-grep-config) | ast-grep rules for agent-navigable code (ADR-0022); the path checker is `please-style check` |
| [`@pleaseai/bun-lint-config`](./packages/bun-lint-config) | `bunfig.toml` `[lint]` tables with the `@pleaseai/eslint-config` rules that `bun lint` runs natively |

## `@pleaseai/eslint-config`

Expand Down Expand Up @@ -79,6 +80,14 @@ bunx ast-grep scan

Every rule ships as a warning. See the [ast-grep Config guide](https://code-style.pages.dev/en/ast-grep-config) for the rule list and how to fix each violation.

## `@pleaseai/bun-lint-config`

```sh
bunx @pleaseai/code-style init # select bun-lint-config
```

`init` writes the package's `lint.toml` into `bunfig.toml` for `bun lint` (Bun canary). See the [bun lint Config guide](https://code-style.pages.dev/en/bun-lint-config) for what it covers and how to copy it by hand.

## Development

To set up the repo, build, and lint locally, follow [Getting started in CONTRIBUTING.md](./CONTRIBUTING.md#getting-started).
Expand Down
69 changes: 69 additions & 0 deletions apps/docs/src/content/docs/en/bun-lint-config.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
---
title: "bun lint Config"
description: "The @pleaseai/eslint-config rules that bun lint runs natively, as bunfig.toml [lint] tables."
sidebar:
order: 6
---
`@pleaseai/bun-lint-config` provides the rules of `@pleaseai/eslint-config` that [`bun lint`](https://bun.com/docs/lint) runs natively, as the `[lint]` tables of a `bunfig.toml`. The package ships one file, `lint.toml`, generated from the ESLint config.

`bun lint` is only in Bun canary builds for now. bunfig.toml has no `extends`, so the tables are copied into your project's `bunfig.toml`.

## What it covers

The generator keeps:

- the rules Bun has built in: ESLint core, `@typescript-eslint`, `unicorn`, `import`, and `node` (`eslint-plugin-n`), with their options
- the file scoping of the ESLint config, as `[[lint.overrides]]` for TypeScript files, tests, scripts, `.d.ts`, config files, and so on
- the global ignores, as `ignorePatterns`
- rules that have a native equivalent under another name, mapped onto it (see below)

What is left out:

- plugins Bun does not run natively, apart from the rules mapped below: stylistic (`style/*`), `regexp`, `jsdoc`, `antfu`, `perfectionist`, `unused-imports`, `eslint-comments`, `command`, and `e18e`
- JSON, YAML, TOML, and Markdown, which `bun lint` does not lint
- formatting: the package configures `[lint]` only, not `[fmt]`

Bun's own default rules stay on even where `@pleaseai/eslint-config` does not enable them: 14 ESLint core rules (such as `no-constant-condition`, `for-direction`, `no-useless-escape`, and `no-unsafe-optional-chaining`), the `bun:test` rules in files that import `bun:test`, and the React rules when `react` is a dependency. So `bun lint` can report a little more than ESLint.

## Mapped rules

`src/rule-map.ts` maps a rule that `bun lint` has no native version of onto the native rule that does the same, and the generator writes it under the native name, with the same severity, options, and file scoping:

- antfu's `test/*` (vitest) rules onto `vitest/*`: `consistent-test-it`, `no-identical-title`, `no-import-node-test`, `prefer-hooks-in-order`, `prefer-lowercase-title`, and `no-only-tests` as `vitest/no-focused-tests`
- `unused-imports/no-unused-vars` onto `@typescript-eslint/no-unused-vars`
- the `style/jsx-*` rules onto `react/jsx-*`: `closing-bracket-location`, `closing-tag-location`, `curly-brace-presence`, `curly-newline`, `curly-spacing`, `equals-spacing`, `first-prop-new-line`, `indent-props`, `max-props-per-line`, `one-expression-per-line`, and `tag-spacing`
- `antfu/no-top-level-await` onto `n/no-top-level-await`
- `e18e/prefer-array-some`, `prefer-date-now`, `prefer-regex-test`, and `prefer-object-has-own` onto `unicorn/prefer-array-some`, `unicorn/prefer-date-now`, `unicorn/prefer-regexp-test`, and `prefer-object-has-own`

A mapped rule owns its target: the ESLint config's own entries for the target are dropped (it turns `@typescript-eslint/no-unused-vars` off in TypeScript files, for example), and the generator fails if one of them is not `off`. `jsx-wrap-multilines` is not mapped, because Bun rejects its `propertyValue` option.

The mapped rules are close to the ESLint ones, not identical:

- the vitest rules need an import from `vitest`; in a file that imports `bun:test`, Bun runs its own `bun:test` rules instead
- findings can start at a different column: `no-import-node-test` points at the module name, `no-identical-title` at the title, `prefer-array-some` at `filter`, and `prefer-regexp-test` at the regular expression
- Bun runs `no-unused-vars` and `@typescript-eslint/no-unused-vars` as one rule, so the mapped `unused-imports/no-unused-vars` owns `no-unused-vars` too and its options apply in every file; the core rule, which ESLint also runs in JavaScript files, is not written
- the `react/jsx-*` rules run without `react` as a dependency, because the config turns them on explicitly

## Usage

Run the CLI and select **bun-lint-config**:

```bash
bunx @pleaseai/code-style init
```

`init` installs the package and writes `lint.toml` into `bunfig.toml` between `# >>> @pleaseai/bun-lint-config` and `# <<< @pleaseai/bun-lint-config` comments. Run `init` again after an upgrade to refresh the block; the rest of `bunfig.toml` is kept. If `bunfig.toml` already sets lint options outside the block, `init` leaves the file alone and asks you to remove them first.

To copy it by hand, append the file to `bunfig.toml` and keep the tables at the end of the file, since a key after them belongs to the last table:

```bash
bun add -D @pleaseai/bun-lint-config
cat node_modules/@pleaseai/bun-lint-config/lint.toml >> bunfig.toml
```

`bun --config=node_modules/@pleaseai/bun-lint-config/lint.toml lint` is not the same: `--config` replaces `bunfig.toml` instead of adding to it.

## Running bun lint

- A `lint` script in `package.json` shadows `bun lint`. Run `bun lint --no-script`, or make the script `bun lint`.
- Do not use this next to an `eslint.config.*` file. Next to an ESLint config, `bun lint` reads that config and applies the `[lint]` keys on top of it, so pick one of the two.
7 changes: 5 additions & 2 deletions apps/docs/src/content/docs/en/cli.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,9 @@ An optional `code-organization.json` can only **add** names — extra TypeScript
| editorconfig | `@pleaseai/editorconfig` | `.editorconfig` |
| agents-md | — | `AGENTS.md` (marker-managed block) |
| ast-grep | `@pleaseai/ast-grep-config`, `@ast-grep/cli` | `sgconfig.yml` |
| bun-lint-config | `@pleaseai/bun-lint-config` | `bunfig.toml` `[lint]` (marker-managed block) |

`init --yes` applies every tool except **bun-lint-config**, which is opt-in: `bun lint` is an alternative to ESLint, not an addition to it, so select it yourself in the interactive `init`.

## The `AGENTS.md` Rules Block

Expand Down Expand Up @@ -130,7 +133,7 @@ The full canonical rules list is shipped as `node_modules/@pleaseai/code-style/r

| Flag | Description |
| --- | --- |
| `--yes`, `-y` | Accept defaults and overwrite existing files without prompting |
| `--yes`, `-y` | Accept defaults (every tool except the opt-in bun-lint-config) and overwrite existing files without prompting |
| `--lang <ko\|en>` | Force the CLI locale (defaults to `$LC_ALL` / `$LANG`) |
| `--help`, `-h` | Print help |
| `--version`, `-v` | Print the CLI version |
Expand All @@ -151,7 +154,7 @@ Combine `--yes` with a locale override for a fully non-interactive invocation su
pleaseai-code-style --yes --lang en init
```

This accepts defaults for every tool, overwrites any existing config files, and uses English output.
This applies every tool except the opt-in bun-lint-config, overwrites any existing config files, and uses English output.

## Binaries

Expand Down
6 changes: 6 additions & 0 deletions apps/docs/src/content/docs/en/index.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,12 @@ ast-grep rules that keep a codebase navigable for coding agents.

</Card>

<Card title="bun lint Config" icon="ph:lightning" href="/en/bun-lint-config">

The ESLint config rules that `bun lint` runs natively, for `bunfig.toml`.

</Card>

<Card title="CLI" icon="ph:terminal" href="/en/cli">

One-command setup for eslint, prettier, editorconfig, and the `AGENTS.md` rules block.
Expand Down
69 changes: 69 additions & 0 deletions apps/docs/src/content/docs/ko/bun-lint-config.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
---
title: "bun lint Config"
description: "@pleaseai/eslint-config의 규칙 가운데 bun lint가 네이티브로 실행하는 규칙을 담은 bunfig.toml의 [lint] 테이블."
sidebar:
order: 6
---
`@pleaseai/bun-lint-config`는 `@pleaseai/eslint-config`의 규칙 가운데 [`bun lint`](https://bun.com/docs/lint)가 네이티브로 실행하는 규칙을 `bunfig.toml`의 `[lint]` 테이블로 제공합니다. 이 패키지는 ESLint 설정에서 생성한 `lint.toml` 파일 하나만 배포합니다.

`bun lint`는 아직 Bun canary 빌드에만 있습니다. bunfig.toml에는 `extends`가 없으므로 테이블을 프로젝트의 `bunfig.toml`에 복사해서 씁니다.

## 포함 범위

생성기는 다음을 유지합니다.

- Bun에 내장된 규칙: ESLint 코어, `@typescript-eslint`, `unicorn`, `import`, `node`(`eslint-plugin-n`)와 그 옵션
- ESLint 설정의 파일 범위: TypeScript 파일, 테스트, 스크립트, `.d.ts`, 설정 파일 등에 대한 `[[lint.overrides]]`
- 전역 ignore: `ignorePatterns`
- 이름은 다르지만 네이티브 대응 규칙이 있는 규칙: 대응 규칙으로 매핑(아래 참고)

다음은 포함하지 않습니다.

- Bun이 네이티브로 실행하지 않는 플러그인(아래에서 매핑한 규칙 제외): stylistic(`style/*`), `regexp`, `jsdoc`, `antfu`, `perfectionist`, `unused-imports`, `eslint-comments`, `command`, `e18e`
- `bun lint`가 검사하지 않는 JSON, YAML, TOML, Markdown
- 포매팅: 이 패키지는 `[fmt]`가 아니라 `[lint]`만 설정합니다.

`@pleaseai/eslint-config`가 켜지 않는 규칙이라도 Bun이 기본으로 켜는 규칙은 그대로 켜져 있습니다. ESLint 코어 규칙 14개(`no-constant-condition`, `for-direction`, `no-useless-escape`, `no-unsafe-optional-chaining` 등), `bun:test`를 import하는 파일의 `bun:test` 규칙, `react`가 의존성에 있을 때의 React 규칙이 그렇습니다. 그래서 `bun lint`는 ESLint보다 조금 더 많이 보고할 수 있습니다.

## 매핑한 규칙

`src/rule-map.ts`는 `bun lint`에 같은 이름의 네이티브 규칙이 없지만 같은 일을 하는 네이티브 규칙이 있는 경우, 그 규칙으로 매핑합니다. 생성기는 심각도, 옵션, 파일 범위를 그대로 두고 네이티브 이름으로 기록합니다.

- antfu의 `test/*`(vitest) 규칙을 `vitest/*`로: `consistent-test-it`, `no-identical-title`, `no-import-node-test`, `prefer-hooks-in-order`, `prefer-lowercase-title`, 그리고 `no-only-tests`는 `vitest/no-focused-tests`로
- `unused-imports/no-unused-vars`를 `@typescript-eslint/no-unused-vars`로
- `style/jsx-*` 규칙을 `react/jsx-*`로: `closing-bracket-location`, `closing-tag-location`, `curly-brace-presence`, `curly-newline`, `curly-spacing`, `equals-spacing`, `first-prop-new-line`, `indent-props`, `max-props-per-line`, `one-expression-per-line`, `tag-spacing`
- `antfu/no-top-level-await`를 `n/no-top-level-await`로
- `e18e/prefer-array-some`, `prefer-date-now`, `prefer-regex-test`, `prefer-object-has-own`을 각각 `unicorn/prefer-array-some`, `unicorn/prefer-date-now`, `unicorn/prefer-regexp-test`, `prefer-object-has-own`으로

매핑한 규칙이 대상 규칙을 소유합니다. 대상 규칙에 대한 ESLint 설정의 자체 항목은 버리고(예: TypeScript 파일에서 `@typescript-eslint/no-unused-vars`를 끄는 항목), 그 항목 중 `off`가 아닌 것이 있으면 생성기가 실패합니다. `jsx-wrap-multilines`는 Bun이 `propertyValue` 옵션을 거부하므로 매핑하지 않습니다.

매핑한 규칙은 ESLint 규칙과 비슷하지만 똑같지는 않습니다.

- vitest 규칙은 `vitest`에서 import하는 파일에서 동작합니다. `bun:test`를 import하는 파일에서는 Bun이 자체 `bun:test` 규칙을 실행합니다.
- 보고 위치(열)가 다를 수 있습니다. `no-import-node-test`는 모듈 이름, `no-identical-title`은 제목, `prefer-array-some`은 `filter`, `prefer-regexp-test`는 정규식을 가리킵니다.
- Bun은 `no-unused-vars`와 `@typescript-eslint/no-unused-vars`를 하나의 규칙으로 실행하므로, 매핑한 `unused-imports/no-unused-vars`가 `no-unused-vars`도 소유하고 모든 파일에서 그 옵션이 적용됩니다. ESLint가 JavaScript 파일에서 함께 실행하는 코어 규칙은 쓰지 않습니다.
- `react/jsx-*` 규칙은 설정이 명시적으로 켜므로 `react`가 의존성에 없어도 실행됩니다.

## 사용법

CLI를 실행하고 **bun-lint-config**를 선택합니다.

```bash
bunx @pleaseai/code-style init
```

`init`은 패키지를 설치하고 `lint.toml`을 `bunfig.toml`의 `# >>> @pleaseai/bun-lint-config`와 `# <<< @pleaseai/bun-lint-config` 주석 사이에 씁니다. 업그레이드한 뒤 `init`을 다시 실행하면 블록이 갱신되고, `bunfig.toml`의 나머지는 그대로 유지됩니다. 블록 밖에 이미 lint 설정이 있으면 `init`은 파일을 건드리지 않고 그 설정을 먼저 지우라고 안내합니다.

직접 복사하려면 파일을 `bunfig.toml` 끝에 덧붙이고, 테이블을 파일의 맨 끝에 두세요. 테이블 뒤에 오는 키는 마지막 테이블에 속하게 됩니다.

```bash
bun add -D @pleaseai/bun-lint-config
cat node_modules/@pleaseai/bun-lint-config/lint.toml >> bunfig.toml
```

`bun --config=node_modules/@pleaseai/bun-lint-config/lint.toml lint`는 같은 방법이 아닙니다. `--config`는 `bunfig.toml`에 더하는 것이 아니라 `bunfig.toml`을 대신합니다.

## bun lint 실행

- `package.json`에 `lint` 스크립트가 있으면 `bun lint`가 그 스크립트를 실행합니다. `bun lint --no-script`로 실행하거나 스크립트를 `bun lint`로 바꾸세요.
- `eslint.config.*` 파일과 함께 쓰지 마세요. ESLint 설정이 있으면 `bun lint`는 그 설정을 읽고 그 위에 `[lint]` 키를 적용하므로, 둘 중 하나만 사용하세요.
Loading
Loading