Docs
Install aired four ways. All paths are no-auth and free. Source on GitHub.
Skill
Adds a SKILL.md to your project so any AI agent (Claude Code, Cursor, Windsurf, Codex) discovers and uses aired automatically. This is the recommended path.
npx skills add progrmoiz/aired -g
-ginstalls the skill user-globally (under~/<agent>/skills/) so it works across all projects.- The skills CLI auto-detects which agent is running it and targets that agent.
- Powered by skills.sh.
CLI
Publishes a file or directory and prints the URL. Inlines CSS, JS, and images automatically. Pipe-friendly.
npx aired dashboard.html
Common flags
| Flag | Effect |
|---|---|
--ttl <dur> | Expiry: 1h, 24h, 7d, 30d |
--permanent | No expiry |
--pin <pin> | PIN-protect viewing |
-t, --title <title> | Custom page title |
--reads <n> | Auto-delete after N views |
--json | Print { url, update_token, expiresAt } |
Other commands
| Command | Description |
|---|---|
aired ./dir/ | Bundle a directory into one HTML |
aired update <id> <file> | Update an existing page |
aired delete <id> | Delete a page |
aired info <id> | Show page metadata |
aired tokens | List stored update tokens |
aired tokens prune | Drop tokens for expired pages |
aired doctor | Diagnostics (Node.js, API reachability, token store) |
The CLI persists update tokens locally via conf. On macOS that lands in ~/Library/Preferences/aired-nodejs/; on Linux ~/.config/aired-nodejs/.
MCP server
Streamable HTTP at https://aired.sh/mcp. Exposes a publish_html tool — your AI publishes artifacts directly through the MCP transport.
Claude Code
claude mcp add aired --transport http https://aired.sh/mcp
Cursor · .cursor/mcp.json
{
"mcpServers": {
"aired": { "url": "https://aired.sh/mcp" }
}
}
VS Code · .vscode/mcp.json
{
"servers": {
"aired": { "type": "http", "url": "https://aired.sh/mcp" }
}
}
Windsurf · ~/.codeium/windsurf/mcp_config.json
{
"mcpServers": {
"aired": { "serverUrl": "https://aired.sh/mcp" }
}
}
Codex · ~/.codex/config.toml
[mcp_servers.aired]
url = "https://aired.sh/mcp"
STDIO bridge (any client)
{
"mcpServers": {
"aired": {
"command": "npx",
"args": ["-y", "mcp-remote", "https://aired.sh/mcp"]
}
}
}
Tool: publish_html
Single tool. Inputs:
{
"html": "string, required, <= 2 MB",
"title": "string, optional",
"ttl": "number (seconds), optional",
"permanent": "boolean, optional",
"pin": "string, optional",
"reads": "number, optional, auto-delete after N views"
}
Returns { id, url, update_token, expiresAt }.
HTTP API
No SDK, no auth. POST your HTML and get a URL back.
curl -X POST https://aired.sh/api/publish \
-H "Content-Type: application/json" \
-d '{"html": "<h1>Hello</h1>"}'
Response:
{
"url": "https://aired.sh/p/a1b2c3d4e5",
"update_token": "tok_...",
"expiresAt": "2026-05-16T12:00:00.000Z"
}
Endpoints
| Method | Path | Description |
|---|---|---|
POST | /api/publish | Create a page. Returns { id, url, update_token, expiresAt }. Also updates if id + update_token are in the body. |
PUT | /api/pages/:id | Update by update_token in the JSON body. |
DELETE | /api/pages/:id | Delete by Authorization: Bearer <token> header. |
GET | /api/pages/:id | Public metadata: { id, title, size, readCount, expiresAt }. No auth. |
GET | /api/stats | Aggregate counts and recent publishes for the homepage feed. |
POST | /api/report | Body { id, reason }. Flag a page for abuse review. |
GET | /og/:id | Generated Open Graph image for the page. |
GET | /p/:id | Public viewer for a published page. |
POST | /p/:id/verify-pin | Submit a PIN to view a protected page. |
Request body — POST /api/publish
{
"html": "<!doctype html>...", // required, max 2 MB
"title": "My dashboard", // optional, auto-extracted from <title> if omitted
"ttl": 604800, // optional seconds (default 604800 = 7 days)
"permanent": false, // optional, true = no expiry (overrides ttl)
"pin": "1234", // optional, viewer must enter to view
"reads": 10, // optional, auto-delete after N views
// To update an existing page in one call, also include:
"id": "a1b2c3d4e5",
"update_token": "tok_..."
}
Request body — PUT /api/pages/:id
{
"html": "<!doctype html>...", // required
"title": "Optional new title", // optional
"update_token": "tok_..." // required, in body (not header)
}
Update via curl
curl -X PUT https://aired.sh/api/pages/a1b2c3d4e5 \
-H "Content-Type: application/json" \
-d '{"html":"<h1>v2</h1>","update_token":"tok_..."}'
Delete via curl
curl -X DELETE https://aired.sh/api/pages/a1b2c3d4e5 \
-H "Authorization: Bearer tok_..."
Auth
- Publishing is anonymous — no API key required.
- Every publish returns an
update_token. It is the only credential for that page. - PUT takes the token in the JSON body as
update_token. - DELETE takes the token as
Authorization: Bearer <token>header. - POST can act as update when
idandupdate_tokenare both in the body. - Lose the token and you can't mutate the page (you can still publish a fresh one).
Errors
All errors are JSON: { "error": "<message>" }.
| Status | When |
|---|---|
400 | Invalid JSON body, missing html, validation failed. |
401 | DELETE missing Authorization: Bearer header. |
403 | update_token does not match the page. |
404 | Page id does not exist (or expired). |
410 | Page exists but has expired. |
429 | Rate limit (5 publishes/hour/IP). Wait an hour. |
503 | Storage write limit reached. Retry shortly. |
PIN protection
Pass pin when publishing. The viewer at /p/:id shows a PIN form before serving the HTML.
Submit a PIN
curl -X POST https://aired.sh/p/a1b2c3d4e5/verify-pin \
-H "Content-Type: application/json" \
-d '{"pin":"1234"}'
On success, the server sets an HttpOnly, SameSite=Strict cookie scoped to /p/:id with a 1-hour TTL — subsequent loads are pass-through until it expires.
Limits
| Max artifact size | 2 MB |
| Publishes per hour per IP | 5 |
| Default TTL | 7 days |
| Max TTL | permanent |
Need more? aired is open source — run your own.
Self-hosting
aired runs as a single Cloudflare Worker with a KV namespace for metadata and an R2 bucket for HTML.
- Clone progrmoiz/aired.
- Create your own KV namespace and R2 bucket; update
apps/worker/wrangler.tomlwith the IDs. pnpm install && pnpm run build && cd apps/worker && pnpm wrangler deploy.- Point a custom domain or use the default
workers.devsubdomain.
Agent surfaces
For agents that want context before acting:
- /llms.txt — concise agent context
- /llms-full.txt — expanded reference with examples
- /index.md — markdown homepage
- /.well-known/agent.json — agent discovery manifest
- /.well-known/ai-plugin.json — OpenAI plugin manifest
- /mcp — MCP streamable HTTP endpoint