← Back to Skills Marketplace
pirumpi

cftunnel

by Carlos Martin · GitHub ↗ · v1.1.0 · MIT-0
cross-platform ⚠ suspicious
104
Downloads
0
Stars
0
Active Installs
2
Versions
Install in OpenClaw
/install cftunnel
Description
Expose local services to the internet via Cloudflare Tunnels. CLI (npx cftunnel) and Node.js library for creating tunnels, configuring ingress routes, managi...
README (SKILL.md)

cftunnel — Cloudflare Tunnel Manager for AI Agents

Expose local services to the internet via Cloudflare Tunnels. Use this skill when you need to make a locally running application accessible at a public HTTPS URL.

Flow: Start a local service (e.g. on port 3000) → cftunnel creates a tunnel + DNS route → the service is live at https://hostname.domain.com.

Authentication

Set these environment variables before running any command:

# Option A: API Key + Email (most common)
export CLOUDFLARE_API_KEY=\x3Capi-key>
export CLOUDFLARE_EMAIL=\x3Caccount-email>

# Option B: API Token (scoped, if available)
export CLOUDFLARE_API_TOKEN=\x3Capi-token>

# Always required:
export CLOUDFLARE_ACCOUNT_ID=\x3Caccount-id>

Quick Reference

Expose a local service (fastest path)

If a tunnel and cloudflared are already running (check with tunnel list), just add a route and DNS:

# 1. Add ingress route to existing tunnel
npx cftunnel route add \x3Ctunnel-id> --hostname \x3Chostname> --service http://localhost:\x3Cport>

# 2. Create DNS CNAME
npx cftunnel dns create --zone-id \x3Czone-id> --hostname \x3Chostname> --tunnel-id \x3Ctunnel-id>

Create everything from scratch (one command)

npx cftunnel quickstart \
  --name \x3Ctunnel-name> \
  --hostname \x3Chostname> \
  --service http://localhost:\x3Cport> \
  --zone-id \x3Czone-id>

Then run the connector: npx cftunnel run \x3Ctunnel-id>

Programmatic usage (Node.js library)

import { createClient, quickstart } from 'cftunnel';

const client = createClient({ apiKey: '...', apiEmail: '...' });
const result = await quickstart(client, {
  accountId: '...',
  name: 'my-app',
  hostname: 'app.example.com',
  service: 'http://localhost:3000',
  zoneId: '...',
});
console.log(result.run_cmd);

All Commands

Tunnel lifecycle

Command Purpose
npx cftunnel tunnel list List all tunnels. Find existing tunnel IDs and check status (healthy/down/inactive).
npx cftunnel tunnel create \x3Cname> Create a new tunnel. Returns tunnel ID and secret. Add --config-src local for YAML-managed config.
npx cftunnel tunnel get \x3Ctunnel-id> Get tunnel details including connection status.
npx cftunnel tunnel delete \x3Ctunnel-id> Delete a tunnel. Must have no active connections.
npx cftunnel tunnel token \x3Ctunnel-id> Get the token needed to run cloudflared. Returns run_cmd and install_cmd.

Ingress routes (hostname → local service mapping)

Command Purpose
npx cftunnel route list \x3Ctunnel-id> Show current ingress rules. Always has a catch-all 404 as last rule.
npx cftunnel route add \x3Ctunnel-id> --hostname \x3Chost> --service \x3Curl> Add a route. Preserves existing routes, appends before catch-all. Optional --path for path filtering.
npx cftunnel route remove \x3Ctunnel-id> --hostname \x3Chost> Remove a route by hostname.
npx cftunnel route set \x3Ctunnel-id> --route host1=svc1 --route host2=svc2 Replace ALL routes. Use for bulk configuration.

DNS records

Command Purpose
npx cftunnel dns create --zone-id \x3Czid> --hostname \x3Chost> --tunnel-id \x3Ctid> Create proxied CNAME pointing hostname to tunnel. Required for the hostname to resolve.
npx cftunnel dns list --zone-id \x3Czid> List all DNS records in the zone.
npx cftunnel dns delete \x3Crecord-id> --zone-id \x3Czid> Delete a DNS record.

Running the connector

Command Purpose
npx cftunnel run \x3Ctunnel-id> Run cloudflared in foreground. Auto-detects cloudflared from PATH or npm package.
npx cftunnel run \x3Ctunnel-id> --install-service Install cloudflared as a persistent system service (survives reboots).

