Notion-style editing over the plain markdown already in your git repo.
Your repo is the storage. Docs stay ordinary markdown – readable on GitHub, diffable, reviewable through PRs, and directly usable by AI coding agents. Every save is a git commit under your own identity. Delete fragmt tomorrow and you still have a folder of markdown and its full history.
npx fragmt init # inside any git clone containing markdown
npx fragmt serve # opens the editorRequires Node 22+.
Documentation tools make you choose between a good editor and owning your content.
Notion and Confluence give you the editor and keep the content in their database – export is lossy, history lives in their pane instead of your toolchain, and your coding agent can't read any of it without an API integration. Plain markdown in git gives you ownership, review and agent-readability, but the editing experience is a text editor.
fragmt refuses the trade.
| Notion / Confluence | Markdown + text editor | fragmt | |
|---|---|---|---|
| Storage | vendor database | your repo | your repo |
| Editing | WYSIWYG | text editor | WYSIWYG |
| Diff and review | their version history | git diff / PRs |
git diff / PRs |
| Agent-readable | via API | yes | yes, first-class |
| Cost at 5 seats | per seat, monthly | free | free |
| Self-host seat limit | capped or licensed | – | none |
What it is not: an open-source Notion clone – only the editing UX is Notion-style – and not a CMS. The emphasis is documentation. Nearest relative is Wiki.js, differentiated by being agentic-ready from the ground up: the agent surface is the CLI itself, riding the same core library as the UI.
- Notion-style WYSIWYG over plain markdown. Selection and right-click
bubbles for headings, quotes, links and tables; a
/menu for blocks and images. No markdown knowledge required. - Save is a commit. Frontmatter preserved byte-for-byte, a stale-base-hash guard against concurrent edits, and your real git identity on every commit.
- Main is protected, whether the branch actually is or not. Editing a doc on main starts a draft branch automatically; a global Merge button lands it.
- Merge conflicts resolve in the tool – per-hunk ours/theirs or a free-edit box, structural merging for comment sidecars, one concluding commit.
- Draft changes are visible – on a draft branch, an amber bar marks every
block the draft's commits touched, computed from
git diffagainst main. - Inline comments anchored to text as marks in the markdown itself, threads versioned in JSON sidecars. No comment backend.
- Ctrl/Cmd+K search across titles and bodies, and a side-by-side preview pane for reading one doc against another.
- Full file lifecycle – create, rename, move, delete, drag and drop, a
recycle bin,
.gitignorerespected,@references between docs. - Agents are first-class users – see Agents.
npx fragmt init # scaffold: writes .fragmt.json, adopts existing markdown
npx fragmt serve # start the editor, prints the URLOr globally: npm i -g fragmt, then fragmt init and fragmt serve.
init must run inside a git clone. It never overwrites an existing config – a
second run prints already initialized and exits 0. Scope it to a subfolder
with fragmt init --root docs. Or give the docs a repo of their own, nested
inside a code repo – see Docs in a code repo.
Platforms: tested on Windows. Linux and macOS verification is in progress – reports from those platforms are welcome.
When the docs belong to a code repository, mixing docs commits into code history gets old fast: separate PRs, tangled diffs, agents wading through it all. fragmt can give the docs folder a git repo of its own, nested inside the working tree:
fragmt init --folder docs --new # docs/ becomes its own git repo
fragmt serve # run from docs/ – the outer repo is untouchedThe folder is created if missing, and markdown already sitting there rides the
nested repo's initial commit – the outer repo's own history is left alone.
After creation, init offers to wire up an origin: paste a fresh GitHub or
GitLab URL and fragmt pushes the docs repo and stages it as a submodule in
the outer repo, so the host renders docs/ as a linked folder and teammates
get everything with git clone --recursive. Skip the prompt and fragmt writes
a .gitignore entry instead and prints the exact commands for later – a
re-run of init offers the wiring again.
An AGENTS.md lands at both roots: the outer one tells coding agents the
docs live in the nested repo; the inner one carries the usual fragmt rules.
Running serve or agent from the outer root simply points you at the
folder.
fragmt can maintain the doc bundle as an
open-knowledge-format
(OKF v0.2) knowledge base: typed concept docs, a generated index.md per
directory, and the doc-to-doc reference graph kept as derived frontmatter.
Docs stay plain markdown – OKF is a file convention any tooling (and any
agent) can read directly.
fragmt init --okf # enable on a fresh OR existing repo
fragmt validate # print conformance findings, one per line
fragmt validate --fix # apply the mechanical repairs in one commitinit --okf adopts, never rewrites: existing files are validated and the
findings printed, the index.md set and the reference fields are committed,
and validate --fix finishes adoption in a single pass. It composes with
--folder --new for a nested docs repo.
In OKF mode fragmt maintains:
- Conformant defaults – new docs are born with a
type: conceptandstatus: draftfrontmatter block; any non-empty type is conformant. - Generated
index.md– per directory holding docs: concepts grouped under# <Type>sections with absolute links, subdirectory entries linking the subdirectory's ownindex.md; regenerated on membership changes (create, move, rename, delete, merge) – never on content saves. references/referenced-by– frontmatter fields derived from body links, recomputed on every save. Body links stay canonical; the fields are a cache.- Trust stamping – every save rewrites
generated: { by, at }:byis the committing identity ashuman:<email-local-part>, or an agent's self-declared--as-actorstring (defaultfragmt-agent/unspecified– a machine never claims a human's review).verifiedis an append-only event log with four affordances, each appending{ by, at }in the same commit as its act: resolving a comment thread, the doc head's Verify button, Save as Verified beside Save, andfragmt agent verify <doc>(its--as-actordefaulting to the same self-declared string). - Trust badges – derived, never stored: doc cards and the doc head show
the §5.3 tier (unverified / machine-confirmed / human-reviewed) from the
verifiedactors, and a stale chip oncenow >= stale_after. An absent status renders nothing – stable is silence, never implied. The Verify button shows its already-mine state (Verified, from the server-derivedverifiedByYou) while staying clickable – events are append-only. - Unified metadata editing – a collapsible metadata block between the
doc head and the content shows every
key: value(collapsed by default). The one Edit button edits content AND metadata together; the one Save commits both in a single commit through field splices (never re-serialized YAML, unknown keys byte-preserved). Beyond the curated fields (type,description,tags,status,stale_after) any §4.1 extension key is editable and new keys can be added – several per save.statusis enum-only –draft/stable/deprecated, enforced at the API seam; the UI's select is convenience. - References pane – the right pane's References mode lists the open doc's outgoing and incoming references; a row opens the target in the pane's preview split beside the current doc (the side-by-side default), with open-in-main one click away in the preview head.
- Reference graph – a full-pane view of the whole bundle's link graph: one node per doc, an edge per body link, node color the §5.3 trust tier, a dashed ring when stale, isolated docs kept visible. Hover shows the detail, click opens the doc through the same unsaved-changes guard as every navigation. Derived fresh from body links on every open – never the frontmatter cache – and nothing about it is stored.
- Export – the graph as Mermaid (renders on GitHub), Graphviz DOT, or
JSON, and the docs working tree as a plain zip for sharing outside git:
fragmt export [--format mermaid|dot|json] [--out <file>], orfragmt export --bundle. The graph view's toolbar carries the same set as copy/download buttons. - Reserved names –
index.mdandlog.mdnever hold concepts; creates and renames targeting them are refused, and the UI keeps them read-only (their metadata area explains why, per §3.1).
validate --fix prepends missing frontmatter, adds missing types and
status: draft, repopulates the derived fields, and regenerates the
index.md set (adopted bundles self-heal their link shapes) – all in one
commit, existing YAML never re-serialized. While non-conformant docs
remain, the sidebar shows a banner listing them by path and clause.
fragmt init [--root <path>] [--folder <name>] [--new] [--okf]
fragmt serve [--port <n>] [--auth]
fragmt validate [--fix]
fragmt export [--format mermaid|dot|json] [--out <file>] [--bundle]
fragmt agent [status]
fragmt agent comment <doc> [--thread <id>] [--body <text>] [--resolve] [--author <who>] [--as-actor "<producer>/<version>"] [--full]
fragmt agent draft <doc> [--merge] [--as-actor "<producer>/<version>"]
fragmt agent verify <doc> [--as-actor "<producer>/<version>"] [--author <who>]
fragmt --help
serve --auth turns the editor into a small multi-user server: GitHub
sign-in, your repo's collaborator permissions as access control, Docker
samples included – see HOSTING. Commit authors are
recognized by their GitHub avatar – automatically for signed-in users, and
via a two-line authors map in .fragmt.json for everyone else.
With serve --auth, pull requests are part of the editor: draft branches
push and open PRs as the signed-in user – the review, merge and sync ride
that user's own GitHub token, never the operator's credentials.
- The branch menu carries a PR chip per draft branch; the review lives in the slideout's Pull requests mode – the open list, paged diffs (20 files per page), and Merge with your own token. A conflicted PR states it and links out to GitHub.
- Sync mirrors every branch to origin (never force), so no work lives only
on the local disk – plain
servekeeps pushing with machine credentials. - Branch delete is gated on merged: an unmerged branch can't be deleted from the menu.
- None of this exists in local mode – a solo operator wanting PRs runs
serve --auth.
AI coding agents are first-class users, and the contract is the fragmt agent
CLI – token-lean output, aggregates inline, next-step hints, exit codes 0/1/2,
no interactive prompts.
| Verb | What it does |
|---|---|
fragmt agent status |
Branch, protected-main mark, draft map, merge state |
fragmt agent comment docs/x.md |
List threads; --thread <id> for detail, --full for untruncated bodies |
fragmt agent comment docs/x.md --thread <id> --body "…" |
Reply on a thread (one commit) |
fragmt agent comment docs/x.md --thread <id> --resolve |
Resolve a thread |
fragmt agent draft docs/x.md |
Start or reuse the doc's draft branch |
fragmt agent draft docs/x.md --merge |
Merge the draft into main |
fragmt agent verify docs/x.md |
Append a verified event to the doc in its own commit |
Doc bodies are plain markdown, so agents read and diff them directly; the CLI
matters for drafts, comments and merge state. Mutations accept --author
(Name <address>) so an agent's commits carry its own identity – list the name
under agents in .fragmt.json and the UI marks its comments with a chip.
In OKF mode, agents also self-declare the generated stamp's actor with
--as-actor "<producer>/<version>" (default fragmt-agent/unspecified) –
verbatim, never a false human: claim. draft --merge stamps the doc on
the draft branch before merging; comment --resolve appends the actor's
verified event beside the sidecar write; verify appends it standalone –
the UI's Verify button without the HTTP detour.
fragmt init also writes a delimited <!-- fragmt:begin -->…<!-- fragmt:end -->
block into AGENTS.md, teaching any agent the drafting rules; with
--okf the block additionally teaches the OKF rules – the conformance
contract, the reserved and generated files, which fields fragmt owns, and
the verify/validate loop. Nothing outside the markers is touched.
On Windows with git's default core.autocrlf, every content commit prints
warning: … LF will be replaced by CRLF the next time Git touches it. That is
git's working-copy layer talking, not a fragmt problem: fragmt stores doc
bodies as LF and canonicalizes them on every read and write, so the warning
never reflects a change to the repository. It is noise – no action is needed.
If the noise bothers you, git config core.autocrlf (user level) is the knob;
fragmt adds no .gitattributes of its own.
.fragmt.json at the repo root is the whole configuration surface:
{
"docsRoot": ".",
"order": {},
"authors": { "you@example.com": "YourGitHubUsername" },
"agents": ["ZCode"]
}| Key | Meaning |
|---|---|
docsRoot |
Path, relative to the repo root, that fragmt treats as the doc tree. "." is the whole repo. |
order |
Reserved for explicit doc ordering (v1.x). Always {} for now. |
authors |
Optional map of commit emails to GitHub usernames, for avatars. |
agents |
Optional list of agent display names; their comments get an agent chip. |
okf |
Optional. true maintains the bundle as OKF – set by fragmt init --okf. Absent means legacy behavior. |
Parsing is strict – a malformed config fails loudly with the file path rather than falling back to a silent default.
Beta. The full v1 feature set works. What stands between this and 1.0 is dogfood hardening – a long-running effort that closes when it closes, not on a schedule.
Reference docs live in docs/: architecture
and design principles.
The design decisions, the build log and the wrong turns – including why Tiptap won the editor spike and what was deliberately cut from v1 – are written up at migatchev.co.za/projects/fragmt.
See CONTRIBUTING.md. Scope is deliberately tight, so open an issue before a large PR. The most useful contribution right now is dogfooding and issue reports – especially on Linux and macOS.
Built with TypeScript, Node 22, Hono, React 19 + Vite,
Tiptap 3, and a thin execFile wrapper around system git.
MIT – see LICENSE. Copyright © 2026 Andrei Migatchev and contributors.
