codigest 0.3.9__tar.gz → 0.4.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 (45) hide show
  1. {codigest-0.3.9 → codigest-0.4.0}/.github/workflows/publish.yml +2 -2
  2. codigest-0.4.0/.python-version +1 -0
  3. codigest-0.4.0/CITATION.cff +24 -0
  4. codigest-0.4.0/LICENSE +21 -0
  5. {codigest-0.3.9 → codigest-0.4.0}/PKG-INFO +72 -9
  6. {codigest-0.3.9 → codigest-0.4.0}/README.md +67 -5
  7. {codigest-0.3.9 → codigest-0.4.0}/pyproject.toml +4 -4
  8. codigest-0.4.0/src/codigest/commands/cap.py +78 -0
  9. {codigest-0.3.9 → codigest-0.4.0}/src/codigest/commands/clean.py +6 -6
  10. {codigest-0.3.9 → codigest-0.4.0}/src/codigest/commands/diff.py +10 -8
  11. {codigest-0.3.9 → codigest-0.4.0}/src/codigest/commands/digest.py +15 -13
  12. {codigest-0.3.9 → codigest-0.4.0}/src/codigest/commands/init.py +13 -12
  13. codigest-0.4.0/src/codigest/commands/mcp.py +175 -0
  14. {codigest-0.3.9 → codigest-0.4.0}/src/codigest/commands/scan.py +30 -29
  15. {codigest-0.3.9 → codigest-0.4.0}/src/codigest/commands/semdiff.py +24 -29
  16. {codigest-0.3.9 → codigest-0.4.0}/src/codigest/commands/status.py +18 -20
  17. codigest-0.4.0/src/codigest/commands/term.py +234 -0
  18. {codigest-0.3.9 → codigest-0.4.0}/src/codigest/commands/tree.py +22 -19
  19. {codigest-0.3.9 → codigest-0.4.0}/src/codigest/core/cache.py +34 -53
  20. {codigest-0.3.9 → codigest-0.4.0}/src/codigest/core/common.py +36 -29
  21. {codigest-0.3.9 → codigest-0.4.0}/src/codigest/core/git_ops.py +1 -1
  22. {codigest-0.3.9 → codigest-0.4.0}/src/codigest/core/output.py +6 -6
  23. {codigest-0.3.9 → codigest-0.4.0}/src/codigest/core/processor.py +2 -2
  24. {codigest-0.3.9 → codigest-0.4.0}/src/codigest/core/prompts.py +18 -37
  25. codigest-0.4.0/src/codigest/core/redact.py +88 -0
  26. {codigest-0.3.9 → codigest-0.4.0}/src/codigest/core/resolver.py +40 -59
  27. codigest-0.4.0/src/codigest/core/runner.py +136 -0
  28. {codigest-0.3.9 → codigest-0.4.0}/src/codigest/core/scanner.py +13 -25
  29. {codigest-0.3.9 → codigest-0.4.0}/src/codigest/core/semdiff.py +78 -76
  30. {codigest-0.3.9 → codigest-0.4.0}/src/codigest/core/shadow.py +21 -20
  31. codigest-0.4.0/src/codigest/core/shellhist.py +120 -0
  32. {codigest-0.3.9 → codigest-0.4.0}/src/codigest/core/tags.py +2 -3
  33. codigest-0.4.0/src/codigest/core/termstore.py +272 -0
  34. {codigest-0.3.9 → codigest-0.4.0}/src/codigest/main.py +22 -16
  35. {codigest-0.3.9 → codigest-0.4.0}/src/codigest/options.py +6 -6
  36. codigest-0.4.0/src/codigest/shell/hook.ps1 +116 -0
  37. codigest-0.4.0/tests/test_termstore.py +41 -0
  38. {codigest-0.3.9 → codigest-0.4.0}/uv.lock +2 -2
  39. codigest-0.3.9/.python-version +0 -1
  40. {codigest-0.3.9 → codigest-0.4.0}/.gitignore +0 -0
  41. {codigest-0.3.9 → codigest-0.4.0}/src/codigest/__init__.py +0 -0
  42. {codigest-0.3.9 → codigest-0.4.0}/src/codigest/__main__.py +0 -0
  43. {codigest-0.3.9 → codigest-0.4.0}/src/codigest/config.py +0 -0
  44. {codigest-0.3.9 → codigest-0.4.0}/src/codigest/core/structure.py +0 -0
  45. {codigest-0.3.9 → codigest-0.4.0}/src/codigest/core/tokenizer.py +0 -0
