# 🧙‍♂️ Sari (사리)

> **"잠시 내 말 좀 들어보게나... 자네의 소스코드가 지옥의 비명을 지르는 소리를!"** (Stay awhile and listen...)

**사리(Sari)**는 인공지능(AI) 친구들이 여러분의 복잡하고 거대한 코드를 아주 쉽고 빠르게 이해할 수 있도록 도와주는 **'호라드림의 수석 기록관'**이에요.

사리 선생님만 계시면 아무리 얽히고설킨 코드라도 AI가 길을 잃지 않고 필요한 클래스를 0.1초 만에 찾아낼 수 있답니다.  
호라드림의 촛불이 꺼지지 않는 한, 인덱싱 누락이라는 혼돈의 비명은 들리지 않게 될 거예요. 🚀 (선생님이 지팡이로 길을 아주 상세히 안내해주신답니다.)

---

## 🧐 사리 선생님은 누구인가요? (쉽게 이해하기)

여러분의 컴퓨터에는 아주 많은 코드 파일이 있어요. 똑똑한 **AI 친구(Codex, Claude, Cursor, Gemini 등)**에게 코드를 짜달라고 하면 가끔 이런 말을 할 거예요.
*"미안해, 파일이 너무 많아서 어디에 뭐가 있는지 모르겠어!"*

그때 바로 **사리 선생님**이 트리스트럼 어딘가에서 마법처럼 나타납니다!

1.  **지독한 사서**: 사리 선생님은 여러분의 모든 코드를 미리 다 읽어두고, 누가 어느 지옥 구석에 사는지(어떤 함수가 어떤 파일에 있는지) 아주 상세한 **'호라드림 장부'**를 만들어둬요. (눈이 침침하셔도 정규식은 기가 막히게 보십니다.)
2.  **AI의 길잡이**: AI 친구가 "이 프로젝트에서 회원가입은 어떻게 해?"라고 물어보면, 사리 선생님이 지팡이를 짚고 장부를 슥 보고는 "3번 선반 아래, 디아블로의 꼬리 옆에 있는 `user.py` 파일을 보게나! 주석 좀 똑바로 달지 그랬나..."라고 꾸짖으며 알려줍니다.
3.  **MCP(Model Context Protocol)**: 이건 AI 친구와 사리 선생님이 서로 대화할 때 쓰는 **'호라드림 통역기'** 같은 거예요. 이 통역기 덕분에 사리 선생님은 세상의 모든 최신 AI와 대화할 수 있답니다! (고대어는 몰라도 Python은 꿰고 계시죠.) 🤝

---

## 🌟 사리 선생님의 특별한 능력

- **⚡ 차원문 검색**: 수만 줄의 코드도 순식간에 읽어서 필요한 부분만 골라내요. (TP 타는 속도보다 빠릅니다.)
- **🧠 코드 심령술**: 단순히 글자만 찾는 게 아니라, 이게 '함수'인지 '클래스'인지 코드의 영혼(AST)을 읽어냅니다.
- **🔒 철통 보안**: 모든 공부는 여러분의 컴퓨터 안에서만 해요. 코드가 성역(인터넷) 밖으로 절대 나가지 않으니 안심하세요! 지옥의 악마도 여러분의 소스코드는 못 훔쳐갑니다. 🛡️
- **👻 투명 망토**: 백그라운드에서 조용히 일하며 여러분이 코드를 고칠 때마다 장부를 알아서 업데이트해요. (가끔 계신지 확인하지 않으면 섭섭해하십니다.)

---

## 🚀 성역 소환 주문 (설치 방법 - Installation)

터미널(Terminal)을 열고 아래 마법 주문을 딱 한 줄만 복사해서 붙여넣고 엔터(Enter)를 누르세요!  
이 명령어는 **최초 설치**뿐만 아니라, **새로운 워크스페이스 연동**에도 똑같이 사용됩니다.

