[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"project-81640":3},{"id":4,"name":5,"fullName":6,"owner":7,"repo":5,"description":8,"homepage":9,"htmlUrl":10,"language":11,"languages":10,"totalLinesOfCode":10,"stars":12,"forks":13,"watchers":14,"openIssues":15,"contributorsCount":13,"subscribersCount":13,"size":13,"stars1d":13,"stars7d":16,"stars30d":16,"stars90d":13,"forks30d":13,"starsTrendScore":13,"compositeScore":13,"rankGlobal":10,"rankLanguage":10,"license":17,"archived":18,"fork":18,"defaultBranch":19,"hasWiki":20,"hasPages":18,"topics":21,"createdAt":10,"pushedAt":10,"updatedAt":29,"readmeContent":30,"aiSummary":31,"trendingCount":13,"starSnapshotCount":13,"syncStatus":32,"lastSyncTime":33,"discoverSource":34},81640,"flue-snippets","acoyfellow\u002Fflue-snippets","acoyfellow","Real, runnable Flue agents on Cloudflare. Examples teach one product at a time; recipes compose. Every snippet ships an E2E test that deploys an ephemeral Worker, asserts, and tears it down.","https:\u002F\u002Fflue.coey.dev\u002F",null,"TypeScript",22,0,21,5,1,"MIT License",false,"main",true,[22,23,24,25,26,27,28],"ai-agents","alchemy","cloudflare","cloudflare-workers","durable-objects","flue","workers-ai","2026-06-12 02:04:17","# flue-snippets\n\nReal, runnable [Flue](https:\u002F\u002Fflueframework.com) agents on\n[Cloudflare](https:\u002F\u002Fdevelopers.cloudflare.com\u002Fworkers\u002F). Every snippet\ndeploys a real ephemeral Worker, exercises it against live services,\nthen tears it down. No mocks.\n\n[![ci](https:\u002F\u002Fgithub.com\u002Facoyfellow\u002Fflue-snippets\u002Factions\u002Fworkflows\u002Fe2e.yml\u002Fbadge.svg)](https:\u002F\u002Fgithub.com\u002Facoyfellow\u002Fflue-snippets\u002Factions\u002Fworkflows\u002Fe2e.yml)\n\n> Demo site: [flue.coey.dev](https:\u002F\u002Fflue.coey.dev), a guided tour of Flue on Cloudflare, auto-generated from this repo.\n\n```text\nexamples\u002F   one CF product per folder, smallest Flue agent that uses it\nrecipes\u002F    compositions, Flue + multiple primitives + receipts\u002Fproofs\ntemplates\u002F  forkable starters, production-shape, fork-and-ship\n```\n\n## Run one\n\n```sh\ngit clone https:\u002F\u002Fgithub.com\u002Facoyfellow\u002Fflue-snippets\ncd flue-snippets\nbun install         # or: npm install\n\n# https:\u002F\u002Fdash.cloudflare.com\u002Fprofile\u002Fapi-tokens, Workers Scripts:Edit + Workers AI:Read\nexport CLOUDFLARE_API_TOKEN=...\nexport CLOUDFLARE_ACCOUNT_ID=...\n\nbun ex:workers-ai   # or: npm run ex:workers-ai\n```\n\n~60 seconds: deploy, run, assert, destroy. ~$0.0001 in Workers AI usage.\n\nThe agent it just ran:\n\n```ts\n\u002F\u002F examples\u002Fworkers-ai\u002Fworkers-ai.ts\nimport type { FlueContext } from '@flue\u002Fsdk\u002Fclient';\n\nexport const triggers = { webhook: true };\n\nexport default async function ({ payload, env }: FlueContext) {\n  const out = await env.AI.run('@cf\u002Fmoonshotai\u002Fkimi-k2.6', {\n    prompt: payload.message ?? 'Say hi.',\n  });\n  return { answer: out.response };\n}\n```\n\n## Examples\n\nOne Flue agent, one Cloudflare binding.\n\n| Example | Cloudflare product |\n|---|---|\n| [workers-ai](examples\u002Fworkers-ai) | [Workers AI](https:\u002F\u002Fdevelopers.cloudflare.com\u002Fworkers-ai\u002F) |\n| [effect-hello](examples\u002Feffect-hello) | [Workers AI](https:\u002F\u002Fdevelopers.cloudflare.com\u002Fworkers-ai\u002F) + [Effect v4](https:\u002F\u002Fgithub.com\u002FEffect-TS\u002Feffect-smol) (smallest Flue agent whose body is an Effect program) |\n| [kv](examples\u002Fkv) | [Workers KV](https:\u002F\u002Fdevelopers.cloudflare.com\u002Fworkers\u002Fruntime-apis\u002Fkv\u002F) |\n| [r2](examples\u002Fr2) | [R2](https:\u002F\u002Fdevelopers.cloudflare.com\u002Fr2\u002F) |\n| [d1](examples\u002Fd1) | [D1](https:\u002F\u002Fdevelopers.cloudflare.com\u002Fd1\u002F) |\n| [durable-objects](examples\u002Fdurable-objects) | [Durable Objects](https:\u002F\u002Fdevelopers.cloudflare.com\u002Fdurable-objects\u002F) |\n| [ai-gateway](examples\u002Fai-gateway) | [AI Gateway](https:\u002F\u002Fdevelopers.cloudflare.com\u002Fai-gateway\u002F) |\n| [queues](examples\u002Fqueues) | [Queues](https:\u002F\u002Fdevelopers.cloudflare.com\u002Fqueues\u002F) |\n| [vectorize](examples\u002Fvectorize) | [Vectorize](https:\u002F\u002Fdevelopers.cloudflare.com\u002Fvectorize\u002F) |\n| [browser-rendering](examples\u002Fbrowser-rendering) | [Browser Rendering](https:\u002F\u002Fdevelopers.cloudflare.com\u002Fbrowser-rendering\u002F) |\n| [worker-loader](examples\u002Fworker-loader) | [Dynamic Workers](https:\u002F\u002Fdevelopers.cloudflare.com\u002Fdynamic-workers\u002F) |\n| [hyperdrive](examples\u002Fhyperdrive) | [Hyperdrive](https:\u002F\u002Fdevelopers.cloudflare.com\u002Fhyperdrive\u002F) |\n| [email-workers](examples\u002Femail-workers) | [Email Service](https:\u002F\u002Fdevelopers.cloudflare.com\u002Femail-service\u002F) |\n\n## Recipes\n\nFlue + a Cloudflare primitive + an open-source receipt\u002Fproof layer\n([`@acoyfellow\u002Flab`](https:\u002F\u002Fwww.npmjs.com\u002Fpackage\u002F@acoyfellow\u002Flab),\n[`gateproof`](https:\u002F\u002Fgateproof.dev)).\n\n| Recipe | Composes |\n|---|---|\n| [lab-receipt](recipes\u002Flab-receipt) | Workers AI + lab |\n| [do-session](recipes\u002Fdo-session) | Durable Objects |\n| [do-governor](recipes\u002Fdo-governor) | Durable Objects |\n| [lab-checkpoint](recipes\u002Flab-checkpoint) | Durable Objects + lab |\n| [ai-gateway](recipes\u002Fai-gateway) | AI Gateway + Workers AI |\n| [gateway-lab](recipes\u002Fgateway-lab) | AI Gateway + Workers AI + lab |\n| [github-triage](recipes\u002Fgithub-triage) | Workers AI + Flue skills (structured output) |\n| [chat-thinking](recipes\u002Fchat-thinking) | Flue + [Cloudflare Think](https:\u002F\u002Fdevelopers.cloudflare.com\u002Fagents\u002Fapi-reference\u002Fthink\u002F) (DO chat agent) |\n| [virtual-sandbox](recipes\u002Fvirtual-sandbox) | Flue virtual sandbox + R2 |\n| [mcp-client](recipes\u002Fmcp-client) | Flue + co-hosted MCP server (Workers) |\n| [dynamic-workflow](recipes\u002Fdynamic-workflow) | Durable Objects + [Workflows](https:\u002F\u002Fdevelopers.cloudflare.com\u002Fworkflows\u002F) |\n\nEach recipe's README explains what it composes, what it proves, how to run it.\n\n## Local scripts\n\n```sh\nbun ex:\u003Cname>    # examples\u002F\u003Cname>\u002Frun-e2e.sh\nbun rx:\u003Cname>    # recipes\u002F\u003Cname>\u002Frun-e2e.sh\nbun tpl:\u003Cname>   # templates\u002F\u003Cname>\u002Frun-e2e.sh\n```\n\nSee [`package.json`](package.json) for the full list.\n\n## Refresh dependencies\n\n```sh\nbun run update\n```\n\nThat repeatable maintenance command runs `bun update` in the repo and in\n[`site\u002F`](site), refreshes the homepage's visible “Last dependency refresh”\ntimestamp when Bun bumps package manifest versions, then runs the site production\nbuild. If the Flue CLI\u002Fruntime or a dependency used by a snippet changes shape,\nalso update the affected example\u002Frecipe\u002Ftemplate and run its live E2E (`bun\nex:\u003Cname>`, `bun rx:\u003Cname>`, or `bun tpl:\u003Cname>`) before shipping.\n\n## End-to-end flow\n\nEvery `run-e2e.sh` does the same five things:\n\n1. `flue build --target cloudflare`, emits the Worker entrypoint + per-agent DO classes.\n2. `alchemy deploy`, declares the Worker, bindings, and vars; bundles; prints the URL.\n3. Warmup, polls `\u002Fhealth`, then POSTs `\u002Fagents\u002F\u003Cname>\u002Fwarmup` with retries (absorbs route propagation + Workers AI cold start).\n4. Assert, examples curl-and-grep; recipes run a `gateproof.plan.ts` with a `probe.ts` (pure `fetch` + JSON).\n5. `alchemy destroy`, tears the Worker, bindings, and state down. Trapped on `EXIT INT TERM`.\n\nWrangler is not invoked. [alchemy](https:\u002F\u002Falchemy.run) owns the resource graph; Flue emits the entrypoint module that alchemy bundles.\n\n## CI\n\n[`.github\u002Fworkflows\u002Fe2e.yml`](.github\u002Fworkflows\u002Fe2e.yml) is `workflow_dispatch`-only. From the [Actions tab](https:\u002F\u002Fgithub.com\u002Facoyfellow\u002Fflue-snippets\u002Factions), pick `all`, `examples`, `recipes`, `templates`, or a single target. `max-parallel: 1` because Workers AI rate-limits hard under parallel load on a personal account.\n\nSecrets:\n\n- `CF_API_TOKEN_E2E`, Workers Scripts:Edit + Workers AI:Read, plus permissions for any product-specific targets you enable (R2 \u002F D1 \u002F KV \u002F Queues \u002F AI Gateway \u002F Vectorize \u002F Browser Rendering \u002F Worker Loader \u002F Hyperdrive \u002F Email).\n- `CF_ACCOUNT_ID_E2E`, Cloudflare account ID.\n- `EMAIL_FROM`, `EMAIL_TO`, only needed if you enable `examples\u002Femail-workers`. Without them, the send call returns a structured error and the assertion still passes (it accepts either a real send or a structured `E_*` code).\n\n## FAQ\n\n**Does it really deploy?** Yes. Each `run-e2e.sh` calls `alchemy deploy`, hits a real `*.workers.dev` URL, then `alchemy destroy`s it. CI does the same. There is no mock layer.\n\n**What does it cost?** ~$0.0001 per snippet per run (Workers AI llama-scout call). Free tier is plenty for the entire matrix.\n\n**Why no wrangler?** [alchemy](https:\u002F\u002Falchemy.run) is the resource graph (Workers + bindings + vars, declared in TypeScript, with destroy). Flue is the agent runtime (emits the Worker entrypoint module). The two compose cleanly; wrangler would duplicate alchemy's job.\n\n**Why does CI run sequentially?** Workers AI rate-limits aggressively on personal accounts under parallel load. `max-parallel: 1` keeps the matrix green.\n\n**Can I run only one?** Yes, every example, recipe, and template is independent. `bun ex:\u003Cname>`, `bun rx:\u003Cname>`, or `bun tpl:\u003Cname>`. Or trigger a single target from the Actions dropdown.\n\n## Contributing\n\nSee [`CONTRIBUTING.md`](CONTRIBUTING.md). Security issues: [`SECURITY.md`](SECURITY.md).\n\n## License\n\n[MIT](LICENSE).\n","该项目提供了在Cloudflare上运行的真实可执行的Flue代理示例。每个代码片段都部署了一个临时Worker，对其进行测试后销毁，确保了整个过程无需模拟。核心功能包括与多种Cloudflare产品（如Workers AI、KV、Durable Objects等）集成，并且每个示例都附带端到端测试以验证其正确性。特别适合于希望学习如何将Flue框架应用于Cloudflare生态系统的开发者，以及需要快速搭建和测试基于Cloudflare Workers应用的场景。项目使用TypeScript编写，遵循MIT许可协议。",2,"2026-06-11 04:05:48","CREATED_QUERY"]