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
7 changes: 6 additions & 1 deletion apps/docs/src/content/docs/en/cli.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -131,10 +131,15 @@ The full canonical rules are shipped per language for AI assistants that prefer
| Flag | Description |
| --- | --- |
| `--yes`, `-y` | Accept defaults and overwrite existing files without prompting |
| `--lang <list>` | Languages for the AGENTS.md rules block, comma-separated (`init`/`doctor`: detected; `update`: the languages already in the block; see below) |
| `--locale <ko\|en>` | Force the CLI locale (defaults to `$LC_ALL` / `$LANG`) |
| `--help`, `-h` | Print help |
| `--version`, `-v` | Print the CLI version |

## Languages

`--lang <list>` selects the programming languages the AGENTS.md rules block links to, for example `--lang typescript,dart`. Accepted values: `typescript`, `dart`, `rust`, `java`, `go`, `python`, `ruby`, `csharp`, `html-css`. Without it, `init` detects languages from marker files in the project root: `package.json` or `tsconfig.json` (typescript), `pubspec.yaml` (dart), `Cargo.toml` (rust), `build.gradle`, `build.gradle.kts` or `pom.xml` (java), `go.mod` (go), `pyproject.toml` (python). Interactive `init` lets you adjust the detected set. `update` keeps the languages the existing block links unless `--lang` is given. An unknown `--lang` value exits with an error (exit code 1) listing the accepted languages. `doctor` reports the detected languages.

## Localisation

The CLI auto-detects your locale from `LC_ALL`, `LANG`, or `LC_MESSAGES` and currently ships Korean and English messages. Override with `--locale ko` or `--locale en`:
Expand All @@ -143,7 +148,7 @@ The CLI auto-detects your locale from `LC_ALL`, `LANG`, or `LC_MESSAGES` and cur
pleaseai-code-style --locale ko init
```

`--lang ko` and `--lang en` still set the locale for now, with a deprecation warning. When both flags are given, `--locale` wins. Any other `--lang` value, or a `--locale` value other than `ko` or `en`, exits with an error (exit code 1). A future release uses `--lang` to select programming languages.
`--lang ko` and `--lang en` are the deprecated locale alias: they still set the locale for now, with a deprecation warning, and select no languages. When both `--lang ko|en` and `--locale` are given, `--locale` wins. A `--locale` value other than `ko` or `en` also exits with an error (exit code 1).
Comment thread
amondnet marked this conversation as resolved.

## CI Usage

Expand Down
7 changes: 6 additions & 1 deletion apps/docs/src/content/docs/ko/cli.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -131,10 +131,15 @@ CLI는 두 마커 주석 사이의 내용 **만** 관리하며 — `AGENTS.md`
| 플래그 | 설명 |
| --- | --- |
| `--yes`, `-y` | 기본값을 수락하고 기존 파일을 확인 없이 덮어씀 |
| `--lang <list>` | AGENTS.md 룰 블록에 넣을 언어, 쉼표로 구분 (`init`/`doctor`: 자동 감지, `update`: 블록에 이미 있는 언어, 아래 참고) |
| `--locale <ko\|en>` | CLI 언어 강제 지정 (기본값은 `$LC_ALL` / `$LANG`) |
| `--help`, `-h` | 도움말 출력 |
| `--version`, `-v` | CLI 버전 출력 |

## 언어

`--lang <list>`는 AGENTS.md 룰 블록이 가리킬 프로그래밍 언어를 고릅니다. 예: `--lang typescript,dart`. 지원 값은 `typescript`, `dart`, `rust`, `java`, `go`, `python`, `ruby`, `csharp`, `html-css`입니다. 옵션이 없으면 `init`이 프로젝트 루트의 마커 파일로 언어를 감지합니다. `package.json` 또는 `tsconfig.json`(typescript), `pubspec.yaml`(dart), `Cargo.toml`(rust), `build.gradle`, `build.gradle.kts`, `pom.xml`(java), `go.mod`(go), `pyproject.toml`(python)이 해당합니다. 대화형 `init`은 감지된 목록을 조정할 수 있게 합니다. `update`는 `--lang`을 주지 않으면 기존 블록이 가리키는 언어를 유지합니다. 알 수 없는 `--lang` 값은 지원하는 언어 목록과 함께 오류로 종료합니다(종료 코드 1). `doctor`는 감지된 언어를 보여줍니다.

## 현지화

CLI는 `LC_ALL`, `LANG`, `LC_MESSAGES`에서 locale을 자동 감지하며, 현재 한국어와 영어 메시지를 제공합니다. `--locale ko` 또는 `--locale en`으로 강제 지정할 수 있습니다:
Expand All @@ -143,7 +148,7 @@ CLI는 `LC_ALL`, `LANG`, `LC_MESSAGES`에서 locale을 자동 감지하며, 현
pleaseai-code-style --locale ko init
```

