One section in, one section out — on Markdown/GEML files, bad writes refused.
English | 中文
GEML is a lightweight, Agent-Native markup language, designed for people and AI agents to read and write the same document.
One format, two readers.
In agent-driven development and knowledge work, plain text and Markdown have no deterministic block boundaries: a program and a model trade the whole file in and the whole file back out — at best probing for it with line windows, and restating the original verbatim to rewrite it. Token cost grows with the length of the document, and the operation turns bloated. After a few rounds of rewriting, the copies excerpted elsewhere start to drift.
You can start without changing a thing. geml list, geml find and geml get address the Markdown you already have — nothing is converted, no new files, your .md stays .md:
geml list README.md # every section, as an address
geml get README.md '#key-features' # read ONE section, not the file
geml set README.md '#key-features' --body # write one section back
geml replace README.md 'old text' 'new text' # swap a string, told which block held it
Only that section enters the agent’s context — a couple of KB, not the whole ~48 KB file.
Need finer than a section — one block, one chart, one table? Let .geml stand in the middle ground: edit at that grain, and the --to md you ship never drifts from it.
A block has a name; the things inside it have a coordinate. A table's cell, a
data block's leaf, a key in meta — each has a coordinate the structure already
gives it, and get and set land on exactly that value.
geml get doc.geml '#fy[2]["Q1"]' # one cell
geml set doc.geml '#intake["fields"][1]["name"]' # one leaf in the JSON
For people, it is plain text that reads clean; for agents, it is an addressable, verifiable, traceable, revertible "Doc-as-a-Base".
GEML is minimal. It is plain text — still clean with no renderer in sight; one block syntax for the whole language; addressable, verifiable, referenceable structure, natively.
Instead of a separate mini-syntax for each kind of content, GEML carries every kind in one container: the typed block. Code is a block. So are tables, diagrams, math, callouts, even metadata — and a run of prose can be one too (=== text), whenever you want it addressable. Extending it later is just as plain. The shape is the same every time, which makes the language easy enough to learn that it's hard to get wrong.
=== code {#hello lang=python}
print("hi")
===
geml get doc.geml '#hello' # by name, just this block
Blocks have names so the verbs have somewhere to land — the full syntax is in the format in 1 minute.
Contents: What it solves · Why now · What's different · The format in 1 minute · Profiles · Get hands-on · With an LLM · Maturity & versions · The design · Roadmap · Take part · License
Context load and token bloat
AST-level precision and parsing determinism
Document copy fragmentation
#id hits one semantically complete block, and the rest never enters the context.profile metadata without inventing new syntax or breaking parsers.| Dimension | Markdown | JSON / YAML | GEML |
|---|---|---|---|
| Context cost (block-wise I/O) | High (whole file in and out) | High (whole file + syntax noise) | Minimal (only the target block) |
| Precise AST operations | Weak (no strict semantic nodes) | Strong | Strong (built for agent reads and writes) |
| Human readability | High | Medium | High |
| Single-source references | Unsupported | Needs protocol extensions | Native (modular embeds) |
| Domain extensibility | Fractured (proprietary syntax hacks) | Schema-dependent | Native Profiles (zero new syntax + verified) |
| Write safety | Weak | Medium | Strong (a bad write is refused before landing + single-block revert) |
Because both the producer and the consumer of a document have changed.
In traditional software engineering, a document was either a static explanation for people to read, or a serialized data file for programs.
Today, people and AI agents collaborate on the same document at high frequency. When the agent becomes the document's "second reader and co-author", the old balance breaks for good:
Yet none of our existing text infrastructure was designed for this scene:
The root of all three failures is each tool's own virtue: Markdown's "never error, write anything" is what gives people their freedom to write — and exactly why a machine cannot trust the structure it reads back; JSON/XML's strict schema is what gives machines their certainty — and exactly why nobody writes prose in it. The virtue is the defect, which is why patches cannot fix this: bolting "a broken reference must fail the build" onto Markdown betrays its contract, and stripping the wrapper syntax from JSON denies its nature. When people and agents start co-writing the same text at high frequency, what is needed is not a compromise between the two poles, but a format that treats "readable by people" and "operable by machines" as one design constraint from day one.
GEML invents no heavy new runtime. Borrowing from the REST architectural style of Dr. Roy Fielding's dissertation, it gives plain-text documents one standard set of operational semantics:
| Old pain | The matching capability (the four laws) | What it buys developers and agents |
|---|---|---|
| Changing one spot means rewriting the whole text | The Law of Addressing | Every block carries an #id; get/set reads and writes that block alone. What is never loaded cannot be broken — the context window stays yours. |
| Copies everywhere, all drifting | The Law of Projection | === embed evaluates dynamically instead of copy-pasting; one definition at the source ends the labor of syncing copies. |
| Bad formats / broken references pollute downstream | The Law of Validation | References and syntax are checked at build time; a bad write is stopped before it lands, with no waiting for human review. |
| One bad edit forces a whole-file rollback | The Law of Rollback | The companion .gemlhistory reverts a single block atomically — no tearing down the page; a lightweight version safety net for agents. |
A document no longer needs just a format — it needs a set of verbs. GEML keeps plain-text readability and adds deterministic block-level operations.
💡 Deep Dive: If you are interested in the dilemma of engineering documents in the LLM era and why we need to redesign a plain-text format from the ground up, read our full article on the blog: "Why Do We Need a New Text Format in the Era of LLMs?"
GEML stays small on purpose — the thinking, what it refuses, and what is still open are in how we thought about the design.
The four capabilities were established a chapter ago — addressing, projection, validation, rollback. This chapter is where each format lands against them, and where GEML draws its boundaries.
Each of the four has mature solutions in its own field; what's unusual is meeting all four in one plain-text format:
| Family | What the state really is | Addressable / referenceable | Projectable / embeddable | Verifiable | History / traceability |
|---|---|---|---|---|---|
| Word / Docs | Opaque state | ❌ No block-level keys; access via platform APIs | ❌ Copy-paste only | ❌ No checking at all | ⚠️ Platform server-side, not in the file |
| Markdown / AsciiDoc | A stream of characters | ⚠️ Heading anchors or dialect ids; no read/write verbs | ⚠️ Dialect embeds (Obsidian ![[…]], include::) — break silently | ❌ Broken links fail silently | ❌ None in-format — external git required |
| JSON / XML | Data serialization | ✔️ (id / schema) | ⚠️ XML only (XInclude, external) | ✔️ Via an external toolchain | ❌ None in-format — external git required |
| GEML | Plain text + block structure | ✔️ A unique #id per block (referenceable natively) | ✔️ === embed: a reference is a lookup (native) | ✔️ A build-time error | ✔️ .gemlhistory next to the file (traceable natively) |
Item by item: vs. CommonMark · vs. XML and JSON · a 7-format capability matrix · the Markdown variants and tools in awesome-markdown (Chinese, an HTML page).
Coexisting with Markdown: GEML is the editing source of truth, Markdown is the delivered artifact. Project one way with geml <file> --to md|html and ship .md or .html as before. Collaboration, not lock-in. (Projection is lossy: block ids and table-bound charts don't survive it.)
Don't take the table's word for it — re-run it. This is what I asked the model:
Based on your own experience editing the READMEs just now, describe the command steps you go through on a document (I saw you using grep and such), and whether you cache documents to save tokens — let's compare, and from that see which parts of GEML would actually earn their place.
What came back: what one edit costs and a real day replayed. Paste the question to your own model and see what it tells you.
PS: I am still trying to work out whether the upstream chain (who calls this) and the downstream chain (what it calls) that codemap produces can pin down functions and call sites — and change project code — the same way. I will post a report when I have one.
One shape, every type. A block's basic syntax is === type [attributes] … === (where attributes like {#id .class key=val} are optional) — only the type (and how its body is read) changes:
=== code {lang=python}
print("hi")
===
=== note {.intro}
Parsed prose with *emphasis* and a [[#budget]] reference.
===
=== meta
title = "Budget plan"
===
A run of = (three or more) opens a block; an equal-length run closes it; longer fences nest inside shorter ones. A block that carries an #id can also close with the labeled fence === #id — no fence-length counting, which makes long blocks much harder to get wrong (nesting still requires a longer outer fence: a same-length bare === in the body closes the block early, labeled or not). The type decides how the body is read — raw (verbatim: code, diagram, math, table), flow (parsed prose with inline markup: note, text), or data (one key=val per line: meta); embed carries no body at all — its src= names the block it stands for — and every block may carry an attribute object {#id .class key=val}, where a .class is a semantic label, never a styling hook. The full inline grammar (emphasis, links, [[#id]] auto-references, media, footnotes, inline $math$) is in the spec.
Write a table visually:
=== table {#budget caption="Annual cost"}
| Plan | Months | Rate |
|-------|-------:|-----:|
| Basic | 1 | 30 |
| Pro | 2 | 30 |
===
…or as data. A table holds the facts; a view over it derives the
computed columns and the summary row:
=== table {#fy25 format=csv header=1}
Segment, Q1, Q2, Q3, Q4
Cloud, 8, 10, 12, 14
Platform, 5, 6, 7, 9
Services, 3, 4, 4, 5
===
=== view {#fy25-report src=#fy25 compute="FY [%.1f] = Q1 + Q2 + Q3 + Q4; n = 1" summary="Segment = 'Total'; FY [%.1f] = sum(FY); n = sum(n)"}
===
Both table forms describe the same model. The FY column and Total row are computed at build time, by the view:
| Segment | Q1 | Q2 | Q3 | Q4 | FY | n |
|---|---|---|---|---|---|---|
| Cloud | 8 | 10 | 12 | 14 | 44.0 | 1 |
| Platform | 5 | 6 | 7 | 9 | 27.0 | 1 |
| Services | 3 | 4 | 4 | 5 | 16.0 | 1 |
| Total | 87.0 | 3 |
compute runs + - * / ( ) per row over columns; summary adds a foot row from the aggregates sum / avg / min / max / count (with arithmetic over them, e.g. weighted ratios); a trailing [printf] sets numeric display. n above is the row-count idiom — count tallies non-empty cells in one column, so a constant column summed is what counts rows.
Tables can also pull their data from an external CSV via src="regions.csv".
=== math {#gauss caption="Gaussian integral"}
\int_{-\infty}^{\infty} e^{-x^2} dx = \sqrt{\pi}
===
$$\int_{-\infty}^{\infty} e^{-x^2} dx = \sqrt{\pi}$$
GEML never interprets a diagram body; it routes it to a pluggable renderer (an unknown format is a warning, body preserved):
=== diagram {#flow format=mermaid caption="Review flow"}
graph LR
A[Draft] --> B{Review} -->|ok| C[Publish]
===
graph LR
A[Draft] --> B{Review} -->|ok| C[Publish]
A diagram can also chart a table — single source of truth, with the column references checked at build time and no data copied:
=== diagram {format=geml-chart data=#fy25-report type=bar x=Segment y=FY}
===
Drawn from the #fy25-report view above — FY is a computed column, so the
chart binds to the view that derives it, not to the base table:
xychart-beta
title "FY by segment"
x-axis [Cloud, Platform, Services]
y-axis "FY"
bar [44, 27, 16]
Every block type names what it holds: code a region of code, table a grid, math a formula. data holds a data value, and it is where the data formats live — json (the default), jsonl, and yaml for a declared subset; toml reserved. Being typed means the body is read, not just displayed: a missing comma fails the build, geml get --json returns the value itself, and a chart can read it directly.
=== data {#log format=jsonl}
{"ts":"09:00","p95":41}
{"ts":"09:10","p95":58}
===
A jsonl body holds one record per line, which a program can blind-append at end-of-file. Records can also stay in their own file: src=ops/latency.jsonl#L900-999 names the file and, optionally, a line window — so the log keeps being appended and tailed as before, while the document is its verified, addressable, chartable view of it.
One block can stand for another: in the same document by src=#id, across documents by src=other.geml#id. An embed is a dynamic lookup of the source at render time — change the source once and every embed follows; delete it and geml check fails the build on the spot.
=== embed {src=#fy25}
===
The body stays empty; the target lives in src=.
Markdown can't show you the projection. To see it live: install the browser extension, open the raw link to sample.geml, and scroll to the Transclusion section — a same-document projection (src=#roadmap), cross-document projections, and even chained resolution (an embed pulls a chart, which itself binds to a table in another file) all render in place: nothing is written there, yet edit the source once and the projection follows.
Want to author interactive forms, define a design token system, or map an entire codebase's call graph inside your documents?
In traditional Markdown, this requires proprietary plugins (:::note, custom JSX tags), inevitably fracturing into incompatible dialect silos.
GEML solves this with Profiles (Application-layer vocabularies, spec §8.6): A single-line declaration that unlocks domain-specific structured superpowers on demand.
=== meta
profile = "geml-style/v1 geml-form/v1"
===
=== form-field {#email label="Work email" type=email required pattern="[^@]+@acme\\.com"}
===
=== style-rule {#cta match="button.cta" bg="{{brand}}" radius="6px"}
===
• 🧩 Mix & match like Lego bricks
The core syntax stays minimal and frozen, while domain capabilities expand infinitely. Call graphs, design tokens, form validation, version history... compose multiple domain vocabularies with one profile = "..." line.
• ⚡ Zero-plugin overhead with instant tooling support
Adding a new domain block requires zero parser forks or custom plugins. Custom blocks instantly inherit the entire infrastructure: deterministic #id addressing, geml get/set blockwise mutation, CLI verbs, MCP protocol, and autonomous AI Agent control.
• 🛡️ Naturally portable, never locked in Extend capabilities without breaking interoperability. In any third-party or unfamiliar processor, documents maintain 100% structural integrity and block-level addressability, ending the nightmare of broken formatting when switching tools.
| Profile (guide) | Status | What it's for | Superpowers Admitted | CLI | Live Demo / Example |
|---|---|---|---|---|---|
geml-codemap/v1 | stable | Generates your codebase's call graph as GEML documents: one block per method, so you can see who calls it and what it calls; front-end and back-end merge into one graph | code blocks: anchor, name, entry-via | geml codemap build|verify|serve | Interactive Call Graph · sample.geml |
geml-media/v1 | draft | Describes a video timeline in one document: assets, clips, subtitle and voice tracks; export it as a web player, or render an MP4 with ffmpeg | media, media-asset, media-clip, media-text | geml media build|export|lay|todo | Doc-to-Video (Doc to MP4 via ffmpeg) |
geml-style/v1 | draft | Colours, spacing and layout live in a separate stylesheet document whose rules apply to your content; the content document itself stays unchanged | style-rule, style-state, style-screen, style-frame | geml style check | GitHub Blob Page 1:1 Replica |
geml-history/v1 | stable | Keeps past versions in a .gemlhistory file beside the document: read any old version, put back a single block, or roll back the whole file | history-revision, history-keyframe, history-blob | geml history save|get|restore | Atomic Block Rollback Workflow |
geml-form/v1 | draft | Describes a form in a document: its fields, their types, which are required, allowed ranges; the browser extension and the playground draw a preview | form, form-field, form-group, form-options, form-note; constraint attributes pattern, min, max… on form-field | — | Interactive Complex Form Example |
geml-translator/v1 | draft | A translation document holds no translated text: it embeds the source and names the target language, and the browser extension machine-translates it on open, so it follows every change to the source | embed and meta attribute translate-to | — | — |
💡 Want to see Profiles in action? •
geml-medialive demo: One cut document and one command (geml media build ep01-cut.geml --out ep01.mp4 --burn-subs) orchestrates ffmpeg to align audio/video, mix tracks, and burn subtitles into a finished video (see it). •geml-stylelive demo: Content stays pure text inpage.geml, while styles and layout live ingithub.style.geml— rendering a 1:1 pixel-accurate replica of GitHub's blob page without CSS lock-in (see it). • Every profile name in the table opens its one-page guide — what it does, the first command, everyday use. If you write code, start withgeml-codemap. You can also easily create your own custom domain profile.
▶ Try writing GEML in the Playground — edit on the left, rendered live on the right, and the build verdict flips red the moment a reference breaks. No install, nothing to read first.
Then, in the order that suits you:
.geml link (the raw file, not the GitHub blob page — that one is HTML): the GEML spec itself (dogfood — the spec is a GEML document, rendered at scale), the showcase (a computed table, four charts, a Mermaid flow, and math), or playground/sample.geml for the interactive code-graph.page.geml holds every string and github.style.geml holds every colour and length, and the viewer knows about neither. It opens in any browser — the viewer's own code draws it — with the GEML that makes it right below.npm i -g @geml/geml (Node 22+), then geml check a document, or point it at your own repo with geml codemap build.npx -y @geml/geml skill install puts the authoring skill, the CLI and the MCP server in place, user-global, for every project. It edits no settings and installs no hooks. Details.geml check diagnostics, geml list addresses, --to html markup), each rule tagged with its source and status.The goal is one thing: your model edits a block at a time, and verifies — never re-reads and re-emits a whole file to change one paragraph. Getting there takes one step, and which step depends on what you use.
npx -y @geml/geml skill install
It installs the authoring skill, the geml CLI and the MCP server, user-global,
for every project. No settings.json edits, no hooks; re-run after an upgrade.
(Prefer plugins? claude plugin marketplace add geml-spec/geml, then
/plugin install geml@geml — same skill, MCP server bundled.)
The same setup, packaged as a dsh bundle — the geml MCP server plus the authoring and code-graph skills:
dsh plugin --profile web add @geml/dsh-plugin # web = the profile dsh boots by default; use your own profile name if you run another
Listed on dshmarket and awesome-dsh-plugin; source in integrations/dsh-plugin/.
The same payload once more, packaged for Codex: both skills, the MCP server, and
a SessionStart hook. Start Codex in a checkout of this repo and it shows up in
/plugins (the marketplace source is committed at
.agents/plugins/marketplace.json); to add it without cloning, the git-subdir
entry is in integrations/codex-plugin/.
Then say it once in a session, and the project has switched:
This project uses GEML as its base document format; generate other formats from it as needed.
A model with no skill to read needs the rules once. Paste the prompt below, and
keep geml check as the gate on whatever it writes back — the CLI is
npm i -g @geml/geml (Node 22+).
Write the document as GEML: every block is
=== type [attributes]…===(the format in 1 minute lists the types). Four rules are the ones models get wrong: the closing fence is a=run of the exact opening length, and a body containing===needs a longer outer fence; headings are ATX#only, with no---frontmatter (metadata is=== meta); every#idis unique and every reference ([[#id]],[text](#id),[^id],data=#id) must resolve; there is no raw HTML. The normative spec isGEML-spec.md.
geml list doc.geml # CALL FIRST: every block, its address, kind, lines
geml find "words" doc.geml # search block content -> an address, not a line number
geml get doc.geml '#hello' # read ONE block (a heading id = its whole section)
geml get doc.geml '#hello' --intro # a section cuts three ways: --head | --intro | --body
geml set doc.geml '#license' --in template.geml#mit # replace that block, forking another
geml add doc.geml --after '#intro' --in snippet.geml # insert a fragment (keeps its own ids)
geml revert doc.geml '#plan' --rev -1 # roll ONE block back
geml check doc.geml # validate only: diagnostics + exit code
Any section cuts three ways, on get and set alike: --head is the heading
line, --intro what it says before its first subheading, --body everything
under it — so --body always contains --intro, and equals it when there is no
subheading. A section's opening can be edited without pulling its subsections
into context.
Every mutation is re-parsed before it writes and refused if it would break the
document — which is what makes editing unattended safe. The rest of the verbs
(delete, rename, history, --to md|html|geml conversion, addressing a
block by type or content hash) are in the
parser README.
A standard Model Context Protocol server ships with the package, so your agent
edits one block at a time instead of rewriting whole files — on Markdown and
GEML alike. It runs locally on Windows, macOS, and Linux; --root is the
directory the server is confined to (use . or ${workspaceFolder} to bind to
the active project).
Claude Code — one-command setup (installs skill, CLI, and MCP server):
npx -y @geml/geml skill install
(Or register manually via CLI: claude mcp add --scope user geml -- npx -y @geml/geml mcp --root .)
Cursor — add .cursor/mcp.json to your project:
{
"mcpServers": {
"geml": {
"command": "npx",
"args": ["-y", "@geml/geml", "mcp", "--root", "${workspaceFolder}"]
}
}
}
(Or in Cursor Settings → Features → MCP: name geml, command npx -y @geml/geml mcp --root .)
Claude Desktop — add to claude_desktop_config.json:
{
"mcpServers": {
"geml": {
"command": "npx",
"args": [
"-y",
"@geml/geml",
"mcp",
"--root",
"/absolute/path/to/your/docs"
]
}
}
}
Then just ask for the change you want — "fix the Q3 row in the FY26 table" — and
the agent addresses that one block. You never learn a tool name: each mirrors a
CLI verb (geml set → geml_set), so one vocabulary covers the terminal and the
agent.
Two guarantees make this better than letting a model rewrite the file: a write is
parsed before it reaches disk and refused with its diagnostics if it would
break the document, and every write first records a .gemlhistory revision — so a
bad edit is both prevented and undoable (geml_revert restores one block, the
rest of the file byte-identical). Paths stay confined to --root, which a client
cannot widen.
Point --root at a repository that has a code graph (geml codemap build) and the
same server also answers "who calls this" — four read-only geml_codemap_* tools,
one client entry instead of two. Every tool and option:
docs/mcp-guide.md.
GEML is a small, young spec — but a stable one: 1.0 is released and usable for real documents (this repo's own spec is one), with a strict conformance suite, a reference implementation that passes it (versioned independently of the spec), and an open proposal process.
There is one specification, and it is bilingual. The .gemlhistory sidecar
is defined by the geml-history/v1 profile — an application layer on top of
the spec rather than part of it, which is also why it is MIT and the spec is
CC-BY (LICENSE-spec.md says why):
| Document | English | 中文 |
|---|---|---|
| The specification | GEML-spec.md | GEML-spec_CN.md |
geml-history/v1 profile | geml-history-profile.md | geml-history-profile_CN.md |
Every profile this project publishes: spec/profiles/.
GEML-spec.geml is the specification written in GEML, required to parse clean on every test run.acme-invoice), leaving hyphen-free names to future versions of the spec (§8.5)..geml (version sidecar .gemlhistory), media type text/vnd.geml — a vendor-tree name; the standards-tree text/geml can be applied for if the spec is ever published through the IETF..geml URL names the block bearing that id (§0.6) — which is not what #tag means on an HTML page.Human–Agent Isomorphism, Not a Compromise Instead of splitting the difference between human-readable Markdown and machine-readable JSON, GEML treats human readability and machine determinism as a single, uncompromising constraint. Humans get clean, distraction-free prose; agents get a strongly typed AST—eliminating translation loss between two separate formats.
Doc-as-a-Base, Not a Stream of Characters
Traditional documents are fragile streams of characters where editing one sentence often forces a full-file rewrite. GEML treats a document as an addressable database of structured records with stable primary keys (#id). Every block has an independent lifecycle, spatial coordinate, and atomic CRUD interface suited for O(1) agent reads and writes.
One Syntax Primitive, Infinite Domain Vocabularies
Refuse to invent syntax patches for every new kind of content. GEML uses a single typed-block primitive (=== type) to carry code, data, tables, math, and layout. Domain capabilities expand infinitely through Profiles (profile = "..."): the grammar stays 100% frozen, while vocabularies remain open—ending dialect fragmentation at the root.
Transclusion over Duplication: Kill the Incentive to Copy
Traditional hyperlinks are signposts pointing elsewhere, encouraging copy-pasting that inevitably causes copies to drift out of sync. GEML references are dynamic viewports (=== embed): define once at the source, and project live everywhere. Maintain a single source of truth by removing the motivation to copy.
Compiler-Grade Integrity: Treat Documentation Like Code
Markdown's ethos is "never fail, render something"—the primary breeding ground for agent hallucinations and silent documentation decay. GEML enforces strict build-time static validation. Broken #ids, invalid attributes, and cyclic references fail the build with a non-zero exit code. Catch errors before they pollute downstream systems.
Local-First History, Not Cloud Lock-in or Git Overhead
Data belongs on the local filesystem, and versioning belongs at block granularity. GEML refuses to lock version history behind proprietary cloud platforms (like Notion or Google Docs), while avoiding the heavy whole-repo commit overhead of Git for micro-edits. The companion .gemlhistory gives plain text local-first atomic snapshots and surgical rollback (geml revert #id), ensuring true data sovereignty and safety.
| Refused | Why |
|---|---|
| A diagram language of its own | External DSLs are hosted (Mermaid, Graphviz, D2, …); the format defines only the hosting protocol |
| A raw-HTML escape hatch | Semantics stay portable, tied to no backend or renderer |
Setext headings / --- frontmatter | ATX # only, so nothing collides with a thematic break |
| A full spreadsheet engine | Per-row formulas and summary aggregates are enough; no cell addressing, lookups, or macros |
1.0 specification, in English and Chinese, with a conformance suite — plus the geml-history/v1 profile that defines the .gemlhistory sidecar@geml/geml: parser, CLI, block-level .gemlhistory trackinggeml mcp) for Claude Code, Cursor, Codex and other MCP hostsgeml)xai-org/plugin-marketplaceGEML is 1.0, but "stable" means the rules already there won't shift under you,
not that the design is settled. There is exactly one implementation so far, and
one set of opinions behind the spec. Your thinking can still change the spec itself.
If you want a hand in it:
Come argue about these, the proposals still in draft:
form typed block — addressable fields, an inert destinationSomething else on your mind? Start a discussion.
| Gap | Where it stands | What it takes |
|---|---|---|
| Skill installation for more agent tools | Gemini CLI, Qwen Code and AGENTS.md are installed by detection already; the MCP server works with any client | Add the rest the same way: Cursor, GitHub Copilot, Cline — their rule-file conventions move fast, so check the current docs before writing one in |
| How well the primer holds on other models | Only exercised on Claude | Have GPT / Gemini / a local model each write a batch of GEML from the primer, count how many pass geml check first time, and report the rules they keep getting wrong — those are the ones the primer should name |
| Deeper Obsidian integration | Renders, but not in the community store yet | Editing at the CodeMirror layer and seamless two-way rendering, plus the store submission itself. Wants someone who knows the Obsidian API. |
| The viewer on other browsers | Chrome works | Firefox / Safari ports. |
| Packaging the RAG integrations | LangChain / LlamaIndex are reference implementations | Publishing to PyPI; and wiring up other frameworks (Haystack, DSPy, …). |
Or propose something new:
Or put it to use:
| Scenario | Where | State |
|---|---|---|
| From the command line — validate, convert, edit by block, version history, all in one command | @geml/geml (source geml-parser/) | Available |
Read it in the browser — open any raw .geml link and it renders in place: computed tables, charts, Mermaid, math, with diagnostics as a banner | Chrome Web Store · source | Available |
| Let an agent edit by block — an MCP server; the agent changes one block instead of rewriting the file, and every write is validated before it reaches disk | docs/mcp-guide.md | Available |
| Use it from DeepSeek Harness — the geml MCP server plus the authoring and code-graph skills, one installable bundle | @geml/dsh-plugin · dshmarket · source | Available |
Use it from Codex — the same payload again: both skills, the MCP server, and a SessionStart hook, installable from /plugins | integrations/codex-plugin/ | Available from this repo; not in the public plugin directory yet |
| Use it from Grok — the same payload once more: both skills and the MCP server | integrations/grok-plugin/ | Available from this repo; the xai-org/plugin-marketplace PR is not opened yet |
Sync a Logseq graph to plain text — a Logseq 2.0 DB graph as continuously synced GEML files, addressable and git-friendly, with restore as the way back | @geml/logseq-sync · source | Watcher on npm; the plugin installs from a release zip — the marketplace listing (PR #893) is not merged yet |
| Turn a codebase into a document — the whole call graph as a tree of GEML documents, browsable | geml codemap build (guide · design) | Available |
| Write it in your editor — syntax highlighting + build-time reference checking | Visual Studio Marketplace · source | Available |
| Render it in Obsidian — the reference parser + the viewer's renderer, the same code path as the web | integrations/obsidian/ | Built, not in the community store |
Feed a RAG / agent framework — block-level loaders (one chunk per block, carrying block_id) + agent editing tools | integrations/langchain+llamaindex/ | Reference implementation |
| Try it without installing anything — edit on the left, live render on the right | Playground | Available |
Three files to read first: GOVERNANCE.md for how decisions get
made, CONTRIBUTING.md for how to send work, and
CODE_OF_CONDUCT.md for the one rule about people —
disagree with the design as sharply as you like, not with the person.
spec/ The specification as .md (EN / 中文) and the CC-BY spec
license, with profiles/ (application layers — geml-history,
geml-codemap, geml-style, geml-form, geml-media,
geml-translator — each a reference beside a one-page usage
guide) and proposals/ (GEPs), both MIT
spec/in_geml_format/ The dogfood: the specification written in GEML, with its
.gemlhistory sidecar
geml-parser/ Reference parser, renderer, CLI + codemap toolkit (TypeScript, Node 22)
integrations/ Everywhere GEML plugs in: geml-viewer (browser extension),
geml-check-action (CI), vscode, obsidian, logseq (two-way
vault sync + the watcher), tree-sitter (brief),
langchain+llamaindex (RAG loaders), windows-icon
(Explorer file icons), the agent-harness plugins —
claude-plugin, codex-plugin, grok-plugin, dsh-plugin — and
website (what this repository pushes to the site)
.agents/, .claude-plugin/ Plugin marketplace manifests, so the plugins show up
from a checkout (Codex `/plugins`, Claude Code `/plugin`)
docs/ Guides (MCP, writing a parser), design records, the release
runbook, assets (logos)
.claude/skills/ Claude skills: GEML authoring, and the code graph
.github/ CI + geml-check workflows, MCP registry publish, and issue
templates (bug, GEP, new implementation)
(website) The homepage, playground, demos, blog, comparisons,
benchmarks, manifesto and illustrated pages live in their
own repository, geml-spec/geml-spec.github.io, which links
here for the spec and guides; t
Source-derived launch command. Check the maintainer’s required arguments and credentials before running:
npx -y @geml/gemlMerge this template into ~/Library/Application Support/Claude/claude_desktop_config.json. Keep existing servers. Add any arguments, credentials, and permissions required by the maintainer; this template has not been install-tested.
{
"mcpServers": {
"io-github-geml-spec-geml": {
"command": "npx",
"args": [
"-y",
"@geml/geml"
]
}
}
}Restart Claude Desktop completely for changes to take effect. Confirm the server appears connected in the client’s tool list, then try a read-only example from its documentation.
Claude Desktop setup referenceGEML — a plain-text document format built to be edited in place, one section at a time works with any MCP-compatible client. Copy the config snippet from the Configuration section above and add it to the file shown for your client, then restart the application.
~/Library/Application Support/Claude/claude_desktop_config.jsonRestart Claude Desktop completely for changes to take effect.~/.cursor/mcp.jsonRestart Cursor for changes to take effect..vscode/mcp.jsonReload VS Code window for changes to take effect.~/.codeium/windsurf/mcp_config.jsonRestart Windsurf for changes to take effect..mcp.jsonSave at the project root, then start Claude Code in that project and review the MCP server approval prompt. Keep real credentials out of shared files.