codigest 0.3.2__tar.gz → 0.3.5__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 (32) hide show
  1. codigest-0.3.5/PKG-INFO +199 -0
  2. codigest-0.3.5/README.md +174 -0
  3. {codigest-0.3.2 → codigest-0.3.5}/pyproject.toml +2 -1
  4. {codigest-0.3.2 → codigest-0.3.5}/src/codigest/commands/diff.py +25 -24
  5. {codigest-0.3.2 → codigest-0.3.5}/src/codigest/commands/digest.py +16 -11
  6. codigest-0.3.5/src/codigest/commands/scan.py +160 -0
  7. {codigest-0.3.2 → codigest-0.3.5}/src/codigest/commands/semdiff.py +44 -38
  8. codigest-0.3.5/src/codigest/commands/tree.py +82 -0
  9. codigest-0.3.5/src/codigest/core/common.py +118 -0
  10. {codigest-0.3.2 → codigest-0.3.5}/src/codigest/core/prompts.py +2 -2
  11. codigest-0.3.5/src/codigest/core/resolver.py +151 -0
  12. {codigest-0.3.2 → codigest-0.3.5}/src/codigest/core/scanner.py +3 -3
  13. {codigest-0.3.2 → codigest-0.3.5}/src/codigest/core/semdiff.py +3 -3
  14. {codigest-0.3.2 → codigest-0.3.5}/src/codigest/core/shadow.py +69 -27
  15. {codigest-0.3.2 → codigest-0.3.5}/src/codigest/main.py +1 -1
  16. {codigest-0.3.2 → codigest-0.3.5}/uv.lock +5 -1
  17. codigest-0.3.2/PKG-INFO +0 -176
  18. codigest-0.3.2/README.md +0 -151
  19. codigest-0.3.2/src/codigest/commands/scan.py +0 -175
  20. codigest-0.3.2/src/codigest/commands/tree.py +0 -110
  21. {codigest-0.3.2 → codigest-0.3.5}/.github/workflows/publish.yml +0 -0
  22. {codigest-0.3.2 → codigest-0.3.5}/.gitignore +0 -0
  23. {codigest-0.3.2 → codigest-0.3.5}/.python-version +0 -0
  24. {codigest-0.3.2 → codigest-0.3.5}/src/codigest/__init__.py +0 -0
  25. {codigest-0.3.2 → codigest-0.3.5}/src/codigest/__main__.py +0 -0
  26. {codigest-0.3.2 → codigest-0.3.5}/src/codigest/commands/init.py +0 -0
  27. {codigest-0.3.2 → codigest-0.3.5}/src/codigest/config.py +0 -0
  28. {codigest-0.3.2 → codigest-0.3.5}/src/codigest/core/git_ops.py +0 -0
  29. {codigest-0.3.2 → codigest-0.3.5}/src/codigest/core/processor.py +0 -0
  30. {codigest-0.3.2 → codigest-0.3.5}/src/codigest/core/structure.py +0 -0
  31. {codigest-0.3.2 → codigest-0.3.5}/src/codigest/core/tags.py +0 -0
  32. {codigest-0.3.2 → codigest-0.3.5}/src/codigest/core/tokenizer.py +0 -0
