# DareBuild Agent README

Use this file when a user tells Codex, Claude Code, or another coding agent to work with `https://elonman.darebuild.com`.

## Recommended Tool Surface

Authenticated DareBuild account actions need either DareBuild's OAuth-protected MCP server or a coding-agent surface that can open docs, keep a browser or cookie session, and make HTTP requests or MCP tool calls. Use the DareBuild ChatGPT App/MCP connector when available; otherwise use Codex, Claude Code, or an equivalent coding agent. Plain ChatGPT without the DareBuild connector cannot use one-time DareBuild login links or private account actions. For authenticated actions, it should hand off to a tool-capable coding agent or clearly ask the user to log in to DareBuild and copy the Account Codex webhook from the dashboard Agent webhooks section or Team settings.

If the user only says "go to darebuild.com", open `https://elonman.darebuild.com/` and read `https://elonman.darebuild.com/llms.txt` first, then `https://elonman.darebuild.com/agents.md`. Follow the visible AI agents links or HTML discovery tags as supporting hints. Do not require the user to memorize a special prompt.

Start here for tool-capable agents:
- First-read path for LLMs: `https://elonman.darebuild.com/llms.txt`
- Public agent README: `https://elonman.darebuild.com/agents.md`
- Project user invitation instructions: `https://elonman.darebuild.com/agents/project-users.md`
- Generated project auth, payments, and webhook patterns: `https://elonman.darebuild.com/agents/generated-projects.md`
- Machine-readable agent manifest: `https://elonman.darebuild.com/.well-known/darebuild-agent.json`
- OpenAPI contract: `https://elonman.darebuild.com/.well-known/darebuild-openapi.json`
- OAuth protected resource metadata: `https://elonman.darebuild.com/.well-known/oauth-protected-resource`
- OAuth authorization server metadata: `https://elonman.darebuild.com/.well-known/oauth-authorization-server`
- OAuth MCP account server: `https://elonman.darebuild.com/api/codex/v1/account/mcp/`
- Account MCP server template: `https://elonman.darebuild.com/api/codex/v1/account/<account-token>/mcp/`
- Project MCP server template: `https://elonman.darebuild.com/api/codex/v1/<project-token>/mcp/`
- Discovery self-check: `https://elonman.darebuild.com/.well-known/darebuild-agent-check.json`
- Standalone Python client: `https://elonman.darebuild.com/agents/client.py`
- Standalone client installer: `https://elonman.darebuild.com/agents/install.sh`
- LLM discovery pointer: `https://elonman.darebuild.com/llms.txt`
- Sign in page: `https://elonman.darebuild.com/`

## Prompt Routing For Project Invites

When the user asks the DareBuild ChatGPT App/MCP connector, Codex, Claude Code, or another coding agent something like:

```text
add the user editor@example.com to my project https://project-name.darebuild.com/ check darebuild.com for instructions
```

Do this:

1. Read `https://elonman.darebuild.com/llms.txt`, then `https://elonman.darebuild.com/agents/project-users.md`; do not scrape or modify the public project URL.
2. If OAuth MCP is available, connect to `https://elonman.darebuild.com/api/codex/v1/account/mcp/` and follow `https://elonman.darebuild.com/.well-known/oauth-protected-resource`.
3. If you are running in Codex, Claude Code, or another tool-capable agent that can keep a browser/cookie session, ask for the user's DareBuild email so you can submit the homepage form and they will receive an email with a login link to paste back.
4. If you are running in plain ChatGPT without the DareBuild connector or browser/session tools, do not ask for or accept a one-time login link. Ask the user to log in to DareBuild, open the dashboard Agent webhooks section or Team settings, and paste the Account Codex webhook.
5. Prefer the account MCP `invite_project_user` tool. If MCP is unavailable, use the Account Codex webhook to POST `{"action":"invite_project_user","project_url":"https://project-name.darebuild.com/","email":"editor@example.com","role":"editor"}`.