```bash
# macOS / Linux (유닉스의 축복을 받은 자들)
curl -fsSL https://raw.githubusercontent.com/BaeCheolHan/sari/main/install.py | python3 - -y

# Windows (파워쉘의 마법사들)
irm https://raw.githubusercontent.com/BaeCheolHan/sari/main/install.py | python - -y
```

### 📖 호라드림의 설치 계시 (How it works)
사리 선생님의 설치 마법은 아주 영리하게 동작합니다:

1.  **최초 소환:** 사리가 없는 컴퓨터에서 실행하면, `~/.local/share/sari`에 전역 설치를 진행하고 현재 워크스페이스를 연동합니다.
2.  **워크스페이스 추가:** 이미 사리가 설치된 컴퓨터라면, **불필요한 재설치 없이** 현재 폴더에 필요한 설정 파일(`.codex/config.toml` 등)만 번개처럼 빠르게 생성합니다.
3.  **자동화 우호적:** `-y` 옵션을 통해 파이프라인 설치 시 발생할 수 있는 입력 오류(EOFError)를 원천 차단합니다.


### 설치하면 어떤 마법이 일어나나요?
1.  **지혜 전수**: 사리 선생님이 일할 때 필요한 최소한의 도구(Python 엔진 등)를 자동으로 준비합니다.
2.  **비밀 거처 마련**: 도서관 주소를 만듭니다. (이사 비용은 무료입니다.)
    - **macOS/Linux**: `~/.local/share/sari` (사과 마크가 찍힌 비밀 창고)
    - **Windows**: `%LOCALAPPDATA%\sari` (창문이 달린 비밀 창고)
3.  **통역기 연결**: AI 에이전트들이 사리 선생님께 "헬프!"를 외칠 수 있도록 MCP 통역기를 연결합니다.

### 설정은 어디에 숨겨지나요? (쌍둥이 CLI 지원)
설치 스크립트(`install.py`)는 **설정이 지옥의 촉수처럼 흩어져 충돌**나는 것을 막기 위해 다음처럼 엄격하게 동작합니다.

- **쌍둥이의 축복**: 현재 작업 폴더의 `.codex/config.toml`과 `.gemini/config.toml` 양쪽에 사리 선생님의 영혼 인장을 동시에 찍습니다. (하나만 하면 섭섭하니까요.)
- **부정한 유산 정화**: `~/.codex/config.toml`과 `~/.gemini/config.toml`에 남아있던 케케묵은 설정들은 자비 없이 불태워 소멸시킵니다. (오직 깨끗한 것만이 살아남으리!)
- **성역의 예절**: Claude/Cursor 설정은 **함부로 발을 들이지 않습니다.** (남의 집 안방 가구는 집주인이 직접 옮기는 게 도리죠.) 필요하면 아래 비급 예시를 보고 직접 수련하여 옮기시게나.

### 여러 워크스페이스를 동시에? (분신술의 대가)
- **설정은 워크스페이스별로 각자의 운명**을 가집니다.  
  예: A에서 실행 → `A/.codex/config.toml` 생성 (A의 기록)  
  B에서 실행 → `B/.codex/config.toml` 생성 (B의 밀서)
- **몸은 하나, 지혜는 여러 곳에**: 사리 선생님은 하나의 데몬(Daemon)으로 동작하지만, 성역 곳곳에 분신을 보내어 **A와 B 워크스페이스를 동시에** 관리할 수 있습니다! (선생님이 워커홀릭이라 AB 둘 다 켜두면 둘 다 샅샅이 수집하신다네.)
- **철저한 기록 분리**: A의 장부와 B의 장부는 서로 섞이지 않도록 엄격히 분리된 서랍(Data Directory)에 보관됩니다. A에서 디아블로를 검색했는데 B의 바알이 튀어나오는 일은 없으니 안심하시게나.

---

## 🪄 1‑Step 모드 vs 설치본 고정 모드

**1‑Step 모드(권장)**  
레포의 `bootstrap.sh`를 config에 등록하면, 첫 실행 시 자동 설치/업데이트 후 **설치본으로 전환**됩니다.

