diff --git a/README.md b/README.md
index 6d81a36..92dae3d 100644
--- a/README.md
+++ b/README.md
@@ -2,9 +2,9 @@
**Don't meet. Meld.**
-meld puts the context on a URL so neither side has to paste the block. Then the URL dies.
+meld puts the context on a capability URL so neither side has to paste the block. The URL is the shared bearer for the exchange. It dissolves on the timer you choose.
-One URL. Both sides add context. When it resolves, the host serves 410 and the meld is gone. No history, no threads, no accounts.
+One URL. Both sides add context. Pick 3 minutes, 1 hour, or 1 day. When that timer ends, the host serves 410 and the bridge is gone. No history, no threads, no accounts.
## Live
@@ -30,7 +30,7 @@ https://meld.mergeinc.workers.dev
# Create a meld — get one share URL
curl -X POST https://meld.mergeinc.workers.dev/api/melds \
-H "Content-Type: application/json" \
- -d '{"context": "Auth flow: OAuth2+PKCE, JWT tokens, refresh rotation"}'
+ -d '{"context": "Auth flow: OAuth2+PKCE, JWT tokens, refresh rotation", "ttl": "1hr"}'
# → {"code": "abc123", "url": "https://…/m/abc123", ...}
# Party B (human or agent) resolves:
@@ -49,7 +49,7 @@ curl https://meld.mergeinc.workers.dev/api/melds/abc123
## Trust model
-Capability URL + TTL. The host is readable while live, and anyone with the link can read it. Not for secrets/credentials/regulated. The meld dissolves on TTL. Mint-next means: create another meld URL and put it in the reply. Full statement: [TRUST.md](TRUST.md).
+Capability URL + TTL. The host is readable while live, and anyone with the link can read it. Not for secrets/credentials/regulated. Create requires a bridge time: `3m`, `1hr`, or `1d`. The server enforces that TTL. Full statement: [TRUST.md](TRUST.md).
## API
@@ -64,4 +64,4 @@ Capability URL + TTL. The host is readable while live, and anyone with the link
## Pricing
-Humans are free in the browser. Agents get 3 creates/IP/hour, then can use `POST /v1/keys` or wait. No subscriptions. Playbooks: https://meld.mergeinc.workers.dev/recipes.md.
+Pilot bridges are free. No payment is required. Create requires `ttl`: `3m` (3 minutes), `1hr` (1 hour), or `1d` (1 day). Per-minute abuse limits still apply. Playbooks: https://meld.mergeinc.workers.dev/recipes.md.
diff --git a/TRUST.md b/TRUST.md
index 111938b..bb763be 100644
--- a/TRUST.md
+++ b/TRUST.md
@@ -1,10 +1,10 @@
# meld — trust model
-- **Capability URL + TTL.** The URL grants access while the meld is live.
-- **Host-readable while live.**
-- **Anyone with the link can read it.**
-- **Not for secrets/credentials/regulated.**
-- **Dissolves on TTL.** Unresolved melds last up to one hour; resolved melds about ten minutes.
-- **Mint-next.** Create another meld URL and put it in the reply.
+- Capability URL + TTL: the URL grants access while the meld is live.
+- Host-readable while live.
+- Anyone with the link can read it.
+- Not for secrets/credentials/regulated.
+- Dissolves on the TTL chosen at create: 3 minutes (`3m`), 1 hour (`1hr`), or 1 day (`1d`).
+- Bridge time is required: 3m, 1hr, or 1d. The server enforces that TTL. There is no default.
-meld is an ephemeral context handoff, not a vault. The host stores ordinary context only for the live TTL, then deletes the meld. There are no accounts or long-term content archives. Use meld for ordinary, disposable handoffs only.
+The host stores ordinary context for the live TTL and deletes the meld after expiry. There are no accounts or long-term content archives. Rate-limit identity is IP-based. Use meld for ordinary, disposable handoffs only.
diff --git a/deploy/AGENTS-root.md b/deploy/AGENTS-root.md
index 1326454..000d272 100644
--- a/deploy/AGENTS-root.md
+++ b/deploy/AGENTS-root.md
@@ -1,17 +1,39 @@
# AGENTS.md — working with meld
-meld is a capability URL + TTL for a one-time context handoff. The host is readable while live; anyone with the link can read it. Not for secrets/credentials/regulated. The meld dissolves on TTL.
+meld puts context on a capability URL with a TTL. The host is readable while live, and anyone with the link can read it. After TTL, the meld dissolves and the host serves 410. Not for secrets, credentials, or regulated data.
-## Flow
+## Quick start
```bash
+# Create; share url. Keep owner_token only for the legacy /result read.
curl -s https://meld.mergeinc.workers.dev/api/melds \
-H 'content-type: application/json' -H 'X-Meld-Client: agent' \
- -d '{"context":"..."}'
-# share .url, then resolve with the returned .code
+ -d '{"context":"...","ttl":"1hr"}'
+# -> {code, url, owner_url, owner_token, expires_at}
+
+# Resolve from the link.
curl -s https://meld.mergeinc.workers.dev/api/melds/{code}/resolve \
-H 'content-type: application/json' -d '{"context":"..."}'
+
+# Anyone holding the capability URL can read the live contexts.
curl -s https://meld.mergeinc.workers.dev/api/melds/{code}
```
-Mint-next means: create another meld URL and put it in the reply. MCP: https://meld.mergeinc.workers.dev/mcp
+## Locked claims
+
+- Capability URL + TTL.
+- Host-readable while live.
+- Anyone with the link can read it.
+- Not for secrets/credentials/regulated.
+- Dissolves on TTL.
+- Bridge time is required: 3m, 1hr, or 1d. The server enforces that TTL. There is no default.
+
+## Agent-to-agent
+
+Create, send the share URL, resolve once, then read the URL. Pass `ttl` as `3m`, `1hr`, or `1d`. There is no default. MCP: https://meld.mergeinc.workers.dev/mcp
+
+## Limits and docs
+
+Pilot bridges are free. Create requires `ttl`: `3m`, `1hr`, or `1d`. Per-minute limits apply to everyone. Errors: 400, 403 PIN, 404, 409, 410, 429.
+
+Machine-readable docs: /llms.txt · /agents.md · /recipes.md · /openapi.json · /trust.md
diff --git a/deploy/agents_content.py b/deploy/agents_content.py
index f4493e1..851a6d4 100644
--- a/deploy/agents_content.py
+++ b/deploy/agents_content.py
@@ -1,35 +1,4 @@
from html import escape
-AGENTS_MD = '''# meld — agent API
-
-meld is a capability URL + TTL for one context exchange. The host is readable while live; anyone with the link can read it. Not for secrets/credentials/regulated. The meld dissolves on TTL.
-
-## Create -> resolve -> read
-
-```bash
-curl -s https://meld.mergeinc.workers.dev/api/melds \\
- -H 'content-type: application/json' -H 'X-Meld-Client: agent' \\
- -d '{"context":"What architecture fits 10M users?"}'
-# share the returned .url and note .code
-curl -s https://meld.mergeinc.workers.dev/api/melds/{code}/resolve \\
- -H 'content-type: application/json' \\
- -d '{"context":"Event-driven services plus a queue."}'
-curl -s https://meld.mergeinc.workers.dev/api/melds/{code}
-```
-
-The capability URL is the access. `owner_token` and `/result` remain as a legacy owner-read path. Resolve is one answer; identical retries are idempotent and a conflicting answer returns 409.
-
-## Mint-next
-
-If more context is needed, mint-next means: create another meld URL and put it in the reply.
-
-```bash
-next=$(curl -s https://meld.mergeinc.workers.dev/api/melds \\
- -H 'content-type: application/json' -H 'X-Meld-Client: agent' \\
- -d '{"context":"Follow-up: ..."}')
-# Put next.url in the reply.
-```
-
-MCP remote: https://meld.mergeinc.workers.dev/mcp · Recipes: /recipes.md · OpenAPI: /openapi.json
-'''
-AGENTS_HTML = '
meld — agent API
'+escape(AGENTS_MD)+'
'
+AGENTS_MD = '# meld — agent API\n\nmeld is a capability URL + TTL for one context exchange. Host-readable while live; anyone with the link can read it. Not for secrets/credentials/regulated. The meld dissolves on TTL.\n\n## Create -> resolve -> read\n\n```bash\ncurl -s https://meld.mergeinc.workers.dev/api/melds \\\n -H \'content-type: application/json\' -H \'X-Meld-Client: agent\' \\\n -d \'{"context":"What architecture fits 10M users?","ttl":"1hr"}\'\n# share the returned .url and note .code\ncurl -s https://meld.mergeinc.workers.dev/api/melds/{code}/resolve \\\n -H \'content-type: application/json\' \\\n -d \'{"context":"Event-driven services plus a queue."}\'\ncurl -s https://meld.mergeinc.workers.dev/api/melds/{code}\n```\n\nThe capability URL is the access. `owner_token` and `/result` remain as a legacy owner-read path. Resolve is one answer; identical retries are idempotent and a conflicting answer returns 409.\n\n## Bridge time\n\n`ttl` is required on create and must be `3m`, `1hr`, or `1d`. The server enforces that lifetime. There is no default. Pilot creates are free.\n\nMCP remote: https://meld.mergeinc.workers.dev/mcp · Recipes: /recipes.md · OpenAPI: /openapi.json\n'
+AGENTS_HTML = 'meld — agent API
\ No newline at end of file
+const API = location.origin;
+let code = null;
+let picked = "";
+let watching = false;
+let watchTimer = null;
+// One read every 10s is 6/min, under the 60/min view limit. No new auth.
+const esc = s => { const d = document.createElement("div"); d.textContent = s ?? ""; return d.innerHTML; };
+async function api(method, path, body, headers = {}) {
+ const r = await fetch(API + path, {
+ method,
+ headers: { "Content-Type": "application/json", "X-Meld-Client": "human", ...headers },
+ body: body ? JSON.stringify(body) : undefined
+ });
+ const d = await r.json().catch(() => ({ detail: r.statusText }));
+ if (!r.ok) throw Error(d.detail || String(r.status));
+ return d;
+}
+function setSteps(active) {
+ document.getElementById("creator-rail").classList.remove("off");
+ document.getElementById("receiver-rail").classList.add("off");
+ for (let i = 1; i <= 4; i++) {
+ const el = document.getElementById("s" + i);
+ el.classList.toggle("on", i === active);
+ el.classList.toggle("done", i < active || active > 4);
+ }
+}
+function setReceiverJob(active) {
+ document.getElementById("creator-rail").classList.add("off");
+ document.getElementById("receiver-rail").classList.remove("off");
+ for (let i = 1; i <= 3; i++) {
+ const el = document.getElementById("r" + i);
+ el.classList.toggle("on", i === active);
+ el.classList.toggle("done", i < active || active > 3);
+ }
+}
+function trustBlock(forOpener) {
+ const last = forOpener
+ ? "The bridge dissolves when its timer runs out. Then the link is gone."
+ : "The bridge dissolves when the timer you choose runs out. Then the link is gone.";
+ return '
Read this before you put text on the bridge.
'
+ + "
The link is the bearer. Anyone who has it can read the exchange while it is live.
"
+ + "
The host can read it while it is live.
"
+ + "
Not for secrets, credentials, or regulated data.
"
+ + "
" + last + "
"
+ + "
";
+}
+function needsBlock() {
+ return '
'
+ + '
The handoffThe working context the other person or agent should read.
'
+ + '
A bridge timeOnly three: 3 minutes, 1 hour, or 1 day.
'
+ + '
The capability URLSharing the link is what lets the other side in.
'
+ + '
A reply on that linkThey open it, answer, and you read the reply here.
Hand one piece of working context to another person or agent. You get a capability URL. That URL is the shared bearer for the exchange, and it dies on the timer you pick.
'
+ + needsBlock()
+ + ''
+ + ''
+ + '
This text is what they see when they open the link. Leave out secrets.
'
+ + ''
+ + '
'
+ + timeBtn("3m", "3 minutes", "For a quick handoff. Dissolves in 3 minutes.")
+ + timeBtn("1hr", "1 hour", "For a working session. Dissolves in 1 hour.")
+ + timeBtn("1d", "1 day", "For a handoff that can wait. Dissolves in 1 day.")
+ + "
"
+ + '
Choose one. Nothing is selected until you do. There is no other duration.