尚未偵測到更新。GitHub 發布版本後會顯示在這裡。
個人 GitHub 帳號下公開儲存庫的擁有者可以登入並驗證所有權,自行管理介紹,無需管理員核准。
登入並產生驗證檔案,在 30 分鐘內將其提交至此儲存庫的預設分支。其他分支或分叉儲存庫中的檔案無效。然後在下方檢查檔案,即可無需管理員核准直接管理專案。請保留檔案以維持管理權限。
如需登入,將前往登入頁面。登入後請回到此處,再次點擊所選的驗證按鈕。
在專案資料夾中執行 /nomorevibe verify,即可驗證所有權並自行管理介紹。
一分鐘完成驗證Mint per-user, revocable Claude/agent skills from a Cloudflare Worker — the API secret bakes itself into the skill at download time. HMAC-derived keys, never stored; one-integer revocation; no app-level auth.
翻譯準備中
取自儲存庫 README
正在載入完整 README。 以下為已儲存的摘錄。
Mint per-user, revocable Claude skills from your own Cloudflare Worker — the secret bakes itself into the skill at download time.
Live, against stash-demo.hsieh-ting-lin.workers.dev: the credential is baked in (never typed), the CLI just works, then revoking it server-side kills the already-downloaded skill on the spot.檢視完整 README ↗Mint per-user, revocable Claude skills from your own Cloudflare Worker — the secret bakes itself into the skill at download time.
Live, against stash-demo.hsieh-ting-lin.workers.dev: the credential is baked in (never typed), the CLI just works, then revoking it server-side kills the already-downloaded skill on the spot.
A tiny, self-contained reference implementation of a paradigm: instead of
pasting an API key into every agent and every machine, your server mints a
personalized Agent Skill
on download — a .skill bundle with a .env already baked in. The agent
unzips it and immediately knows your infra, authenticated, with a credential
that is scoped to one person, derived not stored, and revocable with a single
integer.
Runs free on Cloudflare Workers + KV + D1. No app-level auth code — Cloudflare Access handles identity; this repo handles minting.
Every time you start a new project, your agent doesn't know your private infra. So you do one of two bad things:
Static secrets don't fit a world where agents are the API consumers. You want to hand each agent (each person, each laptop) its own credential, know who is calling, and be able to kill exactly one of them without rotating everyone.
The skill carries its own secret, and the server mints it per user.
┌─────────────┐ Access login ┌──────────────────────────┐
│ browser │ ────────────────▶ │ Worker: GET /api/me/skill│
│ (console) │ │ bakes .env { base,key, │
└─────────────┘ ◀── stash.skill ─│ email } + zips skill/ │
(zip w/ .env) └──────────────────────────┘
│ unzip into ~/.claude/skills/
▼
┌─────────────┐ Bearer key + ┌──────────────────────────┐
│ any agent │ X-User-Email │ Worker: /api/kv/* │
│ (stash CLI)│ ────────────────▶ │ re-derives key, verifies │
└─────────────┘ ◀── data ────────│ (the ONLY gate, public) │
└──────────────────────────┘
The key is never stored anywhere:
key = "stashk_" + base64url( HMAC-SHA256( SERVER_SECRET, `${email}:${version}` ) )
SERVER_SECRET is one global Worker secret.version is a per-user integer in D1 — the only per-user state.(secret, email, version) and constant-time compares. Nothing to look up, nothing to leak.| Static API key | skill-with-secret |
|---|---|
| Stored in DB / env → leaks if either leaks | Derived, never stored. Leak the whole DB → zero usable keys |
| One key for everyone | One key per person, bound to their email by HMAC |
| Revoke = rotate the shared key = break everyone | Revoke one user by bumping their integer version |
| Agent must be told the URL + key by hand | Baked into the skill at download — agent just works |
| Can't tell who's calling | Every call carries a verified email |
| Anyone can probe "is this email a member?" | Anti-enumeration: unknown email and bad key are indistinguishable, with uniform timing |
This is the right shape for the agent era: a credential that is minted, self-installing, attributable, and individually revocable — with the auth boundary kept at the edge (Cloudflare Access), not reimplemented in your app.
A public, no-login demo running the exact same Worker with DEMO_MODE=1, which
swaps Cloudflare Access for a throwaway per-browser identity. Open it, download a
real .skill, and rotate it to watch the old one get revoked — no account
needed.
Stand up your own in one command (wrangler login first):
pnpm setup:demo # creates D1 + KV, sets the secret, deploys — prints the URL
CI can also auto-deploy on every push to main
(.github/workflows/deploy-demo.yml). Details in docs/DEMO.md.
It's a sandbox: throwaway secret, disposable KV, ephemeral identities. The real paradigm keeps Access in front (see Quickstart).
pnpm install
cp wrangler.toml.example wrangler.toml # fill in ids (see docs/SETUP.md)
wrangler secret put STASH_KEY_SECRET # openssl rand -hex 32
pnpm db:migrate:remote
pnpm deploy
Then put the minting routes behind Cloudflare Access (via the Zero Trust
dashboard, or any CLI that drives the Access API), open the console at your
Worker's URL, and click Download stash.skill. Full walkthrough:
docs/SETUP.md.
After unzipping the download into ~/.claude/skills/stash/:
stash put demo "it works" # ① the minted skill talks to your Worker
stash get demo # → it works
# …click "Rotate key" in the console…
stash get demo # → 401: this skill was revoked ← the whole point
# …re-download, unzip, retry…
stash get demo # → it works again
That rotate → 401 → re-download arc is the entire value proposition in three
commands: a credential you can kill and re-mint, per person, in one click.
There's also a browser path — the console page (/) can put/get/ls
against the protected resource live, so you can see the loop without a terminal.
worker/
index.ts # route wiring: public API (bearer) vs minting (Access)
lib/apikey.ts # HMAC key derivation + the anti-enumeration middleware ★
lib/access.ts # Cloudflare Access JWT verify (+ localhost dev bypass)
routes/resource.ts # the example protected resource — a per-user KV stash
routes/mint.ts # /key, /key/rotate, /skill (zips the bundle + baked .env)
console.ts # the self-contained demo page
skill/ # SOURCE OF TRUTH for the minted skill (SKILL.md + CLI)
scripts/gen-bundle.mjs# snapshots skill/ into the Worker (it has no filesystem)
migrations/0001_init.sql # users(email, key_version) — the salt, never the key
Want this for your infra? Replace routes/resource.ts with your own
endpoints and rewrite skill/ to drive them. The minting + auth machinery
(apikey.ts, mint.ts, access.ts, gen-bundle.mjs) is the reusable core —
that's the part you paste into every project.
SubtleCrypto.timingSafeEqual over fixed-
length digests).STASH_KEY_SECRET is unset.401 and run the same
HMAC + compare work, so membership can't be enumerated by response or timing.key_version is immediate and total for that user, and
invisible to everyone else.MIT — see LICENSE.