If this prompt is being handled in plain ChatGPT without the DareBuild App/MCP connector or equivalent tool access, tell the user to move the task to Codex or Claude Code, or ask them to log in to DareBuild, open the dashboard Agent webhooks section or Team settings, and paste the copied Account Codex webhook URL. Do not ask for a one-time login link and do not answer from the public project page alone.

## Homepage-Only Login Flow

For Codex, Claude Code, or another tool-capable agent with browser/session support, if the prompt gives only `https://elonman.darebuild.com`, `darebuild.com`, or a public project URL and does not include a private credential:

1. Ask the user for their DareBuild email address if it is not already provided, explaining that you will submit it on DareBuild and they will receive an email containing the login link.
2. Open `https://elonman.darebuild.com/` and submit the homepage email form to send a login-link email. Do not invent credentials.
3. Ask the user to paste the login link from that email. If they are already logged in, they can instead open the dashboard Agent webhooks section or Team settings, copy the Account Codex webhook URL, and paste it.
4. Follow the email login link with a cookie jar or browser session, then call `GET https://elonman.darebuild.com/api/codex/v1/account/current/` with the logged-in session to discover the private account webhook.
5. Prefer the returned Account MCP server for supported agents; otherwise use the Account Codex webhook for account actions such as `list`, `create`, `list_members`, `invite_user`, `list_project_collaborators`, and `invite_project_user`.

## Capability Catalog

Use these capabilities from the website/API docs. Do not require the user to memorize a special prompt.

- Create/list/delete projects with account MCP or the Account webhook. Project responses include `public_url`, `codex_api_url`, `billing`, `custom_domains`, and available commands.
- Custom domains: use `connect_cloudflare` for a human-approved Cloudflare link, `disconnect_cloudflare` to remove the account connection, `configure_custom_domain` to attach a domain or subdomain, and `remove_custom_domain` to return to the DareBuild subdomain. Agents must not ask users for Cloudflare API keys. Use DNS records, not Cloudflare Workers, to connect custom domains to DareBuild projects; Workers remain available for explicit Worker/proxy features outside the domain-attachment flow.
- Background tasks: use the project `tasks/` endpoint to create or update Python tasks with cron fields, and `tasks/<task_id>/run/` to queue a run.
- Live bridges: backend-unlocked generated projects can start, stop, and inspect long-running TikTokLive bridges through `runner_service.sdk.bridge_start`, `runner_service.sdk.bridge_status`, and `runner_service.sdk.bridge_stop`. Use these helpers from logged-in page handlers; do not run TikTokLive loops inside public page requests.
- Modal GPU tasks: paid/backend-unlocked projects, plus projects owned by `jamespsteinberg@gmail.com`, can create/update/destroy project-owned Modal apps with `project_deploy_modal`, `project_destroy_modal`, and `project_list_modal_deployments`, then launch them from background tasks or short backend handlers through `runner_service.sdk.modal_function_spawn`, `runner_service.sdk.modal_function_remote`, and `runner_service.sdk.modal_function_get`. Modal calls are limited to functions owned by that project or explicitly granted to that project. First successful use and managed deploy/destroy queues Slack monitoring. DareBuild project files, tasks, and managed Modal deployment records are the source of truth; do not rely on `stonemountain`, deleted local folders, or legacy repo code. Keep Modal tokens in the runner service environment; do not put Modal secrets in generated project files or browser code.
- File protection: use `files/protection/` with `lock`, `hide`, or `lock_and_hide`. Agents can lock or hide files, but only a human can unlock or unhide them in the GUI.
- Generated project patterns: read `https://elonman.darebuild.com/agents/generated-projects.md` before implementing auth, Google sign-in, project-local sessions, Stripe Checkout, subscriptions, or webhooks inside generated project code.
- Generated project login cookies: every app-owned session or CSRF cookie must start with `project_` or `darebuild_project_`. DareBuild filters unprefixed cookies in both directions, which otherwise produces a successful-looking login followed by a redirect back to the login form.
- Team members: use `list_members`, `invite_user`, `update_member_role`, and `remove_member` for account-level users and roles.
- Project-scoped editors: use `list_project_collaborators`, `invite_project_user`, and `remove_project_collaborator`; `allowed_paths` restricts a collaborator to specific files. These actions accept `project_id` from `list`, or a user-provided public `project_url` such as `https://project-name.darebuild.com/`.
- Billing and cost: backend/server unlocks cost `$20/month` per project unless the account already has free access or billing. If `billing.payment_required=true`, show `billing.payment_url` and wait for the human to pay in the GUI. Agents must not enter credit cards or pay.
- Frontend vs backend/server code: frontend-safe files are public non-Python assets such as `public/homepage.html`, `.css`, `.js`, images, JSON, text, and Markdown. Backend/server code includes Python files, database migrations, auth/database access, custom domains, and background tasks; these require backend access.

