codigest 0.3.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- codigest-0.3.0/.github/workflows/main.yml +30 -0
- codigest-0.3.0/.github/workflows/publish.yml +75 -0
- codigest-0.3.0/.gitignore +87 -0
- codigest-0.3.0/.python-version +1 -0
- codigest-0.3.0/PKG-INFO +145 -0
- codigest-0.3.0/README.md +120 -0
- codigest-0.3.0/pyproject.toml +38 -0
- codigest-0.3.0/src/codigest/__init__.py +0 -0
- codigest-0.3.0/src/codigest/commands/diff.py +84 -0
- codigest-0.3.0/src/codigest/commands/digest.py +88 -0
- codigest-0.3.0/src/codigest/commands/init.py +87 -0
- codigest-0.3.0/src/codigest/commands/scan.py +142 -0
- codigest-0.3.0/src/codigest/commands/semdiff.py +131 -0
- codigest-0.3.0/src/codigest/commands/tree.py +110 -0
- codigest-0.3.0/src/codigest/config.py +0 -0
- codigest-0.3.0/src/codigest/core/git_ops.py +73 -0
- codigest-0.3.0/src/codigest/core/processor.py +31 -0
- codigest-0.3.0/src/codigest/core/prompts.py +164 -0
- codigest-0.3.0/src/codigest/core/scanner.py +99 -0
- codigest-0.3.0/src/codigest/core/semdiff.py +175 -0
- codigest-0.3.0/src/codigest/core/shadow.py +171 -0
- codigest-0.3.0/src/codigest/core/structure.py +48 -0
- codigest-0.3.0/src/codigest/core/tags.py +75 -0
- codigest-0.3.0/src/codigest/core/tokenizer.py +14 -0
- codigest-0.3.0/src/codigest/main.py +34 -0
- codigest-0.3.0/uv.lock +206 -0
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
name: Publish to PyPI
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
tags:
|
|
6
|
+
- 'v*'
|
|
7
|
+
workflow_dispatch:
|
|
8
|
+
jobs:
|
|
9
|
+
pypi-publish:
|
|
10
|
+
name: Build and publish Python distribution to PyPI
|
|
11
|
+
runs-on: ubuntu-latest
|
|
12
|
+
environment: github
|
|
13
|
+
permissions:
|
|
14
|
+
id-token: write
|
|
15
|
+
contents: read
|
|
16
|
+
|
|
17
|
+
steps:
|
|
18
|
+
- uses: actions/checkout@v4
|
|
19
|
+
|
|
20
|
+
- name: Install uv
|
|
21
|
+
uses: astral-sh/setup-uv@v5
|
|
22
|
+
|
|
23
|
+
- name: Set up Python
|
|
24
|
+
run: uv python install 3.14
|
|
25
|
+
|
|
26
|
+
- name: Build package
|
|
27
|
+
run: uv build
|
|
28
|
+
|
|
29
|
+
- name: Publish package distributions to PyPI
|
|
30
|
+
uses: pypa/gh-action-pypi-publish@release/v1
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
name: Publish Python distributions to PyPI and GitHub Pages
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
tags:
|
|
6
|
+
- 'v*' # v0.3.0 태그 푸시 시 배포 실행
|
|
7
|
+
# branches:
|
|
8
|
+
# - main # main 브랜치 푸시 시 문서 배포 실행 (옵션)
|
|
9
|
+
|
|
10
|
+
jobs:
|
|
11
|
+
build-n-publish:
|
|
12
|
+
name: Build and publish Python distributions to PyPI
|
|
13
|
+
runs-on: ubuntu-latest
|
|
14
|
+
# v* 태그일 때만 실행
|
|
15
|
+
if: startsWith(github.ref, 'refs/tags/v')
|
|
16
|
+
environment: release
|
|
17
|
+
permissions:
|
|
18
|
+
id-token: write # Trusted Publishing을 위한 필수 권한
|
|
19
|
+
contents: read
|
|
20
|
+
|
|
21
|
+
steps:
|
|
22
|
+
- uses: actions/checkout@v4
|
|
23
|
+
|
|
24
|
+
# [변경] uv 설치 (가장 빠르고 확실한 방법)
|
|
25
|
+
- name: Install uv
|
|
26
|
+
uses: astral-sh/setup-uv@v5
|
|
27
|
+
|
|
28
|
+
# [변경] Python 3.14 설정 (uv 이용)
|
|
29
|
+
- name: Set up Python
|
|
30
|
+
run: uv python install 3.14
|
|
31
|
+
|
|
32
|
+
# [변경] 의존성 설치 및 빌드 (uv build 하나로 해결)
|
|
33
|
+
- name: Build package
|
|
34
|
+
run: uv build
|
|
35
|
+
|
|
36
|
+
# PyPI 배포 (기존 형식 유지)
|
|
37
|
+
- name: Publish package distributions to PyPI
|
|
38
|
+
uses: pypa/gh-action-pypi-publish@release/v1
|
|
39
|
+
|
|
40
|
+
deploy-docs:
|
|
41
|
+
name: Build and deploy Sphinx docs to GitHub Pages
|
|
42
|
+
runs-on: ubuntu-latest
|
|
43
|
+
if: github.ref == 'refs/heads/main'
|
|
44
|
+
permissions:
|
|
45
|
+
contents: write
|
|
46
|
+
steps:
|
|
47
|
+
- uses: actions/checkout@v4
|
|
48
|
+
|
|
49
|
+
- name: Install uv
|
|
50
|
+
uses: astral-sh/setup-uv@v5
|
|
51
|
+
|
|
52
|
+
- name: Set up Python
|
|
53
|
+
run: uv python install 3.14
|
|
54
|
+
|
|
55
|
+
- name: Install Python and Sphinx dependencies
|
|
56
|
+
run: |
|
|
57
|
+
uv pip install --system --upgrade pip
|
|
58
|
+
if [ -f docs/requirements.txt ]; then uv pip install --system -r docs/requirements.txt; fi
|
|
59
|
+
|
|
60
|
+
- name: Build HTML docs with Sphinx
|
|
61
|
+
run: |
|
|
62
|
+
if [ -d "docs" ]; then
|
|
63
|
+
sphinx-build -b html docs/source docs/html
|
|
64
|
+
touch docs/html/.nojekyll
|
|
65
|
+
else
|
|
66
|
+
echo "No docs folder found, skipping build."
|
|
67
|
+
mkdir -p docs/html
|
|
68
|
+
touch docs/html/.nojekyll
|
|
69
|
+
fi
|
|
70
|
+
|
|
71
|
+
- name: Deploy to GitHub Pages
|
|
72
|
+
uses: peaceiris/actions-gh-pages@v3
|
|
73
|
+
with:
|
|
74
|
+
github_token: ${{ secrets.GITHUB_TOKEN }}
|
|
75
|
+
publish_dir: docs/html
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
# --------------------------------------------------------------------
|
|
2
|
+
# Python Core & Bytecode
|
|
3
|
+
# --------------------------------------------------------------------
|
|
4
|
+
__pycache__/
|
|
5
|
+
*.py[cod]
|
|
6
|
+
*$py.class
|
|
7
|
+
|
|
8
|
+
# --------------------------------------------------------------------
|
|
9
|
+
# Virtual Environments (uv / venv)
|
|
10
|
+
# --------------------------------------------------------------------
|
|
11
|
+
.venv/
|
|
12
|
+
venv/
|
|
13
|
+
env/
|
|
14
|
+
ENV/
|
|
15
|
+
|
|
16
|
+
# --------------------------------------------------------------------
|
|
17
|
+
# Distribution / Build Artifacts
|
|
18
|
+
# --------------------------------------------------------------------
|
|
19
|
+
build/
|
|
20
|
+
dist/
|
|
21
|
+
wheels/
|
|
22
|
+
*.egg-info/
|
|
23
|
+
.eggs/
|
|
24
|
+
*.egg
|
|
25
|
+
MANIFEST
|
|
26
|
+
|
|
27
|
+
# --------------------------------------------------------------------
|
|
28
|
+
# Tooling Caches & Logs
|
|
29
|
+
# --------------------------------------------------------------------
|
|
30
|
+
# Ruff
|
|
31
|
+
.ruff_cache/
|
|
32
|
+
|
|
33
|
+
# MyPy
|
|
34
|
+
.mypy_cache/
|
|
35
|
+
.dmypy.json
|
|
36
|
+
dmypy.json
|
|
37
|
+
|
|
38
|
+
# Pytest / Coverage
|
|
39
|
+
.pytest_cache/
|
|
40
|
+
.coverage
|
|
41
|
+
htmlcov/
|
|
42
|
+
coverage.xml
|
|
43
|
+
*.cover
|
|
44
|
+
|
|
45
|
+
# Log files
|
|
46
|
+
*.log
|
|
47
|
+
|
|
48
|
+
# --------------------------------------------------------------------
|
|
49
|
+
# Environment Variables & Secrets
|
|
50
|
+
# --------------------------------------------------------------------
|
|
51
|
+
.env
|
|
52
|
+
.env.local
|
|
53
|
+
.secrets
|
|
54
|
+
|
|
55
|
+
# --------------------------------------------------------------------
|
|
56
|
+
# IDE & Editor Settings
|
|
57
|
+
# --------------------------------------------------------------------
|
|
58
|
+
# VS Code
|
|
59
|
+
.vscode/
|
|
60
|
+
!.vscode/settings.json
|
|
61
|
+
!.vscode/tasks.json
|
|
62
|
+
!.vscode/launch.json
|
|
63
|
+
!.vscode/extensions.json
|
|
64
|
+
|
|
65
|
+
# JetBrains / PyCharm
|
|
66
|
+
.idea/
|
|
67
|
+
|
|
68
|
+
# macOS
|
|
69
|
+
.DS_Store
|
|
70
|
+
|
|
71
|
+
# --------------------------------------------------------------------
|
|
72
|
+
# Codigest Project Specifics
|
|
73
|
+
# --------------------------------------------------------------------
|
|
74
|
+
# Artifact directory (stores config, prompts, but often ignored if local-only)
|
|
75
|
+
# You might want to commit .codigest/config.toml and prompts.toml,
|
|
76
|
+
# but ignore the output snapshots.
|
|
77
|
+
# For now, following your previous pattern:
|
|
78
|
+
.codigest/
|
|
79
|
+
|
|
80
|
+
# Default output filenames (if generated in root)
|
|
81
|
+
snapshot.xml
|
|
82
|
+
digest.xml
|
|
83
|
+
changes.diff
|
|
84
|
+
tree.txt
|
|
85
|
+
|
|
86
|
+
# Temporary test outputs
|
|
87
|
+
test_output/
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
3.14
|
codigest-0.3.0/PKG-INFO
ADDED
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: codigest
|
|
3
|
+
Version: 0.3.0
|
|
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 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
|
+
## Core Philosophy
|
|
33
|
+
|
|
34
|
+
* **Read-Only & Safe**: Codigest never modifies your source code. It only reads, analyzes, and formats context.
|
|
35
|
+
* **Context-Aware**: Instead of dumping raw text, it structures code into XML snapshots designed for LLM comprehension.
|
|
36
|
+
* **Session-Based Tracking**: It maintains an internal anchor to track "work-in-progress" changes independently of your Git commits.
|
|
37
|
+
* **Python 3.14 Native**: Built using modern Python features including PEP 750 Tag Strings for safe XML generation.
|
|
38
|
+
|
|
39
|
+
## Installation
|
|
40
|
+
|
|
41
|
+
Requires **Python 3.14+**.
|
|
42
|
+
|
|
43
|
+
```bash
|
|
44
|
+
# Install via uv
|
|
45
|
+
git clone https://github.com/SJB7777/codigest.git
|
|
46
|
+
cd codigest
|
|
47
|
+
uv tool install .
|
|
48
|
+
````
|
|
49
|
+
|
|
50
|
+
## Workflow & Commands
|
|
51
|
+
|
|
52
|
+
### 1\. Initialization
|
|
53
|
+
|
|
54
|
+
Sets up the `.codigest` directory and captures the initial baseline anchor.
|
|
55
|
+
|
|
56
|
+
```bash
|
|
57
|
+
codigest init
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
### 2\. Full Context Snapshot (`scan`)
|
|
61
|
+
|
|
62
|
+
Scans the entire codebase and generates a structured XML snapshot.
|
|
63
|
+
|
|
64
|
+
* **Output:** `.codigest/snapshot.xml`
|
|
65
|
+
* **Use Case:** Providing the LLM with the full project context at the start of a session.
|
|
66
|
+
* **Side Effect:** Updates the internal Context Anchor to the current state.
|
|
67
|
+
|
|
68
|
+
```bash
|
|
69
|
+
codigest scan --m " Python 3.14 project. Do NOT use typing. List/Dict."
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
### 3\. Incremental Changes (`diff`)
|
|
73
|
+
|
|
74
|
+
Tracks text-based changes between the last `scan` and the current working tree.
|
|
75
|
+
|
|
76
|
+
* **Output:** `.codigest/changes.diff`
|
|
77
|
+
* **Use Case:** "I modified 3 files. Here is exactly what changed since the last snapshot."
|
|
78
|
+
* **Note:** This is based on the internal Shadow Git, not your project's Git history.
|
|
79
|
+
|
|
80
|
+
```bash
|
|
81
|
+
codigest diff
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
### 4\. Semantic Analysis (`semdiff`)
|
|
85
|
+
|
|
86
|
+
Analyzes **structural changes** (AST-based) rather than line-by-line text differences.
|
|
87
|
+
|
|
88
|
+
* **Output:** `.codigest/semdiff.xml`
|
|
89
|
+
* **Use Case:** "I refactored the API. Show me which functions were added, removed, or had their signatures changed."
|
|
90
|
+
* **Benefit:** Significantly reduces token usage compared to raw diffs by ignoring formatting/comment changes.
|
|
91
|
+
|
|
92
|
+
```bash
|
|
93
|
+
codigest semdiff
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
### 5\. Architecture Digest (`digest`)
|
|
97
|
+
|
|
98
|
+
Generates a high-level outline of the project structure (Classes, Functions, Methods only).
|
|
99
|
+
|
|
100
|
+
* **Output:** `.codigest/digest.xml`
|
|
101
|
+
* **Use Case:** "Don't read the implementation details. Just understand the class hierarchy and available methods."
|
|
102
|
+
|
|
103
|
+
<!-- end list -->
|
|
104
|
+
|
|
105
|
+
```bash
|
|
106
|
+
codigest digest
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
## Configuration
|
|
110
|
+
|
|
111
|
+
You can customize behavior in `.codigest/config.toml`.
|
|
112
|
+
|
|
113
|
+
```toml
|
|
114
|
+
[filter]
|
|
115
|
+
# Target extensions
|
|
116
|
+
extensions = [".py", ".ts", ".rs", ".md", ".json"]
|
|
117
|
+
|
|
118
|
+
# Exclude patterns (Gitignore syntax)
|
|
119
|
+
exclude_patterns = [
|
|
120
|
+
"*.lock",
|
|
121
|
+
"tests/data/",
|
|
122
|
+
"legacy_code/"
|
|
123
|
+
]
|
|
124
|
+
|
|
125
|
+
[output]
|
|
126
|
+
format = "xml"
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
## Architecture Details
|
|
130
|
+
|
|
131
|
+
**Context Anchor (Shadow Git)**
|
|
132
|
+
Codigest maintains a hidden, lightweight Git repository inside `.codigest/anchor`.
|
|
133
|
+
|
|
134
|
+
* When you run `scan`, the current state is committed to this anchor.
|
|
135
|
+
* When you run `diff`, the tool compares your working directory against this anchor.
|
|
136
|
+
* When you run `semdiff`, the tool parses the AST of the anchor version and the current version to detect logical drifts.
|
|
137
|
+
|
|
138
|
+
**Safety Mechanisms**
|
|
139
|
+
|
|
140
|
+
* **structure-aware dedent:** Ensures XML tags are perfectly aligned regardless of code indentation.
|
|
141
|
+
* **Automatic Exclusion:** Self-referential files (`.codigest/`) are automatically ignored to prevent recursion loops.
|
|
142
|
+
|
|
143
|
+
## License
|
|
144
|
+
|
|
145
|
+
MIT License
|
codigest-0.3.0/README.md
ADDED
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
# Codigest
|
|
2
|
+
|
|
3
|
+
Codigest is a 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
|
+
## Core Philosophy
|
|
8
|
+
|
|
9
|
+
* **Read-Only & Safe**: Codigest never modifies your source code. It only reads, analyzes, and formats context.
|
|
10
|
+
* **Context-Aware**: Instead of dumping raw text, it structures code into XML snapshots designed for LLM comprehension.
|
|
11
|
+
* **Session-Based Tracking**: It maintains an internal anchor to track "work-in-progress" changes independently of your Git commits.
|
|
12
|
+
* **Python 3.14 Native**: Built using modern Python features including PEP 750 Tag Strings for safe XML generation.
|
|
13
|
+
|
|
14
|
+
## Installation
|
|
15
|
+
|
|
16
|
+
Requires **Python 3.14+**.
|
|
17
|
+
|
|
18
|
+
```bash
|
|
19
|
+
# Install via uv
|
|
20
|
+
git clone https://github.com/SJB7777/codigest.git
|
|
21
|
+
cd codigest
|
|
22
|
+
uv tool install .
|
|
23
|
+
````
|
|
24
|
+
|
|
25
|
+
## Workflow & Commands
|
|
26
|
+
|
|
27
|
+
### 1\. Initialization
|
|
28
|
+
|
|
29
|
+
Sets up the `.codigest` directory and captures the initial baseline anchor.
|
|
30
|
+
|
|
31
|
+
```bash
|
|
32
|
+
codigest init
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
### 2\. Full Context Snapshot (`scan`)
|
|
36
|
+
|
|
37
|
+
Scans the entire codebase and generates a structured XML snapshot.
|
|
38
|
+
|
|
39
|
+
* **Output:** `.codigest/snapshot.xml`
|
|
40
|
+
* **Use Case:** Providing the LLM with the full project context at the start of a session.
|
|
41
|
+
* **Side Effect:** Updates the internal Context Anchor to the current state.
|
|
42
|
+
|
|
43
|
+
```bash
|
|
44
|
+
codigest scan --m " Python 3.14 project. Do NOT use typing. List/Dict."
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
### 3\. Incremental Changes (`diff`)
|
|
48
|
+
|
|
49
|
+
Tracks text-based changes between the last `scan` and the current working tree.
|
|
50
|
+
|
|
51
|
+
* **Output:** `.codigest/changes.diff`
|
|
52
|
+
* **Use Case:** "I modified 3 files. Here is exactly what changed since the last snapshot."
|
|
53
|
+
* **Note:** This is based on the internal Shadow Git, not your project's Git history.
|
|
54
|
+
|
|
55
|
+
```bash
|
|
56
|
+
codigest diff
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
### 4\. Semantic Analysis (`semdiff`)
|
|
60
|
+
|
|
61
|
+
Analyzes **structural changes** (AST-based) rather than line-by-line text differences.
|
|
62
|
+
|
|
63
|
+
* **Output:** `.codigest/semdiff.xml`
|
|
64
|
+
* **Use Case:** "I refactored the API. Show me which functions were added, removed, or had their signatures changed."
|
|
65
|
+
* **Benefit:** Significantly reduces token usage compared to raw diffs by ignoring formatting/comment changes.
|
|
66
|
+
|
|
67
|
+
```bash
|
|
68
|
+
codigest semdiff
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
### 5\. Architecture Digest (`digest`)
|
|
72
|
+
|
|
73
|
+
Generates a high-level outline of the project structure (Classes, Functions, Methods only).
|
|
74
|
+
|
|
75
|
+
* **Output:** `.codigest/digest.xml`
|
|
76
|
+
* **Use Case:** "Don't read the implementation details. Just understand the class hierarchy and available methods."
|
|
77
|
+
|
|
78
|
+
<!-- end list -->
|
|
79
|
+
|
|
80
|
+
```bash
|
|
81
|
+
codigest digest
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
## Configuration
|
|
85
|
+
|
|
86
|
+
You can customize behavior in `.codigest/config.toml`.
|
|
87
|
+
|
|
88
|
+
```toml
|
|
89
|
+
[filter]
|
|
90
|
+
# Target extensions
|
|
91
|
+
extensions = [".py", ".ts", ".rs", ".md", ".json"]
|
|
92
|
+
|
|
93
|
+
# Exclude patterns (Gitignore syntax)
|
|
94
|
+
exclude_patterns = [
|
|
95
|
+
"*.lock",
|
|
96
|
+
"tests/data/",
|
|
97
|
+
"legacy_code/"
|
|
98
|
+
]
|
|
99
|
+
|
|
100
|
+
[output]
|
|
101
|
+
format = "xml"
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
## Architecture Details
|
|
105
|
+
|
|
106
|
+
**Context Anchor (Shadow Git)**
|
|
107
|
+
Codigest maintains a hidden, lightweight Git repository inside `.codigest/anchor`.
|
|
108
|
+
|
|
109
|
+
* When you run `scan`, the current state is committed to this anchor.
|
|
110
|
+
* When you run `diff`, the tool compares your working directory against this anchor.
|
|
111
|
+
* When you run `semdiff`, the tool parses the AST of the anchor version and the current version to detect logical drifts.
|
|
112
|
+
|
|
113
|
+
**Safety Mechanisms**
|
|
114
|
+
|
|
115
|
+
* **structure-aware dedent:** Ensures XML tags are perfectly aligned regardless of code indentation.
|
|
116
|
+
* **Automatic Exclusion:** Self-referential files (`.codigest/`) are automatically ignored to prevent recursion loops.
|
|
117
|
+
|
|
118
|
+
## License
|
|
119
|
+
|
|
120
|
+
MIT License
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
[project]
|
|
2
|
+
name = "codigest"
|
|
3
|
+
version = "0.3.0"
|
|
4
|
+
description = "Human-Centered Codebase Context Manager for LLMs"
|
|
5
|
+
authors = [{name = "Codigest Team", email = "sngd024@google.com"}]
|
|
6
|
+
readme = "README.md"
|
|
7
|
+
requires-python = ">=3.14"
|
|
8
|
+
license = { text = "MIT" }
|
|
9
|
+
dependencies = [
|
|
10
|
+
"typer",
|
|
11
|
+
"rich",
|
|
12
|
+
"loguru",
|
|
13
|
+
"pathspec",
|
|
14
|
+
"pyperclip",
|
|
15
|
+
"tomli-w",
|
|
16
|
+
]
|
|
17
|
+
|
|
18
|
+
classifiers = [
|
|
19
|
+
"Programming Language :: Python :: 3",
|
|
20
|
+
"Programming Language :: Python :: 3.14",
|
|
21
|
+
"License :: OSI Approved :: MIT License",
|
|
22
|
+
"Operating System :: OS Independent",
|
|
23
|
+
"Topic :: Software Development :: Libraries :: Python Modules",
|
|
24
|
+
"Topic :: Utilities",
|
|
25
|
+
"Intended Audience :: Developers",
|
|
26
|
+
]
|
|
27
|
+
|
|
28
|
+
[project.urls]
|
|
29
|
+
Homepage = "https://github.com/SJB777/codigest"
|
|
30
|
+
Repository = "https://github.com/SJB777/codigest"
|
|
31
|
+
Issues = "https://github.com/SJB777/codigest/issues"
|
|
32
|
+
|
|
33
|
+
[project.scripts]
|
|
34
|
+
codigest = "codigest.main:app"
|
|
35
|
+
|
|
36
|
+
[build-system]
|
|
37
|
+
requires = ["hatchling"]
|
|
38
|
+
build-backend = "hatchling.build"
|
|
File without changes
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
import typer
|
|
2
|
+
import pyperclip
|
|
3
|
+
from pathlib import Path
|
|
4
|
+
from rich.console import Console
|
|
5
|
+
from rich.progress import Progress, SpinnerColumn, TextColumn
|
|
6
|
+
|
|
7
|
+
from ..core import scanner, prompts, shadow
|
|
8
|
+
from .scan import _load_config_filters
|
|
9
|
+
|
|
10
|
+
app = typer.Typer()
|
|
11
|
+
console = Console()
|
|
12
|
+
|
|
13
|
+
@app.callback(invoke_without_command=True)
|
|
14
|
+
def handle(
|
|
15
|
+
copy: bool = typer.Option(True, help="Auto-copy to clipboard"),
|
|
16
|
+
save: bool = typer.Option(True, help="Save to .codigest/changes.diff"),
|
|
17
|
+
message: str = typer.Option("", "--message", "-m", help="Add specific instruction context"),
|
|
18
|
+
):
|
|
19
|
+
"""
|
|
20
|
+
[Context Update] Shows changes since the last 'codigest scan'.
|
|
21
|
+
Useful for updating LLM context without re-uploading everything.
|
|
22
|
+
"""
|
|
23
|
+
root_path = Path.cwd()
|
|
24
|
+
anchor = shadow.ContextAnchor(root_path)
|
|
25
|
+
|
|
26
|
+
# 1. Check Baseline Existence
|
|
27
|
+
last_update = anchor.get_last_update_time()
|
|
28
|
+
if last_update == "Never":
|
|
29
|
+
console.print("[yellow]⚠️ No scan history found.[/yellow]")
|
|
30
|
+
console.print(" Run [bold cyan]codigest scan[/bold cyan] first to establish a baseline.")
|
|
31
|
+
raise typer.Exit(1)
|
|
32
|
+
|
|
33
|
+
console.print(f"[dim]Checking changes since last scan ({last_update})...[/dim]")
|
|
34
|
+
|
|
35
|
+
# 2. Calculate Diff
|
|
36
|
+
with Progress(
|
|
37
|
+
SpinnerColumn(),
|
|
38
|
+
TextColumn("[bold blue]Analyzing changes...[/bold blue]"),
|
|
39
|
+
transient=True,
|
|
40
|
+
console=console
|
|
41
|
+
) as progress:
|
|
42
|
+
task = progress.add_task("diff", total=None)
|
|
43
|
+
|
|
44
|
+
# Load same filters as scan
|
|
45
|
+
extensions, extra_ignores = _load_config_filters(root_path)
|
|
46
|
+
|
|
47
|
+
# Get current valid files (Working Tree)
|
|
48
|
+
current_files = scanner.scan_project(root_path, extensions, extra_ignores)
|
|
49
|
+
|
|
50
|
+
# Compare Working Tree vs Anchor
|
|
51
|
+
diff_content = anchor.get_changes(current_files)
|
|
52
|
+
|
|
53
|
+
progress.update(task, completed=100)
|
|
54
|
+
|
|
55
|
+
if not diff_content.strip():
|
|
56
|
+
console.print("[green]✨ No changes detected since last scan.[/green]")
|
|
57
|
+
return
|
|
58
|
+
|
|
59
|
+
# 3. Render
|
|
60
|
+
prompt_engine = prompts.get_engine(root_path)
|
|
61
|
+
try:
|
|
62
|
+
formatted_diff = prompt_engine.render(
|
|
63
|
+
"diff",
|
|
64
|
+
project_name=root_path.name,
|
|
65
|
+
context_message=f"Changes since last scan ({last_update})",
|
|
66
|
+
diff_content=diff_content,
|
|
67
|
+
instruction=message
|
|
68
|
+
)
|
|
69
|
+
except Exception:
|
|
70
|
+
# Fallback if template fails
|
|
71
|
+
formatted_diff = f"<diff>\n{diff_content}\n</diff>"
|
|
72
|
+
|
|
73
|
+
# 4. Output
|
|
74
|
+
console.print(f"[bold green]✔ Changes Detected![/bold green] ({len(formatted_diff)} chars)")
|
|
75
|
+
|
|
76
|
+
if copy:
|
|
77
|
+
pyperclip.copy(formatted_diff)
|
|
78
|
+
console.print("[dim]📋 Copied to clipboard[/dim]")
|
|
79
|
+
|
|
80
|
+
if save:
|
|
81
|
+
out_path = root_path / ".codigest" / "changes.diff"
|
|
82
|
+
out_path.parent.mkdir(exist_ok=True)
|
|
83
|
+
out_path.write_text(formatted_diff, encoding="utf-8")
|
|
84
|
+
console.print(f"[dim]💾 Saved to {out_path}[/dim]")
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
import typer
|
|
2
|
+
import pyperclip
|
|
3
|
+
from pathlib import Path
|
|
4
|
+
from rich.console import Console
|
|
5
|
+
from rich.progress import Progress, SpinnerColumn, TextColumn
|
|
6
|
+
|
|
7
|
+
from ..core import scanner, structure, prompts, semdiff, tags, tokenizer
|
|
8
|
+
|
|
9
|
+
# Reuse config loader
|
|
10
|
+
from .scan import _load_config_filters
|
|
11
|
+
|
|
12
|
+
app = typer.Typer()
|
|
13
|
+
console = Console()
|
|
14
|
+
|
|
15
|
+
@app.callback(invoke_without_command=True)
|
|
16
|
+
def handle(
|
|
17
|
+
target: Path = typer.Argument(Path.cwd(), help="Target directory"),
|
|
18
|
+
copy: bool = typer.Option(True, help="Auto-copy to clipboard"),
|
|
19
|
+
save: bool = typer.Option(True, help="Save to .codigest/digest.xml"),
|
|
20
|
+
message: str = typer.Option("", "--message", "-m", help="Add specific instruction"),
|
|
21
|
+
):
|
|
22
|
+
"""
|
|
23
|
+
[Architectural View] Summarizes the codebase structure (Classes/Functions only).
|
|
24
|
+
"""
|
|
25
|
+
root_path = target.resolve()
|
|
26
|
+
|
|
27
|
+
prompt_engine = prompts.get_engine(root_path)
|
|
28
|
+
extensions, extra_ignores = _load_config_filters(root_path)
|
|
29
|
+
|
|
30
|
+
with Progress(
|
|
31
|
+
SpinnerColumn(),
|
|
32
|
+
TextColumn("[bold blue]Digesting Architecture...[/bold blue]"),
|
|
33
|
+
transient=True,
|
|
34
|
+
console=console
|
|
35
|
+
) as progress:
|
|
36
|
+
|
|
37
|
+
task = progress.add_task("digest", total=None)
|
|
38
|
+
|
|
39
|
+
files = scanner.scan_project(root_path, extensions, extra_ignores)
|
|
40
|
+
tree_str = structure.generate_ascii_tree(files, root_path)
|
|
41
|
+
|
|
42
|
+
summary_blocks = []
|
|
43
|
+
for file_path in files:
|
|
44
|
+
# Only summarize Python files via AST
|
|
45
|
+
if file_path.suffix in (".py", ".pyi"):
|
|
46
|
+
try:
|
|
47
|
+
content = file_path.read_text(encoding="utf-8")
|
|
48
|
+
summary = semdiff.summarize(content)
|
|
49
|
+
|
|
50
|
+
if summary:
|
|
51
|
+
rel_path = file_path.relative_to(root_path).as_posix()
|
|
52
|
+
block = tags.xml(t"""
|
|
53
|
+
<file path="{rel_path}">
|
|
54
|
+
{summary}
|
|
55
|
+
</file>
|
|
56
|
+
""")
|
|
57
|
+
summary_blocks.append(block)
|
|
58
|
+
except Exception:
|
|
59
|
+
continue
|
|
60
|
+
|
|
61
|
+
summary_blob = "\n".join(summary_blocks)
|
|
62
|
+
|
|
63
|
+
try:
|
|
64
|
+
digest_content = prompt_engine.render(
|
|
65
|
+
"digest",
|
|
66
|
+
project_name=root_path.name,
|
|
67
|
+
tree_structure=tree_str,
|
|
68
|
+
digest_content=summary_blob,
|
|
69
|
+
instruction=message
|
|
70
|
+
)
|
|
71
|
+
except Exception as e:
|
|
72
|
+
console.print(f"[red]❌ Rendering Failed:[/red] {e}")
|
|
73
|
+
raise typer.Exit(1)
|
|
74
|
+
|
|
75
|
+
progress.update(task, completed=100)
|
|
76
|
+
|
|
77
|
+
token_count = tokenizer.estimate_tokens(digest_content)
|
|
78
|
+
console.print(f"[bold green]✔ Digest Generated![/bold green] ([bold cyan]~{token_count:,} Tokens[/bold cyan])")
|
|
79
|
+
|
|
80
|
+
if copy:
|
|
81
|
+
pyperclip.copy(digest_content)
|
|
82
|
+
console.print("[dim]📋 Copied to clipboard[/dim]")
|
|
83
|
+
|
|
84
|
+
if save:
|
|
85
|
+
out_path = root_path / ".codigest" / "digest.xml"
|
|
86
|
+
out_path.parent.mkdir(exist_ok=True)
|
|
87
|
+
out_path.write_text(digest_content, encoding="utf-8")
|
|
88
|
+
console.print(f"[dim]💾 Saved to {out_path}[/dim]")
|