legalize-cli 0.1.0__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 (111) hide show
  1. legalize_cli-0.1.0/.gitignore +11 -0
  2. legalize_cli-0.1.0/LICENSE +21 -0
  3. legalize_cli-0.1.0/PKG-INFO +614 -0
  4. legalize_cli-0.1.0/README.md +556 -0
  5. legalize_cli-0.1.0/pyproject.toml +75 -0
  6. legalize_cli-0.1.0/src/legalize_cli/__init__.py +5 -0
  7. legalize_cli-0.1.0/src/legalize_cli/__main__.py +66 -0
  8. legalize_cli-0.1.0/src/legalize_cli/auth.py +56 -0
  9. legalize_cli-0.1.0/src/legalize_cli/cache.py +227 -0
  10. legalize_cli-0.1.0/src/legalize_cli/commands/__init__.py +0 -0
  11. legalize_cli-0.1.0/src/legalize_cli/commands/article.py +117 -0
  12. legalize_cli-0.1.0/src/legalize_cli/commands/asof_cmd.py +222 -0
  13. legalize_cli-0.1.0/src/legalize_cli/commands/auth_cmd.py +62 -0
  14. legalize_cli-0.1.0/src/legalize_cli/commands/cache_cmd.py +126 -0
  15. legalize_cli-0.1.0/src/legalize_cli/commands/diff.py +167 -0
  16. legalize_cli-0.1.0/src/legalize_cli/commands/list_laws.py +100 -0
  17. legalize_cli-0.1.0/src/legalize_cli/commands/list_precedents.py +83 -0
  18. legalize_cli-0.1.0/src/legalize_cli/commands/mcp_cmd.py +35 -0
  19. legalize_cli-0.1.0/src/legalize_cli/commands/precedent.py +65 -0
  20. legalize_cli-0.1.0/src/legalize_cli/commands/search_cmd.py +149 -0
  21. legalize_cli-0.1.0/src/legalize_cli/config.py +58 -0
  22. legalize_cli-0.1.0/src/legalize_cli/github/__init__.py +0 -0
  23. legalize_cli-0.1.0/src/legalize_cli/github/blobs.py +24 -0
  24. legalize_cli-0.1.0/src/legalize_cli/github/commits.py +81 -0
  25. legalize_cli-0.1.0/src/legalize_cli/github/contents.py +68 -0
  26. legalize_cli-0.1.0/src/legalize_cli/github/search_code.py +50 -0
  27. legalize_cli-0.1.0/src/legalize_cli/github/trees.py +57 -0
  28. legalize_cli-0.1.0/src/legalize_cli/http.py +198 -0
  29. legalize_cli-0.1.0/src/legalize_cli/laws/__init__.py +0 -0
  30. legalize_cli-0.1.0/src/legalize_cli/laws/articles.py +211 -0
  31. legalize_cli-0.1.0/src/legalize_cli/laws/asof.py +94 -0
  32. legalize_cli-0.1.0/src/legalize_cli/laws/diff.py +233 -0
  33. legalize_cli-0.1.0/src/legalize_cli/laws/frontmatter.py +82 -0
  34. legalize_cli-0.1.0/src/legalize_cli/laws/list.py +107 -0
  35. legalize_cli-0.1.0/src/legalize_cli/laws/model.py +89 -0
  36. legalize_cli-0.1.0/src/legalize_cli/laws/revisions.py +76 -0
  37. legalize_cli-0.1.0/src/legalize_cli/laws/status.py +45 -0
  38. legalize_cli-0.1.0/src/legalize_cli/mcp_server.py +404 -0
  39. legalize_cli-0.1.0/src/legalize_cli/precedents/__init__.py +0 -0
  40. legalize_cli-0.1.0/src/legalize_cli/precedents/fetch.py +63 -0
  41. legalize_cli-0.1.0/src/legalize_cli/precedents/index.py +112 -0
  42. legalize_cli-0.1.0/src/legalize_cli/precedents/list.py +41 -0
  43. legalize_cli-0.1.0/src/legalize_cli/precedents/model.py +28 -0
  44. legalize_cli-0.1.0/src/legalize_cli/rate_limit.py +90 -0
  45. legalize_cli-0.1.0/src/legalize_cli/search/__init__.py +0 -0
  46. legalize_cli-0.1.0/src/legalize_cli/search/code_search.py +37 -0
  47. legalize_cli-0.1.0/src/legalize_cli/search/metadata_search.py +37 -0
  48. legalize_cli-0.1.0/src/legalize_cli/search/strategies.py +37 -0
  49. legalize_cli-0.1.0/src/legalize_cli/search/tree_filter.py +79 -0
  50. legalize_cli-0.1.0/src/legalize_cli/search/unicode.py +33 -0
  51. legalize_cli-0.1.0/src/legalize_cli/util/__init__.py +0 -0
  52. legalize_cli-0.1.0/src/legalize_cli/util/article_parse.py +49 -0
  53. legalize_cli-0.1.0/src/legalize_cli/util/cli_common.py +107 -0
  54. legalize_cli-0.1.0/src/legalize_cli/util/errors.py +77 -0
  55. legalize_cli-0.1.0/src/legalize_cli/util/normalize.py +39 -0
  56. legalize_cli-0.1.0/tests/__init__.py +0 -0
  57. legalize_cli-0.1.0/tests/conftest.py +7 -0
  58. legalize_cli-0.1.0/tests/fixtures/__init__.py +0 -0
  59. legalize_cli-0.1.0/tests/fixtures/github/commits_asof.json +26 -0
  60. legalize_cli-0.1.0/tests/fixtures/github/commits_mingbeop.json +50 -0
  61. legalize_cli-0.1.0/tests/fixtures/github/tree_laws_full.json +31 -0
  62. legalize_cli-0.1.0/tests/fixtures/github/tree_laws_small.json +85 -0
  63. legalize_cli-0.1.0/tests/fixtures/laws/ambiguous_levels.md +19 -0
  64. legalize_cli-0.1.0/tests/fixtures/laws/amended.md +15 -0
  65. legalize_cli-0.1.0/tests/fixtures/laws/article_no_sub.md +15 -0
  66. legalize_cli-0.1.0/tests/fixtures/laws/deleted_article.md +19 -0
  67. legalize_cli-0.1.0/tests/fixtures/laws/mingbeop_2015.md +33 -0
  68. legalize_cli-0.1.0/tests/fixtures/laws/mingbeop_2024.md +39 -0
  69. legalize_cli-0.1.0/tests/fixtures/laws/mingbeop_like.md +37 -0
  70. legalize_cli-0.1.0/tests/fixtures/laws/small_simple.md +22 -0
  71. legalize_cli-0.1.0/tests/fixtures/laws/small_three_hashes.md +21 -0
  72. legalize_cli-0.1.0/tests/fixtures/precedents/metadata_small.json +47 -0
  73. legalize_cli-0.1.0/tests/fixtures/precedents/sample_precedent.md +18 -0
  74. legalize_cli-0.1.0/tests/integration/__init__.py +0 -0
  75. legalize_cli-0.1.0/tests/integration/conftest.py +117 -0
  76. legalize_cli-0.1.0/tests/integration/test_article.py +79 -0
  77. legalize_cli-0.1.0/tests/integration/test_asof.py +92 -0
  78. legalize_cli-0.1.0/tests/integration/test_cli_smoke.py +42 -0
  79. legalize_cli-0.1.0/tests/integration/test_diff.py +159 -0
  80. legalize_cli-0.1.0/tests/integration/test_list_laws.py +109 -0
  81. legalize_cli-0.1.0/tests/integration/test_precedent_get.py +80 -0
  82. legalize_cli-0.1.0/tests/integration/test_search_code.py +63 -0
  83. legalize_cli-0.1.0/tests/integration/test_search_metadata.py +44 -0
  84. legalize_cli-0.1.0/tests/integration/test_search_tree.py +45 -0
  85. legalize_cli-0.1.0/tests/integration/test_timezone_assertion.py +47 -0
  86. legalize_cli-0.1.0/tests/live/__init__.py +0 -0
  87. legalize_cli-0.1.0/tests/live/conftest.py +15 -0
  88. legalize_cli-0.1.0/tests/live/test_smoke_asof_mingbeop.py +21 -0
  89. legalize_cli-0.1.0/tests/live/test_smoke_list_laws.py +19 -0
  90. legalize_cli-0.1.0/tests/live/test_smoke_search.py +30 -0
  91. legalize_cli-0.1.0/tests/unit/__init__.py +0 -0
  92. legalize_cli-0.1.0/tests/unit/test_article_query.py +46 -0
  93. legalize_cli-0.1.0/tests/unit/test_articles.py +108 -0
  94. legalize_cli-0.1.0/tests/unit/test_asof.py +112 -0
  95. legalize_cli-0.1.0/tests/unit/test_auth.py +71 -0
  96. legalize_cli-0.1.0/tests/unit/test_auth_cmd.py +47 -0
  97. legalize_cli-0.1.0/tests/unit/test_cache.py +136 -0
  98. legalize_cli-0.1.0/tests/unit/test_cache_cmd.py +104 -0
  99. legalize_cli-0.1.0/tests/unit/test_commits_parse.py +46 -0
  100. legalize_cli-0.1.0/tests/unit/test_diff.py +89 -0
  101. legalize_cli-0.1.0/tests/unit/test_errors.py +68 -0
  102. legalize_cli-0.1.0/tests/unit/test_force_push_fingerprint.py +98 -0
  103. legalize_cli-0.1.0/tests/unit/test_frontmatter.py +101 -0
  104. legalize_cli-0.1.0/tests/unit/test_heavy_scan_budget.py +86 -0
  105. legalize_cli-0.1.0/tests/unit/test_json_schema_version.py +29 -0
  106. legalize_cli-0.1.0/tests/unit/test_mcp_server.py +51 -0
  107. legalize_cli-0.1.0/tests/unit/test_precedent_index_fetch.py +116 -0
  108. legalize_cli-0.1.0/tests/unit/test_rate_limit.py +105 -0
  109. legalize_cli-0.1.0/tests/unit/test_search_unicode.py +23 -0
  110. legalize_cli-0.1.0/tests/unit/test_trees_parse.py +44 -0
  111. legalize_cli-0.1.0/tests/unit/test_unicode.py +45 -0