@@ -0,0 +1,199 @@
1
+ Metadata-Version: 2.4
2
+ Name: codigest
3
+ Version: 0.3.5
4
+ Summary: Human-Centered Codebase Context Manager for LLMs
5
+ Project-URL: Homepage, https://github.com/SJB777/codigest
6
+ Project-URL: Repository, https://github.com/SJB777/codigest
7
+ Project-URL: Issues, https://github.com/SJB777/codigest/issues
8
+ Author-email: Codigest Team <sngd024@google.com>
9
+ License: MIT
10
+ Classifier: Intended Audience :: Developers
11
+ Classifier: License :: OSI Approved :: MIT License
12
+ Classifier: Operating System :: OS Independent
13
+ Classifier: Programming Language :: Python :: 3
14
+ Classifier: Programming Language :: Python :: 3.14
15
+ Classifier: Topic :: Software Development :: Libraries :: Python Modules
16
+ Classifier: Topic :: Utilities
17
+ Requires-Python: >=3.14
18
+ Requires-Dist: loguru
19
+ Requires-Dist: pathspec
20
+ Requires-Dist: pyperclip
21
+ Requires-Dist: rich
22
+ Requires-Dist: tomli-w
23
+ Requires-Dist: typer
24
+ Description-Content-Type: text/markdown
25
+
26
+ # Codigest
27
+
28
+ **Codigest** is a standalone CLI tool designed to extract, structure, and track the context of your codebase for Large Language Models (LLMs).
29
+
30
+ Unlike simple copy-paste tools, Codigest employs a **Context Anchor** system (Shadow Git) to track changes locally without polluting your main version control history. It also features **Semantic Analysis** to detect structural changes in your code.
31
+
32
+ > **Note:** You can use the short alias **`cdg`** instead of `codigest` for faster typing.
33
+
34
+ ## Core Philosophy
35
+
36
+ * **Read-Only & Safe**: Codigest never modifies your source code. It only reads, analyzes, and formats context.
37
+ * **Context-Aware**: Instead of dumping raw text, it structures code into XML snapshots designed for LLM comprehension.
38
+ * **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.
40
+
41
+ ## Installation
42
+
43
+ Codigest runs as a global tool. You don't need to add it to your project's `requirements.txt`.
44
+ We strongly recommend using **uv** for the best experience.
45
+
46
+ ### Step 1: Install `uv`
47
+
48
+ If you don't have `uv` installed, use **Winget** (Windows) or curl (macOS/Linux).
49
+
50
+ ```powershell
51
+ # Windows (via Winget)
52
+ winget install --id astral-sh.uv
53
+
54
+ # macOS/Linux
55
+ curl -LsSf [https://astral.sh/uv/install.sh](https://astral.sh/uv/install.sh) | sh
56
+
57
+ ```
58
+
59
+ ### Step 2: Install `codigest`
60
+
61
+ Install Codigest globally. `uv` will automatically manage the required Python 3.14 environment for you.
62
+
63
+ ```bash
64
+ uv tool install codigest
65
+ ```
66
+
67
+ ### Step 3: Update Path (Important!)
68
+
69
+ To run `codigest` (or `cdg`) from any terminal, ensure your tools directory is in your PATH.
70
+
71
+ ```bash
72
+ uv tool update-shell
73
+ ```
74
+
75
+ *> **Note:** Restart your terminal (or VS Code) after this step to apply changes.*
76
+
77
+ ---
78
+
79
+ ## Workflow & Commands
80
+
81
+ Once installed, use the **`cdg`** command anywhere.
82
+
83
+ ### 1. Initialization
84
+
85
+ Sets up the `.codigest` directory and captures the initial baseline anchor.
86
+
87
+ ```bash
88
+ cdg init
89
+ ```
90
+
91
+ ### 2. Full Context Snapshot (`scan`)
92
+
93
+ Scans the codebase and generates a structured XML snapshot. Includes a **Pre-flight Check** to prevent accidental token overflow.
94
+
95
+ * **Output:** `.codigest/snapshot.xml`
96
+ * **Features:**
97
+ * **Smart Confirmation:** Automatically skips confirmation for small contexts, but warns you for large ones (>30k tokens).
98
+ * **Dependency Resolution (`-r`):** Automatically finds and includes local files imported by your target files.
99
+ * **Scope Control:** You can specify folders or files to scan.
100
+
101
+
102
+
103
+ ```bash
104
+ # Basic scan (Interactive confirmation if large)
105
+ cdg scan
106
+
107
+ # Scan specific folder with dependency resolution (Smart Context)
108
+ cdg scan src/main.py -r
109
+
110
+ # Force execution without confirmation (Good for CI/CD)
111
+ cdg scan -y --message "Automated snapshot"
112
+ ```
113
+
114
+ ### 3. Incremental Changes (`diff`)
115
+
116
+ Tracks text-based changes between the last `scan` and the current working tree.
117
+
118
+ * **Output:** `.codigest/changes.diff`
119
+ * **Use Case:** "I modified 3 files. Here is exactly what changed since the last snapshot."
120
+ * **Note:** Checks against the internal Shadow Git, enabling tracking without committing to the real Git.
121
+
122
+ ```bash
123
+ cdg diff
124
+ ```
125
+
126
+ ### 4. Semantic Analysis (`semdiff`)
127
+
128
+ Analyzes **structural changes** (AST-based) rather than line-by-line text differences.
129
+
130
+ * **Output:** `.codigest/semdiff.xml`
131
+ * **Use Case:** "I refactored the API. Show me added/removed functions or signature changes."
132
+ * **Benefit:** Reduces token usage by ignoring formatting/comment changes.
133
+
134
+ ```bash
135
+ cdg semdiff
136
+ ```
137
+
138
+ ### 5. Project Tree (`tree`)
139
+
140
+ Visualizes the project structure. Respects `.gitignore`.
141
+
142
+ * **Style:** Professional, cleaner output without emojis for better readability.
143
+ * **Use Case:** Quickly verifying which files are being tracked.
144
+
145
+ ```bash
146
+ cdg tree
147
+ ```
148
+
149
+ ### 6. Architecture Digest (`digest`)
150
+
151
+ Generates a high-level outline of the project structure (Classes, Functions, Methods only).
152
+
153
+ * **Output:** `.codigest/digest.xml`
154
+ * **Use Case:** "Don't read the implementation details. Just understand the class hierarchy."
155
+
156
+ ```bash
157
+ cdg digest
158
+ ```
159
+
160
+ ---
161
+
162
+ ## Configuration
163
+
164
+ You can customize behavior in `.codigest/config.toml`.
165
+
166
+ ```toml
167
+ [filter]
168
+ # Target extensions
169
+ extensions = [".py", ".ts", ".rs", ".md", ".json"]
170
+
171
+ # Exclude patterns (Gitignore syntax)
172
+ exclude_patterns = [
173
+ "*.lock",
174
+ "tests/data/",
175
+ "legacy_code/"
176
+ ]
177
+
178
+ [output]
179
+ format = "xml"
180
+ ```
181
+
182
+ ## Architecture Details
183
+
184
+ **Context Anchor (Shadow Git)**
185
+ Codigest maintains a hidden, lightweight Git repository inside `.codigest/anchor/.shadow_git`.
186
+
187
+ * It is renamed to `.shadow_git` to prevent VS Code and other IDEs from confusing it with your project's actual repository.
188
+ * When you run `scan`, the current state is committed to this anchor.
189
+ * When you run `diff`, the tool compares your working directory against this anchor.
190
+
191
+ **Safety Mechanisms**
192
+
193
+ * **Pre-flight Check:** Calculates estimated token count before processing to prevent context overflow errors.
194
+ * **Structure-Aware Dedent:** Ensures XML tags are perfectly aligned (flush-left) to prevent indentation artifacts in LLM prompts.
195
+ * **XML Injection Protection:** Automatically escapes content within XML tags.
196
+
197
+ ## License
198
+
199
+ MIT License
@@ -0,0 +1,174 @@
1
+ # Codigest
2
+
3
+ **Codigest** is a standalone CLI tool designed to extract, structure, and track the context of your codebase for Large Language Models (LLMs).
4
+
5
+ Unlike simple copy-paste tools, Codigest employs a **Context Anchor** system (Shadow Git) to track changes locally without polluting your main version control history. It also features **Semantic Analysis** to detect structural changes in your code.
6
+
7
+ > **Note:** You can use the short alias **`cdg`** instead of `codigest` for faster typing.
8
+
9
+ ## Core Philosophy
10
+
11
+ * **Read-Only & Safe**: Codigest never modifies your source code. It only reads, analyzes, and formats context.
12
+ * **Context-Aware**: Instead of dumping raw text, it structures code into XML snapshots designed for LLM comprehension.
13
+ * **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.
15
+
16
+ ## Installation
17
+
18
+ Codigest runs as a global tool. You don't need to add it to your project's `requirements.txt`.
19
+ We strongly recommend using **uv** for the best experience.
20
+
21
+ ### Step 1: Install `uv`
22
+
23
+ If you don't have `uv` installed, use **Winget** (Windows) or curl (macOS/Linux).
24
+
25
+ ```powershell
26
+ # Windows (via Winget)
27
+ winget install --id astral-sh.uv
28
+
29
+ # macOS/Linux
30
+ curl -LsSf [https://astral.sh/uv/install.sh](https://astral.sh/uv/install.sh) | sh
31
+
32
+ ```
33
+
34
+ ### Step 2: Install `codigest`
35
+
36
+ Install Codigest globally. `uv` will automatically manage the required Python 3.14 environment for you.
37
+
38
+ ```bash
39
+ uv tool install codigest
40
+ ```
41
+
42
+ ### Step 3: Update Path (Important!)
43
+
44
+ To run `codigest` (or `cdg`) from any terminal, ensure your tools directory is in your PATH.
45
+
46
+ ```bash
47
+ uv tool update-shell
48
+ ```
49
+
50
+ *> **Note:** Restart your terminal (or VS Code) after this step to apply changes.*
51
+
52
+ ---
53
+
54
+ ## Workflow & Commands
55
+
56
+ Once installed, use the **`cdg`** command anywhere.
57
+
58
+ ### 1. Initialization
59
+
60
+ Sets up the `.codigest` directory and captures the initial baseline anchor.
61
+
62
+ ```bash
63
+ cdg init
64
+ ```
65
+
66
+ ### 2. Full Context Snapshot (`scan`)
67
+
68
+ Scans the codebase and generates a structured XML snapshot. Includes a **Pre-flight Check** to prevent accidental token overflow.
69
+
70
+ * **Output:** `.codigest/snapshot.xml`
71
+ * **Features:**
72
+ * **Smart Confirmation:** Automatically skips confirmation for small contexts, but warns you for large ones (>30k tokens).
73
+ * **Dependency Resolution (`-r`):** Automatically finds and includes local files imported by your target files.
74
+ * **Scope Control:** You can specify folders or files to scan.
75
+
76
+
77
+
78
+ ```bash
79
+ # Basic scan (Interactive confirmation if large)
80
+ cdg scan
81
+
82
+ # Scan specific folder with dependency resolution (Smart Context)
83
+ cdg scan src/main.py -r
84
+
85
+ # Force execution without confirmation (Good for CI/CD)
86
+ cdg scan -y --message "Automated snapshot"
87
+ ```
88
+
89
+ ### 3. Incremental Changes (`diff`)
90
+
91
+ Tracks text-based changes between the last `scan` and the current working tree.
92
+
93
+ * **Output:** `.codigest/changes.diff`
94
+ * **Use Case:** "I modified 3 files. Here is exactly what changed since the last snapshot."
95
+ * **Note:** Checks against the internal Shadow Git, enabling tracking without committing to the real Git.
96
+
97
+ ```bash
98
+ cdg diff
99
+ ```
100
+
101
+ ### 4. Semantic Analysis (`semdiff`)
102
+
103
+ Analyzes **structural changes** (AST-based) rather than line-by-line text differences.
104
+
105
+ * **Output:** `.codigest/semdiff.xml`
106
+ * **Use Case:** "I refactored the API. Show me added/removed functions or signature changes."
107
+ * **Benefit:** Reduces token usage by ignoring formatting/comment changes.
108
+
109
+ ```bash
110
+ cdg semdiff
111
+ ```
112
+
113
+ ### 5. Project Tree (`tree`)
114
+
115
+ Visualizes the project structure. Respects `.gitignore`.
116
+
117
+ * **Style:** Professional, cleaner output without emojis for better readability.
118
+ * **Use Case:** Quickly verifying which files are being tracked.
119
+
120
+ ```bash
121
+ cdg tree
122
+ ```
123
+
124
+ ### 6. Architecture Digest (`digest`)
125
+
126
+ Generates a high-level outline of the project structure (Classes, Functions, Methods only).
127
+
128
+ * **Output:** `.codigest/digest.xml`
129
+ * **Use Case:** "Don't read the implementation details. Just understand the class hierarchy."
130
+
131
+ ```bash
132
+ cdg digest
133
+ ```
134
+
135
+ ---
136
+
137
+ ## Configuration
138
+
139
+ You can customize behavior in `.codigest/config.toml`.
140
+
141
+ ```toml
142
+ [filter]
143
+ # Target extensions
144
+ extensions = [".py", ".ts", ".rs", ".md", ".json"]
145
+
146
+ # Exclude patterns (Gitignore syntax)
147
+ exclude_patterns = [
148
+ "*.lock",
149
+ "tests/data/",
150
+ "legacy_code/"
151
+ ]
152
+
153
+ [output]
154
+ format = "xml"
155
+ ```
156
+
157
+ ## Architecture Details
158
+
159
+ **Context Anchor (Shadow Git)**
160
+ Codigest maintains a hidden, lightweight Git repository inside `.codigest/anchor/.shadow_git`.
161
+
162
+ * It is renamed to `.shadow_git` to prevent VS Code and other IDEs from confusing it with your project's actual repository.
163
+ * When you run `scan`, the current state is committed to this anchor.
164
+ * When you run `diff`, the tool compares your working directory against this anchor.
165
+
166
+ **Safety Mechanisms**
167
+
168
+ * **Pre-flight Check:** Calculates estimated token count before processing to prevent context overflow errors.
169
+ * **Structure-Aware Dedent:** Ensures XML tags are perfectly aligned (flush-left) to prevent indentation artifacts in LLM prompts.
170
+ * **XML Injection Protection:** Automatically escapes content within XML tags.
171
+
172
+ ## License
173
+
174
+ MIT License
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "codigest"
3
- version = "0.3.2"
3
+ version = "0.3.5"
4
4
  description = "Human-Centered Codebase Context Manager for LLMs"