Decision Guide

"I need to expose port N on a domain" → Check tunnel list for a healthy tunnel. If one exists, use route add + dns create. If not, use quickstart.

"I need to add another service to an existing tunnel"route add + dns create. One tunnel can serve many hostnames.

"I need to change where a hostname points"route remove --hostname X then route add --hostname X --service \x3Cnew-url>. DNS stays the same.

"I need to take a service offline"route remove --hostname X and optionally dns delete \x3Crecord-id>.

"The tunnel exists but cloudflared isn't running"npx cftunnel run \x3Ctunnel-id> or use tunnel token to get the token for manual cloudflared invocation.

Service URL Formats

The --service flag accepts these protocols:

Format Example Use case
http://host:port http://localhost:3000 HTTP web apps, APIs
https://host:port https://localhost:8443 HTTPS backends
tcp://host:port tcp://localhost:5432 Databases, raw TCP
ssh://host:port ssh://localhost:22 SSH access
unix:///path unix:///tmp/app.sock Unix socket apps
http_status:CODE http_status:404 Static status response (catch-all)

Output Format

All commands output JSON to stdout. Progress/errors go to stderr.

Parse with jq:

TUNNEL_ID=$(npx cftunnel tunnel create my-app | jq -r '.id')
TOKEN=$(npx cftunnel tunnel token $TUNNEL_ID | jq -r '.token')

Common Patterns

Pattern 1: Deploy a new web app

cd /path/to/app && npm start &

npx cftunnel quickstart \
  --name my-web-app \
  --hostname app.example.com \
  --service http://localhost:8080 \
  --zone-id \x3Czone-id>

npx cftunnel run \x3Ctunnel-id-from-output>

Pattern 2: Add subdomain to existing tunnel

npx cftunnel tunnel list | jq '.[] | select(.status == "healthy")'

npx cftunnel route add \x3Ctunnel-id> --hostname api.example.com --service http://localhost:4000
npx cftunnel dns create --zone-id \x3Czone-id> --hostname api.example.com --tunnel-id \x3Ctunnel-id>

Pattern 3: Swap service behind a hostname

npx cftunnel route remove \x3Ctunnel-id> --hostname app.example.com
npx cftunnel route add \x3Ctunnel-id> --hostname app.example.com --service http://localhost:9000

Pattern 4: Clean teardown

npx cftunnel route remove \x3Ctunnel-id> --hostname app.example.com
npx cftunnel dns list --zone-id \x3Czone-id>
npx cftunnel dns delete \x3Crecord-id> --zone-id \x3Czone-id>
npx cftunnel tunnel delete \x3Ctunnel-id>

Pattern 5: Programmatic usage in agent code

import { createClient, createTunnel, addRoute, createDNS } from 'cftunnel';

const client = createClient(); // reads from env vars
const tunnel = await createTunnel(client, { accountId: '...', name: 'my-app' });
await addRoute(client, {
  accountId: '...',
  tunnelId: tunnel.id,
  hostname: 'app.example.com',
  service: 'http://localhost:3000',
});
await createDNS(client, {
  zoneId: '...',
  hostname: 'app.example.com',
  tunnelId: tunnel.id,
});

Important Notes

  • A tunnel must have cloudflared running to serve traffic. Creating a tunnel and routes alone is not enough.
  • The catch-all http_status:404 rule is always appended automatically. Do not add it manually.
  • DNS CNAME records must be proxied through Cloudflare (orange cloud). This is set automatically.
  • One tunnel can serve multiple hostnames. Prefer reusing existing healthy tunnels over creating new ones.
  • route set replaces ALL routes. Use route add/route remove for incremental changes.
  • If cloudflared is already running as a service, route changes take effect immediately (no restart needed).

Global Flags

