On this page

History bundles (.mdh)

Experimental. This format is new, and whether it earns a place outside Wymark is unsettled. It is specified and stable enough to build against, but if you are sending a document with tracked changes to someone who does not use Wymark, export to Word instead.

Wymark can export a document together with its version history as a single file. What the recipient gets is a markdown document plus its past versions — not a special viewing mode and nothing that pops up in their face.

Because the versions arrive as versions, Wymark can show the most recent step as a review: the difference between the last two versions in the bundle is waiting to be accepted or rejected. What that difference is depends on what you chose to send — the changes you have in flight, if that is the scope you exported, or the step since your previous checkpoint if you sent the whole history. Send a bundle whose last two versions are identical and there is simply no review, just a document with its history intact.

A new file extension is the kind of thing that rightly makes people suspicious. So, plainly, before anything else:

A .mdh file is a zip archive of markdown files. That is the entire format.

There is no manifest, no metadata sidecar, no binary section, and nothing Wymark-specific inside it. Rename plan.mdh to plan.zip and double-click it: you get a folder of .md files, one per version, each named with a timestamp. Every one of them opens in any text editor, renders in any markdown viewer, and diffs in git. If Wymark disappeared tomorrow, the contents would still be exactly as readable as the day they were written.

plan.20260725T103000Z.md
plan.20260725T112215Z.md
plan.20260726T090000Z.draft-for-legal.md

The file names are the metadata. A timestamp orders them; an optional label after the timestamp is a version name someone typed. The last one, chronologically, is the current document — the version that lands on disk when the bundle is opened. The rest are its history.

That is the whole design. You can build a valid bundle with zip, and a shell script or an AI agent can produce one without knowing anything about Wymark.

Why the format is this plain, why it is a container at all, and why it is not meant as lock-in is in the design note Why a history bundle is a zip of markdown files.

What a bundle does not carry

A bundle carries versions, faithfully and byte for byte. It does not carry why you made a change, who accepted what, or the sequence of keystrokes between two versions — because Wymark never had that either.

In particular, changes have no author. A diff is the difference between two texts, so it cannot say who typed which part — not you, not the AI agent editing alongside you. There is no field for it, in the bundle or anywhere else in Wymark.

Comments do carry a name, filled in from your OS user account when you write one. Treat it as a label rather than as evidence: it is plain text sitting in the markdown, so anyone can edit it in the raw view, and an agent writing a comment supplies whatever name it likes. Useful for telling voices apart in a thread; not something to lean on if the question is who really said what.

What happens when you open one

Opening a .mdh in Wymark asks where you want the document saved, then:

  • The newest version becomes a real markdown file on disk, byte for byte as the sender had it. This is an ordinary markdown file from that point on.
  • The version before it becomes the review baseline, so the step between those two is on screen as an accept/reject review.
  • The rest of the history is restored as versions, each keeping the timestamp it originally had — so the history reads as the chronology it actually was, not as “imported just now”.

Nothing is stitched into a document you already have. An imported bundle is always a new document, because merging someone else’s history into yours would require guessing which of two divergent chains was correct.

Sending to someone who does not use Wymark

A bundle is only useful to a Wymark user — outside it, it is a zip of files you would have to read in order yourself. So it is the wrong thing to attach to an email to a client, a lawyer, or a colleague who has never heard of this application.

For that, export to Word (.docx). Your changes can be exported as real Word track changes — insertions, deletions, moves and formatting changes as Word’s own revision marks — and your comments as real Word comments with threaded replies. The recipient opens it in Word, sees changes to accept or reject exactly where they expect to, and never learns that the document was markdown.

Word export is itself labelled early access: its shape is settled and it ships, but on some documents it still produces wrong output, so open the exported file in Word before you send it. It is still the better choice for this audience — it is the format they already know, and it asks them to trust nothing new — but it is not a more finished feature than this one, only a more familiar one.

One caveat carries over from the limit described above. Word puts a name on every revision mark, and Wymark has no per-change author to supply, so an export stamps them all with a single one: yours, from your OS user account. If an AI agent wrote half the changes, they still arrive as yours. Comments keep whatever name they carry in the file, which is normally also you — the usual exception being replies written by an agent.

The rule of thumb:

  • Sending to a Wymark user, and the history matters — send a .mdh. They get the versions, not just the outcome.
  • Sending to anyone else — send a .docx with track changes (early access: check it in Word first). It is the format they already know, and it does not ask them to trust an experimental one.
  • Both sides use git — use git. A bundle is a snapshot chain, and git is better at being git.

Images travel inside the bundle

Markdown documents reference images, and a bundle that carried only the text would hand the recipient a document with holes in it. So an export can include them: the scope chooser has an “Include images” checkbox, on by default, showing the file count and total size before you commit. Bundles are capped at 128 MB either way — past that, an attachment has stopped being something anyone can mail, and the export tells you to slim it rather than writing a file no reader will accept.