`--lang ko`와 `--lang en`도 당분간은 로케일을 지정하지만 사용 중단 경고를 출력합니다. 두 플래그를 함께 주면 `--locale`이 우선합니다. 그 밖의 `--lang` 값이나 지원하지 않는 `--locale` 값은 무시되지 않고 오류로 종료합니다(종료 코드 1). 이후 릴리스에서는 `--lang`이 프로그래밍 언어 선택에 쓰입니다.
`--lang ko`와 `--lang en`은 사용 중단된 로케일 별칭입니다. 당분간은 로케일을 지정하며 사용 중단 경고를 출력하고, 언어는 선택하지 않습니다. `--lang ko|en`과 `--locale`을 함께 주면 `--locale`이 우선합니다. 지원하지 않는 `--locale` 값도 오류로 종료합니다(종료 코드 1).

## CI에서의 사용

Expand Down
21 changes: 17 additions & 4 deletions packages/cli/README.ko.md
Original file line number Diff line number Diff line change
Expand Up @@ -220,19 +220,32 @@ CLI는 아래 마커 사이의 내용만 관리합니다 — `AGENTS.md`의 나
| 플래그 | 설명 |
| --- | --- |
| `--yes`, `-y` | 기본값을 수락하고 기존 파일을 확인 없이 덮어씀 |
| `--lang <list>` | AGENTS.md 룰 블록에 넣을 언어, 쉼표로 구분 (`init`/`doctor`: 자동 감지, `update`: 블록에 이미 있는 언어, 아래 참고) |
| `--locale <ko\|en>` | CLI 언어 강제 지정 (기본값은 `$LANG`) |
| `--help`, `-h` | 도움말 출력 |
| `--version`, `-v` | 버전 출력 |

## 언어

`--lang <list>`는 AGENTS.md 룰 블록이 가리킬 프로그래밍 언어를 고릅니다. 예:
`--lang typescript,dart`. 지원 값은 `typescript`, `dart`, `rust`, `java`, `go`,
`python`, `ruby`, `csharp`, `html-css`입니다. 옵션이 없으면 `init`이 프로젝트 루트의
마커 파일로 언어를 감지합니다. `package.json` 또는 `tsconfig.json`(typescript),
`pubspec.yaml`(dart), `Cargo.toml`(rust), `build.gradle`, `build.gradle.kts`,
`pom.xml`(java), `go.mod`(go), `pyproject.toml`(python)이 해당합니다. 대화형 `init`은
감지된 목록을 조정할 수 있게 합니다. `update`는 `--lang`을 주지 않으면 기존 블록이
가리키는 언어를 유지합니다. 알 수 없는 `--lang` 값은 지원하는 언어 목록과 함께 오류로
종료합니다(종료 코드 1). `doctor`는 감지된 언어를 보여줍니다.

## 현지화

CLI는 `LC_ALL` / `LANG` / `LC_MESSAGES`에서 locale을 자동 감지하며, 현재 한국어와
영어 메시지를 제공합니다. `--locale ko` 또는 `--locale en`으로 강제 지정할 수 있습니다.

