本文へ移動
cccskills
無料GitHub で公開

cloudflare-drop

Publish a static site (a folder of HTML/CSS/JS/images/fonts) to Cloudflare and get back a live, shareable URL in seconds. Use when you have a finished static page or site and need to hand someone a link they can open on any device — reports, mockups, one-off landing pages, AI-generated HTML, "give me a link I can share". Runs one packaged command (references/deploy.mjs) built on the Wrangler CLI, which is what Cloudflare's own agent guidance tells agents to use. Deploys permanently to your Cloudflare account when credentials are present, or as a 60-minute claimable preview when they are not — and says plainly which one you got. Bakes an expiry countdown into previews (matched to the real 60-minute limit; --ttl to shorten it), and supports optional server-side six-digit access-code protection with -otp for permanent links only. Unprotected delivery may fall back to a file; protected delivery fails closed.

インストール方法を見る

含まれるファイル(21)

  • SKILL.md16.7 KB
  • CHANGELOG.md11.0 KB
  • references/deploy.mjs26.9 KB
  • references/drop-index.mjs11.2 KB
  • references/inject-countdown.mjs6.5 KB
  • references/otp-gate.html6.6 KB
  • references/otp-security.md3.7 KB
  • references/otp-worker.mjs6.1 KB
  • references/otp.mjs3.1 KB
  • references/test/cli-args.test.mjs941 B
  • references/test/drop-index.test.mjs16.9 KB
  • references/test/otp.test.mjs7.3 KB
  • references/test/staging-review.test.mjs8.4 KB
  • references/test/ttl.test.mjs3.5 KB
  • references/test/verify-backoff.test.mjs6.5 KB
  • references/test/wrangler-env.test.mjs6.5 KB
  • references/test/wrangler.test.mjs6.7 KB
  • references/ttl.mjs4.6 KB
  • references/wrangler.mjs10.9 KB
  • test/deploy-staging.test.mjs2.0 KB
  • test/inject-countdown.test.mjs6.8 KB

SKILL.md(原文)

インストールする前に、エージェントに与えられる指示の中身を確認できます。

cloudflare-drop: publish a static site as a shareable link

Turn a finished static page into a live URL with one command. Cloudflare serves it from its edge at https://<name>.<account>.workers.dev in seconds.

Two hosting modes, and the skill picks the one that will actually work:

whenlifetime
permanentCLOUDFLARE_API_TOKEN is setforever — it's in your account
temporary previewno usable credentials60 minutes, unless claimed

The mode is detected, not guessed, and always reported back — so you never hand someone a link believing it's permanent when it dies in an hour.

Protection contract

When the user asks for password protection, use -otp on a permanent deployment. Temporary previews and renew reject it before upload. Never omit the flag on retry, change hosting mode silently, embed the report behind a client-side password form, or fall back to publishing an unprotected copy. An explicit --permanent uses the operator's Cloudflare account and requires authentication. Without -otp, behavior is unchanged.

Stage only intended deliverables in a dedicated input folder: the existing helper copies sibling files too. Keep CSV exports, credentials, source repositories and unrelated reports out of that folder. A protected share authorizes access to all its staged assets after login. Use a fresh worker name when moving previously public content behind a password; old downloads and cached public copies cannot be revoked. Every deploy now prints the staging review described below before it uploads — read it, and say something to the user if it flags a file.

What is about to become public

Staging copies the page's whole sibling directory, recursively, because a multi-file page renders broken without its assets. node_modules, .git, __MACOSX and every dotfile (so .env too) were already excluded. What was never visible is the ordinarily-named file — secrets.json, credentials.txt, backup.sql, id_rsa — and this skill's whole job is to turn a folder into a public URL.

So every run prints, on stderr, before the upload:

STAGED_FILES 7
STAGED_REVIEW 4 of 7 staged files are outside HTML/CSS/JS/images/fonts. …
  SENSITIVE_NAME  secrets.json  (312 bytes)
  UNEXPECTED_TYPE  backup.sql  (24 bytes)

A clean run prints STAGED_FILES n and STAGED_REVIEW ok — the headline is printed on every path, so its absence means the review did not run, not that there was nothing to say.

