Bud is a device-agent platform for AI-assisted terminal access across remote machines. The repo has three runnable packages:
- bud/: Rust daemon that runs on the target machine
- service/: Fastify backend with Better Auth, REST/SSE, and Bud WebSocket gateway
- web/: React + Vite UI
Start with AGENTS.md for repo rules and bud.spec.md for architecture.
- Node
20.19+or22.12+for the Vite 7 web toolchain pnpm- Rust stable toolchain
- PostgreSQL
tmuxon any machine running the Bud daemon- Optional for the local HTTPS profile:
mkcert,caddy, and local wildcard DNS for*.bud-show.test
- Install dependencies:
cd service && pnpm install
cd ../web && pnpm install- Copy env templates:
cp service/.env.example service/.env
cp web/.env.example web/.env
cp bud/.env.example bud/.env- Fill the service auth vars in service/.env.example:
APP_BASE_URLFor local Vite dev this is usuallyhttp://localhost:5173BETTER_AUTH_URLFor local auth/iOS dev this is usuallyhttp://localhost:5173even though the Fastify process itself still listens onhttp://localhost:3000API_AUDIENCEUsuallyhttp://localhost:5173/apifor the default local setupBETTER_AUTH_SECRETBETTER_AUTH_TRUSTED_ORIGINSUsuallyhttp://localhost:5173,http://localhost:3000GITHUB_CLIENT_ID/GITHUB_CLIENT_SECRETGOOGLE_CLIENT_ID/GOOGLE_CLIENT_SECRET
- Configure OAuth callbacks:
- GitHub callback:
http://localhost:5173/api/auth/callback/github - Google callback:
http://localhost:5173/api/auth/callback/google
If you are testing from another machine or a phone, replace localhost with your LAN host everywhere: APP_BASE_URL, BETTER_AUTH_URL, BETTER_AUTH_TRUSTED_ORIGINS, the OAuth callback URLs, VITE_API_PROXY_TARGET, and BUD_SERVER_URL.
- Create the database and push schema:
createdb bud
cd service
pnpm db:push- Start the backend:
cd service
pnpm dev- Start the web app:
cd web
pnpm dev- Start the Bud daemon:
cd bud
set -a; source .env; set +a
cargo run -- --terminal-enabledBud should print a claim URL and QR code. Open the web app or scan the QR, sign in with GitHub or Google, approve the device, and wait for the daemon to reconnect.
The current prototype deployment shape is:
webandservicedeploy separately- browser and hosted auth traffic stay same-origin
- one public origin fronts app routes,
/api/*,/.well-known/*, and/ws servicestays single-instance for now
For a deployed prototype environment, use one public origin such as https://bud.example.com:
APP_BASE_URL=https://bud.example.comBETTER_AUTH_URL=https://bud.example.comAPI_AUDIENCE=https://bud.example.com/api- browser
VITE_API_BASE_URLshould usually stay unset - Bud daemon
BUD_SERVER_URLshould bewss://bud.example.com/ws
Routing contract for the public origin:
/api/*->service/.well-known/*->service/ws->service- everything else ->
web
Checked-in deployment artifacts for this prototype shape:
- render.yaml: Render Blueprint for
web,service, and PostgreSQL - deploy/cloudflare/bud-front-door-worker.js: Cloudflare Worker source for app/API path routing and
*.bud.showweb-view proxy routing - plan/deploy/cloudflare-front-door-runbook.md: Cloudflare path-routing and deploy-order runbook for the single public origin
Database note:
- local development uses
pnpm db:push - deployed/prototype environments should use checked-in migrations, not
db:push
- Terminal 1:
cd service && pnpm dev - Terminal 2:
cd web && pnpm dev - Terminal 3:
cd bud && set -a; source .env; set +a && cargo run -- --terminal-enabled
The default local setup does not require Caddy or mkcert. Use this optional profile when you need production-like browser behavior for proxied web views, especially secure iframe cookies, split app/proxy sites, and WSS upgrades.
The checked-in HTTPS profile uses literal localhost for the app/auth/API
origin because Google OAuth accepts localhost but rejects arbitrary
.localhost hostnames as authorized origins. Proxied sites use a separate
reserved .test site with explicit local DNS so Safari and iOS WKWebView do
not depend on browser-specific wildcard .localhost behavior.
- App/auth/API/SSE/Bud WebSocket origin:
https://localhost:3443 - Proxy endpoint hosts:
https://<slug>.bud-show.test:3443
Install the local HTTPS tools once:
brew install mkcert caddy dnsmasqConfigure local wildcard DNS for proxy endpoints:
mkdir -p "$(brew --prefix)/etc/dnsmasq.d"
printf 'port=53\nlisten-address=127.0.0.1\naddress=/bud-show.test/127.0.0.1\n' > "$(brew --prefix)/etc/dnsmasq.d/bud-show.test.conf"
grep -q 'dnsmasq.d' "$(brew --prefix)/etc/dnsmasq.conf" 2>/dev/null || printf 'conf-dir=$(brew --prefix)/etc/dnsmasq.d/,*.conf\n' >> "$(brew --prefix)/etc/dnsmasq.conf"
sudo mkdir -p /etc/resolver
printf 'nameserver 127.0.0.1\n' | sudo tee /etc/resolver/test
sudo brew services restart dnsmasqmacOS note: /etc/resolver/test expects the scoped DNS server on port 53 for
this setup. Do not point it at dnsmasq running on a non-53 localhost port. If
127.0.0.1:53 is unavailable, bind dnsmasq to a loopback alias on port 53 and
put that alias in /etc/resolver/test.
Verify DNS before continuing:
dscacheutil -q host -a name smoke.bud-show.testThen run the repo-root setup command:
pnpm dev:https:setupThat command runs mkcert setup, generates the Caddy cert files in .certs/,
and checks that smoke.bud-show.test resolves to 127.0.0.1. mkcert -install may prompt for your macOS password because it adds a local CA to the
system trust store. Run setup in an interactive terminal if your editor or
agent shell cannot show the sudo prompt.
Use the HTTPS env examples as opt-in replacements or copy their values into your existing local env files:
cp service/.env.https.example service/.env
cp web/.env.https.example web/.env
cp bud/.env.https.example bud/.envFill provider secrets in service/.env, then start the HTTPS profile from the
repo root:
pnpm dev:httpspnpm dev:https owns the service dev server, the web dev server, and Caddy. It
also injects NODE_EXTRA_CA_CERTS="$(mkcert -CAROOT)/rootCA.pem" before
starting Node child processes so service-side OAuth/JWKS verification trusts
the local mkcert CA.
In another terminal, start the Bud daemon with the HTTPS env:
cd bud && set -a; source .env; set +a && cargo run -- --terminal-enabledCheck an already-running HTTPS profile with:
pnpm dev:https:checkProvision the local iOS OAuth client for the HTTPS profile with:
pnpm dev:https:provision-iosOpen https://localhost:3443. To switch back to the default HTTP flow, stop
pnpm dev:https and restore the default env values from the .env.example
files.
If Caddy returns a 502 for /, confirm the Vite web dev server is running at
http://localhost:5173; the HTTPS front door proxies app routes to that
server.
- service/README.md: backend setup, auth env, DB push, local testing
- web/README.md: frontend env and dev server setup
- bud/README.md: daemon env, claim flow, and local launch
- docs/proto.md: protocol shapes and versions
- design/: design docs
- plan/: phased implementation plans
- debug/: debugging notes
Licensing note: Bud is public for early release-flow testing. It is not yet open source. Component-level licenses will be added before the first stable public release.