dsh-web
zhu1090093659/dsh-webDeepSeek Harness(DSH)Web 插件聚合生态包 · 一切皆插件,创意工坊分发(dsh-market.com)
One format, two readers. People and AI agents now co-write the same document. Legible for people; addressable, verifiable, and versioned for machines. GEML is plain text — organized by one typed block for everything, remembered by a .gemlhistory sidecar.
*English | 中文*
GEML is a lightweight markup language with uniform, addressable blocks and standard verbs. Easy for humans to read, safe for agents to mutate. 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
geml history save README.md -m 'tighten intro' # a revision into README.md.gemlhistory, beside the fileOnly that section enters the agent’s context — a couple of KB, not the whole file, however long it grows. And every save is a revision you can read back or roll back, one block or the whole file.
▶ Try it in the Playground — no install, nothing to read first.
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 JSONFor 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 blockBlocks 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 ·
#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 --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}$$