ts-context-bundle
v0.2.0
Published
Generate deterministic LLM context bundles from TypeScript projects
Readme
ts-context-bundle
Generate deterministic LLM context bundles from TypeScript entrypoints. The CLI emits a single Markdown file that lists included files and embeds each file’s contents in fenced code blocks. Two inclusion strategies are supported:
- closure: walk the static import/export graph (default)
- bundle: use esbuild tree-shaking to get the actual input file set
- both: emit both sections and show differences
Install
npm i -g ts-context-bundle
# or
pnpm add -g ts-context-bundleNode.js >= 20 is required.
Usage
ts-context-bundle src/index.tsts-context-bundle \
src/index.ts \
--entry src/worker.ts \
--no-enhance \
--mode bundle \
--include-bundle-output \
--out context.mdts-context-bundle \
src/index.ts \
--dir src/features \
--mode both \
--depth 2 \
--exclude "**/generated/**" \
--jsonCLI Flags
<entry-file>(required, positional): primary TypeScript entry file.--entry <file>(repeatable): additional TypeScript entry files.--dir <path>(repeatable): directory mode. Every.ts/.tsx(and optional.d.ts) file in the directory becomes an entrypoint, then results are unioned and deduped.--tsconfig <path>: defaults to nearesttsconfig.jsonfound by walking upward fromcwd.--out <file>: defaultcontext.md.--mode closure|bundle|both: defaultclosure.--depth <n>: default2(closure only).--exclude <glob>(repeatable): overrides default excludes.--include-node-modules: include resolved files undernode_modules.--max-file-kb <n>: default512(large files are truncated, not skipped).--max-total-kb <n>: default8192(budget for included content).--include-dts: include.d.tsfiles.--include-bundle-output: append bundled JS (bundle/both modes).--enhance/--no-enhance: run an AI file-list refinement pass viacodexCLI (codex-5.3-spark). Enabled by default whencodexis installed.--quiet: suppress non-error logging.--json: emitcontext.stats.jsonnext to the output file.
Default exclude globs (unless --exclude is provided):
**/node_modules/****/dist/****/build/****/.next/****/coverage/****/*.map**/*.snap
Closure vs Bundle
- closure follows
import/exportdeclarations andimport("...")with string literals. It respectstsconfigbaseUrlandpathsmappings. - bundle runs esbuild with tree-shaking and uses the metafile to determine the actual input files.
Output format
The Markdown bundle:
- A header block with the command, version, mode, depth, tsconfig, and counts.
- A deterministic list of included files.
- Each file’s contents in fenced code blocks, separated by
---.
When enhancement adds files, those files are explicitly labeled as [AI-added context] in the file list and in each file section heading note.
Large files (over --max-file-kb) are truncated to the first 200 lines and last 50 lines with a note. If --max-total-kb is exceeded, the tool stops adding files and records a note about skipped files.
JSON stats
When --json is provided, a context.stats.json file is written next to the output Markdown. It contains:
includedFiles:{ path, bytes, truncated, reasonIfSkipped }skippedFiles:{ path, reason, detail? }totals: counts and included byte totalsmode,tsconfig, and depth metadata
For mode=both, the JSON contains closure and bundle sections plus a diff summary.
Assumptions and behavior notes
- Directory paths are only accepted via
--dir. Passing a directory via<entry-file>or--entryis a usage error. --dirmode treats each matched TypeScript file in that directory tree as an entrypoint.- Explicit entry files are always included, even if they match an exclude glob.
--excludereplaces the default excludes entirely.- Non-TypeScript files are skipped. Only
.ts,.tsx, and optional.d.tsare supported. - Enhancement mode asks Codex to prune noisy files and optionally add missing TypeScript files for debugging context. If
codexCLI is not installed, enhancement is skipped automatically. - Bundle mode stubs common asset imports (for example
.png,.svg, fonts, and media), and those files are not included in the context. - When
--include-bundle-outputis used with multiple entrypoints, outputs are concatenated in a single section with file markers.
Troubleshooting: “Why wasn’t a file included?”
Common reasons:
- The import was unresolved (typo, missing extension, or not covered by
tsconfigpaths). - The file is under
node_modulesand--include-node-moduleswas not set. - The file matched an exclude glob.
- The file was beyond the closure
--depth. - The file extension is not supported.
- The
--max-total-kbbudget was exceeded.