**설치본 고정 모드**  
설치본 경로 `~/.local/share/sari/bootstrap.sh`를 등록하면 **자동 업데이트 없이** 고정된 버전을 사용합니다. (변화를 거부하는 보수적인 사서 모드입니다.)

**자동 업데이트 기준**  
레포 tag와 설치본 `VERSION`이 다르면, 레포의 `bootstrap.sh`가 `install.py`를 자동 실행합니다.

**bootstrap 스크립트 위치**
- **macOS/Linux (레포)**: `/path/to/sari/bootstrap.sh`
- **macOS/Linux (설치본)**: `~/.local/share/sari/bootstrap.sh`
- **Windows (설치본)**: `%LOCALAPPDATA%\sari\bootstrap.bat`

---

## 🧭 차원문 연결 위치와 동작 (실행 위치 요약)
| 실행 위치 (차원문 주소) | workspace-root가 없을 때 운명 |
|---|---|
| 레포 내부 | 레포 또는 상위 `.codex-root`를 고향으로 인식 |
| 워크스페이스 루트 | "여기가 내 집이구나!" 하고 바로 정착 |
| 홈 디렉토리 (`~`) | 여러분의 온 집안 살림을 다 뒤집어 봄 (강력히 비추천!) |

---

## ⚠️ "성스러운 혼용" 금지 경고
`command`에 **설치본과 레포 경로를 섞어 쓰면** 지옥문이 열릴 수 있습니다:
- 업데이트 규칙이 뒤엉켜서 고대 버전이 튀어나오거나,
- 서로 다른 데몬이 나타나 포트 47779를 두고 '성전'을 벌이거나,
- "어느 설정이 진짜인가" 하고 자아 분열이 일어납니다.

따라서 **config에는 항상 한 경로만 유지**하세요. (1‑Step 또는 고정 모드 중 하나!)

---

## 🔁 성역의 유지보수 (Update & Recovery)

### 🔁 강제 업데이트 및 복구
만약 설치 폴더가 손상되었거나, 최신 버전으로 강제 재설치가 필요하다면 `--update` 플래그를 사용하세요.

```bash
# 설치가 꼬였거나 업데이트가 필요할 때
curl -fsSL https://raw.githubusercontent.com/BaeCheolHan/sari/main/install.py | python3 - --update -y
```

### ✅ 수석 기록관의 최종 점검 (Checklist)
설치 후 모든 것이 정상인지 확인하려면 **닥터(Doctor)**를 소환하세요:
```bash
python3 ~/.local/share/sari/doctor.py
```

### 🧹 도서관 대청소 및 보안 (Caution!)
- **장부의 소멸**: 삭제 시 공들여 만든 기록(DB)도 함께 가루가 됩니다 → 재설치 후 **재인덱싱이라는 전설급 노가다**가 필요합니다.
- **수행의 시간**: 첫 실행 시 시간이 오래 걸릴 수 있습니다. (호라드림 도서관 20,000평을 혼자 빗질하신다고 생각해보시게나, 지극히 정상이라네.)

### 🔒 천상의 보안/프라이버시
- 모든 공부와 검색은 **여러분의 안방(로컬)**에서만 수행됩니다.
- 코드가 지옥(외부 서버)으로 전송되는 불상사는 결코 일어나지 않습니다.
- 로그와 캐시는 오직 여러분의 하드디스크 깊숙한 곳에만 봉인됩니다. (디아블로도 못 훔쳐가네.)

### 🧼 Redaction (민감정보 마스킹)
- 인덱싱/텔레메트리 로그 기록 전 **민감정보를 마스킹**합니다.
- 기본값은 `redact_enabled=true`이며, 설정에서 비활성화할 수 있습니다.
- 마스킹 범위/패턴은 `app/indexer.py`의 `_redact` 로직 기준입니다.

---

