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

Uploaded Python 3

File details

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

File metadata

  • Download URL: mdmirror-0.2.1.tar.gz
  • Upload date:
  • Size: 53.2 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.1.tar.gz
Algorithm Hash digest
SHA256 0bca258a3e5082d779d25a7e6937c8d7d24870fcb67af8bd0d84405a59ded2f5
MD5 6ddd5c275f9440831d7c23c97f440217
BLAKE2b-256 e432c8d3604cf657b1e69ba4a84a0c827556a2a8f19aac5bf963267c061ef4ab

See more details on using hashes here.

Provenance

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

File metadata

  • Download URL: mdmirror-0.2.1-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.1-py3-none-any.whl
Algorithm Hash digest
SHA256 e650604ed13f732cde103bc7b5fad87c26ab1e154b84276d85ed13cc86265dba
MD5 9476e46f54f9d265f158cd00894731b0
BLAKE2b-256 93454e8663b4b34ba2834a9dc423851073a8a9d3d4ec3f339f7a2882ba326760

See more details on using hashes here.

Provenance

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