`--lang ko`와 `--lang en`도 당분간은 로케일을 지정하지만 사용 중단 경고를 출력합니다.
두 플래그를 함께 주면 `--locale`이 우선합니다. 그 밖의 `--lang` 값이나 지원하지 않는
`--locale` 값은 무시되지 않고 오류로 종료합니다(종료 코드 1). 이후 릴리스에서는
`--lang`이 프로그래밍 언어 선택에 쓰입니다.
`--lang ko`와 `--lang en`은 사용 중단된 로케일 별칭입니다. 당분간은 로케일을 지정하며
사용 중단 경고를 출력하고, 언어는 선택하지 않습니다. `--lang ko|en`과 `--locale`을
함께 주면 `--locale`이 우선합니다. 지원하지 않는 `--locale` 값도 오류로
종료합니다(종료 코드 1).

## 라이선스

Expand Down
22 changes: 18 additions & 4 deletions packages/cli/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -404,20 +404,34 @@ JavaScript).
| Flag | Description |
| --- | --- |
| `--yes`, `-y` | Accept defaults, overwrite existing files without prompting |
| `--lang <list>` | Languages for the AGENTS.md rules block, comma-separated (`init`/`doctor`: detected; `update`: the languages already in the block; see below) |
| `--locale <ko\|en>` | Force the CLI locale (defaults to `$LANG`) |
| `--help`, `-h` | Print help |
| `--version`, `-v` | Print version |

## Languages

`--lang <list>` selects the programming languages the AGENTS.md rules block links
to, for example `--lang typescript,dart`. Accepted values: `typescript`, `dart`,
`rust`, `java`, `go`, `python`, `ruby`, `csharp`, `html-css`. Without it, `init`
detects languages from marker files in the project root: `package.json` or
`tsconfig.json` (typescript), `pubspec.yaml` (dart), `Cargo.toml` (rust),
`build.gradle`, `build.gradle.kts` or `pom.xml` (java), `go.mod` (go),
`pyproject.toml` (python). Interactive `init` lets you adjust the detected set.
`update` keeps the languages the existing block links unless `--lang` is given.
An unknown `--lang` value exits with an error (exit code 1) listing the accepted
languages. `doctor` reports the detected languages.

## Localisation

The CLI auto-detects your locale from `LC_ALL` / `LANG` / `LC_MESSAGES` and
currently ships Korean and English messages. Override with `--locale ko` or
`--locale en`.

`--lang ko` and `--lang en` still set the locale for now, with a deprecation
warning. When both flags are given, `--locale` wins. Any other `--lang` value, or
a `--locale` value other than `ko` or `en`, exits with an error (exit code 1). A
future release uses `--lang` to select programming languages.
`--lang ko` and `--lang en` are the deprecated locale alias: they still set the
locale for now, with a deprecation warning, and select no languages. When both
`--lang ko|en` and `--locale` are given, `--locale` wins. A `--locale` value other
than `ko` or `en` also exits with an error (exit code 1).

## License

Expand Down
6 changes: 4 additions & 2 deletions packages/cli/rules.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,5 +14,7 @@ apply to every language, then the guide for the language you are writing:
- [`rules/csharp.md`](./rules/csharp.md) — C#
- [`rules/html-css.md`](./rules/html-css.md) — HTML and CSS

`pleaseai-code-style update` points your `AGENTS.md` block at the general and
TypeScript guides; the other guides are read from this index for now.
`pleaseai-code-style init` and `update` point your `AGENTS.md` block at the
general guide plus the guide of each selected language. Languages are detected
from marker files in the project root, or set with `--lang <list>`; `update`
keeps the languages the existing block links unless `--lang` is given.
32 changes: 20 additions & 12 deletions packages/cli/src/appliers.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import type { Language } from './languages.js'
import type { Tool, ToolApplyResult, ToolContext } from './tools.js'
import { copyFileSync, existsSync, writeFileSync } from 'node:fs'
import { dirname, resolve as joinPath } from 'node:path'
Expand All @@ -10,6 +11,7 @@ import {
writePackageJson,
} from './fs-utils.js'
import { t } from './i18n.js'
import { detectLanguages, languagesFromAgentsBlock, RULES_PREFIX } from './languages.js'

