context-gen-cli 1.2.4__tar.gz → 1.3.3__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 (21) hide show
  1. {context_gen_cli-1.2.4 → context_gen_cli-1.3.3}/PKG-INFO +28 -50
  2. {context_gen_cli-1.2.4 → context_gen_cli-1.3.3}/README.md +27 -49
  3. context_gen_cli-1.3.3/context_gen/cli.py +242 -0
  4. context_gen_cli-1.3.3/context_gen/distill.py +107 -0
  5. {context_gen_cli-1.2.4 → context_gen_cli-1.3.3}/context_gen_cli.egg-info/PKG-INFO +28 -50
  6. {context_gen_cli-1.2.4 → context_gen_cli-1.3.3}/context_gen_cli.egg-info/SOURCES.txt +1 -0
  7. {context_gen_cli-1.2.4 → context_gen_cli-1.3.3}/pyproject.toml +1 -1
  8. context_gen_cli-1.2.4/context_gen/cli.py +0 -287
  9. {context_gen_cli-1.2.4 → context_gen_cli-1.3.3}/context_gen/__init__.py +0 -0
  10. {context_gen_cli-1.2.4 → context_gen_cli-1.3.3}/context_gen/extractor.py +0 -0
  11. {context_gen_cli-1.2.4 → context_gen_cli-1.3.3}/context_gen/generator.py +0 -0
  12. {context_gen_cli-1.2.4 → context_gen_cli-1.3.3}/context_gen/graph.py +0 -0
  13. {context_gen_cli-1.2.4 → context_gen_cli-1.3.3}/context_gen/mcp/__init__.py +0 -0
  14. {context_gen_cli-1.2.4 → context_gen_cli-1.3.3}/context_gen/mcp/advanced_tools.py +0 -0
  15. {context_gen_cli-1.2.4 → context_gen_cli-1.3.3}/context_gen/scanner.py +0 -0
  16. {context_gen_cli-1.2.4 → context_gen_cli-1.3.3}/context_gen_cli.egg-info/dependency_links.txt +0 -0
  17. {context_gen_cli-1.2.4 → context_gen_cli-1.3.3}/context_gen_cli.egg-info/entry_points.txt +0 -0
  18. {context_gen_cli-1.2.4 → context_gen_cli-1.3.3}/context_gen_cli.egg-info/requires.txt +0 -0
  19. {context_gen_cli-1.2.4 → context_gen_cli-1.3.3}/context_gen_cli.egg-info/top_level.txt +0 -0
  20. {context_gen_cli-1.2.4 → context_gen_cli-1.3.3}/setup.cfg +0 -0
  21. {context_gen_cli-1.2.4 → context_gen_cli-1.3.3}/tests/test_advanced_tools.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: context-gen-cli
3
- Version: 1.2.4
3
+ Version: 1.3.3
4
4
  Summary: A modern CLI tool that scans any project, builds an AST-based dependency graph, and generates structured LLM context (agent.md / agent.json).
5
5
  Author: yakkshit
6
6
  License-Expression: MIT
@@ -25,7 +25,7 @@ Requires-Dist: pytest>=8.0.0; extra == "dev"
25
25
  Requires-Dist: build>=1.1.0; extra == "dev"
26
26
  Requires-Dist: twine>=5.0.0; extra == "dev"
27
27
 
28
- # ⚡ context-gen-cli (Python Edition)
28
+ # ⚡ context-gen-cli (`ctx`) — Python Edition
29
29
 
