| Needs | A free chorus.host account. You read one 6-digit code from your email; it works in a headless agent session with no browser login. |
| Doesn't need | A Cloudflare account, a browser OAuth step, or a credit card. |
| URL lifetime | Until you delete it. |
Can an agent deploy a serverless function with no account at all?
Checked 1 October 2026 against Cloudflare's claim-deployments docs and Netlify's AI quickstart.
| chorus.host Workers | Cloudflare npx wrangler@latest deploy --temporary | Netlify netlify deploy --allow-anonymous | Your own Cloudflare account | |
|---|---|---|---|---|
| Before the first deploy | A 6-digit email code, once | Nothing (Wrangler 4.102.0 or later; you accept Cloudflare's terms and a proof-of-work runs automatically) | Nothing | Sign up, then wrangler login or an API token |
| URL lifetime with no human step | Until deleted | 60 minutes unless a person claims it | 1 hour unless claimed | Until deleted |
| Server code | Yes, JavaScript modules; the CLI bundles TypeScript, npm packages and Hono | Yes | No: Netlify says "sites or apps that use serverless functions or edge functions will require an account" | Yes |
| Storage | None built in | KV, D1 (1 database, 100 MB), Durable Objects, Queues | n/a | All of it |
| Static files on the same origin | No; pair it with a site at <name>.chorus.host | Static Assets, 1,000 files of up to 5 MiB | Static only | Yes |
| Secrets | Yes, and they stay set across redeploys and rollbacks | Not in Cloudflare's list of supported resources | n/a | Yes |
| Cron triggers | Not yet | Not in the list | n/a | Yes |
Vercel's agent skill also has a no-auth fallback that returns a preview URL and a claim URL; how long an unclaimed deploy lasts isn't documented. here.now hosts static files only and its docs say not to use it for backend code: see chorus.host vs here.now.
Deploy a plain JavaScript Worker
1. Write the Worker
Save this as worker.js. It answers GET /api/hello with JSON that any web page can fetch.
export default {
async fetch(request, env) {
const url = new URL(request.url);
if (url.pathname === "/api/hello") {
return Response.json(
{ message: "hello from chorus.host", time: new Date().toISOString() },
{ headers: { "Access-Control-Allow-Origin": "*" } },
);
}
return new Response("Not found", { status: 404 });
},
};
2. Get an API key
Signing up and signing in are the same step. With the CLI:
curl -fsSL https://chorus.host/install.sh -o install-beacon.sh && sh install-beacon.sh
beacon login --email you@example.com
beacon login --email you@example.com --code 123456
The first login emails you a 6-digit code; the second saves your key to ~/.config/beacon/config.json. Without the CLI, see sign in from a headless agent.
3. Deploy
From the folder that holds worker.js:
beacon deploy --slug my-api --pretty
Or with two HTTP calls, one to create the Worker and one to upload the code:
curl -sS https://chorus.host/v1/workers \
-H "Authorization: Bearer $BEACON_API_KEY" \
-H "Content-Type: application/json" \
-d '{"slug":"my-api"}'
curl -sS https://chorus.host/v1/workers/my-api/deploy \
-H "Authorization: Bearer $BEACON_API_KEY" \
-F 'metadata={"entryPoint":"worker.js","compatibilityDate":"2026-09-01"}' \
-F "file=@worker.js"
Then try it:
curl -sS https://my-api.worker.chorus.host/api/hello
Redeploy the same way after every change. The URL stays the same.
Deploy a Hono app
curl -fsSL https://chorus.host/install.sh -o install-beacon.sh && sh install-beacon.sh
beacon init my-api --template hono
cd my-api && npm install && npm i -D esbuild
beacon login --email you@example.com # then: --code 123456
beacon deploy --pretty
The template's index.ts is a normal Hono app. To let a web page on another host call it, add CORS:
import { Hono } from 'hono'
import { cors } from 'hono/cors'
const app = new Hono()
app.use('/api/*', cors())
app.get('/api/hello', (c) => c.json({ message: 'Hello from chorus.host!' }))
export default app
beacon deploy bundles index.ts and its npm imports with esbuild and serves it at https://my-api.worker.chorus.host. Secrets are c.env.NAME. Claude Code, Codex and Cursor can run these commands as they are.
Sign in from a headless agent
No browser window, OAuth redirect or token page. The agent sends a code to the user's email, asks the user for it, and gets an API key:
curl -sS https://chorus.host/v1/auth/send-otp \
-H "Content-Type: application/json" -d '{"email":"you@example.com"}'
# the user reads the 6-digit code from the email (valid for 10 minutes)
curl -sS https://chorus.host/v1/auth/verify-otp \
-H "Content-Type: application/json" -d '{"email":"you@example.com","code":"123456"}'
# {"apiKey":"chk_...","account":{...}}
Keep the key in BEACON_API_KEY (the CLI also reads ~/.config/beacon/config.json). Five wrong tries cancel a code.
Secrets
printf '%s' "sk-your-token" | beacon secret set UPSTREAM_TOKEN - --slug my-api
curl -sS -X PUT https://chorus.host/v1/workers/my-api/secrets/UPSTREAM_TOKEN \
-H "Authorization: Bearer $BEACON_API_KEY" \
-H "Content-Type: application/json" \
-d '{"value":"sk-your-token"}'
Your code reads it as env.UPSTREAM_TOKEN. Set secrets after the first deploy; they stay set across redeploys and rollbacks. Names use capital letters, digits and underscores. chorus.host stores only the names; the values are kept by Cloudflare and can't be read back.
Watch the logs
beacon logs my-api
This streams one JSON line per request, including anything your code passes to console.log. Over HTTP, GET /v1/workers/my-api/logs/tail returns a WebSocket URL to read the same stream from.
Give a static site an API
Option A: two hosts. Publish the site to my-app.chorus.host and the Worker to my-app-api.worker.chorus.host (a site and a Worker can't share a name). The page calls the API with fetch, and the Worker sends Access-Control-Allow-Origin, as the example in step 1 does:
const res = await fetch("https://my-app-api.worker.chorus.host/api/hello");
const data = await res.json();
beacon init my-app --template fullstack scaffolds both halves: a React frontend in frontend/ for my-app.chorus.host and a Hono API in backend/ for my-app-api.worker.chorus.host.
Option B: one origin, no CORS. For a small page, let the Worker serve the HTML too:
const page = `<!doctype html>
<title>Counter</title>
<p id="out">Loading…</p>
<script>
fetch("/api/hello").then((r) => r.json()).then((d) => (out.textContent = d.message));
</script>`;
export default {
async fetch(request) {
const { pathname } = new URL(request.url);
if (pathname.startsWith("/api/")) {
return Response.json({ message: "hello from the same origin" });
}
return new Response(page, { headers: { "Content-Type": "text/html; charset=utf-8" } });
},
};
Roll back
curl -sS -X POST https://chorus.host/v1/workers/my-api/rollback \
-H "Authorization: Bearer $BEACON_API_KEY"
This puts the previous deploy back. To pick an older one, send {"deploymentId":"..."} with an id from GET /v1/workers/my-api/deployments.
Free tier and limits
Free, with no credit card. These are the limits today:
| Limit | Value |
|---|---|
| Code per deploy | 3 MB total, up to 100 files |
| Language | JavaScript ES modules. For npm imports or TypeScript, the CLI bundles with esbuild or runs your npm run build. |
| Secret values | 5 KB each |
| New Workers | 10 per hour |
| Deploys and rollbacks | 20 per hour |
| Log sessions | 5 per hour |
| Scheduled (cron) runs | Not available yet |
| Storage (KV, Durable Objects) | Not available. Keep data in a service you call with fetch. |
| Outbound requests | Public HTTP and HTTPS only. Private and internal addresses are blocked. |
| Without an account | Not available. Workers need an API key; static sites don't. |
Receiving webhooks? Follow the GitHub and Stripe webhook receiver guide.
Questions
Can my agent add an API backend to a static site?
Yes. Publish the site to <name>.chorus.host and deploy the API as a Worker at <name>-api.worker.chorus.host, then call it from the page with fetch, sending an Access-Control-Allow-Origin header from the Worker. Or serve the page from the Worker itself and skip CORS.
Can my agent deploy a webhook endpoint?
Yes. A Worker gets a public HTTPS URL as soon as it deploys, so it can receive webhooks from GitHub, Stripe or any other service. Keep the signing secret as a Worker secret. Step by step: deploy a GitHub or Stripe webhook receiver.
Does it support TypeScript and npm packages?
With the CLI, yes: if your entry file imports packages, beacon deploy bundles it with esbuild (npm i -D esbuild), or runs your npm run build if package.json has one. The HTTP API takes JavaScript modules as they are, so bundle TypeScript before uploading.
Can I deploy a Hono app from Claude Code or Codex to a public URL?
Yes. beacon init my-api --template hono, npm install, then beacon deploy. The agent signs in with a code from your email, so no browser is needed, and the app is live at https://my-api.worker.chorus.host.
How long does a chorus.host Worker URL stay up?
Until you delete it. There's no claim window and no expiry for Workers.
Is chorus.host Workers free?
Yes. There are no paid plans and no credit card. The limits above apply, including 20 deploys an hour.
Do I need a Cloudflare account?
No. chorus.host runs the Worker on its own Cloudflare account. If you only need it for an hour, Cloudflare's wrangler deploy --temporary also works without an account; it's deleted after 60 minutes unless someone claims it.