Inside the archive, images are ordinary zip entries under the same relative paths the document references — rename the bundle to .zip and you see exactly what travels. Readers that predate images simply skip them, which is the ignore rule doing what it was designed for: no manifest announces them, and no existing bundle became invalid.

The rules are short:

  • Only referenced files travel. The images named by the versions you export — never a folder sweep. Web images stay links.
  • References to files elsewhere on your machine are rewritten — in the bundle only, never in your own document — to point into the document’s assets folder, and the files travel there. Your disk layout is not the recipient’s business: a path like /Users/you/Desktop/draft-v2/fig.png says things you may not intend to say, so it never leaves the machine. That applies even when the file is missing — the recipient gets a clean broken reference, not your original path.
  • Import extracts them beside the document, byte for byte at the paths the archive carries, and reports what it did. Only entries the versions actually reference land on disk; anything else in the archive is skipped and named in the report.
  • Import never overwrites. An image already in place with the same bytes is left alone (importing the same bundle twice just works); one with different bytes refuses the whole import before anything is written.

Two honest limits. The first belongs to the format, not to what Wymark knows: Wymark’s own version history keeps the images each version was saved with, but a bundle carries one copy per path, from today’s disk, across every version you export. A historic version in the bundle whose image was later overwritten therefore travels with today’s bytes, and one whose image was deleted travels with a missing reference — a bundle is less faithful than the local history it came from. The second: since only referenced files travel, an image nothing in the exported versions points at stays home.

The specification

The normative spec for the current version of the format, including the exact filename grammar, the ordering rule, front-matter handling, and the safety rules a reader must apply to an archive it was sent, is wymark.history/1. It lives with Wymark’s source, and this page is a summary of it rather than a replacement.

Two things from it are worth repeating here, because they affect what you can do with a bundle rather than how to parse one:

  • The archive’s own file name means nothing. Rename plan.mdh however you like; mail systems routinely turn it into plan (1).mdh. The document’s identity comes from the version files inside, never from the container.
  • Every version in a bundle must name the same document. A bundle is one document’s history. A reader must refuse one that mixes several, rather than guessing which of them is the document you meant to open.
# History bundles (`.mdh`)

