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.2.tar.gz (53.8 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.2-py3-none-any.whl (16.3 kB view details)

Uploaded Python 3

File details

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

File metadata

  • Download URL: mdmirror-0.2.2.tar.gz
  • Upload date:
  • Size: 53.8 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.2.tar.gz
Algorithm Hash digest
SHA256 ad965c59fcc400c893b99cfcbccc4b8e03bcadd4762ea429da2195494dc07194
MD5 5ad5b9f362d80d7cd8b67a3c68fafcae
BLAKE2b-256 7df4998733e33573ed3c0090a65f540a6ce433c6881b03fa0f6d6814dba1eed5

See more details on using hashes here.

Provenance

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

File metadata

  • Download URL: mdmirror-0.2.2-py3-none-any.whl
  • Upload date:
  • Size: 16.3 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.2-py3-none-any.whl
Algorithm Hash digest
SHA256 563677e95abce8cbb1b30cb477115479d6c54a426a16b53541109e91ecea1670
MD5 a1380e8b7c8bb40b6ed12af593493c46
BLAKE2b-256 4b6f918e0924725ce347de485f6ee39570155b2dd073101b63b10014ab87a0eb

See more details on using hashes here.

Provenance

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