Skip to main content

Mirror a folder tree into Claude-optimal Markdown — single-file bundle by default, ghost-tree mode optional.

Project description

mdmirror

PyPI version CI Python versions License: MIT

Turn any folder into Claude-optimal Markdown context with one command.

mdmirror repo                  # → ./repo.claude.md
mdmirror repo --stdout | pbcopy  # paste-ready clipboard

What it does

  • Recursively walks a folder.
  • Converts office docs / PDFs / HTML via markitdown.
  • Source code (.py, .ts, .go, …) is fenced with the right language tag — no mangling.
  • Each file gets a source: frontmatter so the LLM always knows where a chunk came from.
  • Output is sorted by path: deterministic, diffable across runs.
  • Token count is exact (via tiktoken), not a heuristic.
  • Aggressive default ignore list: .git, node_modules, dist, lockfiles, fonts, images, archives. Honors .gitignore.

Install

pipx install mdmirror     # recommended — isolated env
# or
uv tool install mdmirror
# or
pip install mdmirror

Office formats (docx, xlsx, pptx, pdf, outlook) ship in the base install. For audio transcription via whisper:

pipx install '.[audio]'   # adds whisper, youtube-transcription
pipx install '.[all]'     # everything

Modes

Default — Claude bundle

mdmirror repo                # → ./repo.claude.md
mdmirror repo bundle.md      # → ./bundle.md
mdmirror repo --stdout       # stream to stdout

The bundle is a single .md with a header, a complete file tree, then every file in alphabetical order:

# Context bundle: repo

Source root: `/path/to/repo`

## File tree
```
README.md
src/lib/foo.ts
src/main.py
```

---
source: README.md
bytes: 312
---

# Hello

…

<!-- ────────────────────────────── -->

---
source: src/lib/foo.ts
bytes: 412
---

```ts
// file contents
```

Tree mirror

For when you want one .md per file on disk:

mdmirror repo --tree           # → ./repo_md/
mdmirror repo out --tree       # → ./out/
mdmirror repo out --tree --bundle   # tree AND ./repo.claude.md

Flags

Flag Purpose
--tree Mirror as a folder of .md files instead of one bundle
--bundle With --tree, also emit a bundle at ./<input>.claude.md
--stdout Stream the bundle to stdout (great for | pbcopy)
--overwrite Replace existing output files
--dry-run Report planned actions, write nothing
--workers N Parallel worker processes
--skip-pattern PAT Extra gitignore-style pattern (repeatable)
--include-hidden Don't skip dotfiles / dotdirs
--follow-symlinks Follow symlinks (cycle-safe)
--no-default-ignore Disable the built-in skip list
--no-gitignore Don't honor a root .gitignore
--no-frontmatter Strip the source: YAML header
--no-fence Disable code fencing (everything goes through markitdown)
-q, -v Quiet / verbose logging

Behaviors worth knowing

  • Naming (tree mode): report.docx becomes report.docx.md so a sibling report.pdf doesn't collide. *.md files pass through unchanged.
  • Output safety: refuses to run if the output dir is inside the input dir.
  • Failures don't crash the run. Each failed file is logged and counted; everything else still gets converted.
  • Logs go to stderr. Stdout stays clean for --stdout piping.

Develop

uv pip install -e '.[dev]'
.venv/bin/pytest -q -m "not integration"   # fast (~0.5s)
.venv/bin/pytest -q                         # incl. real markitdown roundtrip

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

mdmirror-0.2.0rc1.tar.gz (53.0 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

mdmirror-0.2.0rc1-py3-none-any.whl (16.1 kB view details)

Uploaded Python 3

File details

Details for the file mdmirror-0.2.0rc1.tar.gz.

File metadata

  • Download URL: mdmirror-0.2.0rc1.tar.gz
  • Upload date:
  • Size: 53.0 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for mdmirror-0.2.0rc1.tar.gz
Algorithm Hash digest
SHA256 422de04d3fd30e51b19d7d29644bc1220060da30dab0e9ed793da15e3f146d8e
MD5 6b58ca981550e5d083ea2d4a4bce1a58
BLAKE2b-256 b4970eb1754a9c25d1166e9a6818948bebf21ed30aa63328b523cde9f4eaaf0f

See more details on using hashes here.

Provenance

The following attestation bundles were made for mdmirror-0.2.0rc1.tar.gz:

Publisher: release.yml on f3r21/mdmirror

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file mdmirror-0.2.0rc1-py3-none-any.whl.

File metadata

  • Download URL: mdmirror-0.2.0rc1-py3-none-any.whl
  • Upload date:
  • Size: 16.1 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for mdmirror-0.2.0rc1-py3-none-any.whl
Algorithm Hash digest
SHA256 20cbbd85279ae2753f4dc17d4f925f7c0283b5f4d10a0fbf4f826a013a7d0610
MD5 102f86a42ebf8e86948a012207cbf7ca
BLAKE2b-256 b5291ee002b9814210f86cfe46e6eaa3586769b7aef0f803606bb25c51ee8f6c

See more details on using hashes here.

Provenance

The following attestation bundles were made for mdmirror-0.2.0rc1-py3-none-any.whl:

Publisher: release.yml on f3r21/mdmirror

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page