@shree_vitkar/contextpack
v0.1.17
Published
Pack any repo into clean, token-budgeted context for humans and AI coding agents.
Maintainers
Readme
contextpack
Don't dump the repo into the model. Pack what matters.
A CLI that turns a codebase into a focused, token-budgeted digest—for humans reviewing code and AI agents that need context without the noise.
Install
npx -p @shree_vitkar/contextpack contextpack pack .Or install globally:
npm install -g @shree_vitkar/contextpack
contextpack pack .Windows
The recommended approach on Windows is using npx, which requires no PATH configuration:
npx -p @shree_vitkar/contextpack contextpack pack .To install globally:
npm install -g @shree_vitkar/contextpack
contextpack pack .If contextpack is not recognized after global install:
Find your npm global bin directory:
npm config get prefixThis is usually
%AppData%\npm(e.g.,C:\Users\YourName\AppData\Roaming\npm).Add that path to your User PATH environment variable:
- Press
Win + R, typesysdm.cpl, press Enter - Go to Advanced → Environment Variables
- Under User variables, edit Path and add the npm prefix path
- Press
Restart your terminal (CMD, PowerShell, or Git Bash).
Verify the CLI wrapper exists:
dir "%AppData%\npm\contextpack*"You should see
contextpackandcontextpack.cmd.
Note: The package is scoped
@shree_vitkar/contextpackbut the CLI binary name iscontextpack.
Use with agents (MCP)
contextpack mcp is a stdio MCP server. Agents call pack (digest) and list (budget preview / map, no file bodies) instead of shelling out. Default root is the server process cwd. Absolute paths and .. escapes outside cwd are rejected. Secret redaction is on. Project config (.contextpack.json) is respected the same way as the CLI.
npx -y -p @shree_vitkar/contextpack contextpack mcpClaude Code
claude mcp add contextpack -- npx -y -p @shree_vitkar/contextpack contextpack mcpCursor — .cursor/mcp.json:
{
"mcpServers": {
"contextpack": {
"command": "npx",
"args": ["-y", "-p", "@shree_vitkar/contextpack", "contextpack", "mcp"]
}
}
}Generic mcpServers block (Claude Desktop, VS Code Copilot, Windsurf, Codex, and others that use this shape):
{
"mcpServers": {
"contextpack": {
"command": "npx",
"args": ["-y", "-p", "@shree_vitkar/contextpack", "contextpack", "mcp"]
}
}
}compare stays CLI-only (a human-facing naive-vs-packed table, not something an agent needs in the loop). More patterns: docs/agents.md.
Usage
# Pack current directory to stdout
contextpack pack .
# Budget to ~8k tokens, write to file
contextpack pack ./src --budget 8000 -o context.md
# JSON output for tooling
contextpack pack . --budget 12000 --format json -o context.json
# Skip tests and fixtures
contextpack pack . --ignore 'tests/**' --ignore 'fixtures/**'
# Preview which files would be included (dry-run)
contextpack pack . --list --budget 8000
# Only files changed since main branch
contextpack pack . --since main --budget 8000
# Preview changes from last commit
contextpack pack . --since HEAD~1 --list
# Pack unified diffs of changes since main (cheaper than full files)
contextpack pack . --since main --diff
# Boost files matching a topic (substring on path or content; ranking only)
contextpack pack . --focus auth,jwt --budget 4000
# Preview a topic-ranked pack
contextpack pack . --focus "login session" --list
# Pack only files matching a search (agent workflow)
rg -l 'JWT|auth' -g '*.ts' | contextpack pack . --budget 8000
# Explicit path list from a file (does not also read stdin)
contextpack pack . --paths-from changed.txt --budget 4000 -o context.md
# Preview the selected paths under budget
contextpack pack . --paths-from paths.txt --list
# Keep raw values (trusted local debug / inspect a false positive)
contextpack pack . --no-redact
# Bodies only (skip the digest map and its budget reserve)
contextpack pack . --no-map --budget 4000
# Skip project config for one invocation
contextpack pack . --no-config --budget 4000
# Honest naive-dump vs packed table (chars/4 estimates)
contextpack compare .
contextpack compare ./src --budget 8000Optional project config sets pack defaults so you do not repeat the same flags. Walk from the pack root upward and stop at the first match: .contextpack.json, then contextpack.json. If neither exists, a "contextpack" key in the nearest package.json uses the same schema.
{
"budget": 8000,
"format": "md",
"ignore": ["fixtures/**"],
"focus": ["auth", "jwt"]
}CLI flags always win. --since, --diff, --out, --list, and --paths-from stay on the command line (not config keys). --no-config skips the file.
What it does
- Walks the directory tree, respecting
.gitignoreand optional agent ignore files at the pack root (.cursorignore,.aiignore,.copilotignore) — or, with a piped path list /--paths-from, resolves only an explicit path list (no tree walk) - Filters out noise:
node_modules, lockfiles, binaries, build artifacts, secrets - Optionally filters to only git-changed files with
--since. Combined with a piped list or--paths-from, packs the intersection - With
--diff, packs unified diffs of those changes instead of full file bodies (untracked files stay full content) - Ranks files by signal (README and manifests first, tests last).
--focusboosts files whose path or packed content contains those keywords (substring, not semantic search) — ranking only, not a filter - Fits within your token budget, keeping the highest-value files
- When a file doesn't fully fit, includes a useful prefix (marked as partial) rather than dropping it entirely
- Redacts obvious secret-looking substrings in file bodies and diffs (best-effort;
--no-redactto disable) - Reserves a compact Map of discovered candidates from the budget (included / partial / truncated / skipped), then fits file bodies in what remains.
--no-mapskips the map - Outputs a structured digest (Markdown, JSON, or plain text)
Ignore layers (gitignore syntax), applied in this order:
DEFAULT_IGNORES → .gitignore → .cursorignore → .aiignore → .copilotignore → extra ignores (project config ignore, or CLI --ignore if you passed the flag — CLI replaces config)
Agent ignore files are optional and only read from the pack root when present (not nested per-directory). --include still force-includes matched paths and wins over ignores.
Flags
| Flag | Description |
| --- | --- |
| [path] | Directory to pack (default: .) |
| -b, --budget <n> | Max tokens (~chars/4). Default: 16000. Use 0 for unlimited. |
| -f, --format <fmt> | md (default), json, or plain |
| -o, --out <file> | Write to file instead of stdout |
| -i, --ignore <pat> | Extra ignore pattern (repeatable) |
| --include <pat> | Force-include pattern (repeatable) |
| --max-file-bytes <n> | Skip files larger than N bytes (default: 512KB) |
| -l, --list | Preview which files would be included without dumping contents |
| -s, --since <ref> | Only include files changed since git ref (e.g. main, HEAD~1) |
| --diff | With --since, pack unified diffs of tracked changes instead of full files |
| --paths-from <file> | Pack only paths listed in a file (one per line; - reads stdin). Piped stdin without this flag is the same as -. No tree walk |
| --no-redact | Disable best-effort secret redaction (keep raw values; useful to inspect a false positive locally) |
| --focus <terms> | Boost ranking for files matching keywords (comma/space-separated substring on path or content; repeatable). Ranking only — not a filter, not semantic search |
| --no-map | Omit the digest map and do not reserve map tokens from the budget. --list still previews files |
| --no-config | Skip project config (.contextpack.json / contextpack.json / package.json) |
| -q, --quiet | Suppress stderr summary |
| -V, --version | Print version |
| compare [path] | Naive-dump vs packed table (default budgets: 500, 2000, 0). --budget is repeatable. --ignore / --include / --max-file-bytes apply to pack() only |
| mcp | Stdio MCP server (pack + list tools). Logs to stderr; stdout is protocol-only |
For AI coding agents
contextpack is designed for both humans and AI agents. Before a large refactor or when you need codebase context:
# Get a digest of the codebase structure
contextpack pack . --budget 8000 -o context.md
# Boost files matching a topic (substring on path or content; ranking only)
contextpack pack . --focus auth,jwt --budget 4000 -o context.md
# See how a naive dump compares to packing (chars/4)
contextpack compare .Prefer MCP when the host supports it (see Use with agents (MCP)). The CLI still works when you want a file on disk.
Agent setup
Drop Cursor / Claude integration files into a repo so agents know when and how to run contextpack:
npx -p @shree_vitkar/contextpack contextpack initWrites (create only if missing; --force overwrites):
.cursor/rules/contextpack.mdc— when/how to packskills/contextpack/SKILL.md— skill with the real install/run commands
Add --agents to create or append a short AGENTS.md section.
See docs/agents.md for integration patterns.
GitHub Action (PR digest)
On pull_request, pack only what changed since the base SHA (--since + --diff) and post a short comment. The full digest is a workflow artifact — not a dump of the whole repo.
# .github/workflows/contextpack-pr.yml
name: contextpack PR
on: pull_request
permissions:
contents: read
pull-requests: write
jobs:
pack:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- uses: shreeshailaya/contextpack/.github/actions/pack-pr@masterThis repo runs the same job from .github/workflows/contextpack-pr.yml (local uses: ./.github/actions/pack-pr). Copy the Action directory into another repo if you do not want to reference this one.
Inputs, permissions, and failure modes: docs/github-action.md.
Secrets
Path ignores already skip .env, *.pem, and similar files. Packed contents (full files and unified diffs) also get best-effort redaction of obvious secret-looking substrings: PEM private-key blocks, GitHub / OpenAI / Slack / AWS-access-key prefixes, Bearer tokens, and common api_key= / password= / token= assignments.
This is not a security scanner. Short placeholders (YOUR_API_KEY, changeme) are left alone. The digest summary reports redacted: N when anything was replaced. Use --no-redact when you need the raw text (for example, to inspect a false positive locally). Do not treat a digest as proof that secrets are absent.
--list still has no file bodies, so it does not redact snippets (there are none). Token estimates in --list match a real pack, including redaction.
Token estimates
Token counts are estimates: characters / 4. This is good enough for budgeting and fits most tokenizers within ~20%. It is not a model-specific tokenizer—don't use it for billing or exact context window calculations.
The digest Map uses the same estimate. Its tokens are reserved from --budget before file bodies are selected so the inventory does not silently overflow. totalTokens is still the sum of included file bodies. --no-map turns that reserve off.
Honest numbers
Measured on fixtures/demo-project with npm run benchmark / contextpack compare (chars/4 estimates, not a model tokenizer):
- Naive dump — every text-ish file, no gitignore, no ranking: 8 files, ~1,649 tokens
- Packed — default ignores; budget 500, 2000, or unlimited: 5 files, ~161 tokens (−90%)
The packed tree fits in a 500-token budget, so that 90% is noise filtering (vendor/, build/, lockfile), not truncation. On this repo's own src/, unlimited pack matches a naive dump (already clean); a tight budget then truncates.
Methodology and the full table: docs/benchmark.md. Re-run on this repo with npm run benchmark, or on any directory with contextpack compare ..
Output formats
- md — Markdown digest with summary table, a Map of discovered candidates (included vs left out), and fenced code blocks. Readable by humans, parseable by agents.
- json — Structured payload with
map, file contents, stats, and metadata. For pipelines and tooling. - plain — Simple separators plus the same map. Easy to paste or pipe.
The map is the cheap inventory: every discovered candidate, marked included / partial / truncated / skipped. --list is that same inventory without file bodies. Map tokens are reserved from the budget (chars÷4 of the compact map text) so adding the map does not silently overflow. totalTokens remains file bodies only. If the map itself is larger than the budget, the digest still includes the map and omits bodies.
Philosophy
- Pack what matters. README, manifests, source files. Not lockfiles, not
node_modules, not binaries. - Respect budgets. When space is tight, prioritize high-signal files over test fixtures. When a high-priority file doesn't fully fit, include what does (partial inclusion) rather than losing it entirely.
- Stay honest. Token counts are estimates (
chars / 4). We say so. Partial files are clearly marked. The map is reserved from the budget so orientation stays cheap without pretending bodies still fit. - Work for both audiences. Humans need readable digests. Agents need structured context. Same tool.
Project layout
src/
cli.ts # Commander CLI
index.ts # bin entry
mcp/ # contextpack mcp (stdio MCP server)
init/ # contextpack init (agent drop-in files)
pack/
collect.ts # Walk + gitignore / agent ignores; optional explicit path list
budget.ts # Priority ranking + selection
tokens.ts # Token estimation
naive.ts # Naive dump (benchmark baseline)
compare.ts # Naive vs packed table (CLI compare + benchmark)
format.ts # md | json | plain output
map.ts # Digest map (inventory + budget reserve)
pack.ts # Orchestrator
pathsFrom.ts # --paths-from parse + path safety
redact.ts # Best-effort secret redaction
focus.ts # --focus term parse + substring match
config.ts # .contextpack.json / package.json defaults
ignore/defaults.ts # Built-in ignore patterns
tests/ # Vitest
scripts/
benchmark.ts # Naive dump vs packed budgets
.github/actions/pack-pr/ # Composite Action: PR --since --diff digestDevelopment
git clone https://github.com/shreeshailaya/contextpack.git
cd contextpack
npm install
npm test
npm run build
npm run benchmarkStatus
v0.1.17 — contextpack mcp runs a stdio MCP server with pack and list tools so agents can get a digest without shelling out. Default root is the process cwd; absolute paths and .. escapes are rejected. Redaction and project config match the CLI. compare stays CLI-only.
License
MIT © Shreeshail Vitkar
