Skip to content

Why markdown?

Every API testing tool faces the same decision: how do you store the collection of requests? Postman picked JSON, Insomnia picked YAML, JetBrains picked a custom .http format, Bruno picked their own DSL. httui picked plain markdown. This page explains why.

PropertyWhat it means in practice
Readable in any editorOpen the runbook in vim, VS Code, GitHub, Obsidian, Notion — it renders. No app dependency to read the spec.
Diffable in gitPull request review for runbooks. Side-by-side comparison. Code-review the API spec.
Searchable everywheregrep, rg, GitHub code search, Spotlight, Obsidian — your runbooks are findable without an indexing service.
Prose-and-code nativeMarkdown was designed for “explanation + code”. Headings, lists, links, blockquotes — all natural ways to document around the requests.
Renders on GitHubPush the vault, browse it as a wiki on GitHub. The fenced code blocks (http, db-*) appear as code blocks with syntax highlighting — degraded but readable.
No format lock-inIf httui dies, you still have .md files. The requests are HTTP-message text, the SQL is SQL. You can run them by hand.

A Postman collection is a JSON file with a deep tree of folders, requests, scripts, environments, pre-request scripts, tests.

ProCon
Rich GUI for editingUnreadable as text — a 200-request collection is 50,000 lines of JSON
Sharable via Postman cloudDiffs are useless (JSON moves around per save)
Pre/post scripts in JavaScriptLocked to the Postman runtime
Workspaces, team accountsNot your data — lives in Postman’s cloud unless you self-host

Similar shape to Postman. YAML is more readable than JSON but still tool-specific. Insomnia Sync moves the data to the cloud or a git repo of YAML.

JetBrains picked the right idea — text-first, one file per collection, requests written as HTTP messages:

### Get user
GET https://api.example.com/users/42
Authorization: Bearer {{token}}

Pros: readable in any editor, lives in your codebase, runs inside IntelliJ. Cons: only IntelliJ executes it; no SQL story; no narrative-around-the-request story (everything is comments prefixed with ### or //).

Bruno is closer in spirit to httui — text-first, lives in git. Its chosen format is a custom DSL (.bru files). Still readable, still git-friendly. But it’s a new format your editor doesn’t know about, and there’s no prose-around-code mode.

Why markdown specifically (not just “text”)

Section titled “Why markdown specifically (not just “text”)”

httui could have invented its own format like Bruno did. The bet on markdown is that the narrative half matters as much as the executable half. A runbook isn’t a list of requests — it’s an explanation of a flow, with the requests embedded in the explanation:

# Refund a payment
When a customer charges back, we need to:
1. Find the original payment by external reference
2. Verify it's in `captured` status (refunds against `pending` fail)
3. Issue the refund
## 1. Find the payment
\`\`\`http alias=find
GET {{API}}/payments?external_ref={{REF}}
\`\`\`
The response should contain exactly one payment...

In markdown, the structure (#, ##, lists, paragraphs) is part of the spec, not metadata around a request. Open this file in any markdown viewer and you have a real document.

In a .http file, that text would all be ### comments, lost on any non-JetBrains tool. In Postman, it’d be a “description” field nobody reads.

The price of markdown is that the executable bits live inside fenced code blocks with a special language:

```http alias=login
POST /auth/login
```
```db-staging
SELECT * FROM users
```

That syntax is markdown-valid — GitHub, Obsidian, etc, render it as a code block. httui’s editor adds the runtime layer on top (toolbar, run button, response panel) without changing the underlying text.

The convention is a small cost — you learn the fence languages once (http, db-<conn>, diff) and you’re done. The payoff: any markdown tool can show your runbook.

The httui editor is the GUI. You don’t write the HTTP message by hand if you don’t want to — the form mode toggle in each HTTP block gives you Postman-style Params/Headers/Body tables. The toggle is round-trip safe: you edit in form, serialize as canonical HTTP-message, edit in raw, switch back to form — no loss.

The difference: the data underneath is still a .md file you can read in vim.

What if I have a Postman collection today?

Section titled “What if I have a Postman collection today?”

There’s an import path (planned, not shipped at the time of writing): point httui at a Postman JSON, get a runbooks/ folder with one .md per request group + a connections.toml per environment. Imperfect (Postman’s pre/post scripts don’t map 1:1), but unblocks migration.

ChoiceWhy
Markdown over JSONReadable as text, diffable in git, renders everywhere
Markdown over YAMLSame benefits + native prose-around-code
Markdown over .httpSame text-first benefit + the narrative half
Markdown over Bruno’s DSLSame git-first benefit + every editor already knows the format

The bet: runbook = doc + tool, and the doc half is at least as important as the tool half. Markdown lets both halves be first-class.