Getting your content out
By the end of this you will have a clone of a workspace on your own machine and a backup file that contains everything, and you will know precisely what each of the two does and does not hold.
Clone the repository
Each workspace is one git repository, and it is the source of truth rather than an export of one. Clone it and you have every document as a Markdown file, with the ordinary git history, readable with the ordinary tools.
git clone <workspace-repository> knowledge
What you get:
knowledge/
grundsaetze.md
bewertung/
sicherheiten.md
diagram.png.asset
Every .md file is a document, front matter and body, exactly as it was
written. Nothing needs converting and nothing needs an API.
What a clone does not contain
The uploaded files themselves. diagram.png.asset is a pointer — a small
text file recording the upload's name, size, type, and checksum. The bytes live
outside the repository.
That is a deliberate design decision rather than an oversight. Git cannot forget a binary once it is committed: history cannot be rewritten without invalidating every clone anyone holds. An upload is far more likely than a typed document to contain somebody else's personal data, and being able to answer an erasure request means being able to actually destroy the bytes.
So a hand-rolled copy of the repositories alone silently misses every upload. For everything at once, take a backup.
Take a backup
One workspace, or all of them:
pnpm --filter @md-platform/core backup <workspaceId> ./backup.tar
pnpm --filter @md-platform/core backup --all ./backup.tar
The file is a single tar containing a manifest, the PostgreSQL records, one git bundle per workspace, and the uploaded files that are not in those bundles. It is the thing that holds documents and uploads together.
Writes to a workspace being copied wait for the duration, so the repository and the records agree with each other. On a busy workspace that means a short delay for writers rather than an inconsistent backup.
The file is not encrypted. It holds customer content in full, plus password and token hashes. It is as sensitive as the database it came from — treat it accordingly.
Read it back before you rely on it
pnpm --filter @md-platform/core restore ./backup.tar --dry-run
This verifies the checksums and reports what the file would do, writing nothing:
Backup taken 2026-08-09T12:58:33.113Z
format : 1
workspaces: 01KZB223QDQP0F7MBN1Q9Z24H2
checksums : 2 verified
Dry run: nothing was changed.
Worth running on any backup you intend to depend on. A backup nobody has ever read back is a hypothesis, not a backup.
Restoring
pnpm --filter @md-platform/core restore ./backup.tar
Restoring is the most destructive operation here and is usually run by somebody who has just lost something, so it refuses a workspace that already has documents:
Workspace 01KZB2… already has 5 document(s). Restoring would replace them. Pass --force to proceed.
Checksums are verified before anything is staged and the swap happens only after that succeeds, so a corrupt file fails without having touched the target.
Rebuilding the index
Not an export, but the same underlying property and worth knowing: PostgreSQL holds a projection of the repositories and can be reconstructed from them.
pnpm --filter @md-platform/core rebuild-projection <workspaceId>
Because git is the source of truth, this cannot lose a document that has been committed. It is also the recovery path if a projection write ever fails after a commit has landed.
What "done" looks like
You have a clone whose .md files you can read in any editor, and a
--dry-run that verified your backup's checksums. Between them, leaving is a
copy rather than a project.