Raw data, clear context.

[
[
[

]
]
]

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].

Infographic showing the Repomix packing pipeline from Git repository through Secretlint scan and optional Tree-sitter compression to one XML file, with measured token counts for Flask's own source: 78,338 tokens by default versus 52,951 tokens with --compress, a 32.4 percent reduction. Two side panels show a secret-scan test where a .env file with AWS keys was excluded before scanning and a random AWS-style key in config/credentials.json was flagged and excluded, plus registry identity details for the exact repomix version tested.
Measured on pallets/flask, src/flask/**/*.py, 24 files, repomix 1.18.0. Token counts and the secret-scan result come from Repomix’s own run output.

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.

commands.sh
Shell
npx --yes repomix@1.18.0 --version
npx --yes repomix@1.18.0 --style xml --include "src/**/*.py" -o out-src-default.xml
npx --yes repomix@1.18.0 --style xml --include "src/**/*.py" --compress -o out-src-compressed.xml
Output
$ npx --yes repomix@1.18.0 --version
1.18.0
exit=0
$ npx --yes repomix@1.18.0 --style xml --include 'src/**/*.py' -o out-src-default.xml
📦 Repomix v1.18.0
No 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.com
exit=0
$ npx --yes repomix@1.18.0 --style xml --include 'src/**/*.py' --compress -o out-src-compressed.xml
📦 Repomix v1.18.0
No 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.com
exit=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.

src/flask/wrappers.py (compressed excerpt)
Python
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:

Output
1 suspicious file(s) detected and excluded from the output:
1. config/credentials.json
- 1 security issue detected
These 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

  1. Repomix homepage
  2. Repomix GitHub repository (yamadashy/repomix)
  3. Repomix Code Compression guide
  4. Repomix Security guide
  5. Repomix MCP Server guide
  6. GHSA-9mm9-rqhj-j5mx / CVE-2026-49987, GitHub Advisory Database
  7. GHSA-hwpp-h97w-2h3j / CVE-2026-49988, GitHub Advisory Database
  8. repomix npm registry page (version metadata)
  9. pallets/flask GitHub repository (test subject)

Leave a comment