30
30
  [![PyPI version](https://img.shields.io/pypi/v/context-gen-cli.svg?color=3775a9)](https://pypi.org/project/context-gen-cli/)
31
31
  [![Python Versions](https://img.shields.io/pypi/pyversions/context-gen-cli.svg)](https://pypi.org/project/context-gen-cli/)
@@ -37,13 +37,14 @@ Requires-Dist: twine>=5.0.0; extra == "dev"
37
37
 
38
38
  ## 🌟 Highlights
39
39
 
40
- - **100% Accurate Python Dependency Graphs**: Built using Python's native `ast` (Abstract Syntax Tree) module to resolve imports, relative packages, entry points, and utilities without regex guesswork.
40
+ - **⚡ Short Command Alias (`ctx`)**: Type `ctx` anywhere in your terminal.
41
+ - **100% Accurate Python Dependency Graphs**: Built using Python's native `ast` (Abstract Syntax Tree) module to resolve imports, relative packages, entry points, and utilities.
42
+ - **📁 Clean Workspace Storage**: Everything (`agent.md`, `agent.json`, `agent.yaml`, `.context-gen.json`) is saved neatly inside `context/`.
41
43
  - **⚡ All-In-One Default Mode (`-d`)**: Auto-generates triple context formats in `context/` and runs a live auto-sync watcher in the background.
42
44
  - **`.gitignore` & Multi-Ignore Respect**: Automatically parses rules from `.gitignore`, `.npmignore`, `.dockerignore`, `.contextignore`, `.ignore`, and filters `.env*` secrets.
43
45
  - **Triple Format Output**: Generates Markdown (`agent.md`), MCP-compatible structured JSON (`agent.json`), and clean YAML (`agent.yaml`).
44
46
  - **🔄 Auto-Sync Watch Mode (`-w`)**: Monitors workspace changes and updates context files automatically on save.
45
- - **Configuration Parity**: Seamlessly reads `.context-gen.json` if present to maintain unified project settings with the Node.js edition.
46
- - **Modern CLI**: Styled with `typer` and `rich` for rich terminal output and progress reporting.
47
+ - **Configuration Parity**: Seamlessly reads `context/.context-gen.json` to maintain unified project settings with the Node.js edition.
47
48
 
48
49
  ---
49
50
 
@@ -63,75 +64,52 @@ pip install context-gen-cli
63
64
  Generates all formats in `context/` and starts the live auto-sync watcher in background:
64
65
 
65
66
  ```bash
66
- context-gen -d
67
+ ctx -d
67
68
  ```
68
69
 
69
70
  ### 2. Generate All Formats (Markdown, JSON, YAML)
70
71
  Scans the current directory and outputs `agent.md`, `agent.json`, and `agent.yaml` in `context/`:
71
72
 
72
73
  ```bash
73
- context-gen .
74
+ ctx
74
75
  ```
75
76
 
76
- ### 3. Generate Specific Format (JSON / MD / YAML)
77
- Generate only the format you need:
78
-
77
+ ### 3. Quick Refresh / Regenerate
79
78
  ```bash
80
- # Generate MCP-ready JSON
81
- context-gen . --format json
82
-
83
- # Generate Markdown
84
- context-gen . --format md
85
-
86
- # Generate YAML
87
- context-gen . --format yaml
79
+ ctx update
88
80
  ```
89
81
 
90
- ### 4. Watch Mode
91
- Keep context files fresh automatically on every file edit:
92
-
82
+ ### 4. Custom Format & Output Destination
93
83
  ```bash
94
- context-gen . --watch
84
+ ctx update -f json
85
+ ctx -o custom_docs/
86
+ ctx -p /path/to/project
95
87
  ```
96
88
 
97
- ### 5. Custom Output Destination & Directory Depth
89
+ ### 5. Watch Mode
90
+ Keep context files fresh automatically on every file edit:
91
+
98
92
  ```bash
99
- context-gen ./my-project -o custom/docs/context.md --max-depth 4
93
+ ctx -w
100
94
  ```
101
95
 
102
96
  ---
103
97
 
104
98
  ## 📖 CLI Reference
105
99
 
106
- ```text
107
- Usage: context-gen [OPTIONS] [PATH]
108
-
109
- Arguments:
110
- [PATH] Target project directory to analyze [default: .]
111
-
112
- Options:
113
- -d, --default ⚡ Zero-config default mode: generate all formats in context/ and run live auto-sync watcher
114
- -f, --format [all|md|json|yaml] Output format [default: all]
115
- -o, --output PATH Custom output file path (e.g. context/agent.md or custom.json)
116
- -w, --watch Watch directory and auto-regenerate context on file changes
117
- --max-depth INTEGER Maximum directory depth to scan (1-10) [default: 3]
118
- --help Show this message and exit
119
- ```
120
-
121
- ---
122
-
123
- ## 🌐 Node.js & Live MCP Server
124
-
125
- Looking for the live MCP server with interactive SSE streaming and public tunnels? Check out the [Node.js edition](https://www.npmjs.com/package/context-gen-cli):
126
-
127
- ```bash
128
- npx context-gen-cli -d
129
- # or
130
- npx context-gen-cli --mcp
131
- ```
100
+ | Flag / Command | Alias | Description |
101
+ | :--- | :--- | :--- |
102
+ | `ctx -d` | `ctx --default` | **⚡ All-in-One**: Generates context files and starts live auto-sync watcher |
103
+ | `ctx -w` | `ctx --watch` | **👀 Watch Mode**: Auto-regenerates context on file changes |
104
+ | `ctx -f <type>` | `ctx --format <type>` | **Format**: `md`, `json`, `yaml`, or `all` |
105
+ | `ctx -o <path>` | `ctx --output <path>` | **Custom Output**: Output file/folder path |
106
+ | `ctx -p <path>` | `ctx --project <path>` | **Target Directory**: Directory to analyze |
107
+ | `ctx update` | — | **Refresh**: Regenerate context files |
108
+ | `ctx --help` | — | View full help options |
132
109
 
133
110
  ---
134
111
 
135
112
  ## 📄 License
136
113
 
137
114
  MIT © [yakkshit](https://github.com/yakkshit)
115
+
@@ -1,4 +1,4 @@
1
- # ⚡ context-gen-cli (Python Edition)
1
+ # ⚡ context-gen-cli (`ctx`) — Python Edition
2
2
 
3
3
  [![PyPI version](https://img.shields.io/pypi/v/context-gen-cli.svg?color=3775a9)](https://pypi.org/project/context-gen-cli/)
4
4
  [![Python Versions](https://img.shields.io/pypi/pyversions/context-gen-cli.svg)](https://pypi.org/project/context-gen-cli/)
@@ -10,13 +10,14 @@
10
10
 
11
11
  ## 🌟 Highlights
12
12
 
13
- - **100% Accurate Python Dependency Graphs**: Built using Python's native `ast` (Abstract Syntax Tree) module to resolve imports, relative packages, entry points, and utilities without regex guesswork.
13
+ - **⚡ Short Command Alias (`ctx`)**: Type `ctx` anywhere in your terminal.
14
+ - **100% Accurate Python Dependency Graphs**: Built using Python's native `ast` (Abstract Syntax Tree) module to resolve imports, relative packages, entry points, and utilities.
15
+ - **📁 Clean Workspace Storage**: Everything (`agent.md`, `agent.json`, `agent.yaml`, `.context-gen.json`) is saved neatly inside `context/`.
14
16
  - **⚡ All-In-One Default Mode (`-d`)**: Auto-generates triple context formats in `context/` and runs a live auto-sync watcher in the background.
15
17
  - **`.gitignore` & Multi-Ignore Respect**: Automatically parses rules from `.gitignore`, `.npmignore`, `.dockerignore`, `.contextignore`, `.ignore`, and filters `.env*` secrets.
16
18
  - **Triple Format Output**: Generates Markdown (`agent.md`), MCP-compatible structured JSON (`agent.json`), and clean YAML (`agent.yaml`).
17
19
  - **🔄 Auto-Sync Watch Mode (`-w`)**: Monitors workspace changes and updates context files automatically on save.
18
- - **Configuration Parity**: Seamlessly reads `.context-gen.json` if present to maintain unified project settings with the Node.js edition.
19
- - **Modern CLI**: Styled with `typer` and `rich` for rich terminal output and progress reporting.
20
+ - **Configuration Parity**: Seamlessly reads `context/.context-gen.json` to maintain unified project settings with the Node.js edition.
20
21
 
21
22
  ---
22
23
 
@@ -36,75 +37,52 @@ pip install context-gen-cli
36
37
  Generates all formats in `context/` and starts the live auto-sync watcher in background:
37
38
 
38
39
  ```bash
39
- context-gen -d
40
+ ctx -d
40
41
  ```
41
42
 
42
43
  ### 2. Generate All Formats (Markdown, JSON, YAML)
43
44
  Scans the current directory and outputs `agent.md`, `agent.json`, and `agent.yaml` in `context/`:
44
45
 
45
46
  ```bash
46
- context-gen .
47
+ ctx
47
48
  ```
48
49
 
49
- ### 3. Generate Specific Format (JSON / MD / YAML)
50
- Generate only the format you need:
51
-
50
+ ### 3. Quick Refresh / Regenerate
52
51
  ```bash
53
- # Generate MCP-ready JSON
54
- context-gen . --format json
55
-
56
- # Generate Markdown
57
- context-gen . --format md
58
-
59
- # Generate YAML
60
- context-gen . --format yaml
52
+ ctx update
61
53
  ```
62
54
 
63
- ### 4. Watch Mode
64
- Keep context files fresh automatically on every file edit:
65
-
55
+ ### 4. Custom Format & Output Destination
66
56
  ```bash
67
- context-gen . --watch
57
+ ctx update -f json
58
+ ctx -o custom_docs/
59
+ ctx -p /path/to/project
68
60
  ```
69
61
 
70
- ### 5. Custom Output Destination & Directory Depth
62
+ ### 5. Watch Mode
63
+ Keep context files fresh automatically on every file edit:
64
+
71
65
  ```bash
72
- context-gen ./my-project -o custom/docs/context.md --max-depth 4
66
+ ctx -w
73
67
  ```
74
68
 
75
69
  ---
76
70
 
77
71
  ## 📖 CLI Reference
78
72
 
79
- ```text
80
- Usage: context-gen [OPTIONS] [PATH]
81
-
82
- Arguments:
83
- [PATH] Target project directory to analyze [default: .]
84
-
85
- Options:
86
- -d, --default ⚡ Zero-config default mode: generate all formats in context/ and run live auto-sync watcher
87
- -f, --format [all|md|json|yaml] Output format [default: all]
88
- -o, --output PATH Custom output file path (e.g. context/agent.md or custom.json)
89
- -w, --watch Watch directory and auto-regenerate context on file changes
90
- --max-depth INTEGER Maximum directory depth to scan (1-10) [default: 3]
91
- --help Show this message and exit
92
- ```
93
-
94
- ---
95
-
96
- ## 🌐 Node.js & Live MCP Server
97
-
98
- Looking for the live MCP server with interactive SSE streaming and public tunnels? Check out the [Node.js edition](https://www.npmjs.com/package/context-gen-cli):
99
-
100
- ```bash
101
- npx context-gen-cli -d
102
- # or
103
- npx context-gen-cli --mcp
104
- ```
73
+ | Flag / Command | Alias | Description |
74
+ | :--- | :--- | :--- |
75
+ | `ctx -d` | `ctx --default` | **⚡ All-in-One**: Generates context files and starts live auto-sync watcher |
76
+ | `ctx -w` | `ctx --watch` | **👀 Watch Mode**: Auto-regenerates context on file changes |
77
+ | `ctx -f <type>` | `ctx --format <type>` | **Format**: `md`, `json`, `yaml`, or `all` |
78
+ | `ctx -o <path>` | `ctx --output <path>` | **Custom Output**: Output file/folder path |
79
+ | `ctx -p <path>` | `ctx --project <path>` | **Target Directory**: Directory to analyze |
80
+ | `ctx update` | — | **Refresh**: Regenerate context files |
81
+ | `ctx --help` | — | View full help options |
105
82
 
106
83
  ---
107
84
 
108
85
  ## 📄 License
109
86
 
110
87
  MIT © [yakkshit](https://github.com/yakkshit)
88
+
@@ -0,0 +1,242 @@
1
+ """
2
+ context_gen.cli: Typer-based CLI entry point for context-gen-cli (Python Edition).
3
+ """
4
+
5
+ import json
6
+ import time
7
+ from datetime import datetime
8
+ from enum import Enum
9
+ from pathlib import Path
10
+ from typing import List, Optional
11
+ import typer
12
+ from rich.console import Console
13
+ from rich.panel import Panel
14
+ from rich.table import Table
15
+ from rich.progress import Progress, SpinnerColumn, TextColumn, BarColumn, TaskProgressColumn, TimeElapsedColumn
16
+
17
+ from context_gen.scanner import scan_project
18
+ from context_gen.extractor import extract_metadata
19
+ from context_gen.graph import build_dependency_graph
20
+ from context_gen.generator import generate_agent_md, generate_agent_json, generate_agent_yaml
21
+ from context_gen.distill import distill_query
22
+
23
+ app = typer.Typer(
24
+ name="context-gen",
25
+ help="⚡ Generate graph-based project context & distill minimal AI prompts (ctx).",
26
+ add_completion=False,
27
+ no_args_is_help=False,
28
+ )
29
+ console = Console()
30
+
31
+
32
+ class OutputFormat(str, Enum):
33
+ ALL = "all"
34
+ MD = "md"
35
+ JSON = "json"
36
+ YAML = "yaml"
37
+
38
+
39
+ def print_python_banner() -> None:
40
+ banner = r"""
41
+ ___ _ _ __
42
+ / __| |_ \ \/ /
43
+ | (__| _| > <
44
+ \___|\__|/_/\_\
45
+ """
46
+ console.print(f"[bold magenta]{banner}[/bold magenta]")
47
+ console.print(
48
+ Panel.fit(
49
+ "[bold cyan]⚡ context-gen-cli (ctx)[/bold cyan] — [magenta]Senior Engineer Context & Knowledge Graph Engine[/magenta]",
50
+ border_style="cyan",
51
+ )
52
+ )
53
+ console.print("")
54
+
55
+
56
+ def execute_generation_with_progress(
57
+ target_dir: Path,
58
+ format_choice: OutputFormat,
59
+ output_override: Optional[Path] = None,
60
+ max_depth: int = 3,
61
+ ) -> dict:
62
+ with Progress(
63
+ SpinnerColumn("dots", style="cyan"),
64
+ TextColumn("[bold blue]{task.description}"),
65
+ BarColumn(bar_width=35, complete_style="magenta", finished_style="green"),
66
+ TaskProgressColumn(),
67
+ TimeElapsedColumn(),
68
+ console=console,
69
+ ) as progress:
70
+ t1 = progress.add_task("🔍 Scanning workspace files & security guards...", total=100)
71
+ scan_result = scan_project(str(target_dir), max_depth=max_depth)
72
+ progress.update(t1, completed=100)
73
+
74
+ t2 = progress.add_task("📦 Extracting metadata & tech stack signals...", total=100)
75
+ files = scan_result["files"]
76
+ tree = scan_result["tree"]
77
+ metadata = extract_metadata(str(target_dir), files)
78
+ progress.update(t2, completed=100)
79
+
80
+ t3 = progress.add_task("🕸️ Building AST module dependency graph...", total=100)
81
+ graph = build_dependency_graph(files, str(target_dir))
82
+ progress.update(t3, completed=100)
83
+
84
+ t4 = progress.add_task(f"✍️ Generating context artifacts ({format_choice.value})...", total=100)
85
+
86
+ output_dir_name = "context"
87
+ config_file = target_dir / "context" / ".context-gen.json"
88
+ if not config_file.is_file():
89
+ config_file = target_dir / ".context-gen.json"
90
+
91
+ if config_file.is_file():
92
+ try:
93
+ cfg = json.loads(config_file.read_text(encoding="utf-8"))
94
+ output_dir_name = cfg.get("outputDir", "context")
95
+ except Exception:
96
+ pass
97
+
98
+ dest_dir = target_dir / output_dir_name
99
+ dest_dir.mkdir(parents=True, exist_ok=True)
100
+ generated_files: List[Path] = []
101
+
102
+ if output_override:
103
+ out_file = output_override.resolve()
104
+ out_file.parent.mkdir(parents=True, exist_ok=True)
105
+ if format_choice == OutputFormat.JSON:
106
+ out_file.write_text(json.dumps(generate_agent_json(metadata, graph, tree, str(target_dir)), indent=2), encoding="utf-8")
107
+ elif format_choice == OutputFormat.YAML:
108
+ out_file.write_text(generate_agent_yaml(metadata, graph, tree, str(target_dir)), encoding="utf-8")
109
+ else:
110
+ out_file.write_text(generate_agent_md(metadata, graph, tree), encoding="utf-8")
111
+ generated_files.append(out_file)
112
+ else:
113
+ formats_to_build = ["md", "json", "yaml"] if format_choice == OutputFormat.ALL else [format_choice.value]
114
+ if "md" in formats_to_build:
115
+ f = dest_dir / "agent.md"
116
+ f.write_text(generate_agent_md(metadata, graph, tree), encoding="utf-8")
117
+ generated_files.append(f)
118
+ if "json" in formats_to_build:
119
+ f = dest_dir / "agent.json"
120
+ f.write_text(json.dumps(generate_agent_json(metadata, graph, tree, str(target_dir)), indent=2), encoding="utf-8")
121
+ generated_files.append(f)
122
+ if "yaml" in formats_to_build:
123
+ f = dest_dir / "agent.yaml"
124
+ f.write_text(generate_agent_yaml(metadata, graph, tree, str(target_dir)), encoding="utf-8")
125
+ generated_files.append(f)
126
+
127
+ progress.update(t4, completed=100)
128
+
129
+ console.print("")
130
+ return {
131
+ "files": files,
132
+ "graph": graph,
133
+ "metadata": metadata,
134
+ "generated_files": generated_files,
135
+ "output_dir": dest_dir,
136
+ }
137
+
138
+
139
+ def run_watch_loop(target_dir: Path, format_choice: OutputFormat, max_depth: int = 3) -> None:
140
+ console.print(
141
+ Panel(
142
+ f"[bold cyan]👀 Watch Mode Active[/bold cyan]\n"
143
+ f"[dim]Monitoring:[/dim] [green]{target_dir}[/green]\n"
144
+ f"[dim]Auto-updating context on save. Press [bold]Ctrl+C[/bold] to stop.[/dim]",
145
+ border_style="cyan",
146
+ )
147
+ )
148
+
149
+ def get_snapshot():
150
+ snap = {}
151
+ for p in target_dir.rglob("*"):
152
+ if p.is_file():
153
+ rel = p.relative_to(target_dir).as_posix()
154
+ if not any(t in rel for t in ["context/", "node_modules/", ".git/", "__pycache__/", ".venv/", "agent."]):
155
+ try:
156
+ snap[rel] = p.stat().st_mtime
157
+ except Exception:
158
+ pass
159
+ return snap
160
+
161
+ last_snapshot = get_snapshot()
162
+ try:
163
+ while True:
164
+ time.sleep(1.0)
165
+ current = get_snapshot()
166
+ if current != last_snapshot:
167
+ last_snapshot = current
168
+ ts = datetime.now().strftime("%H:%M:%S")
169
+ console.print(f"[dim][{ts}][/dim] [bold green]🔄 Change detected. Syncing context...[/bold green]")
170
+ execute_generation_with_progress(target_dir, format_choice, max_depth=max_depth)
171
+ except KeyboardInterrupt:
172
+ console.print("\n[bold yellow]👋 Stopping watch mode...[/bold yellow]")
173
+
174
+
175
+ @app.callback(invoke_without_command=True)
176
+ def main(
177
+ ctx: typer.Context,
178
+ path: Path = typer.Argument(default=Path("."), help="Target project directory."),
179
+ project: Optional[Path] = typer.Option(None, "--project", "-p", help="Target project directory."),
180
+ default_mode: bool = typer.Option(False, "--default", "-d", help="⚡ Generate all formats + live watch mode."),
181
+ format: OutputFormat = typer.Option(OutputFormat.ALL, "--format", "-f", help="Output format: all, md, json, yaml."),
182
+ output: Optional[Path] = typer.Option(None, "--output", "-o", help="Custom output path."),
183
+ watch: bool = typer.Option(False, "--watch", "-w", help="Watch directory for changes."),
184
+ max_depth: int = typer.Option(3, "--max-depth", min=1, max=10, help="Max scan depth."),
185
+ ) -> None:
186
+ if ctx.invoked_subcommand is not None:
187
+ return
188
+
189
+ target_dir = (project or path).resolve()
190
+ print_python_banner()
191
+ res = execute_generation_with_progress(target_dir, format, output_override=output, max_depth=max_depth)
192
+
193
+ table = Table(show_header=False, box=None)
194
+ table.add_row("[bold]📂 Scanned Files:[/bold]", f"[cyan]{len(res['files'])}[/cyan]")
195
+ table.add_row("[bold]🕸️ Graph Edges:[/bold]", f"[magenta]{len(res['graph']['edges'])}[/magenta]")
196
+ table.add_row("[bold]⚡ Tech Stack:[/bold]", f"[green]{', '.join(res['metadata']['techStack'])}[/green]")
197
+ table.add_row("[bold]📁 Destination:[/bold]", f"[yellow]{res['output_dir']}[/yellow]")
198
+ table.add_row("[bold]�� Artifacts:[/bold]", f"[bold cyan]{', '.join(f.name for f in res['generated_files'])}[/bold cyan]")
199
+
200
+ console.print(Panel(table, title="[bold green]✅ Context Generated Successfully[/bold green]", border_style="green"))
201
+ console.print(
202
+ Panel(
203
+ "[bold cyan]ctx distill \"add feature\"[/bold cyan] → 🧠 Get minimal Senior Engineer context plan\n"
204
+ "[bold cyan]ctx -d[/bold cyan] → ⚡ All-in-one generate + live watcher\n"
205
+ "[bold cyan]ctx update -f json[/bold cyan] → 🔄 Quick format refresh",
206
+ title="[bold]💡 Quick Commands[/bold]",
207
+ border_style="blue",
208
+ )
209
+ )
210
+
211
+ if default_mode or watch:
212
+ run_watch_loop(target_dir, format, max_depth=max_depth)
213
+
214
+
215
+ @app.command()
216
+ def distill(
217
+ prompt: str = typer.Argument(..., help="Task or feature request to distill context for."),
218
+ budget: int = typer.Option(250, "--budget", "-b", help="Max token budget."),
219
+ project: Path = typer.Option(Path("."), "--project", "-p", help="Target project directory."),
220
+ ) -> None:
221
+ """🧠 Distill minimal high-signal context using Entropy + Knowledge Graph."""
222
+ res = distill_query(str(project.resolve()), prompt, budget=budget)
223
+ if res["status"] == "needs_clarification":
224
+ console.print(Panel(res["output"], title="[bold yellow]⚠️ Clarification Needed[/bold yellow]", border_style="yellow"))
225
+ else:
226
+ console.print(Panel(res["output"], title="[bold cyan]🧠 Senior Engineer Context Plan[/bold cyan]", border_style="cyan"))
227
+
228
+
229
+ @app.command()
230
+ def update(
231
+ path: Path = typer.Argument(default=Path("."), help="Target project directory."),
232
+ format: OutputFormat = typer.Option(OutputFormat.ALL, "--format", "-f", help="Output format."),
233
+ output: Optional[Path] = typer.Option(None, "--output", "-o", help="Custom output path."),
234
+ ) -> None:
235
+ """🔄 Regenerate and update project context files."""
236
+ target_dir = path.resolve()
237
+ res = execute_generation_with_progress(target_dir, format, output_override=output)
238
+ console.print(f"[bold green]✓ Context updated in {res['output_dir']}![/bold green]")
239
+
240
+
241
+ if __name__ == "__main__":
242
+ app()
@@ -0,0 +1,107 @@
1
+ import os
2
+ import re
3
+ import math
4
+ from pathlib import Path
5
+
6
+ IGNORE_DIRS = {
7
+ "node_modules", ".git", ".next", "dist", "build", ".graviton",
8
+ "target", "__pycache__", ".venv", "venv", ".dart_tool", "bin", "obj",
9
+ "test", "tests", "context", "public",
10
+ }
11
+
12
+ SUPPORTED_EXT = {
13
+ ".ts": "ts", ".tsx": "ts", ".js": "js", ".jsx": "js",
14
+ ".py": "python", ".rs": "rust", ".go": "go", ".dart": "dart", ".cs": "csharp",
15
+ }
16
+
17
+ def get_hardware_budget(file_count: int) -> dict:
18
+ total_cores = os.cpu_count() or 2
19
+ allocated = 2 if (total_cores >= 6 and file_count >= 80) else 1
20
+ return {"total_cores": total_cores, "allocated_threads": allocated}
21
+
22
+ def scan_signatures(root_dir: Path) -> list[dict]:
23
+ sigs = []
24
+ for dirpath, dirnames, filenames in os.walk(root_dir):
25
+ dirnames[:] = [d for d in dirnames if d not in IGNORE_DIRS and not d.startswith(".") and not d.endswith(".egg-info")]
26
+ for fname in filenames:
27
+ ext = Path(fname).suffix
28
+ if ext not in SUPPORTED_EXT:
29
+ continue
30
+ full_path = Path(dirpath) / fname
31
+ rel_path = str(full_path.relative_to(root_dir))
32
+ try:
33
+ code = full_path.read_text(encoding="utf-8", errors="ignore")
34
+ except Exception:
35
+ continue
36
+
37
+ imports = re.findall(r"(?:import|from|use|using)\s+['\"]?([\w./:-]+)", code)[:6]
38
+ exports = re.findall(r"(?:export\s+(?:async\s+)?(?:function|const|class)|def|class|pub\s+fn|func)\s+([A-Za-z_]\w*)", code)[:6]
39
+ tokens = max(10, len(f"{rel_path} {' '.join(imports)} {' '.join(exports)}") // 4)
40
+ sigs.append({
41
+ "path": rel_path,
42
+ "lang": SUPPORTED_EXT[ext],
43
+ "imports": list(dict.fromkeys(imports)),
44
+ "exports": list(dict.fromkeys(exports)),
45
+ "tokens": tokens,
46
+ })
47
+ return sigs
48
+
49
+ def distill_query(root_dir: str, prompt: str, budget: int = 250) -> dict:
50
+ root = Path(root_dir).resolve()
51
+ sigs = scan_signatures(root)
52
+ hw = get_hardware_budget(len(sigs))
53
+
54
+ if not sigs:
55
+ return {"status": "needs_clarification", "output": "No source files found. Which directory contains your code?"}
56
+
57
+ words = [w for w in re.split(r"\W+", prompt.lower()) if len(w) > 2]
58
+ scored = []
59
+ for s in sigs:
60
+ haystack = f"{s['path']} {' '.join(s['imports'])} {' '.join(s['exports'])}".lower()
61
+ hits = sum(1 for w in words if w in haystack)
62
+ scored.append((s, 0.1 + hits * 0.45))
63
+
64
+ max_s = max(sc for _, sc in scored)
65
+ exps = [math.exp((sc - max_s) / 0.35) for _, sc in scored]
66
+ total_exp = sum(exps)
67
+ probs = [e / total_exp for e in exps]
68
+ initial_h = -sum(p * math.log2(p) for p in probs if p > 1e-6)
69
+
70
+ ranked = sorted(
71
+ [(s, p, (p * initial_h * 1.6), (p * initial_h * 1.6) / s["tokens"]) for (s, _), p in zip(scored, probs)],
72
+ key=lambda x: x[3],
73
+ reverse=True,
74
+ )
75
+
76
+ entropy = initial_h
77
+ picked = []
78
+ used_tokens = 0
79
+ for sig, prob, delta_h, _ in ranked:
80
+ if used_tokens + sig["tokens"] > budget or entropy < 1.5:
81
+ break
82
+ if prob < 0.05 and picked:
83
+ break
84
+ picked.append(sig)
85
+ used_tokens += sig["tokens"]
86
+ entropy = max(0.35, entropy - delta_h)
87
+
88
+ if entropy >= 1.5 or (len(words) <= 3 and ranked[0][1] < 0.22):
89
+ sample = ranked[0][0]["path"] if ranked else "src/main.py"
90
+ output = (
91
+ f"CLARIFICATION NEEDED (Before Writing Code):\n"
92
+ f"1. **Implementation Pattern:** Should I extend an existing module? (e.g., *Follow `{sample}`* or *Create a standalone file*)\n"
93
+ f"2. **Side Effects:** Should this persist state/files or run read-only?"
94
+ )
95
+ return {"status": "needs_clarification", "output": output}
96
+
97
+ refs = "\n".join(
98
+ f" • {p['path']} [{p['lang']}] — exports: [{', '.join(p['exports'][:4])}], imports: [{', '.join(p['imports'][:4])}]"
99
+ for p in picked
100
+ )
101
+ output = (
102
+ f"### Senior Engineer Context Plan ({used_tokens} tokens | CPU: {hw['allocated_threads']} core)\n"
103
+ f"- **Task:** {prompt}\n"
104
+ f"- **Primary Files to Reference:**\n{refs}\n"
105
+ f"- **Architecture Guardrail:** Match existing imports, function signatures, and module boundaries."
106
+ )
107
+ return {"status": "ready", "output": output}
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: context-gen-cli
3
- Version: 1.2.4
3
+ Version: 1.3.3
4
4
  Summary: A modern CLI tool that scans any project, builds an AST-based dependency graph, and generates structured LLM context (agent.md / agent.json).
5
5
  Author: yakkshit
6
6
  License-Expression: MIT
@@ -25,7 +25,7 @@ Requires-Dist: pytest>=8.0.0; extra == "dev"
25
25
  Requires-Dist: build>=1.1.0; extra == "dev"
26
26
  Requires-Dist: twine>=5.0.0; extra == "dev"
27
27
 
28
- # ⚡ context-gen-cli (Python Edition)
28
+ # ⚡ context-gen-cli (`ctx`) — Python Edition
29
29
 
30
30
  [![PyPI version](https://img.shields.io/pypi/v/context-gen-cli.svg?color=3775a9)](https://pypi.org/project/context-gen-cli/)
31
31
  [![Python Versions](https://img.shields.io/pypi/pyversions/context-gen-cli.svg)](https://pypi.org/project/context-gen-cli/)
@@ -37,13 +37,14 @@ Requires-Dist: twine>=5.0.0; extra == "dev"
37
37
 
38
38
  ## 🌟 Highlights
39
39
 
40
- - **100% Accurate Python Dependency Graphs**: Built using Python's native `ast` (Abstract Syntax Tree) module to resolve imports, relative packages, entry points, and utilities without regex guesswork.
40
+ - **⚡ Short Command Alias (`ctx`)**: Type `ctx` anywhere in your terminal.
41
+ - **100% Accurate Python Dependency Graphs**: Built using Python's native `ast` (Abstract Syntax Tree) module to resolve imports, relative packages, entry points, and utilities.
42
+ - **📁 Clean Workspace Storage**: Everything (`agent.md`, `agent.json`, `agent.yaml`, `.context-gen.json`) is saved neatly inside `context/`.
41
43
  - **⚡ All-In-One Default Mode (`-d`)**: Auto-generates triple context formats in `context/` and runs a live auto-sync watcher in the background.
42
44
  - **`.gitignore` & Multi-Ignore Respect**: Automatically parses rules from `.gitignore`, `.npmignore`, `.dockerignore`, `.contextignore`, `.ignore`, and filters `.env*` secrets.
43
45
  - **Triple Format Output**: Generates Markdown (`agent.md`), MCP-compatible structured JSON (`agent.json`), and clean YAML (`agent.yaml`).
44
46
  - **🔄 Auto-Sync Watch Mode (`-w`)**: Monitors workspace changes and updates context files automatically on save.
45
- - **Configuration Parity**: Seamlessly reads `.context-gen.json` if present to maintain unified project settings with the Node.js edition.
46
- - **Modern CLI**: Styled with `typer` and `rich` for rich terminal output and progress reporting.
47
+ - **Configuration Parity**: Seamlessly reads `context/.context-gen.json` to maintain unified project settings with the Node.js edition.
47
48
 
48
49
  ---
49
50
 
@@ -63,75 +64,52 @@ pip install context-gen-cli
63
64
  Generates all formats in `context/` and starts the live auto-sync watcher in background:
64
65
 
65
66
  ```bash
66
- context-gen -d
67
+ ctx -d
67
68
  ```
68
69
 
69
70
  ### 2. Generate All Formats (Markdown, JSON, YAML)
70
71
  Scans the current directory and outputs `agent.md`, `agent.json`, and `agent.yaml` in `context/`:
71
72
 
72
73
  ```bash
73
- context-gen .
74
+ ctx
74
75
  ```
75
76
 
76
- ### 3. Generate Specific Format (JSON / MD / YAML)
77
- Generate only the format you need:
78
-
77
+ ### 3. Quick Refresh / Regenerate
79
78
  ```bash
80
- # Generate MCP-ready JSON
81
- context-gen . --format json
82
-
83
- # Generate Markdown
84
- context-gen . --format md
85
-
86
- # Generate YAML
87
- context-gen . --format yaml
79
+ ctx update
88
80
  ```
89
81
 
90
- ### 4. Watch Mode
91
- Keep context files fresh automatically on every file edit:
92
-
82
+ ### 4. Custom Format & Output Destination
93
83
  ```bash
94
- context-gen . --watch
84
+ ctx update -f json
85
+ ctx -o custom_docs/
86
+ ctx -p /path/to/project
95
87
  ```
96
88
 
97
- ### 5. Custom Output Destination & Directory Depth
89
+ ### 5. Watch Mode
90
+ Keep context files fresh automatically on every file edit:
91
+
98
92
  ```bash
99
- context-gen ./my-project -o custom/docs/context.md --max-depth 4
93
+ ctx -w
100
94
  ```
101
95
 
102
96
  ---
103
97
 
104
98
  ## 📖 CLI Reference
105
99
 
106
- ```text
107
- Usage: context-gen [OPTIONS] [PATH]
108
-
109
- Arguments:
110
- [PATH] Target project directory to analyze [default: .]
111
-
112
- Options:
113
- -d, --default ⚡ Zero-config default mode: generate all formats in context/ and run live auto-sync watcher
114
- -f, --format [all|md|json|yaml] Output format [default: all]
115
- -o, --output PATH Custom output file path (e.g. context/agent.md or custom.json)
116
- -w, --watch Watch directory and auto-regenerate context on file changes
117
- --max-depth INTEGER Maximum directory depth to scan (1-10) [default: 3]
118
- --help Show this message and exit
119
- ```
120
-
121
- ---
122
-
123
- ## 🌐 Node.js & Live MCP Server
124
-
125
- Looking for the live MCP server with interactive SSE streaming and public tunnels? Check out the [Node.js edition](https://www.npmjs.com/package/context-gen-cli):
126
-
127
- ```bash
128
- npx context-gen-cli -d
129
- # or
130
- npx context-gen-cli --mcp
131
- ```
100
+ | Flag / Command | Alias | Description |
101
+ | :--- | :--- | :--- |
102
+ | `ctx -d` | `ctx --default` | **⚡ All-in-One**: Generates context files and starts live auto-sync watcher |
103
+ | `ctx -w` | `ctx --watch` | **👀 Watch Mode**: Auto-regenerates context on file changes |
104
+ | `ctx -f <type>` | `ctx --format <type>` | **Format**: `md`, `json`, `yaml`, or `all` |
105
+ | `ctx -o <path>` | `ctx --output <path>` | **Custom Output**: Output file/folder path |
106
+ | `ctx -p <path>` | `ctx --project <path>` | **Target Directory**: Directory to analyze |
107
+ | `ctx update` | — | **Refresh**: Regenerate context files |
108
+ | `ctx --help` | — | View full help options |
132
109
 
133
110
  ---
134
111
 
135
112
  ## 📄 License
136
113
 
137
114
  MIT © [yakkshit](https://github.com/yakkshit)
115
+
@@ -2,6 +2,7 @@ README.md
2
2
  pyproject.toml
3
3
  context_gen/__init__.py
4
4
  context_gen/cli.py
5
+ context_gen/distill.py
5
6
  context_gen/extractor.py
6
7
  context_gen/generator.py
7
8
  context_gen/graph.py
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "context-gen-cli"
7
- version = "1.2.4"
7
+ version = "1.3.3"
8
8
  description = "A modern CLI tool that scans any project, builds an AST-based dependency graph, and generates structured LLM context (agent.md / agent.json)."
9
9
  readme = "README.md"
10
10
  authors = [{ name = "yakkshit" }]
@@ -1,287 +0,0 @@
1
- """
2
- context_gen.cli: Typer-based CLI entry point for context-gen-cli (Python Edition).
3
- """
4
-
5
- import json
6
- import time
7
- from datetime import datetime
8
- from enum import Enum
9
- from pathlib import Path
10
- from typing import List, Optional
11
- import typer
12
- from rich.console import Console
13
- from rich.panel import Panel
14
- from rich.table import Table
15
-
16
- from context_gen.scanner import scan_project
17
- from context_gen.extractor import extract_metadata
18
- from context_gen.graph import build_dependency_graph
19
- from context_gen.generator import generate_agent_md, generate_agent_json, generate_agent_yaml
20
-
21
- app = typer.Typer(
22
- name="context-gen",
23
- help="⚡ Generate graph-based project context (agent.md, agent.json, agent.yaml) for LLMs.",
24
- add_completion=False,
25
- no_args_is_help=False
26
- )
27
- console = Console()
28
-
29
-
30
- class OutputFormat(str, Enum):
31
- """Supported output formats."""
32
- ALL = "all"
33
- MD = "md"
34
- JSON = "json"
35
- YAML = "yaml"
36
-
37
-
38
- def execute_generation(
39
- target_dir: Path,
40
- format_choice: OutputFormat,
41
- output_override: Optional[Path] = None,
42
- max_depth: int = 3,
43
- verbose: bool = True
44
- ) -> dict:
45
- """Scans and generates the requested context format files."""
46
- scan_result = scan_project(str(target_dir), max_depth=max_depth)
47
- files = scan_result["files"]
48
- tree = scan_result["tree"]
49
-
50
- metadata = extract_metadata(str(target_dir), files)
51
- graph = build_dependency_graph(files, str(target_dir))
52
-
53
- # Read output directory from .context-gen.json if available
54
- config_file = target_dir / ".context-gen.json"
55
- output_dir_name = "context"
56
- if config_file.is_file():
57
- try:
58
- with open(config_file, "r", encoding="utf-8") as f:
59
- cfg = json.load(f)
60
- output_dir_name = cfg.get("outputDir", "context")
61
- except Exception:
62
- pass
63
-
64
- dest_dir = target_dir / output_dir_name
65
- dest_dir.mkdir(parents=True, exist_ok=True)
66
-
67
- generated_files: List[Path] = []
68
-
69
- if output_override:
70
- out_file = output_override.resolve()
71
- out_file.parent.mkdir(parents=True, exist_ok=True)
72
- if format_choice == OutputFormat.JSON:
73
- json_data = generate_agent_json(metadata, graph, tree, str(target_dir))
74
- out_file.write_text(json.dumps(json_data, indent=2), encoding="utf-8")
75
- elif format_choice == OutputFormat.YAML:
76
- yaml_text = generate_agent_yaml(metadata, graph, tree, str(target_dir))
77
- out_file.write_text(yaml_text, encoding="utf-8")
78
- else:
79
- md_text = generate_agent_md(metadata, graph, tree)
80
- out_file.write_text(md_text, encoding="utf-8")
81
- generated_files.append(out_file)
82
- else:
83
- # Determine formats to generate
84
- formats_to_build = ["md", "json", "yaml"] if format_choice == OutputFormat.ALL else [format_choice.value]
85
-
86
- if "md" in formats_to_build:
87
- md_file = dest_dir / "agent.md"
88
- md_text = generate_agent_md(metadata, graph, tree)
89
- md_file.write_text(md_text, encoding="utf-8")
90
- generated_files.append(md_file)
91
-
92
- if "json" in formats_to_build:
93
- json_file = dest_dir / "agent.json"
94
- json_data = generate_agent_json(metadata, graph, tree, str(target_dir))
95
- json_file.write_text(json.dumps(json_data, indent=2), encoding="utf-8")
96
- generated_files.append(json_file)
97
-
98
- if "yaml" in formats_to_build:
99
- yaml_file = dest_dir / "agent.yaml"
100
- yaml_text = generate_agent_yaml(metadata, graph, tree, str(target_dir))
101
- yaml_file.write_text(yaml_text, encoding="utf-8")
102
- generated_files.append(yaml_file)
103
-
104
- return {
105
- "files": files,
106
- "graph": graph,
107
- "metadata": metadata,
108
- "generated_files": generated_files,
109
- "output_dir": dest_dir
110
- }
111
-
112
-
113
- def run_watch_loop(target_dir: Path, format_choice: OutputFormat, max_depth: int = 3) -> None:
114
- """Runs a live background file watch loop that regenerates context on changes."""
115
- console.print(
116
- Panel(
117
- f"[bold cyan]👀 Watch Mode Active[/bold cyan]\n"
118
- f"[dim]Monitoring workspace:[/dim] [green]{target_dir}[/green]\n"
119
- f"[dim]Auto-updating context files on save. Press [bold]Ctrl+C[/bold] to exit.[/dim]",
120
- border_style="cyan"
121
- )
122
- )
123
-
124
- last_snapshot = {}
125
-
126
- def get_snapshot():
127
- snap = {}
128
- for p in target_dir.rglob("*"):
129
- if p.is_file():
130
- rel = p.relative_to(target_dir).as_posix()
131
- if not any(token in rel for token in ["context/", "node_modules/", ".git/", "__pycache__/", ".venv/", "agent."]):
132
- try:
133
- snap[rel] = p.stat().st_mtime
134
- except Exception:
135
- pass
136
- return snap
137
-
138
- last_snapshot = get_snapshot()
139
-
140
- try:
141
- while True:
142
- time.sleep(1.0)
143
- current_snapshot = get_snapshot()
144
-
145
- changed = False
146
- for f, mtime in current_snapshot.items():
147
- if f not in last_snapshot or last_snapshot[f] != mtime:
148
- changed = True
149
- break
150
-
151
- if not changed and set(last_snapshot.keys()) != set(current_snapshot.keys()):
152
- changed = True
153
-
154
- if changed:
155
- last_snapshot = current_snapshot
156
- time_str = datetime.now().strftime("%H:%M:%S")
157
- console.print(f"[dim][{time_str}][/dim] [bold green]🔄 Project changed. Regenerating context files...[/bold green]")
158
- execute_generation(target_dir, format_choice, max_depth=max_depth, verbose=False)
159
- console.print(f"[dim][{time_str}][/dim] [bold cyan]✓ Context files updated & synced in context/![/bold cyan]")
160
- except KeyboardInterrupt:
161
- console.print("\n[bold yellow]👋 Stopping watch mode...[/bold yellow]")
162
-
163
-
164
- @app.command()
165
- def main(
166
- path: Path = typer.Argument(
167
- default=Path("."),
168
- help="Target project directory to analyze.",
169
- file_okay=False,
170
- dir_okay=True,
171
- readable=True,
172
- resolve_path=True,
173
- ),
174
- project: Optional[Path] = typer.Option(
175
- None,
176
- "--project",
177
- "-p",
178
- help="Target project directory to analyze.",
179
- file_okay=False,
180
- dir_okay=True,
181
- readable=True,
182
- resolve_path=True,
183
- ),
184
- default_mode: bool = typer.Option(
185
- False,
186
- "--default",
187
- "-d",
188
- help="⚡ Zero-config default mode: generate all formats in context/ and run live auto-sync watcher.",
189
- ),
190
- format: OutputFormat = typer.Option(
191
- OutputFormat.ALL,
192
- "--format",
193
- "-f",
194
- help="Output format: 'all', 'md', 'json', or 'yaml'.",
195
- case_sensitive=False,
196
- ),
197
- mcp: bool = typer.Option(
198
- False,
199
- "--mcp",
200
- "-m",
201
- help="Start MCP server mode.",
202
- ),
203
- interactive: bool = typer.Option(
204
- False,
205
- "--interactive",
206
- "-i",
207
- help="Run in interactive mode.",
208
- ),
209
- output: Optional[Path] = typer.Option(
210
- None,
211
- "--output",
212
- "-o",
213
- help="Custom output file path (e.g. context/agent.md or custom.json).",
214
- ),
215
- watch: bool = typer.Option(
216
- False,
217
- "--watch",
218
- "-w",
219
- help="Watch directory and auto-regenerate context on file changes.",
220
- ),
221
- max_depth: int = typer.Option(
222
- 3,
223
- "--max-depth",
224
- help="Maximum directory depth to scan.",
225
- min=1,
226
- max=10,
227
- ),
228
- ) -> None:
229
- """
230
- Scan a project, build an AST-powered dependency graph, and generate LLM context.
231
- """
232
- target_dir = (project or path).resolve()
233
-
234
- # If -d / --default is supplied, generate all formats and keep watch running
235
- if default_mode:
236
- console.print(
237
- Panel.fit(
238
- f"[bold cyan]⚡ context-gen-cli (Python All-In-One Mode -d)[/bold cyan]\n"
239
- f"[dim]Target:[/dim] [green]{target_dir}[/green]\n"
240
- f"[dim]Mode:[/dim] [yellow]Auto-Generate All Formats + Live Background Watcher[/yellow]",
241
- border_style="cyan"
242
- )
243
- )
244
- res = execute_generation(target_dir, OutputFormat.ALL, max_depth=max_depth)
245
- table = Table(show_header=False, box=None)
246
- table.add_row("[bold]Scanned Files:[/bold]", f"[cyan]{len(res['files'])}[/cyan]")
247
- table.add_row("[bold]AST Graph Edges:[/bold]", f"[cyan]{len(res['graph']['edges'])}[/cyan]")
248
- table.add_row("[bold]Tech Stack:[/bold]", f"[green]{', '.join(res['metadata']['techStack'])}[/green]")
249
- table.add_row("[bold]Generated Files:[/bold]", f"[yellow]{', '.join(f.name for f in res['generated_files'])}[/yellow]")
250
- console.print(Panel(table, title="[bold green]✅ Context Generated in context/[/bold green]", border_style="green"))
251
- run_watch_loop(target_dir, OutputFormat.ALL, max_depth=max_depth)
252
- return
253
-
254
- console.print(
255
- Panel.fit(
256
- f"[bold cyan]⚡ context-gen-cli (Python Edition)[/bold cyan]\n"
257
- f"[dim]Analyzing target:[/dim] [green]{target_dir}[/green]\n"
258
- f"[dim]Format:[/dim] [yellow]{format.value.upper()}[/yellow]",
259
- border_style="cyan"
260
- )
261
- )
262
-
263
- with console.status("[bold green]Scanning directory and parsing AST graph...[/bold green]"):
264
- res = execute_generation(target_dir, format, output_override=output, max_depth=max_depth)
265
-
266
- # Display completion summary
267
- table = Table(show_header=False, box=None)
268
- table.add_row("[bold]Scanned Files:[/bold]", f"[cyan]{len(res['files'])}[/cyan]")
269
- table.add_row("[bold]AST Graph Edges:[/bold]", f"[cyan]{len(res['graph']['edges'])}[/cyan]")
270
- table.add_row("[bold]Tech Stack:[/bold]", f"[green]{', '.join(res['metadata']['techStack'])}[/green]")
271
- table.add_row("[bold]Output Destination:[/bold]", f"[yellow]{res['output_dir']}[/yellow]")
272
- table.add_row("[bold]Generated Files:[/bold]", f"[green]{', '.join(f.name for f in res['generated_files'])}[/green]")
273
-
274
- console.print(
275
- Panel(
276
- table,
277
- title="[bold green]✅ Context Generated Successfully[/bold green]",
278
- border_style="green"
279
- )
280
- )
281
-
282
- if watch:
283
- run_watch_loop(target_dir, format, max_depth=max_depth)
284
-
285
-
286
- if __name__ == "__main__":
287
- app()