@@ -25,7 +25,7 @@ jobs:
25
25
 
26
26
  # Python 3.14 설정 (uv 이용)
27
27
  - name: Set up Python
28
- run: uv python install 3.14
28
+ run: uv python install 3.15
29
29
 
30
30
  # 의존성 설치 및 빌드 (uv build 하나로 해결)
31
31
  - name: Build package
@@ -48,7 +48,7 @@ jobs:
48
48
  uses: astral-sh/setup-uv@v5
49
49
 
50
50
  - name: Set up Python
51
- run: uv python install 3.14
51
+ run: uv python install 3.15
52
52
 
53
53
  - name: Install Python and Sphinx dependencies
54
54
  run: |
@@ -0,0 +1 @@
1
+ 3.15
@@ -0,0 +1,24 @@
1
+ cff-version: 1.2.0
2
+ message: "If you use this software, please cite it as below."
3
+ type: software
4
+ title: "Codigest: codebase and terminal context manager for LLM-assisted development"
5
+ abstract: >-
6
+ Command-line tool that extracts project snapshots, change-tracked diffs,
7
+ structural (semantic) diffs and captured terminal output as LLM-ready XML,
8
+ and serves them to AI agents over MCP.
9
+ authors:
10
+ - family-names: Yong
11
+ given-names: Isaac
12
+ email: isaacyong@naver.com
13
+ affiliation: Sogang University
14
+ repository-code: "https://github.com/NaNIsaac/codigest"
15
+ url: "https://pypi.org/project/codigest/"
16
+ license: MIT
17
+ version: 0.4.0
18
+ date-released: "2026-10-15"
19
+ keywords:
20
+ - LLM
21
+ - developer tools
22
+ - code context
23
+ - MCP
24
+ - CLI
codigest-0.4.0/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025-2026 Isaac Yong
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.
@@ -1,20 +1,21 @@
1
1
  Metadata-Version: 2.5
2
2
  Name: codigest
3
- Version: 0.3.9
3
+ Version: 0.4.0
4
4
  Summary: Human-Centered Codebase Context Manager for LLMs
5
5
  Project-URL: Homepage, https://github.com/NaNIsaac/codigest
6
6
  Project-URL: Repository, https://github.com/NaNIsaac/codigest
7
7
  Project-URL: Issues, https://github.com/NaNIsaac/codigest/issues
8
- Author-email: Codigest Team <sngd024@google.com>
8
+ Author-email: Isaac Yong <isaacyong@naver.com>
9
9
  License: MIT
10
+ License-File: LICENSE
10
11
  Classifier: Intended Audience :: Developers
11
12
  Classifier: License :: OSI Approved :: MIT License
12
13
  Classifier: Operating System :: OS Independent
13
14
  Classifier: Programming Language :: Python :: 3
14
- Classifier: Programming Language :: Python :: 3.14
15
+ Classifier: Programming Language :: Python :: 3.15
15
16
  Classifier: Topic :: Software Development :: Libraries :: Python Modules
16
17
  Classifier: Topic :: Utilities
17
- Requires-Python: >=3.14
18
+ Requires-Python: >=3.15
18
19
  Requires-Dist: loguru
19
20
  Requires-Dist: pathspec
20
21
  Requires-Dist: pyperclip
