dumbtv
dumbtv takes the ads, screen tracking and update nags out of your Fire TV over ADB. No root, none of your apps touched, every step can be undone. Free and open source.
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-lev
SecurityTypeScript · PythonGitHub @htlin222OnlineOwner unconfirmed
Have you tried it? One tap is enough. No sign-in needed.
No updates detected yet. GitHub releases will appear here.
Owners of public repositories under a personal GitHub account can sign in to verify ownership and manage the introduction themselves. No administrator approval is needed.
Sign in, generate a verification file, and commit it to this repository’s default branch within 30 minutes. Files on other branches or forks do not count. Then check the file below to manage the project without administrator approval. Keep the file to retain your access.
If needed, you will go to sign-in. After signing in, return here and press your chosen verification button again.
Run /nomorevibe verify in your project folder to verify ownership and manage the introduction yourself.
Verify in one minuteAsk about other verification options
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.
Taken from the repository README
Loading the full README. The saved excerpt is shown below.
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.Read the full 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.