## 🧭 다중 워크스페이스를 똑똑하게 쓰는 방법
“A도 보고 싶고 B도 보고 싶어!” 하시는 분들을 위한 **현실적인 추천 패턴**이에요.

- **방법 1: 워크스페이스별로 설정을 나눠두기 (권장)**  
  A, B 각각에 `.codex/config.toml`을 만들어 두고, 필요할 때 그 폴더에서 실행하세요.  
  사리 선생님은 **현재 위치 기준**으로 움직이는 성격이라, 그게 제일 명확합니다.

- **방법 2: 하나의 워크스페이스만 집중 관리**  
  “지금은 A만 봐야 해!”라면 B는 과감하게 잊으세요.  
사리는 **한 번에 하나에 집중하는 선생님**이에요. (멀티태스킹은 다음 학기에…)

---

## 🧯 문제 해결 (Troubleshooting)

### Q. MCP 연결이 안 돼요
- `command` 경로가 실제 존재하는지 확인하세요.  
  (레포 경로인지 설치본 경로인지 헷갈리기 쉬워요!)
- 데몬 상태 확인:
  ```bash
  # macOS/Linux
  ~/.local/share/sari/bootstrap.sh daemon status
  
  # Windows
  %LOCALAPPDATA%\sari\bootstrap.bat daemon status
  ```
- 기동이 느리면 `startup_timeout_sec`를 120~180으로 올려보세요.

### Q. 첫 실행이 너무 느려요
- 첫 인덱싱은 원래 시간이 좀 걸립니다. (호라드림 도서관 20,000평을 혼자 청소하신다고 생각해보세요.)
- `--workspace-root`로 범위를 줄이면 훨씬 빨라집니다. (선생님께 청소 범위를 좁게 알려드리는 매너!)

### Q. 테스트가 운영 데몬과 충돌해요
- 격리된 환경에서 실행하려면 `scripts/run_tests_isolated.sh`를 사용하세요. (HOME/registry/log/port 분리)

### Q. 업데이트가 안 되는 것 같아요
- **1‑Step 모드인지 확인**하세요 (레포 `bootstrap.sh` 사용).
- 설치본 `VERSION`을 확인하세요:
  ```bash
  cat ~/.local/share/sari/VERSION
  ```

### Q. 설정 파일이 여기저기 생겼어요
- 사리 선생님은 **글로벌 설정과 프로젝트 설정이 뒤섞여 혼돈이 오는 걸 극도로 혐오합니다.**  
  그래서 글로벌 `~/.codex/config.toml`은 평화롭게 정리하고, **프로젝트별 서랍(설정)**만 사용하도록 유도합니다.  
  설정의 질서가 곧 코드의 평화입니다.

---

## 🧩 왜 설정을 자동으로 다 안 고쳐주나요?
Codex, Gemini, Claude, Cursor… 이 녀석들은 성격도 다르고 사는 곳(설정 경로)도 제각각이에요.  
사리 선생님은 **“남의 집 안방 가구 배치를 함부로 바꾸지 않겠다”**는 엄격한 도덕적 철학이 있습니다. 😄  
(사실 잘못 건드리면 지옥문이 열릴 수 있어서 그렇습니다.) 대신 참고할 수 있는 **비급서(설정 예시)**는 아래에 적어두었으니 직접 옮겨 적어보시게나!

---

## 🎮 사리 선생님 부려먹기 (Usage)

### 1단계: 내 프로젝트 공부시키기
여러분 개발 실력의 결정체(혹은 지옥에서 온 스파게티 코드)인 폴더로 이동해서 아래 명령어를 입력하세요. 그럼 사리 선생님이 지팡이를 짚고 그 폴더를 샅샅이 뒤지기 시작합니다!

```bash
# macOS/Linux
$HOME/.local/share/sari/bootstrap.sh init

# Windows
%LOCALAPPDATA%\sari\bootstrap.bat init
```