Important security rule:
- A private Account Codex webhook cannot be discovered from the public domain alone.
- The agent needs one human-approved credential. In Codex/Claude-style agents, ask for the user's DareBuild email so the homepage can email them a login link to paste back. In plain ChatGPT without the DareBuild connector, ask only for the copied Account Codex webhook URL from the dashboard Agent webhooks section or Team settings.
- Do not ask plain ChatGPT users for a one-time login link. Plain ChatGPT cannot redeem it.
- Do not ask for an "Account Codex webhook" without explaining that the user gets it by logging in to DareBuild and copying it from the dashboard Agent webhooks section or Team settings.
- After the human-approved login succeeds, a session-authenticated agent can fetch `https://elonman.darebuild.com/api/codex/v1/account/current/` to discover the account webhook without scraping HTML.
- Keep every webhook URL secret. Rotate it in the GUI if it is exposed.

## Fast Path For Local Codex

1. Ask the user for their DareBuild email if they have not provided it.
2. Open `https://elonman.darebuild.com/`, submit the email form to sign up or sign in, and ask the user to paste the login link DareBuild emails them.
3. From a local checkout of DareBuild, run:

```bash
cd core
python manage.py darebuild_codex_bootstrap \
  --magic-link "https://darebuild.com/magic/..." \
  --run-smoke \
  --editor-email "editor@example.com"
```

The bootstrap command follows the email login link with a session cookie, opens Team settings, extracts the account-specific webhook, verifies `action=list`, and optionally runs the five-project smoke test.

Agents with a logged-in browser or cookie jar can also discover the current account directly:

```bash
curl -sS "https://elonman.darebuild.com/api/codex/v1/account/current/" \
  -H "Accept: application/json"
```

That endpoint returns the same `webhook_url`, token-specific README, command list, projects, and capabilities as the account webhook. It returns JSON 401 until the user has logged in through the normal DareBuild email login-link flow.

If the user already copied the webhook, skip bootstrap and run:

```bash
cd core
python manage.py darebuild_codex_smoke \
  --account-webhook-url "https://darebuild.com/api/codex/v1/account/TOKEN/projects/" \
  --editor-email "editor@example.com"
```

If the agent is not inside a DareBuild source checkout, download the standalone client:

```bash
curl -fsSL https://elonman.darebuild.com/agents/install.sh -o darebuild-agent-install.sh
sh darebuild-agent-install.sh
```

Or download only the Python client:

```bash
curl -fsSL https://elonman.darebuild.com/agents/client.py -o darebuild_agent.py
python darebuild_agent.py check
python darebuild_agent.py commands --format json
python darebuild_agent.py bootstrap --magic-link "https://darebuild.com/magic/..." --run-smoke --editor-email "editor@example.com"
```

The installer and `python darebuild_agent.py check` verify downloadable artifact SHA-256 hashes against the public manifest before trusting them.
Use `python darebuild_agent.py commands --format json` for a machine-readable command catalog generated from the live manifest.