> **Experimental.** This format is new, and whether it earns a place outside Wymark is unsettled. It is specified and stable enough to build against, but if you are sending a document with tracked changes to someone who does not use Wymark, [export to Word instead](#sending-to-someone-who-does-not-use-wymark).

Wymark can export a document *together with its version history* as a single file. What the recipient gets is a markdown document plus its past versions — not a special viewing mode and nothing that pops up in their face.

Because the versions arrive as versions, Wymark can show the most recent step as a review: the difference between the last two versions in the bundle is waiting to be accepted or rejected. What that difference *is* depends on what you chose to send — the changes you have in flight, if that is the scope you exported, or the step since your previous checkpoint if you sent the whole history. Send a bundle whose last two versions are identical and there is simply no review, just a document with its history intact.

A new file extension is the kind of thing that rightly makes people suspicious. So, plainly, before anything else:

**A `.mdh` file is a zip archive of markdown files. That is the entire format.**

There is no manifest, no metadata sidecar, no binary section, and nothing Wymark-specific inside it. Rename `plan.mdh` to `plan.zip` and double-click it: you get a folder of `.md` files, one per version, each named with a timestamp. Every one of them opens in any text editor, renders in any markdown viewer, and diffs in `git`. If Wymark disappeared tomorrow, the contents would still be exactly as readable as the day they were written.

```
plan.20260725T103000Z.md
plan.20260725T112215Z.md
plan.20260726T090000Z.draft-for-legal.md
```

The file names *are* the metadata. A timestamp orders them; an optional label after the timestamp is a version name someone typed. The last one, chronologically, is the current document — the version that lands on disk when the bundle is opened. The rest are its history.

That is the whole design. You can build a valid bundle with `zip`, and a shell script or an AI agent can produce one without knowing anything about Wymark.

Why the format is this plain, why it is a container at all, and why it is not meant as lock-in is in the design note [Why a history bundle is a zip of markdown files](/docs/how-it-works/history-bundles).

## What a bundle does not carry

A bundle carries versions, faithfully and byte for byte. It does not carry *why* you made a change, who accepted what, or the sequence of keystrokes between two versions — because Wymark never had that either.

**In particular, changes have no author.** A diff is the difference between two texts, so it cannot say who typed which part — not you, not the AI agent editing alongside you. There is no field for it, in the bundle or anywhere else in Wymark.

Comments do carry a name, filled in from your OS user account when you write one. Treat it as a label rather than as evidence: it is plain text sitting in the markdown, so anyone can edit it in the raw view, and an agent writing a comment supplies whatever name it likes. Useful for telling voices apart in a thread; not something to lean on if the question is who really said what.

## What happens when you open one

Opening a `.mdh` in Wymark asks where you want the document saved, then:

- The newest version becomes a real markdown file on disk, byte for byte as the sender had it. This is an ordinary markdown file from that point on.
- The version before it becomes the review baseline, so the step between those two is on screen as an accept/reject review.
- The rest of the history is restored as versions, each keeping the timestamp it originally had — so the history reads as the chronology it actually was, not as "imported just now".

Nothing is stitched into a document you already have. An imported bundle is always a new document, because merging someone else's history into yours would require guessing which of two divergent chains was correct.

## Sending to someone who does not use Wymark

A bundle is only useful to a Wymark user — outside it, it is a zip of files you would have to read in order yourself. So it is the wrong thing to attach to an email to a client, a lawyer, or a colleague who has never heard of this application.

For that, **export to Word (`.docx`)**. Your changes can be exported as real Word **track changes** — insertions, deletions, moves and formatting changes as Word's own revision marks — and your comments as real Word comments with threaded replies. The recipient opens it in Word, sees changes to accept or reject exactly where they expect to, and never learns that the document was markdown.

Word export is itself labelled **early access**: its shape is settled and it ships, but on some documents it still produces wrong output, so open the exported file in Word before you send it. It is still the better choice for this audience — it is the format they already know, and it asks them to trust nothing new — but it is not a more finished feature than this one, only a more familiar one.

One caveat carries over from the limit described above. Word puts a name on every revision mark, and Wymark has no per-change author to supply, so an export stamps them all with a single one: yours, from your OS user account. If an AI agent wrote half the changes, they still arrive as yours. Comments keep whatever name they carry in the file, which is normally also you — the usual exception being replies written by an agent.

The rule of thumb:

- **Sending to a Wymark user, and the history matters** — send a `.mdh`. They get the versions, not just the outcome.
- **Sending to anyone else** — send a `.docx` with track changes (early access: check it in Word first). It is the format they already know, and it does not ask them to trust an experimental one.
- **Both sides use git** — use git. A bundle is a snapshot chain, and git is better at being git.

## Images travel inside the bundle

Markdown documents reference images, and a bundle that carried only the text would hand the recipient a document with holes in it. So an export can include them: the scope chooser has an **"Include images"** checkbox, on by default, showing the file count and total size before you commit. Bundles are capped at 128 MB either way — past that, an attachment has stopped being something anyone can mail, and the export tells you to slim it rather than writing a file no reader will accept.

Inside the archive, images are ordinary zip entries under the same relative paths the document references — rename the bundle to `.zip` and you see exactly what travels. Readers that predate images simply skip them, which is the ignore rule doing what it was designed for: no manifest announces them, and no existing bundle became invalid.

The rules are short:

- **Only referenced files travel.** The images named by the versions you export — never a folder sweep. Web images stay links.
- **References to files elsewhere on your machine are rewritten** — in the bundle only, never in your own document — to point into the document's assets folder, and the files travel there. Your disk layout is not the recipient's business: a path like `/Users/you/Desktop/draft-v2/fig.png` says things you may not intend to say, so it never leaves the machine. That applies even when the file is missing — the recipient gets a clean broken reference, not your original path.
- **Import extracts them beside the document,** byte for byte at the paths the archive carries, and reports what it did. Only entries the versions actually reference land on disk; anything else in the archive is skipped and named in the report.
- **Import never overwrites.** An image already in place with the same bytes is left alone (importing the same bundle twice just works); one with *different* bytes refuses the whole import before anything is written.

Two honest limits. The first belongs to the format, not to what Wymark knows: Wymark's own version history keeps the images each version was saved with, but a bundle carries **one copy per path, from today's disk**, across every version you export. A historic version in the bundle whose image was later overwritten therefore travels with today's bytes, and one whose image was deleted travels with a missing reference — a bundle is less faithful than the local history it came from. The second: since only referenced files travel, an image nothing in the exported versions points at stays home.

## The specification

The normative spec for the current version of the format, including the exact filename grammar, the ordering rule, front-matter handling, and the safety rules a reader must apply to an archive it was sent, is `wymark.history/1`. It lives with Wymark's source, and this page is a summary of it rather than a replacement.

Two things from it are worth repeating here, because they affect what you can do with a bundle rather than how to parse one:

- **The archive's own file name means nothing.** Rename `plan.mdh` however you like; mail systems routinely turn it into `plan (1).mdh`. The document's identity comes from the version files inside, never from the container.
- **Every version in a bundle must name the same document.** A bundle is one document's history. A reader must refuse one that mixes several, rather than guessing which of them is the document you meant to open.