> **참고**: `--workspace-root`를 사용하면 선생님의 이동 범위를 제한할 수 있습니다.  
> 예) `.../bootstrap.sh init --workspace-root /path/to/my_precious_code`

### 2단계: AI에게 물어보기
이제 AI 친구(Codex, Claude, Cursor 등)를 열고 평소처럼 질문해보세요.

> "사리 선생님의 장부를 뒤져서 **로그인 로직**이 어느 지옥 구석에 있는지 찾아줘."  
> "이 프로젝트의 **데이터베이스 구조**를 설명해주게나. 사서 선생님이 아는 대로 말이야."

그럼 AI가 사리 선생님에게 달려가 장부를 확인하고, 아주 정확한 답변을 여러분께 알려줄 거예요! (가끔 답변 끝에 "Stay awhile and listen"이라고 붙여도 놀라지 마세요.) ✨

---

## 📊 Sari MCP vs Standard Tools (실측 기반 분석)
아래 수치는 **2026-02-02 기준, 실제 워크스페이스(636 files)**에서 실측한 바이트 크기입니다.  
분석에 사용된 저장소 이름/코드 내용은 **공개하지 않았습니다**. (구조·통계만 공개)  
토큰 추정은 `1,000 bytes ≈ 280 tokens` 기준으로 계산했습니다. (모델별 오버헤드는 제외)

### 측정 방법 요약
- Sari MCP: `status(details)`, `list_files`, `search_symbols` 응답의 **바이트 크기 측정**
- Standard Tools: `ls -R`, `rg --files`, `rg "class.*Application"` 출력의 **바이트 크기 측정**
- 동일 워크스페이스/동일 시점/동일 필터로 비교

### 1) 구조 탐색 (파일 트리 파악)
| 도구 | 측정 항목 | 바이트 | 추정 토큰 |
| --- | --- | ---:| ---:|
| Sari | `status(details)` | 1,649 | ~462 |
| Sari | `list_files` (limit=2000, returned=500) | 115,397 | ~32,311 |
| Standard | `ls -R` | 66,146 | ~18,521 |
| Standard | `rg --files` | 73,196 | ~20,495 |

**해석:**  
- `status(details)`는 구조 파악용 요약으로 **출력량이 가장 작습니다.**  
- `list_files`는 JSON 메타데이터 때문에 **전체 호출 시 출력량이 커질 수 있습니다.**
- 따라서 **요약 → repo 좁히기 → 상세** 순으로 사용하는 것이 토큰 효율이 높습니다.

### 2) 엔트리포인트 식별 (Application 클래스 탐색)
| 도구 | 측정 항목 | 바이트 | 결과 수 |
| --- | --- | ---:| ---:|
| Sari | `search_symbols Application` | 1,008 | 4 |
| Standard | `rg "class.*Application"` | 667 | 4 |

**해석:**  
- 출력량은 유사하지만, Sari는 **심볼 타입/경로/라인을 구조화**해 반환합니다.  
- 후속 단계(`read_symbol`)로 이어질 때 **추가 탐색 비용이 줄어듭니다.**

### 3) 결론 (실측 기반)
Sari는 **“요약 → 좁히기 → 심볼 읽기”** 워크플로우에서 가장 효율적입니다.  
반대로 `list_files`를 전체에 무심코 호출하면 토큰 비용이 커질 수 있으니,  
**repo 지정 또는 요약 모드**를 반드시 사용하세요.

---

## ⚡ 성능과 비용 최적화 가이드
Sari는 인덱싱 + FTS 기반 검색 구조라서 **“어떤 단계에서 쓰느냐”**에 따라 체감 성능이 크게 달라집니다.

### 1) 구조 파악: 요약 모드가 기본
- **권장:** `status(details)` → `repo_candidates` → `list_files(repo=...)`
- `list_files`는 **repo 미지정 시 요약 모드**로 동작합니다.  
  큰 워크스페이스에서 **전체 파일 목록을 한 번에 덤프하면 비용/토큰 폭주**가 발생합니다.