@@ -0,0 +1,11 @@
1
+ .venv/
2
+ dist/
3
+ build/
4
+ __pycache__/
5
+ *.egg-info/
6
+ .pytest_cache/
7
+ .coverage
8
+ htmlcov/
9
+ .cache/
10
+ *.pyc
11
+ .omc/
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 legalize-kr contributors
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.
@@ -0,0 +1,614 @@
1
+ Metadata-Version: 2.4
2
+ Name: legalize-cli
3
+ Version: 0.1.0
4
+ Summary: API-first CLI for Korean laws and precedents mirrored by legalize-kr.
5
+ Project-URL: Homepage, https://github.com/legalize-kr
6
+ Project-URL: Repository, https://github.com/legalize-kr/legalize-cli
7
+ Project-URL: Issues, https://github.com/legalize-kr/legalize-cli/issues
8
+ Author: legalize-kr contributors
9
+ License: MIT License
10
+
11
+ Copyright (c) 2026 legalize-kr contributors
12
+
13
+ Permission is hereby granted, free of charge, to any person obtaining a copy
14
+ of this software and associated documentation files (the "Software"), to deal
15
+ in the Software without restriction, including without limitation the rights
16
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
17
+ copies of the Software, and to permit persons to whom the Software is
18
+ furnished to do so, subject to the following conditions:
19
+
20
+ The above copyright notice and this permission notice shall be included in all
21
+ copies or substantial portions of the Software.
22
+
23
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
24
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
25
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
26
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
27
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
28
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
29
+ SOFTWARE.
30
+ License-File: LICENSE
31
+ Keywords: cli,github,korean,law,legalize-kr
32
+ Classifier: Development Status :: 3 - Alpha
33
+ Classifier: Environment :: Console
34
+ Classifier: Intended Audience :: Developers
35
+ Classifier: Intended Audience :: Legal Industry
36
+ Classifier: License :: OSI Approved :: MIT License
37
+ Classifier: Natural Language :: Korean
38
+ Classifier: Programming Language :: Python :: 3
39
+ Classifier: Programming Language :: Python :: 3.10
40
+ Classifier: Programming Language :: Python :: 3.11
41
+ Classifier: Programming Language :: Python :: 3.12
42
+ Classifier: Topic :: Utilities
43
+ Requires-Python: >=3.10
44
+ Requires-Dist: httpx>=0.27
45
+ Requires-Dist: pydantic>=2.6
46
+ Requires-Dist: python-dateutil>=2.9
47
+ Requires-Dist: pyyaml>=6.0
48
+ Requires-Dist: regex>=2024.4.16
49
+ Requires-Dist: typer>=0.12
50
+ Provides-Extra: dev
51
+ Requires-Dist: coverage>=7.4; extra == 'dev'
52
+ Requires-Dist: pytest-cov>=5.0; extra == 'dev'
53
+ Requires-Dist: pytest-httpx>=0.30; extra == 'dev'
54
+ Requires-Dist: pytest>=8.0; extra == 'dev'
55
+ Provides-Extra: mcp
56
+ Requires-Dist: mcp>=1.0; extra == 'mcp'
57
+ Description-Content-Type: text/markdown
58
+
59
+ # legalize-cli
60
+
61
+ GitHub REST API로 한국 법령·판례를 조회하는 CLI — 클론 없이, 인증 없이 바로 사용.
62
+
63
+ [legalize-kr](https://github.com/legalize-kr) 미러에서 한국 법령 및 법원 판례를 직접 명령줄로 조회합니다. LLM/에이전트 소비(`--json` 지원)와 사람이 직접 탐색하는 용도 모두를 위해 설계되었습니다.
64
+
65
+ ## 설치
66
+
67
+ Python 3.10+가 필요합니다.
68
+
69
+ ```bash
70
+ # 권장: 격리 설치
71
+ pipx install legalize-cli
72
+
73
+ # venv 또는 CI 내부
74
+ pip install legalize-cli
75
+
76
+ # 설치 없이 바로 실행
77
+ uvx legalize-cli laws list --json
78
+ ```
79
+
80
+ ## 빠른 시작
81
+
82
+ ```bash
83
+ # 법률 목록 조회 (JSON, 처음 5개)
84
+ legalize laws list --category 법률 --json | jq '.items[:5]'
85
+
86
+ # 민법 전문 조회 (2015-06-01 기준)
87
+ legalize laws get 민법 --date 2015-06-01
88
+
89
+ # 민법 특정 조문 조회
90
+ legalize laws article 민법 제839조의2 --date 2015-06-01 --json
91
+
92
+ # 민법 두 시점 비교 (조문별 변경 내역)
93
+ legalize laws diff 민법 민법 --date-a 2015-01-01 --date-b 2024-01-01 --mode article
94
+
95
+ # 법령에서 키워드 검색
96
+ legalize search "부동산 점유취득시효" --in laws --json
97
+ ```
98
+
99
+ ## GitHub 토큰 설정 (Rate Limit 해결)
100
+
101
+ ### 왜 필요한가?
102
+
103
+ GitHub API는 인증 없이 **시간당 60회** 요청만 허용합니다. 토큰을 사용하면 **시간당 5,000회**로 늘어납니다.
104
+
105
+ | 상태 | 요청 한도 |
106
+ |------|-----------|
107
+ | 미인증 (기본) | 60 req/hr (IP당) |
108
+ | GitHub 토큰 사용 | 5,000 req/hr |
109
+
110
+ 명령당 소비 요청 수:
111
+
112
+ | 명령 | 소비 요청 수 (콜드) |
113
+ |------|---------------------|
114
+ | `laws list` | 1회 (이후 1시간 캐시) |
115
+ | `laws get <name> --date D` | 2회 (커밋 조회 + 파일 조회) |
116
+ | `laws diff A B` | 4회 (as-of 해석 2회 × 2) |
117
+ | `search --heavy-content-scan` | 최대 N회 (후보 수만큼); 토큰 없으면 `--yes-exhaust-quota` 필요 |
118
+
119
+ ### 토큰 발급 방법
120
+
121
+ **방법 1: GitHub CLI 사용 (가장 간단)**
122
+
123
+ ```bash
124
+ # GitHub CLI 설치 후 로그인
125
+ gh auth login
126
+
127
+ # 현재 로그인된 토큰을 환경변수로 설정
128
+ export GITHUB_TOKEN=$(gh auth token)
129
+ ```
130
+
131
+ **방법 2: Personal Access Token (PAT) 직접 발급**
132
+
133
+ 1. [GitHub → Settings → Developer settings → Personal access tokens → Tokens (classic)](https://github.com/settings/tokens) 접속
134
+ 2. **"Generate new token (classic)"** 클릭
135
+ 3. Note: `legalize-cli` 입력
136
+ 4. 권한 선택: **`public_repo` 스코프만 체크** (공개 저장소 읽기 전용으로 충분)
137
+ 5. 생성된 토큰을 복사
138
+
139
+ ```bash
140
+ # 환경변수로 설정 (셸 프로파일에 추가 권장)
141
+ export GITHUB_TOKEN=ghp_xxxxxxxxxxxxxxxxxxxx
142
+ ```
143
+
144
+ **방법 3: Fine-grained Personal Access Token (더 안전)**
145
+
146
+ 1. [GitHub → Settings → Developer settings → Personal access tokens → Fine-grained tokens](https://github.com/settings/tokens?type=beta) 접속
147
+ 2. **"Generate new token"** 클릭
148
+ 3. Repository access: **"Public Repositories (read-only)"** 선택
149
+ 4. 별도 권한 추가 없이 생성
150
+
151
+ ```bash
152
+ export GITHUB_TOKEN=github_pat_xxxxxxxxxxxxxxxxxxxx
153
+ ```
154
+
155
+ ### 토큰 적용 방법
156
+
157
+ 우선순위 순서로 세 가지 방식을 지원합니다:
158
+
159
+ ```bash
160
+ # 1순위: 매 명령에 직접 전달
161
+ legalize laws list --token ghp_xxxx
162
+
163
+ # 2순위: 표준 환경변수 (권장)
164
+ export GITHUB_TOKEN=ghp_xxxx
165
+ legalize laws list
166
+
167
+ # 3순위: legalize-cli 전용 환경변수
168
+ export LEGALIZE_GITHUB_TOKEN=ghp_xxxx
169
+ legalize laws list
170
+ ```
171
+
172
+ 셸 프로파일(`~/.bashrc`, `~/.zshrc`)에 추가하면 매번 설정할 필요가 없습니다:
173
+
174
+ ```bash
175
+ echo 'export GITHUB_TOKEN=$(gh auth token)' >> ~/.zshrc
176
+ ```
177
+
178
+ ### 현재 인증 상태 확인
179
+
180
+ ```bash
181
+ legalize auth status --json
182
+ ```
183
+
184
+ 출력 예시:
185
+
186
+ ```json
187
+ {
188
+ "schema_version": "1.0",
189
+ "kind": "auth.status",
190
+ "token_present": true,
191
+ "token_source": "GITHUB_TOKEN",
192
+ "token_preview": "ghp_…****",
193
+ "rate_limit": {
194
+ "limit": 5000,
195
+ "remaining": 4987,
196
+ "used": 13,
197
+ "reset": "2024-01-15T11:00:00+09:00"
198
+ }
199
+ }
200
+ ```
201
+
202
+ ## MCP 서버 (LLM/에이전트 통합)
203
+
204
+ Claude Desktop, Cursor 등 MCP 지원 클라이언트에 legalize-kr을 tool로 등록할 수 있습니다.
205
+
206
+ ### 설치
207
+
208
+ ```bash
209
+ pip install 'legalize-cli[mcp]'
210
+ # 또는
211
+ pipx install 'legalize-cli[mcp]'
212
+ ```
213
+
214
+ ### 제공 Tool 목록
215
+
216
+ | Tool | 설명 |
217
+ |------|------|
218
+ | `laws_list` | 법령 목록 조회 (카테고리·페이지 필터) |
219
+ | `laws_get` | 법령 전문 조회 (날짜 기준) |
220
+ | `laws_article` | 특정 조문 조회 (제839조 등) |
221
+ | `search` | 법령·판례 키워드 검색 |
222
+ | `precedents_list` | 판례 목록 조회 (법원·사건종류 필터) |
223
+ | `precedents_get` | 판례 전문 조회 (사건번호·판례일련번호) |
224
+
225
+ ### Claude Desktop 설정
226
+
227
+ `~/Library/Application Support/Claude/claude_desktop_config.json` 에 추가:
228
+
229
+ ```json
230
+ {
231
+ "mcpServers": {
232
+ "legalize-kr": {
233
+ "command": "legalize-mcp",
234
+ "env": {
235
+ "GITHUB_TOKEN": "ghp_xxxxxxxxxxxxxxxxxxxx"
236
+ }
237
+ }
238
+ }
239
+ }
240
+ ```
241
+
242
+ `legalize-mcp` 대신 `legalize mcp serve`를 사용하는 경우:
243
+
244
+ ```json
245
+ {
246
+ "mcpServers": {
247
+ "legalize-kr": {
248
+ "command": "legalize",
249
+ "args": ["mcp", "serve"],
250
+ "env": {
251
+ "GITHUB_TOKEN": "ghp_xxxxxxxxxxxxxxxxxxxx"
252
+ }
253
+ }
254
+ }
255
+ }
256
+ ```
257
+
258
+ ### Cursor / VS Code (MCP 설정)
259
+
260
+ `.cursor/mcp.json` 또는 `.vscode/mcp.json`:
261
+
262
+ ```json
263
+ {
264
+ "servers": {
265
+ "legalize-kr": {
266
+ "type": "stdio",
267
+ "command": "legalize-mcp",
268
+ "env": {
269
+ "GITHUB_TOKEN": "ghp_xxxxxxxxxxxxxxxxxxxx"
270
+ }
271
+ }
272
+ }
273
+ }
274
+ ```
275
+
276
+ ### 직접 실행 (테스트용)
277
+
278
+ ```bash
279
+ # stdio 서버 직접 실행
280
+ legalize mcp serve
281
+
282
+ # 또는 단축 엔트리포인트
283
+ legalize-mcp
284
+ ```
285
+
286
+ ### 사용 예시 (Claude에서)
287
+
288
+ MCP 서버 등록 후 Claude에게 자연어로 질문할 수 있습니다:
289
+
290
+ > "민법 제750조 조문을 알려줘"
291
+ > "부동산 점유취득시효 관련 판례를 검색해줘"
292
+ > "근로기준법이 2020년과 2024년 사이에 어떻게 바뀌었는지 확인해줘"
293
+
294
+ ### 토큰 설정
295
+
296
+ MCP 서버는 환경변수를 자동으로 읽습니다. `env` 설정에 `GITHUB_TOKEN`을 추가하거나 시스템 환경변수로 미리 설정해두면 됩니다. 토큰 없이도 동작하지만 시간당 60회 제한이 있습니다 (토큰 사용 시 5,000회).
297
+
298
+ **토큰 발급 방법:**
299
+
300
+ ```bash
301
+ # 방법 1: GitHub CLI (가장 간단)
302
+ gh auth login
303
+ export GITHUB_TOKEN=$(gh auth token)
304
+ ```
305
+
306
+ GitHub CLI가 없다면 직접 발급합니다:
307
+
308
+ 1. [GitHub → Settings → Developer settings → Personal access tokens → Tokens (classic)](https://github.com/settings/tokens) 접속
309
+ 2. **"Generate new token (classic)"** 클릭
310
+ 3. 권한: **`public_repo`** 스코프만 체크 (공개 저장소 읽기 전용으로 충분)
311
+ 4. 생성된 토큰을 `claude_desktop_config.json`의 `env.GITHUB_TOKEN`에 입력
312
+
313
+ 더 안전한 Fine-grained token을 사용하려면 [GitHub → Settings → Developer settings → Personal access tokens → Fine-grained tokens](https://github.com/settings/tokens?type=beta)에서 **"Public Repositories (read-only)"** 권한으로 생성합니다. 자세한 내용은 [GitHub 토큰 설정](#github-토큰-설정-rate-limit-해결) 섹션을 참고하세요.
314
+
315
+ ## 명령 레퍼런스
316
+
317
+ ### `laws list` — 법령 목록 조회
318
+
319
+ ```bash
320
+ legalize laws list [--category 법률|시행령|시행규칙|대통령령|all] [--page N] [--page-size M] [--json]
321
+ ```
322
+
323
+ JSON 응답: `{"schema_version": "1.0", "kind": "laws.list", "total": N, "items": [{"name", "path", "category"}], ...}`
324
+
325
+ ### `laws as-of` — 특정 시점 기준 법령 목록
326
+
327
+ 특정 날짜 기준으로 유효한 법령을 나열합니다 (기본값: 오늘, KST).
328
+
329
+ ```bash
330
+ legalize laws as-of [--date YYYY-MM-DD] [--category 법률|...] [--include-repealed] [--semantic 공포일자|시행일자] [--json]
331
+ ```
332
+
333
+ ### `laws get` — 법령 전문 조회
334
+
335
+ ```bash
336
+ legalize laws get <법령명> [--category 법률|시행령|...] [--date YYYY-MM-DD] [--json]
337
+ ```
338
+
339
+ JSON 응답: `{"schema_version": "1.0", "kind": "laws.get", "law", "resolved_commit_date", "frontmatter", "body"}`
340
+
341
+ ### `laws article` — 특정 조문 조회
342
+
343
+ ```bash
344
+ legalize laws article <법령명> <조문번호> [--category X] [--date YYYY-MM-DD] [--json]
345
+ ```
346
+
347
+ 조문번호 형식 모두 허용: `제839조`, `839`, `839조의2`, `839-2`, `제839조의2`
348
+
349
+ JSON 응답: `{"schema_version": "1.0", "kind": "laws.article", "article_no": {"조": "839", "의": "2", "항": null, "호": null}, "status", "annotations", "content", "parent_structure"}`
350
+
351
+ ### `laws diff` — 두 버전 비교
352
+
353
+ 주로 동일 법령의 시점 간 변경을 비교합니다.
354
+
355
+ ```bash
356
+ legalize laws diff <법령-a> <법령-b> [--date-a D] [--date-b D] [--mode unified|side-by-side|article] [--json]
357
+ ```
358
+
359
+ article 모드 상태값: `modified | added | removed | renamed | whitespace-only`
360
+
361
+ ### `precedents list` — 판례 목록 조회
362
+
363
+ ```bash
364
+ legalize precedents list [--court 대법원|하급심] [--type 민사|형사|가사|...] [--page N] [--page-size M] [--json]
365
+ ```
366
+
367
+ ### `precedents get` — 판례 전문 조회
368
+
369
+ 사건번호, 판례일련번호, 또는 경로로 단일 판례를 조회합니다.
370
+
371
+ ```bash
372
+ legalize precedents get <사건번호|path> [--json]
373
+ ```
374
+
375
+ ### `search` — 키워드 검색
376
+
377
+ 법령 및/또는 판례 전체에서 키워드를 검색합니다.
378
+
379
+ ```bash
380
+ legalize search <키워드> [--in laws|precedents|all] [--strategy auto|code|tree|metadata] [--json]
381
+ ```
382
+
383
+ 검색 전략:
384
+ - `code`: GitHub 코드 검색 (토큰 필수, 가장 정확)
385
+ - `tree`: 토큰 없이 경로명 매칭 (빠름)
386
+ - `metadata`: 판례 인덱스 검색 (캐시 후 API 비용 0)
387
+ - `auto`: 토큰 유무에 따라 자동 선택
388
+
389
+ ### `cache info` / `cache clear` — 캐시 관리
390
+
391
+ ```bash
392
+ legalize cache info [--json]
393
+ legalize cache clear [--older-than 7d] [--yes]
394
+ ```
395
+
396
+ ### `auth status` — 인증 상태 확인
397
+
398
+ ```bash
399
+ legalize auth status [--json]
400
+ ```
401
+
402
+ ## 사용 예시
403
+
404
+ ### 예시 1: 민법 특정 조문의 시점별 변화 추적
405
+
406
+ ```bash
407
+ # 2015년과 2024년의 재산분할 관련 조문 비교
408
+ legalize laws diff 민법 민법 \
409
+ --date-a 2015-01-01 \
410
+ --date-b 2024-01-01 \
411
+ --mode article \
412
+ --json | jq '.articles[] | select(.status == "modified")'
413
+ ```
414
+
415
+ ### 예시 2: 조문 내용을 LLM에 투입
416
+
417
+ ```bash
418
+ # 민법 제839조의2 전문을 JSON으로 가져와서 LLM 컨텍스트로 사용
419
+ legalize laws article 민법 제839조의2 --json | jq '{
420
+ 조문: .article_no,
421
+ 상태: .status,
422
+ 기준일: .resolved_commit_date,
423
+ 본문: .content
424
+ }'
425
+ ```
426
+
427
+ ### 예시 3: 부동산 관련 판례 검색 (토큰 없이)
428
+
429
+ ```bash
430
+ # 판례 메타데이터 인덱스에서 검색 (API 비용 없음)
431
+ legalize search "부동산 점유취득시효" --in precedents --strategy metadata --json | \
432
+ jq '.items[:5] | .[] | {사건번호: .사건번호, 법원: .법원명, 날짜: .선고일자}'
433
+ ```
434
+
435
+ ### 예시 4: 법령 전문 검색 (토큰 사용)
436
+
437
+ ```bash
438
+ # GitHub 코드 검색으로 법령 본문에서 키워드 검색 (토큰 필수)
439
+ export GITHUB_TOKEN=$(gh auth token)
440
+ legalize search "개인정보 처리" --in laws --strategy code --json | jq '.items'
441
+ ```
442
+
443
+ ### 예시 5: 법령 개정 이력 탐색
444
+
445
+ ```bash
446
+ # 근로기준법 현재 전문 확인
447
+ legalize laws get 근로기준법
448
+
449
+ # 5년 전 시점과 비교
450
+ legalize laws diff 근로기준법 근로기준법 \
451
+ --date-a 2019-01-01 \
452
+ --date-b 2024-01-01 \
453
+ --mode unified
454
+ ```
455
+
456
+ ### 예시 6: 특정 날짜 기준 유효 법령 목록 (시행일자 기준)
457
+
458
+ ```bash
459
+ # 2020-01-01 기준 시행 중인 법률 목록 (시행일자 기준)
460
+ legalize laws as-of --date 2020-01-01 --semantic 시행일자 --category 법률 --json | \
461
+ jq '.items | length'
462
+ ```
463
+
464
+ ### 예시 7: 오프라인 모드 (네트워크 없이 캐시 조회)
465
+
466
+ ```bash
467
+ # 캐시된 데이터만 사용 (네트워크 차단 환경에서 유용)
468
+ legalize laws get 민법 --offline
469
+ legalize search "손해배상" --in precedents --offline --json
470
+ ```
471
+
472
+ ### 예시 8: 판례 전문 조회
473
+
474
+ ```bash
475
+ # 대법원 판례 목록에서 민사 판례 5개 확인
476
+ legalize precedents list --court 대법원 --type 민사 --page-size 5 --json
477
+
478
+ # 사건번호로 특정 판례 조회
479
+ legalize precedents get "2022다12345" --json
480
+ ```
481
+
482
+ ### 예시 9: CI/CD에서 사용 (GitHub Actions)
483
+
484
+ ```yaml
485
+ # .github/workflows/law-check.yml
486
+ - name: 법령 최신 상태 확인
487
+ env:
488
+ GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
489
+ run: |
490
+ uvx legalize-cli laws get 개인정보보호법 --json > current-law.json
491
+ ```
492
+
493
+ ### 예시 10: 캐시 워밍 (대량 조회 전 준비)
494
+
495
+ ```bash
496
+ # 자주 사용하는 법령 미리 캐시
497
+ for law in 민법 형법 상법 근로기준법 개인정보보호법; do
498
+ legalize laws get "$law" > /dev/null
499
+ echo "$law 캐시 완료"
500
+ done
501
+ ```
502
+
503
+ ## 전역 플래그
504
+
505
+ | 플래그 | 설명 |
506
+ |--------|------|
507
+ | `--json` | 기계가 읽기 쉬운 JSON 출력 (안정적 스키마) |
508
+ | `--token <t>` | `$GITHUB_TOKEN` 환경변수를 직접 덮어씀 |
509
+ | `--no-cache` | 디스크 캐시 우회 |
510
+ | `--cache-dir <p>` | 캐시 디렉터리 경로 직접 지정 |
511
+ | `--offline` | 네트워크 호출 거부; 캐시만 읽음 |
512
+ | `-v` / `-vv` | stderr에 로그 상세도 증가 |
513
+
514
+ ## JSON 스키마 버전 관리
515
+
516
+ 모든 `--json` 출력에 `"schema_version": "1.0"`이 포함됩니다.
517
+
518
+ - **마이너 버전 증가** (1.0 → 1.1): 필드 추가만 — 1.x 소비자는 계속 동작
519
+ - **메이저 버전 증가** (1.0 → 2.0): 파괴적 변경
520
+
521
+ CI에서 `tests/unit/test_json_schema_version.py`로 강제 검증합니다.
522
+
523
+ ## 종료 코드
524
+
525
+ | 코드 | 의미 |
526
+ |------|------|
527
+ | 0 | 성공 |
528
+ | 1 | 일반 오류 |
529
+ | 4 | 해당 날짜에 없음 |
530
+ | 5 | 불명확한 헤딩 레벨 (파서) |
531
+ | 6 | 조문을 찾을 수 없음 |
532
+ | 7 | Rate limit 초과 / 인증 필요 |
533
+ | 8 | 파서 오류 |
534
+ | 9 | 오프라인 모드이나 네트워크 필요 |
535
+
536
+ ## 캐시
537
+
538
+ 위치: `~/.cache/legalize-cli/` (`$XDG_CACHE_HOME/legalize-cli/` 또는 `$LEGALIZE_CLI_CACHE_DIR`로 변경 가능)
539
+
540
+ | 서브디렉터리 | TTL | 내용 |
541
+ |-------------|-----|------|
542
+ | `trees/` | 1시간 | 저장소 트리 목록 |
543
+ | `commits/` | 10분 | 경로별 커밋 목록 |
544
+ | `contents/` | 7일 | 법령/판례 마크다운 (경로 + author_date 키) |
545
+ | `precedent-index/` | 24시간 | precedent-kr/metadata.json (~34MB) |
546
+ | `search/` | 1시간 | 코드 검색 결과 |
547
+ | `etag/` | 7일 | 조건부 재검증용 ETag 본문 |
548
+
549
+ ## Force-push 안전성
550
+
551
+ `legalize-kr`과 `precedent-kr` 저장소는 파이프라인이 이력을 재구성할 때 주기적으로 force-push됩니다. 이 도구는 캐시 데이터를 커밋 SHA가 아닌 `(path, author_date)` 기준으로 주소를 지정합니다. 경로별 핑거프린트가 재빌드 후 콘텐츠 변경을 감지하고 오래된 캐시 항목을 자동으로 무효화합니다.
552
+
553
+ ## 문제 해결
554
+
555
+ **"Rate limit exceeded"**
556
+ ```bash
557
+ export GITHUB_TOKEN=$(gh auth token)
558
+ # 또는 GitHub에서 PAT 발급 후:
559
+ export GITHUB_TOKEN=ghp_xxxxxxxxxxxxxxxxxxxx
560
+ ```
561
+
562
+ **"Code search requires authentication"**
563
+ ```bash
564
+ # 토큰 없이 검색하려면 전략을 명시적으로 지정
565
+ legalize search "키워드" --strategy tree # 경로명 매칭
566
+ legalize search "키워드" --strategy metadata # 판례 인덱스만
567
+ ```
568
+
569
+ **오래된 캐시**
570
+ ```bash
571
+ legalize cache clear
572
+ # 또는 특정 기간 이전 캐시만 삭제
573
+ legalize cache clear --older-than 1d --yes
574
+ ```
575
+
576
+ ## 개발자 가이드
577
+
578
+ ### 테스트 실행
579
+
580
+ ```bash
581
+ cd cli-tools
582
+ pip install -e ".[dev]"
583
+ pytest
584
+ ```
585
+
586
+ ### 카세트 재녹화
587
+
588
+ 테스트는 실제 GitHub API를 매번 호출하지 않고 `tests/fixtures/cassettes/`에 녹화된 HTTP 응답을 재생합니다. API 응답 형식이 바뀌거나 새 테스트 케이스를 추가할 때 실제 네트워크로 재녹화합니다.
589
+
590
+ ```bash
591
+ LEGALIZE_CLI_LIVE=1 ./scripts/record-cassettes.sh
592
+ ```
593
+
594
+ 라이브 테스트만 별도로 실행하려면:
595
+
596
+ ```bash
597
+ LEGALIZE_CLI_LIVE=1 pytest tests/live/
598
+ ```
599
+
600
+ ### 의존성
601
+
602
+ | 패키지 | 용도 |
603
+ |--------|------|
604
+ | `typer` | CLI 프레임워크 |
605
+ | `httpx` | HTTP 클라이언트 |
606
+ | `pydantic` | 데이터 검증 |
607
+ | `PyYAML` | frontmatter 파싱 |
608
+ | `regex` | 한국어 조문 번호 파싱 |
609
+ | `python-dateutil` | 날짜 파싱 |
610
+
611
+ ## 라이선스
612
+
613
+ - 법령/판례 텍스트: 공개 도메인 (대한민국 정부 저작물)
614
+ - 이 도구: MIT