5
5
  authors = [{name = "Codigest Team", email = "sngd024@google.com"}]
6
6
  readme = "README.md"
@@ -32,6 +32,7 @@ Issues = "https://github.com/SJB777/codigest/issues"
32
32
 
33
33
  [project.scripts]
34
34
  codigest = "codigest.main:app"
35
+ cdg = "codigest.main:app"
35
36
 
36
37
  [build-system]
37
38
  requires = ["hatchling"]
@@ -4,15 +4,13 @@ from pathlib import Path
4
4
  from rich.console import Console
5
5
  from rich.progress import Progress, SpinnerColumn, TextColumn
6
6
 
7
- from ..core import scanner, prompts, shadow
8
- from .scan import _load_config_filters
7
+ from ..core import prompts, shadow, tags, common
9
8
 
10
9
  app = typer.Typer()
11
10
  console = Console()
12
11
 
13
12
  @app.callback(invoke_without_command=True)
14
13
  def handle(
15
- # target 인자 추가
16
14
  target: Path = typer.Argument(
17
15
  Path.cwd(),
18
16
  help="Target directory to check diff",
@@ -24,24 +22,29 @@ def handle(
24
22
  copy: bool = typer.Option(True, help="Auto-copy to clipboard"),
25
23
  save: bool = typer.Option(True, help="Save to .codigest/changes.diff"),
26
24
  message: str = typer.Option("", "--message", "-m", help="Add specific instruction context"),
25
+ # [추가] resolve 옵션
26
+ resolve: bool = typer.Option(False, "-r", "--resolve", help="Recursively resolve imports"),
27
27
  ):
28
28
  """
29
29
  [Context Update] Shows changes since the last 'codigest scan'.
30
30
  Useful for updating LLM context without re-uploading everything.
31
31
  """
32
- root_path = target
33
- anchor = shadow.ContextAnchor(root_path)
32
+ # [1] Context Setup
33
+ ctx = common.get_context(target)
34
+ root_path = ctx.root_path
34
35
 
35
- # 1. Check Baseline Existence
36
+ anchor = shadow.ContextAnchor(root_path)
37
+
38
+ # Check Baseline
36
39
  last_update = anchor.get_last_update_time()
37
40
  if last_update == "Never":
38
41
  console.print("[yellow]⚠️ No scan history found.[/yellow]")
39
- console.print(" Run [bold cyan]codigest scan[/bold cyan] first to establish a baseline.")
42
+ console.print(" Run [bold cyan]cdg scan[/bold cyan] first to establish a baseline.")
40
43
  raise typer.Exit(1)
41
44
 
42
45
  console.print(f"[dim]Checking changes since last scan ({last_update})...[/dim]")
43
46
 
44
- # 2. Calculate Diff
47
+ # [2] Calculate Diff via Context
45
48
  with Progress(
46
49
  SpinnerColumn(),
47
50
  TextColumn("[bold blue]Analyzing changes...[/bold blue]"),
@@ -49,23 +52,20 @@ def handle(
49
52
  console=console
50
53
  ) as progress:
51
54
  task = progress.add_task("diff", total=None)
52
-
53
- # Load same filters as scan
54
- extensions, extra_ignores = _load_config_filters(root_path)
55
-
56
- # Get current valid files (Working Tree)
57
- current_files = scanner.scan_project(root_path, extensions, extra_ignores)
58
-
55
+
56
+ # ★ Use common context to get files (handles config & resolve)
57
+ current_files = ctx.get_target_files(resolve_deps=resolve)
58
+
59
59
  # Compare Working Tree vs Anchor
60
60
  diff_content = anchor.get_changes(current_files)
61
-
61
+
62
62
  progress.update(task, completed=100)
63
63
 
64
64
  if not diff_content.strip():
65
- console.print("[green]✨ No changes detected since last scan.[/green]")
65
+ console.print("[green]No changes detected since last scan.[/green]")
66
66
  return
67
67
 
68
- # 3. Render
68
+ # [3] Render
69
69
  prompt_engine = prompts.get_engine(root_path)
70
70
  try:
71
71
  formatted_diff = prompt_engine.render(
@@ -76,18 +76,19 @@ def handle(
76
76
  instruction=message
77
77
  )
78
78
  except Exception:
79
- # Fallback if template fails
80
- formatted_diff = f"<diff>\n{diff_content}\n</diff>"
79
+ # Fallback if template fails (using safe escaping via tags)
80
+ safe_content = tags.escape_xml_value(diff_content)
81
+ formatted_diff = f"<diff>\n{safe_content}\n</diff>"
81
82
 
82
- # 4. Output
83
- console.print(f"[bold green]✔ Changes Detected![/bold green] ({len(formatted_diff)} chars)")
83
+ # [4] Output
84
+ console.print(f"[bold green]Changes Detected![/bold green] ({len(formatted_diff)} chars)")
84
85
 
85
86
  if copy:
86
87
  pyperclip.copy(formatted_diff)
87
- console.print("[dim]📋 Copied to clipboard[/dim]")
88
+ console.print("[dim]Clipboard copied[/dim]")
88
89
 
89
90
  if save:
90
91
  out_path = root_path / ".codigest" / "changes.diff"
91
92
  out_path.parent.mkdir(exist_ok=True)
92
93
  out_path.write_text(formatted_diff, encoding="utf-8")
93
- console.print(f"[dim]💾 Saved to {out_path}[/dim]")
94
+ console.print(f"[dim]Saved to {out_path}[/dim]")
@@ -4,10 +4,7 @@ from pathlib import Path
4
4
  from rich.console import Console
5
5
  from rich.progress import Progress, SpinnerColumn, TextColumn
6
6
 
7
- from ..core import scanner, structure, prompts, semdiff, tags, tokenizer
8
-
9
- # Reuse config loader
10
- from .scan import _load_config_filters
7
+ from ..core import structure, prompts, semdiff, tags, tokenizer, common
11
8
 
12
9
  app = typer.Typer()
13
10
  console = Console()
@@ -18,14 +15,17 @@ def handle(
18
15
  copy: bool = typer.Option(True, help="Auto-copy to clipboard"),
19
16
  save: bool = typer.Option(True, help="Save to .codigest/digest.xml"),
20
17
  message: str = typer.Option("", "--message", "-m", help="Add specific instruction"),
18
+ # [추가]
19
+ resolve: bool = typer.Option(False, "-r", "--resolve", help="Recursively resolve imports"),
21
20
  ):
22
21
  """
23
22
  [Architectural View] Summarizes the codebase structure (Classes/Functions only).
24
23
  """
25
- root_path = target.resolve()
24
+ # [1] Context Setup
25
+ ctx = common.get_context(target)
26
+ root_path = ctx.root_path
26
27
 
27
28
  prompt_engine = prompts.get_engine(root_path)
28
- extensions, extra_ignores = _load_config_filters(root_path)
29
29
 
30
30
  with Progress(
31
31
  SpinnerColumn(),
@@ -36,19 +36,24 @@ def handle(
36
36
 
37
37
  task = progress.add_task("digest", total=None)
38
38
 
39
- files = scanner.scan_project(root_path, extensions, extra_ignores)
39
+ # [2] File Discovery via Context
40
+ files = ctx.get_target_files(ignore_config=False, resolve_deps=resolve)
41
+
40
42
  tree_str = structure.generate_ascii_tree(files, root_path)
41
43
 
42
44
  summary_blocks = []
43
45
  for file_path in files:
44
- # Only summarize Python files via AST
45
46
  if file_path.suffix in (".py", ".pyi"):
46
47
  try:
47
48
  content = file_path.read_text(encoding="utf-8")
48
49
  summary = semdiff.summarize(content)
49
50
 
50
51
  if summary:
51
- rel_path = file_path.relative_to(root_path).as_posix()
52
+ try:
53
+ rel_path = file_path.relative_to(root_path).as_posix()
54
+ except ValueError:
55
+ rel_path = f"[EXTERNAL]/{file_path.name}"
56
+
52
57
  block = tags.file(rel_path, summary)
53
58
  summary_blocks.append(block)
54
59
  except Exception:
@@ -71,7 +76,7 @@ def handle(
71
76
  progress.update(task, completed=100)
72
77
 
73
78
  token_count = tokenizer.estimate_tokens(digest_content)
74
- console.print(f"[bold green]✔ Digest Generated![/bold green] ([bold cyan]~{token_count:,} Tokens[/bold cyan])")
79
+ console.print(f"[bold green]Digest Generated![/bold green] ([bold cyan]~{token_count:,} Tokens[/bold cyan])")
75
80
 
76
81
  if copy:
77
82
  pyperclip.copy(digest_content)
@@ -81,4 +86,4 @@ def handle(
81
86
  out_path = root_path / ".codigest" / "digest.xml"
82
87
  out_path.parent.mkdir(exist_ok=True)
83
88
  out_path.write_text(digest_content, encoding="utf-8")
84
- console.print(f"[dim]💾 Saved to {out_path}[/dim]")
89
+ console.print(f"[dim]💾 Saved to {out_path}[/dim]")