Headless Mode
Trigger Autohand Code from a Cloudflare Worker
Use a Worker as the public webhook and policy layer while Autohand Code runs on a VPS, Docker host, or Cloudflare Container.
Provider docs used
Cloudflare Workers can validate HTTP requests at the edge and forward to your runner. Store sensitive values as Worker secrets, not plaintext Wrangler variables. Keep the current docs open: Workers docs and Workers secrets.
Architecture
The Worker does not run the Autohand Code CLI. It validates inbound requests, checks tokens or signatures, and forwards approved jobs to a runner endpoint. The runner can be exposed through Cloudflare Tunnel, a private origin, or Cloudflare Containers.
Step 1: Create the Worker
npm create cloudflare@latest autohand-trigger
cd autohand-trigger
Step 2: Add the trigger code
export default {
async fetch(request, env) {
if (request.method !== "POST") {
return new Response("method not allowed", { status: 405 });
}
const auth = request.headers.get("authorization");
if (auth !== `Bearer ${env.PUBLIC_TRIGGER_TOKEN}`) {
return new Response("unauthorized", { status: 401 });
}
const body = await request.text();
const runnerResponse = await fetch(env.RUNNER_URL, {
method: "POST",
headers: {
authorization: `Bearer ${env.RUNNER_BACKEND_TOKEN}`,
"content-type": "application/json"
},
body
});
return new Response(await runnerResponse.text(), {
status: runnerResponse.status
});
}
};
Step 3: Store secrets
Cloudflare secrets are encrypted bindings attached to a Worker and available through env in the fetch handler. Use them for tokens and origin URLs that should not appear in source control.
wrangler secret put PUBLIC_TRIGGER_TOKEN
wrangler secret put RUNNER_BACKEND_TOKEN
wrangler secret put RUNNER_URL
For local development, put development-only values in .dev.vars and keep that file out of git.
Step 4: Deploy and trigger
wrangler deploy
curl -X POST https://autohand-trigger.example.workers.dev \
-H "Authorization: Bearer $PUBLIC_TRIGGER_TOKEN" \
-H "Content-Type: application/json" \
--data '{"repo":"your-org/your-repo","task":"review latest changes"}'
Step 5: Make the runner task-aware
Have the origin runner parse the JSON body and map allowed tasks to fixed Autohand Code prompts. Avoid letting arbitrary webhook payloads become raw shell commands.
const prompts = {
review: "Review the latest changes and summarize action items",
docs: "Update documentation for the latest CLI behavior"
};
const selected = prompts[payload.task] || prompts.review;
spawn("autohand", ["-p", selected, "--restricted", "--output-format", "stream-json"], {
cwd: repoDir,
env: process.env
});
Operations checklist
- Use Worker secrets for trigger and backend tokens.
- Validate request method, content type, signature, and allowed task names.
- Do not expose model provider keys to the Worker unless the Worker itself calls the model provider.
- Forward only normalized, allowlisted jobs to the runner.
- Use Cloudflare logs or a Tail Worker for debugging webhook traffic.