plugins/cloudflare/skills/ai-gateway/SKILL.md
Use this skill when the user asks about Cloudflare AI Gateway, proxying AI API requests through Cloudflare, setting up Claude Code with AI Gateway, configuring ANTHROPIC_BASE_URL, routing AI traffic through a gateway for logging/caching/rate-limiting, cost tracking for AI APIs, connecting Claude Code to OpenRouter or z.ai via a gateway, or managing AI Gateway with Pulumi.
npx skillsauth add nsheaps/ai-mktpl cloudflare-ai-gatewayInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
Cloudflare AI Gateway is a managed proxy that sits between your application and AI inference providers (Anthropic, OpenAI, OpenRouter, z.ai, etc.). It provides observability, caching, rate limiting, cost tracking, and fallback routing — without changing your application code beyond updating the base URL.
| Feature | Description | | ------------------ | -------------------------------------------------------------------- | | Logging | Full request/response logging with metadata (tokens, latency, cost) | | Caching | Cache identical prompts to reduce cost and latency; configurable TTL | | Rate Limiting | Per-gateway or per-user rate limits to control spend | | Cost Tracking | Real-time cost analytics across all providers | | Retries | Automatic retries with backoff on provider errors | | Fallbacks | Route to a backup provider if the primary fails | | Real-time Logs | Stream logs in the dashboard for debugging |
AI Gateway acts as a reverse proxy. You replace the provider's base URL with the gateway URL:
https://gateway.ai.cloudflare.com/v1/{account_id}/{gateway_id}/{provider}
Supported {provider} values include:
anthropic — Anthropic (Claude models)openai — OpenAI (GPT models)openrouter — OpenRouter (multi-model aggregator)workers-ai — Cloudflare Workers AIazure-openai — Azure OpenAI Servicegoogle-ai-studio — Google AI Studio (Gemini)huggingface — Hugging Face Inference APIgroq — Groqcohere — Coheremistral — Mistral AIperplexity-ai — PerplexityFor providers not in the built-in list (like z.ai), use the universal endpoint:
POST https://gateway.ai.cloudflare.com/v1/{account_id}/{gateway_id}
With a body that specifies the provider and target URL. See the universal endpoint docs.
In the Cloudflare dashboard or via Pulumi (see below), create a gateway. Note your:
claude-code)Set the ANTHROPIC_BASE_URL environment variable to route all Anthropic API calls through the gateway:
# In your shell profile (~/.bashrc, ~/.zshrc, etc.)
export ANTHROPIC_BASE_URL="https://gateway.ai.cloudflare.com/v1/YOUR_ACCOUNT_ID/YOUR_GATEWAY_ID/anthropic"
Or in a project's .env file:
ANTHROPIC_BASE_URL=https://gateway.ai.cloudflare.com/v1/YOUR_ACCOUNT_ID/YOUR_GATEWAY_ID/anthropic
Or in Claude Code's settings (~/.claude/settings.json or .claude/settings.json):
{
"env": {
"ANTHROPIC_BASE_URL": "https://gateway.ai.cloudflare.com/v1/YOUR_ACCOUNT_ID/YOUR_GATEWAY_ID/anthropic"
}
}
# Start Claude Code — it should work transparently
claude
# Check the AI Gateway dashboard for logged requests
# https://dash.cloudflare.com/?to=/:account/ai/ai-gateway/YOUR_GATEWAY_ID
Your ANTHROPIC_API_KEY is still sent in the x-api-key header as normal. The gateway proxies it to Anthropic. The gateway itself authenticates via your Cloudflare account.
Claude Code on the web (claude.ai) uses Anthropic's infrastructure directly and does not support ANTHROPIC_BASE_URL overrides. You cannot route claude.ai web traffic through AI Gateway.
However, for Claude Code web sessions (code.claude.com / Claude Code in the browser IDE), you can set environment variables via:
.claude/settings.json:{
"hooks": {
"SessionStart": [
{
"type": "command",
"command": "echo 'ANTHROPIC_BASE_URL=https://gateway.ai.cloudflare.com/v1/ACCT_ID/GATEWAY_ID/anthropic' >> \"$CLAUDE_ENV_FILE\""
}
]
}
}
.claude/settings.json:{
"env": {
"ANTHROPIC_BASE_URL": "https://gateway.ai.cloudflare.com/v1/ACCT_ID/GATEWAY_ID/anthropic"
}
}
Note: Claude Code on the web must have network access to
gateway.ai.cloudflare.com. This works in most environments but may be blocked in restricted network setups.
OpenRouter aggregates 200+ models. Route through AI Gateway for logging:
# The gateway proxies to OpenRouter's API
export OPENROUTER_BASE_URL="https://gateway.ai.cloudflare.com/v1/YOUR_ACCOUNT_ID/YOUR_GATEWAY_ID/openrouter"
Use with any OpenAI-compatible client:
curl "https://gateway.ai.cloudflare.com/v1/ACCT_ID/GATEWAY_ID/openrouter/chat/completions" \
-H "Authorization: Bearer $OPENROUTER_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "anthropic/claude-sonnet-4-20250514",
"messages": [{"role": "user", "content": "Hello"}]
}'
z.ai (Zhipu AI) provides GLM models with an OpenAI-compatible API. Route through the universal endpoint:
curl "https://gateway.ai.cloudflare.com/v1/ACCT_ID/GATEWAY_ID" \
-H "Content-Type: application/json" \
-d '[{
"provider": "zhipu",
"endpoint": "https://open.bigmodel.cn/api/paas/v4/chat/completions",
"headers": {
"Authorization": "Bearer YOUR_ZHIPU_API_KEY",
"Content-Type": "application/json"
},
"query": {
"model": "glm-4-plus",
"messages": [{"role": "user", "content": "Hello"}]
}
}]'
Alternatively, configure z.ai as a custom provider in the AI Gateway dashboard and use:
https://gateway.ai.cloudflare.com/v1/ACCT_ID/GATEWAY_ID/zhipu
AI Gateway supports fallback routing — if the primary provider fails, automatically try another:
curl "https://gateway.ai.cloudflare.com/v1/ACCT_ID/GATEWAY_ID" \
-H "Content-Type: application/json" \
-d '[
{
"provider": "anthropic",
"endpoint": "messages",
"headers": { "x-api-key": "YOUR_ANTHROPIC_KEY" },
"query": { "model": "claude-sonnet-4-20250514", "max_tokens": 1024, "messages": [{"role": "user", "content": "Hello"}] }
},
{
"provider": "openai",
"endpoint": "chat/completions",
"headers": { "Authorization": "Bearer YOUR_OPENAI_KEY" },
"query": { "model": "gpt-4o", "messages": [{"role": "user", "content": "Hello"}] }
}
]'
As of March 2026, there is no native Pulumi or Terraform resource for Cloudflare AI Gateway. The upstream Terraform provider tracks this as issue #6720.
Create the gateway via the dashboard or the Cloudflare REST API.
claude-code) — this becomes the {gateway_id} in URLs# One-time setup — create the gateway
curl -X POST "https://api.cloudflare.com/client/v4/accounts/${ACCOUNT_ID}/ai-gateway/gateways" \
-H "Authorization: Bearer $CLOUDFLARE_API_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"name": "claude-code",
"slug": "claude-code",
"rate_limiting_interval": 60,
"rate_limiting_limit": 200,
"rate_limiting_technique": "fixed",
"cache_ttl": 0
}'
Since no native resource exists, reference the gateway by name in your Pulumi stack outputs:
import * as pulumi from "@pulumi/pulumi";
const config = new pulumi.Config();
const cfConfig = new pulumi.Config("cloudflare");
const accountId = cfConfig.require("accountId");
const aiGatewayName = config.get("aiGatewayName") ?? "claude-code";
// Gateway must be created via dashboard or API first
export const aiGatewayId = aiGatewayName;
export const anthropicBaseUrl = pulumi.interpolate`https://gateway.ai.cloudflare.com/v1/${accountId}/${aiGatewayName}/anthropic`;
export const openrouterBaseUrl = pulumi.interpolate`https://gateway.ai.cloudflare.com/v1/${accountId}/${aiGatewayName}/openrouter`;
Once configured, the AI Gateway dashboard provides:
Access at: https://dash.cloudflare.com/?to=/:account/ai/ai-gateway/YOUR_GATEWAY_ID
| Issue | Solution |
| ------------------------------ | ------------------------------------------------------------------------------------------- |
| 401 Unauthorized | Your API key is passed through to the provider. Verify ANTHROPIC_API_KEY is set correctly |
| 403 Forbidden | Check that your Cloudflare account has AI Gateway enabled |
| 429 Too Many Requests | Hit the gateway rate limit. Increase rateLimitingLimit or wait |
| 502 Bad Gateway | The upstream provider is down. Check provider status pages |
| Requests not appearing in logs | Verify the URL path is correct: /v1/{account_id}/{gateway_id}/{provider} |
| Claude Code hangs on start | Ensure ANTHROPIC_BASE_URL does not have a trailing slash |
tools
Manually reproduce what the github-app plugin's SessionStart hook does to make a GitHub App installation token usable in the current session — materialize the PEM, generate the token, isolate GH_CONFIG_DIR, write the runtime env file, and wire CLAUDE_ENV_FILE so every Bash call sees GH_TOKEN/GITHUB_TOKEN. Use when the hook did not run, the token is missing from the environment, or a shell/teammate needs the token wired up by hand. <example>GH_TOKEN isn't set even though github-app is configured</example> <example>the github-app SessionStart hook didn't run, set up the token manually</example> <example>wire the github app token into CLAUDE_ENV_FILE</example> <example>gh keeps falling back to the wrong account, isolate GH_CONFIG_DIR</example>
tools
Manually configure the GitHub App bot git identity the way the github-app plugin's SessionStart hook does — resolve the app slug and bot user ID, build the <slug>[bot] name and noreply email, set GIT_AUTHOR_*/GIT_COMMITTER_* env vars, and write an isolated GIT_CONFIG_GLOBAL with the gh auth git-credential helper. Use when commits are attributed to the wrong account, "Author identity unknown" appears, or git identity must be set up by hand. <example>my commits are showing up as the handler, not the bot</example> <example>git says Author identity unknown after the github-app hook ran</example> <example>configure the github app bot git identity manually</example> <example>set up the gh credential helper for git push</example>
tools
Manages spec files for requirements capture and validation
tools
# Bash Chaining Alternatives This skill teaches you how to work around the bash command chaining restriction enforced by this plugin. ## Why Chaining is Blocked The `bash-command-rejection` plugin blocks these operators: | Operator | Name | Why Blocked | | -------- | ---------- | ----------------------------------------------------------------------------------- | | `&&` | AND chain | Runs cmd2 only if cmd1 su