The CI lane with a device cert
The problem: some work can't run in a vibe's backend — codegen, heavy builds, anything needing a real container. You want CI to participate in your app's workflow without scattering API tokens through GitHub secrets.
The pattern: enroll a dedicated device for your account, hand its certificate to the runner, and let it speak the same CLI you do.
Enroll the device
vibes-diy login enrolls the current machine with a device certificate —
that's the credential the CLI uses everywhere. For CI, enroll once locally,
then export the keybag item it wrote (the device's private key + signed
cert, not just an id) into the runner's environment:
shnpx vibes-diy login # browser flow; enrolls this device
# The enrollment lands in ~/.fireproof/keybag/<id>.json. Copy that file's
# contents into a CI secret — base64 avoids JSON quoting trouble:
base64 -w0 ~/.fireproof/keybag/<id>.json # -> secret BUILDER_DEVICE_ID
yaml# .github/workflows/your-lane.yaml
env:
VIBES_DEVICE_ID: ${{ secrets.BUILDER_DEVICE_ID }}
VIBES_DEVICE_ID accepts the keybag JSON raw or base64-encoded (the full
file or its bare { deviceId, cert } item), and an interactive login already
on the machine always wins over it. With it set, every CLI command runs
headless as your account — no browser, no prompt:
shnpx vibes-diy db query --vibe you/your-hub --db requests # pick up work
npx vibes-diy db put --vibe you/your-hub --db requests '…' # report back
npx vibes-diy generate "the requested app" --handle yourbot --app-slug m-abc123
Why a cert and not a token
The device cert is a builder identity, not a capability grab-bag. It
authenticates as your account, so it passes exactly the gates your
access.js already defines — there's no second permission system to design,
and revoking it is deleting the device. Meanwhile the dangerous
credentials (social tokens, API keys) stay in the vibe's
write-only vault: the two lanes coordinate
entirely through status documents and
never share a secret. If the runner is compromised, the attacker gets a
revocable builder cert — not your Bluesky password.
In production
The platform's mention-builds pipeline is this exact split:
mention-builds.yaml
runs on a cron, and
scripts/mention-builds.mjs
drives the public CLI — the same one you just installed — to pick up
pending-build docs, generate each requested app, verify it actually
serves, and write the result back. (It stores the keybag under its own secret
name, MENTION_BUILDER_DEVICE_ID, and exports it as VIBES_DEVICE_ID at
runtime — the env var name is what the CLI reads; the secret name is yours to
choose.) The workflow self-skips until its secrets
exist, so the lane is dark by default.
Anything that can run a shell can join your app's workflow this way: a
laptop cron, a Raspberry Pi, another CI system. And when the "script" is an
AI agent, skip the shell parsing entirely — npx vibes-diy mcp exposes the
same list/get/put/query/delete surface as an MCP server any agent can mount.