Metadata-Version: 2.5
Name: token-rpg
Version: 0.18.0
Summary: Claude Code 토큰 사용량으로 성장하는 턴제 RPG
License-Expression: MIT
License-File: LICENSE
Keywords: claude,claude-code,cli,idle-game,rpg,token-usage
Classifier: Environment :: Console
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python :: 3
Classifier: Topic :: Games/Entertainment :: Role-Playing
Requires-Python: >=3.9
Description-Content-Type: text/markdown

# Token RPG

Claude Code에 쓴 토큰이 그대로 캐릭터가 되는 턴제 RPG입니다.

실제로 코딩한 만큼 강해집니다. 출력 토큰은 공격력, 캐시 재사용은 방어력,
thinking 토큰은 치명타율이 됩니다. 버그 벌레부터 루트 권한의 군주까지, 개발자의 적 75종이 던전 보스입니다.

```
$ token-rpg open
Lv.28 코드 술사 🧑‍💻  HP 775 ATK 90 DEF 40.0 CRIT 30.5%  배분 56pt  던전 15개
```

## 설치

```bash
pipx install token-rpg
token-rpg open              # 집계 후 브라우저로 열기 (Ctrl+C 로 종료)
```

의존성은 없습니다. 표준 라이브러리만 씁니다. Python 3.9+ 만 있으면 macOS·리눅스·윈도우에서
같은 명령으로 돕니다 (`uv tool install token-rpg`·`pip install token-rpg` 도 같습니다).

아직 안 나온 최신 커밋을 받고 싶으면 GitHub 주소를 그대로 씁니다.

```bash
pipx install git+https://github.com/YCYEOM/token-rpg
```

## 상주 앱

브라우저 탭을 띄워 두지 않고 늘 켜 두고 싶으면 OS 마다 상주 앱이 있습니다. 둘은 같은 일을
합니다 — 저장 서버를 띄우고, 5분마다 사용량을 다시 집계하고, 아이콘을 누르면 게임을 엽니다.
저장 파일 하나를 브라우저와 함께 쓰므로 어느 쪽으로 해도 진행은 이어집니다.

### 윈도우 — 알림 영역(트레이)

```powershell
token-rpg-tray                  # 알림 영역에 상주 (콘솔 창 없음)
token-rpg-tray --startup on     # 로그인할 때 자동 실행
```

왼쪽 클릭이면 게임 창이 열립니다(Edge 앱 모드 — 주소창 없이 팝오버에 가깝습니다. 없으면 기본
브라우저). 오른쪽 클릭이면 `열기 · 지금 갱신 · 자동 실행 · 종료` 메뉴가 나옵니다.

윈도우 트레이는 맥 메뉴 막대와 달리 아이콘 옆에 글자를 못 답니다. 그래서 레벨과
배지가 툴팁 첫 줄(`Lv.31 49% ⬆`)로 갑니다 — 아이콘에 마우스를 올리면 보입니다.

게임 데이터는 `%LOCALAPPDATA%\token-rpg` 에 둡니다(`token-rpg where` 로 확인).
Stop 훅은 `cmd.exe` 문법으로 등록합니다.

### macOS — 메뉴 막대

`Token RPG.app`은 메뉴 막대에 게임패드 아이콘으로 상주합니다. 아이콘 옆에 레벨과
진행률(`Lv.31 49%`)이 뜨고, 마우스를 올리면 오늘 쓴 토큰·다음 레벨까지 남은 EXP를
보여줍니다. 아이콘을 누르면 팝오버 안에서 게임 전체를 그대로 할 수 있습니다.

배지: `⬆` 레벨이 올랐는데 아직 안 열어 봄 · `⛏` 원정이 가득 참 (수령해야 다시 쌓입니다).
앱은 5분마다 사용량을 다시 집계하므로 Codex·Gemini 사용분도 반영합니다.

