codigest 0.4.3__tar.gz → 0.6.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.6.0/.gitattributes +1 -0
- {codigest-0.4.3 → codigest-0.6.0}/CITATION.cff +2 -2
- codigest-0.6.0/PKG-INFO +388 -0
- codigest-0.6.0/README.ko.md +354 -0
- codigest-0.6.0/README.md +362 -0
- codigest-0.6.0/docs/demo/demo.gif +0 -0
- codigest-0.6.0/docs/demo/make_gif.py +134 -0
- {codigest-0.4.3 → codigest-0.6.0}/pyproject.toml +2 -2
- {codigest-0.4.3 → codigest-0.6.0}/server.json +2 -2
- {codigest-0.4.3 → codigest-0.6.0}/src/codigest/commands/diff.py +6 -6
- codigest-0.6.0/src/codigest/commands/mark.py +22 -0
- {codigest-0.4.3 → codigest-0.6.0}/src/codigest/commands/mcp.py +33 -6
- codigest-0.6.0/src/codigest/commands/pack.py +187 -0
- {codigest-0.4.3 → codigest-0.6.0}/src/codigest/commands/scan.py +1 -21
- {codigest-0.4.3 → codigest-0.6.0}/src/codigest/commands/semdiff.py +1 -1
- {codigest-0.4.3 → codigest-0.6.0}/src/codigest/commands/status.py +2 -2
- {codigest-0.4.3 → codigest-0.6.0}/src/codigest/commands/term.py +99 -27
- codigest-0.6.0/src/codigest/core/git_ops.py +28 -0
- {codigest-0.4.3 → codigest-0.6.0}/src/codigest/core/resolver.py +2 -2
- {codigest-0.4.3 → codigest-0.6.0}/src/codigest/core/shadow.py +10 -3
- {codigest-0.4.3 → codigest-0.6.0}/src/codigest/core/structure.py +3 -7
- {codigest-0.4.3 → codigest-0.6.0}/src/codigest/main.py +19 -12
- {codigest-0.4.3 → codigest-0.6.0}/src/codigest/shell/hook.ps1 +27 -34
- codigest-0.6.0/src/codigest/shell/hook.sh +181 -0
- codigest-0.6.0/tests/test_pack.py +52 -0
- codigest-0.6.0/tests/test_shadow.py +14 -0
- codigest-0.6.0/tests/test_structure.py +11 -0
- codigest-0.6.0/tests/test_term_install.py +61 -0
- {codigest-0.4.3 → codigest-0.6.0}/tests/test_termstore.py +10 -0
- {codigest-0.4.3 → codigest-0.6.0}/uv.lock +2 -2
- codigest-0.4.3/PKG-INFO +0 -305
- codigest-0.4.3/README.md +0 -279
- codigest-0.4.3/src/codigest/core/git_ops.py +0 -73
- {codigest-0.4.3 → codigest-0.6.0}/.github/workflows/publish.yml +0 -0
- {codigest-0.4.3 → codigest-0.6.0}/.github/workflows/tests.yml +0 -0
- {codigest-0.4.3 → codigest-0.6.0}/.gitignore +0 -0
- {codigest-0.4.3 → codigest-0.6.0}/.python-version +0 -0
- {codigest-0.4.3 → codigest-0.6.0}/LICENSE +0 -0
- {codigest-0.4.3 → codigest-0.6.0}/src/codigest/__init__.py +0 -0
- {codigest-0.4.3 → codigest-0.6.0}/src/codigest/__main__.py +0 -0
- {codigest-0.4.3 → codigest-0.6.0}/src/codigest/commands/cap.py +0 -0
- {codigest-0.4.3 → codigest-0.6.0}/src/codigest/commands/clean.py +0 -0
- {codigest-0.4.3 → codigest-0.6.0}/src/codigest/commands/digest.py +0 -0
- {codigest-0.4.3 → codigest-0.6.0}/src/codigest/commands/init.py +0 -0
- {codigest-0.4.3 → codigest-0.6.0}/src/codigest/commands/tree.py +0 -0
- {codigest-0.4.3 → codigest-0.6.0}/src/codigest/config.py +0 -0
- {codigest-0.4.3 → codigest-0.6.0}/src/codigest/core/cache.py +0 -0
- {codigest-0.4.3 → codigest-0.6.0}/src/codigest/core/common.py +0 -0
- {codigest-0.4.3 → codigest-0.6.0}/src/codigest/core/output.py +0 -0
- {codigest-0.4.3 → codigest-0.6.0}/src/codigest/core/processor.py +0 -0
- {codigest-0.4.3 → codigest-0.6.0}/src/codigest/core/prompts.py +0 -0
- {codigest-0.4.3 → codigest-0.6.0}/src/codigest/core/redact.py +0 -0
- {codigest-0.4.3 → codigest-0.6.0}/src/codigest/core/runner.py +0 -0
- {codigest-0.4.3 → codigest-0.6.0}/src/codigest/core/scanner.py +0 -0
- {codigest-0.4.3 → codigest-0.6.0}/src/codigest/core/semdiff.py +0 -0
- {codigest-0.4.3 → codigest-0.6.0}/src/codigest/core/shellhist.py +0 -0
- {codigest-0.4.3 → codigest-0.6.0}/src/codigest/core/tags.py +0 -0
- {codigest-0.4.3 → codigest-0.6.0}/src/codigest/core/termstore.py +0 -0
- {codigest-0.4.3 → codigest-0.6.0}/src/codigest/core/tokenizer.py +0 -0
- {codigest-0.4.3 → codigest-0.6.0}/src/codigest/options.py +0 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
*.sh text eol=lf
|
|
@@ -14,8 +14,8 @@ authors:
|
|
|
14
14
|
repository-code: "https://github.com/NaNIsaac/codigest"
|
|
15
15
|
url: "https://pypi.org/project/codigest/"
|
|
16
16
|
license: MIT
|
|
17
|
-
version: 0.
|
|
18
|
-
date-released: "2026-10-
|
|
17
|
+
version: 0.6.0
|
|
18
|
+
date-released: "2026-10-17"
|
|
19
19
|
keywords:
|
|
20
20
|
- LLM
|
|
21
21
|
- developer tools
|
codigest-0.6.0/PKG-INFO
ADDED
|
@@ -0,0 +1,388 @@
|
|
|
1
|
+
Metadata-Version: 2.5
|
|
2
|
+
Name: codigest
|
|
3
|
+
Version: 0.6.0
|
|
4
|
+
Summary: Human-Centered Codebase Context Manager for LLMs
|
|
5
|
+
Project-URL: Homepage, https://github.com/NaNIsaac/codigest
|
|
6
|
+
Project-URL: Repository, https://github.com/NaNIsaac/codigest
|
|
7
|
+
Project-URL: Issues, https://github.com/NaNIsaac/codigest/issues
|
|
8
|
+
Author-email: Isaac Yong <isaacyong@naver.com>
|
|
9
|
+
License: MIT
|
|
10
|
+
License-File: LICENSE
|
|
11
|
+
Classifier: Intended Audience :: Developers
|
|
12
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
13
|
+
Classifier: Operating System :: OS Independent
|
|
14
|
+
Classifier: Programming Language :: Python :: 3
|
|
15
|
+
Classifier: Programming Language :: Python :: 3.15
|
|
16
|
+
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
17
|
+
Classifier: Topic :: Utilities
|
|
18
|
+
Requires-Python: >=3.15.0b1
|
|
19
|
+
Requires-Dist: loguru
|
|
20
|
+
Requires-Dist: pathspec
|
|
21
|
+
Requires-Dist: pyperclip
|
|
22
|
+
Requires-Dist: rich
|
|
23
|
+
Requires-Dist: tomli-w
|
|
24
|
+
Requires-Dist: typer
|
|
25
|
+
Description-Content-Type: text/markdown
|
|
26
|
+
|
|
27
|
+
# Codigest
|
|
28
|
+
|
|
29
|
+
[](https://pypi.org/project/codigest/) [](https://github.com/NaNIsaac/codigest/actions/workflows/tests.yml) [](LICENSE)
|
|
30
|
+
|
|
31
|
+
<!-- mcp-name: io.github.NaNIsaac/codigest -->
|
|
32
|
+
|
|
33
|
+
**Hand an LLM your failing command, the code it points at and your changes, in one paste.**
|
|
34
|
+
|
|
35
|
+
[한국어](README.ko.md)
|
|
36
|
+
|
|
37
|
+
<p align="center">
|
|
38
|
+
<img src="docs/demo/demo.gif" alt="cdg cap runs a failing pytest, then cdg pack bundles the failure, the test file it names and the changed file" width="760">
|
|
39
|
+
</p>
|
|
40
|
+
|
|
41
|
+
## The idea
|
|
42
|
+
|
|
43
|
+
A test fails and you ask an LLM for help. You copy the error, then the test, then the file you
|
|
44
|
+
changed, and the model still asks for one more file.
|
|
45
|
+
|
|
46
|
+
Codigest does the copying. You need two commands:
|
|
47
|
+
|
|
48
|
+
```text
|
|
49
|
+
cdg cap -- pytest runs your command and remembers its output
|
|
50
|
+
cdg pack finds the files that output mentions, adds what you changed,
|
|
51
|
+
and copies all of it to your clipboard
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
Then you paste. That is the whole tool for most days; everything below either sets it up,
|
|
55
|
+
explains it, or is optional.
|
|
56
|
+
|
|
57
|
+
## Install
|
|
58
|
+
|
|
59
|
+
Codigest is a command-line tool. Install it with [uv](https://docs.astral.sh/uv/), which also
|
|
60
|
+
fetches the Python version it needs (3.15) without touching your projects:
|
|
61
|
+
|
|
62
|
+
```bash
|
|
63
|
+
winget install --id astral-sh.uv # Windows (skip if you have uv)
|
|
64
|
+
curl -LsSf https://astral.sh/uv/install.sh | sh # macOS/Linux
|
|
65
|
+
|
|
66
|
+
uv tool install codigest
|
|
67
|
+
uv tool update-shell # then restart your terminal
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
The command is `codigest`, or `cdg` for short.
|
|
71
|
+
If the install fails with a syntax error on `lazy import`, run `uv self update` and try again.
|
|
72
|
+
|
|
73
|
+
## Your first pack
|
|
74
|
+
|
|
75
|
+
Go to a project with a failing test. No setup is needed.
|
|
76
|
+
|
|
77
|
+
**1. Run the test through `cdg cap`.** Put `--` before your command. The output looks exactly as
|
|
78
|
+
it would without `cdg cap`; Codigest just keeps a copy.
|
|
79
|
+
|
|
80
|
+
```bash
|
|
81
|
+
cdg cap -- pytest -q # or npm test, cargo test, go test ./..., make
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
**2. Run `cdg pack`.** It tells you what it picked and why:
|
|
85
|
+
|
|
86
|
+
```console
|
|
87
|
+
$ cdg pack
|
|
88
|
+
Packed ~370 / 30,000 tokens
|
|
89
|
+
failed pytest -q (exit 1, just now)
|
|
90
|
+
changes uncommitted changes (git)
|
|
91
|
+
+ test_prices.py line 5 in failing output
|
|
92
|
+
+ prices.py changed
|
|
93
|
+
📋 Copied pack to clipboard
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
Read it as: the failing command, your uncommitted Git changes, `test_prices.py` because the error
|
|
97
|
+
points at its line 5, and `prices.py` because you edited it.
|
|
98
|
+
|
|
99
|
+
**3. Paste into the chat** and say what you want. You can also put the request in the pack:
|
|
100
|
+
`cdg pack -m "fix the discount calculation"`.
|
|
101
|
+
|
|
102
|
+
<details>
|
|
103
|
+
<summary>What exactly was copied</summary>
|
|
104
|
+
|
|
105
|
+
One XML block: the command with its output, the diff, and each file with line numbers and the
|
|
106
|
+
reason it was included. This is the pack above, unedited apart from the working directory:
|
|
107
|
+
|
|
108
|
+
```xml
|
|
109
|
+
<context_pack project="project">
|
|
110
|
+
<terminal_history>
|
|
111
|
+
<command index="1" command="pytest -q" exit_code="1" cwd="~/project" duration="1.5s" at="2026-10-17T01:58:14+09:00">
|
|
112
|
+
<output>
|
|
113
|
+
F [100%]
|
|
114
|
+
================================= FAILURES ==================================
|
|
115
|
+
_____________________________ test_ten_percent ______________________________
|
|
116
|
+
|
|
117
|
+
def test_ten_percent():
|
|
118
|
+
> assert apply_discount(200, 10) == 180
|
|
119
|
+
E assert -1800 == 180
|
|
120
|
+
E + where -1800 = apply_discount(200, 10)
|
|
121
|
+
|
|
122
|
+
test_prices.py:5: AssertionError
|
|
123
|
+
========================== short test summary info ==========================
|
|
124
|
+
FAILED test_prices.py::test_ten_percent - assert -1800 == 180
|
|
125
|
+
1 failed in 0.11s
|
|
126
|
+
</output>
|
|
127
|
+
</command>
|
|
128
|
+
</terminal_history>
|
|
129
|
+
<changes source="uncommitted changes (git)">
|
|
130
|
+
diff --git a/prices.py b/prices.py
|
|
131
|
+
index 3d691df..428752a 100644
|
|
132
|
+
--- a/prices.py
|
|
133
|
+
+++ b/prices.py
|
|
134
|
+
@@ -1,2 +1,2 @@
|
|
135
|
+
def apply_discount(price, percent):
|
|
136
|
+
- return price * (1 - percent / 100)
|
|
137
|
+
+ return price * (1 - percent)
|
|
138
|
+
</changes>
|
|
139
|
+
<file path="test_prices.py" reason="line 5 in failing output">
|
|
140
|
+
1: from prices import apply_discount
|
|
141
|
+
2:
|
|
142
|
+
3:
|
|
143
|
+
4: def test_ten_percent():
|
|
144
|
+
5: assert apply_discount(200, 10) == 180
|
|
145
|
+
</file>
|
|
146
|
+
<file path="prices.py" reason="changed">
|
|
147
|
+
1: def apply_discount(price, percent):
|
|
148
|
+
2: return price * (1 - percent)
|
|
149
|
+
</file>
|
|
150
|
+
</context_pack>
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
Files that did not fit the budget would be listed in an `<omitted>` block, so the model knows
|
|
154
|
+
what it is not seeing.
|
|
155
|
+
|
|
156
|
+
</details>
|
|
157
|
+
|
|
158
|
+
## Two optional upgrades
|
|
159
|
+
|
|
160
|
+
Once the basic loop works, each of these removes one manual step.
|
|
161
|
+
|
|
162
|
+
**Stop typing `cdg cap`.** Hook your shell once and every command is captured automatically:
|
|
163
|
+
|
|
164
|
+
```bash
|
|
165
|
+
cdg term install # cdg term uninstall to undo
|
|
166
|
+
```
|
|
167
|
+
|
|
168
|
+
**Stop pasting.** Connect your coding agent over MCP and it fetches the pack itself:
|
|
169
|
+
|
|
170
|
+
```bash
|
|
171
|
+
claude mcp add --scope user codigest -- cdg mcp # Claude Code
|
|
172
|
+
```
|
|
173
|
+
|
|
174
|
+
Other clients (Cursor, VS Code, Claude Desktop): add a stdio server with command `cdg` and args
|
|
175
|
+
`["mcp"]`. Details for both are in the [reference](#automatic-capture).
|
|
176
|
+
|
|
177
|
+
## How `pack` decides
|
|
178
|
+
|
|
179
|
+
When a file you expected is missing, or one you didn't expect is there, this is the order `pack`
|
|
180
|
+
fills its token budget (default 30,000):
|
|
181
|
+
|
|
182
|
+
1. Files you name: `cdg pack src/prices.py`.
|
|
183
|
+
2. Files named in the output of the last failed command run in this project:
|
|
184
|
+
`File "x.py", line 7` (Python), `x.py:7` (pytest, gcc, rustc, eslint), `x.ts(7,3)` (tsc).
|
|
185
|
+
Once the same command passes again, that failure is no longer used.
|
|
186
|
+
3. Files you changed: uncommitted and untracked files in Git, or changes since `cdg mark` if you
|
|
187
|
+
set a baseline (see [below](#see-what-changed-since-a-point)).
|
|
188
|
+
4. Tests that import a changed Python file (`test_*.py`, `*_test.py`).
|
|
189
|
+
5. Local Python modules imported by the files above.
|
|
190
|
+
|
|
191
|
+
The failed command and the diff are always included. `.env`, `*.pem`, `*.key` and SSH keys never
|
|
192
|
+
are. Tokens are estimated at four characters each, so the budget is approximate.
|
|
193
|
+
|
|
194
|
+
```bash
|
|
195
|
+
cdg pack -b 8000 # smaller budget
|
|
196
|
+
cdg pack -s > context.xml # print instead of copying
|
|
197
|
+
```
|
|
198
|
+
|
|
199
|
+
## Other things you can hand an LLM
|
|
200
|
+
|
|
201
|
+
`pack` covers the failing-test case. These cover the rest, grouped by what you want to do.
|
|
202
|
+
|
|
203
|
+
### Recall an earlier command
|
|
204
|
+
|
|
205
|
+
Every captured command stays available, not only the last failure:
|
|
206
|
+
|
|
207
|
+
```bash
|
|
208
|
+
cdg term # last command and its output
|
|
209
|
+
cdg term -n 3 # last 3
|
|
210
|
+
cdg term -f # last failed one
|
|
211
|
+
cdg term --here -n 3 # last 3 run in this project
|
|
212
|
+
```
|
|
213
|
+
|
|
214
|
+
### See what changed since a point
|
|
215
|
+
|
|
216
|
+
Set a baseline before you start, then ask for everything since:
|
|
217
|
+
|
|
218
|
+
```bash
|
|
219
|
+
cdg mark # e.g. before a refactor
|
|
220
|
+
# ... work ...
|
|
221
|
+
cdg diff # text diff since the mark
|
|
222
|
+
cdg semdiff # Python only: which functions and classes changed
|
|
223
|
+
```
|
|
224
|
+
|
|
225
|
+
A baseline is a private copy kept in `.codigest/`; your Git history is not touched. Once you set
|
|
226
|
+
one, `pack` also uses it instead of `git diff`.
|
|
227
|
+
|
|
228
|
+
### Give the whole project, or its shape
|
|
229
|
+
|
|
230
|
+
```bash
|
|
231
|
+
cdg scan # every file, as one block (asks first above 30k tokens)
|
|
232
|
+
cdg scan src/app.py -r # one file plus the local files it imports
|
|
233
|
+
cdg digest # Python signatures and docstrings only, much smaller
|
|
234
|
+
cdg tree # just the file tree
|
|
235
|
+
```
|
|
236
|
+
|
|
237
|
+
## Reference
|
|
238
|
+
|
|
239
|
+
- [All commands](#all-commands)
|
|
240
|
+
- [Terminal capture](#terminal-capture)
|
|
241
|
+
- [MCP tools](#mcp-tools)
|
|
242
|
+
- [Configuration](#configuration)
|
|
243
|
+
- [Privacy and safety](#privacy-and-safety)
|
|
244
|
+
- [How it works](#how-it-works)
|
|
245
|
+
- [Development](#development)
|
|
246
|
+
|
|
247
|
+
### All commands
|
|
248
|
+
|
|
249
|
+
Every command that produces context copies it to the clipboard. `-s` / `--stdout` prints it
|
|
250
|
+
instead, `--no-copy` skips the clipboard, and `-m` / `--message` adds an instruction.
|
|
251
|
+
|
|
252
|
+
| Command | What it gives you | Writes to your project |
|
|
253
|
+
| --- | --- | --- |
|
|
254
|
+
| `pack` | Last failure, the files it names, your changes | nothing |
|
|
255
|
+
| `cap` | Runs a command and keeps its output | nothing |
|
|
256
|
+
| `term` | Recent captured commands with output | nothing |
|
|
257
|
+
| `mark` | Sets the baseline | `.codigest/` |
|
|
258
|
+
| `diff` | Text diff since the baseline | `.codigest/changes.diff` |
|
|
259
|
+
| `semdiff` | Function and class level changes since the baseline (Python) | `.codigest/semdiff.txt` |
|
|
260
|
+
| `scan` | The whole project, or chosen paths, as one block | `.codigest/snapshot.txt` |
|
|
261
|
+
| `digest` | Signatures and docstrings, no bodies (Python) | `.codigest/digest.txt` |
|
|
262
|
+
| `tree` | Project tree | nothing |
|
|
263
|
+
| `status` | Baseline age, pending changes, generated files | nothing |
|
|
264
|
+
| `init` | Config file and baseline; only needed to change [file filters](#configuration) | `.codigest/`, `.gitignore` |
|
|
265
|
+
| `clean` | Deletes `.codigest/` (asks first, `-y` to skip) | removes `.codigest/` |
|
|
266
|
+
| `mcp` | MCP server for agents | nothing |
|
|
267
|
+
|
|
268
|
+
More options: `scan -l` adds line numbers, `scan -a` ignores the config filters, `scan -y` skips
|
|
269
|
+
the confirmation (CI). `-r` / `--resolve` on `scan`, `diff`, `semdiff` and `digest` also pulls in
|
|
270
|
+
local files imported by the targets. `cdg <command> --help` lists everything.
|
|
271
|
+
|
|
272
|
+
### Terminal capture
|
|
273
|
+
|
|
274
|
+
`cdg cap` streams the command's output live and records the command line, combined
|
|
275
|
+
stdout/stderr, exit code and working directory. Captures from all projects share one store on
|
|
276
|
+
your machine, so `cap` and `term` work in any directory.
|
|
277
|
+
|
|
278
|
+
```bash
|
|
279
|
+
cdg cap "npm run build | tail -20" # quote pipelines
|
|
280
|
+
cdg term -i 2 # only the command from 2 runs ago
|
|
281
|
+
cdg term path # where captures are stored (override with CODIGEST_HOME)
|
|
282
|
+
cdg term clear # delete all captures
|
|
283
|
+
```
|
|
284
|
+
|
|
285
|
+
Commands not run through `cap` are read from the native shell history (PowerShell, bash, zsh,
|
|
286
|
+
fish), without their output.
|
|
287
|
+
|
|
288
|
+
#### Automatic capture
|
|
289
|
+
|
|
290
|
+
`cdg term install` edits your PowerShell profile, `~/.bashrc` and `~/.zshrc` for whichever of
|
|
291
|
+
these shells is installed; choose with `--shell powershell|bash|zsh|all`. On Windows, Git Bash
|
|
292
|
+
counts as bash. Commands still run in your current session (`cd`, variables and functions work
|
|
293
|
+
normally) and appear in your history as typed. Editors, pagers, REPLs and `ssh` are skipped.
|
|
294
|
+
|
|
295
|
+
- Skip one command: start the line with a space.
|
|
296
|
+
- Skip more programs: `$env:CODIGEST_CAP_SKIP = '^\s*(myrepl|mytui)\b'` (bash/zsh:
|
|
297
|
+
`export CODIGEST_CAP_SKIP='^(myrepl|mytui)( |$)'`, an extended regex).
|
|
298
|
+
- Disable for a session: `$env:CODIGEST_NOCAP = 1` (bash/zsh: `export CODIGEST_NOCAP=1`).
|
|
299
|
+
- Remove the hooks: `cdg term uninstall`.
|
|
300
|
+
|
|
301
|
+
Limitations:
|
|
302
|
+
|
|
303
|
+
- Captured programs write to a pipe, not a TTY, so some lose colors or progress bars.
|
|
304
|
+
- In bash (4+) and zsh, multi-line commands (loops typed over several lines, heredocs),
|
|
305
|
+
background jobs (`cmd &`) and lines using `!` history expansion are not captured; they run
|
|
306
|
+
normally. In bash, neither are lines that start with a subshell `( ... )`.
|
|
307
|
+
- In bash the hook uses the DEBUG trap and keeps one set before the first prompt (starship,
|
|
308
|
+
bash-preexec); a DEBUG trap set later replaces it.
|
|
309
|
+
|
|
310
|
+
### MCP tools
|
|
311
|
+
|
|
312
|
+
| Tool | Returns |
|
|
313
|
+
| --- | --- |
|
|
314
|
+
| `pack` | Last failure, the files it names, changes and their imports, cut to a budget (`targets`, `budget`, `message`) |
|
|
315
|
+
| `terminal_history` | Recent commands with output and exit code (`count`, `failed`, `here`: only this project, default on) |
|
|
316
|
+
| `scan` | Project snapshot (`targets`, `resolve`, `message`) |
|
|
317
|
+
| `diff` / `semdiff` | Text / structural changes since the baseline |
|
|
318
|
+
| `digest` | Signatures and docstrings only |
|
|
319
|
+
| `tree` | Directory tree |
|
|
320
|
+
|
|
321
|
+
The tools return the same text the CLI prints. None of them moves the baseline, and paths
|
|
322
|
+
outside the project the server was started in are refused.
|
|
323
|
+
|
|
324
|
+
### Configuration
|
|
325
|
+
|
|
326
|
+
`cdg init` writes `.codigest/config.toml`. The `[filter]` section controls which files every
|
|
327
|
+
command considers:
|
|
328
|
+
|
|
329
|
+
```toml
|
|
330
|
+
[filter]
|
|
331
|
+
# Only these extensions (omit to include every non-ignored file)
|
|
332
|
+
extensions = [".py", ".ts", ".rs", ".md", ".json"]
|
|
333
|
+
|
|
334
|
+
# Extra exclusions, in .gitignore syntax (.gitignore itself is always honored)
|
|
335
|
+
exclude_patterns = [
|
|
336
|
+
"*.lock",
|
|
337
|
+
"tests/data/",
|
|
338
|
+
"legacy_code/"
|
|
339
|
+
]
|
|
340
|
+
```
|
|
341
|
+
|
|
342
|
+
`.git/`, `.codigest/`, virtual environments, `node_modules/` and `__pycache__/` are always
|
|
343
|
+
skipped.
|
|
344
|
+
|
|
345
|
+
### Privacy and safety
|
|
346
|
+
|
|
347
|
+
- **Secrets in captures.** Known secret shapes (API keys, tokens, `password=...`, private keys,
|
|
348
|
+
URL credentials) are masked before a capture is written to disk. Output of credential commands
|
|
349
|
+
(`env`, `printenv`, `gh auth token`, `aws configure`, ...) is never stored. This catches common
|
|
350
|
+
formats, not every possible secret.
|
|
351
|
+
- **Secret files.** `pack` never includes `.env*`, `*.pem`, `*.key`, `*.p12`, `*.pfx` or SSH
|
|
352
|
+
private keys, and lists them as omitted instead.
|
|
353
|
+
- **Your project.** No command changes your source files. Commands that save output, and the
|
|
354
|
+
baseline, live only inside `.codigest/`, which `init` adds to `.gitignore`. `pack` without a
|
|
355
|
+
baseline creates nothing at all.
|
|
356
|
+
- **Where captures live.** `cdg term path` shows the file. On macOS and Linux it is readable only
|
|
357
|
+
by you. `cdg term clear` deletes it.
|
|
358
|
+
- **Nothing leaves your machine.** Codigest makes no network requests. Context goes where you
|
|
359
|
+
paste it, or to the MCP client you connected.
|
|
360
|
+
|
|
361
|
+
### How it works
|
|
362
|
+
|
|
363
|
+
- **Baseline.** A Git repository at `.codigest/anchor/.shadow_git`, separate from your project's
|
|
364
|
+
repository. The directory is not named `.git` so editors don't mistake it for yours. `mark` and
|
|
365
|
+
`init` commit the current state to it; `diff`, `semdiff`, `status` and `pack` compare the
|
|
366
|
+
working tree against it.
|
|
367
|
+
- **Captures.** One newline-delimited JSON file holds the last 200 commands; each output is capped
|
|
368
|
+
at 64 KB, keeping the head and tail.
|
|
369
|
+
- **Output.** File contents are XML-escaped inside `<file>` blocks, written flush-left so no stray
|
|
370
|
+
indentation reaches the prompt.
|
|
371
|
+
- **MCP.** The server is a small JSON-RPC loop over stdio. Each tool runs the regular CLI with
|
|
372
|
+
`-s --no-copy`, so an agent sees exactly what you would paste.
|
|
373
|
+
|
|
374
|
+
### Development
|
|
375
|
+
|
|
376
|
+
```bash
|
|
377
|
+
git clone https://github.com/NaNIsaac/codigest
|
|
378
|
+
cd codigest
|
|
379
|
+
uv run cdg --help # run from the checkout
|
|
380
|
+
uv run --with pytest pytest -q # tests
|
|
381
|
+
```
|
|
382
|
+
|
|
383
|
+
The demo GIF is rendered from recorded output by
|
|
384
|
+
[`docs/demo/make_gif.py`](docs/demo/make_gif.py); its docstring explains how to record a new one.
|
|
385
|
+
|
|
386
|
+
## License
|
|
387
|
+
|
|
388
|
+
MIT. See [LICENSE](LICENSE).
|