Problem. Feeding a codebase to a chat-based AI model usually means copying files one at a time, losing directory context and repeatedly re-pasting the parts a model has already forgotten.
Baseline complexity. Manual copy-paste scales linearly with file count and offers no automated check against pasting a stray credential.
Solution. Repomix, an open-source Node.js CLI (repomix@1.18.0, MIT licence, 28.4k GitHub stars as of 19 September 2026 [1][2]), walks a directory or a cloned repository, applies a Secretlint scan and the project’s own .gitignore rules, and concatenates the surviving files into one XML, Markdown, JSON or plain-text document with a directory tree and per-file token counts [1][4].
Measured result. Packing Flask’s own Python source (24 files under src/flask/) produced 78,338 tokens by default and 52,951 tokens with the --compress flag, a 32.4% reduction on this tree, attributed by the project to Tree-sitter based signature extraction [3].

Reproduce the result
Commands and captured output
These three commands were run against a fresh shallow clone of pallets/flask (commit d73fa1cd, 2026-09-08 [9]), scoped to src/flask/**/*.py. Repomix itself was resolved as repomix@1.18.0 from the npm registry (dist shasum 7cb8011d...ddb6a43 [8]) through npx --yes, which is a registry install of a published version, not a pinned Git commit of the tool’s own source.
npx --yes repomix@1.18.0 --versionnpx --yes repomix@1.18.0 --style xml --include "src/**/*.py" -o out-src-default.xmlnpx --yes repomix@1.18.0 --style xml --include "src/**/*.py" --compress -o out-src-compressed.xml
$ npx --yes repomix@1.18.0 --version1.18.0exit=0$ npx --yes repomix@1.18.0 --style xml --include 'src/**/*.py' -o out-src-default.xml📦 Repomix v1.18.0No custom config found at repomix.config.ts, repomix.config.mts, repomix.config.cts, repomix.config.js, repomix.config.mjs, repomix.config.cjs, repomix.config.json5, repomix.config.jsonc, repomix.config.json or global config at /opt/data/home/.config/repomix/repomix.config.ts, /opt/data/home/.config/repomix/repomix.config.mts, /opt/data/home/.config/repomix/repomix.config.cts, /opt/data/home/.config/repomix/repomix.config.js, /opt/data/home/.config/repomix/repomix.config.mjs, /opt/data/home/.config/repomix/repomix.config.cjs, /opt/data/home/.config/repomix/repomix.config.json5, /opt/data/home/.config/repomix/repomix.config.jsonc, /opt/data/home/.config/repomix/repomix.config.json.You can add a config file for additional settings. Please check https://github.com/yamadashy/repomix for more information.✔ Packing completed successfully!📈 Top 5 Files by Token Count:──────────────────────────────1. src/flask/app.py (13,820 tokens, 65,471 chars, 17.6%)2. src/flask/sansio/app.py (8,741 tokens, 39,494 chars, 11.2%)3. src/flask/cli.py (8,482 tokens, 36,835 chars, 10.8%)4. src/flask/sansio/scaffold.py (6,668 tokens, 30,632 chars, 8.5%)5. src/flask/sansio/blueprints.py (5,792 tokens, 27,016 chars, 7.4%)🔎 Security Check:──────────────────✔ No suspicious files detected.📊 Pack Summary:──────────────── Total Files: 24 files Total Tokens: 78,338 tokens Total Chars: 351,598 chars Output: out-src-default.xml Security: ✔ No suspicious files detected🎉 All Done!Your repository has been successfully packed.💡 Repomix is now available in your browser! Try it at https://repomix.comexit=0$ npx --yes repomix@1.18.0 --style xml --include 'src/**/*.py' --compress -o out-src-compressed.xml📦 Repomix v1.18.0No custom config found at repomix.config.ts, repomix.config.mts, repomix.config.cts, repomix.config.js, repomix.config.mjs, repomix.config.cjs, repomix.config.json5, repomix.config.jsonc, repomix.config.json or global config at /opt/data/home/.config/repomix/repomix.config.ts, /opt/data/home/.config/repomix/repomix.config.mts, /opt/data/home/.config/repomix/repomix.config.cts, /opt/data/home/.config/repomix/repomix.config.js, /opt/data/home/.config/repomix/repomix.config.mjs, /opt/data/home/.config/repomix/repomix.config.cjs, /opt/data/home/.config/repomix/repomix.config.json5, /opt/data/home/.config/repomix/repomix.config.jsonc, /opt/data/home/.config/repomix/repomix.config.json.You can add a config file for additional settings. Please check https://github.com/yamadashy/repomix for more information.✔ Packing completed successfully!📈 Top 5 Files by Token Count:──────────────────────────────1. src/flask/app.py (9,591 tokens, 41,983 chars, 18.1%)2. src/flask/sansio/app.py (6,553 tokens, 28,008 chars, 12.4%)3. src/flask/sansio/scaffold.py (4,605 tokens, 19,778 chars, 8.7%)4. src/flask/helpers.py (4,393 tokens, 18,534 chars, 8.3%)5. src/flask/cli.py (4,147 tokens, 16,283 chars, 7.8%)🔎 Security Check:──────────────────✔ No suspicious files detected.📊 Pack Summary:──────────────── Total Files: 24 files Total Tokens: 52,951 tokens Total Chars: 222,342 chars Output: out-src-compressed.xml Security: ✔ No suspicious files detected🎉 All Done!Your repository has been successfully packed.💡 Repomix is now available in your browser! Try it at https://repomix.comexit=0
Environment
Node.js v26.5.1, npm 11.17.0, repomix 1.18.0, Debian-based container on Linux 6.12, run on 19 September 2026. The 1.18.0 release sits well past 1.14.1, the version that fixed two advisories disclosed in May 2026: a high-severity argument-injection issue in the --remote-branch option (GHSA-9mm9-rqhj-j5mx, CVE-2026-49987 [6]) and a moderate file-read boundary gap in the MCP server’s attach_packed_output tool (GHSA-hwpp-h97w-2h3j, CVE-2026-49988 [7]). Neither flag was used in this reproduction.
Methodology
The default pack and the --compress pack both target the identical 24-file set, so their token counts are directly comparable. Token and character counts come straight from Repomix’s own end-of-run summary, not from a separate count. No warm-up runs were discarded; each command was executed once.
What the tool actually does
Repomix’s core loop is straightforward: collect candidate files (respecting .gitignore plus a built-in ignore list that already excludes dotfiles like .env), run each surviving file through Secretlint, then serialise everything into a single document with a directory tree, a file-summary header explaining the format to the reading model, and one section per file [1][4]. The output can target XML, Markdown, JSON or plain text; XML is the default and is what the project recommends pasting into Claude or ChatGPT [1].
Two flags matter for anyone who intends to use this against a large repository rather than a toy example. --include and --ignore take comma-separated fast-glob patterns and narrow the file set before anything is read, which keeps a monorepo pack from ballooning past a model’s context window [1]. --compress runs a Tree-sitter parser over supported languages and keeps function and method signatures, class structures, interface and type definitions, while deleting the loop bodies, conditional logic and internal variables that a human reviewer, not an architecture-level reader, usually needs [3].
What compression removes, concretely
Here is one compressed excerpt from the Flask run, taken from src/flask/wrappers.py. The ⋮---- marker is Repomix’s own delimiter for an elided block. This excerpt illustrates the format of the transformation, not the composition of the aggregate 32.4% reduction: most of that reduction came from removed function and method bodies across all 24 files, which this short excerpt does not show in full.
if t.TYPE_CHECKING: # pragma: no cover⋮----class Request(RequestBase)⋮----"""The request object used by default in Flask. Remembers the matched endpoint and view arguments. It is what ends up as :class:`~flask.request`. If you want to replace the request object used you can subclass this and set :attr:`~flask.Flask.request_class` to your subclass.
The secret scan, tested against a real credential shape
Repomix’s Secretlint integration runs before packing, and its first line of defence is simply not reading certain files at all: a .env file containing AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY lines never reached the pack in this test, because .env matches the tool’s built-in ignore patterns regardless of content.
Content-based detection was tested separately, against a file extension that is not auto-ignored. A first attempt used AWS’s own published documentation example key, AKIAIOSFODNN7EXAMPLE, inside config/credentials.json, and Repomix reported no suspicious files. That is unlikely to be a scanner failure: AKIAIOSFODNN7EXAMPLE is a widely used, publicly documented placeholder that appears in tutorials and test fixtures across the internet and is not attached to any real account, and secret scanners commonly allow-list it for that reason. This explanation is a reasonable inference from the observed result and general knowledge of scanner practice, not a claim independently confirmed against Secretlint’s own rule source. Repeating the test with a freshly generated, random AWS-shaped access key and secret in the same file produced a different result:
1 suspicious file(s) detected and excluded from the output:1. config/credentials.json - 1 security issue detectedThese files have been excluded from the output for security reasons.Please review these files for potential sensitive information.
The random key was excluded, and the tool’s own summary flagged the exact file responsible. This distinction, between a well-known example credential and a plausible real one, is worth knowing before relying on the scan as a blanket guarantee: Secretlint is pattern-based, and any pattern-based scanner necessarily allow-lists or misses some strings. It is a useful first filter, not a substitute for reviewing what gets packed before pasting it into a third-party chat interface [4].
Where it stops helping
Repomix’s own Code Compression guide advertises “~70% token reduction” from --compress [3]. The 32.4% measured here on Flask’s Python source is well below that marketed figure, which is not a contradiction: the guide’s number is presumably drawn from codebases with a different mix of comments, docstrings and boilerplate than Flask’s. Compression is explicitly labelled experimental by the project and trades implementation detail for token count [3]; a model asked to review actual logic, not just architecture, needs the uncompressed pack, and the 32.4% figure measured here is specific to Flask’s own source tree. A codebase with more boilerplate and fewer docstrings could compress further; one with dense, comment-light logic could compress less. Neither number generalises without re-measuring on the target repository.
Packing a remote repository with --remote introduces a separate concern the local tests above did not exercise: a cloned repository’s own repomix.config.* file is treated as untrusted code and is not loaded by default, because a JS or TS config is executed, not merely read, and input.processors can run external commands [4]. Passing --remote-trust-config for a repository that has not been reviewed defeats that protection [4]. The two advisories fixed in 1.14.1 targeted a different local surface: an argument-injection path through --remote-branch, and an MCP server tool that could read arbitrary local text files without the same secret scan the ordinary file-read tool applies [6][7]. Both are closed in the 1.18.0 build used here, and neither flag nor MCP surface was exercised in this reproduction, so this test does not independently confirm the fixes; it establishes only that this specific run used a version released after the fix.
When it is actually useful
Repomix targets subscription-based AI tools such as Claude, ChatGPT or Gemini, where the appeal is avoiding per-token API billing while still giving a chat interface the full repository as context rather than a single pasted file [1]. That trade only works while the packed output fits inside the target model’s context window, which is why --include, --ignore and --compress exist as ways to shrink the pack before it is created rather than after [1][3].
Its MCP server mode (repomix --mcp) lets an AI coding assistant call pack_codebase or pack_remote_repository directly instead of a human running the CLI first, and a --sandbox flag restricts the server’s file tools to one workspace directory when the assistant calling it should not be trusted with arbitrary filesystem reads [5]. This article did not exercise MCP mode or sandboxing directly, so no claim is made here about their behaviour beyond what the project documents.
Sources
- Repomix homepage
- Repomix GitHub repository (yamadashy/repomix)
- Repomix Code Compression guide
- Repomix Security guide
- Repomix MCP Server guide
- GHSA-9mm9-rqhj-j5mx / CVE-2026-49987, GitHub Advisory Database
- GHSA-hwpp-h97w-2h3j / CVE-2026-49988, GitHub Advisory Database
- repomix npm registry page (version metadata)
- pallets/flask GitHub repository (test subject)
Leave a comment