This never blocks a deploy (discipline #3). It is a report. When it flags something, the fixes are: re-stage from a folder holding only the deliverable, or re-run with --assets-only, which stages only recognised static assets and prints STAGED_SKIPPED naming every file it left behind. Relay the flagged names to the user rather than deciding for them — a data.sql someone means to publish is their call.

The one command

node references/deploy.mjs <page.html> [--ttl 30m] [--name my-report] [--permanent] [--assets-only]

It resolves the countdown window → stages the page as index.html at a clean root → deploys via Wrangler → curl-verifies HTTP 200 → prints:

RESULT_URL   https://my-report.ethereal-composer.workers.dev
MODE         temporary
CLAIM_LINK   https://dash.cloudflare.com/claim-preview?claimToken=…
EXPIRY_EPOCH 1785499999

It never prints a URL it didn't verify, and never invents one. The verify is content, not just status: after the 200 backoff, the served page must match the source's byte size (within the injected countdown's growth) and carry a body sentinel — a blank/truncated page that still 200s fails as URL_UNVERIFIED.

URL_UNVERIFIED = deploy failed — do NOT deliver that URL; fall back to the file. If the script prints URL_UNVERIFIED (no 200, or a blank/truncated page that didn't match the content self-verify), the deploy did not succeed. Never hand that URL to the user — treat it as a failure, say so plainly, and offer the HTML file instead (fail-open, discipline #3).

Why Wrangler and not the browser dropzone: cloudflare.com/drop's own "For AI agents" section instructs agents to prefer Wrangler for local CLI workflows. The packaged playwright path was removed in 2.0.0 — the dropzone DOM changed and it silently returned no URL. v1 predicted this switch; this is it.

Flags

flageffect
--ttl 30mcountdown window shown on the page. Accepts s/m/h/d; a bare number is minutes. Default 60m (the real preview lifetime), or $CLOUDFLARE_DROP_TTL. Values above 60m are clamped — see below.
--name my-reportworker name (becomes the subdomain). Defaults to a sanitized filename.
-otp / --otpgenerate a random six-digit access code; permanent links only. Prints OTP_CODE separately after verification.
--permanentforce a normal (account) deploy. Requires credentials.
--no-pause-oauthnever touch the local OAuth file (see below).
--no-countdownskip baking the countdown into the page. The real expiry is unchanged — a temporary preview still dies at 60 minutes and the CLI still prints EXPIRY_EPOCH; only the on-page banner is omitted. Use when the reader finds the banner noisy and you (the operator) own the claim-before-expiry responsibility.
--assets-onlystage only recognised static assets (HTML/CSS/JS/images/fonts) and skip everything else, printing STAGED_SKIPPED with every file left behind. Off by default — the default stages everything and only reports on it.

What the deploy subprocess can see

Wrangler is a third-party CLI running on your machine, so two things are pinned rather than left floating:

  • A fixed version. The deploy runs wrangler@4.134.0, not wrangler@latest. Bumping it is a reviewed change to references/wrangler.mjs, not something that happens silently on the next npm publish.
  • An allowlisted environment. It receives PATH/HOME/TMPDIR and their Windows equivalents, the proxy variables, NODE_EXTRA_CA_CERTS, the Cloudflare credential variables (CLOUDFLARE_API_TOKEN, CF_API_TOKEN, CLOUDFLARE_ACCOUNT_ID, CF_ACCOUNT_ID, CLOUDFLARE_API_KEY, CF_API_KEY, CLOUDFLARE_EMAIL, CF_EMAIL), WRANGLER_HOME/XDG_CONFIG_HOME/ XDG_CACHE_HOME, and CI. Every other variable is withheld, including other vendors' API keys and CLOUDFLARE_API_BASE_URL (which would redirect your Cloudflare token to another host). The count withheld is printed as a NOTE.

If a deploy needs a variable that is not on the list, add it by name:

CLOUDFLARE_DROP_ENV_PASSTHROUGH="WRANGLER_LOG,CLOUDFLARE_API_BASE_URL" \
  node references/deploy.mjs report.html

The names it forwarded are printed back, so the widening is never silent.

Optional six-digit access code

node references/deploy.mjs ./publish/report.html --permanent -otp --name private-report

Requires an authenticated Cloudflare account supporting Workers Static Assets and SQLite Durable Objects. Wrangler provisions the limiter through a migration; the token must also permit that deployment. No token is required for ordinary temporary previews. Check node --version and npm --version (install Node.js with npm if missing); Wrangler is obtained automatically via npm.

After successful protected verification, deliver RESULT_URL and OTP_CODE as separate values to the requesting user. Never put the code in a URL, report, screenshot, public log, claim link, or index. Do not guess or log it again on failure. This flag means a shared access code, not email/SMS delivery, TOTP, or a single-use code: readers may reuse it, and every protected redeploy generates a new code and invalidates old sessions. Permanent deployments do not use preview renewal or archival.

All HTML and static assets pass through server-side authentication before their bytes are sent. Anonymous responses contain only the standalone verification screen; viewing source cannot reveal the report. Correct input sets a signed, host-bound HttpOnly, Secure, SameSite=Strict cookie for one hour. Responses are private, no-store. The Worker enforces a durable 15-minute attempt budget: 10 per client IP and 100 across the deployment (including successful logins). Limits can temporarily block legitimate readers sharing an IP; there is no insecure fallback. Once authorized, a reader can view source and save content normally.

Protected verification checks anonymous paths, rejects a wrong code, and checks the exact original HTML with an authenticated session. If verification or deployment fails, report failure and keep the local deliverable; do not publish it without protection. Server configuration lives outside the assets directory in a private temporary folder, which is removed after the protected deployment attempt. Technical review and tests: OTP security review.

The TTL is a display, not a lifetime

The countdown baked into the page says how long the link is expected to be useful. It does not control the real lifetime — Cloudflare does:

  • On a temporary preview, Cloudflare hard-expires at 60 minutes. A longer TTL is clamped down and TTL_CLAMPED is printed. The page must never promise three hours on a link that dies in one.
  • On a permanent deploy, no countdown is injected at all — a countdown on a link that never dies is the same lie in the other direction.

The default is 60m for exactly this reason. A longer default would be dead configuration: previews clamp it away, permanent deploys drop it entirely, so it would never once reach a reader's screen. --ttl is therefore for shortening the window ("this is only good for the next 30 minutes"), not extending it.

Want a link that outlives the hour? That's not a TTL problem — set CLOUDFLARE_API_TOKEN and deploy permanently, or claim the preview.

The OAuth trap (why --no-pause-oauth exists)

Wrangler refuses --temporary when it detects any existing auth, but a non-interactive shell can't complete an OAuth login either. A machine with a browser-based wrangler login therefore deadlocks: too authenticated for a preview, not authenticated enough to deploy.

The escape is to move the OAuth config aside for the duration of the deploy. This touches the user's credential file, so it is:

  • opt-out-able (--no-pause-oauth),
  • restored in a finally block — even if the deploy crashes,
  • covered by a test that asserts restoration after a thrown deploy.

If you want the permanent path instead, set CLOUDFLARE_API_TOKEN (Workers Scripts: Edit is enough) and the pause never happens.

Renewing an expired preview

node references/deploy.mjs renew <old-url|id> [--ttl 30m]

What it does: resolves the id from the url (the worker name — the first *.workers.dev host label; legacy drop-{id} urls stay recognised) → reads the deploy index → takes the archived HTML copy → strips the stale countdown and re-injects a fresh one → redeploys via Wrangler under the ORIGINAL worker name (so the renewed link stays recognisable) → self-verifies the full content is live (size + sentinel, not just a 200) → records renewed_from (the chain back to the original) → prints the NEW url, expiry, RENEWED_FROM, and RENEW_COUNT.

Expectation honesty — renew returns a new url, not the original. Drop cannot revive a dead link; a renew is a fresh deploy of the same content, so the *.workers.dev address changes. Say this plainly when you deliver a renewed link. If the id was never archived (deployed before indexing, or from another machine), renew fails loudly — it won't guess or invent a link.

Claim etiquette — offer the permanent link only at the 3rd renew (U1b). Most deliveries are just the new link + a one-line expiry reminder, nothing else, like a normal person — no "claim it to keep it forever" pitch on every message. The command gates this for you: it prints RENEW_COUNT and only surfaces a CLAIM_LINK once the same content has been renewed 3 times (RENEW_COUNT >= 3); before that it prints CLAIM_OFFER none. Follow that signal — deliver just the link + expiry on the first delivery and the first two renews, and mention claiming only when the tool surfaces the claim link (a page renewed three times is one the viewer keeps returning to, so keeping it permanently is finally worth raising).

The deploy index, briefly

  • Home resolves in exactly two portable layers: $CLOUDFLARE_DROP_HOME > (standalone) ~/.cloudflare-drop/. It is never the skill dir or a session workspace — those get committed or cleaned up, so an index there would dangle. The skill carries no host-app awareness; an embedding app points the index at an instance-specific dir purely by setting CLOUDFLARE_DROP_HOME in the deploy environment (there is no baked-in middle layer).
  • index.jsonl — one line per deploy, keyed on the drop id (title/summary/deploy-time/expires_at/claim_url/sha256/renewed_from).
  • artifacts/<sha256>.html — a content-addressed copy of the deployed page; identical content is stored once (sha256 dedupe).
  • Pruning (keep it small, don't over-build a GC): artifacts are content-addressed, so it's safe to periodically delete old files — find <home>/artifacts -mtime +2 -delete. An expired drop can't be renewed once its content is gone anyway, and a fresh deploy re-archives.

When NOT to use

  • The deliverable isn't a static site (a server app, an image, a PDF to download) → wrong tool.
  • You have no Node/npm → can't run Wrangler; offer the file instead.

Delivery discipline

  1. Always state the mode. Permanent → say it's permanent. Temporary → say it expires in ~60 minutes and offer the claim link.
  2. Upload the whole folder for multi-file pages. A lone index.html that references style.css renders broken. The stager copies siblings automatically.
  3. Fail open, never fabricate. No URL, failed verify, no Node? Say so plainly and offer the HTML file: "I couldn't publish it just now — want the file?" A made-up workers.dev link is worse than an honest failure.
  4. Check the content before publishing. Deploying makes it publicly reachable by URL; don't publish credentials or someone else's private data.

Anti-patterns

  • Handing back a preview URL without the 60-minute caveat — it silently breaks an hour later.
  • Inventing a *.workers.dev link, or reporting one that never returned 200.
  • Passing --ttl 3h and then telling the user the link lasts 3 hours — the clamp exists precisely because it doesn't. Only a permanent deploy outlives the hour.
  • Leaving the user's OAuth config parked (only possible if you bypass the CLI and call deployWithWrangler yourself without the finally).
  • Using this for something that must persist without setting a token — use the permanent path or Pages/Workers.
  • Uploading a page without its assets — a lone index.html that references style.css/app.js/images renders broken.
  • Ignoring a STAGED_REVIEW that flagged something. It is a report, not a gate, so the deploy succeeded and the file is already public. Say what was flagged.

レビュー

まだレビューはありません。使ってみた感想をお寄せください。

同じリポジトリのスキル

概要と使いどころ

explainer

無料

Requires OFOX_API_KEY — create one at https://app.ofox.ai. Turn an article, doc or release note into a short explainer clip — one person to camera, or a voiceover over illustrative footage. The user supplies the source text and the model generates the speech; audio cannot be uploaded, measured. A 30-second clip holds about eighty spoken words in eight sentences — measured, and well under a tenth of a 1,200-word post — so this skill does not summarise an article, it picks the single idea worth saying and helps choose which one. Use when a user asks to turn writing into a short spoken video, e.g. "make a 30-second explainer from this blog post", "explain this feature in a short video", "turn our changelog into a clip", "a quick video explaining what this paper found". Do not use for a scene between people (see seedance-short-drama), a brand or product ad (see seedance-ad-creative), a handheld creator clip (see ugc-ads), or when the user already has both a portrait and the finished words (see talking-head). Budget sentences as well as words — each sentence boundary costs about 0.7 seconds of silence, so a script with more sentences runs longer at the same word count.

日本語の概要は準備中です。原文の説明を表示しています。

ofoxai/skills22026年9月22日 更新

hal-image

無料

Handle images with ImageMagick (magick) — read metadata, resize, crop, rotate, convert format, combine images (side-by-side or grids with montage), overlay logos/watermarks, and losslessly compress with oxipng before sending. Use when the user sends an image to process, when you produce an image to deliver, or before attaching any image to a message or upload — compressing first keeps transfers fast and tokens low. Core discipline - always compress before delivering, never expose local file paths to the user, and fail open (if a tool is missing or a step errors, pass the original through unchanged; never block the task).

日本語の概要は準備中です。原文の説明を表示しています。

ofoxai/skills22026年9月22日 更新

hal-vault

無料

Securely store, search, and use secrets (API keys, tokens, passwords, SSH keys) with hal-vault, an SSH-key encrypted local secret store. Use when the user shares a credential that should be saved, asks what secrets are stored or where a key is, or when a command/workflow needs a secret injected. Core discipline - never print raw secret values into chat, logs, or files; reference secrets only by their masked form, and use --reveal only to feed another process, never into a command argument (where it lands in the machine's process table) or into text you write down.

日本語の概要は準備中です。原文の説明を表示しています。

ofoxai/skills22026年9月22日 更新

Requires OFOX_API_KEY — create one at https://app.ofox.ai. Change one thing in an image you already have and leave the rest of the picture alone — swap the background, recolour a part, remove or add an object, clean up a photo — from a local jpeg/png/webp file. Delegates to ofox-image-core's `edit` subcommand (POST /v1/images/edits, one synchronous request), prices the job with --dry-run before spending, and reports the real token cost including the uploaded picture, which is billed. Use when a user hands over an image and asks for a change to it, e.g. "change the background of this photo to a beach and keep the person unchanged", "make this button green", "remove the car in the background", or "put this product on a plain white background". Do not use to draw a new image from a text description with no input picture (that is ofox-image-core's `generate`), to produce a set of several images to choose between (see product-image), or to turn a photo into video (see seedance-product-video or seedance-ad-creative). Editing the content of an existing video — "change the background of my clip, keep the product" — has no route here and none in the video API either (measured; the mode field an edit would use is accepted and silently ignored, so nothing errors); this skill edits a single still, and routing such a request to a video skill generates brand-new footage instead of changing theirs.

日本語の概要は準備中です。原文の説明を表示しています。

ofoxai/skills22026年9月22日 更新

Requires OFOX_API_KEY — create one at https://app.ofox.ai, plus two images you already have, a start frame and an end frame. Animates the motion between them as one video — both frames go into a single Ofox video job, the clip opens on A, closes on B, and the model fills the middle. Use when a user has two stills and wants the in-between animated, e.g. "here is the before and the after, animate the transition", "make a video that starts on this image and ends on that one", "tween these two frames", or "move the object from where it sits in the first picture to where it sits in the second". Do not use when only one image exists (animating a single frame is seedance-ad-creative or seedance-product-video), or when the pair is two states of a user interface (see product-demo).

日本語の概要は準備中です。原文の説明を表示しています。

ofoxai/skills22026年9月22日 更新

Requires OFOX_API_KEY — create one at https://app.ofox.ai, plus the music file the finished video must carry. Your audio never reaches the API (measured) — the visuals are written to the track's tempo, mood and sections, then your own file is laid on locally at zero cost. One job caps at 30 seconds, so a three-minute song is six jobs minimum and the cost table says that before anything is spent. Use when a user has a specific piece of music and wants visuals for it, e.g. "make a music video for this track", "visuals for my song", "an MV for this instrumental", "generate footage cut to this beat". Do not use for cheap vertical social drafts (shorts-reels), a brand film that happens to have a music bed (seedance-ad-creative), or when there is no particular audio file the finished video has to carry.

日本語の概要は準備中です。原文の説明を表示しています。

ofoxai/skills22026年9月22日 更新

ofoxai のスキルをすべて見る

このスキルの問題を報告する