Cf rust worker
Agent Flywheel Coding Skills
npx -y skills add JordanChoo/acfs-agent-skills --skill cf-rust-workerAssembled from the repository path, not quoted from the project. Check it against their README if it does not work.
2 things to look at
- no licenseNo license file was found in the repository. Code published without one is not open source by default, so using it at work is a question for whoever answers licensing questions where you are.
- 0 stars0 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.
What its author says it does
Copied from the file, not written here
Build, configure, and deploy Rust-based Cloudflare Workers compiled to WebAssembly. Covers wrangler.toml setup, worker crate versions, build toolchain (rustup + worker-build + wasm32-unknown-unknown), local dev with wrangler dev, secrets management, and Cloudflare dashboard deployment. Use when creating a new Rust Worker, debugging build failures, or deploying via CLI or the CF dashboard UI.
SKILL.md
10.2 KB, as published. Nobody here has run it
cf-rust-worker — Rust Cloudflare Workers Deployment
Build and deploy Rust Cloudflare Workers that compile to WebAssembly and run on Cloudflare's edge network.
When to use this skill
- Creating a new Rust-based Cloudflare Worker from scratch
- Debugging build failures (cargo not found, wasm target missing, worker crate version mismatch)
- Setting up local development with
wrangler dev - Deploying via CLI (
wrangler deploy) or the Cloudflare dashboard UI - Configuring secrets for Workers
Prerequisites
| Requirement | Notes |
|---|---|
| Rust (stable) | rustup with wasm32-unknown-unknown target |
| worker-build | cargo install worker-build |
| Node.js >= 22 | Required by current Wrangler CLI |
| Wrangler CLI | npm install -g wrangler |
If using NVM and the default Node version is < 22, prefix commands:
PATH="$HOME/.nvm/versions/node/v25.9.0/bin:$PATH" wrangler dev
Project scaffolding
Cargo.toml
[package]
name = "my-worker"
version = "0.1.0"
edition = "2021"
[lib]
crate-type = ["cdylib"]
[dependencies]
worker = "0.8"
serde = { version = "1", features = ["derive"] }
serde_json = "1"
console_error_panic_hook = "0.1"
Critical: The worker crate must be >= 0.8.3. Older versions (0.4.x, 0.5.x) are rejected by current worker-build with a version mismatch error. Always use worker = "0.8" or later.
wrangler.toml
name = "my-worker"
main = "build/worker/shim.mjs"
compatibility_date = "2026-05-20"
[build]
command = "curl https://sh.rustup.rs -sSf | sh -s -- -y --default-toolchain stable && . \"$HOME/.cargo/env\" && rustup target add wasm32-unknown-unknown && cargo install -q worker-build && worker-build --release"
Why the build command installs Rust: Cloudflare's build environment does NOT include Rust. If the build command is just worker-build --release, CF dashboard deployments fail with cargo: not found. The full command installs the Rust toolchain, adds the WASM target, installs worker-build, then builds. This is idempotent (rustup skips if already installed) so it works both locally and in CF's clean build environment.
main must be build/worker/shim.mjs, not a .rs or .wasm file. worker-build generates a JS shim that loads the compiled WASM module.
Entry point (src/lib.rs)
use worker::*;
#[event(fetch)]
async fn fetch(req: Request, env: Env, _ctx: Context) -> Result<Response> {
console_error_panic_hook::set_once();
// Your handler logic here
Response::ok("Hello from Rust!")
}
.gitignore (Rust Worker essentials)
# Secrets
.env
.env.*
.dev.vars
# Rust
/target/
# Wrangler / Cloudflare Workers
/worker/
.wrangler/
build/
*.wasm
# Node (wrangler toolchain)
node_modules/
Secrets management
Production secrets (CLI)
wrangler secret put MY_SECRET
# Prompts for the value interactively
Secrets are stored encrypted by Cloudflare and accessed in Rust via:
let value = env.secret("MY_SECRET")?.to_string();
If a required secret is missing, env.secret() returns Err. Handle this with a clear error response (not a panic).
Local development secrets
Create .dev.vars in the project root (must be gitignored):
MY_SECRET="local-value"
ANOTHER_SECRET="local-value-2"
wrangler dev reads .dev.vars automatically. Do NOT commit this file.
Per-environment secrets
wrangler secret put MY_SECRET --env staging
wrangler secret put MY_SECRET --env production
Local development
wrangler dev
This compiles the Rust to WASM and starts a local server (default port 8787). Hot-reload is supported; it recompiles on file changes.
Test with:
curl http://localhost:8787/
Deployment
Option 1: CLI deployment
wrangler login # First time only; opens browser for OAuth
wrangler deploy # Builds and deploys atomically
Wrangler prints the live URL on success (e.g., https://my-worker.your-subdomain.workers.dev).
Secrets persist across deployments. You only need to set them once (or when rotating).
Option 2: Cloudflare dashboard deployment (GitHub integration)
- Log in to the Cloudflare dashboard > Workers & Pages
- Click Create > Import a repository
- Connect GitHub and select the repository
- Configure build settings:
| Field | Value |
|---|---|
| Build command | (leave empty) |
| Deploy command | npx wrangler deploy |
| Root directory | (leave empty) |
Gotchas:
- Build command must be empty when
wrangler.tomlhas a[build]section. The[build].commandinwrangler.tomlruns automatically duringwrangler deploy. If you duplicate it in the dashboard Build command field, it runs twice. - Root directory must be empty (not
/buildorbuild/). The root directory field tells CF where to find the project files, not where build output goes. Setting it tobuild/causes "root directory not found" errors. - Deploy command is
npx wrangler deploy, notwrangler deploy. The dashboard environment may not have wrangler globally installed.
- After first deploy, go to Settings > Variables and Secrets and add all required secrets. Click Encrypt for each.
Every push to main triggers an automatic rebuild and deploy.
Triggering a manual redeploy (dashboard)
Go to Workers & Pages > your-worker > Deployments, find the most recent deployment, click the three-dot menu, and select Retry deployment. Or push an empty commit:
git commit --allow-empty -m "trigger redeploy" && git push
Environment management
Add environment blocks to wrangler.toml:
[env.staging]
name = "my-worker-staging"
[env.production]
name = "my-worker"
Deploy per environment:
wrangler deploy --env staging
wrangler deploy --env production
Each environment gets its own URL and its own set of secrets.
Rollback
CLI:
wrangler deployments list
wrangler deployments rollback <version-id>
Dashboard: Workers & Pages > your-worker > Deployments > select version > Rollback.
Rollbacks are instant. Secrets are unaffected (the previous code runs with current secret values).
Monitoring
wrangler tail # Stream live logs
wrangler tail --format json # Structured output for log aggregation
Common build failures and fixes
cargo: not found (CF dashboard deployment)
Cause: CF's build environment does not include Rust.
Fix: The wrangler.toml [build].command must install Rust. See the wrangler.toml template above.
worker crate version mismatch
Symptom: worker-build errors about incompatible worker crate version.
Fix: Update Cargo.toml to worker = "0.8" or later. Do not use 0.4.x or 0.5.x.
wasm32-unknown-unknown target not installed
Symptom: error[E0463]: can't find crate for std or similar during WASM compilation.
Fix: rustup target add wasm32-unknown-unknown. The wrangler.toml build command template above includes this.
Wrangler requires Node >= 22
Symptom: Wrangler fails to start or shows version compatibility errors.
Fix: Upgrade Node.js. With NVM: nvm install 22 && nvm use 22.
Headers::new() mut warnings
The worker crate's Headers::new() returns a mutable-by-default struct in older versions. In 0.8+, use let headers = Headers::new() (no mut). Methods like headers.set() take &self, not &mut self.
with_body() expects JsValue
When building Request objects for outbound fetch calls, with_body() expects Option<JsValue>, not Option<String>. Convert with .into():
.with_body(Some(payload.to_string().into()))
Outbound HTTP requests
Workers use Cloudflare's built-in Fetch API (no reqwest needed):
use worker::Fetch;
let mut req_init = RequestInit::new();
req_init.with_method(Method::Post);
let mut headers = Headers::new();
headers.set("Authorization", &format!("Bearer {}", api_key))?;
headers.set("Content-Type", "application/json")?;
req_init.with_headers(headers);
req_init.with_body(Some(serde_json::to_string(&body)?.into()));
let req = Request::new_with_init(&url, &req_init)?;
let mut resp = Fetch::Request(req).send().await?;
let text = resp.text().await?;
This avoids pulling in reqwest and keeps the WASM binary small.
Security checklist for public repos
Before committing to a public repository:
-
.dev.varsis in.gitignore -
.envand.env.*are in.gitignore - No secrets appear in
wrangler.toml(usewrangler secret putinstead) - No API keys, tokens, or passwords in any
.rsfile - Error responses never leak secrets or full internal URLs
- Logs use hostnames only, never full URLs (which may contain tokens in query params)
Logging best practices
Use console_log! from the worker crate:
console_log!("request_received target_host={} format={}", hostname, format);
Never log: secrets, authorization headers, full URLs (may contain tokens), request/response bodies containing credentials.
Always log: target hostname, response status, format requested, timing.
View logs with wrangler tail.
Provenance
This skill was derived from building and deploying rusty-gateway, a Rust Cloudflare Worker using BrightData's Web Unlocker API. Every gotcha documented here was encountered firsthand during that build (May 2026). The CF dashboard deployment section in particular captures errors that are not well-documented elsewhere: the "cargo not found" build failure, the root directory vs build output confusion, and the need for npx wrangler deploy as the deploy command.