sari 0.0.1__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (77) hide show
  1. sari-0.0.1/LICENSE +21 -0
  2. sari-0.0.1/PKG-INFO +521 -0
  3. sari-0.0.1/README.md +488 -0
  4. sari-0.0.1/app/__init__.py +1 -0
  5. sari-0.0.1/app/config.py +240 -0
  6. sari-0.0.1/app/db.py +932 -0
  7. sari-0.0.1/app/dedup_queue.py +77 -0
  8. sari-0.0.1/app/engine_registry.py +56 -0
  9. sari-0.0.1/app/engine_runtime.py +472 -0
  10. sari-0.0.1/app/http_server.py +204 -0
  11. sari-0.0.1/app/indexer.py +1532 -0
  12. sari-0.0.1/app/main.py +147 -0
  13. sari-0.0.1/app/models.py +39 -0
  14. sari-0.0.1/app/queue_pipeline.py +65 -0
  15. sari-0.0.1/app/ranking.py +144 -0
  16. sari-0.0.1/app/registry.py +172 -0
  17. sari-0.0.1/app/search_engine.py +572 -0
  18. sari-0.0.1/app/watcher.py +124 -0
  19. sari-0.0.1/app/workspace.py +286 -0
  20. sari-0.0.1/deckard/__init__.py +3 -0
  21. sari-0.0.1/deckard/__main__.py +4 -0
  22. sari-0.0.1/deckard/main.py +345 -0
  23. sari-0.0.1/deckard/version.py +1 -0
  24. sari-0.0.1/mcp/__init__.py +1 -0
  25. sari-0.0.1/mcp/__main__.py +19 -0
  26. sari-0.0.1/mcp/cli.py +485 -0
  27. sari-0.0.1/mcp/daemon.py +149 -0
  28. sari-0.0.1/mcp/proxy.py +304 -0
  29. sari-0.0.1/mcp/registry.py +218 -0
  30. sari-0.0.1/mcp/server.py +519 -0
  31. sari-0.0.1/mcp/session.py +234 -0
  32. sari-0.0.1/mcp/telemetry.py +112 -0
  33. sari-0.0.1/mcp/test_cli.py +89 -0
  34. sari-0.0.1/mcp/test_daemon.py +124 -0
  35. sari-0.0.1/mcp/test_server.py +197 -0
  36. sari-0.0.1/mcp/tools/__init__.py +14 -0
  37. sari-0.0.1/mcp/tools/_util.py +244 -0
  38. sari-0.0.1/mcp/tools/deckard_guide.py +32 -0
  39. sari-0.0.1/mcp/tools/doctor.py +208 -0
  40. sari-0.0.1/mcp/tools/get_callers.py +60 -0
  41. sari-0.0.1/mcp/tools/get_implementations.py +60 -0
  42. sari-0.0.1/mcp/tools/index_file.py +75 -0
  43. sari-0.0.1/mcp/tools/list_files.py +138 -0
  44. sari-0.0.1/mcp/tools/read_file.py +48 -0
  45. sari-0.0.1/mcp/tools/read_symbol.py +99 -0
  46. sari-0.0.1/mcp/tools/registry.py +212 -0
  47. sari-0.0.1/mcp/tools/repo_candidates.py +89 -0
  48. sari-0.0.1/mcp/tools/rescan.py +46 -0
  49. sari-0.0.1/mcp/tools/scan_once.py +54 -0
  50. sari-0.0.1/mcp/tools/search.py +208 -0
  51. sari-0.0.1/mcp/tools/search_api_endpoints.py +72 -0
  52. sari-0.0.1/mcp/tools/search_symbols.py +63 -0
  53. sari-0.0.1/mcp/tools/status.py +135 -0
  54. sari-0.0.1/pyproject.toml +26 -0
  55. sari-0.0.1/sari/__init__.py +1 -0
  56. sari-0.0.1/sari/__main__.py +4 -0
  57. sari-0.0.1/sari.egg-info/PKG-INFO +521 -0
  58. sari-0.0.1/sari.egg-info/SOURCES.txt +75 -0
  59. sari-0.0.1/sari.egg-info/dependency_links.txt +1 -0
  60. sari-0.0.1/sari.egg-info/entry_points.txt +2 -0
  61. sari-0.0.1/sari.egg-info/requires.txt +1 -0
  62. sari-0.0.1/sari.egg-info/top_level.txt +4 -0
  63. sari-0.0.1/setup.cfg +4 -0
  64. sari-0.0.1/tests/test_contracts.py +160 -0
  65. sari-0.0.1/tests/test_doctor_tool.py +103 -0
  66. sari-0.0.1/tests/test_engine_registry.py +42 -0
  67. sari-0.0.1/tests/test_engine_runtime.py +361 -0
  68. sari-0.0.1/tests/test_http_server.py +163 -0
  69. sari-0.0.1/tests/test_import_fallbacks.py +53 -0
  70. sari-0.0.1/tests/test_list_files_tool.py +39 -0
  71. sari-0.0.1/tests/test_memory_leak.py +216 -0
  72. sari-0.0.1/tests/test_read_tools.py +66 -0
  73. sari-0.0.1/tests/test_search_tool.py +135 -0
  74. sari-0.0.1/tests/test_status_tool.py +77 -0
  75. sari-0.0.1/tests/test_tools_more.py +172 -0
  76. sari-0.0.1/tests/test_util_pack.py +88 -0
  77. sari-0.0.1/tests/test_workspace.py +104 -0