### 2) 검색 속도: FTS가 켜져 있는지 확인
- `status(details)`에서 `fts_enabled: true`인지 먼저 확인하세요.  
- `fts_enabled: false`면 검색이 LIKE 폴백으로 전환되어 **느려지고 정확도도 떨어집니다.**
- FTS가 켜져 있어도 **아주 짧은 쿼리(길이 < 3)** 또는 **유니코드 포함 쿼리**는 LIKE로 폴백될 수 있습니다.

### 3) 엔트리포인트 탐색은 심볼 기반이 유리
- `search_symbols` → `read_symbol` 조합은 **필요한 코드 블록만 읽어** 토큰 비용을 줄입니다.
- `read_file`은 “정말 전체 파일이 필요할 때만” 사용하세요.

### 4) 큰 레포일수록 필터링이 핵심
- `repo`, `file_types`, `path_pattern`을 적극 사용하세요.
- 예) `list_files { repo: "sari", file_types: ["py"] }`

---

## 🛠️ 내가 쓰는 앱에 연결하기 (상세 가이드)

### 🤖 Claude Desktop 앱 연동
설정 파일(`claude_desktop_config.json`)을 찾아서 아래 내용을 쏙 넣어주세요.  
이건 마치 선생님 이름표를 달아주는 작업입니다.

```json
{
  "mcpServers": {
    "sari": {
      "command": "/Users/[사용자명]/.local/share/sari/bootstrap.sh",
      "args": []
    }
  }
}
```

### 🧩 Codex / Gemini 설정 예시 (config.toml)
> 아래는 **설치본 고정 모드** 예시입니다. 1‑Step 모드를 쓰려면 `command`를 레포 경로로 바꾸세요.

```toml
[mcp_servers.sari]
command = "/Users/[사용자명]/.local/share/sari/bootstrap.sh"
args = ["--workspace-root", "/Users/[사용자명]/path/to/workspace"]
env = { DECKARD_WORKSPACE_ROOT = "/Users/[사용자명]/path/to/workspace" }
startup_timeout_sec = 60
```

**1‑Step 모드 예시 (레포 bootstrap 사용)**
```toml
[mcp_servers.sari]
command = "/Users/[사용자명]/path/to/sari/bootstrap.sh"
args = ["--workspace-root", "/Users/[사용자명]/path/to/workspace"]
env = { DECKARD_WORKSPACE_ROOT = "/Users/[사용자명]/path/to/workspace" }
startup_timeout_sec = 60
```

**필드별 상세 설명**
- `command`: 사리를 실행할 경로입니다.  
  - **1‑Step 모드**: 레포의 `bootstrap.sh` 경로  
    예) `/path/to/sari/bootstrap.sh`
  - **설치본 고정 모드**: 설치본의 `bootstrap.sh` 경로  
    예) `~/.local/share/sari/bootstrap.sh`
- `args`: 실행 옵션을 리스트로 전달합니다.  
  - `--workspace-root <path>`: 인덱싱할 워크스페이스 루트 경로  
  - **생략 시**: 현재 실행 위치를 기준으로 동작하거나, `.codex-root`가 있는 상위 폴더를 기준으로 동작합니다.
- `env`: 환경 변수를 강제로 주입합니다.  
  - `DECKARD_WORKSPACE_ROOT`는 **workspace-root를 고정**하려고 넣습니다.  
  - `args`와 **동일한 값**을 넣는 것이 권장됩니다. (둘 중 하나만 있어도 동작합니다)
- `startup_timeout_sec`: 데몬 기동 대기 시간(초).  
  초기 인덱싱이 길다면 120~180으로 늘려보세요.

**설정 경로 우선순위(요약)**  
1) `DECKARD_CONFIG` / `LOCAL_SEARCH_CONFIG`  
2) `<workspace>/.codex/tools/sari/config/config.json`  
3) 패키지 기본 config

