gitconfig: name/email from chezmoi data, gh credential helper by PATH lookup (portable to darwin). claude: no credentials, history, projects, sessions, or plugin caches. ssh config as private_ (0600). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
8.0 KiB
Code Review — Workers
How to review Workers code for type correctness, API usage, config validity, and best practices. This is self-contained — do not assume access to other skills.
Retrieval
Prefer retrieval over pre-training. Types, config schemas, and APIs change with compatibility dates and new bindings.
Workers types
Fetch the latest @cloudflare/workers-types before reviewing. The project may have an older version installed.
mkdir -p /tmp/workers-types-latest && \
npm pack @cloudflare/workers-types --pack-destination /tmp/workers-types-latest && \
tar -xzf /tmp/workers-types-latest/cloudflare-workers-types-*.tgz -C /tmp/workers-types-latest
# Types are at /tmp/workers-types-latest/package/index.d.ts
Search this file for the specific type, class, or interface under review. Do not guess type names.
Alternative: npx wrangler types generates a typed Env interface from the local wrangler config.
Fallback: read node_modules/@cloudflare/workers-types/index.d.ts. Note the installed version.
Wrangler config schema
The authoritative schema is bundled with wrangler as config-schema.json (JSON Schema draft-07).
# Read from local node_modules
cat node_modules/wrangler/config-schema.json
Do not guess field names or structures — look them up.
Cloudflare docs
Use the Cloudflare docs search tool if available, or fetch from https://developers.cloudflare.com/workers/. The best practices page lives at /workers/best-practices/workers-best-practices/.
Type Validation
Env interface
- Every binding must have a specific type. Flag
any,unknown,object, orRecord<string, unknown>on bindings. - Binding types that accept generic parameters (Durable Object namespaces, Queues, Service bindings for RPC) must include them. Read the type definition to confirm which types are generic.
- Binding names must match the wrangler config exactly.
- Prefer generated types from
wrangler typesover hand-written interfaces.
Handler and class signatures
Verify against current type definitions — do not assume signatures are stable.
- Correct import path (most Workers platform classes import from
"cloudflare:workers") - Generic type parameter on base classes (e.g.,
DurableObject<Env>) - Binding access pattern:
env.Xin module export handlers,this.env.Xin classes extending platform base classes ExecutionContextas the third param in module export handlers (needed forctx.waitUntil())fetch()handlers must returnPromise<Response>
Binding access — the most common error
- Module export handlers (
fetch,scheduled,queue,email): bindings viaenv.Xparameter - Platform base classes (
WorkerEntrypoint,DurableObject,Workflow,Agent): bindings viathis.env.X
Flag env.X inside a class extending a platform base class. Flag this.env.X inside a module export handler.
Type integrity rules
| Rule | Detail |
|---|---|
No any |
Never on binding types, handler params, or API responses |
| No double-casting | as unknown as T hides real incompatibilities — fix the underlying design |
| Justify suppressions | @ts-ignore/@ts-expect-error must include a comment explaining why |
Prefer satisfies |
Use satisfies ExportedHandler<Env> over as — validates without widening |
| Validate, do not assert | Schema or type guard for untyped data (JSON, parsed bodies), not as |
Stale class patterns
Old patterns survive in codebases long after APIs change.
extendsvsimplements: platform classes useextends, notimplements. Theimplementspattern is legacy and losesthis.ctx,this.env.- Import paths: verify module specifiers match what types actually export. Common mistake: wrong path for
"cloudflare:workers"vs"cloudflare:workflows". - Renamed properties: e.g.,
this.statetothis.ctxin Durable Objects. Search types to confirm. - Constructor signatures: base class constructors change. Verify expected parameters.
Config Validation
Required fields
For executable examples, verify: name, compatibility_date, main. Check the schema for current required fields.
Config format
- JSONC (
wrangler.jsonc) — preferred for new projects - JSON (
wrangler.json) — valid but no comments - TOML (
wrangler.toml) — legacy; acceptable in existing content, flag in new projects
Binding-code consistency
- Every
env.Xreference in code has a corresponding binding declaration in config - Every binding in config is referenced in code (warn on unused)
- Names match exactly (case-sensitive)
- For Durable Objects:
class_namematches the exported class name
Common config mistakes
| Check | What to look for |
|---|---|
Stale compatibility_date |
Should be recent; use $today placeholder in docs |
| Missing DO migrations | Every new DO class needs a migration entry |
| Binding name mismatch | Config binding/name must match env.X in code |
| Secrets in config | Never in vars — use wrangler secret put |
| Wrong binding key | Verify top-level key name against the schema |
| Missing entrypoint | main required for executable Workers |
Anti-Patterns to Flag
See the full anti-patterns table in SKILL.md. The type-specific ones to watch for during review:
anyonEnvor handler params — defeats type safety for all downstream binding accessas unknown as T— hides real type incompatibilities; fix the underlying design@ts-ignore/@ts-expect-errorwithout explanation — masks errors silently; require a justifying commentimplementsinstead ofextendson platform base classes — legacy pattern; losesthis.ctx,this.envenv.Xinside class body — should bethis.env.Xin platform base classesthis.env.Xin module export handler — should beenv.Xparameter- Non-serializable values across boundaries —
Response,Errorin step/queue compiles but fails at runtime
Serialization Boundaries
Data crossing these boundaries must be structured-clone serializable:
- Queue messages: body passed to
.send()or.sendBatch() - Workflow step return values: persisted to durable storage
- DO storage: values in
storage.put()or SQL postMessage(): WebSocket messages
Non-serializable types to flag: Response, Request, Error, functions, class instances with methods, Map/Set, Symbol.
Valid: plain objects, arrays, strings, numbers, booleans, null, ArrayBuffer, Date.
Review Process
- Retrieve — fetch latest workers types, wrangler schema, and best practices page
- Read full files — not just diffs; context matters for binding access patterns
- Categorize code — determines what to check:
- Illustrative (concept demo, comments for most logic): verify correct API names and realistic signatures
- Demonstrative (functional snippet, would work in context): verify syntax, correct APIs, correct binding access
- Executable (standalone, runs without modification): verify compiles, runs, includes imports and config
- Check types — binding access pattern, handler signatures, no
any, no unsafe casts - Check config — compatibility_date, nodejs_compat, observability, secrets, binding-code consistency
- Check patterns — streaming, floating promises, global state, serialization boundaries
- Check security — crypto usage, secret handling, timing-safe comparisons, error handling
- Validate with tools —
npx tsc --noEmit, lint forno-floating-promises - Assess risk — HIGH (auth, crypto, bindings), MEDIUM (business logic, config), LOW (style, comments)
Output format
**[SEVERITY]** Brief description
`file.ts:42` — explanation with evidence
Suggested fix: `code`
Severity: CRITICAL (security, data loss, crash) | HIGH (type error, wrong API, broken config) | MEDIUM (missing validation, edge case) | LOW (style, minor improvement)