# cckr 🇰🇷

Claude Code 한글 패치 CLI

`/btw` → `/근데`, `/help` → `/도움`, `/compact` → `/압축`

슬래시 커맨드 80개 + UI 텍스트 569개 + ICU locale 자동 한국어화를 패치하는 CLI 도구입니다.

> **최적화: Claude Code `v2.1.110`** · 호환: `v2.1.98` ~ `v2.1.110`

## 왜 만들었나

실 시작은 `/btw` 때문…

`/btw` 치려면 한영 전환하고. btw 하고 다시 한영 전환. 나 옛날사람이라 한영 전환 `cmd + space`… 고거 잠깐 물어볼려고 한영 전환을… 몇 번이나… 아으… **한글 좀 안 되나!?** 어 될 거 같네… 기왕 한 거 다 해?! 그래 다 해보자.

잘됐다, 주변에 클코 추천하고 싶은데 분명 영어울렁증 친구들 있을 거야. 이 한글패치로 도움을 줘보자.

---

> [!WARNING]
> # 🚧 BETA — 아직 실험 단계입니다
>
> **cckr는 Claude Code의 `cli.js` 번들을 직접 패치해서 동작합니다.** Anthropic 공식 i18n이 아니라 문자열 매칭 기반이라, 다음과 같은 일이 생길 수 있습니다:
>
> - **CC 업데이트 시 일부 번역이 영문으로 되돌아갈 수 있음** — Anthropic이 원문을 바꾸면 매칭 실패. `cckr apply -v`로 스킵된 항목 확인 가능.
> - **드물게 CC가 크래시할 수 있음** — 패치가 코드 로직을 건드리면 발생. cckr는 이를 감지해 **5분 내 3회 연속 크래시 시 원본 자동 복원**합니다 (3-layer crash defense).
> - **예상 못한 UI 어긋남** — 어순/공백/말줄임표 같은 소소한 표시 문제.
>
> ### 💡 문제가 생기면
>
> ```bash
> cckr restore              # 원본으로 즉시 복원
> cckr update               # 최신 cckr 설치 + 재패치 (이미 수정됐을 수 있음)
> cckr issue "번역 오타"    # 환경 정보 자동 채워서 GitHub 이슈 페이지 열기
> ```
>
> 버그 / 번역 오타 / 깨진 화면은 `cckr issue` 한 줄이면 환경 정보(cckr 버전, CC 버전, OS, cli.js 경로)까지 자동 포함된 [이슈 페이지](https://github.com/shallwefootball/cckr/issues)가 바로 열립니다. 스크린샷 붙여서 제출만 하면 됩니다.
>
> ### ⚖️ 면책
>
> 본 도구는 개인 프로젝트이며 Anthropic과 무관합니다. Claude Code 라이선스를 위반하지 않는 선에서 문자열 수준 패치만 수행하지만, 사용은 **전적으로 사용자 책임**입니다.

---

## 설치

**nvm 사용 시** (대부분)
```bash
npm i -g claude-code-kr
```

**시스템 Node.js 사용 시** (sudo로 CC 설치한 경우)
```bash
sudo npm i -g claude-code-kr
```

설치하면 자동으로:
1. Claude Code의 빌트인 커맨드에 한글 alias + 한글 설명 추가
2. UI 텍스트 한글화 (권한 대화상자, 도구 표시, 팁, 시간, 토큰 등)
3. CC 업데이트 후 자동 재패치 hook 등록

## 패치 상태 확인

```bash
cckr status
```

```
📍 경로: ~/.nvm/.../cli.js
🇰🇷 패치: 적용됨 ✅
📦 cckr 버전: 0.4.18
🔷 CC 버전: 2.1.110
```

## CLI

```bash
cckr status      # 패치 상태 확인
cckr update      # 최신 버전으로 자동 업데이트 + 재패치
cckr apply       # 한글 패치 적용 (이미 적용됐으면 스킵)
cckr apply -f    # 강제 재적용
cckr apply -v    # 적용 + 스킵된 패치 상세 보기
cckr restore     # 원본 복원
cckr list        # 한글 매핑 목록
cckr -v          # 버전 확인

# 시스템 Node.js 환경
sudo cckr apply
sudo cckr restore
```

### 패치 결과 읽기

```
🎉 70개 커맨드 한글화 완료
✅ 안정 패치: 569/569     ← CC 업데이트에도 유지
⚡ 가변 패치: 39/39       ← regex backreference + locale 패치
🔧 구조 패치: 5/5
```

- **안정 패치** — 정적 문자열 (`lib/locales/ko.json`). CC가 영어 문구를 바꾸지 않는 한 유지됨
- **가변 패치** — regex backreference 또는 ICU locale 변경. 변수명 변경에 강함
- **구조 패치** — autocomplete, tab completion 등 코드 구조 변경

## 업데이트

```bash
npm i -g claude-code-kr@latest     # nvm
sudo npm i -g claude-code-kr@latest  # 시스템 Node.js
```

> **Claude Code 업데이트(`claude upgrade`) 후:**
> SessionStart hook이 자동으로 재패치합니다.
> 적용되지 않으면 `cckr apply` (또는 `sudo cckr apply`)를 실행하세요.

## 제거

```bash
npm uninstall -g claude-code-kr     # nvm
sudo npm uninstall -g claude-code-kr  # 시스템 Node.js
```

원본 자동 복원 + hook 제거.

## 프로젝트 구조

```
claude-code-kr/
├── .github/workflows/
│   ├── ci.yml              # 테스트 + 스모크 테스트 (push/PR)
│   └── daily-check.yml     # 매일 최신 CC 호환성 자동 체크
├── bin/
│   └── cc-kr.js            # CLI 진입점 (cckr 명령어)
├── lib/
│   ├── patcher.js          # 패치 엔진 (string + regex 매칭, 마커 스킵)
│   ├── mappings.js         # 한글 커맨드 매핑 80개
│   ├── hooks.js            # SessionStart hook 관리
│   ├── locales/
│   │   └── ko.json         # 번역 카탈로그 (569개 정적 문자열)
│   └── patches/
│       ├── fragile.js      # regex backreference + ICU locale (39개)
│       └── structural.js   # 코드 구조 변경 (crash hint, tab completion 등, 5개)
├── scripts/
│   ├── postinstall.js      # npm install 시 자동 패치
│   ├── preuninstall.js     # npm uninstall 시 자동 복원
│   └── extract.js          # 번들 AST 파싱 → 번역 후보 추출 (devDep)
├── test/
│   └── patcher.test.js     # 패치 테스트 25개
├── index.js                # 모듈 진입점
├── package.json
├── ARCHITECTURE.md         # 핵심 결정 사항과 이유
├── UPDATE-FLOW.md          # CC 업데이트 자동 대응 플로우
├── TRANSLATION-STATUS.md   # 번역 현황 추적
└── TROUBLESHOOTING.md      # 디버깅 기록
```

- [ARCHITECTURE.md](ARCHITECTURE.md) — 각 결정의 배경과 트레이드오프
- [UPDATE-FLOW.md](UPDATE-FLOW.md) — CC 업데이트 대응, 시나리오별 동작

### 패치 구조

패치를 세 계층으로 관리합니다:

| 계층 | 저장소 | 안정성 | 매칭 방식 | CC 업데이트 시 |
|------|--------|--------|----------|----------------|
| **안정 (stable)** | `lib/locales/ko.json` | 높음 | 정적 문자열 (`"Yes"` → `"네"`) | Anthropic이 영어를 바꿀 때만 깨짐 |
| **가변 (fragile)** | `lib/patches/fragile.js` | 중간 | **regex backreference** (`/return (\w+)\?\`Reading \$\{\1\}\`/`) | 구조가 크게 바뀔 때만 깨짐 |
| **구조 (structural)** | `lib/patches/structural.js` | 낮음 | 큰 코드 블록 (tab completion, autocomplete) | 함수 구조 변경 시 깨짐 |

**안정 패치는 카탈로그 기반**: `ko.json`에 `{"english": "한글"}` 한 줄만 추가하면 끝. regex 작성 불필요.

```json
{
  "\"Do you want to proceed?\"": "\"실행할까요?\"",
  "label:\"Yes\",value:\"yes\"": "label:\"네\",value:\"yes\""
}
```

**가변 패치의 핵심 — regex backreference**:

```js
// Before (변수명 K에 고정 — CC 재빌드 시 K→j로 바뀌면 깨짐)
['return K?`Reading ${K}`:"Reading file"', 'return K?`${K} 읽는 중`:"파일 읽는 중"']

// After (어떤 변수명이든 매칭)
[/return ([\w$]+)\?`Reading \$\{\1\}`:"Reading file"/,
 'return $1?`${$1} 읽는 중`:"파일 읽는 중"']
```

`\1` backreference로 *같은* 변수명이 반복될 때만 매칭. `K`, `j`, `$`, `_` 어떤 minify 결과가 와도 살아남습니다.

### 안전 장치

**적용 단계**
1. **syntax 검증** — `apply()` 후 `node --check`로 패치된 `cli.js`가 파싱되는지 확인. 실패 시 자동으로 `.bak`에서 복원.
2. **출현횟수 가드** — 10회 초과 매칭되는 패턴은 코드 로직 오염 위험으로 판단, 자동 차단. `VERIFIED_SAFE` 화이트리스트(`label:"Yes"` 등)에만 예외.
3. **마커 기반 스킵** — `cli.js.cckr`에 `{ccVersion, cckrVersion}` 저장. 다음 실행 시 값이 같으면 ~140ms로 스킵 (vs 풀 패치 ~25초).
4. **CC 버전 감지** — `apply()` 결과가 `testedCcVersion`과 다르면 경고.

**런타임 방어 (3계층 crash defense)**
1. **Prevention** — 출현횟수 가드가 적용 전에 위험 패턴 차단.
2. **Diagnosis** — `cli.js` 상단에 `process.on("exit", ...)` 핸들러 주입. 비정상 종료 시 stderr로 `[cckr] CC 오류 — cckr restore 로 원본 복원 가능` 안내.
3. **Recovery (auto-restore)** — 5분 내 3회 연속 재패치 시도 감지 시 `.bak`에서 자동 복원. 사용자가 패치 때문에 CC가 크래시하는 걸 몰라도 자가 치유됨.

**CI**
- **일간 호환성 체크** — 매일 09:00 UTC에 최신 CC 설치 → 패치 시도 → 실패하면 GitHub Issue 자동 생성.

## 한글화 범위

### 슬래시 커맨드 (80개)

| 영어 | 한글 | 설명 |
|------|------|------|
| `/btw` | `/근데` | 사이드 질문하기 |
| `/clear` | `/초기화` | 대화 기록 지우기 |
| `/compact` | `/압축` | 대화 요약으로 컨텍스트 확보 |
| `/resume` | `/이어서` | 이전 대화 이어서 하기 |
| `/help` | `/도움` | 도움말 보기 |
| `/diff` | `/변경` | 변경사항 보기 |
| `/plan` | `/계획` | 계획 모드 |
| `/batch` | `/일괄` | 대규모 변경을 병렬 worktree로 |
| `/rewind` | `/되돌리기` | 코드/대화를 이전 시점으로 |
| ... | ... | [전체 목록: `cckr list`] |

> 기존 영어 커맨드는 그대로 동작합니다.

### UI 텍스트

**권한 대화상자**

| 영어 | 한글 |
|------|------|
| `Do you want to proceed?` | `실행할까요?` |
| `Yes` | `네` |
| `No` | `아니요` |
| `Yes, and don't ask again for...` | `네, 다시 묻지 않기:...` |

**권한 모드**

| 영어 | 한글 |
|------|------|
| `⏵⏵ bypass permissions on` | `⏵⏵ 확인 생략 중` |
| `⏵⏵ accept edits on` | `⏵⏵ 수정 허용 중` |
| `(shift+tab to cycle)` | `(shift+tab으로 전환하기)` |

**도구 동작**

| 영어 | 한글 |
|------|------|
| `Reading file` | `파일 읽는 중` |
| `Editing src/index.ts` | `src/index.ts 수정 중` |
| `Searching for pattern` | `pattern 검색 중` |
| `Running command` | `명령어 실행 중` |

**Spinner verb (진행 상태)**

| 영어 | 한글 |
|------|------|
| `Generating…` | `생성 중…` |
| `Running…` | `실행 중…` |
| `Loading…` | `로딩 중…` |
| `Processing…` | `처리 중…` |
| `Consulting the rubber duck…` | `러버덕에게 상담 중…` |
| `Reticulating splines…` | `스플라인 보간 중…` |

**대기 메시지 (응답 늦을 때)**

| 영어 | 한글 |
|------|------|
| `Hmm…` | `음…` |
| `This one needs a moment…` | `잠시만요…` |
| `Working through it…` | `풀어보는 중…` |
| `Cross-referencing seventeen theories…` | `열일곱 가지 이론 교차 검토 중…` |
| `Double-checking the double-checks…` | `재확인을 재확인하는 중…` |
| `Almost there…` | `거의 다 왔어요…` |
| `Still here, still at it…` | `여기 있어요, 계속 중…` |

**도구 요약 (한국어 어순)**

| 영어 | 한글 |
|------|------|
| `Searching for 3 patterns, reading 1 file` | `3개 패턴 검색, 1개 파일 읽는 중` |
| `Listed 1 directory` | `1개 폴더 목록 완료` |

**상태 표시**

| 영어 | 한글 |
|------|------|
| `(34s · ↓ 278 tokens · thinking)` | `(34초 · ↓ 278 토큰 · 생각중)` |
| `thought for 23s` | `23초간 생각함` |
| `Crunched for 2m 27s` | `2분 27초에 걸쳐 처리 완료` |
| `Done (3 tool uses · 1.3k tokens)` | `Done (도구 3회 · 1.3천 토큰)` |

**ICU locale 자동 한국어화** ✨

JavaScript 표준 `Intl.*` API의 locale을 `en-US` → `ko`로 한 줄씩 패치하면, ICU가 모든 표시를 자동으로 한국어로 처리합니다.

**숫자 (compact)**
| 영어 | 한글 | 실제 값 |
|------|------|---------|
| `1.3k` | `1.3천` | 1,300 |
| `13k` | `1.3만` | 13,000 |
| `1.3M` | `130만` | 1,300,000 |
| `100M` | `1억` | 100,000,000 |

**날짜**
| 영어 | 한글 |
|------|------|
| `Mar 15` | `3월 15일` |
| `Friday` | `금요일` |
| `Fri, Mar 15, 2024` | `2024년 3월 15일 (금)` |

**시간**
| 영어 | 한글 |
|------|------|
| `02:30 PM` | `오후 02:30` |
| `3:45 PM` | `오후 3:45` |

**상대 시간**
| 영어 | 한글 |
|------|------|
| `5 minutes ago` | `5분 전` |
| `yesterday` | `어제` |
| `tomorrow` | `내일` |
| `in 1 minute` | `1분 후` |

**가장 효율적인 패치 패턴** — 단 4종류의 locale 변경(`Intl.NumberFormat`, `Intl.RelativeTimeFormat`, `toLocaleString`, `toLocaleDateString`, `toLocaleTimeString`)으로 토큰/파일/날짜/시간/상대시간 표시 전체가 자동 한국어화됩니다. ICU 표준이 알아서 처리하므로 천/만/억 변환 로직, 월 이름, 요일 이름 같은 걸 우리가 짤 필요 없습니다.

**기타**

| 영어 | 한글 |
|------|------|
| `Welcome back!` | `다시 오셨네요!` |
| `Compacting conversation…` | `대화 압축 중…` |
| `Answering…` | `답변 중…` |
| `Showing detailed transcript` | `상세 기록 표시 중` |
| `(ctrl+o to expand)` | `(ctrl+o으로 펼쳐보기)` |
| `Interrupted · What should Claude do instead?` | `중단됨 · 대신 무엇을 할까요?` |

> 전체 번역 현황은 [TRANSLATION-STATUS.md](TRANSLATION-STATUS.md) 참고

## 번역 원칙

**번역하는 것** — 사용자가 읽고 이해해야 하는 UI 텍스트
- 슬래시 커맨드 이름과 설명
- 권한 대화상자 (Yes/No, 실행할까요?)
- 진행 상태 메시지 (읽는 중, 수정 중, 검색 중...)
- 시간/토큰 표시 (34s → 34초, tokens → 토큰)
- 팁 메시지, 도움말, 안내 메시지

**번역하지 않는 것** — 개발자에게 이미 익숙한 기술 용어
- 도구 이름: `Bash`, `Read`, `Edit`, `Write`, `Grep`, `Glob`, `Fetch`, `Agent`
- 프로토콜/시스템: `MCP`, `IDE`, `API`, `git`
- 키보드 단축키: `ctrl+o`, `shift+tab`, `Esc`

## 제한사항

cckr는 **CC의 `cli.js` 안에 박힌 문자열만** 번역합니다. 다음 영역은 다룰 수 없습니다:

| 영역 | 출처 | 대응 |
|------|------|------|
| **Skill 커맨드** (`/commit`, `/review`, `/loop` 등) | `~/.claude/skills/<name>/SKILL.md` 또는 plugin cache의 frontmatter | skill 배포자가 i18n |
| **사용자 settings 커스텀** (`spinnerVerbs.mode: "replace"` 등) | `~/.claude/settings.json` | 사용자가 `mode: "append"`로 바꾸거나 제거 |
| **MCP 서버 응답** | 각 MCP 서버 | 서버 쪽 i18n |
| **plugin 출력** | plugin 코드 | plugin 작성자 i18n |
| **Claude API 응답** | Anthropic API | 시스템 프롬프트로 한글 지시 |
| **외부 도구 출력** (git, npm, jest 등) | 각 도구 | 도구 locale 설정 |

기타 알려진 제한:
- **CC 업데이트 시 가변 패치 깨질 수 있음** — `cckr apply -v`로 스킵된 패치 확인. 안정 패치는 대부분 유지됨.
- **한글 autocomplete** — IME 조합 중에는 자동완성이 트리거되지 않을 수 있음. 조합 완료 후 동작.

## 번역 추가 워크플로우 (contributor)

새 영어 텍스트를 발견하면:

```bash
# 1. 번들에서 해당 텍스트 검색 (AST 컨텍스트 포함)
npm run find "Do you want"

# 출력:
# right: "Do you want to proceed?" ✓        ← 이미 번역됨
# arguments: "Do you want to allow this"    ← 미번역

# 2. lib/locales/ko.json 에 번역 추가
# {
#   "\"Do you want to allow this\"": "\"이 작업을 허용할까요?\""
# }

# 3. 적용
cckr apply --force
```

전체 후보 추출:
```bash
npm run extract
# → lib/locales/candidates.txt 에 1000+ 후보 저장
```

## 원리

Claude Code의 `cli.js` 번들을 문자열 매칭으로 패치합니다:

```js
// before
{name:"btw", description:"Ask a quick side question..."}

// after
{name:"btw", aliases:["근데"], description:"대화 흐름을 끊지 않고 사이드 질문하기"}
```

- 테스트 기준: Claude Code v2.1.98 ~ v2.1.110

## License

MIT
