Google Docs, but for your markdown files. Open a local .md from the terminal,
edit it with other people in real time, leave comments, propose tracked changes,
and roll back through history — then pull the result back to disk.
Built on Convex for the database and sync engine, TipTap / ProseMirror for the editor, and a deliberately bare, monochrome interface. The whole app is just the document on first glance; controls fade in only when you reach for them.
- Real-time multiplayer editing — operational-transform sync via Convex's
prosemirror-synccomponent, with live collaborator carets. - Comments — anchored to a text range, threaded replies, resolve / reopen, synced to everyone instantly.
- Suggestion mode — toggle from Edit to Suggest and your changes become tracked insertions/deletions you can accept or reject. Edit mode applies changes directly.
- Edit history — save named version snapshots and restore any of them (the restore syncs to all open clients).
- CLI access —
multimark ./file.mdseeds the file and opens it in your default browser;multimark pull ./file.mdwrites the latest content back.
Requires Node 18+ and a Convex account.
npm install
npx convex dev # first run configures the project + writes VITE_CONVEX_URL to .env.local
npm run dev # starts Convex (watch) + Vite on http://localhost:5173All configuration is read from the environment — see .env.example. Nothing is
hardcoded, and .env.local (your deployment URL) is gitignored. The web app and
CLI both read VITE_CONVEX_URL.
Icons. The UI prefers Nucleo's filled set (
nucleo-core-fill-24), a private package fetched only whenNUCLEO_LICENSE_KEYis in your environment at install time. It's an optional dependency — if it isn't installed, the app automatically falls back to react-icons (MIT), sonpm install && npm run devjust works without a license.
Link it once, then use it anywhere:
npm link
multimark ./notes.md # seed + open in the default browser
multimark list # list all documents
multimark pull ./notes.md # write the document's current content back to the fileEnvironment:
MULTIMARK_WEB_URL— web app origin (defaulthttp://localhost:5173)MULTIMARK_USER— your display name (default: OS username)
The CLI talks to your Convex deployment over HTTP using VITE_CONVEX_URL from
.env.local. Convex is cloud-synced, so collaborators on other machines pointed
at the same deployment + web URL edit together — local dev or not.
- One Convex
documentsrow per file; the live document is a ProseMirror doc synced by@convex-dev/prosemirror-sync(created server-side so there's no client race). The file's markdown seeds it once, claimed atomically. - Comments and suggestions ride inside the synced doc as ProseMirror
marks, so every client sees the anchors automatically. Thread metadata and
resolved state live in reactive Convex tables (
comments). - Presence is a heartbeat table; remote carets are rendered as editor decorations.
- The web client serializes the doc back to markdown (debounced) into
currentMarkdown, which is whatmultimark pullreads.
convex/ schema + sync API + comments / presence / versions functions
src/editor/ TipTap setup, comment & suggestion marks, the workspace UI
src/comments src/history side panels
cli/ the multimark CLI
Body type is Geist (SIL Open Font License — see
public/fonts/OFL.txt), self-hosted. This project is MIT licensed (see
LICENSE). Nucleo icons are licensed separately and are not redistributed here;
the open-source react-icons fallback covers anyone without a Nucleo license.