@@ -31,12 +32,24 @@ Unlike simple copy-paste tools, Codigest employs a **Context Anchor** system (Sh
31
32
 
32
33
  > **Note:** You can use the short alias **`cdg`** instead of `codigest` for faster typing.
33
34
 
35
+ ## Quickstart
36
+
37
+ ```bash
38
+ uv tool install codigest
39
+
40
+ cdg scan # whole project as LLM-ready XML (copied to clipboard)
41
+ cdg init && cdg diff # set an anchor, later get only what changed
42
+ cdg cap -- pytest -q # run a command and keep its output
43
+ cdg term -f # hand the last failed command + output to your LLM
44
+ claude mcp add codigest -- cdg mcp # let AI agents call all of the above
45
+ ```
46
+
34
47
  ## Core Philosophy
35
48
 
36
49
  * **Read-Only & Safe**: Codigest never modifies your source code. It only reads, analyzes, and formats context.
37
50
  * **Context-Aware**: Instead of dumping raw text, it structures code into XML snapshots designed for LLM comprehension.
38
51
  * **Session-Based Tracking**: It maintains an internal anchor to track "work-in-progress" changes independently of your Git commits.
39
- * **Environment Isolated**: Runs in its own isolated Python 3.14 environment via `uv`, ensuring it never conflicts with your project's dependencies.
52
+ * **Environment Isolated**: Runs in its own isolated Python 3.15 environment via `uv`, ensuring it never conflicts with your project's dependencies.
40
53
 
41
54
  ## Installation
42
55
 
@@ -52,13 +65,12 @@ If you don't have `uv` installed, use **Winget** (Windows) or curl (macOS/Linux)
52
65
  winget install --id astral-sh.uv
53
66
 
54
67
  # macOS/Linux
55
- curl -LsSf [https://astral.sh/uv/install.sh](https://astral.sh/uv/install.sh) | sh
56
-
68
+ curl -LsSf https://astral.sh/uv/install.sh | sh
57
69
  ```
58
70
 
59
71
  ### Step 2: Install `codigest`
60
72
 
61
- Install Codigest globally. `uv` will automatically manage the required Python 3.14 environment for you.
73
+ Install Codigest globally. `uv` will automatically manage the required Python 3.15 environment for you.
62
74
 
63
75
  ```bash
64
76
  uv tool install codigest
@@ -192,6 +204,57 @@ cdg clean
192
204
  cdg clean -y
193
205
  ```
194
206
 
207
+ ### 9. Terminal Capture & Recall (`cap`, `term`)
208
+
209
+ Runs a command transparently (output still streams live) and records its command line, combined stdout/stderr, exit code and cwd in a machine-global store. `term` then recalls recent entries as a `<terminal_history>` block for your LLM. Works in any directory, no `cdg init` needed.
210
+
211
+ * **Use Case:** "This test failed. Here's exactly what I ran and what it printed."
212
+ * **Safety:** Known secret shapes (API keys, tokens, `password=...`) are redacted before anything touches disk. Output of credential commands (`env`, `printenv`, `gh auth token`, ...) is never stored.
213
+ * **Fallback:** Commands not run through `cap` are read from the native shell history (PowerShell, bash, zsh, fish), without output.
214
+
215
+ **Automatic capture (PowerShell):** `cdg term install` hooks your PowerShell profile so *every* command is captured without the `cap` prefix. Commands run in your current session (`cd`, variables and functions behave normally). Editors, pagers, REPLs and `ssh` are skipped automatically.
216
+
217
+ * Skip one command: start the line with a space.
218
+ * Skip more programs: `$env:CODIGEST_CAP_SKIP = '^\s*(myrepl|mytui)\b'`
219
+ * Disable for a session: `$env:CODIGEST_NOCAP = 1`. Remove: `cdg term uninstall`.
220
+ * Trade-off: captured programs write to a pipe, not a TTY, so some lose colors or progress bars.
221
+
222
+ ```bash
223
+ cdg term install # PowerShell: capture everything automatically
224
+
225
+ # Run and capture (prefix with -- so flags reach the command)
226
+ cdg cap -- pytest -q
227
+ cdg cap "npm run build | tail -20"
228
+
229
+ # Recall
230
+ cdg term # last command
231
+ cdg term -n 3 # last 3 commands
232
+ cdg term -i 2 # only the command from 2 runs ago
233
+ cdg term -f # last failed command
234
+
235
+ cdg term path # where captures are stored (override with CODIGEST_HOME)
236
+ cdg term clear # delete all captures
237
+ ```
238
+
239
+ ### 10. For AI Agents (`mcp`)
240
+
241
+ `cdg mcp` serves Codigest as an [MCP](https://modelcontextprotocol.io) server over stdio, so coding agents can pull context themselves instead of asking you to paste it.
242
+
243
+ | Tool | Returns |
244
+ | --- | --- |
245
+ | `terminal_history` | Recent commands with output and exit code (`count`, `failed`) |
246
+ | `scan` | Project snapshot (`targets`, `resolve`, `message`) |
247
+ | `diff` / `semdiff` | Text / structural changes since the anchor |
248
+ | `digest` | Signatures and docstrings only |
249
+ | `tree` | Directory tree |
250
+
251
+ ```bash
252
+ # Claude Code
253
+ claude mcp add --scope user codigest -- cdg mcp
254
+ ```
255
+
256
+ Other clients (Cursor, VS Code, Claude Desktop): add a stdio server with command `cdg` and args `["mcp"]`.
257
+
195
258
  ---
196
259
 
197
260
  ## Configuration
@@ -231,4 +294,4 @@ Codigest maintains a hidden, lightweight Git repository inside `.codigest/anchor
231
294
 
232
295
  ## License
233
296
 
234
- MIT License
297
+ MIT. See [LICENSE](LICENSE).
@@ -6,12 +6,24 @@ Unlike simple copy-paste tools, Codigest employs a **Context Anchor** system (Sh
6
6
 
7
7
  > **Note:** You can use the short alias **`cdg`** instead of `codigest` for faster typing.
8
8
 
9
+ ## Quickstart
10
+
11
+ ```bash
12
+ uv tool install codigest
13
+
14
+ cdg scan # whole project as LLM-ready XML (copied to clipboard)
15
+ cdg init && cdg diff # set an anchor, later get only what changed
16
+ cdg cap -- pytest -q # run a command and keep its output
17
+ cdg term -f # hand the last failed command + output to your LLM
18
+ claude mcp add codigest -- cdg mcp # let AI agents call all of the above
19
+ ```
20
+
9
21
  ## Core Philosophy
10
22
 
11
23
  * **Read-Only & Safe**: Codigest never modifies your source code. It only reads, analyzes, and formats context.
12
24
  * **Context-Aware**: Instead of dumping raw text, it structures code into XML snapshots designed for LLM comprehension.
13
25
  * **Session-Based Tracking**: It maintains an internal anchor to track "work-in-progress" changes independently of your Git commits.
14
- * **Environment Isolated**: Runs in its own isolated Python 3.14 environment via `uv`, ensuring it never conflicts with your project's dependencies.
26
+ * **Environment Isolated**: Runs in its own isolated Python 3.15 environment via `uv`, ensuring it never conflicts with your project's dependencies.
15
27
 
16
28
  ## Installation
17
29
 
@@ -27,13 +39,12 @@ If you don't have `uv` installed, use **Winget** (Windows) or curl (macOS/Linux)
27
39
  winget install --id astral-sh.uv
28
40
 
29
41
  # macOS/Linux
30
- curl -LsSf [https://astral.sh/uv/install.sh](https://astral.sh/uv/install.sh) | sh
31
-
42
+ curl -LsSf https://astral.sh/uv/install.sh | sh
32
43
  ```
33
44
 
34
45
  ### Step 2: Install `codigest`
35
46
 
36
- Install Codigest globally. `uv` will automatically manage the required Python 3.14 environment for you.
47
+ Install Codigest globally. `uv` will automatically manage the required Python 3.15 environment for you.
37
48
 
38
49
  ```bash
39
50
  uv tool install codigest
@@ -167,6 +178,57 @@ cdg clean
167
178
  cdg clean -y
168
179
  ```
169
180
 
181
+ ### 9. Terminal Capture & Recall (`cap`, `term`)
182
+
183
+ Runs a command transparently (output still streams live) and records its command line, combined stdout/stderr, exit code and cwd in a machine-global store. `term` then recalls recent entries as a `<terminal_history>` block for your LLM. Works in any directory, no `cdg init` needed.
184
+
185
+ * **Use Case:** "This test failed. Here's exactly what I ran and what it printed."
186
+ * **Safety:** Known secret shapes (API keys, tokens, `password=...`) are redacted before anything touches disk. Output of credential commands (`env`, `printenv`, `gh auth token`, ...) is never stored.
187
+ * **Fallback:** Commands not run through `cap` are read from the native shell history (PowerShell, bash, zsh, fish), without output.
188
+
189
+ **Automatic capture (PowerShell):** `cdg term install` hooks your PowerShell profile so *every* command is captured without the `cap` prefix. Commands run in your current session (`cd`, variables and functions behave normally). Editors, pagers, REPLs and `ssh` are skipped automatically.
190
+
191
+ * Skip one command: start the line with a space.
192
+ * Skip more programs: `$env:CODIGEST_CAP_SKIP = '^\s*(myrepl|mytui)\b'`
193
+ * Disable for a session: `$env:CODIGEST_NOCAP = 1`. Remove: `cdg term uninstall`.
194
+ * Trade-off: captured programs write to a pipe, not a TTY, so some lose colors or progress bars.
195
+
196
+ ```bash
197
+ cdg term install # PowerShell: capture everything automatically
198
+
199
+ # Run and capture (prefix with -- so flags reach the command)
200
+ cdg cap -- pytest -q
201
+ cdg cap "npm run build | tail -20"
202
+
203
+ # Recall
204
+ cdg term # last command
205
+ cdg term -n 3 # last 3 commands
206
+ cdg term -i 2 # only the command from 2 runs ago
207
+ cdg term -f # last failed command
208
+
209
+ cdg term path # where captures are stored (override with CODIGEST_HOME)
210
+ cdg term clear # delete all captures
211
+ ```
212
+
213
+ ### 10. For AI Agents (`mcp`)
214
+
215
+ `cdg mcp` serves Codigest as an [MCP](https://modelcontextprotocol.io) server over stdio, so coding agents can pull context themselves instead of asking you to paste it.
216
+
217
+ | Tool | Returns |
218
+ | --- | --- |
219
+ | `terminal_history` | Recent commands with output and exit code (`count`, `failed`) |
220
+ | `scan` | Project snapshot (`targets`, `resolve`, `message`) |
221
+ | `diff` / `semdiff` | Text / structural changes since the anchor |
222
+ | `digest` | Signatures and docstrings only |
223
+ | `tree` | Directory tree |
224
+
225
+ ```bash
226
+ # Claude Code
227
+ claude mcp add --scope user codigest -- cdg mcp
228
+ ```
229
+
230
+ Other clients (Cursor, VS Code, Claude Desktop): add a stdio server with command `cdg` and args `["mcp"]`.
231
+
170
232
  ---
171
233
 
172
234
  ## Configuration
@@ -206,4 +268,4 @@ Codigest maintains a hidden, lightweight Git repository inside `.codigest/anchor
206
268
 
207
269
  ## License
208
270
 
209
- MIT License
271
+ MIT. See [LICENSE](LICENSE).
@@ -1,10 +1,10 @@
1
1
  [project]
2
2
  name = "codigest"
3
- version = "0.3.9"
3
+ version = "0.4.0"
4
4
  description = "Human-Centered Codebase Context Manager for LLMs"
5
- authors = [{name = "Codigest Team", email = "sngd024@google.com"}]
5
+ authors = [{ name = "Isaac Yong", email = "isaacyong@naver.com" }]
6
6
  readme = "README.md"
7
- requires-python = ">=3.14"
7
+ requires-python = ">=3.15"
8
8
  license = { text = "MIT" }
9
9
  dependencies = [
10
10
  "typer",
@@ -17,7 +17,7 @@ dependencies = [
17
17
 
18
18
  classifiers = [
19
19
  "Programming Language :: Python :: 3",
20
- "Programming Language :: Python :: 3.14",
20
+ "Programming Language :: Python :: 3.15",
21
21
  "License :: OSI Approved :: MIT License",
22
22
  "Operating System :: OS Independent",
23
23
  "Topic :: Software Development :: Libraries :: Python Modules",
@@ -0,0 +1,78 @@
1
+ """
2
+ `cdg cap` -- run a command transparently and record it for later recall.
3
+
4
+ Registered on the root app as a single command (not a Typer group), so the
5
+ first word after `cap` is treated as the wrapped program rather than a
6
+ subcommand. It declares no options of its own: everything after `cap` belongs
7
+ to the wrapped command, so flags like `-n` are never stolen from it.
8
+ """
9
+ from pathlib import Path
10
+ from typing import Annotated
11
+
12
+ import typer
13
+ from rich.console import Console
14
+
15
+ lazy from ..core import runner, termstore, shellhist
16
+
17
+ err_console = Console(stderr=True)
18
+
19
+ CONTEXT_SETTINGS = {
20
+ "allow_extra_args": True,
21
+ "ignore_unknown_options": True,
22
+ }
23
+
24
+ CommandArgument = Annotated[
25
+ list[str] | None,
26
+ typer.Argument(
27
+ metavar="COMMAND...",
28
+ help="Command to run. Prefix with `--` so its flags are passed through.",
29
+ ),
30
+ ]
31
+
32
+
33
+ def handle(ctx: typer.Context, command: CommandArgument = None) -> None:
34
+ """
35
+ [Capture] Run a command, show its output as usual, and record it globally.
36
+
37
+ Examples:
38
+
39
+ cdg cap -- pytest -q
40
+
41
+ cdg cap "npm run build | tail -20"
42
+ """
43
+ args = [*(command or []), *ctx.args]
44
+
45
+ if not args:
46
+ err_console.print(
47
+ "[yellow]Usage:[/yellow] cdg cap -- <command>\n"
48
+ "[dim]Example: cdg cap -- pytest -q[/dim]"
49
+ )
50
+ raise typer.Exit(code=2)
51
+
52
+ command_text = runner.join_command(args)
53
+
54
+ try:
55
+ exit_code, output, duration_ms = runner.run(args)
56
+ except FileNotFoundError as e:
57
+ err_console.print(f"[red][Error][/red] Command not found: {args[0]}")
58
+ raise typer.Exit(code=127) from e
59
+ except RuntimeError as e:
60
+ err_console.print(f"[red][Error][/red] {e}")
61
+ raise typer.Exit(code=1) from e
62
+
63
+ entry = termstore.Entry(
64
+ command=command_text,
65
+ output=output,
66
+ exit_code=exit_code,
67
+ cwd=str(Path.cwd()),
68
+ shell=shellhist.detect_shell(),
69
+ started_at=termstore.now_iso(),
70
+ duration_ms=duration_ms,
71
+ )
72
+
73
+ try:
74
+ termstore.append_entry(entry)
75
+ except OSError as e:
76
+ err_console.print(f"[dim]⚠️ Capture not stored: {e}[/dim]")
77
+
78
+ raise typer.Exit(code=exit_code)
@@ -1,9 +1,9 @@
1
- import typer
2
- import shutil
3
1
  from pathlib import Path
2
+
3
+ import typer
4
4
  from rich.console import Console
5
5
 
6
- from ..core import common
6
+ lazy from ..core import common
7
7
 
8
8
  app = typer.Typer()
9
9
  console = Console()
@@ -19,7 +19,7 @@ def handle(
19
19
  resolve_path=True
20
20
  ),
21
21
  yes: bool = typer.Option(False, "-y", "--yes", "-f", "--force", help="Skip confirmation prompt"),
22
- ):
22
+ ) -> None:
23
23
  """
24
24
  [Cleanup] Removes the .codigest environment and clears all context anchors and artifacts.
25
25
  """
@@ -38,8 +38,8 @@ def handle(
38
38
  raise typer.Exit()
39
39
 
40
40
  try:
41
- shutil.rmtree(codigest_dir)
41
+ common.remove_tree(codigest_dir)
42
42
  console.print(f"[bold green]✔ Successfully removed .codigest environment from {root_path}[/bold green]")
43
43
  except Exception as e:
44
44
  console.print(f"[bold red]Error removing .codigest:[/bold red] {e}")
45
- raise typer.Exit(1)
45
+ raise typer.Exit(1) from e
@@ -1,17 +1,19 @@
1
- import typer
2
1
  from pathlib import Path
3
- from rich.progress import Progress, SpinnerColumn, TextColumn
2
+
3
+ import typer
4
4
 
5
5
  from ..options import CopyOption, StdoutOption, ResolveOption, MessageOption
6
- from ..core import prompts, shadow, tags, common
7
- from ..core.output import OutputHandler
6
+
7
+ lazy from rich.progress import Progress, SpinnerColumn, TextColumn
8
+ lazy from ..core import prompts, shadow, tags, common
9
+ lazy from ..core.output import OutputHandler
8
10
 
9
11
  app = typer.Typer()
10
12
 
11
13
  @app.callback(invoke_without_command=True)
12
14
  def handle(
13
15
  target: Path = typer.Argument(
14
- Path.cwd(),
16
+ Path.cwd(),
15
17
  help="Target directory to check diff",
16
18
  exists=True,
17
19
  file_okay=False,
@@ -23,7 +25,7 @@ def handle(
23
25
  stdout: StdoutOption = False,
24
26
  message: MessageOption = "",
25
27
  resolve: ResolveOption = False,
26
- ):
28
+ ) -> None:
27
29
  """
28
30
  [Context Update] Shows changes since the last 'codigest scan'.
29
31
  Useful for updating LLM context without re-uploading everything.
@@ -34,7 +36,7 @@ def handle(
34
36
  # [1] Context Setup
35
37
  ctx = common.get_context(target)
36
38
  root_path = ctx.root_path
37
-
39
+
38
40
  anchor = shadow.ContextAnchor(root_path)
39
41
 
40
42
  # Check Baseline
@@ -84,7 +86,7 @@ def handle(
84
86
 
85
87
  # [4] Output
86
88
  log_console.print(f"[bold green]Changes Detected![/bold green] ({len(formatted_diff)} chars)")
87
-
89
+
88
90
  def _save():
89
91
  if save:
90
92
  out_path = root_path / ".codigest" / "changes.diff"
@@ -1,10 +1,12 @@
1
- import typer
2
1
  from pathlib import Path
3
- from rich.progress import Progress, SpinnerColumn, TextColumn
2
+
3
+ import typer
4
4
 
5
5
  from ..options import CopyOption, StdoutOption, ResolveOption, MessageOption
6
- from ..core import structure, prompts, semdiff, tags, tokenizer, common, cache
7
- from ..core.output import OutputHandler
6
+
7
+ lazy from rich.progress import Progress, SpinnerColumn, TextColumn
8
+ lazy from ..core import structure, prompts, semdiff, tags, tokenizer, common, cache
9
+ lazy from ..core.output import OutputHandler
8
10
 
9
11
  app = typer.Typer()
10
12
 
@@ -16,7 +18,7 @@ def handle(
16
18
  stdout: StdoutOption = False,
17
19
  message: MessageOption = "",
18
20
  resolve: ResolveOption = False,
19
- ):
21
+ ) -> None:
20
22
  """
21
23
  [Architectural View] Summarizes the codebase structure (Classes/Functions only).
22
24
  """
@@ -26,7 +28,7 @@ def handle(
26
28
  # [1] Context Setup
27
29
  ctx = common.get_context(target)
28
30
  root_path = ctx.root_path
29
-
31
+
30
32
  prompt_engine = prompts.get_engine(root_path)
31
33
 
32
34
  with Progress(
@@ -35,12 +37,12 @@ def handle(
35
37
  transient=True,
36
38
  console=log_console
37
39
  ) as progress:
38
-
40
+
39
41
  task = progress.add_task("digest", total=None)
40
-
42
+
41
43
  # [2] File Discovery via Context
42
44
  files = ctx.get_target_files(ignore_config=False, resolve_deps=resolve)
43
-
45
+
44
46
  tree_str = structure.generate_ascii_tree(files, root_path)
45
47
 
46
48
  content_cache = cache.ContentCache(root_path)
@@ -72,7 +74,7 @@ def handle(
72
74
  content_cache.save()
73
75
 
74
76
  summary_blob = "\n".join(summary_blocks)
75
-
77
+
76
78
  try:
77
79
  digest_content = prompt_engine.render(
78
80
  "digest",
@@ -83,13 +85,13 @@ def handle(
83
85
  )
84
86
  except Exception as e:
85
87
  log_console.print(f"[red]❌ Rendering Failed:[/red] {e}")
86
- raise typer.Exit(1)
87
-
88
+ raise typer.Exit(1) from e
89
+
88
90
  progress.update(task, completed=100)
89
91
 
90
92
  token_count = tokenizer.estimate_tokens(digest_content)
91
93
  log_console.print(f"[bold green]Digest Generated![/bold green] ([bold cyan]~{token_count:,} Tokens[/bold cyan])")
92
-
94
+
93
95
  def _save():
94
96
  if save:
95
97
  out_path = root_path / ".codigest" / "digest.txt"
@@ -1,9 +1,10 @@
1
- import typer
2
1
  from pathlib import Path
2
+
3
+ import typer
3
4
  from rich.console import Console
4
- from rich.panel import Panel
5
5
 
6
- from ..core import scanner, shadow
6
+ lazy from rich.panel import Panel
7
+ lazy from ..core import scanner, shadow
7
8
 
8
9
  app = typer.Typer()
9
10
  console = Console()
@@ -13,7 +14,7 @@ DEFAULT_CONFIG = """# Codigest Configuration File
13
14
  description = "Auto-generated context configuration"
14
15
 
15
16
  [filter]
16
- max_file_size_kb = 100
17
+ max_file_size_kb = 100
17
18
  extensions = [
18
19
  ".py", ".pyi",
19
20
  ".ts", ".tsx", ".js", ".jsx",
@@ -37,7 +38,7 @@ structure = "toon"
37
38
  def handle(
38
39
  # target 인자 추가 (기본값: 현재 위치)
39
40
  target: Path = typer.Argument(
40
- Path.cwd(),
41
+ Path.cwd(),
41
42
  help="Target directory to initialize",
42
43
  exists=True,
43
44
  file_okay=False,
@@ -45,12 +46,12 @@ def handle(
45
46
  resolve_path=True
46
47
  ),
47
48
  force: bool = typer.Option(False, "--force", "-f", help="Overwrite existing config"),
48
- ):
49
+ ) -> None:
49
50
  """
50
51
  Initialize the .codigest environment and capture the initial state.
51
52
  """
52
53
  root_path = target # Typer가 이미 resolve_path=True로 절대경로 변환해줌
53
-
54
+
54
55
  config_dir = root_path / ".codigest"
55
56
  config_file = config_dir / "config.toml"
56
57
  gitignore_file = root_path / ".gitignore"
@@ -61,7 +62,7 @@ def handle(
61
62
  if not config_dir.exists():
62
63
  config_dir.mkdir()
63
64
  console.print(" [green]✔[/green] Created [bold].codigest/[/bold] directory")
64
-
65
+
65
66
  if not config_file.exists() or force:
66
67
  config_file.write_text(DEFAULT_CONFIG, encoding="utf-8")
67
68
  console.print(" [green]✔[/green] Created [bold]config.toml[/bold]")
@@ -75,22 +76,22 @@ def handle(
75
76
  console.print("\n[dim]Creating initial context anchor...[/dim]")
76
77
  try:
77
78
  # Default scan settings for initialization
78
- files = scanner.scan_project(root_path)
79
+ files = scanner.scan_project(root_path)
79
80
  anchor = shadow.ContextAnchor(root_path)
80
81
  anchor.update(files)
81
82
  console.print(" [green]✔[/green] Baseline snapshot captured.")
82
83
  except Exception as e:
83
84
  console.print(f" [red]⚠️ Failed to create initial anchor: {e}[/red]")
84
85
 
85
- console.print("\n[bold green]✨ Ready to digest![/bold green]")
86
+ console.print("\n[bold green]✨ Ready to digest![/bold green]")
86
87
  console.print("Try running: [cyan]codigest diff[/cyan] to see changes from now on.")
87
88
 
88
- def _update_gitignore(path: Path):
89
+ def _update_gitignore(path: Path) -> None:
89
90
  entry = ".codigest/"
90
91
  if not path.exists():
91
92
  path.write_text(f"# Git Ignore\n{entry}\n", encoding="utf-8")
92
93
  return
93
-
94
+
94
95
  if entry not in path.read_text(encoding="utf-8"):
95
96
  with path.open("a", encoding="utf-8") as f:
96
97
  f.write(f"\n{entry}\n")