async function confirmOverwrite(file: string, auto: boolean): Promise<boolean> {
if (auto) {
Expand Down Expand Up @@ -136,25 +138,25 @@ async function applyEditorConfig(ctx: ToolContext): Promise<ToolApplyResult> {

// --- AGENTS.md --------------------------------------------------------------

const AGENTS_BODY = `# Passion Factory Code Style
const AGENTS_INTRO = `# Passion Factory Code Style

These rules are managed by \`@pleaseai/code-style\`. Run \`pleaseai-code-style update\`
to refresh this block. Do not edit between the marker comments — your changes
will be overwritten.

- Formatter: \`@pleaseai/eslint-config\` (wraps \`@antfu/eslint-config\`)
`

const AGENTS_TYPESCRIPT = `- Formatter: \`@pleaseai/eslint-config\` (wraps \`@antfu/eslint-config\`)
- No semicolons, single quotes, 2-space indent, trailing commas, LF line endings
- ESM only — never emit \`require\`/\`module.exports\`
- TypeScript: \`strict: true\`, prefer \`type\` over \`interface\`, no implicit \`any\`
- Prefer named exports, early returns, \`async\`/\`await\`, optional chaining
- File size target: ≤ 500 lines
- Tests live under the package's \`test/\` (or \`tests/\`) root, mirroring the source path
(\`src/foo/bar.ts\` → \`test/foo/bar.test.ts\`); no \`import.meta.vitest\` in-source tests
- Conventional Commits for all commit messages
`

For the full rules (what an AI coding assistant needs to know before writing code),
read \`node_modules/@pleaseai/code-style/rules/general.md\` and
\`node_modules/@pleaseai/code-style/rules/typescript.md\`.`
const AGENTS_GENERAL = `- File size target: ≤ 500 lines
Comment thread
amondnet marked this conversation as resolved.
`
Comment thread
amondnet marked this conversation as resolved.

const AGENTS_CODE_ORGANIZATION = `- Code organization (named exports, file names, error files, test paths, shared helpers):
\`node_modules/@pleaseai/ast-grep-config/README.md\`; check with \`ast-grep scan\` and \`please-style check\`
Expand All @@ -179,18 +181,24 @@ function wantsCodeOrganization(ctx: ToolContext): boolean {
}
}

function agentsBody(ctx: ToolContext): string {
return wantsCodeOrganization(ctx)
? AGENTS_BODY.replace('- Conventional', `${AGENTS_CODE_ORGANIZATION}- Conventional`)
: AGENTS_BODY
function agentsBody(ctx: ToolContext, languages: Language[]): string {
const guides = ['general', ...languages].map(id => `\`${RULES_PREFIX}/${id}.md\``)
const pointer = guides.length > 1
? `${guides.slice(0, -1).join(', ')} and ${guides.at(-1)}`
: guides[0]
return `${AGENTS_INTRO}${languages.includes('typescript') ? AGENTS_TYPESCRIPT : ''}${AGENTS_GENERAL}${wantsCodeOrganization(ctx) ? AGENTS_CODE_ORGANIZATION : ''}- Conventional Commits for all commit messages

For the full rules (what an AI coding assistant needs to know before writing code),
read ${pointer}.`
}

export async function applyAgentsMd(ctx: ToolContext): Promise<ToolApplyResult> {
const result: ToolApplyResult = { created: [], updated: [], skipped: [] }
const target = joinPath(ctx.cwd, 'AGENTS.md')
const label = 'AGENTS.md'
const existing = readFileOrNull(target)
const next = upsertMarkerBlock(existing, agentsBody(ctx))
const languages = ctx.languages ?? languagesFromAgentsBlock(existing) ?? detectLanguages(ctx.cwd)
const next = upsertMarkerBlock(existing, agentsBody(ctx, languages))

if (existing == null) {
writeFileSync(target, next)
Expand Down
36 changes: 34 additions & 2 deletions packages/cli/src/commands.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import type { Language } from './languages.js'
import type { Tool, ToolApplyResult, ToolContext } from './tools.js'
import { spawnSync } from 'node:child_process'
import { existsSync } from 'node:fs'
Expand All @@ -12,10 +13,12 @@
readPackageJson,
} from './fs-utils.js'
import { t } from './i18n.js'
import { detectLanguages, LANGUAGES } from './languages.js'

export interface CommandOptions {
cwd: string
autoAccept: boolean
languages?: Language[]
}

function assertProjectRoot(cwd: string): void {
Expand Down Expand Up @@ -49,7 +52,7 @@

// --- init -------------------------------------------------------------------

export async function runInit(opts: CommandOptions): Promise<void> {

Check failure on line 55 in packages/cli/src/commands.ts

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Refactor this function to reduce its Cognitive Complexity from 16 to the 15 allowed.

See more on https://sonarcloud.io/project/issues?id=pleaseai_code-style&issues=AaFpBJUI-atdljJVCPfQ&open=AaFpBJUI-atdljJVCPfQ&pullRequest=69
assertProjectRoot(opts.cwd)
intro(t('appTitle'))

Expand Down Expand Up @@ -94,6 +97,27 @@
.map(id => TOOLS.find(tool => tool.id === id))
.filter((tool): tool is Tool => tool != null)

let languages = opts.languages
if (languages === undefined && selectedTools.some(tool => tool.id === 'agents-md')) {
const detected = detectLanguages(opts.cwd)
if (opts.autoAccept) {
languages = detected
}
else {
const chosen = await multiselect({
message: t('selectLanguages'),
options: LANGUAGES.map(value => ({ value, label: value })),
initialValues: detected,
required: false,
})
if (isCancel(chosen)) {
cancel(t('cancelled'))
process.exit(0)
}
languages = chosen
}
}

// 1. Install packages (de-duped) for selected tools.
const packagesToInstall = Array.from(
new Set(selectedTools.flatMap(tool => tool.packages)),
Expand All @@ -115,7 +139,7 @@
}

// 2. Apply each tool's side-effects.
const ctx: ToolContext = { cwd: opts.cwd, autoAccept: opts.autoAccept, selectedToolIds: selectedTools.map(tool => tool.id) }
const ctx: ToolContext = { cwd: opts.cwd, autoAccept: opts.autoAccept, selectedToolIds: selectedTools.map(tool => tool.id), languages }
const results: ToolApplyResult[] = []
for (const tool of selectedTools) {
results.push(await tool.apply(ctx))
Expand All @@ -130,7 +154,7 @@
export async function runUpdate(opts: CommandOptions): Promise<void> {
assertProjectRoot(opts.cwd)
intro(t('appTitle'))
const result = await applyAgentsMd({ cwd: opts.cwd, autoAccept: true, selectedToolIds: [] })
const result = await applyAgentsMd({ cwd: opts.cwd, autoAccept: true, selectedToolIds: [], languages: opts.languages })
reportResults(result)
log.success(t('agentsBlockUpdated'))
outro(t('done'))
Expand All @@ -156,6 +180,14 @@
log.info(` ${tool.label} — ${suffix}`)
}

if (opts.languages != null) {
log.info(` ${t('doctorSelectedLanguages')(opts.languages.join(', '))}`)
}
else {
const languages = detectLanguages(opts.cwd)
log.info(` ${languages.length > 0 ? t('doctorLanguages')(languages.join(', ')) : t('doctorNoLanguages')}`)
}

// File presence checks.
const files = [
'eslint.config.mjs',
Expand Down
9 changes: 9 additions & 0 deletions packages/cli/src/fs-utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,15 @@ export function buildMarkerBlock(body: string): string {
return `${BEGIN_MARKER}\n${body.trim()}\n${END_MARKER}`
}

export function readMarkerBlock(content: string): string | undefined {
const begin = content.indexOf(BEGIN_MARKER)
const end = content.indexOf(END_MARKER)
if (begin === -1 || end === -1 || end < begin) {
return undefined
}
return content.slice(begin + BEGIN_MARKER.length, end)
}

export function upsertMarkerBlock(existing: string | null, body: string): string {
const block = buildMarkerBlock(body)
if (existing == null) {
Expand Down
Loading
Loading