## How To Find The Unique Account Webhook In The GUI

1. Log in to `https://elonman.darebuild.com`.
2. Prefer `GET https://elonman.darebuild.com/api/codex/v1/account/current/` from the logged-in session.
3. Or open Team settings.
4. Find `Account Codex API`.
5. Copy the URL shown under `Local project management`.

The URL looks like:

```text
https://elonman.darebuild.com/api/codex/v1/account/<account-token>/projects/
```

The same panel includes a token-specific Agent README URL and copyable command examples.

## Account Webhook

Endpoint:

```text
GET or POST https://elonman.darebuild.com/api/codex/v1/account/<account-token>/projects/
```

Use `POST` with JSON. `GET` is equivalent to `action=list`.

Account actions:

```json
{"action":"list"}
{"action":"create","name":"New app","starter_key":"blank","subdomain":"new-app"}
{"action":"connect_cloudflare"}
{"action":"create","name":"Test3 hello world","starter_key":"hello-world","subdomain":"test3","custom_domain":"test3.darefail.com","cloudflare":{"zone_name":"darefail.com","proxy_mode":"dns_only"}}
{"action":"configure_custom_domain","project_id":123,"custom_domain":"test3.darefail.com","cloudflare":{"zone_name":"darefail.com","proxy_mode":"dns_only"}}
{"action":"remove_custom_domain","project_id":123,"custom_domain":"test3.darefail.com"}
{"action":"request_project_limit_approval","name":"New app","starter_key":"blank"}
{"action":"delete","project_id":123}
{"action":"list_members"}
{"action":"invite_user","email":"editor@example.com","role":"member"}
{"action":"update_member_role","email":"editor@example.com","role":"admin"}
{"action":"remove_member","email":"editor@example.com"}
{"action":"list_project_collaborators","project_url":"https://project-name.darebuild.com/"}
{"action":"invite_project_user","project_url":"https://project-name.darebuild.com/","email":"editor@example.com","role":"editor","allowed_paths":["public/homepage.css","public/homepage.js"]}
{"action":"remove_project_collaborator","project_url":"https://project-name.darebuild.com/","email":"editor@example.com"}
```

The `list` and `create` responses include each project's `codex_api_url`. Use that URL for project-scoped editing.
Project responses include `custom_domains` with TXT verification and routing instructions. Use `connect_cloudflare` first; if `cloudflare.connected` is false, give the human `cloudflare.approval_url`, wait for approval, and retry the domain action. If `cloudflare.approval_link_ready` is false, report that DareBuild platform OAuth setup is incomplete. When connected, `configure_custom_domain` creates the TXT record and an unproxied DNS-only CNAME by default without exposing Cloudflare credentials to Codex. Use DNS records, not Cloudflare Workers, to connect custom domains to DareBuild projects; use DareBuild's returned TXT verification record and routing target. Use `cloudflare.proxy_mode="cloudflare_saas"` only when DareBuild's Cloudflare for SaaS platform settings are configured. Use `remove_custom_domain` to return the project to its DareBuild subdomain and clean up DareBuild-created Cloudflare DNS resources when Cloudflare is still connected.
Accounts default to 20 active projects. If `list` returns `project_limit.limit_reached=true` or `create` returns `error_code=project_limit_reached`, POST `request_project_limit_approval`; it sends DareBuild a Slack/email request and the user must wait for approval before creating more projects.

Starter keys:
- `blank`
- `hello-world`
- `project-auth-password`
- `allauth-login-links`
- `todo-list`
- `background-timestamp-task`

## Project Codex API

Project URLs are returned as:

```text
https://elonman.darebuild.com/api/codex/v1/<project-token>/
```

Project endpoints:

```text
GET  manifest/
GET  client.py
POST preview/
POST changes/
GET  media/
POST media/  (multipart field `media`)
POST files/protection/
POST migrations/
GET  migrations/<migration_id>/
POST tasks/
POST tasks/<task_id>/run/
POST project/
```

