$npx -y skills add fastly/fastly-agent-toolkit --skill fastly-fiddleUse when testing VCL against real Fastly edge infrastructure, writing assertion-based Fiddle tests, producing shareable fiddle URLs for bug reproductions, running VCL integration tests in CI, linting VCL remotely via the Fiddle API, or working with clientFetch/events/originFetche
| 1 | # Fastly Fiddle — Real-Edge VCL Testing |
| 2 | |
| 3 | ## Trigger and scope |
| 4 | |
| 5 | Trigger on: Fastly Fiddle, fiddle.fastly.dev URLs, the Fiddle HTTP API, CI testing of VCL services, real-edge VCL tests, shareable VCL reproductions, `clientFetch.*`/`events.*`/`originFetches.*` test expressions, `.test.js` / Mocha specs that target fiddles, SSE `updateResult` / `waitingForSync` events, remote VCL linting via Fiddle, or validating real Fastly behavior (geo, WAF, ESI, clustering, shielding) that local tools cannot simulate. |
| 6 | |
| 7 | Do NOT use for: local VCL unit testing (use `falco`), fast TDD loops (Fiddle has a 10-20s edge-sync floor per publish), Fastly Compute/Wasm testing (use `viceroy` or `fastlike`), production service deployment (use `fastly-cli`), or anything requiring authenticated Fastly API access — Fiddle does not use your Fastly API key. |
| 8 | |
| 9 | Fastly Fiddle is a web-based sandbox at <https://fiddle.fastly.dev> that compiles and runs VCL on real Fastly edge nodes. Because it uses the production VCL compiler and real POPs, it's the only way outside a real service to test VCL features that depend on edge infrastructure — geolocation data, WAF, ESI, clustering, shielding, rate limiting, real TLS, and real cache behavior. |
| 10 | |
| 11 | **Official UI**: <https://fiddle.fastly.dev> |
| 12 | **Demo CI runner**: <https://github.com/fastly/demo-fiddle-ci> |
| 13 | **API base**: `https://fiddle.fastly.dev` (undocumented but stable; no auth required for public fiddles) |
| 14 | |
| 15 | ## When Fiddle, when Falco |
| 16 | |
| 17 | | Need | Use | |
| 18 | | ----------------------------------------------------- | ---------------------------------- | |
| 19 | | Fast local iteration (< 1s), watch mode, offline | `falco test` | |
| 20 | | Real Fastly VCL compiler and semantics | Fiddle | |
| 21 | | Real `client.geo.*`, WAF, ESI, rate limiting, shield | Fiddle | |
| 22 | | Shareable URL for bug repros and support tickets | Fiddle | |
| 23 | | CI against real edge nodes | Fiddle | |
| 24 | | Structured lint with line/col (no execution required) | Either | |
| 25 | | Fastly Compute (WASM) | Neither — use `viceroy`/`fastlike` | |
| 26 | |
| 27 | Common workflow: iterate locally with `falco test` for speed, then push edge cases to Fiddle when you need real Fastly behavior or a shareable link. See [falco-vs-fiddle.md](references/falco-vs-fiddle.md) for full trade-offs. |
| 28 | |
| 29 | ## Workflow: deliverable first, then the cheapest check that answers your question |
| 30 | |
| 31 | Two rules keep you out of the slow path, which is what wastes time and gets |
| 32 | agents killed by a wall-clock limit: |
| 33 | |
| 34 | 1. **If your job is to produce a spec file, write it to disk first**, before |
| 35 | any network call. The file is the deliverable — it must exist even if a |
| 36 | later publish stalls on a cold edge-sync. Don't build the spec only inside |
| 37 | a `curl --data` argument and lose it when the call blocks. |
| 38 | |
| 39 | 2. **Match the check to the question.** "Does this VCL compile / is the spec |
| 40 | shape accepted?" is answered by a _single_ `POST /fiddle` reading `valid` — |
| 41 | ~1-3s, no execution, no edge-sync wait (see gotcha #5). You only need the |
| 42 | full publish → execute → SSE round trip when you must observe _runtime_ |
| 43 | assertion results (actual `clientFetch`/`originFetches`/`events` values), |
| 44 | and that pays the 10-120s edge-sync floor per publish. **Executing is the |
| 45 | exception, not the default** — reach for it deliberately, and always bound |
| 46 | your wait; never block indefinitely on the stream. |
| 47 | |
| 48 | ### Lint-only (the common case): compile check, no execution |
| 49 | |
| 50 | ```bash |
| 51 | scripts/run-fiddle.sh --lint-only fiddle.json |
| 52 | # {fiddle_id, url, valid, lintStatus}. Exit 0 = compiles, 2 = lint error |
| 53 | # (details on stderr). No /execute, no SSE, no edge-sync wait. |
| 54 | ``` |
| 55 | |
| 56 | The raw equivalent is one call — POST and read `valid`: |
| 57 | |
| 58 | ```bash |
| 59 | UA='fiddle-skill-example/1.0' |
| 60 | curl -sS --max-time 30 -X POST https://fiddle.fastly.dev/fiddle \ |
| 61 | -H 'Content-Type: application/json' -H "User-Agent: $UA" \ |
| 62 | --data @fiddle.json | jq '{valid, lintStatus}' # valid==true ⇒ it compiles |
| 63 | ``` |
| 64 | |
| 65 | ### Full round trip (only when you need runtime results) |
| 66 | |
| 67 | When you genuinely need to see assertions pass/fail on the edge, the bundled |
| 68 | helper handles publish → execute → SSE → completion-detection in one call, |
| 69 | with a bounded `--max-wait` (default 180s per attempt) so it can't hang: |
| 70 | |
| 71 | ```bash |
| 72 | scripts/run-fiddle.sh examples/robots.json |
| 73 | # Prints fiddle URL, then pass/fail JSON per assertion (including body_preview |
| 74 | # and status by default). Exits non-zero on failure |