sari-0.0.1/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
sari-0.0.1/PKG-INFO ADDED
@@ -0,0 +1,521 @@
1
+ Metadata-Version: 2.4
2
+ Name: sari
3
+ Version: 0.0.1
4
+ Summary: Sari - Local Search MCP Server
5
+ Author: Horadric
6
+ License: MIT License
7
+
8
+ Copyright (c) 2026
9
+
10
+ Permission is hereby granted, free of charge, to any person obtaining a copy
11
+ of this software and associated documentation files (the "Software"), to deal
12
+ in the Software without restriction, including without limitation the rights
13
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
14
+ copies of the Software, and to permit persons to whom the Software is
15
+ furnished to do so, subject to the following conditions:
16
+
17
+ The above copyright notice and this permission notice shall be included in all
18
+ copies or substantial portions of the Software.
19
+
20
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
21
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
23
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
24
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
25
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
26
+ SOFTWARE.
27
+
28
+ Requires-Python: >=3.9
29
+ Description-Content-Type: text/markdown
30
+ License-File: LICENSE
31
+ Requires-Dist: watchdog>=2.0.0
32
+ Dynamic: license-file
33
+
34
+ # 🧙‍♂️ Sari (사리)
35
+
36
+ > **"잠시 내 말 좀 들어보게나... 자네의 소스코드가 지옥의 비명을 지르는 소리를!"** (Stay awhile and listen...)
37
+
38
+ **사리(Sari)**는 인공지능(AI) 친구들이 여러분의 복잡하고 거대한 코드를 아주 쉽고 빠르게 이해할 수 있도록 도와주는 **'호라드림의 수석 기록관'**이에요.
39
+
40
+ 사리 선생님만 계시면 아무리 얽히고설킨 코드라도 AI가 길을 잃지 않고 필요한 클래스를 0.1초 만에 찾아낼 수 있답니다.
41
+ 호라드림의 촛불이 꺼지지 않는 한, 인덱싱 누락이라는 혼돈의 비명은 들리지 않게 될 거예요. 🚀 (선생님이 지팡이로 길을 아주 상세히 안내해주신답니다.)
42
+
43
+ ---
44
+
45
+ ## 🧐 사리 선생님은 누구인가요? (쉽게 이해하기)
46
+
47
+ 여러분의 컴퓨터에는 아주 많은 코드 파일이 있어요. 똑똑한 **AI 친구(Codex, Claude, Cursor, Gemini 등)**에게 코드를 짜달라고 하면 가끔 이런 말을 할 거예요.
48
+ *"미안해, 파일이 너무 많아서 어디에 뭐가 있는지 모르겠어!"*
49
+
50
+ 그때 바로 **사리 선생님**이 트리스트럼 어딘가에서 마법처럼 나타납니다!
51
+
52
+ 1. **지독한 사서**: 사리 선생님은 여러분의 모든 코드를 미리 다 읽어두고, 누가 어느 지옥 구석에 사는지(어떤 함수가 어떤 파일에 있는지) 아주 상세한 **'호라드림 장부'**를 만들어둬요. (눈이 침침하셔도 정규식은 기가 막히게 보십니다.)
53
+ 2. **AI의 길잡이**: AI 친구가 "이 프로젝트에서 회원가입은 어떻게 해?"라고 물어보면, 사리 선생님이 지팡이를 짚고 장부를 슥 보고는 "3번 선반 아래, 디아블로의 꼬리 옆에 있는 `user.py` 파일을 보게나! 주석 좀 똑바로 달지 그랬나..."라고 꾸짖으며 알려줍니다.
54
+ 3. **MCP(Model Context Protocol)**: 이건 AI 친구와 사리 선생님이 서로 대화할 때 쓰는 **'호라드림 통역기'** 같은 거예요. 이 통역기 덕분에 사리 선생님은 세상의 모든 최신 AI와 대화할 수 있답니다! (고대어는 몰라도 Python은 꿰고 계시죠.) 🤝
55
+
56
+ ---
57
+
58
+ ## 🌟 사리 선생님의 특별한 능력
59
+
60
+ - **⚡ 차원문 검색**: 수만 줄의 코드도 순식간에 읽어서 필요한 부분만 골라내요. (TP 타는 속도보다 빠릅니다.)
61
+ - **🧠 코드 심령술**: 단순히 글자만 찾는 게 아니라, 이게 '함수'인지 '클래스'인지 코드의 영혼(AST)을 읽어냅니다.
62
+ - **🔒 철통 보안**: 모든 공부는 여러분의 컴퓨터 안에서만 해요. 코드가 성역(인터넷) 밖으로 절대 나가지 않으니 안심하세요! 지옥의 악마도 여러분의 소스코드는 못 훔쳐갑니다. 🛡️
63
+ - **👻 투명 망토**: 백그라운드에서 조용히 일하며 여러분이 코드를 고칠 때마다 장부를 알아서 업데이트해요. (가끔 계신지 확인하지 않으면 섭섭해하십니다.)
64
+
65
+ ---
66
+
67
+ ## 🚀 성역 소환 주문 (설치 방법 - Installation)
68
+
69
+ 터미널(Terminal)을 열고 아래 마법 주문을 딱 한 줄만 복사해서 붙여넣고 엔터(Enter)를 누르세요!
70
+ 이 명령어는 **최초 설치**뿐만 아니라, **새로운 워크스페이스 연동**에도 똑같이 사용됩니다.
71
+
72
+ ```bash
73
+ # macOS / Linux (유닉스의 축복을 받은 자들)
74
+ curl -fsSL https://raw.githubusercontent.com/BaeCheolHan/sari/main/install.py | python3 - -y
75
+
76
+ # Windows (파워쉘의 마법사들)
77
+ irm https://raw.githubusercontent.com/BaeCheolHan/sari/main/install.py | python - -y
78
+ ```
79
+
80
+ ### 📖 호라드림의 설치 계시 (How it works)
81
+ 사리 선생님의 설치 마법은 아주 영리하게 동작합니다:
82
+
83
+ 1. **최초 소환:** 사리가 없는 컴퓨터에서 실행하면, `~/.local/share/sari`에 전역 설치를 진행하고 현재 워크스페이스를 연동합니다.
84
+ 2. **워크스페이스 추가:** 이미 사리가 설치된 컴퓨터라면, **불필요한 재설치 없이** 현재 폴더에 필요한 설정 파일(`.codex/config.toml` 등)만 번개처럼 빠르게 생성합니다.
85
+ 3. **자동화 우호적:** `-y` 옵션을 통해 파이프라인 설치 시 발생할 수 있는 입력 오류(EOFError)를 원천 차단합니다.
86
+
87
+
88
+ ### 설치하면 어떤 마법이 일어나나요?
89
+ 1. **지혜 전수**: 사리 선생님이 일할 때 필요한 최소한의 도구(Python 엔진 등)를 자동으로 준비합니다.
90
+ 2. **비밀 거처 마련**: 도서관 주소를 만듭니다. (이사 비용은 무료입니다.)
91
+ - **macOS/Linux**: `~/.local/share/sari` (사과 마크가 찍힌 비밀 창고)
92
+ - **Windows**: `%LOCALAPPDATA%\sari` (창문이 달린 비밀 창고)
93
+ 3. **통역기 연결**: AI 에이전트들이 사리 선생님께 "헬프!"를 외칠 수 있도록 MCP 통역기를 연결합니다.
94
+
95
+ ### 설정은 어디에 숨겨지나요? (쌍둥이 CLI 지원)
96
+ 설치 스크립트(`install.py`)는 **설정이 지옥의 촉수처럼 흩어져 충돌**나는 것을 막기 위해 다음처럼 엄격하게 동작합니다.
97
+
98
+ - **쌍둥이의 축복**: 현재 작업 폴더의 `.codex/config.toml`과 `.gemini/config.toml` 양쪽에 사리 선생님의 영혼 인장을 동시에 찍습니다. (하나만 하면 섭섭하니까요.)
99
+ - **부정한 유산 정화**: `~/.codex/config.toml`과 `~/.gemini/config.toml`에 남아있던 케케묵은 설정들은 자비 없이 불태워 소멸시킵니다. (오직 깨끗한 것만이 살아남으리!)
100
+ - **성역의 예절**: Claude/Cursor 설정은 **함부로 발을 들이지 않습니다.** (남의 집 안방 가구는 집주인이 직접 옮기는 게 도리죠.) 필요하면 아래 비급 예시를 보고 직접 수련하여 옮기시게나.
101
+
102
+ ### 여러 워크스페이스를 동시에? (분신술의 대가)
103
+ - **설정은 워크스페이스별로 각자의 운명**을 가집니다.
104
+ 예: A에서 실행 → `A/.codex/config.toml` 생성 (A의 기록)
105
+ B에서 실행 → `B/.codex/config.toml` 생성 (B의 밀서)
106
+ - **몸은 하나, 지혜는 여러 곳에**: 사리 선생님은 하나의 데몬(Daemon)으로 동작하지만, 성역 곳곳에 분신을 보내어 **A와 B 워크스페이스를 동시에** 관리할 수 있습니다! (선생님이 워커홀릭이라 AB 둘 다 켜두면 둘 다 샅샅이 수집하신다네.)
107
+ - **철저한 기록 분리**: A의 장부와 B의 장부는 서로 섞이지 않도록 엄격히 분리된 서랍(Data Directory)에 보관됩니다. A에서 디아블로를 검색했는데 B의 바알이 튀어나오는 일은 없으니 안심하시게나.
108
+
109
+ ---
110
+
111
+ ## 🪄 1‑Step 모드 vs 설치본 고정 모드
112
+
113
+ **1‑Step 모드(권장)**
114
+ 레포의 `bootstrap.sh`를 config에 등록하면, 첫 실행 시 자동 설치/업데이트 후 **설치본으로 전환**됩니다.
115
+
116
+ **설치본 고정 모드**
117
+ 설치본 경로 `~/.local/share/sari/bootstrap.sh`를 등록하면 **자동 업데이트 없이** 고정된 버전을 사용합니다. (변화를 거부하는 보수적인 사서 모드입니다.)
118
+
119
+ **자동 업데이트 기준**
120
+ 레포 tag와 설치본 `VERSION`이 다르면, 레포의 `bootstrap.sh`가 `install.py`를 자동 실행합니다.
121
+
122
+ **bootstrap 스크립트 위치**
123
+ - **macOS/Linux (레포)**: `/path/to/sari/bootstrap.sh`
124
+ - **macOS/Linux (설치본)**: `~/.local/share/sari/bootstrap.sh`
125
+ - **Windows (설치본)**: `%LOCALAPPDATA%\sari\bootstrap.bat`
126
+
127
+ ---
128
+
129
+ ## 🧭 차원문 연결 위치와 동작 (실행 위치 요약)
130
+ | 실행 위치 (차원문 주소) | workspace-root가 없을 때 운명 |
131
+ |---|---|
132
+ | 레포 내부 | 레포 또는 상위 `.codex-root`를 고향으로 인식 |
133
+ | 워크스페이스 루트 | "여기가 내 집이구나!" 하고 바로 정착 |
134
+ | 홈 디렉토리 (`~`) | 여러분의 온 집안 살림을 다 뒤집어 봄 (강력히 비추천!) |
135
+
136
+ ---
137
+
138
+ ## ⚠️ "성스러운 혼용" 금지 경고
139
+ `command`에 **설치본과 레포 경로를 섞어 쓰면** 지옥문이 열릴 수 있습니다:
140
+ - 업데이트 규칙이 뒤엉켜서 고대 버전이 튀어나오거나,
141
+ - 서로 다른 데몬이 나타나 포트 47779를 두고 '성전'을 벌이거나,
142
+ - "어느 설정이 진짜인가" 하고 자아 분열이 일어납니다.
143
+
144
+ 따라서 **config에는 항상 한 경로만 유지**하세요. (1‑Step 또는 고정 모드 중 하나!)
145
+
146
+ ---
147
+
148
+ ## 🔁 성역의 유지보수 (Update & Recovery)
149
+
150
+ ### 🔁 강제 업데이트 및 복구
151
+ 만약 설치 폴더가 손상되었거나, 최신 버전으로 강제 재설치가 필요하다면 `--update` 플래그를 사용하세요.
152
+
153
+ ```bash
154
+ # 설치가 꼬였거나 업데이트가 필요할 때
155
+ curl -fsSL https://raw.githubusercontent.com/BaeCheolHan/sari/main/install.py | python3 - --update -y
156
+ ```
157
+
158
+ ### ✅ 수석 기록관의 최종 점검 (Checklist)
159
+ 설치 후 모든 것이 정상인지 확인하려면 **닥터(Doctor)**를 소환하세요:
160
+ ```bash
161
+ python3 ~/.local/share/sari/doctor.py
162
+ ```
163
+
164
+ ### 🧹 도서관 대청소 및 보안 (Caution!)
165
+ - **장부의 소멸**: 삭제 시 공들여 만든 기록(DB)도 함께 가루가 됩니다 → 재설치 후 **재인덱싱이라는 전설급 노가다**가 필요합니다.
166
+ - **수행의 시간**: 첫 실행 시 시간이 오래 걸릴 수 있습니다. (호라드림 도서관 20,000평을 혼자 빗질하신다고 생각해보시게나, 지극히 정상이라네.)
167
+
168
+ ### 🔒 천상의 보안/프라이버시
169
+ - 모든 공부와 검색은 **여러분의 안방(로컬)**에서만 수행됩니다.
170
+ - 코드가 지옥(외부 서버)으로 전송되는 불상사는 결코 일어나지 않습니다.
171
+ - 로그와 캐시는 오직 여러분의 하드디스크 깊숙한 곳에만 봉인됩니다. (디아블로도 못 훔쳐가네.)
172
+
173
+ ### 🧼 Redaction (민감정보 마스킹)
174
+ - 인덱싱/텔레메트리 로그 기록 전 **민감정보를 마스킹**합니다.
175
+ - 기본값은 `redact_enabled=true`이며, 설정에서 비활성화할 수 있습니다.
176
+ - 마스킹 범위/패턴은 `app/indexer.py`의 `_redact` 로직 기준입니다.
177
+
178
+ ---
179
+
180
+ ## 🧭 다중 워크스페이스를 똑똑하게 쓰는 방법
181
+ “A도 보고 싶고 B도 보고 싶어!” 하시는 분들을 위한 **현실적인 추천 패턴**이에요.
182
+
183
+ - **방법 1: 워크스페이스별로 설정을 나눠두기 (권장)**
184
+ A, B 각각에 `.codex/config.toml`을 만들어 두고, 필요할 때 그 폴더에서 실행하세요.
185
+ 사리 선생님은 **현재 위치 기준**으로 움직이는 성격이라, 그게 제일 명확합니다.
186
+
187
+ - **방법 2: 하나의 워크스페이스만 집중 관리**
188
+ “지금은 A만 봐야 해!”라면 B는 과감하게 잊으세요.
189
+ 사리는 **한 번에 하나에 집중하는 선생님**이에요. (멀티태스킹은 다음 학기에…)
190
+
191
+ ---
192
+
193
+ ## 🧯 문제 해결 (Troubleshooting)
194
+
195
+ ### Q. MCP 연결이 안 돼요
196
+ - `command` 경로가 실제 존재하는지 확인하세요.
197
+ (레포 경로인지 설치본 경로인지 헷갈리기 쉬워요!)
198
+ - 데몬 상태 확인:
199
+ ```bash
200
+ # macOS/Linux
201
+ ~/.local/share/sari/bootstrap.sh daemon status
202
+
203
+ # Windows
204
+ %LOCALAPPDATA%\sari\bootstrap.bat daemon status
205
+ ```
206
+ - 기동이 느리면 `startup_timeout_sec`를 120~180으로 올려보세요.
207
+
208
+ ### Q. 첫 실행이 너무 느려요
209
+ - 첫 인덱싱은 원래 시간이 좀 걸립니다. (호라드림 도서관 20,000평을 혼자 청소하신다고 생각해보세요.)
210
+ - `--workspace-root`로 범위를 줄이면 훨씬 빨라집니다. (선생님께 청소 범위를 좁게 알려드리는 매너!)
211
+
212
+ ### Q. 테스트가 운영 데몬과 충돌해요
213
+ - 격리된 환경에서 실행하려면 `scripts/run_tests_isolated.sh`를 사용하세요. (HOME/registry/log/port 분리)
214
+
215
+ ### Q. 업데이트가 안 되는 것 같아요
216
+ - **1‑Step 모드인지 확인**하세요 (레포 `bootstrap.sh` 사용).
217
+ - 설치본 `VERSION`을 확인하세요:
218
+ ```bash
219
+ cat ~/.local/share/sari/VERSION
220
+ ```
221
+
222
+ ### Q. 설정 파일이 여기저기 생겼어요
223
+ - 사리 선생님은 **글로벌 설정과 프로젝트 설정이 뒤섞여 혼돈이 오는 걸 극도로 혐오합니다.**
224
+ 그래서 글로벌 `~/.codex/config.toml`은 평화롭게 정리하고, **프로젝트별 서랍(설정)**만 사용하도록 유도합니다.
225
+ 설정의 질서가 곧 코드의 평화입니다.
226
+
227
+ ---
228
+
229
+ ## 🧩 왜 설정을 자동으로 다 안 고쳐주나요?
230
+ Codex, Gemini, Claude, Cursor… 이 녀석들은 성격도 다르고 사는 곳(설정 경로)도 제각각이에요.
231
+ 사리 선생님은 **“남의 집 안방 가구 배치를 함부로 바꾸지 않겠다”**는 엄격한 도덕적 철학이 있습니다. 😄
232
+ (사실 잘못 건드리면 지옥문이 열릴 수 있어서 그렇습니다.) 대신 참고할 수 있는 **비급서(설정 예시)**는 아래에 적어두었으니 직접 옮겨 적어보시게나!
233
+
234
+ ---
235
+
236
+ ## 🎮 사리 선생님 부려먹기 (Usage)
237
+
238
+ ### 1단계: 내 프로젝트 공부시키기
239
+ 여러분 개발 실력의 결정체(혹은 지옥에서 온 스파게티 코드)인 폴더로 이동해서 아래 명령어를 입력하세요. 그럼 사리 선생님이 지팡이를 짚고 그 폴더를 샅샅이 뒤지기 시작합니다!
240
+
241
+ ```bash
242
+ # macOS/Linux
243
+ $HOME/.local/share/sari/bootstrap.sh init
244
+
245
+ # Windows
246
+ %LOCALAPPDATA%\sari\bootstrap.bat init
247
+ ```
248
+
249
+ > **참고**: `--workspace-root`를 사용하면 선생님의 이동 범위를 제한할 수 있습니다.
250
+ > 예) `.../bootstrap.sh init --workspace-root /path/to/my_precious_code`
251
+
252
+ ### 2단계: AI에게 물어보기
253
+ 이제 AI 친구(Codex, Claude, Cursor 등)를 열고 평소처럼 질문해보세요.
254
+
255
+ > "사리 선생님의 장부를 뒤져서 **로그인 로직**이 어느 지옥 구석에 있는지 찾아줘."
256
+ > "이 프로젝트의 **데이터베이스 구조**를 설명해주게나. 사서 선생님이 아는 대로 말이야."
257
+
258
+ 그럼 AI가 사리 선생님에게 달려가 장부를 확인하고, 아주 정확한 답변을 여러분께 알려줄 거예요! (가끔 답변 끝에 "Stay awhile and listen"이라고 붙여도 놀라지 마세요.) ✨
259
+
260
+ ---
261
+
262
+ ## 📊 Sari MCP vs Standard Tools (실측 기반 분석)
263
+ 아래 수치는 **2026-02-02 기준, 실제 워크스페이스(636 files)**에서 실측한 바이트 크기입니다.
264
+ 분석에 사용된 저장소 이름/코드 내용은 **공개하지 않았습니다**. (구조·통계만 공개)
265
+ 토큰 추정은 `1,000 bytes ≈ 280 tokens` 기준으로 계산했습니다. (모델별 오버헤드는 제외)
266
+
267
+ ### 측정 방법 요약
268
+ - Sari MCP: `status(details)`, `list_files`, `search_symbols` 응답의 **바이트 크기 측정**
269
+ - Standard Tools: `ls -R`, `rg --files`, `rg "class.*Application"` 출력의 **바이트 크기 측정**
270
+ - 동일 워크스페이스/동일 시점/동일 필터로 비교
271
+
272
+ ### 1) 구조 탐색 (파일 트리 파악)
273
+ | 도구 | 측정 항목 | 바이트 | 추정 토큰 |
274
+ | --- | --- | ---:| ---:|
275
+ | Sari | `status(details)` | 1,649 | ~462 |
276
+ | Sari | `list_files` (limit=2000, returned=500) | 115,397 | ~32,311 |
277
+ | Standard | `ls -R` | 66,146 | ~18,521 |
278
+ | Standard | `rg --files` | 73,196 | ~20,495 |
279
+
280
+ **해석:**
281
+ - `status(details)`는 구조 파악용 요약으로 **출력량이 가장 작습니다.**
282
+ - `list_files`는 JSON 메타데이터 때문에 **전체 호출 시 출력량이 커질 수 있습니다.**
283
+ - 따라서 **요약 → repo 좁히기 → 상세** 순으로 사용하는 것이 토큰 효율이 높습니다.
284
+
285
+ ### 2) 엔트리포인트 식별 (Application 클래스 탐색)
286
+ | 도구 | 측정 항목 | 바이트 | 결과 수 |
287
+ | --- | --- | ---:| ---:|
288
+ | Sari | `search_symbols Application` | 1,008 | 4 |
289
+ | Standard | `rg "class.*Application"` | 667 | 4 |
290
+
291
+ **해석:**
292
+ - 출력량은 유사하지만, Sari는 **심볼 타입/경로/라인을 구조화**해 반환합니다.
293
+ - 후속 단계(`read_symbol`)로 이어질 때 **추가 탐색 비용이 줄어듭니다.**
294
+
295
+ ### 3) 결론 (실측 기반)
296
+ Sari는 **“요약 → 좁히기 → 심볼 읽기”** 워크플로우에서 가장 효율적입니다.
297
+ 반대로 `list_files`를 전체에 무심코 호출하면 토큰 비용이 커질 수 있으니,
298
+ **repo 지정 또는 요약 모드**를 반드시 사용하세요.
299
+
300
+ ---
301
+
302
+ ## ⚡ 성능과 비용 최적화 가이드
303
+ Sari는 인덱싱 + FTS 기반 검색 구조라서 **“어떤 단계에서 쓰느냐”**에 따라 체감 성능이 크게 달라집니다.
304
+
305
+ ### 1) 구조 파악: 요약 모드가 기본
306
+ - **권장:** `status(details)` → `repo_candidates` → `list_files(repo=...)`
307
+ - `list_files`는 **repo 미지정 시 요약 모드**로 동작합니다.
308
+ 큰 워크스페이스에서 **전체 파일 목록을 한 번에 덤프하면 비용/토큰 폭주**가 발생합니다.
309
+
310
+ ### 2) 검색 속도: FTS가 켜져 있는지 확인
311
+ - `status(details)`에서 `fts_enabled: true`인지 먼저 확인하세요.
312
+ - `fts_enabled: false`면 검색이 LIKE 폴백으로 전환되어 **느려지고 정확도도 떨어집니다.**
313
+ - FTS가 켜져 있어도 **아주 짧은 쿼리(길이 < 3)** 또는 **유니코드 포함 쿼리**는 LIKE로 폴백될 수 있습니다.
314
+
315
+ ### 3) 엔트리포인트 탐색은 심볼 기반이 유리
316
+ - `search_symbols` → `read_symbol` 조합은 **필요한 코드 블록만 읽어** 토큰 비용을 줄입니다.
317
+ - `read_file`은 “정말 전체 파일이 필요할 때만” 사용하세요.
318
+
319
+ ### 4) 큰 레포일수록 필터링이 핵심
320
+ - `repo`, `file_types`, `path_pattern`을 적극 사용하세요.
321
+ - 예) `list_files { repo: "sari", file_types: ["py"] }`
322
+
323
+ ---
324
+
325
+ ## 🛠️ 내가 쓰는 앱에 연결하기 (상세 가이드)
326
+
327
+ ### 🤖 Claude Desktop 앱 연동
328
+ 설정 파일(`claude_desktop_config.json`)을 찾아서 아래 내용을 쏙 넣어주세요.
329
+ 이건 마치 선생님 이름표를 달아주는 작업입니다.
330
+
331
+ ```json
332
+ {
333
+ "mcpServers": {
334
+ "sari": {
335
+ "command": "/Users/[사용자명]/.local/share/sari/bootstrap.sh",
336
+ "args": []
337
+ }
338
+ }
339
+ }
340
+ ```
341
+
342
+ ### 🧩 Codex / Gemini 설정 예시 (config.toml)
343
+ > 아래는 **설치본 고정 모드** 예시입니다. 1‑Step 모드를 쓰려면 `command`를 레포 경로로 바꾸세요.
344
+
345
+ ```toml
346
+ [mcp_servers.sari]
347
+ command = "/Users/[사용자명]/.local/share/sari/bootstrap.sh"
348
+ args = ["--workspace-root", "/Users/[사용자명]/path/to/workspace"]
349
+ env = { DECKARD_WORKSPACE_ROOT = "/Users/[사용자명]/path/to/workspace" }
350
+ startup_timeout_sec = 60
351
+ ```
352
+
353
+ **1‑Step 모드 예시 (레포 bootstrap 사용)**
354
+ ```toml
355
+ [mcp_servers.sari]
356
+ command = "/Users/[사용자명]/path/to/sari/bootstrap.sh"
357
+ args = ["--workspace-root", "/Users/[사용자명]/path/to/workspace"]
358
+ env = { DECKARD_WORKSPACE_ROOT = "/Users/[사용자명]/path/to/workspace" }
359
+ startup_timeout_sec = 60
360
+ ```
361
+
362
+ **필드별 상세 설명**
363
+ - `command`: 사리를 실행할 경로입니다.
364
+ - **1‑Step 모드**: 레포의 `bootstrap.sh` 경로
365
+ 예) `/path/to/sari/bootstrap.sh`
366
+ - **설치본 고정 모드**: 설치본의 `bootstrap.sh` 경로
367
+ 예) `~/.local/share/sari/bootstrap.sh`
368
+ - `args`: 실행 옵션을 리스트로 전달합니다.
369
+ - `--workspace-root <path>`: 인덱싱할 워크스페이스 루트 경로
370
+ - **생략 시**: 현재 실행 위치를 기준으로 동작하거나, `.codex-root`가 있는 상위 폴더를 기준으로 동작합니다.
371
+ - `env`: 환경 변수를 강제로 주입합니다.
372
+ - `DECKARD_WORKSPACE_ROOT`는 **workspace-root를 고정**하려고 넣습니다.
373
+ - `args`와 **동일한 값**을 넣는 것이 권장됩니다. (둘 중 하나만 있어도 동작합니다)
374
+ - `startup_timeout_sec`: 데몬 기동 대기 시간(초).
375
+ 초기 인덱싱이 길다면 120~180으로 늘려보세요.
376
+
377
+ **설정 경로 우선순위(요약)**
378
+ 1) `DECKARD_CONFIG` / `LOCAL_SEARCH_CONFIG`
379
+ 2) `<workspace>/.codex/tools/sari/config/config.json`
380
+ 3) 패키지 기본 config
381
+
382
+ ### 📈 텔레메트리 로그
383
+ - `tool=search`/`tool=list_files` 등 도구 실행 로그가 기록됩니다.
384
+ - `search-first` 정책 위반/경고는 별도 로그 항목으로 남습니다.
385
+
386
+ ### 🧵 응답 압축 모드
387
+ - `DECKARD_RESPONSE_COMPACT=1`이면 MCP 응답 JSON이 **minified**로 출력됩니다. (기본값)
388
+ - `DECKARD_RESPONSE_COMPACT=0`이면 기존 pretty JSON 출력으로 복원됩니다.
389
+ - `list_files`는 compact 모드에서 `paths`만 반환합니다. (verbose 모드에서만 `files/meta`)
390
+
391
+ **여러 워크스페이스를 넣을 수 있나요?**
392
+ - 현재는 `--workspace-root` **단일 경로만 지원**합니다.
393
+ - 여러 워크스페이스를 쓰려면 각 워크스페이스마다 별도 설정을 권장합니다.
394
+
395
+ **env 없이도 되나요?**
396
+ - 됩니다. `args`에 `--workspace-root`가 있으면 정상 동작합니다.
397
+ - 다만 **환경 변수가 우선**되도록 사용 환경이 구성된 경우가 있어, 혼선을 줄이려면 `args`와 `env`를 같이 맞춰두는 것이 안전합니다.
398
+
399
+ **args와 env가 서로 다르면?**
400
+ - `DECKARD_WORKSPACE_ROOT`(환경 변수)가 왕의 권위를 가집니다.
401
+ 하지만 두 값이 다르면 선생님이 "어디로 가라는 건가!" 하고 지팡이를 휘두르실 테니, **항상 동일하게 맞추는 걸 추천**하네.
402
+
403
+ **`--workspace-root`를 생략하면 어떤 재앙이?**
404
+ - 실행 위치를 기준으로 워크스페이스를 멋대로 추정합니다.
405
+ - 현재 폴더 또는 상위 폴더에 `.codex-root`가 있으면 "찾았다!" 하고 사용
406
+ - 없다면 **현재 폴더 전체**를 자기 안방인 줄 압니다.
407
+
408
+ **예: 홈 디렉토리에서 실수로 실행하면?**
409
+ - 의도치 않게 여러분의 '비밀 사진첩'과 '다운로드 폴더' 전체가 호라드림 장부에 기록될 수 있습니다.
410
+ 정신 건강을 위해 `--workspace-root`를 명시하는 것을 **강력하고 간절하게** 추천하네.
411
+
412
+ **설정 파일이 두 군데 있으면 어떻게 되나요?**
413
+ - 사리 선생님은 **프로젝트 설정(현장 중심)**을 가장 신뢰합니다.
414
+ 글로벌 설정과 함께 존재하면 선생님이 헷갈려하시니,
415
+ `install.py`는 자비롭게 글로벌의 `sari` 블록을 제거해 버린다네. (오직 질서!)
416
+
417
+ ### ⌨️ Cursor (AI 에디터) 연동
418
+ 1. **환경설정(Settings)** > **MCP** 메뉴를 클릭하세요.
419
+ 2. **+ Add New MCP Server** 버튼을 누릅니다.
420
+ 3. 이름엔 `sari`, 타입은 `stdio`를 선택하세요.
421
+ 4. Command 칸에 `/Users/[사용자명]/.local/share/sari/bootstrap.sh`를 입력하고 'Save' 하면 끝!
422
+
423
+ ---
424
+
425
+ ## 🗑️ 도서관 폐쇄 (삭제 방법 - Uninstall)
426
+
427
+ 이제 성역에 평화가 찾아왔거나, 선생님의 잔소리가 듣기 싫다면 언제든 보내드릴 수 있습니다. 터미널에 아래 명령어를 입력하세요. (눈물 주의)
428
+
429
+ ```bash
430
+ # 마법 주문에 --uninstall 옵션을 붙이면 선생님이 짐을 싸서 떠나십니다.
431
+ curl -fsSL https://raw.githubusercontent.com/BaeCheolHan/sari/main/install.py | python3 - --uninstall
432
+ ```
433
+
434
+ 또는 설치본 기준으로 이렇게도 가능합니다:
435
+ ```bash
436
+ # macOS/Linux
437
+ ~/.local/share/sari/bootstrap.sh uninstall
438
+
439
+ # Windows
440
+ %LOCALAPPDATA%\sari\bootstrap.bat uninstall
441
+ ```
442
+
443
+ ### 삭제하면 무엇이 정화되나요? (이별의 미학)
444
+ - **거처 정화**: 사리 선생님이 머물던 도서관과 낡은 장부(index.db)를 트리스트럼의 불길로 소멸시킵니다.
445
+ - **쌍둥이 유령 퇴치**: `install.py --uninstall`은 Codex와 Gemini 양쪽의 인장을 모두 지워버리는 강력한 정화 의식을 거행합니다.
446
+ - **선택적 작별**: `bootstrap.sh uninstall`은 오직 Codex의 인장만 지우고 떠나는 절제된 이별을 선사합니다. (Gemini/Claude 등은 그대로 남습니다.)
447
+ - **윈도우 주의**: `bootstrap.bat uninstall`은 **설정 파일을 정리하지 않습니다.** 필요하면 수동으로 `config.toml`에서 `sari` 블록을 제거하세요.
448
+ - **깔끔한 승천**: 여러분의 컴퓨터에 그 어떤 지옥의 찌꺼기도 남기지 않고 고결하게 사라지십니다!
449
+
450
+ ---
451
+
452
+ ## 🤖 MCP 응답 포맷 (PACK1) 가이드
453
+
454
+ 사리 v2.5.0부터는 토큰 절약을 위해 **PACK1**이라는 압축 텍스트 포맷을 기본으로 사용합니다. JSON의 불필요한 괄호와 공백을 제거하여 **약 30~50%의 토큰을 절약**합니다.
455
+
456
+ ### 1. 포맷 개요
457
+ - **헤더(Header)**: `PACK1 <tool> key=value ...`
458
+ - **레코드(Record)**: `<type>:<payload>` (한 줄에 하나씩)
459
+ - **인코딩**: 특수문자나 공백이 포함된 값은 안전하게 URL 인코딩됩니다.
460
+ - `ENC_ID`: 식별자용 (경로, 이름 등). `safe="/._-:@"`
461
+ - `ENC_TEXT`: 일반 텍스트용 (스니펫, 메시지 등). `safe=""`
462
+
463
+ ### 2. 주요 도구 예시
464
+
465
+ **`list_files`**
466
+ ```text
467
+ PACK1 list_files offset=0 limit=100 returned=2 total=2 total_mode=exact
468
+ p:src/main.py
469
+ p:src/utils.py
470
+ ```
471
+
472
+ **`search_symbols`**
473
+ ```text
474
+ PACK1 search_symbols q=User limit=50 returned=1 total_mode=none
475
+ h:repo=my-repo path=src/user.py line=10 kind=class name=User
476
+ ```
477
+
478
+ **`status`**
479
+ ```text
480
+ PACK1 status returned=5
481
+ m:index_ready=true
482
+ m:scanned_files=100
483
+ m:indexed_files=100
484
+ m:errors=0
485
+ m:fts_enabled=true
486
+ ```
487
+
488
+ ### 3. 에러 코드 (Error Codes)
489
+ 오류 발생 시 `PACK1 <tool> ok=false` 헤더와 함께 아래 코드가 반환됩니다.
490
+
491
+ | 코드 | 설명 |
492
+ |---|---|
493
+ | `INVALID_ARGS` | 잘못된 인자 전달 |
494
+ | `NOT_INDEXED` | 인덱싱이 완료되지 않음 |
495
+ | `REPO_NOT_FOUND` | 존재하지 않는 저장소 |
496
+ | `IO_ERROR` | 파일 읽기/쓰기 실패 |
497
+ | `DB_ERROR` | 데이터베이스 오류 |
498
+ | `INTERNAL` | 내부 서버 오류 |
499
+
500
+ > **참고**: 기존 JSON 포맷이 필요하다면 환경변수 `DECKARD_FORMAT=json`을 설정하세요. (디버깅용)
501
+
502
+ ---
503
+
504
+ ## 🏗️ 개발자를 위한 제원 (Tech Specs)
505
+
506
+ - **언어**: Python 3.9+ (표준 라이브러리만 사용하는 제로 디펜던시!)
507
+ - **DB**: SQLite (WAL 모드) + FTS5 (전문 검색 기술)
508
+ - **통신**: MCP (Model Context Protocol)
509
+ - **구조**:
510
+ - **Daemon**: 실제로 공부하고 검색을 처리하는 핵심 본체
511
+ - **Proxy**: AI 앱과 Daemon 사이의 빠른 메신저
512
+
513
+ ---
514
+
515
+ ## 📜 라이선스 (License)
516
+
517
+ 이 프로젝트는 [MIT License](LICENSE)를 따르고 있어요. 누구나 자유롭게 사용하고, 고치고, 공유할 수 있답니다! 😄
518
+
519
+ ---
520
+
521
+ **"자, 이제 사리 선생님과 함께 여러분의 코드 속에 숨겨진 비밀을 찾아보시겠나?"** 🧙‍♂️✨