### 📈 텔레메트리 로그
- `tool=search`/`tool=list_files` 등 도구 실행 로그가 기록됩니다.
- `search-first` 정책 위반/경고는 별도 로그 항목으로 남습니다.

### 🧵 응답 압축 모드
- `DECKARD_RESPONSE_COMPACT=1`이면 MCP 응답 JSON이 **minified**로 출력됩니다. (기본값)
- `DECKARD_RESPONSE_COMPACT=0`이면 기존 pretty JSON 출력으로 복원됩니다.
- `list_files`는 compact 모드에서 `paths`만 반환합니다. (verbose 모드에서만 `files/meta`)

**여러 워크스페이스를 넣을 수 있나요?**
- 현재는 `--workspace-root` **단일 경로만 지원**합니다.
- 여러 워크스페이스를 쓰려면 각 워크스페이스마다 별도 설정을 권장합니다.

**env 없이도 되나요?**
- 됩니다. `args`에 `--workspace-root`가 있으면 정상 동작합니다.
- 다만 **환경 변수가 우선**되도록 사용 환경이 구성된 경우가 있어, 혼선을 줄이려면 `args`와 `env`를 같이 맞춰두는 것이 안전합니다.

**args와 env가 서로 다르면?**
- `DECKARD_WORKSPACE_ROOT`(환경 변수)가 왕의 권위를 가집니다.  
  하지만 두 값이 다르면 선생님이 "어디로 가라는 건가!" 하고 지팡이를 휘두르실 테니, **항상 동일하게 맞추는 걸 추천**하네.

**`--workspace-root`를 생략하면 어떤 재앙이?**
- 실행 위치를 기준으로 워크스페이스를 멋대로 추정합니다.  
  - 현재 폴더 또는 상위 폴더에 `.codex-root`가 있으면 "찾았다!" 하고 사용
  - 없다면 **현재 폴더 전체**를 자기 안방인 줄 압니다.

**예: 홈 디렉토리에서 실수로 실행하면?**
- 의도치 않게 여러분의 '비밀 사진첩'과 '다운로드 폴더' 전체가 호라드림 장부에 기록될 수 있습니다.  
  정신 건강을 위해 `--workspace-root`를 명시하는 것을 **강력하고 간절하게** 추천하네.

**설정 파일이 두 군데 있으면 어떻게 되나요?**
- 사리 선생님은 **프로젝트 설정(현장 중심)**을 가장 신뢰합니다.  
  글로벌 설정과 함께 존재하면 선생님이 헷갈려하시니,  
  `install.py`는 자비롭게 글로벌의 `sari` 블록을 제거해 버린다네. (오직 질서!)

### ⌨️ Cursor (AI 에디터) 연동
1.  **환경설정(Settings)** > **MCP** 메뉴를 클릭하세요.
2.  **+ Add New MCP Server** 버튼을 누릅니다.
3.  이름엔 `sari`, 타입은 `stdio`를 선택하세요.
4.  Command 칸에 `/Users/[사용자명]/.local/share/sari/bootstrap.sh`를 입력하고 'Save' 하면 끝!

---

## 🗑️ 도서관 폐쇄 (삭제 방법 - Uninstall)

이제 성역에 평화가 찾아왔거나, 선생님의 잔소리가 듣기 싫다면 언제든 보내드릴 수 있습니다. 터미널에 아래 명령어를 입력하세요. (눈물 주의)

```bash
# 마법 주문에 --uninstall 옵션을 붙이면 선생님이 짐을 싸서 떠나십니다.
curl -fsSL https://raw.githubusercontent.com/BaeCheolHan/sari/main/install.py | python3 - --uninstall
```

또는 설치본 기준으로 이렇게도 가능합니다:
```bash
# macOS/Linux
~/.local/share/sari/bootstrap.sh uninstall

# Windows
%LOCALAPPDATA%\sari\bootstrap.bat uninstall
```

