{
  "markdown": "[![MCP Toplist](https://mcptoplist.com/badge/io.github.geml-spec%2Fgeml.svg)](https://mcptoplist.com/server/io.github.geml-spec%2Fgeml) \n\n\n<p align=\"center\">\n  <picture>\n    <source media=\"(prefers-color-scheme: dark)\" srcset=\"docs/assets/logo/geml-logo-dark.svg\">\n    <img src=\"docs/assets/logo/geml-logo-light.svg\" alt=\"GEML\" width=\"340\">\n  </picture>\n</p>\n\n# GEML — General Expressive Markup Language\n[![npm](https://img.shields.io/npm/v/%40geml%2Fgeml?label=npm)](https://www.npmjs.com/package/@geml/geml) [![MCP](https://img.shields.io/badge/MCP-supported-blue.svg)](https://modelcontextprotocol.io) [![CI](https://github.com/geml-spec/geml/actions/workflows/ci.yml/badge.svg)](https://github.com/geml-spec/geml/actions/workflows/ci.yml) [![GEML check](https://github.com/geml-spec/geml/actions/workflows/geml-check.yml/badge.svg)](https://github.com/geml-spec/geml/actions/workflows/geml-check.yml) [![spec: 1.0](https://img.shields.io/badge/spec-1.0-brightgreen.svg)](spec/GEML-spec.md) [![code: MIT](https://img.shields.io/badge/code-MIT-blue.svg)](LICENSE) [![spec license: CC BY 4.0](https://img.shields.io/badge/spec%20license-CC%20BY%204.0-lightgrey.svg)](spec/LICENSE-spec.md)\n\n*English | [中文](README_CN.md)*\n\nGEML is an **Agent-Native** fundamental markup format and protocol, designed for people and AI agents to read and write the same document.<br>\n**One format, two readers.**\nIn 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.\n\n**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`:\n\n```sh\ngeml list    README.md                          # every section, as an address\ngeml get     README.md '#key-features'          # read ONE section, not the file\ngeml set     README.md '#key-features' --body   # write one section back\ngeml replace README.md 'old text' 'new text'    # swap a string, told which block held it\n```\n\nOnly that section enters the agent’s context — a couple of KB, not the whole ~40 KB file.\n\nNeed 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.\n\nFor people, it is plain text that reads clean; for agents, it is an addressable, verifiable, traceable, revertible **[\"Doc-as-a-Base\"](docs/MANIFESTO.md)**.\n\n---\n\n**GEML is minimal.**\nIt is plain text — still clean with no renderer in sight;\none block syntax for the whole language;\naddressable, verifiable, referenceable structure, natively.\n\nInstead 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.\n\n```\n=== code {#hello lang=python}\nprint(\"hi\")\n===\n```\n\n```sh\ngeml get doc.geml '#hello'   # by name, just this block\n```\n\nBlocks have names so the verbs have somewhere to land — the full syntax is in\n[the format in 1 minute](#one-minute).\n\n**Contents:** [What it solves](#problems) · [Why now](#why-now) · [What's different](#whats-different) ·\n[The format in 1 minute](#one-minute) · [A gift for programmers](#code-graph) ·\n[Get hands-on](#hands-on) · [With an LLM](#with-an-llm) ·\n[Maturity & versions](#maturity) · [The design](#challenge) · [Roadmap](#roadmap) · [Take part](#contributing) ·\n[License](#license)\n\n<a id=\"problems\"></a>\n## What it solves\n\n### Problems solved\n\n1. **Context load and token bloat**\n   * **Status quo**: data formats like JSON/XML carry heavy wrapper tags and syntax symbols; Markdown lacks strict structural metadata and a reference mechanism.\n   * **Approach**: tuned markup density and syntax overhead, reading and writing only the target block — context cost no longer grows with document length, keeping **agent reads and writes lightweight**.\n\n2. **AST-level precision and parsing determinism**\n   * **Status quo**: unstructured text degrades over multiple rounds of LLM reads and writes — broken formatting, semantic drift, parsing hallucinations.\n   * **Approach**: a deterministic grammar that maps directly to an abstract syntax tree (AST), so programs and LLMs perform atomic block-level create/read/update/delete.\n\n3. **Document copy fragmentation**\n   * **Status quo**: multi-agent collaboration and shared pipelines pass content around by copy-paste, leaving multiple disconnected copies.\n   * **Approach**: **Single Source of Truth** by design — standardized module references and data binding eliminate redundant copies and version divergence.\n\n### Key features\n\n#### 1. AST-level structured operations\n* Uniform node definitions; a document parses directly into a typed document tree (AST).\n* Agents pinpoint the target section, attribute or component; partial patches and idempotent updates replace whole-file rewrites. Writes land as byte splices with whole-document re-validation — the tree serves reading and validation, and every untouched byte is guaranteed unchanged.\n\n#### 2. Low-token reads and writes\n* What is saved is not markup characters — it is the part never read: `#id` hits one semantically complete block, and the rest never enters the context.\n* For the same semantics, markedly lower prompt-token cost: better model throughput, lower inference cost.\n\n#### 3. Single source of truth, modular references\n* Native cross-document, cross-fragment component references.\n* Change the source node once and every reference follows — no version skew.\n\n#### 4. Robust two-way reads and writes\n* One block shape for the whole language — easy to generate and hard to get wrong, a good match for mainstream LLM output distributions.\n* A strict validator with precise error locations and actionable repair feedback.\n\n### Comparison\n\n| Dimension | Markdown | JSON / YAML | GEML |\n| :--- | :--- | :--- | :--- |\n| **Context cost (block-wise I/O)** | High (whole file in and out) | High (whole file + syntax noise) | **Minimal (only the target block)** |\n| **Precise AST operations** | Weak (no strict semantic nodes) | Strong | **Strong (built for agent reads and writes)** |\n| **Human readability** | High | Medium | **High** |\n| **Single-source references** | Unsupported | Needs protocol extensions | **Native (modular embeds)** |\n| **Write safety** | Weak | Medium | **Strong (a bad write is refused before landing + single-block revert)** |\n\n---\n\n<a id=\"why-now\"></a>\n## Why the LLM era needs a brand-new text format\n\nBecause **both the producer and the consumer of a document have changed**.\n\nIn traditional software engineering, a document was either a static explanation for people to read, or a serialized data file for programs.\n\nToday, 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:\n\n1. **Context is scarce compute**: every whole-document read or write burns an agent's limited attention window and reasoning budget;\n2. **Human–machine collaboration needs an isomorphic carrier**: people need to read it at a glance, agents need to read and write it precisely, block by block;\n3. **Knowledge must have a single source of truth**: scattered prompts and copy-pasted Markdown are destined to decay with every iteration.\n\nYet none of our existing text infrastructure was designed for this scene:\n\n* **Markdown (typeset for people)**: no stable structural blocks, no machine keys. To change one parameter, an agent must read and write the whole text — **wasting context budget** across multi-turn loops, and inviting drift in both format and meaning.\n* **JSON / XML (serialized for machines)**: full of wrapper syntax and structural noise — blocking natural human reading, while quietly eating expensive tokens in long contexts.\n* **Scratch memory and scattered files (no single source of truth)**: context is torn across chat history and Markdown copies everywhere; a copy is drift from the moment it is made, and version skew and hallucinated distortion follow.\n\nThe 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**.\n\n### The answer: **[\"Doc-as-a-Base\"](docs/MANIFESTO.md)**\n\nGEML invents no heavy new runtime. Borrowing from the **[REST](https://www.ics.uci.edu/~fielding/pubs/dissertation/rest_arch_style.htm)** architectural style of Dr. Roy Fielding's dissertation, it gives plain-text documents one standard set of operational semantics:\n\n| Old pain | The matching capability (the four laws) | What it buys developers and agents |\n| :--- | :--- | :--- |\n| **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. |\n| **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. |\n| **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. |\n| **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. |\n\n> **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.\n\n> 💡 **Deep Dive:**\n> 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?\"**](https://geml-spec.github.io/geml/blog/2026/08/03/why-do-we-need-a-new-text-format-in-the-era-of-llms/)\n\n---\n\n<a id=\"whats-different\"></a>\n## What's different about GEML\n\nGEML stays small on purpose — the thinking, what it refuses, and what is still open are in [how we thought about the design](#challenge).\n\nThe 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.\n\n### How other formats compare\n\nEach of the four has mature solutions in its own field; what's unusual is meeting all four in one plain-text format:\n\n| Family | What the state really is | Addressable / referenceable | Projectable / embeddable | Verifiable | History / traceability |\n| :--- | :--- | :--- | :--- | :--- | :--- |\n| **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 |\n| **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 |\n| **JSON / XML** | Data serialization | ✔️ (id / schema) | ⚠️ XML only (XInclude, external) | ✔️ Via an external toolchain | ❌ None in-format — external git required |\n| **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)** |\n\nItem by item: [vs. CommonMark](docs/comparisons/GEML-vs-CommonMark.md) · [vs. XML and JSON](docs/comparisons/GEML-vs-XML-and-JSON.md) · [a 7-format capability matrix](docs/comparisons/COMPARISON.md).\n\nCoexisting 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.)*\n\n**Don't take the table's word for it — re-run it.** This is what I asked the model:\n\n> 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.\n\nWhat came back: **[what one edit costs](docs/benchmarks/addressing-cost.md)** and **[a real day replayed](docs/benchmarks/mixed-toolchain.md)**. Paste the question to your own model and see what it tells you.\nPS: 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.\n\n<a id=\"one-minute\"></a>\n## The format in 1 minute\n\n### Typed blocks\n\n**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:\n\n```\n=== code {lang=python}\nprint(\"hi\")\n===\n\n=== note {.intro}\nParsed prose with *emphasis* and a [[#budget]] reference.\n===\n\n=== meta\ntitle = \"Budget plan\"\n===\n```\n\nA 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](spec/GEML-spec.md).\n\n### Tables — two bodies, one model\n\nWrite a table visually:\n\n```\n=== table {#budget caption=\"Annual cost\"}\n| Plan  | Months | Rate |\n|-------|-------:|-----:|\n| Basic |      1 |   30 |\n| Pro   |      2 |   30 |\n===\n```\n\n…or as data. A table holds the facts; a **`view`** over it derives the\n**computed columns** and the **summary row**:\n\n```\n=== table {#fy25 format=csv header=1}\nSegment,  Q1, Q2, Q3, Q4\nCloud,     8, 10, 12, 14\nPlatform,  5,  6,  7,  9\nServices,  3,  4,  4,  5\n===\n\n=== view {#fy25-report src=#fy25 compute=\"FY [%.1f] = Q1 + Q2 + Q3 + Q4; n = 1\" summary=\"Segment = 'Total'; FY [%.1f] = sum(FY); n = sum(n)\"}\n===\n```\n\n*Both table forms describe the same model. The `FY` column and `Total` row are computed at build time, by the view:*\n\n| Segment   | Q1 | Q2 | Q3 | Q4 |   FY | n |\n|-----------|---:|---:|---:|---:|-----:|--:|\n| Cloud     |  8 | 10 | 12 | 14 | 44.0 | 1 |\n| Platform  |  5 |  6 |  7 |  9 | 27.0 | 1 |\n| Services  |  3 |  4 |  4 |  5 | 16.0 | 1 |\n| **Total** |    |    |    |    | **87.0** | **3** |\n\n`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.\n\n\nTables can also pull their data from an external CSV via `src=\"regions.csv\"`.\n\n> ❓ **Up for discussion:** should computed columns and the summary row stay? [Keep, freeze, or drop — say which](https://github.com/geml-spec/geml/discussions/19).\n\n### Math\n\n```\n=== math {#gauss caption=\"Gaussian integral\"}\n\\int_{-\\infty}^{\\infty} e^{-x^2} dx = \\sqrt{\\pi}\n===\n```\n\n$$\\int_{-\\infty}^{\\infty} e^{-x^2} dx = \\sqrt{\\pi}$$\n\n### Diagrams & charts — host a DSL, or chart a table\n\nGEML never interprets a diagram body; it routes it to a pluggable renderer (an unknown `format` is a warning, body preserved):\n\n```\n=== diagram {#flow format=mermaid caption=\"Review flow\"}\ngraph LR\n  A[Draft] --> B{Review} -->|ok| C[Publish]\n===\n```\n\n```mermaid\ngraph LR\n  A[Draft] --> B{Review} -->|ok| C[Publish]\n```\n\nA diagram can also **chart a table** — single source of truth, with the column references checked at build time and no data copied:\n\n```\n=== diagram {format=geml-chart data=#fy25-report type=bar x=Segment y=FY}\n===\n```\n\n*Drawn from the `#fy25-report` view above — `FY` is a computed column, so the\nchart binds to the view that derives it, not to the base table:*\n\n```mermaid\nxychart-beta\n  title \"FY by segment\"\n  x-axis [Cloud, Platform, Services]\n  y-axis \"FY\"\n  bar [44, 27, 16]\n```\n\n### Data — a value, not just text\n\nEvery 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.\n\n```\n=== data {#log format=jsonl}\n{\"ts\":\"09:00\",\"p95\":41}\n{\"ts\":\"09:10\",\"p95\":58}\n===\n\n```\n\nA `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.\n\n### Embeds — a dynamic reference, not a copy\n\nOne 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.\n\n```\n=== embed {src=#fy25}\n===\n```\n\nThe body stays empty; the target lives in `src=`.\n\nMarkdown can't show you the projection. To see it live: install the [browser extension](https://chromewebstore.google.com/detail/opmhfphgoidpnipphfgkhhjhmnmaenie), open the [raw link to sample.geml](https://raw.githubusercontent.com/geml-spec/geml/main/playground/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.\n\n<a id=\"code-graph\"></a>\n## A gift for programmers — geml-code-graph\n\nTo test GEML's expressive power and flexibility — and above all to see whether block-level bidirectional linking holds up — let's try it on a code graph, a familiar but demanding case for programmers:\n**your whole codebase's call graph, written as GEML.** `geml codemap build` lays the call graph out as a tree of GEML documents — every method an `#id` block, with `#calls` / `#called-by` edges both ways. The **downstream chain** (what a method calls) for troubleshooting, the **upstream chain** (who calls it) for the blast radius — all visible in a second;\n\n![The method graph of geml-parser/render.ts: hovering RenderCtx.inline lights up its whole caller chain while everything else dims; clicking a node opens its source right beside the graph](docs/assets/codemap-render-ts.gif)\n\n```sh\nnpm i -g @geml/geml\ngeml codemap build              # --root defaults to . : detect languages -> index -> one merged graph in ./.geml-code-graph/\ngeml codemap serve              # opens your browser on the graph\n```\n\n> [!NOTE]\n> **Requirements.** Node **22+** for the CLI (`npm i -g @geml/geml`). Everything\n> below is optional and used only where noted: [Joern](https://docs.joern.io/installation)\n> for non-TS/JS languages in the code graph, and Chrome for the\n> [viewer extension](https://chromewebstore.google.com/detail/opmhfphgoidpnipphfgkhhjhmnmaenie).\n\n> [!TIP]\n> **TS/JS** — zero setup: `build` fetches the scip indexer by itself.\n> **Java / C / Python / Go / Kotlin** — one extra download, [Joern](https://docs.joern.io/installation): unzip its release package and pass that folder to build, e.g. `--joern ~/joern/joern-cli` (`--joern C:\\joern\\joern-cli` on Windows), or put it on PATH and skip the flag.\n> Mixed front-end + back-end repo — everything merges into **one graph**.\n\ngeml-code-graph is itself a diagram format — one line embeds it in any GEML document (`=== diagram {format=geml-code-graph src=.geml-code-graph/index.geml} ===`), and an optional per-commit hook (bundled with the Claude skill) rebuilds it as the code moves, so the graph doesn't drift.\n\nScale is measured, not promised: on Apache Flink's codebase — **13,585 Java source\nfiles, ~81,000 methods, 266,821 call edges** — the plain-text *data tables* still\nopen and query instantly, and you can grep any method name to trace its call chain.\nReproduce it yourself: clone `apache/flink` and run `geml codemap build --joern …` at\nits root.\n\n<a id=\"hands-on\"></a>\n## Next — get hands-on now\n\n▶ **[Try writing GEML in the Playground](https://geml-spec.github.io/geml/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.\n\nThen, in the order that suits you:\n\n1. **See it render in your browser.** Install the **[extension](https://chromewebstore.google.com/detail/opmhfphgoidpnipphfgkhhjhmnmaenie)** and open a raw `.geml` link *(the raw file, not the GitHub blob page — that one is HTML)*: the **[GEML spec itself](https://raw.githubusercontent.com/geml-spec/geml/main/spec/in_geml_format/GEML-spec.geml)** (dogfood — the spec is a GEML document, rendered at scale), the **[showcase](https://raw.githubusercontent.com/geml-spec/geml/main/playground/showcase.geml)** (a computed table, four charts, a Mermaid flow, and math), or **[playground/sample.geml](https://raw.githubusercontent.com/geml-spec/geml/main/playground/sample.geml)** for the interactive code-graph.\n2. **Run it locally.** `npm i -g @geml/geml` (Node 22+), then `geml check` a document, or point it at your own repo with `geml codemap build`.\n3. **Set up Claude Code — one command.** `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](#with-an-llm).\n4. **Read the grammar.** The **[full spec](spec/GEML-spec.md)** (EN / [中文](spec/GEML-spec_CN.md)) is normative and short enough to read in a sitting.\n5. **Or see it worked through, rule by rule.** **[GEML, illustrated](docs/illustrated/README.md)** (EN / [中文](docs/illustrated/README_CN.md)) — eleven self-contained pages, one per block type, per profile, and for the CLI: GEML on the left, what the processor *actually* does on the right (`geml check` diagnostics, `geml list` addresses, `--to html` markup), each rule tagged with its source and status.\n\n<a id=\"with-an-llm\"></a>\n## Using GEML with an LLM\n\nThe goal is one thing: your model **edits a block at a time, and verifies** —\nnever re-reads and re-emits a whole file to change one paragraph. Getting there\ntakes one step, and which step depends on what you use.\n\n### Using Claude Code — run this\n\n```sh\nnpx -y @geml/geml skill install\n```\n\nIt installs the authoring skill, the `geml` CLI and the MCP server, user-global,\nfor every project. No `settings.json` edits, no hooks; re-run after an upgrade.\n*(Prefer plugins? `claude plugin marketplace add geml-spec/geml`, then\n`/plugin install geml@geml` — same skill, MCP server bundled.)*\n\n### Using DeepSeek Harness — add this bundle\n\nThe same setup, packaged as a dsh bundle — the geml MCP server plus the authoring and code-graph skills:\n\n```sh\ndsh plugin --profile web add @geml/dsh-plugin   # web = the profile dsh boots by default; use your own profile name if you run another\n```\n\nListed on [dshmarket](https://dshmarket.com/p/geml-spec/geml--integrations-dsh-plugin/) and [awesome-dsh-plugin](https://awesome-dsh-plugin.com/p/geml-spec/geml--integrations-dsh-plugin/); source in [integrations/dsh-plugin/](integrations/dsh-plugin/).\n\n### Using Codex — install the plugin\n\nThe same payload once more, packaged for Codex: both skills, the MCP server, and\na `SessionStart` hook. Start Codex in a checkout of this repo and it shows up in\n`/plugins` (the marketplace source is committed at\n`.agents/plugins/marketplace.json`); to add it without cloning, the `git-subdir`\nentry is in [integrations/codex-plugin/](integrations/codex-plugin/).\n\nThen say it once in a session, and the project has switched:\n\n> This project uses GEML as its base document format; generate other formats\n> from it as needed.\n\n### Using anything else — paste this, then check the output\n\nA model with no skill to read needs the rules once. Paste the prompt below, and\nkeep `geml check` as the gate on whatever it writes back — the CLI is\n`npm i -g @geml/geml` (Node 22+).\n\n> Write the document as GEML: every block is `=== type [attributes]` … `===`\n> ([the format in 1 minute](#one-minute) lists the types). Four rules are the\n> ones models get wrong: the closing fence is a `=` run of the *exact* opening\n> length, and a body containing `===` needs a longer outer fence; headings are\n> ATX `#` only, with no `---` frontmatter (metadata is `=== meta`); every `#id`\n> is unique and every reference (`[[#id]]`, `[text](#id)`, `[^id]`, `data=#id`)\n> must resolve; there is no raw HTML. The normative spec is\n> [`GEML-spec.md`](spec/GEML-spec.md).\n\n### What it will do with it\n\n```sh\ngeml list   doc.geml                                     # CALL FIRST: every block, its address, kind, lines\ngeml find   \"words\" doc.geml                             # search block content -> an address, not a line number\ngeml get    doc.geml '#hello'                            # read ONE block (a heading id = its whole section)\ngeml get    doc.geml '#hello' --intro                    # a section cuts three ways: --head | --intro | --body\ngeml set    doc.geml '#license' --in template.geml#mit   # replace that block, forking another\ngeml add    doc.geml --after '#intro' --in snippet.geml  # insert a fragment (keeps its own ids)\ngeml revert doc.geml '#plan' --rev -1                    # roll ONE block back\ngeml check  doc.geml                                     # validate only: diagnostics + exit code\n```\n\nAny section cuts three ways, on `get` and `set` alike: `--head` is the heading\nline, `--intro` what it says before its first subheading, `--body` everything\nunder it — so `--body` always contains `--intro`, and equals it when there is no\nsubheading. A section's opening can be edited without pulling its subsections\ninto context.\n\nEvery mutation is re-parsed before it writes and refused if it would break the\ndocument — which is what makes editing unattended safe. The rest of the verbs\n(`delete`, `rename`, `history`, `--to md|html|geml` conversion, addressing a\nblock by type or content hash) are in the\n[parser README](geml-parser/README.md).\n\n### MCP Server\n\nA standard Model Context Protocol server ships with the package, so your agent\nedits **one block at a time** instead of rewriting whole files — on Markdown and\nGEML alike. It runs locally on Windows, macOS, and Linux; `--root` is the\ndirectory the server is confined to (use `.` or `${workspaceFolder}` to bind to\nthe active project).\n\n**Claude Code** — one-command setup (installs skill, CLI, and MCP server):\n\n```sh\nnpx -y @geml/geml skill install\n```\n\n*(Or register manually via CLI: `claude mcp add --scope user geml -- npx -y @geml/geml mcp --root .`)*\n\n**Cursor** — add `.cursor/mcp.json` to your project:\n\n```json\n{\n  \"mcpServers\": {\n    \"geml\": {\n      \"command\": \"npx\",\n      \"args\": [\"-y\", \"@geml/geml\", \"mcp\", \"--root\", \"${workspaceFolder}\"]\n    }\n  }\n}\n```\n\n*(Or in Cursor Settings → Features → MCP: name `geml`, command `npx -y @geml/geml mcp --root .`)*\n\n**Claude Desktop** — add to `claude_desktop_config.json`:\n\n```json\n{\n  \"mcpServers\": {\n    \"geml\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"-y\",\n        \"@geml/geml\",\n        \"mcp\",\n        \"--root\",\n        \"/absolute/path/to/your/docs\"\n      ]\n    }\n  }\n}\n```\n\nThen just ask for the change you want — \"fix the Q3 row in the FY26 table\" — and\nthe agent addresses that one block. You never learn a tool name: each mirrors a\nCLI verb (`geml set` → `geml_set`), so one vocabulary covers the terminal and the\nagent.\n\nTwo guarantees make this better than letting a model rewrite the file: a write is\nparsed **before** it reaches disk and refused with its diagnostics if it would\nbreak the document, and every write first records a `.gemlhistory` revision — so a\nbad edit is both *prevented* and *undoable* (`geml_revert` restores one block, the\nrest of the file byte-identical). Paths stay confined to `--root`, which a client\ncannot widen.\n\nPoint `--root` at a repository that has a code graph (`geml codemap build`) and the\nsame server also answers \"who calls this\" — four read-only `geml_codemap_*` tools,\none client entry instead of two. Every tool and option:\n[docs/mcp-guide.md](docs/mcp-guide.md).\n\n<a id=\"maturity\"></a>\n## Ecosystem and maturity\n\nGEML 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.\n\nThere is **one** specification, and it is bilingual. The `.gemlhistory` sidecar\nis defined by the `geml-history/v1` **profile** — an application layer on top of\nthe spec rather than part of it, which is also why it is MIT and the spec is\nCC-BY ([`LICENSE-spec.md`](spec/LICENSE-spec.md) says why):\n\n| Document | English | 中文 |\n|----------|---------|------|\n| The specification | [`GEML-spec.md`](spec/GEML-spec.md) | [`GEML-spec_CN.md`](spec/GEML-spec_CN.md) |\n| `geml-history/v1` profile | [`geml-history-profile.md`](spec/profiles/geml-history/geml-history-profile.md) | [`geml-history-profile_CN.md`](spec/profiles/geml-history/geml-history-profile_CN.md) |\n\nEvery profile this project publishes: [`spec/profiles/`](spec/profiles/README.md).\n\n### Versions and compatibility\n\n- **Self-hosting** — [`GEML-spec.geml`](spec/in_geml_format/GEML-spec.geml) is the specification written in GEML, required to parse clean on every test run.\n- **A [conformance suite](geml-parser/test/conformance/)** is what holds separate implementations compatible.\n- **A reference implementation of the parser.** **1,300+** unit tests today, plus the conformance corpus, round-trip serialization and end-to-end CLI runs, with coverage CI-gated at ≥**95%** lines / statements / functions / branches.\n- **Forward compatibility is in the grammar.** A processor must degrade gracefully on constructs it does not recognize (spec §8.2), which is why adding a block type or a diagram format is **not** a breaking change. The type registry is open: an unregistered type name should contain a hyphen (`acme-invoice`), leaving hyphen-free names to future versions of the spec (§8.5).\n- **Claiming conformance.** An implementation may call itself *conformant to GEML 1.0* once it reproduces the conformance suite case for case (§8.5). No permission needed, and no sign-off from this repo.\n- **On the wire.** Extension `.geml` (version sidecar `.gemlhistory`), media type `text/geml`, or `text/vnd.geml` where a registered type is required — `text/geml` is not registered with IANA yet.\n- A fragment identifier on a `.geml` URL names the block bearing that id (§0.6) — which is not what `#tag` means on an HTML page.\n\n<a id=\"challenge\"></a>\n## How we thought about the design\n\n### What the design follows\n\n**It is plain text meant for people to read.** Fully readable with no renderer — which is why there is no raw-HTML escape hatch, and why a style may never change what a document says.\n\n**One primitive, a few models.** Every kind of content is the same typed block; extending the format means **registering a type, not inventing syntax**. The type says what it **becomes**: `meta` is key–value shared across the document, `code` is a region of code at a location, `data` is a data value, `table` is a grid waiting to be worked, `diagram` is a hosted external DSL, `embed` is a view onto a source of content\n\n**A reference is a window, not a navigation.** An HTML link navigates: the target is not in the document you are holding, so people copy it in anyway. What is being designed out is not dead links; it is the incentive to copy. *Cost: rendering may need to read several files, and must degrade gracefully when it can't.*\n\n**Prefer subtraction.** Where a rule breeds edge cases, the feature goes rather than the edge cases getting specified: no underscore emphasis, no setext headings, no indented code blocks, no raw HTML. The ambiguity is deleted at the source instead of enumerated in test cases. *Cost: some things you can write in Markdown you cannot write here.*\n\n**No broken windows.** Markdown's ethos is never to fail — render something. GEML's is the opposite: verified at build time rather than tolerated at render time. A dangling `#id` is an error with a non-zero exit. Stable ids, `geml check` and the diagnostic catalogue all follow from that one decision. *Cost: a document that \"looks fine\" can fail your build.*\n\n**A sidecar travels with the document without getting into it.** The `.geml` file is the source of content and stays deliberately small. Anything else is not pushed into it but points back at it — a version history in `.gemlhistory`, say — and deleting that leaves the document perfectly valid. *Cost: a convention, explicit or implied, and two files that travel together.*\n\n**The command line is built for an agent.** The fewest verbs that cover everything, kept orthogonal, with pipeable input and output and options that stay consistent across them.\n\n### What it therefore refuses\n\n| Refused | Why |\n|---|---|\n| A diagram language of its own | External DSLs are hosted (Mermaid, Graphviz, D2, …); the format defines only the hosting protocol |\n| A raw-HTML escape hatch | Semantics stay portable, tied to no backend or renderer |\n| Setext headings / `---` frontmatter | ATX `#` only, so nothing collides with a thematic break |\n| A full spreadsheet engine | Per-row formulas and summary aggregates are enough; no cell addressing, lookups, or macros |\n\n<a id=\"roadmap\"></a>\n## Roadmap\n\n- [x] The GEML `1.0` specification, in English and Chinese, with a conformance suite — plus the `geml-history/v1` profile that defines the `.gemlhistory` sidecar\n- [x] Reference implementation `@geml/geml`: parser, CLI, block-level `.gemlhistory` tracking\n- [x] Official MCP server (`geml mcp`) for Claude Code, Cursor, Codex and other MCP hosts\n- [x] codemap — a whole codebase's call graph, written as GEML\n- [x] Ecosystem integrations: VS Code highlighting and reference checking, tree-sitter, Obsidian, Logseq (two-way sync against a live DB graph), the browser viewer, a GitHub Action, LangChain / LlamaIndex, and the agent-harness plugins — Claude Code, Codex, Grok, DeepSeek Harness, plus root manifests for Gemini CLI and Kimi Code\n- [ ] The Logseq plugin listed in the Logseq marketplace ([PR #893](https://github.com/logseq/marketplace/pull/893)) and the Grok plugin listed in `xai-org/plugin-marketplace`\n- [ ] The VS Code extension on the Marketplace\n- [ ] Parsers in other languages (Rust / Python) — the spec and the conformance suite are public, so community implementations are welcome; we are glad to help line them up\n\n---\n\n<a id=\"contributing\"></a>\n## Take part\n\nGEML is `1.0`, but \"stable\" means **the rules already there won't shift under you**,\nnot that the design is settled. There is exactly **one implementation** so far, and\n**one set of opinions** behind the spec. Your thinking can still change the spec itself.\nIf you want a hand in it:\n\n**Come argue about these**:\n\n- [Should the format keep computed columns and summary rows?](https://github.com/geml-spec/geml/discussions/19)\n- [If styling is supported, how should it be designed?](https://github.com/geml-spec/geml/discussions/17)\n- [Is the GEML history file a made-up need?](https://github.com/geml-spec/geml/discussions/18)\n- [`--view` reads through an embed. Flag, or its own verb?](https://github.com/geml-spec/geml/discussions/21)\n\n<a id=\"integrations\"></a>\nOr **claim a piece**:\n\n| Gap | Where it stands | What it takes |\n|---|---|---|\n| **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 |\n| **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 |\n| **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. |\n| **The viewer on other browsers** | Chrome works | Firefox / Safari ports. |\n| **Packaging the RAG integrations** | LangChain / LlamaIndex are reference implementations | Publishing to PyPI; and wiring up other frameworks (Haystack, DSPy, …). |\n\n- **Write a second implementation of the spec** — a new GEML parser in whatever language you like ([how to write a parser](docs/WRITING-A-PARSER.md))\n- **Finding the places where the spec is ambiguous is itself the contribution**, whether or not that parser ever ships.\n\nOr **propose something new**:\n\n- A GEP: the proposal, the spec edit and the conformance cases land together ([process](spec/proposals/README.md))\n\nOr **put it to use**:\n\n| Scenario | Where | State |\n|---|---|---|\n| **From the command line** — validate, convert, edit by block, version history, all in one command | [`@geml/geml`](https://www.npmjs.com/package/@geml/geml) (source [`geml-parser/`](geml-parser/)) | Available |\n| **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](https://chromewebstore.google.com/detail/opmhfphgoidpnipphfgkhhjhmnmaenie) · [source](integrations/geml-viewer/) | Available |\n| **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`](docs/mcp-guide.md) | Available |\n| **Use it from DeepSeek Harness** — the geml MCP server plus the authoring and code-graph skills, one installable bundle | [`@geml/dsh-plugin`](https://www.npmjs.com/package/@geml/dsh-plugin) · [dshmarket](https://dshmarket.com/p/geml-spec/geml--integrations-dsh-plugin/) · [source](integrations/dsh-plugin/) | Available |\n| **Use it from Codex** — the same payload again: both skills, the MCP server, and a `SessionStart` hook, installable from `/plugins` | [`integrations/codex-plugin/`](integrations/codex-plugin/) | Available from this repo; not in the public plugin directory yet |\n| **Use it from Grok** — the same payload once more: both skills and the MCP server | [`integrations/grok-plugin/`](integrations/grok-plugin/) | Available from this repo; the `xai-org/plugin-marketplace` PR is not opened yet |\n| **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`](https://www.npmjs.com/package/@geml/logseq-sync) · [source](integrations/logseq/) | Watcher on npm; the plugin installs from a release zip — the marketplace listing ([PR #893](https://github.com/logseq/marketplace/pull/893)) is not merged yet |\n| **Turn a codebase into a document** — the whole call graph as a tree of GEML documents, browsable | `geml codemap build` ([design](docs/design/specs/geml-codemap/DESIGN-geml-code-graph.md)) | Available |\n| **Write it in your editor** — syntax highlighting + build-time reference checking | [`integrations/vscode/`](integrations/vscode/) | Built — install from source; not on the Marketplace yet |\n| **Render it in Obsidian** — the reference parser + the viewer's renderer, the same code path as the web | [`integrations/obsidian/`](integrations/obsidian/) | Built, not in the community store |\n| **Feed a RAG / agent framework** — block-level loaders (one chunk per block, carrying `block_id`) + agent editing tools | [`integrations/langchain+llamaindex/`](integrations/langchain+llamaindex/) | Reference implementation |\n| **Try it without installing anything** — edit on the left, live render on the right | [Playground](https://geml-spec.github.io/geml/playground/) | Available |\n\nThree files to read first: [`GOVERNANCE.md`](GOVERNANCE.md) for how decisions get\nmade, [`CONTRIBUTING.md`](CONTRIBUTING.md) for how to send work, and\n[`CODE_OF_CONDUCT.md`](CODE_OF_CONDUCT.md) for the one rule about people —\ndisagree with the design as sharply as you like, not with the person.\n\n## Repository layout\n\n```\nspec/                  The specification as .md (EN / 中文) and the CC-BY spec\n                       license, with profiles/ (application layers — geml-history,\n                       geml-codemap, geml-style, geml-form) and proposals/ (GEPs),\n                       both MIT\nspec/in_geml_format/   The dogfood: the specification written in GEML, with its\n                       .gemlhistory sidecar\ngeml-parser/           Reference parser, renderer, CLI + codemap toolkit (TypeScript, Node 22)\nintegrations/          Everywhere GEML plugs in: geml-viewer (browser extension),\n                       geml-check-action (CI), vscode, obsidian, logseq (two-way\n                       vault sync + the watcher), tree-sitter (brief),\n                       langchain+llamaindex (RAG loaders), windows-icon\n                       (Explorer file icons), and the agent-harness plugins —\n                       claude-plugin, codex-plugin, grok-plugin, dsh-plugin\n.agents/, .claude-plugin/   Plugin marketplace manifests, so the plugins show up\n                       from a checkout (Codex `/plugins`, Claude Code `/plugin`)\nplayground/            In-browser playground (+ a live geml-code-graph of this repo)\ndocs/                  Guides, design notes, comparisons/ (COMPARISON + vs-CommonMark +\n                       vs-XML-and-JSON), assets (logos, used by the Pages site below),\n                       and an example .geml to render\n.claude/skills/        Claude skills: GEML authoring, and the code graph\n.github/               CI + geml-check workflows, MCP registry publish, and issue\n                       templates (bug, GEP, new implementation)\nsite/                  The geml-spec.github.io/geml Pages site: a project homepage\n                       (index.md) plus a Jekyll blog (blog/, posts in _posts/) —\n                       the long-form \"why a new format\" article (EN / 中文) lives\n                       there as its first post. `cd site && bundle exec jekyll\n                       serve` builds it locally; .github/workflows/pages.yml\n                       builds and deploys it (grafting in playground/ as static\n                       output) on push to main.\n```\n\n<a id=\"license\"></a>\n## License & governance\n\n**Code is MIT** ([`LICENSE`](LICENSE)): everything in this repository —\n`geml-parser/`, all of `integrations/`, `playground/`, `.claude/skills/`, the GEPs\nin `spec/proposals/` — except the specification documents.\n\n**The specification documents are CC-BY-4.0** ([`LICENSE-spec.md`](spec/LICENSE-spec.md),\nwhich lists them exactly): `spec/GEML-spec*` and `spec/in_geml_format/*`. There is one\nspecification; the profiles under `spec/profiles/` are application layers and are MIT.\nA spec is not software, so anyone may build a conformant\nimplementation without permission — and call it *conformant to GEML 1.0* once it\npasses the [conformance suite](geml-parser/test/conformance/).\n\n**Using the name.** You need no permission to implement GEML, to name an\nimplementation after the format (`geml-rs`, `pygeml`, a `geml` package on your\nlanguage's registry), or to state that your tool reads and writes GEML. Two\nrequests, neither of them a legal restriction: call an implementation *conformant to\nGEML 1.0* only once it passes the conformance suite, and don't imply that this\nproject wrote, endorses, or maintains it. Attribution for the specification text\nitself is what CC-BY-4.0 already asks for.\n",
  "bytes": 46355,
  "sha": "8e11e5b125b221fbcbe1267ecdc5865b5ae1b612e33594543b891324759de134",
  "repo_slug": "geml-spec/geml",
  "fonte": "repo",
  "truncated": false,
  "api": "https://agentalog.com/api/listings/plg_geml_spec_geml_9de64489/readme"
}