[!WARNING] Pre-release · under active development.
marxmlis in the0.0.xplaceholder phase — the name on crates.io is reserved, but the working API lands in0.1.0. APIs, types, and selector grammar will change without notice until then. Don't depend on it in production yet.
marxml lets you read and write XML-shaped tags embedded in markdown documents. Find them with CSS-style selectors, change them surgically, validate they're well-formed — without rewriting the prose around them.
Features
- Find tags with selectors.
task[id^="4."],phase > task,note:not([archived])— the CSS subset you already know. Compiled once viaSelector::parse, reused many. - Edit surgically. Mutators take
&strand returnStringby splicing into the source. Every byte you didn't touch comes back identical: prose, whitespace, comments, ordering. - Validate the shape. Required attributes, enum/regex constraints, child rules — declarative schema, structured errors with line numbers.
- No
unsafe. Workspace-wideunsafe_code = "forbid". Hand-rolled state-machine tokenizer, stack-based tree assembler,thiserrorerror types.
Why?
marxml started as plumbing for a workflow agent — plan and phase-planning documents (think GSD-style trackers) stored as markdown with task state inside XML tags. Agents needed to update those tags reliably: flip a status, append a note, mark a child done — without rewriting the surrounding prose or hallucinating new structure.
The general lesson: LLMs drift at the prose level but stay disciplined inside known XML tags. Scope the model's output to a tag, and the read/write boundary becomes deterministic again. marxml is the read/write layer for that boundary — selectors to find tags, byte-preserving mutation to change them, schema to verify what came back.
Install
MSRV: 1.75.
Quickstart
use ;
let src = r#"
<phase id="1" status="todo">
<task id="1.1" status="todo">do this</task>
<task id="1.2" status="done">finished</task>
</phase>
"#;
let doc = parse?;
let sel = parse?;
for task in doc.select
let updated = doc.update;
println!;
# Ok::
Docs
API reference on docs.rs. Long-form documentation lives in the repository:
- Rust reference — API surface, design notes, lints, MSRV.
- DSL reference — selectors, validation schema, cookbook recipes, formal grammar.
- Architecture — tokenizer state machine, mutation strategy, two-track API.
There's also an npm package of the same name — same API surface via napi-rs bindings, prebuilt binaries per platform.
License
Dual-licensed under either MIT or Apache 2.0 at your option.