
Codigest
io.github.NaNIsaacPublished by GitHub account NaNIsaacv0.13.0Updated Oct 29, 2026
Terminal output, project snapshots and semantic diffs as LLM-ready context
Overview
Codigest packages chosen code context — project snapshots, digests, diffs and failed terminal commands — as text an AI assistant can read.
- What you can do
- Bundle the whole project, chosen files or folders, or locally imported files as one snapshot with a file tree
- Summarize signatures and docstrings only, or show the directory tree at a chosen depth
- Compare against a baseline you set, as a text diff or a function-level structural diff
- Collect a failing command's output together with the files its errors point at, within a token budget
- Report recent captured terminal commands with their output and exit code
- When to use it
- Useful when a coding assistant needs the right slice of a repository rather than a pasted error or the whole codebase, for example debugging a failing test or reviewing a refactor. It only prepares context; it does not call a model or suggest fixes.
- Requirements
- Runs locally as a stdio server started with the cdg mcp command, from a prebuilt binary or the PyPI package codigest installed with uv (Python 3.15). No accounts, API keys or network access are needed. Terminal capture requires running cdg term install to hook the shell.
Installation
In SourceWeft
- Open Codigest in the dashboard and add it to a workspace.
- Enable the server for the chats that should use its tools.
Desktop only via STDIO. STDIO servers start a local process, so they need the SourceWeft desktop host.
Other MCP clients
Follow the launch instructions in the repository.
README
Codigest
Share the code context you choose with an AI: your project, a few files, what changed, or the command that failed.
Documentation: nanisaac.github.io/codigest (installation, guides, command reference). 한국어
[Codigest MCP — MCPRush security rating]
Automated release-specific security scan (A–F), not an independent security certification.
How ratings work.
Suppose a test fails and you want a coding assistant to help. Pasting the error alone may omit the function under test; pasting the whole repository buries the problem in unrelated files.
Codigest lets you choose what context to send. From the terminal, it can collect selected files, their local imports, recent changes, or a failed command and the files mentioned in its output. It packages the selection as text for you to inspect and paste into ChatGPT, Claude, or another tool. It does not choose a fix or call a model on its own.
What it does
- Bundles code you pick. The whole project, chosen files and folders, or the local files they import (Python, JS/TS), as one block with the file tree.
- Shows what changed. Text or function-level diffs since a baseline you set, without touching your Git history.
- Brings in terminal output. It records commands you run and can hand over a failing one together with the files its error points at.
- Says what it included. Every bundle reports its size, and
packgives the reason for each file and names the ones it left out. - Filters common secrets. It excludes
.envfiles and known key patterns and attempts to mask tokens in code or output. Review a bundle before sharing it; automated filtering cannot guarantee that every sensitive value is caught. - Works with agents. Claude Code, Cursor and other MCP clients can request the same output.
Codigest does not call any AI model; it only prepares what you send to one. Everything runs on your machine.
[cdg cap runs a failing pytest, then cdg pack bundles the failure, the test file it names and the changed file]
One of the workflows below: a test fails, and one command collects what the model needs.
Install
Prebuilt binary, no Python needed. Windows (cmd or PowerShell):
Linux, macOS and Termux:
This installs cdg to %LOCALAPPDATA%\Programs\codigest (added to your user PATH) on Windows,
~/.local/bin on Linux and macOS, and $PREFIX/bin in Termux. Run the same line again to update.
CDG_VERSION=0.12.1 pins a version and CDG_INSTALL_DIR=... picks the folder (then PATH is left
alone). Supported: Windows x64, Linux x64 and ARM64, macOS Intel and Apple Silicon, Android ARM64
(Termux; the tests also run inside Termux in CI). Archives for download by hand are on the
releases page. No setup is needed in your projects.
Both scripts check the archive against the SHA-256 GitHub records for it. On Linux and macOS,
install.sh will not replace a cdg from the Python package in the same folder unless
CDG_FORCE=1 is set.
Python package
The same commands are on PyPI as codigest. Install it with uv, which
also fetches the Python version it needs (3.15) and keeps it apart from your projects:
The command is codigest, or cdg for short. Both installs provide a command called cdg, so keep
only one of them on PATH. If the install fails with a syntax error on lazy import, run
uv self update and try again.
Next, cdg term install hooks your shell so the output of every command is kept for cdg pack and
cdg term. It is off until you run it; see Terminal capture.
On Windows, PowerShell's help codigest is a separate command from codigest --help.
For optional native Get-Help integration without automatic command capture:
This adds a small forwarding function to your PowerShell profile; other help commands are
unchanged. The CLI's own full command reference is still available via cdg --help.
In a terminal, every command below copies its result to the clipboard. Add -s to also print it,
-o FILE to also write it to a file, --no-copy to leave the clipboard alone, and -m "..." to
put your question or instruction in it. When the output goes to a pipe or a file instead
(cdg scan > ctx.xml, cdg digest | less, a script, a coding agent's shell), it is printed and
the clipboard is left alone; add --copy to copy it anyway. Over SSH the copy goes to the clipboard of the machine you
type on (OSC 52), not the remote one; see output options.
1. Share your project with an AI chat
Run scan in your project and paste:
The clipboard now holds the file tree and every file, honoring .gitignore:
Large projects ask before copying (above 30k tokens or 100 files). For those, share less, as in the next section.
2. Share only part of it, or what changed
The examples from here on are the same project a little later: prices.py has grown a Cart
class, and an old MATLAB version sits in legacy/.
digest is the overview to start a conversation with. It lists every function, class and
top-level variable of Python files, and the functions and %% sections of MATLAB files, in the
order they appear, with the line they start on and the first line of their docstring (or, in
MATLAB, of their help comment). Class attributes and dataclass fields are listed with their
values, shortened when long:
A model that has seen this can ask for exactly what it needs ("show me Cart.total"), and
cdg scan prices.py:16-19 gives it just that method, numbered the same way:
tree -L keeps a large or vendored folder from flooding the output:
To share what changed while you work, set a baseline first:
A baseline is a private copy kept in .codigest/; your Git history is not touched.
3. Hand over a failing command
Run the command through cdg cap. The output looks exactly as it would without it; Codigest
keeps a copy. Then ask for a pack:
Read it as: the failing command, your uncommitted Git changes, test_prices.py because the error
points at its line 5, and prices.py because you edited it.
What exactly was copied
Files that did not fit the budget would be listed in an <omitted> block, so the model knows
what it is not seeing.
How pack decides
Plain cdg pack fills its token budget (default 30,000) in this order:
- Files named in the output of the last failed command run in this project in the past hour:
File "x.py", line 7(Python),x.py:7(pytest, ruff, gcc, rustc, eslint),x.ts(7,3)(tsc). Once the same command passes again, that failure is no longer used. A file that is only named in the output, not changed by you, comes as an excerpt: ten lines around each place the output points at, marked with alines="40-60"attribute. Short files come whole. - The project functions and classes that the failing Python tests call, whole, with reason
called from failing test .... A traceback that ends in an assertion names only the test; this brings the code under test even when the bug is already committed and nothing shows in a diff. - Files you changed: uncommitted and untracked files in Git, or changes since
cdg mark. A long changed file comes as the parts its diff hunks touch (the diff itself is in the pack already). - Tests that import those files (
test_*.py,*_test.py,*.test.ts,*.spec.js, ...). - Project files they import: Python imports, and relative imports in JS/TS (
./x,./x.jsforx.ts,./dirfordir/index.ts).
When you name files, you get only those files. --with adds automatic sources back:
The failed command and the diff are always included when their source is on. A long command
output keeps its first 80 and last 40 lines (the first failures and the summary); cdg term -f
shows all of it. Tokens are estimated
at four characters each, so the budget is approximate.
Making it smoother
cdg term install hooks your shell so every command is captured without typing cdg cap
(cdg term uninstall removes it). cdg term shows what was captured; see
Terminal capture.
4. Let an agent fetch it
Connect your coding agent over MCP and it requests context itself instead of asking you to paste:
Other clients (Cursor, VS Code, Claude Desktop): add a stdio server with command cdg and args
["mcp"]. The tools are listed under MCP tools.
An agent that can run shell commands needs no setup at all. Its shell is not a terminal, so cdg
prints the result for it and never touches your clipboard. A way of working that suits agents:
The code in every block is exactly as written in the file (->, <, & are not escaped), so
code copied out of it can be pasted back. A large scan with nobody to answer the size question
stops with a hint instead of waiting; -y takes it all.
Reference
- All commands
- Terminal capture
- MCP tools
- Configuration
- Privacy and safety
- Upgrading from 0.9
- How it works
- Development
All commands
cdg --help lists them in the same groups.
Shared options: -s / --stdout also prints the result (status messages go to stderr; on by
default when piped), --copy / --no-copy overrides the clipboard default (copy in a terminal,
not when piped), -o FILE also writes it to a file, -m / --message adds an
instruction.
scan -l adds line numbers, scan -a ignores the config filters, scan -y skips the
confirmation (CI). -r / --resolve on scan, diff, semdiff and digest also pulls in
local files imported by the targets. scan and term take --format markdown|json for chats that
render Markdown or for scripts (XML is the default). --preset NAME on any command fills in options
saved under [presets.<command>.NAME] in .codigest/config.toml or your user config; options typed
after it win. cdg <command> --help lists everything.
Terminal capture
cdg cap streams the command's output live and records the command line, combined
stdout/stderr, exit code and working directory. cdg term --context also includes the
hostname at capture time and the shell name. The PC name is opt-in because it may be
sensitive; older captures have no hostname, and cdg term still copies without it.
Captures from all projects share one store on
your machine, so cap and term work in any directory.
Commands not run through cap are read from the native shell history (PowerShell, bash, zsh,
fish), without their output.
Automatic capture
cdg term install edits your PowerShell profile, ~/.bashrc and ~/.zshrc for whichever of
these shells is installed; choose with --shell powershell|bash|zsh|all. On Windows, Git Bash
counts as bash. Commands still run in your current session (cd, variables and functions work
normally) and appear in your history as typed. Programs that need a real terminal are skipped: editors, pagers, ssh, full-screen tools (tmux, zellij, herdr, k9s, yazi, ...), docker/podman/kubectl with -it, npm/pnpm/yarn/bun init or create, npx create-*, pip uninstall, gh auth login, az login, gcloud auth login and gcloud init, aws configure, ssh-keygen, sudo, and database shells (psql, mysql, sqlite3, ...). A prompt that does not end its line stays invisible in the capture pipe until the next newline, so the command would look stuck.
- Skip one command: start the line with a space.
- Skip more programs:
$env:CODIGEST_CAP_SKIP = '^\s*(myrepl|mytui)\b'(bash/zsh:export CODIGEST_CAP_SKIP='^(myrepl|mytui)( |$)', an extended regex). - Disable for a session:
$env:CODIGEST_NOCAP = 1(bash/zsh:export CODIGEST_NOCAP=1). - Remove the hooks:
cdg term uninstall. Each startup file gets back the exact bytes it had before install (line endings, BOM, final newline); one that install created is deleted with any folder made for it, as are the hook copies in the data folder. Captured commands stay untilcdg term clear.
Programs that run other commands
A program that runs a command line for you, such as hf from
hanfix (it re-runs the previous command typed with the Korean
layout on), would otherwise be captured as a whole, and the command it runs would get the capture
pipe instead of the terminal. Such a program can work with the hook in two steps:
- Add its command names to
CODIGEST_RUNNERSwhen it loads; the hook does not capture a line that starts with one of them. Append, so the order in which the startup file loads it and codigest does not matter:- PowerShell:
$global:CODIGEST_RUNNERS += 'hf' - bash/zsh:
CODIGEST_RUNNERS="${CODIGEST_RUNNERS-} hf"(a shell variable, space-separated)
- PowerShell:
- Run each command line through
__cdg_runwhen it is defined, looked up when the line runs. It applies the hook's own rules to that line: a program that needs the terminal keeps it, anything else is captured under that line.- PowerShell:
if (Get-Command __cdg_run -CommandType Function -ErrorAction Ignore) { . __cdg_run $line } else { Invoke-Expression $line } - bash/zsh:
if typeset -f __cdg_run >/dev/null; then __cdg_run "$line"; else eval "$line"; fi
- PowerShell:
A program that does not do step 2 can still be listed in CODIGEST_RUNNERS: what it runs then keeps
the terminal and is not captured. thefuck is one:
$global:CODIGEST_RUNNERS += 'fuck' (bash/zsh: CODIGEST_RUNNERS="${CODIGEST_RUNNERS-} fuck").
A program can instead replace the typed line before it runs: when Enter is pressed, the hook calls
each function listed in CODIGEST_REWRITERS with the line, and the first one that claims it gives
the line to run. That line then goes on as if typed: it is the one in the shell history (PSReadLine's
and the engine's in PowerShell), the hook's rules decide whether it is captured, and $? is its own.
hf typed alone can work this way; hf inside a longer line still uses the steps above.
- PowerShell:
$global:CODIGEST_REWRITERS += 'name'. The function gets the line and returns$null(not its line), the new line, or@{ Line = <new>; Confirm = $true }to ask first. - bash/zsh:
CODIGEST_REWRITERS="${CODIGEST_REWRITERS-} name". The function gets the line, setsREPLYto the new line and returns 0, or 2 to ask first, or returns 1 when it is not its line. - When asked, the hook shows the new line with
[Enter / Ctrl+C]: Enter runs it, any other key drops it (nothing runs, nothing is added to history). - A function that fails, returns anything else, or gives a line that does not parse leaves the line as typed, without a message. So does a result that comes after more than 200 ms: it is discarded. This is not a timeout: the hook waits for the function to return, so one that hangs blocks Enter.
- The function should not add to history itself.
- A line typed with a leading space keeps it, so it stays out of the capture.
- Not in a PowerShell remote session, nested prompt or the debugger.
In PowerShell the hook works with another PSConsoleHostReadLine (VS Code's shell integration,
atuin): it calls that one for the line, so it sees the line as typed, and only wraps what it
returns. When one is loaded after the hook, the hook puts itself back on top while the shell
waits for input, also when that one reads the line itself (atuin does); the first line after it
is not captured.
The profile loads a copy of the hook that cdg term install puts in the data folder (shell/ next to the captures), not the file inside the package. After updating codigest, run cdg term install again to refresh it.
Limitations:
- Captured programs write to a pipe, not a TTY, so some lose colors or progress bars.
- In bash (4+) and zsh, multi-line commands (loops typed over several lines, heredocs),
background jobs (
cmd &) and lines using!history expansion are not captured; they run normally. In bash, neither are lines that start with a subshell( ... ). - In bash the hook uses the DEBUG trap and keeps one set before the first prompt (starship, bash-preexec); a DEBUG trap set later replaces it.
- In bash, VS Code's shell integration loaded after the hook stops the capture (#52).
- Long output is bounded: the PowerShell hook keeps the first and last 2,000 lines, and a bash or zsh capture file over 4 MB is read 1 MB from each end. The store then keeps 64 KB.
- In PowerShell, a command counts as failed when its exit code is non-zero or an error reached
the screen; an error hidden with
-ErrorActionis not a failure. - The PowerShell hook does not wrap lines in remote sessions, nested prompts or the debugger.
MCP tools
The tools return the same text the CLI prints. None of them moves the baseline, and paths outside the project the server was started in are refused.
Configuration
cdg init writes .codigest/config.toml. The [filter] section controls which files every
command considers:
.git/, .codigest/, virtual environments, node_modules/ and __pycache__/ are always
skipped.
Privacy and safety
- Credential files.
.env*(except.env.exampleand similar templates),*.pem,*.key,*.p12,*.pfx, keystores,.netrc,.pgpassand SSH private keys are never included by any command.scansays which it withheld,packlists them as omitted, and their hunks in a diff are replaced with a notice. - Tokens in code and diffs. Private keys, JWTs, vendor tokens (OpenAI, GitHub, AWS, Google,
Slack, GitLab, npm, Stripe
sk_/rk_, Hugging Facehf_) and passwords in URLs are masked in everything Codigest outputs. Ordinary code such astoken = get_token()is left alone. - Secrets in captures. On top of that, terminal output is checked before it is written to
disk for
Authorizationheaders and forkey=valueandkey: valuepairs, with a quoted key ("password": "...") or a key that ends in a secret name after_or-(AWS_SECRET_ACCESS_KEY,DB_PASS; alsopassandpwd). The output of credential-printing commands is never stored:env,printenv,gh auth token,aws configureandaws sts get-session-token/assume-role,az account get-access-token,gcloud auth print-access-token,kubectl get secret,kubectl config view --raw,op read,bw get,pass show,vault read,catof.env,.npmrc,.pypirc,.netrc, key files orcredentials.json, and a few more (the full list isDENY_COMMANDSinsrc/codigest/core/redact.py). - These rules catch common formats, not every possible secret.
- Your project. No command changes your source files. Only
markandinitcreate.codigest/, which holds its own.gitignore(*) so it never shows ingit status;initalso adds it to the project's.gitignore. - Where captures live.
cdg term pathshows the file. On macOS and Linux it is readable only by you.cdg term cleardeletes it. - Nothing leaves your machine. Codigest makes no network requests. Context goes where you paste it, or to the MCP client you connected.
Upgrading from 0.9
- Piped or redirected output is printed without
-sand no longer copied; add--copyif a script relied on the clipboard. <file>blocks hold the code verbatim instead of XML-escaped. A custom template in.codigest/prompts.tomlnow receives the blocks unescaped too; only{instruction}is escaped.digestoutput is numbered, in source order, with docstrings, and takes several paths.
Upgrading from 0.8
scan,diff,semdiffanddigestno longer save into.codigest/*.txt; use-o FILE.diff --no-saveand the like are gone.cdg initno longer sets a baseline; runcdg mark.cdg pack FILESpacks only those files; add--with failure,changes,tests,importsfor the previous behavior.- Outputs no longer start with built-in instructions to the model ("You are an expert..."). Put
your own with
-m, or a template in.codigest/prompts.toml.
How it works
- Baseline. A Git repository at
.codigest/anchor/.shadow_git, separate from your project's repository.markcommits the current state to it;diff,semdiff,statusandpackcompare the working tree against it. - Captures. One newline-delimited JSON file holds the last 200 commands; each output is capped at 64 KB, keeping the head and tail.
- Output. File contents go into
<file>blocks verbatim. Only a closing tag of one of Codigest's own blocks inside a file (a literal</file>) is written as</file>, so it cannot end the block early. - MCP. The server is a small JSON-RPC loop over stdio. Each tool runs the regular CLI with
-s --no-copy, so an agent sees exactly what you would paste.
Development
License
MIT. See LICENSE.
Source: README.md at commit d30f3ca
Tools
0Version history
8- v0.13.0LatestOct 29, 2026
- v0.12.2Oct 21, 2026
- v0.12.1Oct 21, 2026
- v0.11.0Oct 21, 2026
- v0.10.0Oct 19, 2026
- v0.9.0Oct 18, 2026
- v0.8.0Oct 16, 2026
- v0.5.0Oct 15, 2026
Score
50% of the applicable checks met
How complete this listing is, computed from the registry entry, the endpoint and public sources. Not a rating of the server and not a statement that it is safe or working today: reachability is a dated check, and no installs or reviews go into the score.
- Reached in the last 30 days25 pts
Keep the endpoint answering the MCP handshake; SourceWeft probes it every 30 days.
- Auth declared10 pts
Declare the credential headers in the registry entry, or keep the endpoint answering the probe so its auth can be classified.
- Tools listed15 pts
Answer tools/list without a credential, or ship a package that starts in a sandbox without one.
- DescriptionRequired15 pts
- Logo10 pts
- Documentation15 pts
- License10 pts