Flag Env Var Description
--api-token CLOUDFLARE_API_TOKEN Cloudflare API token (bearer auth)
--api-key CLOUDFLARE_API_KEY Cloudflare API key (requires --api-email)
--api-email CLOUDFLARE_EMAIL Cloudflare account email
--account-id CLOUDFLARE_ACCOUNT_ID Cloudflare account ID
Usage Guidance
This skill appears to do what it says: manage Cloudflare Tunnels via an npm CLI. Before installing or running it, consider the following: (1) prefer using a scoped CLOUDFLARE_API_TOKEN with minimal permissions instead of a global API key; the SKILL.md mentions the token option but the metadata doesn't declare it — provide only the credentials you intend to allow. (2) npm -g will download and install code on the host; only install packages from sources you trust and check the package repo if unsure. (3) 'npx cftunnel run' may invoke cloudflared and the documented '--install-service' will create a persistent system service (requires admin rights) — don't run that unless you want a long-lived service. (4) DNS and tunnel operations can expose local services publicly and modify zone records — ensure you limit scope to dedicated zones/accounts. If you want extra assurance, review the cftunnel npm/GitHub source before installing and use a dedicated Cloudflare account or token with narrow scope.
Capability Analysis
Type: OpenClaw Skill Name: cftunnel Version: 1.1.0 The skill provides a wrapper for Cloudflare Tunnels, enabling high-risk behaviors such as exposing local network services to the public internet and managing DNS records. It requires highly privileged credentials (CLOUDFLARE_API_KEY) and includes functionality for persistence through system service installation (`--install-service` in SKILL.md). While these capabilities are aligned with the tool's stated purpose, the inherent risk of bypassing firewalls and the potential for credential exposure or unauthorized network access via the agent justify a suspicious classification. Additionally, _meta.json contains an anomalous future-dated timestamp (March 2026).
Capability Assessment
Purpose & Capability
Name/description (manage Cloudflare tunnels, routes, and DNS) align with required binaries (node, cftunnel) and the Cloudflare API credentials listed. The install step (npm -g cftunnel) is reasonable for a CLI/library of this kind.
Instruction Scope
SKILL.md instructs the agent to create tunnels, add routes, and modify DNS — all expected. It also documents running cloudflared and optionally installing it as a system service; that step would modify the host (persistent service) if executed by the user/agent. SKILL.md references CLOUDFLARE_API_TOKEN as an alternative auth method but the metadata does not declare that env var.
Install Mechanism
Install uses npm (-g) to install the cftunnel package and create a cftunnel binary — a standard, expected mechanism. npm global installs download and write code to disk (moderate risk compared to purely instruction-only skills), but the source points to a public npm package and a GitHub homepage, not an arbitrary URL.
Credentials
Requested env vars (CLOUDFLARE_API_KEY, CLOUDFLARE_EMAIL, CLOUDFLARE_ACCOUNT_ID) are appropriate for Cloudflare API operations. Two points: (1) the SKILL.md also references CLOUDFLARE_API_TOKEN as a safer/scoped alternative but that token variable is not included in the declared requires.env, and (2) a global API key (CLOUDFLARE_API_KEY) is high-privilege compared to a scoped API token — prefer creating a scoped token limited to the necessary zones and actions.
Persistence & Privilege
always:false and no required config paths indicate the skill does not demand forced permanent inclusion. The skill documents a user-invocable option to install cloudflared as a persistent system service, which requires elevated privileges if executed, but that is an explicit user action rather than implicit behavior of the skill bundle.
How to Use
  1. Make sure OpenClaw is installed (local or Docker)
  2. Run the install command in chat: /install cftunnel
  3. After installation, invoke the skill by name or use /cftunnel
  4. Provide required inputs per the skill's parameter spec and get structured output
Version History
v1.1.0
Fix install to use global npm install (npm i -g cftunnel) so cftunnel binary is available in PATH
v1.0.0
Initial release: CLI + library for managing Cloudflare Tunnels, ingress routes, and DNS records
Metadata
Slug cftunnel
Version 1.1.0
License MIT-0
All-time Installs 0
Active Installs 0
Total Versions 2
Frequently Asked Questions

What is cftunnel?

Expose local services to the internet via Cloudflare Tunnels. CLI (npx cftunnel) and Node.js library for creating tunnels, configuring ingress routes, managi... It is an AI Agent Skill for Claude Code / OpenClaw, with 104 downloads so far.

How do I install cftunnel?

Run "/install cftunnel" in the OpenClaw or Claude Code chat to install it in one step — no extra setup required.

Is cftunnel free?

Yes, cftunnel is completely free, licensed under MIT-0. You can download, install and use it at no cost.

Which platforms does cftunnel support?

cftunnel is cross-platform and runs anywhere OpenClaw / Claude Code is available (cross-platform).

Who created cftunnel?

It is built and maintained by Carlos Martin (@pirumpi); the current version is v1.1.0.

💬 Comments