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.0.tar.gz (52.9 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.0-py3-none-any.whl (16.1 kB view details)

Uploaded Python 3

File details

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

File metadata

  • Download URL: mdmirror-0.2.0.tar.gz
  • Upload date:
  • Size: 52.9 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.0.tar.gz
Algorithm Hash digest
SHA256 b888ab7b5e6c40f62d25be4ee482c6476ee1f0e62b78b39e97a0013991ab8efc
MD5 a54c7eca095a976f98b8cf2e06b12b62
BLAKE2b-256 34ed40289b1fcd5d1f8465da948fe2f56fd3d7155bfe642d580ce06273c7fcbf

See more details on using hashes here.

Provenance

The following attestation bundles were made for mdmirror-0.2.0.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.0-py3-none-any.whl.

File metadata

  • Download URL: mdmirror-0.2.0-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.0-py3-none-any.whl
Algorithm Hash digest
SHA256 ba32e1fe03932bdf9bd79de14f2f52bfab6fce505a96996df6ddc02bb269c5a0
MD5 f5f0447f968e0aed43ba22ff05980dd8
BLAKE2b-256 821c2a36adf93330f3fa8e6e717ee32b5e74c646df564cc19dfb6c8d63ff3b6a

See more details on using hashes here.

Provenance

The following attestation bundles were made for mdmirror-0.2.0-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