받는 곳은 [릴리스 페이지](https://github.com/YCYEOM/token-rpg/releases/latest) —
`Token-RPG-macOS.dmg` 를 받아 안에 든 `Token RPG.app` 을 `Applications` 로 드래그합니다.
새 버전이 나오면 게임 화면의 **업데이트** 버튼이 DMG 를 직접 받아 앱을 갈아끼웁니다
([업데이트](#업데이트) 참고).

직접 빌드하려면 macOS Command Line Tools에서 다음을 실행합니다.

```bash
zsh scripts/build-macos-app.sh
open dist-macos/Token-RPG-macOS.dmg
```

앱은 독립적인 Swift/AppKit UI입니다. 다만 사용량 집계 로직은 번들에 든 `token_rpg.py`로
실행하므로 `python3`가 PATH에 있어야 합니다. 앱이 읽는 것은 로컬 로그뿐이고, 데이터를
외부로 보내지 않습니다.

지금 만드는 DMG는 **서명·공증하지 않은 개발 빌드**입니다. 다른 사람에게 배포하려면
Apple Developer ID로 서명하고 공증해야 Gatekeeper 경고 없이 열 수 있습니다.

## 자동 갱신

```bash
token-rpg install-hook      # Claude Code Stop 훅에 등록
```

이후 Claude Code가 응답을 마칠 때마다 스탯을 자동으로 갱신합니다(백그라운드, 1초 미만).
`token-rpg uninstall-hook`으로 되돌립니다. `~/.claude/settings.json`을 고치기 전에
항상 `.bak` 백업을 남깁니다.

## 게임 구조

**스탯** — 토큰 종류가 캐릭터 빌드를 정합니다. 사용 패턴이 곧 개성입니다.

| 스탯 | 출처 |
|---|---|
| HP | 출력 토큰 (기본 100) |
| ATK | 출력 토큰 |
| DEF | 캐시 읽기. 받는 피해를 **비율로** 깎는다 (보스 ATK 와 같으면 절반) |
| CRIT | thinking 토큰 (토큰만으로 최대 50%, 전체 상한 100% — 넘친 만큼 CDMG로) |
| CDMG | 치명타 피해. 기본 200%, 배분 +1%p/pt, 특성 '파괴의 유산' ×1.12/lv |
| SPD | API 호출 수 (+ 배분 포인트). 보스보다 N배 빠르면 한 턴에 N번 |
| EXP | 입력 + 캐시 생성 + 출력 |

**던전** — 보스 15종이 한 층입니다. 누구 PC에서든 같은 던전이고, 층을 오를수록 보스가
지수로 강해집니다.

**층마다 테마가 다릅니다 (v0.15.0).** 예전에는 2층부터 같은 15종이 능력치만 커져서 다시
나왔습니다. 5층이면 같은 보스를 다섯 번째 보는 셈이었습니다.

| 층 | 테마 | 첫 보스 → 마지막 보스 |
|---|---|---|
| 1 | 코드 버그 | 버그 벌레 → 토큰 한도의 군주 |
| 2 | 인프라 장애 | 타임아웃 거미 → 온콜의 군주 |
| 3 | AI | 오타 프롬프트 임프 → 정렬 실패의 군주 |
| 4 | 회사 | 급한 건 모기 → 분기 실적의 군주 |
| 5 | 보안 | 피싱 낚시꾼 → 루트 권한의 군주 |

6층부터는 처음으로 돌아가 이름 앞에 "변종"이 붙습니다(변종 버그 벌레). 바뀌는 것은 이름과
이모지뿐입니다. 능력치·혼·유물 능력치는 칸 번호를 따르므로 밸런스와 저장은 그대로입니다. 내 스탯은
토큰에 선형으로 크고 보스는 거듭제곱근으로 큽니다. 그래서 막힌 곳은 토큰을 더 쓰면 반드시 넘습니다.

**극초반은 완만합니다 (v0.11.0)** — 예전엔 1스테이지 보스를 잡는 데 누적 200만 토큰이
필요했습니다. 갓 깐 Lv.1 은 ATK 가 0 인데 보스 DEF 가 8 이라 데미지가 한 점도 안 들어갔습니다.
시작조차 못 하고 꺾이는 구간이었습니다. 이제 6스테이지까지 보스 능력치를 눌러 두고 거기서
원래 곡선에 합류합니다 — **토큰 0 으로도 1스테이지는 깹니다.** 레벨 곡선도 저렙만 완만해져
Lv.2 가 9배(5,460 EXP), Lv.10 이 1.8배 빠릅니다. Lv.32 에서 1.18배, Lv.70 위로는 예전과
같고 **Lv.99 총량(=초월 비용)은 그대로**입니다 — 손본 건 극초반뿐입니다.

**초월** — Lv.99 에서 레벨을 1로 되돌리고 다시 올립니다. 레벨은 배분 포인트(2pt/레벨)를
주는데 99에서 막혀, 그 위로는 토큰을 아무리 써도 포인트가 안 늘었습니다. **이미 받은
포인트는 적립해 두고** 레벨과 칭호만 처음으로 돌립니다 — 초월 1회에 198pt 가 굳습니다.
스탯 배분·혼·유물·클리어 기록은 건드리지 않습니다. EXP 는 쓴 토큰이라 줄지 않습니다.
그래서 저장에 적힌 초월 횟수만큼 덜어내고 레벨을 다시 셉니다 (`hero()` 와 JS `lvNow()`
양쪽에 같은 식이 있고, `selftest` 가 표로 붙들어 둡니다).

**환생** — 클리어 기록과 스탯 배분을 버리고 혼을 얻습니다. 혼으로 사는 영구 특성은
배율(×1.12/레벨)이라, 배분 포인트로는 따라갈 수 없는 층 벽을 넘게 해줍니다.
영구 특성은 일곱입니다 — 힘의 유산(ATK ×1.12/레벨), 파괴의 유산(CDMG ×1.12/레벨),
혼의 유산(HP ×1.16/레벨), 신속의 유산(SPD ×1.20/레벨), **벽의 유산(DEF ×1.28/레벨)**,
수확(얻는 혼 +3%), 각성(배분 포인트 +4). 배율이 제각각인 이유는 아래에 적었습니다.

**파괴의 유산은 원래 +5%p 가산이었습니다.** 보스가 스테이지마다 ×1.28 로 곱해지는 곡선이라
가산은 따라가지 못했고, 혼 23,455 를 부어도 도달 스테이지가 9 에서 9 로 그대로였습니다
(같은 혼이면 힘의 유산이 16). 배율로 바꾸니 힘의 유산보다 한 칸 뒤에 서고, CRIT 이
높을수록 좁혀집니다 — 들러리가 아니라 빌드가 고르는 선택이 됐습니다. `selftest` 가
'사면 더 깊이 가고, 힘의 유산과 세 칸 안에 서되 넘지는 않는다'를 붙들고 있습니다.

**상한이 있는 능력치는 영구 특성으로 두지 않습니다** — 되팔 수 없는데 어느 레벨부터
값이 반으로 죽으면 그건 선택이 아니라 함정입니다. 그래서 CRIT(상한 100%)은 토큰·배분
포인트·유물로만 오릅니다. 일곱 다 상한이 없어서 언제 사도 죽지 않고, 선택은 실수를
피하는 문제가 아니라 **무엇을 먼저 사느냐**의 문제가 됩니다.

**DEF 는 받는 피해를 비율로 깎습니다.** `피해 = ATK² ÷ (ATK + DEF)` 입니다. DEF 가 상대
ATK 와 같은 자리수면 절반이고, 아무리 높아도 0 이 되지는 않습니다.

예전에는 그냥 빼기였습니다(`ATK − DEF`). 49스테이지 보스 ATK 가 336만인데 배분을 전부
DEF 에 넣어도 6만이라 피해가 **1.88%** 줄었습니다. 벽의 유산은 0레벨이든 70레벨이든
도달 스테이지가 똑같았습니다. 뚫고 못 뚫고의 벼랑도 있었습니다 — 상대 DEF 를 못 넘으면
타격당 1 피해였습니다. 비율로 바꾸니 둘 다 사라집니다. 지금은 벽 54레벨이면 같은 자리에서
피해가 96.2% 줄고 도달이 53 에서 55 로 갑니다.

**보스보다 N배 빠르면 한 턴에 N번 칩니다.** 소수점은 확률로 한 번 더 칩니다 — 2.5배면
두 번은 확정, 세 번째는 절반입니다. 느리면 선공을 내줍니다(던전 목록에 빨갛게 뜹니다).
던전 목록이 스테이지마다 타격 수를 적어 줍니다. 상한은 없습니다.

상한을 뒀던 적이 있습니다. 효과가 '피해 두 배'에서 멈추니 배율 특성과 겨룰 수가 없었습니다.
힘의 유산 20레벨은 ATK ×9.65 인데 속도는 아무리 올려도 ×2 였습니다. 상한이 곧 천장이고,
천장이 있는 한 속도는 영원히 들러리였습니다. 그래서 없앴습니다.

**특성 배율은 그 스탯이 무엇과 겨루는지에 맞춥니다.** 전부 ×1.12 이던 시절에는 벽과
신속이 죽어 있었습니다. 혼을 얼마를 부어도 도달 스테이지가 그대로라, 사면 손해인
특성이었습니다.

| 유산 | 배율 | 왜 |
|---|---|---|
| 힘 · 파괴 | ×1.12 | 피해에 곱으로 붙습니다. 이걸로 충분합니다 |
| 혼(HP) | ×1.16 | 피해를 견디는 쪽. 벽과 함께 커야 합니다 |
| 신속(SPD) | ×1.20 | 보스 SPD 와의 비율 싸움. 타격 수가 배로 늘어 `STEP` 은 과했습니다 |
| 벽(DEF) | ×1.28 | 보스 ATK 와 1:1 로 맞섭니다. `STEP` 과 같으니 **1레벨이 한 스테이지분**입니다 |

| 특성 레벨 | 0 | 10 | 20 | 30 | 40 | 60 |
|---|---|---|---|---|---|---|
| 힘의 유산 도달 | 10 | 12 | 14 | 16 | 19 | 23 |
| 혼의 유산 도달 | 10 | 12 | 14 | 16 | 19 | 23 |
| 벽의 유산 도달 | 10 | 11 | 13 | 16 | 18 | 22 |
| 파괴의 유산 도달 | 10 | 11 | 13 | 15 | 18 | 22 |
| 신속의 유산 도달 | 10 | 12 | 14 | 16 | 18 | 22 |

다섯이 전 구간에서 한 칸 안에 서고 한 번도 힘의 유산을 넘지 않습니다. `selftest` 가
다섯 전부에 대해 "사면 더 깊이 가고, 힘과 세 칸 안에 서되 넘지 않는다"를 붙들고 있습니다.

**이 표는 영웅 하나(개발자 영웅, 2026-10-07 에 Lv.31)의 값입니다.** 그 특성 하나만 샀을 때입니다. 사용 패턴이 다르면 조금
어긋납니다. v0.14.10 에서 고정 영웅 여섯으로 재 보니 넷이 위 기준에서 벗어났습니다.

| 영웅 | 벗어난 곳 |
|---|---|
| 첫 주 (Lv.9) | 파괴 20레벨이 도달을 못 늘립니다. 환생만으로는 4스테이지에서 안 움직입니다 |
| 많이 씀 (Lv.64) | 벽 60레벨이 31, 힘이 30 — 한 칸 넘습니다 |
| 초월 직전 (Lv.98) | 혼 20레벨이 25, 힘이 24 — 한 칸 넘습니다 |
| 캐시만 쓴 영웅 | 벽 20레벨이 13, 힘이 12. 파괴 20레벨이 도달을 못 늘립니다 |

`selftest` 는 이 넷을 느슨한 기준(힘을 넘어도 한 칸까지, 60레벨이면 도달이 는다)으로 봅니다.
지금보다 더 벌어지면 실패합니다.

SPD 는 **배분 포인트**(+3/pt)로도 올립니다. 배분분에도 특성 배율이 곱해지므로 깊은 층에서도
값을 합니다. 대신 그만큼 ATK 를 포기합니다.

타격이 50회를 넘으면 다 굴리지 않고 한 대 기댓값에 곱합니다. 수천 번을 굴리면 자동 도전이
화면을 멎게 합니다. 전투 로그는 한 턴을 한 줄로 `x132타 → 총 피해` 로 적습니다.

**수확** — 지금 세게 할지, 다음 환생부터 더 많이 벌지. 3%/레벨은 시뮬레이션으로 고른
값입니다. 더 올리면 깊은 층이 일찍 열립니다 (6%면 5층 진입이 19회 → 16회, 8층이 40회 → 31회.
10%면 14회, 25회).
환생 1회에는 **기운** 하나가 듭니다. 기운은 게임을 시작한 뒤 새로 쓴 토큰 100만마다 하나씩,
3개까지 쌓입니다. 그래서 진행 속도가 실제 사용량에 묶입니다 — 하루 150~250만 쓰면
1층을 다 깨는 데 2~3일. 시작 전에 쓴 토큰은 세지 않습니다.

**후반 혼 배율 (v0.14.11, v0.16.0 에서 고침)** — 46스테이지(4층)부터 보스가 환생 때 주는 혼이
스테이지마다 ×1.10 씩 늡니다. 그 전까지 혼은 스테이지 번호의 2.4제곱이었습니다. 특성 비용은 스테이지마다 약 ×1.3 씩
지수로 오르는데 혼은 다항식이라, 5층부터 층마다 환생이 두 배씩 들었습니다.

| 그 층에 드는 환생 | 5층 | 6층 | 7층 | 8층 | 9층 | 10층 | 11층 |
|---|---|---|---|---|---|---|---|
| 예전 | 9 | 20 | 49 | — | — | — | — |
| 지금 | 7 | 7 | 6 | 7 | 8 | 10 | 12 |

개발자 영웅(Lv.31)을 고정해 두고 환생 혼만 센 모델 값입니다. 1~3층은 바뀌지 않습니다.

**보조 수입은 환생이 커진 만큼만 커집니다 (v0.16.0).** 원정·미션·혼 사냥·슬롯·유물 중복·황금 개체는
"최고 스테이지 보스 몇 판치"로 정해져 있습니다. 그 한 판의 값을 무엇으로 잡느냐가 후반을 가릅니다.

| 한 판의 값 | 깊은 층에서 보조 수입 ÷ 환생 수입 | 5~9층에 드는 환생 |
|---|---|---|
| 후반 배율을 그대로 (v0.14.11) | 1.4, 최대 2.0 — 환생보다 많이 법니다 | 3 · 4 · 3 · 4 · 4 |
| 배율 없이 | 6층 0.1, 8층부터 0.01 아래 — 버려집니다 | 3 · 5 · 5 · 6 · 7 |
| **환생이 커진 만큼만 (지금)** | 0.6 에서 0.4 로 천천히 줄어듦 (최대 1.0 → 0.6) | 4 · 3 · 4 · 5 · 6 |

들어오는 혼을 전부 넣고 잰 값입니다(개발자 영웅, 보통 수준의 보조 수입). v0.14.11 은 환생 혼만 센 모델로
골랐고, 보조 수입이 환생을 넘어서는 것을 놓쳤습니다. 환생이 버는 혼은 1스테이지부터의 합이라, 배율이 붙으면
최고 스테이지 22판치에서 8판치로 줄어듭니다. 보조 수입의 판수는 그대로였습니다.

지금은 환생 한 번이 "보조 수입용 한 판"으로 몇 판치인지가 배율 없던 시절과 같습니다. 그래서 놀 거리가
후반에도 버려지지 않고, 환생이 주 수입으로 남습니다. 위 표의 "지금" 줄(7 · 7 · 6 · 7 · 8)보다 실제가 빠른
것은 그 표가 환생 혼만 세기 때문입니다.

×1.10 은 잰 값입니다. ×1.08 이면 8층부터 다시 느려지고(14회), ×1.12 부터는 뒤로 갈수록 빨라져
끝없이 오릅니다. `selftest` 가 둘을 붙들고 있습니다 — 환생 혼만 센 모델에서 "5~9층이 층당 4~12회",
보조 수입 최대치와 황금 개체까지 넣은 모델에서 "6~9층이 층당 3~12회, 7~10층의 보조 수입이 환생의 30% 이상 100% 미만".

**원정** — 역대 최고로 깊이 간 스테이지를 자동 반복해 혼을 캡니다. 최대 8시간까지
쌓이고, 수령 이후 새로 쓴 토큰이 생산 배율이 됩니다(최대 3배).
**환생해도 멈추지 않습니다** — 기준이 이번 회차 진행이 아니라 역대 최고 기록이고,
쌓여 있던 미수령분도 그대로 남습니다.

**자동 도전** — 첫 환생 후 해금하고, **켜진 채로 시작합니다**. 지금 능력치로 이길 수 있는
다음 스테이지를 1초에 하나씩 연출 없이 깹니다. 더 못 오르면 멈추지 않고 이번 판 가장 깊은
스테이지를 계속 반복해 유물을 캡니다. 진 스테이지로는 능력치가 바뀔 때까지 다시 오르지
않습니다. 켜 둔 채 환생하면 직전 배분을 그대로 다시 걸어 목표까지 알아서 올라갑니다.

스테이지를 골라 돌리려면 `눌러서 고르기` 를 펼칩니다. 역대 클리어한 스테이지를 고르면
거기까지만 오르고 그곳을 반복합니다. 평소에는 접혀 있어서 스테이지가 늘어도 화면이
밀리지 않습니다.

**층 단위로도 고릅니다 (v0.17.3).** 칸들이 층마다 묶여 있고, 층 이름이 적힌 머리줄을 누르면 그 층에서
깬 스테이지가 통째로 들어갑니다. 다시 누르면 그 층만 빠집니다. 여러 층을 같이 골라도 되고, 층을 고른 뒤
칸 하나씩 빼도 됩니다. 황금 개체를 한 층씩 모을 때 열다섯 번을 누르지 않아도 됩니다.

**미션** — 게임 안 행동이 아니라 **실제 사용량**으로 채웁니다. 초기화 주기별로 나눠
보여줍니다 — 일일은 자정에, 주간은 월요일에 바뀝니다.

일일은 오늘 토큰 T·2T·3T 세 단이고(AI 툴을 여럿 쓰면 "오늘 2개 이상"이 하나 더 붙습니다),
주간은 5일 사용과 주간 토큰 5T입니다. 기준 T 는 지난 14일 평균의 절반이라 사용량에 맞춰집니다.
연속 사용일마다 보상 +10%(최대 7일).

보상 총합은 하루치·한 주치로 **고정**입니다(`DAY_BUDGET`·`WEEK_BUDGET`, 단위는 최고
스테이지 보스 격파 몇 번분). 그날의 미션들이 가중치로 나눠 갖습니다. 미션을 더 쪼개도 수입이
늘지 않습니다. 쉬운 단은 적게 주므로 하루치를 다 받으려면 3단까지 가야 합니다.
환생이 주 수입원으로 남도록 `selftest` 가 미션 주간 수입을 환생 수입과 견줘 상한을 지킵니다.

**주간 레이드 (v0.17.0)** — 탑과 별개로 매주 월요일에 레이드 보스 하나가 섭니다. HP 는 **이번 주에
실제로 쓴 토큰**으로만 깎입니다. 스탯과 전투는 관계없습니다 — 탑이 막힌 주에도 할 일이 남습니다.

| | 값 |
|---|---|
| 열리는 때 | 16스테이지(2층 첫 보스)를 깬 뒤 |
| 보스 HP | 지난 4주의 주간 사용량 평균 (쓴 주만 셉니다). 하한 100만 토큰 |
| 단계 보상 | HP 의 25·50·75·100% 를 깎을 때마다 혼 (최고 스테이지 2판치씩, 한 주에 8판치) |
| 격파 보상 | 위 혼에 더해 가진 유물 하나가 한 등급 오릅니다 |
| 보스 | 여섯이 주마다 돌아갑니다 (월요일의 거신 → 분기 마감의 용 → …) |

평소대로 쓰면 주말쯤 잡습니다. 주가 바뀌면 남은 HP 와 상관없이 다음 보스로 넘어가고, 안 받은 보상은
사라집니다. 진행도는 로그에서 계산한 값이라 저장을 고쳐도 바뀌지 않습니다.

**격파하면 가진 유물 가운데 하나가 한 등급 오릅니다 (v0.17.1).** 일반 → 희귀 → 영웅 → 전설 → 신화
순서이고, 신화가 아닌 유물 중에서 무작위로 고릅니다. v0.17.0 은 등급을 새로 굴렸습니다. 열에 여섯은
일반이라, 유물을 모은 뒤로는 거의 혼으로 바뀌었습니다 — 한 주를 채워 잡은 보상이 빈손이었습니다.
올릴 것이 없을 때도 버려지지 않습니다. 유물이 하나도 없으면 하나를 주고, 전부 신화면 최고 스테이지
한 판치 혼을 줍니다. 등급의 천장은 그대로입니다 — 15칸 전부 신화까지 레이드만으로 많아야 60주입니다.

**1층에서 열리지 않는 이유.** 1층에서는 주간 보조 수입(미션·혼 사냥·슬롯)이 이미 상한(환생의 2배)에
닿아 있어 레이드 몫을 얹을 자리가 없습니다. 16스테이지부터는 상한 안입니다. `selftest` 가 16스테이지부터
180스테이지까지 한 칸도 건너뛰지 않고 봅니다. 연속 사용 배율은 레이드에 붙지 않습니다 — 레이드가 이미
한 주의 사용량을 재기 때문입니다. 환생 사이 보조 수입의 최대치는 21.6판치에서 22.2판치가 됩니다(+2.6%).

**혼 사냥** — 직접 손으로 버는 유일한 칸입니다. 왕복하는 표식을 과녁에서 멈춥니다.
과녁 안의 **금색 띠**가 한가운데(x1.5)이고, 보라 띠 안이면 중심에 가까울수록 더 줍니다.
벗어나면 0입니다. 멈춘 자리에 표식이 남아(한가운데 금색·명중 초록·빗나감 빨강)
얼마나 어긋났는지 %p 로 보여준 뒤 다음 발이 출발합니다. 한 판은 **5발**이고 **맞힐수록**
표식이 빨라집니다(첫 발 2.4초 왕복, 명중마다 x1.18 — 다 맞히면 마지막 발 1.25초).
빗나가면 속도는 그대로입니다 — 못 맞히는 사람에게 벌로 더 어려워지지 않습니다.
스테이지를 하나 깨면 열리고 하루 3판, 자정에 초기화합니다. 시작하는 순간 한 판이 빠지므로
불리한 발을 새로고침으로 무를 수 없습니다. 보상은 역대 최고 스테이지를 따라 오릅니다.

미션과 마찬가지로 하루 예산이 **고정**이라(`MINI_BUDGET`) 아무리 잘해도 진행 속도는
흔들리지 않습니다 — 실력은 수입의 상한이 아니라 그 상한을 채우는 속도만 바꿉니다.
`selftest` 가 미션과 함께 묶어 환생 수입과 견줍니다.

**슬롯** — 3x3 릴, 가로 셋·세로 셋·대각선 둘까지 여덟 줄. 칸은 왼쪽부터 차례로 서고,
같은 문양이 한 줄에 셋이면 혼이 붙습니다(🪙x4 · 🐛x6 · 🐍x9 · 🦇x15 · 🗿x30 · 🐉x90 · 💎x300).
여덟 줄 합쳐 **세 판 중 한 판꼴로 맞고**(실측 31.6%) 한 판 평균은 x2.42 입니다.
세로는 실제 슬롯이라면 라인이 아니지만(릴 하나가 보여주는 창일 뿐입니다) 3x3 격자를 보면
누구나 세로도 셉니다 — 화면이 말하는 것과 규칙이 어긋나면 그건 규칙이 틀린 겁니다.

혼 사냥이 실력으로 버는 칸이라면 여기는 운으로 버는 칸입니다. 잘 하고 못 하고가 없으니
하루 판수(`SLOT_TRIES`, 10판)만 주고, 지급을 평균 배당으로 나눠 **하루 기대 수입을
`SLOT_BUDGET`(1 격파분)에 못박아** 뒀습니다 — 운은 얼마를 버느냐가 아니라 언제 받느냐만 바꿉니다.
실측 20만 일로 하루 평균 0.997 격파분, 열 판 모두 꽝인 날은 2.2% 입니다.
스테이지를 하나 깨면 열리고, 돌리는 순간 한 판이 빠지며 자정에 초기화합니다.
하루 몫을 다 써도 버튼은 잠기지 않습니다 — 혼만 안 들어오는 **연습판**으로 계속 돌아갑니다.
돌리는 재미까지 하루 예산에 묶을 이유는 없습니다.

`selftest` 가 문양표(`SLOT_SYM`)의 확률 합을 100%로, `SLOT_AVG` 를 그 표에서 다시 계산한
평균 배당으로 붙들고, 슬롯 수입을 미션·혼 사냥과 묶어 환생 수입과 견줍니다. 이 상한 때문에
`SLOT_BUDGET` 은 1 이 한계입니다 — 2 로 올리면 1층에서 미션 주간 수입이 환생의 2배를 넘습니다.

**유물** — 보스가 가끔 자기 유물을 떨어뜨립니다(역대 첫 격파 30%,
재격파 1%). 반복 파밍으로 나온 중복은 혼으로 조금(1/20)만 바뀝니다 — 재격파 확률을
두 배로 올린 만큼 환산을 절반으로 낮췄습니다. 도감만 빨리 차고 켜 두기만 해서 버는 혼은 그대로입니다.
등급은 일반 60%·희귀 28%·영웅 10%·전설 1.6%·**신화 0.4%**이고 오를 때마다 효과가 두 배입니다
(ATK·HP·DEF·혼 +3/6/12/24/48%, CRIT +0.5/1/2/4/8%p). 보스마다 하나만 가지며 더 높은 등급이
나와야 바뀝니다. 환생해도 남습니다.

**어떤 능력치가 붙을지는 칸마다 고정입니다** — 무작위인 것은 등급뿐입니다. 어느 층이든
1번 칸 보스는 ATK, 2번 칸 보스는 CRIT 유물을 떨어뜨립니다. 유물은 칸마다 하나라 모두 15개이고,
도감은 지금 층에서 그 칸을 지키는 보스의 번호와 이름으로 적습니다 — 던전 목록과 짝이 맞습니다. ATK·HP·DEF·CRIT·혼
다섯 종을 15칸에 3개씩 나눠 층 앞뒤로 흩어 놨으니, 원하는 빌드에 맞춰 어디를 먼저
깰지 고르면 됩니다. 던전 목록과 유물 도감 양쪽에 무엇이 나올지 적혀 있습니다.

아래는 1층 이름입니다. 다른 층은 같은 칸의 보스가 같은 능력치를 줍니다.

| | 보스 (1층) |
|---|---|
| ATK | 버그 벌레 · 스파게티 크라켄 · 스택 오버플로 히드라 |
| HP | 레거시 전갈 · 메모리 누수 슬라임 · 프로덕션 장애 드래곤 |
| DEF | 널 포인터 박쥐 · 데드락 골렘 · 기술 부채 리치 |
| CRIT | 무한 루프 뱀 · 머지 충돌 도깨비 · 레이스 컨디션 유령 |
| 혼 | 좀비 프로세스 · 의존성 지옥 악마 · 토큰 한도의 군주 |

**변이와 변이 조각 (v0.18.0)** — 변종 층(6층~)의 보스는 층마다 특수한 능력 하나를 갖습니다. 예전에는
6층부터 이름 앞에 "변종"만 붙고 1~5층과 똑같았습니다.

| 층 | 변이 | 능력 |
|---|---|---|
| 6 | 🛡️ 철갑 | 내가 주는 피해 ÷3 |
| 7 | ☠️ 저주 | 내 최대 HP ÷3 |
| 8 | 💢 광폭 | 보스 ATK ×1.75 |
| 9 | 🗡️ 관통 | 내 DEF ÷4 |
| 10 | 🧊 무감각 | 내 치명타 피해 ÷3 |

다섯 층마다 되풀이하고, 11층부터는 두 겹입니다(÷3 이 ÷9 가 됩니다).

**변이 조각으로 지웁니다.** 변종 층의 보스를 이길 때마다 2% 로 변이 조각이 나옵니다. 반복 전투가 주된
길입니다. 조각으로 그 변이의 내성을 올리면 배수가 줄고, 10레벨이면 한 겹이 사라집니다. 내성 한 겹은
조각 975개, 반복 전투로 켜 둔 채 13.5시간쯤입니다. 조각과 내성은 환생해도 남습니다.

| 조각을 캐는 정도 (보통 수준의 영웅) | 6~10층에 드는 환생 | 12층에 닿는 회차 |
|---|---|---|
| 변이 없음 (v0.17.4) | 6 · 5 · 6 · 7 · 9 | 63 |
| 안 캔다 | 6 · 6 · 8 · 8 · 10 | 76 |
| 하루 1시간 | 6 · 6 · 7 · 8 · 10 | 72 |
| 하루 4시간 | 6 · 6 · 6 · 8 · 8 | 65 |
| 하루 종일 | 6 · 5 · 6 · 8 · 9 | 64 |

**조각은 변이를 지우는 데만 씁니다.** 다 모아도 변이가 없던 때보다 빨라지지 않습니다. 반복 전투는 토큰이
안 드는 시간이라, 덤이 생기면 켜 두기만 해서 환생 기운 제한을 돌게 됩니다. `selftest` 가 "내성을 아무리
올려도 변이가 없을 때보다 쉬워지지 않는다"를 붙들고 있습니다. 안 캐도 막히지는 않습니다 — 느려질 뿐입니다.
다만 두 겹이 되는 11층부터는 차이가 커집니다.

다섯 변이의 세기는 "최적 배분의 여유가 1/3 로 준다"에 맞췄습니다. 관통과 무감각은 빌드를 탑니다 — DEF 나
치명타에 기대지 않는 빌드는 가볍게 지나갑니다.

**턴을 세는 능력(재생·선제 같은)은 넣지 않았습니다.** 재 보니 깊은 층의 전투는 두 턴 안에 끝납니다
(막히는 자리에서 격파 0.2~1.7턴). 턴을 세는 규칙은 아무 일도 안 하거나 층을 통째로 막았습니다.

**보스 도감과 황금 개체 (v0.16.0)** — 보스를 처음 이기면 도감 윗줄에 찍힙니다. 싸울 때마다 0.1%
확률로 그 보스의 **황금 개체**가 대신 나옵니다. 이름 앞에 "황금"이 붙고 능력치는 같습니다.
이기면 도감 아랫줄에 찍힙니다. 자동 반복과 수동 도전 모두 해당합니다.

| | 값 |
|---|---|
| 출현 확률 | 0.1% — 자동 반복(1초에 한 판)을 켜 두면 17분에 한 번꼴 |
| 처음 잡을 때 | 그 스테이지 혼 한 판치 (보조 수입용 값) |
| 황금 한 칸 | 얻는 혼 +0.5% (영구) |
| 한 층의 황금 15종 | 배분 포인트 +4 (영구) |
| 전부(75종) | 얻는 혼 +37.5%, 배분 +20pt |

**이미 잡은 황금은 다시 잡아도 혼을 주지 않습니다.** 자동 반복이 1초에 한 판이라, 주면 켜 두기만
해도 혼이 쌓여 환생 기운 제한을 돕니다. 유물 중복을 1/20 로 묶어 둔 것과 같은 이유입니다.
그래서 혼 보상은 칸마다 한 번이고, 남는 것은 영구 보너스입니다. 한 층 15종은 한 칸씩 골라
가며 잡으면 켜 둔 채 네 시간쯤, 15칸을 한꺼번에 돌리면 열네 시간쯤 듭니다.
6층부터 나오는 변종은 같은 칸을 씁니다 — 도감은 75종이 끝입니다. 6층은 1층 줄, 7층은 2층 줄에 찍히고,
도감 카드가 지금 층이 어느 줄인지 표시합니다.

**처음 잡을 때 보상이 한 판치인 이유.** 5배로 넣고 재 보니 처음 한 번만 줘도 5층·6층이 환생
2~3회에 열렸습니다(기준은 층당 4~12회). 한 층에 황금이 15칸이라, 환생 한 번 사이에 환생 다섯 번치
혼이 들어왔습니다. 한 판치면 5~9층이 층당 4~7회로 기준 안입니다. `selftest` 가 하루 종일 켜 두고
값이 큰 칸부터 잡는 경우로 이 기준을 붙들고 있습니다.
도감이 없던 저장은 이미 깬 스테이지의 보스를 본 것으로 찍어 줍니다.

**환생 보너스** — 환생할 때마다 얻는 혼(환생·원정·미션·유물 중복)이 영구히 +2%씩 늡니다.
10회면 +20%, 25회면 +50%. 혼 배수는 환생·유물·수확·도감 넷이 곱해지므로, 캐릭터 카드 아래
`얻는 혼 x1.34 (환생 +2% · 유물 +6% · 수확 +24%)` 줄에 합쳐서 보여 줍니다.

**시작점** — 설치한 날부터 셉니다. 이미 몇 달 치 로그가 쌓여 있으면 깔자마자 고레벨로
시작해 성장이 통째로 사라지기 때문입니다. 처음 실행할 때 기준을 정하고 `config.json` 에
남깁니다. 이미 쓰던 설치(스냅샷이나 저장이 남아 있는 설치)는 과거를 그대로 지킵니다.

```bash
token-rpg since              # 지금 기준 보기
token-rpg since all          # 예전 기록까지 전부 세기
token-rpg since 2026-01-01   # 특정 날짜부터
```

세션 파일 단위로 거르므로 기준일을 걸친 세션 하나는 통째로 셉니다.

**누적은 지워지지 않습니다** — Claude Code 는 30일 지난 대화 로그를 스스로 지웁니다
(`cleanupPeriodDays`). 그래서 v0.14.6 부터 세션 파일별 합계를 `ledger.json` 장부에 적어 두고,
로그가 사라져도 장부 값으로 계속 셉니다. 장부가 생기기 전에 이미 지워진 로그는 되살릴 수 없습니다.

## 업데이트

새 버전이 있으면 게임 화면 맨 위에 알림이 뜹니다. **업데이트** 버튼을 누르면 깔린 방식
(`uv tool`·`pipx`)을 알아서 찾아 올립니다. 끝나면 창을 다시 열면 됩니다.

```bash
token-rpg update        # 터미널에서도 같은 일을 합니다
```

메뉴 막대 앱도 같은 버튼입니다. 누르면 릴리스의 DMG 를 직접 받아 앱을 갈아끼우고, 앱이
잠깐 닫혔다 다시 뜹니다. 앱 폴더를 고칠 권한이 없거나 DMG 를 못 받으면 릴리스 페이지를
엽니다 — 그때는 받아서 `Applications` 에 덮어쓰면 됩니다. 터미널의 `token-rpg update` 는
앱 사본을 건드리지 않고 받을 주소만 알려 줍니다.

버전 확인은 GitHub 릴리스 API 한 번이고, **파이썬 쪽에서 하고 결과를 60초 재사용합니다**
(게임 페이지가 직접 바깥으로 나가지 않습니다). 보내는 것은 버전 문자열뿐이고 사용량·로그는
어디로도 나가지 않습니다. 끄려면 `config.json` 에 `"updateCheck": false` 를 넣습니다.

## 여러 PC 합산

각 PC에서 `token-rpg export`를 돌리면 4KB짜리 스냅샷만 남습니다. 스냅샷 폴더를 클라우드
동기화 폴더로 지정하면 모든 기기가 합쳐집니다. 양쪽 OS 에서 같은 폴더를 가리키면 됩니다.

```bash
# macOS · 리눅스 (~/.zshrc 나 ~/.bashrc 에)
export TOKEN_RPG_SNAPSHOTS=~/Dropbox/token-rpg
```
```powershell
# 윈도우 — setx 는 새로 여는 창부터 적용됩니다
setx TOKEN_RPG_SNAPSHOTS "$env:USERPROFILE\Dropbox\token-rpg"
```

지정한 뒤 각 PC 에서 `token-rpg export` 를 한 번 돌리면 그 폴더에 스냅샷이 생깁니다.
기존 `snapshots` 폴더에 있던 파일은 새 폴더로 옮깁니다 (`token-rpg where` 로 위치 확인).

**사용량은 알아서 합칩니다.** PC 마다 `<호스트이름>.json` 을 따로 쓰고 합산할 때 전부
더하므로, 파일당 PC 하나라 충돌이 구조적으로 없습니다. 여러 PC 에서 동시에 코딩해도 됩니다.

**게임 진행은 한 번에 한 PC 에서만 합니다.** `game.save` 는 파일 하나를 기기끼리 같이 씁니다.
한 PC 안에서는 브라우저 탭과 상주 앱이 `rev` 번호로 서로를 막아 줍니다(오래된 창이
덮어쓰려 하면 거부하고 최신 저장을 불러옵니다). 다른 PC 끼리는 서로의 `rev` 를 볼 수 없습니다.
두 기기에서 동시에 켜 두면 동기화 서비스가 충돌 사본을 만들거나 늦게 쓴 쪽이 덮어씁니다.
한쪽에서 게임 창과 상주 앱을 닫고 동기화가 끝난 뒤 다른 쪽을 열면 됩니다.

**진행 저장은 봉인해서 적습니다.** `game.save` 는 v0.10.0 부터 `base64(JSON).서명` 한 줄이라
텍스트 편집기로 열어 혼·환생·배분을 고칠 수 없습니다. 서명이 맞지 않으면 불러오지 않습니다.
쓰던 설치는 처음 갱신할 때 자동으로 봉인하니 따로 할 일은 없습니다 — **다만 이 파일을 같이 쓰는
설치본은 전부 v0.10.0 이상이어야 합니다.** 한 PC 안에서도 설치본이 여러 개일 수 있으니
(`uv tool`·`pip`·맥 앱 번들) `token-rpg update` 를 각각 돌려야 합니다.

스냅샷(`snapshots/*.json`)도 봉인해서 쓰지만 **평문도 받아 줍니다.** 옛 설치본의 훅이 평문으로
덮어쓰는 일이 흔한데 거기서 거부하면 그 PC 토큰이 0 이 되기 때문입니다. 스냅샷은 매번 진짜
로그에서 다시 만들므로 손대도 다음 갱신에 덮어씁니다.

열쇠가 소스 안에 있어 작정하면 위조할 수 있습니다. 막는 대상은 "파일 열어서 0 하나 더 붙이기"입니다.

## 명령

| 명령 | 하는 일 |
|---|---|
| `token-rpg` / `build` | 사용량 재집계 후 `game.html` 갱신 |
| `status` | 현재 스탯을 JSON 으로 출력 (상주 앱이 읽습니다) |
| `open` | 갱신 후 로컬 서버(`127.0.0.1:8765`)로 브라우저에서 열기. Ctrl+C로 종료 |
| `serve` | 게임과 저장만 제공 (메뉴 막대 앱이 띄웁니다) |
| `export` | 이 PC의 스냅샷만 갱신 |
| `balance` | 난이도·환생 곡선 표 출력 |
| `selftest` | 집계·병합·밸런스·게임 화면 자체 검증 |
| `where` | 데이터 위치 출력 |
| `update` | 새 버전 확인 후 업그레이드 |
| `since [all\|now\|YYYY-MM-DD]` | 언제부터의 토큰을 셀지 보기/바꾸기 |
| `install-hook` / `uninstall-hook` | 자동 갱신 등록/해제 |
| `providers` | 프로바이더 목록과 스캔 위치 |
| `scan add\|remove <프로바이더> <폴더>` | 추가 스캔 폴더 등록/해제 |
| `enable` / `disable <프로바이더>` | 프로바이더 켜기/끄기 |

## 데이터

`~/.claude/projects/**/*.jsonl`의 `usage` 필드만 읽습니다. Codex·Gemini CLI 를 쓰면
[프로바이더](#프로바이더) 표의 위치도 같은 방식으로 읽습니다. **읽기 전용이고,
아무것도 밖으로 보내지 않습니다.** 게임 데이터는
`~/.local/share/token-rpg/`(또는 `$XDG_DATA_HOME`)에 저장합니다. 진행 상황은 스냅샷 폴더의
`game.save` 파일 하나에 두고, 브라우저와 상주 앱이 같이 씁니다. 서버 없이 `game.html` 을
파일로 직접 열었을 때만 그 브라우저의 localStorage 에 둡니다.

## 검증

```bash
python token_rpg.py selftest
```

파이썬 쪽 집계·병합·밸런스를 보고, 이어서 게임 화면을 실제로 돌립니다.

밸런스는 고정 영웅 여섯(`BALANCE_HEROES` — 첫 주·보통·많이 씀·초월 직전·출력만·캐시만)으로
늘 봅니다. 이 PC 에 사용 기록이 있으면 그 영웅으로도 한 번 더 봅니다. 예전에는 이 PC 의
영웅 하나로만 봤고, 기록이 없는 CI 에서는 밸런스 검증과 그 뒤의 검사가 통째로 빠졌습니다.

화면과 전투는
`token_rpg.py` 안의 JS 인데, 파이썬과 같은 식이 두 벌이라 한쪽만 고치면 어긋납니다.
`tests/game_smoke.js` 가 가짜 DOM 위에 그 스크립트를 올리고 한 바퀴 돕니다 — 배분, 전투,
슬롯, 혼 사냥, 미션, 원정, 환생, 자동 도전, 특성 구입, 저장 코드, 초월, 옛 저장 이관까지.

| 보는 것 | 잡는 것 |
|---|---|
| 예외가 안 난다 | 선언 순서, 없는 id, 오타 (v0.14.4 는 화면이 통째로 비었습니다) |
| 그린 글자에 NaN·undefined 가 없다 | 없는 상수를 읽는 계산 (v0.14.5 의 NaN 레벨) |
| 파이썬과 값이 같다 | 보스·레벨·특성 비용·최종 스탯·벽 스테이지 |

`node` 가 있어야 돕니다. 없으면 알리고 건너뛰며, CI 에서는 실패합니다. 깔린 사본에는
`tests/` 가 없어 이 단계가 없습니다. 브라우저가 아니라서 배치와 CSS 는 보지 못합니다.

## 프로바이더

여러 AI 툴의 사용량을 한 캐릭터로 합산합니다.

```bash
token-rpg providers                          # 목록과 스캔 위치
token-rpg scan add codex '~/backup/*/sessions'   # 로그가 기본 위치 밖일 때
token-rpg disable codex                      # 특정 프로바이더 끄기
```

| 프로바이더 | 기본 위치 | 상태 |
|---|---|---|
| `claude-code` | `~/.claude/projects` | 검증됨 |
| `codex` | `~/.codex/sessions` | 검증됨 (codex cli 0.153.4) |
| `gemini` | `~/.gemini/tmp` | 검증됨 (gemini cli 0.59.0) |

Codex CLI는 `cached_input_tokens`·`reasoning_output_tokens`를 남겨 DEF·CRIT까지
그대로 대응합니다. `token_count` 이벤트의 `total_token_usage`는 세션 누적이라
파일마다 마지막 값만 셉니다.

Gemini CLI는 텔레메트리 없이도 세션 로그(`chats/session-*.jsonl`)의 답변마다
`tokens`(input·output·cached·thoughts)를 남깁니다. 답변 단위라 전부 더하고,
`cached`는 DEF, `thoughts`는 CRIT로 대응합니다.

**웹에서 쓴 것은 잡히지 않습니다.** ChatGPT·Gemini 웹, Cursor, GitHub Copilot은
토큰 집계를 서버에서만 하고 로컬에 숫자를 남기지 않습니다. CLI 툴을 설치해서
써야 기록이 생깁니다.

새 툴을 붙이려면 `PROVIDERS`에 "파일 하나를 읽어 토큰 합계를 돌려주는 함수"
하나만 추가하면 됩니다. 또는 스냅샷 JSON을 직접 뱉어도 됩니다:

```json
{"host": "내PC", "updated": "2026-09-10T00:00:00+00:00",
 "agg": {"input": 0, "output": 0, "cache_read": 0, "thinking": 0, "calls": 0},
 "projects": {"프로젝트명": 0}, "days": ["2026-09-10"]}
```

## 라이선스

MIT
