Repository navigation
Expand file tree
/
Copy pathrepo-context-budgets.html
More file actions
146 lines (135 loc) · 8.85 KB
/
Copy pathrepo-context-budgets.html
File metadata and controls
146 lines (135 loc) · 8.85 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Fitting a repo into an LLM's context window, without blowing the budget</title>
<meta name="description" content="Why full-repo dumps waste tokens and leak secrets, and how git-diff-aware, token-budget-aware context packing actually works.">
<link rel="canonical" href="https://dacode-dev.github.io/repo-context-budgets.html">
<meta property="og:type" content="website">
<meta property="og:site_name" content="dacode-dev">
<meta property="og:title" content="Fitting a repo into an LLM context window without blowing the budget">
<meta property="og:description" content="Why full-repo dumps waste tokens and leak secrets, and how git-diff-aware, token-budget-aware context packing works.">
<meta property="og:url" content="https://dacode-dev.github.io/repo-context-budgets.html">
<meta name="twitter:card" content="summary">
<style>
:root {
--bg: #0b0d10;
--card: #14171c;
--text: #e8eaed;
--muted: #9aa0a6;
--accent: #6ee7b7;
--border: #262a30;
--code-bg: #0e1013;
}
@media (prefers-color-scheme: light) {
:root {
--bg: #f7f7f8;
--card: #ffffff;
--text: #16181c;
--muted: #5f6368;
--accent: #059669;
--border: #e2e4e8;
--code-bg: #f1f2f4;
}
}
* { box-sizing: border-box; }
body {
margin: 0;
background: var(--bg);
color: var(--text);
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
display: flex;
justify-content: center;
padding: 48px 20px;
line-height: 1.6;
}
.card {
max-width: 720px;
width: 100%;
background: var(--card);
border: 1px solid var(--border);
border-radius: 16px;
padding: 40px;
}
h1 { font-size: 1.6rem; margin: 0 0 8px; line-height: 1.3; }
h2 { font-size: 1.15rem; margin: 32px 0 12px; }
p.byline { color: var(--muted); margin: 0 0 32px; font-size: 0.9rem; }
p { margin: 0 0 16px; }
code {
font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
background: var(--code-bg);
padding: 2px 6px;
border-radius: 4px;
font-size: 0.88em;
}
pre {
background: var(--code-bg);
border: 1px solid var(--border);
border-radius: 10px;
padding: 16px;
overflow-x: auto;
font-size: 0.85rem;
}
pre code { background: none; padding: 0; }
table {
width: 100%;
border-collapse: collapse;
margin: 16px 0;
font-size: 0.88rem;
}
th, td {
text-align: left;
padding: 8px 10px;
border-bottom: 1px solid var(--border);
}
th { color: var(--muted); font-weight: 600; }
a { color: var(--accent); }
ul { padding-left: 20px; margin: 0 0 16px; }
li { margin-bottom: 6px; }
.back { display: inline-block; margin-top: 32px; font-size: 0.85rem; color: var(--muted); }
.back a { color: var(--muted); }
</style>
</head>
<body>
<div class="card">
<h1>Fitting a repo into an LLM's context window, without blowing the budget</h1>
<p class="byline">A note on context packing for agentic coding workflows.</p>
<p>Every agentic coding tool eventually hits the same wall: the model has a finite context window, and a real repo doesn't fit in it. The usual fix is some variant of "dump the repo to text" — walk the tree, concatenate every file, hand it to the model. That works for a 200-file toy project. It falls apart on anything real, for three concrete reasons.</p>
<h2>Full dumps waste the budget on the wrong files</h2>
<p>If you're asking an agent to review a change, it needs the change — not the entire history of every file that happens to live in the same repo. A full dump spends most of its tokens on code that's completely irrelevant to the task, which pushes genuinely relevant files out of the window or forces truncation that cuts them off mid-file.</p>
<p>The fix is git-diff-awareness: pack only what changed since a ref (a branch, a commit, a tag), not the whole tree. <code>--since main</code> instead of <code>.</code>. This alone usually cuts what you're pasting by 80-95% on a real change, because most of a repo is untouched by any given diff.</p>
<h2>"Fits in the window" and "fits in the budget you actually have" are different numbers</h2>
<p>A model's context window is a hard ceiling, but the number that actually matters is usually smaller — you're sharing that window with the system prompt, the conversation so far, and the model's own output. A tool that just checks "is this under 200k tokens" against the wrong ceiling will still blow your real budget.</p>
<p>Token-budget-awareness means capping to an actual number you specify, and doing it in a way that degrades gracefully — keep the most relevant files (usually: most recently modified) and tell you explicitly what got dropped, rather than silently truncating mid-file or failing outright.</p>
<h2>Repos contain secrets, and copy-paste doesn't know that</h2>
<p>API keys, private key blocks, <code>.env</code> values, cloud credentials — real repos have these, sometimes in files you forgot were tracked, sometimes in test fixtures that were never meant to be secret-free. A tool that blindly dumps file contents into a chat window will happily paste a live credential straight into a third-party LLM provider's logs.</p>
<p>This is a solvable problem with plain pattern matching: AWS-style keys, GitHub/Slack/Stripe/OpenAI/Anthropic token formats, PEM blocks, JWTs, and generic <code>KEY=value</code> env-style secret assignments can all be caught and redacted before anything leaves your machine, on by default rather than as an opt-in flag nobody remembers to set.</p>
<h2>What this looks like in practice</h2>
<table>
<tr><th>Approach</th><th>Diff-aware</th><th>Budget-aware</th><th>Redacts secrets</th></tr>
<tr><td>Manual copy-paste</td><td>Sometimes (if you're careful)</td><td>No</td><td>No</td></tr>
<tr><td>Full-repo dump tools</td><td>Diff appended on top of the full dump, not scope-restricting</td><td>Fail-fast guard (errors over budget, doesn't fit to it)</td><td>No</td></tr>
<tr><td><a href="https://www.npmjs.com/package/llm-ctxpack">llm-ctxpack</a></td><td>Yes — <code>--since</code> restricts the packed file set itself</td><td>Yes — <code>--budget</code> fits to it (real tokenizer, keeps newest files, reports what's dropped)</td><td>Yes, on by default</td></tr>
</table>
<pre><code>npx llm-ctxpack . --since main --budget 20000 -o context.md</code></pre>
<p>That one command: only the files that changed vs <code>main</code>, capped to a 20k-token budget with the most recently modified files prioritized, secrets redacted, written to a Markdown file with a per-file token breakdown you can paste straight into any chat or agent context.</p>
<h2>Surgical scoping and spend visibility</h2>
<p>Beyond diff-scoping, you can shape the packed set with repeatable gitignore-style patterns, and answer “what’s eating my context window?” without leaving the terminal:</p>
<pre><code>npx llm-ctxpack . --include "src/**" --exclude "*.test.js" # only src/, skip tests
npx llm-ctxpack . --top 10 # 10 largest files by tokens (stderr)</code></pre>
<p><code>--include</code>/<code>--exclude</code> use the same pattern engine as your .gitignore, so behavior matches what you already know; excludes win over includes. Redaction now also covers GitLab, npm, Hugging Face, Vercel, Linear, SendGrid and Twilio tokens, OpenAI <code>sk-proj-</code> keys, and passwords embedded in database connection URLs (<code>postgres://user:[REDACTED]@host</code>) — still on by default, still fully local.</p>
<p>It's free, MIT-licensed, works with any tool that takes pasted-in text — Claude, Claude Code, ChatGPT, Cursor, Copilot Chat, or a custom agent's system prompt. Source and docs: <a href="https://github.com/dacode-dev/llm-ctxpack">github.com/dacode-dev/llm-ctxpack</a>.</p>
<p>Just want to check how many tokens a chunk of text is, without a whole repo involved? There's a standalone <a href="https://dacode-dev.github.io/token-counter.html">browser-based token counter</a> — paste text, see the count and how much of each model's context window it uses, nothing uploaded.</p>
<div class="back"><a href="https://dacode-dev.github.io/">← dacode-dev.github.io</a></div>
</div>
<p style="margin-top:30px;padding-top:16px;border-top:1px solid var(--border);color:var(--muted);font-size:.88rem;">
Part of <a href="https://dacode-dev.github.io/">dacode-dev</a>:
<a href="/agent-context-api.html">Agent Context API</a> ·
<a href="https://github.com/dacode-dev/llm-ctxpack">llm-ctxpack</a> ·
<a href="/token-counter.html">Token Counter</a> ·
<a href="https://dacode-dev.github.io/x402-services-directory/">x402 Directory</a> ·
<a href="/what-is-x402.html">What is x402?</a>
</p>
</body>
</html>