### 삭제하면 무엇이 정화되나요? (이별의 미학)
- **거처 정화**: 사리 선생님이 머물던 도서관과 낡은 장부(index.db)를 트리스트럼의 불길로 소멸시킵니다.
- **쌍둥이 유령 퇴치**: `install.py --uninstall`은 Codex와 Gemini 양쪽의 인장을 모두 지워버리는 강력한 정화 의식을 거행합니다.
- **선택적 작별**: `bootstrap.sh uninstall`은 오직 Codex의 인장만 지우고 떠나는 절제된 이별을 선사합니다. (Gemini/Claude 등은 그대로 남습니다.)
- **윈도우 주의**: `bootstrap.bat uninstall`은 **설정 파일을 정리하지 않습니다.** 필요하면 수동으로 `config.toml`에서 `sari` 블록을 제거하세요.
- **깔끔한 승천**: 여러분의 컴퓨터에 그 어떤 지옥의 찌꺼기도 남기지 않고 고결하게 사라지십니다!

---

## 🤖 MCP 응답 포맷 (PACK1) 가이드

사리 v2.5.0부터는 토큰 절약을 위해 **PACK1**이라는 압축 텍스트 포맷을 기본으로 사용합니다. JSON의 불필요한 괄호와 공백을 제거하여 **약 30~50%의 토큰을 절약**합니다.

### 1. 포맷 개요
- **헤더(Header)**: `PACK1 <tool> key=value ...`
- **레코드(Record)**: `<type>:<payload>` (한 줄에 하나씩)
- **인코딩**: 특수문자나 공백이 포함된 값은 안전하게 URL 인코딩됩니다.
  - `ENC_ID`: 식별자용 (경로, 이름 등). `safe="/._-:@"`
  - `ENC_TEXT`: 일반 텍스트용 (스니펫, 메시지 등). `safe=""`

### 2. 주요 도구 예시

**`list_files`**
```text
PACK1 list_files offset=0 limit=100 returned=2 total=2 total_mode=exact
p:src/main.py
p:src/utils.py
```

**`search_symbols`**
```text
PACK1 search_symbols q=User limit=50 returned=1 total_mode=none
h:repo=my-repo path=src/user.py line=10 kind=class name=User
```

**`status`**
```text
PACK1 status returned=5
m:index_ready=true
m:scanned_files=100
m:indexed_files=100
m:errors=0
m:fts_enabled=true
```

### 3. 에러 코드 (Error Codes)
오류 발생 시 `PACK1 <tool> ok=false` 헤더와 함께 아래 코드가 반환됩니다.

| 코드 | 설명 |
|---|---|
| `INVALID_ARGS` | 잘못된 인자 전달 |
| `NOT_INDEXED` | 인덱싱이 완료되지 않음 |
| `REPO_NOT_FOUND` | 존재하지 않는 저장소 |
| `IO_ERROR` | 파일 읽기/쓰기 실패 |
| `DB_ERROR` | 데이터베이스 오류 |
| `INTERNAL` | 내부 서버 오류 |

> **참고**: 기존 JSON 포맷이 필요하다면 환경변수 `DECKARD_FORMAT=json`을 설정하세요. (디버깅용)

---

## 🏗️ 개발자를 위한 제원 (Tech Specs)

- **언어**: Python 3.9+ (표준 라이브러리만 사용하는 제로 디펜던시!)
- **DB**: SQLite (WAL 모드) + FTS5 (전문 검색 기술)
- **통신**: MCP (Model Context Protocol) 
- **구조**: 
    - **Daemon**: 실제로 공부하고 검색을 처리하는 핵심 본체
    - **Proxy**: AI 앱과 Daemon 사이의 빠른 메신저

---

## 📜 라이선스 (License)

이 프로젝트는 [MIT License](LICENSE)를 따르고 있어요. 누구나 자유롭게 사용하고, 고치고, 공유할 수 있답니다! 😄

---

**"자, 이제 사리 선생님과 함께 여러분의 코드 속에 숨겨진 비밀을 찾아보시겠나?"** 🧙‍♂️✨
