context-gen-cli 1.2.5__tar.gz → 1.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.
- context_gen_cli-1.3.5/PKG-INFO +192 -0
- context_gen_cli-1.3.5/README.md +164 -0
- context_gen_cli-1.3.5/context_gen/cli.py +242 -0
- context_gen_cli-1.3.5/context_gen/distill.py +107 -0
- {context_gen_cli-1.2.5 → context_gen_cli-1.3.5}/context_gen/scanner.py +18 -0
- context_gen_cli-1.3.5/context_gen_cli.egg-info/PKG-INFO +192 -0
- {context_gen_cli-1.2.5 → context_gen_cli-1.3.5}/context_gen_cli.egg-info/SOURCES.txt +1 -0
- {context_gen_cli-1.2.5 → context_gen_cli-1.3.5}/context_gen_cli.egg-info/requires.txt +2 -1
- {context_gen_cli-1.2.5 → context_gen_cli-1.3.5}/pyproject.toml +3 -2
- context_gen_cli-1.2.5/PKG-INFO +0 -115
- context_gen_cli-1.2.5/README.md +0 -88
- context_gen_cli-1.2.5/context_gen/cli.py +0 -507
- context_gen_cli-1.2.5/context_gen_cli.egg-info/PKG-INFO +0 -115
- {context_gen_cli-1.2.5 → context_gen_cli-1.3.5}/context_gen/__init__.py +0 -0
- {context_gen_cli-1.2.5 → context_gen_cli-1.3.5}/context_gen/extractor.py +0 -0
- {context_gen_cli-1.2.5 → context_gen_cli-1.3.5}/context_gen/generator.py +0 -0
- {context_gen_cli-1.2.5 → context_gen_cli-1.3.5}/context_gen/graph.py +0 -0
- {context_gen_cli-1.2.5 → context_gen_cli-1.3.5}/context_gen/mcp/__init__.py +0 -0
- {context_gen_cli-1.2.5 → context_gen_cli-1.3.5}/context_gen/mcp/advanced_tools.py +0 -0
- {context_gen_cli-1.2.5 → context_gen_cli-1.3.5}/context_gen_cli.egg-info/dependency_links.txt +0 -0
- {context_gen_cli-1.2.5 → context_gen_cli-1.3.5}/context_gen_cli.egg-info/entry_points.txt +0 -0
- {context_gen_cli-1.2.5 → context_gen_cli-1.3.5}/context_gen_cli.egg-info/top_level.txt +0 -0
- {context_gen_cli-1.2.5 → context_gen_cli-1.3.5}/setup.cfg +0 -0
- {context_gen_cli-1.2.5 → context_gen_cli-1.3.5}/tests/test_advanced_tools.py +0 -0
|
@@ -0,0 +1,192 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: context-gen-cli
|
|
3
|
+
Version: 1.3.5
|
|
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
|
+
Author: yakkshit
|
|
6
|
+
License-Expression: MIT
|
|
7
|
+
Keywords: llm,context,agent,cli,code-analysis,ast,graph,mcp
|
|
8
|
+
Classifier: Development Status :: 4 - Beta
|
|
9
|
+
Classifier: Environment :: Console
|
|
10
|
+
Classifier: Intended Audience :: Developers
|
|
11
|
+
Classifier: Programming Language :: Python :: 3
|
|
12
|
+
Classifier: Programming Language :: Python :: 3.9
|
|
13
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
14
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
15
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
16
|
+
Classifier: Topic :: Software Development :: Code Generators
|
|
17
|
+
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
18
|
+
Requires-Python: >=3.9
|
|
19
|
+
Description-Content-Type: text/markdown
|
|
20
|
+
Requires-Dist: typer>=0.12.0
|
|
21
|
+
Requires-Dist: rich>=13.7.0
|
|
22
|
+
Requires-Dist: shellingham>=1.5.4
|
|
23
|
+
Requires-Dist: pathspec>=0.12.1
|
|
24
|
+
Provides-Extra: dev
|
|
25
|
+
Requires-Dist: pytest>=8.0.0; extra == "dev"
|
|
26
|
+
Requires-Dist: build>=1.1.0; extra == "dev"
|
|
27
|
+
Requires-Dist: twine>=5.0.0; extra == "dev"
|
|
28
|
+
|
|
29
|
+
# ⚡ context-gen-cli (`ctx`) — Python Edition
|
|
30
|
+
|
|
31
|
+
<p align="center">
|
|
32
|
+
<a href="https://pypi.org/project/context-gen-cli/"><img src="https://img.shields.io/pypi/v/context-gen-cli.svg?color=3775a9" alt="PyPI version" /></a>
|
|
33
|
+
<a href="https://pypi.org/project/context-gen-cli/"><img src="https://img.shields.io/pypi/pyversions/context-gen-cli.svg" alt="Python Versions" /></a>
|
|
34
|
+
<a href="https://modelcontextprotocol.io"><img src="https://img.shields.io/badge/MCP-Protocol%20Ready-6366f1.svg" alt="MCP Ready" /></a>
|
|
35
|
+
<a href="https://opensource.org/licenses/MIT"><img src="https://img.shields.io/badge/License-MIT-blue.svg" alt="MIT License" /></a>
|
|
36
|
+
<a href="https://resume.cedzlabs.com/labs"><img src="https://img.shields.io/badge/Cedzlabs-Labs%20%E2%86%97-cyan.svg" alt="Cedzlabs Labs" /></a>
|
|
37
|
+
</p>
|
|
38
|
+
|
|
39
|
+
> **Stop dumping 50,000 raw tokens into your AI coding agent.**
|
|
40
|
+
> `context-gen-cli` analyzes any codebase using native AST parsers and **Entropy-Guided Reference Distillation (EGRD)** to give Cursor, Antigravity, Claude Code, and VS Code an ultra-dense **~40-token Senior Engineer Context Plan**—or stops to ask targeted questions if your prompt is ambiguous.
|
|
41
|
+
|
|
42
|
+
---
|
|
43
|
+
|
|
44
|
+
### 💡 Package Name vs. Command Alias
|
|
45
|
+
|
|
46
|
+
| What you install | What you run in your terminal |
|
|
47
|
+
| :--- | :--- |
|
|
48
|
+
| `pip install context-gen-cli` | **`ctx`** |
|
|
49
|
+
|
|
50
|
+
> **Why `ctx`?** While the package is registered as `context-gen-cli` on PyPI and npm, you shouldn't have to type 15 characters every time you run a command. The binary alias **`ctx`** is automatically registered upon installation. (The full `context-gen` alias is also preserved for scripts).
|
|
51
|
+
|
|
52
|
+
---
|
|
53
|
+
|
|
54
|
+
## 🌟 Highlights
|
|
55
|
+
|
|
56
|
+
- **⚡ Fast Short Alias (`ctx`)**: Type `ctx` anywhere in your terminal.
|
|
57
|
+
- **🧠 Entropy-Guided Reference Distillation (EGRD)**: Calculates Shannon Entropy ($H$) over codebase signatures to filter 98.5% of prompt noise.
|
|
58
|
+
- **🛡️ Anti-Hallucination Clarification Gate**: If your prompt is ambiguous ($H \ge 1.50\text{ bits}$), `ctx` halts guessing and asks targeted questions using real paths from your repo.
|
|
59
|
+
- **🕸️ 100% Accurate AST Knowledge Graph**: Uses native AST traversal to resolve relative imports, exports, roles, and downstream **Blast Radius** (what files break if this changes).
|
|
60
|
+
- **🔋 Zero GPU / CUDA Bloat**: Strictly capped at 1–2 CPU cores. No 15GB PyTorch downloads or local embedding models.
|
|
61
|
+
- **📁 Clean Monorepo / Workspace Storage**: Saves context models neatly into `context/agent.md`, `context/agent.json`, and `context/agent.yaml`.
|
|
62
|
+
- **🔒 Security Filter**: Strips virtual environments (`.venv*`, `venv*`), `.env*` files, pem/key certificates, and secrets automatically.
|
|
63
|
+
|
|
64
|
+
---
|
|
65
|
+
|
|
66
|
+
## 📦 Installation
|
|
67
|
+
|
|
68
|
+
```bash
|
|
69
|
+
# Standard installation
|
|
70
|
+
pip install context-gen-cli
|
|
71
|
+
|
|
72
|
+
# Or with pipx (recommended for isolated global CLI tools)
|
|
73
|
+
pipx install context-gen-cli
|
|
74
|
+
|
|
75
|
+
# Or with uv
|
|
76
|
+
uv tool install context-gen-cli
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
Verify installation:
|
|
80
|
+
```bash
|
|
81
|
+
ctx --help
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
---
|
|
85
|
+
|
|
86
|
+
## 🚀 Everyday Workflows & Examples
|
|
87
|
+
|
|
88
|
+
### 1. ⚡ All-In-One Workspace Mode (`ctx -d`)
|
|
89
|
+
Generates triple context formats (`agent.md`, `agent.json`, `agent.yaml`) in `context/` and runs a live auto-sync watcher in the background:
|
|
90
|
+
```bash
|
|
91
|
+
ctx -d
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
### 2. 🎯 Distill a Specific Prompt (`ctx distill`)
|
|
95
|
+
Generate a dense Senior Engineer Blueprint for any task:
|
|
96
|
+
```bash
|
|
97
|
+
ctx distill "add jwt refresh token rotation to authentication"
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
**Output:**
|
|
101
|
+
```text
|
|
102
|
+
╔═══════════════════════════════════════════════════════════════╗
|
|
103
|
+
║ 🧠 SENIOR ENGINEER CONTEXT PLAN (EGRD Distilled) ║
|
|
104
|
+
╚═══════════════════════════════════════════════════════════════╝
|
|
105
|
+
|
|
106
|
+
🎯 Task: add jwt refresh token rotation to authentication
|
|
107
|
+
⚙️ Engineering Mode: Architecture / Refactor
|
|
108
|
+
|
|
109
|
+
📂 Primary Files to Reference:
|
|
110
|
+
✔ src/services/auth.py
|
|
111
|
+
✔ src/routes/auth_routes.py
|
|
112
|
+
✔ src/models/user.py
|
|
113
|
+
|
|
114
|
+
💥 Blast Radius (Downstream Callers):
|
|
115
|
+
src/middleware/guard.py, src/app.py
|
|
116
|
+
|
|
117
|
+
🛡️ Architecture Guardrail:
|
|
118
|
+
Changes affect 2 downstream callers. Verify token payload backward compatibility.
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
### 3. ⚠️ The Clarification Gate (Ambiguous Prompts)
|
|
122
|
+
If you provide a vague prompt like:
|
|
123
|
+
```bash
|
|
124
|
+
ctx distill "update config"
|
|
125
|
+
```
|
|
126
|
+
Instead of hallucinating or dumping the entire repository, `ctx` pauses and shows:
|
|
127
|
+
```text
|
|
128
|
+
╔═══════════════════════════════════════════════════════════════╗
|
|
129
|
+
║ ⚠️ CLARIFICATION NEEDED — Ambiguous Prompt Detected ║
|
|
130
|
+
╚═══════════════════════════════════════════════════════════════╝
|
|
131
|
+
|
|
132
|
+
▸ Prompt entropy H = 1.84 bits exceeds confident threshold (1.50 bits).
|
|
133
|
+
▸ Disambiguate by specifying target:
|
|
134
|
+
1. src/config/database.py
|
|
135
|
+
2. src/config/server.py
|
|
136
|
+
3. src/config/redis.py
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
### 4. 📊 Check Token Weight & Savings (`ctx --tokens`)
|
|
140
|
+
Inspect how much context weight your AI agent saves compared to raw directory dumps:
|
|
141
|
+
```bash
|
|
142
|
+
ctx --tokens
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
---
|
|
146
|
+
|
|
147
|
+
## 📖 CLI Reference
|
|
148
|
+
|
|
149
|
+
| Command | Description |
|
|
150
|
+
| :--- | :--- |
|
|
151
|
+
| `ctx` | Scans workspace and generates `agent.md`, `agent.json`, `agent.yaml` in `context/` |
|
|
152
|
+
| `ctx -d` / `ctx --default` | **⚡ All-in-One**: Generates context and starts live file-watching sync |
|
|
153
|
+
| `ctx distill "<prompt>"` | **🧠 EGRD Distiller**: Generates high-signal Senior Engineer Blueprint |
|
|
154
|
+
| `ctx -w` / `ctx --watch` | **👀 Watch Mode**: Watches codebase and auto-updates context files on save |
|
|
155
|
+
| `ctx --tokens` | **📊 Token Analytics**: Displays token counts and compression ratios |
|
|
156
|
+
| `ctx -o <dir>` | **📁 Custom Output**: Specify output directory (defaults to `context/`) |
|
|
157
|
+
| `ctx -f <format>` | **📄 Format Filter**: Choose `md`, `json`, `yaml`, or `all` |
|
|
158
|
+
| `ctx update` | **🔄 Quick Refresh**: Re-indexes the current workspace |
|
|
159
|
+
| `ctx --help` | View full options and flag descriptions |
|
|
160
|
+
|
|
161
|
+
---
|
|
162
|
+
|
|
163
|
+
## 🛠️ MCP (Model Context Protocol) Integration
|
|
164
|
+
|
|
165
|
+
`ctx` can act as an MCP server for **Cursor**, **Claude Desktop**, **Antigravity**, and **VS Code**:
|
|
166
|
+
|
|
167
|
+
Add to your MCP settings (`claude_desktop_config.json` or Cursor Settings):
|
|
168
|
+
```json
|
|
169
|
+
{
|
|
170
|
+
"mcpServers": {
|
|
171
|
+
"context-gen": {
|
|
172
|
+
"command": "ctx",
|
|
173
|
+
"args": ["-d"]
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
```
|
|
178
|
+
|
|
179
|
+
---
|
|
180
|
+
|
|
181
|
+
## 🤝 Ecosystem & Links
|
|
182
|
+
|
|
183
|
+
- **Documentation & Showcase:** [https://resume.cedzlabs.com/labs](https://resume.cedzlabs.com/labs)
|
|
184
|
+
- **Node.js (npm):** `npx context-gen-cli@latest`
|
|
185
|
+
- **Homebrew (macOS):** `brew install context-gen-cli`
|
|
186
|
+
- **GitHub Repository:** [https://github.com/yakkshit/context-gen](https://github.com/yakkshit/context-gen)
|
|
187
|
+
|
|
188
|
+
---
|
|
189
|
+
|
|
190
|
+
## 📄 License
|
|
191
|
+
|
|
192
|
+
MIT © [Yakkshit](https://github.com/yakkshit) & [Cedzlabs](https://resume.cedzlabs.com/labs)
|
|
@@ -0,0 +1,164 @@
|
|
|
1
|
+
# ⚡ context-gen-cli (`ctx`) — Python Edition
|
|
2
|
+
|
|
3
|
+
<p align="center">
|
|
4
|
+
<a href="https://pypi.org/project/context-gen-cli/"><img src="https://img.shields.io/pypi/v/context-gen-cli.svg?color=3775a9" alt="PyPI version" /></a>
|
|
5
|
+
<a href="https://pypi.org/project/context-gen-cli/"><img src="https://img.shields.io/pypi/pyversions/context-gen-cli.svg" alt="Python Versions" /></a>
|
|
6
|
+
<a href="https://modelcontextprotocol.io"><img src="https://img.shields.io/badge/MCP-Protocol%20Ready-6366f1.svg" alt="MCP Ready" /></a>
|
|
7
|
+
<a href="https://opensource.org/licenses/MIT"><img src="https://img.shields.io/badge/License-MIT-blue.svg" alt="MIT License" /></a>
|
|
8
|
+
<a href="https://resume.cedzlabs.com/labs"><img src="https://img.shields.io/badge/Cedzlabs-Labs%20%E2%86%97-cyan.svg" alt="Cedzlabs Labs" /></a>
|
|
9
|
+
</p>
|
|
10
|
+
|
|
11
|
+
> **Stop dumping 50,000 raw tokens into your AI coding agent.**
|
|
12
|
+
> `context-gen-cli` analyzes any codebase using native AST parsers and **Entropy-Guided Reference Distillation (EGRD)** to give Cursor, Antigravity, Claude Code, and VS Code an ultra-dense **~40-token Senior Engineer Context Plan**—or stops to ask targeted questions if your prompt is ambiguous.
|
|
13
|
+
|
|
14
|
+
---
|
|
15
|
+
|
|
16
|
+
### 💡 Package Name vs. Command Alias
|
|
17
|
+
|
|
18
|
+
| What you install | What you run in your terminal |
|
|
19
|
+
| :--- | :--- |
|
|
20
|
+
| `pip install context-gen-cli` | **`ctx`** |
|
|
21
|
+
|
|
22
|
+
> **Why `ctx`?** While the package is registered as `context-gen-cli` on PyPI and npm, you shouldn't have to type 15 characters every time you run a command. The binary alias **`ctx`** is automatically registered upon installation. (The full `context-gen` alias is also preserved for scripts).
|
|
23
|
+
|
|
24
|
+
---
|
|
25
|
+
|
|
26
|
+
## 🌟 Highlights
|
|
27
|
+
|
|
28
|
+
- **⚡ Fast Short Alias (`ctx`)**: Type `ctx` anywhere in your terminal.
|
|
29
|
+
- **🧠 Entropy-Guided Reference Distillation (EGRD)**: Calculates Shannon Entropy ($H$) over codebase signatures to filter 98.5% of prompt noise.
|
|
30
|
+
- **🛡️ Anti-Hallucination Clarification Gate**: If your prompt is ambiguous ($H \ge 1.50\text{ bits}$), `ctx` halts guessing and asks targeted questions using real paths from your repo.
|
|
31
|
+
- **🕸️ 100% Accurate AST Knowledge Graph**: Uses native AST traversal to resolve relative imports, exports, roles, and downstream **Blast Radius** (what files break if this changes).
|
|
32
|
+
- **🔋 Zero GPU / CUDA Bloat**: Strictly capped at 1–2 CPU cores. No 15GB PyTorch downloads or local embedding models.
|
|
33
|
+
- **📁 Clean Monorepo / Workspace Storage**: Saves context models neatly into `context/agent.md`, `context/agent.json`, and `context/agent.yaml`.
|
|
34
|
+
- **🔒 Security Filter**: Strips virtual environments (`.venv*`, `venv*`), `.env*` files, pem/key certificates, and secrets automatically.
|
|
35
|
+
|
|
36
|
+
---
|
|
37
|
+
|
|
38
|
+
## 📦 Installation
|
|
39
|
+
|
|
40
|
+
```bash
|
|
41
|
+
# Standard installation
|
|
42
|
+
pip install context-gen-cli
|
|
43
|
+
|
|
44
|
+
# Or with pipx (recommended for isolated global CLI tools)
|
|
45
|
+
pipx install context-gen-cli
|
|
46
|
+
|
|
47
|
+
# Or with uv
|
|
48
|
+
uv tool install context-gen-cli
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
Verify installation:
|
|
52
|
+
```bash
|
|
53
|
+
ctx --help
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
---
|
|
57
|
+
|
|
58
|
+
## 🚀 Everyday Workflows & Examples
|
|
59
|
+
|
|
60
|
+
### 1. ⚡ All-In-One Workspace Mode (`ctx -d`)
|
|
61
|
+
Generates triple context formats (`agent.md`, `agent.json`, `agent.yaml`) in `context/` and runs a live auto-sync watcher in the background:
|
|
62
|
+
```bash
|
|
63
|
+
ctx -d
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
### 2. 🎯 Distill a Specific Prompt (`ctx distill`)
|
|
67
|
+
Generate a dense Senior Engineer Blueprint for any task:
|
|
68
|
+
```bash
|
|
69
|
+
ctx distill "add jwt refresh token rotation to authentication"
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
**Output:**
|
|
73
|
+
```text
|
|
74
|
+
╔═══════════════════════════════════════════════════════════════╗
|
|
75
|
+
║ 🧠 SENIOR ENGINEER CONTEXT PLAN (EGRD Distilled) ║
|
|
76
|
+
╚═══════════════════════════════════════════════════════════════╝
|
|
77
|
+
|
|
78
|
+
🎯 Task: add jwt refresh token rotation to authentication
|
|
79
|
+
⚙️ Engineering Mode: Architecture / Refactor
|
|
80
|
+
|
|
81
|
+
📂 Primary Files to Reference:
|
|
82
|
+
✔ src/services/auth.py
|
|
83
|
+
✔ src/routes/auth_routes.py
|
|
84
|
+
✔ src/models/user.py
|
|
85
|
+
|
|
86
|
+
💥 Blast Radius (Downstream Callers):
|
|
87
|
+
src/middleware/guard.py, src/app.py
|
|
88
|
+
|
|
89
|
+
🛡️ Architecture Guardrail:
|
|
90
|
+
Changes affect 2 downstream callers. Verify token payload backward compatibility.
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
### 3. ⚠️ The Clarification Gate (Ambiguous Prompts)
|
|
94
|
+
If you provide a vague prompt like:
|
|
95
|
+
```bash
|
|
96
|
+
ctx distill "update config"
|
|
97
|
+
```
|
|
98
|
+
Instead of hallucinating or dumping the entire repository, `ctx` pauses and shows:
|
|
99
|
+
```text
|
|
100
|
+
╔═══════════════════════════════════════════════════════════════╗
|
|
101
|
+
║ ⚠️ CLARIFICATION NEEDED — Ambiguous Prompt Detected ║
|
|
102
|
+
╚═══════════════════════════════════════════════════════════════╝
|
|
103
|
+
|
|
104
|
+
▸ Prompt entropy H = 1.84 bits exceeds confident threshold (1.50 bits).
|
|
105
|
+
▸ Disambiguate by specifying target:
|
|
106
|
+
1. src/config/database.py
|
|
107
|
+
2. src/config/server.py
|
|
108
|
+
3. src/config/redis.py
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
### 4. 📊 Check Token Weight & Savings (`ctx --tokens`)
|
|
112
|
+
Inspect how much context weight your AI agent saves compared to raw directory dumps:
|
|
113
|
+
```bash
|
|
114
|
+
ctx --tokens
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
---
|
|
118
|
+
|
|
119
|
+
## 📖 CLI Reference
|
|
120
|
+
|
|
121
|
+
| Command | Description |
|
|
122
|
+
| :--- | :--- |
|
|
123
|
+
| `ctx` | Scans workspace and generates `agent.md`, `agent.json`, `agent.yaml` in `context/` |
|
|
124
|
+
| `ctx -d` / `ctx --default` | **⚡ All-in-One**: Generates context and starts live file-watching sync |
|
|
125
|
+
| `ctx distill "<prompt>"` | **🧠 EGRD Distiller**: Generates high-signal Senior Engineer Blueprint |
|
|
126
|
+
| `ctx -w` / `ctx --watch` | **👀 Watch Mode**: Watches codebase and auto-updates context files on save |
|
|
127
|
+
| `ctx --tokens` | **📊 Token Analytics**: Displays token counts and compression ratios |
|
|
128
|
+
| `ctx -o <dir>` | **📁 Custom Output**: Specify output directory (defaults to `context/`) |
|
|
129
|
+
| `ctx -f <format>` | **📄 Format Filter**: Choose `md`, `json`, `yaml`, or `all` |
|
|
130
|
+
| `ctx update` | **🔄 Quick Refresh**: Re-indexes the current workspace |
|
|
131
|
+
| `ctx --help` | View full options and flag descriptions |
|
|
132
|
+
|
|
133
|
+
---
|
|
134
|
+
|
|
135
|
+
## 🛠️ MCP (Model Context Protocol) Integration
|
|
136
|
+
|
|
137
|
+
`ctx` can act as an MCP server for **Cursor**, **Claude Desktop**, **Antigravity**, and **VS Code**:
|
|
138
|
+
|
|
139
|
+
Add to your MCP settings (`claude_desktop_config.json` or Cursor Settings):
|
|
140
|
+
```json
|
|
141
|
+
{
|
|
142
|
+
"mcpServers": {
|
|
143
|
+
"context-gen": {
|
|
144
|
+
"command": "ctx",
|
|
145
|
+
"args": ["-d"]
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
---
|
|
152
|
+
|
|
153
|
+
## 🤝 Ecosystem & Links
|
|
154
|
+
|
|
155
|
+
- **Documentation & Showcase:** [https://resume.cedzlabs.com/labs](https://resume.cedzlabs.com/labs)
|
|
156
|
+
- **Node.js (npm):** `npx context-gen-cli@latest`
|
|
157
|
+
- **Homebrew (macOS):** `brew install context-gen-cli`
|
|
158
|
+
- **GitHub Repository:** [https://github.com/yakkshit/context-gen](https://github.com/yakkshit/context-gen)
|
|
159
|
+
|
|
160
|
+
---
|
|
161
|
+
|
|
162
|
+
## 📄 License
|
|
163
|
+
|
|
164
|
+
MIT © [Yakkshit](https://github.com/yakkshit) & [Cedzlabs](https://resume.cedzlabs.com/labs)
|
|
@@ -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()
|