$npx mdflow-crypt

Read your encrypted notes. Locally.

MDflow encrypts a document's body in your browser — the server only ever stores ciphertext. mdflow-crypt is a standalone command-line tool that runs the same encryption on your own machine, so you can take an encrypted note out of MDflow, read or edit it offline, and paste it back. Your plaintext and your password never touch a server or an AI model.

bash — decrypt a note
$ npx mdflow-crypt decrypt notes.md
Password: ••••••••
Decrypted → notes_decrypted.md
$ npx mdflow-crypt encrypt notes.md
Password: ••••••••
Confirm password: ••••••••
Encrypted → notes_encrypted.md
$man mdflow-crypt

Why it exists

Encryption in MDflow is deliberately one-way from the cloud's point of view — the server, search, and AI agents only ever see ciphertext. mdflow-crypt is the local key that turns it back into markdown, without giving that plaintext to anyone.

$cat notes.md

Read encrypted notes offline

MDflow encrypts a document's body in your browser; the server only ever stores ciphertext (mdflow-enc:v1:…). That keeps encrypted notes out of search and opaque to AI agents by design. mdflow-crypt lets you take one out and read it on your own machine.

$chmod 600 secret

Nothing leaves your computer

The whole point is local: your plaintext and your password never go to a server or an AI model. Decrypt to edit, re-encrypt, and paste the blob back into MDflow — the crypto runs entirely on your machine.

$npm ls --depth 0

Zero dependencies, one file

A single .mjs file with no dependencies, on Node 18+. Easy to read, easy to audit, and small enough to pin a version you trust for a security-sensitive tool.

$diff browser cli

Byte-identical to the browser

The format is PBKDF2-HMAC-SHA256 (600k iterations) → AES-256-GCM, a verbatim match of MDflow's in-browser encryption. What the app encrypts, the CLI decrypts, and vice versa.

$mdflow-crypt --help

Three steps, round-trip

01

Copy the encrypted body

In MDflow, open the encrypted document and copy its raw body — the mdflow-enc:v1:… text — into a local file, e.g. notes.md.

02

Run it on your machine

npx mdflow-crypt decrypt notes.md. You're prompted for the password (hidden), and the plaintext is written next to the input as notes_decrypted.md.

03

Edit, re-encrypt, paste back

Change the file, run encrypt to get a fresh mdflow-enc:v1:… blob, and paste it into the document body in MDflow. The server still only ever sees ciphertext.

$ls install/

Install from npm

It's on npm as mdflow-crypt. You need Node.js 18 or newer — check with node -v.

No install — run with npx
bash — npx
$ npx mdflow-crypt decrypt notes.md
$ npx mdflow-crypt encrypt notes.md
# pin a version you trust (security tool)
$ npx mdflow-crypt@1.0.2 decrypt notes.md
Or install it permanently
bash — global install
$ npm install -g mdflow-crypt
$ mdflow-crypt encrypt notes.md
$ mdflow-crypt decrypt notes.md

// It's a local tool by design — don't pipe it through a remote runner. Install it, or use npx, and run it on your own machine.

$mdflow-crypt <encrypt|decrypt> <file> [password]

Using it

Two commands. The output file is written next to the input with the original extension dropped — report.md report_encrypted.md or report_decrypted.md.

$mdflow-crypt decrypt notes.md

Reads an mdflow-enc: file and writes the plaintext to notes_decrypted.md. A wrong password or corrupted data exits non-zero and writes nothing.

$mdflow-crypt encrypt notes.md

Encrypts a markdown file to notes_encrypted.mdto paste into MDflow. Refuses a file that's already encrypted, and asks for the password twice.

$mdflow-crypt encrypt notes.md --password-file ~/.pw

Reads the password from the first line of a file — keep it chmod 600. Precedence: --password--password-file positional arg → hidden prompt.

$mdflow-crypt decrypt notes.md --password 's3cret'

Inline password. Visible to other processes and in your shell history — prefer the hidden prompt or a password file for anything sensitive.

$echo $?

Exit codes: 0 ok · 1 usage / unreadable / wrong-shape input · 2 no or mismatched password · 3 decrypt failed. There is no password recovery and no backdoor — a forgotten password means the document is unrecoverable, so store it in a password manager.

$openssl — under the hood

The same crypto as the browser

mdflow-crypt is a verbatim copy of the encryption MDflow runs in your browser, so the two are byte-compatible in both directions.

  • Key derivation. PBKDF2-HMAC-SHA256 with 600,000 iterations and a random per-document salt.
  • Cipher. AES-256-GCM with a random IV — authenticated, so a tampered byte fails to decrypt.
  • No backdoor. No password recovery, no escrow, no telemetry. The password is only ever used on your machine.
  • Auditable. One dependency-free .mjs file, MIT-licensed. Read it on GitHub before you run it.

// New to client-side encryption? See Client-Side Encryption for Notes You Store Online.

$man mdflow-crypt --faq

Questions

What is mdflow-crypt?
mdflow-crypt is a standalone, zero-dependency command-line tool that encrypts and decrypts MDflow documents locally. MDflow stores encrypted document bodies as mdflow-enc:v1 ciphertext; this CLI does the same crypto on your own machine so you can take an encrypted note out of MDflow and read or write it offline. It runs on Node 18+ and is published on npm as mdflow-crypt.
How do I install it?
You don't have to install anything — run it with npx: `npx mdflow-crypt decrypt notes.md`. To install it as a permanent command instead, run `npm install -g mdflow-crypt` and then use `mdflow-crypt encrypt notes.md`. It needs Node.js version 18 or newer.
Is my content or password ever sent anywhere?
No. mdflow-crypt is a local tool by design: decrypting never exposes your content to a server or an AI model, and your password is only used on your machine. Because of that, don't pipe it through a remote runner — install it, or use npx, and run it on your own computer.
Which commands are there, and what do they output?
Two: `encrypt` turns a markdown file into <name>_encrypted.md (paste that into MDflow), and `decrypt` turns an mdflow-enc: file into <name>_decrypted.md. The output is always written next to the input with the original extension dropped — report.md becomes report_encrypted.md or report_decrypted.md.
How is the password supplied?
In order of precedence: the --password flag, then --password-file (the first line of a file, keep it chmod 600), then a positional [password] argument, and otherwise a hidden interactive prompt (encrypt asks twice to confirm). Prefer the prompt or a password file — an inline flag or positional argument is visible to other processes and lands in your shell history.
What if I forget the password?
There is no password recovery and no backdoor. A forgotten password means the encrypted document is unrecoverable, so store it in a password manager. The format is PBKDF2-HMAC-SHA256 (600,000 iterations) into AES-256-GCM, matching MDflow's in-browser encryption exactly.
Is it safe to run this through an AI agent?
No — that defeats the purpose. The reason mdflow-crypt exists is that decryption stays on your machine, so the plaintext never reaches a model. A human should run it in their own terminal. For a security tool, it's also wise to pin a version you trust, e.g. `npx mdflow-crypt@1.0.2`, rather than always pulling the latest.
$npx mdflow-crypt

Keep the ciphertext in the cloud. Read it at home.

Encrypt notes in MDflow, and reach for mdflow-crypt whenever you need the plaintext on your own machine — no server, no model, no dependencies.