AgentFilesystem is a Cloudflare-native file manager for humans and agents.
apps/web: TanStack Start app deployed to Cloudflare Workerspackages/contracts: shared Zod API contractspackages/db: Drizzle schema, helpers, and SQL migrationspackages/cli: Node CLI for login and filesystem management
- Install dependencies with
pnpm install - Configure secrets for GitHub OAuth and R2 presigning
- Run
pnpm --filter @agfs/web cf-typegen - Run
pnpm dev
pnpm dev now auto-applies local D1 migrations before the TanStack Start worker boots, so the Better Auth and AGFS tables stay in sync with local development.
Copy .env.example into your local secret manager or Worker secret setup and provide:
BETTER_AUTH_SECRET,GITHUB_CLIENT_ID,GITHUB_CLIENT_SECRET- Optional:
PAID_PLAN_EMAILSas a comma-delimited list for accounts that should resolve to the paid plan R2_ACCOUNT_ID,R2_BUCKET_NAME,R2_ACCESS_KEY_ID,R2_SECRET_ACCESS_KEYAPP_URL
For local Cloudflare development, put Worker secrets in apps/web/.dev.vars.example as apps/web/.dev.vars. wrangler.jsonc already supplies APP_URL and R2_BUCKET_NAME as non-secret vars.
PAID_PLAN_EMAILS is optional. If set, each comma-delimited email in the list is normalized and granted the paid storage plan.
R2_ACCOUNT_ID, R2_ACCESS_KEY_ID, and R2_SECRET_ACCESS_KEY are optional for local development now. If they are missing, AGFS falls back to a same-origin Worker upload endpoint backed by the local FILES_BUCKET binding instead of generating presigned R2 upload URLs.
pnpm dev: start the TanStack Start app locallypnpm d1:migrate:local: apply the full AGFS + Better Auth schema to the local D1 databasepnpm d1:migrate:remote: apply the production D1 schema to Cloudflarepnpm r2:cors: apply the production R2 CORS policypnpm deploy:production: build and deploy the production Worker toagfs.devpnpm check: run TypeScript checks across the workspacepnpm test: run unit testspnpm --filter @agfs/web cf-typegen: generate local Cloudflare binding types
- One D1 database named
agfs-dbbound asDB - One R2 bucket named
agfs-filesbound asFILES_BUCKET - R2 S3 API credentials stored as Worker secrets for presigned uploads
The repository is now wired to the live D1 database ID e40aac3b-5468-468c-b110-ac6a6ca4cece and a dedicated Wrangler production environment that deploys to the custom domain agfs.dev.
-
Create a production GitHub OAuth app with:
- Homepage URL:
https://agfs.dev - Authorization callback URL:
https://agfs.dev/api/auth/callback/github
- Homepage URL:
-
In the Cloudflare dashboard, create an R2 API token with Object Read & Write access for
agfs-files. Copy the Access Key ID and Secret Access Key once. -
Set the production Worker secrets:
pnpm --filter @agfs/web exec wrangler secret put BETTER_AUTH_SECRET --env production pnpm --filter @agfs/web exec wrangler secret put GITHUB_CLIENT_ID --env production pnpm --filter @agfs/web exec wrangler secret put GITHUB_CLIENT_SECRET --env production pnpm --filter @agfs/web exec wrangler secret put R2_ACCOUNT_ID --env production pnpm --filter @agfs/web exec wrangler secret put R2_ACCESS_KEY_ID --env production pnpm --filter @agfs/web exec wrangler secret put R2_SECRET_ACCESS_KEY --env production
-
Apply the R2 CORS policy:
pnpm r2:cors
-
Apply database migrations:
pnpm d1:migrate:remote
-
Deploy the Worker:
pnpm deploy:production
-
Smoke test:
- Sign in with GitHub at
https://agfs.dev - Upload a file in the web app
- Create a share link and open it in a private window
- Run
AGFS_BASE_URL=https://agfs.dev agfs whoami - Run
AGFS_BASE_URL=https://agfs.dev agfs upload ./shot.png /screenshots/shot.png --share 15m
- Sign in with GitHub at
Production deploys now come from Cloudflare's Git integration in the Cloudflare dashboard.
Recommended settings for this repository:
- Worker / project:
agfs-dev-production - Git repository:
nearbycoder/agfs - Production branch:
main - Root directory: repository root
- Build command:
pnpm --dir apps/web run build:production - Deploy command:
pnpm --dir apps/web exec wrangler deploy --env production
Optional watch paths that fit this monorepo well:
apps/web/**packages/**package.jsonpnpm-lock.yamlpnpm-workspace.yamltsconfig.base.json
If Cloudflare enables preview builds for non-production branches and asks for a preview deploy command, use:
pnpm --dir apps/web exec wrangler versions upload --env productionThe production app secrets still live in Cloudflare, not GitHub:
BETTER_AUTH_SECRETGITHUB_CLIENT_IDGITHUB_CLIENT_SECRETR2_ACCOUNT_IDR2_ACCESS_KEY_IDR2_SECRET_ACCESS_KEY