Common project calls:

```json
POST changes/
{"files":{"public/homepage.html":"<h1>Hello</h1>"},"publish":true,"message":"Update homepage"}

POST preview/
{"page_slug":"homepage","files":{"public/homepage.html":"<h1>Preview</h1>"}}

POST media/
multipart/form-data with one or more `media` files. Use the returned `media[].url` values in HTML/CSS/JS. DareBuild manages the AWS/S3 storage account; do not ask the user for AWS credentials.

POST files/protection/
{"action":"lock","paths":["public/homepage.py"]}

POST files/protection/
{"action":"hide","paths":["public/homepage.py"]}

POST files/protection/
{"action":"lock_and_hide","paths":["public/homepage.py","shared/__init__.py"]}

POST migrations/
{"name":"create_todos","sql":"create table if not exists todos (id serial primary key, title text not null);","run":true}

POST tasks/
{"name":"Update timestamp","code":"def run(params, context):\n    return {'ok': True}","cron_minute":"0","cron_hour":"*","enabled":true}

POST tasks/<task_id>/run/
{}

Modal GPU task example:
```python
from runner_service.sdk import modal_function_spawn

image_url = PARAMS["image_url"]
call_id = modal_function_spawn("darebuild-build-<build_id>-photo", "analyze_photo", image_url)
print("Modal call:", call_id)
```
Use `modal_function_get(call_id, timeout=0)` from a later background task run to poll a spawned call without blocking the runner. Use `modal_function_remote(...)` only for short calls that can finish within the runner timeout.

TikTokLive bridge example:
```python
from runner_service.sdk import bridge_start

bridge = bridge_start("@your_tiktok_handle", channel="tiktok-live", duration_seconds=3600)
```
Use `bridge_status(channel="tiktok-live")` to poll session state and `bridge_stop(channel="tiktok-live")` to request a clean stop. The browser should listen on the matching project WebSocket channel for `comment` and `bridge-status` events.

POST project/
{"name":"Renamed app"}
```

Human-only operations:
- Billing and credit card entry.
- Unlocking locked files.
- Unhiding files hidden from AI.
- Removing your own team access or downgrading your own administrator role.

Billing rule:
- Users enter credit cards in the GUI unless billing is already on file.
- `jamespsteinberg@gmail.com` has free backend access and should not be sent to checkout.
- If a project response, manifest, or `backend_locked` error returns `billing.payment_required=true`, tell the user payment is required and give them `billing.payment_url`.
- Do not try to pay from Codex. Wait for the user to complete checkout in the DareBuild GUI, then retry the backend action.

Media rule:
- Upload images, videos, audio, fonts, and PDFs through the Project Codex API `media/` endpoint or the downloaded project client's `media` command.
- Use returned URLs in generated project files.
- Do not request, print, or store AWS credentials, S3 keys, bucket names, or per-account storage credentials; DareBuild selects the storage account.

Project-scoped editor rule:
- Use `invite_project_user` with `allowed_paths` to restrict a user to specific files.
- If the user gives a public project URL, pass it as `project_url`; do not scrape or modify the public project page to manage collaborators.
- Project-scoped editors can edit allowed code only.
- They cannot manage settings, billing, roles, users, publishing, tasks, migrations, or file protection.

Five-project acceptance workflow:
1. Create `project-auth-password`; verify project-local signup, verification email, password login, and logged-in state are present.
2. Create `todo-list`; verify the page renders a to-do list backed by the database when backend access is available.
3. Create `background-timestamp-task`; verify task `Update timestamp` is hourly and can be run once when backend access is available.
4. Create `blank`; lock Python files from Codex and edit only `public/homepage.html`.
5. Create `blank`; invite a project-scoped editor, lock and hide Python files, and allow only CSS/JS paths.

When done, report the public URLs returned by the Account Codex smoke command.
