Turn what you've done before into a program. Use agents only for the judgment that remains.
# Release
Run the tests.
```bash exec
npm test
```
Choose the next version.
<Prompt>
Current version and release history:
<File path="package.json" />
<File path="CHANGELOG.md" />
What should the next version be: patch, minor, or major?
</Prompt>$ xmd README.md#Test/CompleteHeadings become entrypoints. Add frontmatter for typed arguments.
$ xmd AGENTS.md#Implement --props-issue=342Load the issue, files, and other known context before the agent starts instead of asking it to rediscover them.
The instructions become part of the program instead of something humans, CI, or agents have to remember to follow.
When you know what you want but don't know how to get there, use an agent. When you know how to get there, make it a program. Don't keep paying an agent to work out something you already know how to do.
Use the least autonomy that gets the job done.
Use an agent to figure it out.
Make it a program.
Keep only that part agentic.
One-off work can stay agentic. Repeated work that you know how to do can become an xmd workflow.
$ xmd plan "1. Read package.json and
CHANGELOG.md.
2. Ask an agent to recommend the
next semantic version and
explain why.
3. Validate the answer.
4. Ask me to approve it.
5. Write RELEASE.md." > release.md<File path="release.md">
<Plan>
1. Read package.json and
CHANGELOG.md.
2. Ask an agent to recommend the
next semantic version and
explain why.
3. Validate the answer.
4. Ask me to approve it.
5. Write RELEASE.md.
</Plan>
</File>xmd plan is command-line shorthand for <Plan>. It turns your instructions into an XMD program using the components available from xmd syntax.
Review it. Change it. Commit it. Then run the program instead of asking an agent to figure the workflow out again.
<Plan> is itself written in XMD. Read the planner source ↗
A Plan is text, so it composes. xmd plan writes the approved program to standard output and runs none of it. xmd run - takes a whole program from standard input — so the two are one command when you want no file in between.
Plan produces a program. Run executes a program from the host or CLI. Composition decides whether and when a planned program runs.
$ xmd plan "prepare the release" | xmd run -Known control flow stays in the program.
SafeParse decides whether the answer is valid, because that rule is already known. If branches on the result, Break ends the loop on success, and the retry prompt shows the same schema and asks only for a correction. max={2} is in the document, so the runtime knows when to stop trying.
<Loop max={2}>
<SafeParse schema={proposalSchema}
as="parsedProposal">
{proposalCandidate}
</SafeParse>
<If condition={parsedProposal.ok}>
<Break />
<Else>
<Prompt as="proposalCandidate"
throwOnError>
Correct your previous response
without changing its meaning.
Return only corrected JSON matching:
<Json value={proposalSchema} />
</Prompt>
</Else>
</If>
</Loop><Let value={{
type: "object",
required: ["bump"],
properties: {
bump: { enum: ["patch", "minor", "major"] }
}
}} as="schema" />
<Parse schema={schema} as="release">
<Prompt>
Which version bump is required?
Return JSON matching:
<Json value={schema} />
</Prompt>
</Parse>
<Elicit as="release" schema={{
type: "object",
required: ["confirmed"],
properties: { confirmed: {
type: "boolean" } }
}}>
Publish this release?
</Elicit>Whether the answer comes from an agent or a person, XMD validates it before the workflow continues.
Architect's result is captured as approvedPlan; Implementor receives it as plan. No hidden conversation and no file needed.
Memory lives only in this run and its nested scopes.
<Architect as="approvedPlan" />
<Implementor plan={approvedPlan} />Angle-bracket components resolve to Markdown files. <Implementor /> can be defined by Implementor.md, so your own components compose exactly like the ones shown here.
<TempDir>
<File path="notes/draft.md">
Draft
</File>
```sh exec
cat notes/draft.md
```
<Glob include={["**/*.md"]}
as="drafts" />
</TempDir>The nesting is the model. Components establish context for everything inside them, and the enclosing scope owns their lifetime.
Effects become execution history. Component expansions, evaluations, and exec operations are journaled automatically, without adding logging statements.
When the scope ends, XMD cleans up what it owns.
A retry must not repeat an external side effect, and a process can stop while work remains. So the run keeps a record of what already happened.
$ xmd run review.md --journal journal.jsonl--journal writes a JSONL trace of what ran and where it stopped. It is for this run, not retained workflow history.
$ xmd workflow start review.mdWorkflow mode is experimental. It keeps its own journal and effect records, separate from --journal.
$ xmd workflow resume <run-id>Resume reuses the effects the history records as completed and stops at the first unresolved boundary, instead of repeating an external effect.
If CI fails after some effects finish, those completions stay recorded. Fix the cause and resume; only the unresolved part needs attention.
The standalone binary needs no runtime. The same CLI also runs under Deno, Node, and Bun.
$ curl -fsSL https://executable.md/install.sh | sh
$ xmd README.md --helpRun the CLI directly from JSR.
$ deno run -A \
jsr:@executablemd/cli \
run README.mdInstall the CLI from npm, then run the same command.
$ npm install -g \
@executablemd/cli
$ xmd README.md --helpInstall the same npm package with Bun.
$ bun add -g \
@executablemd/cli
$ xmd README.md --helpStandalone binary · Deno · Node · Bun
Star the repository to follow releases.
Star on GitHub ↗