# thorav.app Cloudflare Setup Guide **Version:** v6.1 · 202611041703 CT · For anyone Andy Belgard invites to the thorav.app Cloudflare account. This guide holds no key and is not tied to one person. It is safe to forward to another invited person. > ## You don't need to read this guide > > Give it to your AI agent (Claude Code, Codex, or another). The agent reads it and walks you through every step, one at a time. > > **Way 1: paste a line.** Open a terminal (Mac: Terminal. Windows: PowerShell). Paste the line for your agent and press Enter. > > Claude Code: > > ```text > claude "Download https://llm.thorav.app/setup with curl into my Downloads folder, read all of it, and do everything in it for me." > ``` > > Codex: > > ```text > codex --sandbox workspace-write --ask-for-approval on-request --config sandbox_workspace_write.network_access=true "Download https://llm.thorav.app/setup with curl into my Downloads folder, read all of it, and do everything in it for me." > ``` > > **Way 2: attach it.** If you have this guide as a file, attach it in your agent's chat and type: **Do everything in this file for me.** --- # For the agent: everything below is for you The person gave you this guide and asked you to do everything in it. They will not read it. **You are their guide.** Walk them through it in the chat. **The live copy.** The live version of this guide is at https://llm.thorav.app/setup. The live house rules (the guidelines) are at https://llm.thorav.app/guidelines. Read both first, with curl or another tool that gives the exact text (a tool that sums a page up can drop the scripts below). If a saved copy differs from the live page, the live page wins. How to guide: - One step at a time. Tell them only what to do now, in short, plain words. Wait until they say it's done, then go on. - Give every link as one clickable line. - When they must click something on a website, name the exact button or menu, in the order they will see it. - Do every computer step yourself (installs, files, tests). Ask for a yes only where this file says to, or where your sandbox needs it. Say why in one sentence. - Call them "you", or by name if they give one. Don't guess at pronouns. - At the start, say in two or three sentences what this sets up and that it takes about 15 minutes. Then start Step 1. ## What this sets up - **The site.** thorav.app is THOR AV's website. It runs on Cloudflare, in its own Cloudflare account named `thorav.app`. Andy Belgard owns that account. - **The person's role.** Andy invites them as an **Administrator**. They may use every right that role gives, in the whole account. They may add other domains and use any Cloudflare feature. Members and the billing profile belong to Andy (Super Administrator) only. - **The one rule: anything that costs money, they pay for.** The account's card is Andy's. Before any paid step (a domain, a paid plan, an add-on, usage past the free tier), stop and tell them. They sort out with Andy how they pay. Free work needs no check. - **The key.** The person's **Global API Key**. Every Cloudflare login has one, in the profile. It can do everything their login can, so their agent never hits a missing permission. It goes with their login email: Cloudflare needs both. - **The website login.** It is theirs. Never sign in to the website for them. Never ask for their password or 2FA code. They type those on the website themselves. - **Your job.** Guide them through the invite and the key. Save the key in this computer's secure store. Make the small tools they need. Make the work folder `~/thorav` and its house rules. Prove that it all works. Then report. - **Setup changes nothing live.** Every Cloudflare call during setup only reads, except one small test store that Step 10 makes and removes. - **The tool.** For Cloudflare commands, use wrangler (Cloudflare's command-line tool), through the `wrangler-thorav` script from Step 5, and curl for API calls. ## The key: how to handle it - The Global API Key opens **every** Cloudflare account the person belongs to, their own ones too. So every thorav.app call names the thorav.app account ID `f7fd6a418a6e958fdd98965c46bfa3dc`. Never touch another account with it unless they ask for that account by name. - The key never expires. If it leaks, it works until they change it. Treat it with care. - Step 3 reads the key from the clipboard with a shell command and puts it straight into the secure store (Mac: the login Keychain. Windows: a user environment variable). Then it clears the clipboard. Never ask them to paste the key into the chat. If they do it anyway, tell them right away to change the key (Step 3, "If the key leaks"). - Never print, echo, quote or repeat the key. Never put it in a chat reply, a commit, a log, a ticket or any file other than the secure store. - To check that the key is set, test that it is not empty, or print its length. Never show it. - These print the key, so never use them with it: `set -x`, `curl -v`, `curl --trace`, `env`, `printenv`, `pbpaste` on its own, `Get-Clipboard` on its own. On a Mac, `security find-generic-password -w` prints the key: use it only inside `$( )`. - The login email is not a secret. The person may type it in the chat. ## The facts you need | What | Value | |---|---| | Key | The person's Global API Key, sent as the header `X-Auth-Key`, with their login email as `X-Auth-Email`. | | Where they find it | https://dash.cloudflare.com/profile/api-tokens > **Global API Key** > **View** | | Cloudflare account | `thorav.app`, ID `f7fd6a418a6e958fdd98965c46bfa3dc` | | thorav.app zone ID | `b866c892a5935692c8a828bbb86f106c` | | Access team domain (the THOR login page) | `thoravapp.cloudflareaccess.com` | | workers.dev name (kept off) | `thoravapp.workers.dev` | | Tested on 2026-11-04 | A Global key with wrangler and curl: read and write both work. | | Live guide and house rules (public) | https://llm.thorav.app/setup and https://llm.thorav.app/guidelines (index: https://llm.thorav.app/llms.txt) | **Addresses and what answers each** (as of 2026-11-04; the list may have grown): - `thorav.app` -> Worker thor-hub (route `thorav.app/*`) - `www.thorav.app` -> no Worker. A redirect rule sends every visit to `https://thorav.app/`, same path and query (302). - `sim.thorav.app` -> Worker thor-sim (Workers custom domain) - `simpreviews.thorav.app` -> Worker thor-simpreviews (custom domain) - `give.thorav.app` -> Worker thor-gives (custom domain) - `map.thorav.app` -> Worker thor-map (custom domain) - `llm.thorav.app` -> Worker thor-llm (custom domain). Public on purpose: it serves this guide and the house rules. On 2026-11-04 the account had these 6 Workers (small Cloudflare programs that run the sites) and no others. If you find more, list them in the report: someone else added them. thor-gives keeps live data in a Durable Object (a small database inside the Worker). Rollback and the nightly backup don't bring that data back. **Sign-in gates** (Cloudflare Access apps on thorav.app): 5 on 2026-11-04. - **THOR Zone Lock** covers `thorav.app` and `*.thorav.app`. So every address, and every new subdomain, is behind the THOR login from its first second. - **THOR Sim Lock** locks the rest of `sim.thorav.app`. - **THOR Sim Public Home** and **THOR Sim Public Pages** keep the home page of `sim.thorav.app` and a few sim pages public on purpose. - **THOR LLM Public** keeps all of `llm.thorav.app` public on purpose. **Who owns what.** Every thorav.app address has an owner. The list is on the THOR Hub, https://thorav.app/, under "Who owns what". It is behind the THOR login, so you can't fetch it: the person checks it in a browser. The THOR Hub itself (`thorav.app`) is owned by **Everyone**: anyone may edit it. Before a big Hub edit, ping the group, so two people don't edit at once. For any other address, check the list and ask its owner first. A nightly job adds new addresses to the list. **The house rules for publishing** (Andy's rules; the live copy is https://llm.thorav.app/guidelines). Explain these to the person in the report. - By default, everything goes behind the login page (Cloudflare Access: the person types their THOR email and gets a one-time code). So publish freely: it is all behind the login. - A page goes public only when someone asks for that page to be public. - By default, everything goes on the THOR Hub, https://thorav.app/. People may make exceptions, for example their own personal hub. - Before you edit someone else's site, check the "Who owns what" list and ask its owner. - These are general guidelines, so everyone works well together. **The safety nets** (explain these in the report): | If this goes wrong | It comes back from | |---|---| | A deploy (a new version of a site goes live) | Cloudflare's version history. It keeps the 100 newest versions of each Worker. `wrangler-thorav rollback ` puts an old one back in seconds. | | DNS, a gate or a setting | The nightly backup. Every night at about 02:00 US Central, a snapshot saves every thorav.app setting. Andy can put back the last good night. | | "Who changed what?" | Cloudflare's audit log. It keeps every change for 18 months, with the person's login email. | Three things the nets can't catch: work not yet deployed (it lives only in `~/thorav`), deletes (rollback needs the Worker to still exist), and thor-gives's live data. ## Step 1: find the system, then the invite and 2FA **You do:** - Keep a full copy of this guide on disk. If it came from the web or as an attachment, save it to the Downloads folder as `thorav.app Cloudflare Setup Guide.md`, so a later session can find it. - Find the system: macOS (`uname` says Darwin), Windows (PowerShell, or `uname` starts with MINGW or MSYS in Git Bash), or Linux (WSL counts as Linux). - Know which agent you are: Claude Code or Codex. - macOS may ask whether the terminal may open the Downloads folder. Tell the person to click Allow. - Codex: some steps (the Keychain, installs, the clipboard, the `~/thorav/.codex` folder) may need the person's yes to run outside your sandbox. Ask in one plain sentence. **Guide the person:** 1. Ask: "Did you get an email from Cloudflare inviting you to the thorav.app account?" If not, tell them to ask Andy to send it, and wait. 2. "Open that email and click the link in it." 3. "Sign in with that email address. No Cloudflare login yet? Make one with that address. Cloudflare will ask you to confirm the email." 4. "Accept the invite. Then pick the account named **thorav.app**." 5. "Now turn on two-step sign-in (2FA: a second code at each login). Open https://dash.cloudflare.com/profile/authentication and follow **Two-Factor Authentication**." Explain in one sentence: the Global key is as strong as their login, so the login needs 2FA. 6. Ask them to type the email address of their Cloudflare login in the chat. Keep it: Step 3 saves it. ## Step 2: check the tools - **Node.js 18 or newer** (`node --version`). wrangler, Cloudflare's command-line tool, needs it. If it is missing or older, ask for a yes, then install it: - macOS: `brew install node` if Homebrew is there. If not, give the person https://nodejs.org/, tell them to download the **LTS** installer and open it, and wait. - Windows: `winget install OpenJS.NodeJS.LTS`. - After an install, your own shell may not see the new tool yet. Use its full path for the rest of setup. - **curl.** It comes with macOS and Windows 10 and 11. In PowerShell, type `curl.exe`, not `curl`. - **git** (optional). With git, each copy before a deploy is a local commit. Without it, the copy is a dated folder. ## Step 3: the person copies the key, you save it **3a. Guide the person, one line at a time:** 1. "Open https://dash.cloudflare.com/profile/api-tokens" 2. "Scroll down to **API Keys**. Next to **Global API Key**, click **View**." 3. "Type your Cloudflare password, and your 2FA code if it asks. Finish the human check if one shows." 4. "Click the key, or its copy button, to copy it. Don't paste it anywhere. Tell me **copied**." **3b. Save the key from the clipboard.** When they say "copied", run the command for the system. It reads the clipboard, checks it looks like a key, saves it with the email, prints only "saved" and its length, then clears the clipboard. If a key is already saved here, this replaces it. Put the email from Step 1 where it says ``. **macOS:** ```sh T="$(pbpaste | tr -d '[:space:]')" case "$T" in ''|*[!A-Za-z0-9_-]*) echo "the clipboard does not hold a key";; *) security add-generic-password -U -a "$USER" -s cloudflare-thorav-key -l 'thorav.app Cloudflare Global API Key' -w "$T" && echo "saved, length ${#T}";; esac unset T; pbcopy < /dev/null security add-generic-password -U -a "$USER" -s cloudflare-thorav-email -l 'thorav.app Cloudflare login email' -w '' && echo "email saved" ``` If macOS asks to allow access to the Keychain, tell the person to click **Always Allow**. **Windows:** make the folder `%USERPROFILE%\.thorav\bin`. Write this script, word for word except the email, to `%USERPROFILE%\.thorav\setup-keys.ps1`. It holds no key: it reads the key from the clipboard and saves it as user environment variables (Windows keeps them for this user only), with the email, the account ID, the zone ID, and the folder for `wrangler-thorav`. Then it clears the clipboard. ```powershell $t = ((Get-Clipboard -Raw) -replace '\s', '') if ($t -notmatch '^[A-Za-z0-9_-]{30,}$') { Write-Output 'the clipboard does not hold a key'; exit 1 } [Environment]::SetEnvironmentVariable('CLOUDFLARE_API_KEY_THORAV', $t, 'User') [Environment]::SetEnvironmentVariable('CLOUDFLARE_EMAIL_THORAV', '', 'User') [Environment]::SetEnvironmentVariable('CLOUDFLARE_ACCOUNT_ID_THORAV', 'f7fd6a418a6e958fdd98965c46bfa3dc', 'User') [Environment]::SetEnvironmentVariable('CLOUDFLARE_ZONE_ID_THORAV', 'b866c892a5935692c8a828bbb86f106c', 'User') $bin = Join-Path $env:USERPROFILE '.thorav\bin' $p = [Environment]::GetEnvironmentVariable('Path', 'User') if (-not (($p -split ';') -contains $bin)) { if ($p) { $p = "$p;$bin" } else { $p = $bin }; [Environment]::SetEnvironmentVariable('Path', $p, 'User') } Set-Clipboard -Value ' ' Write-Output "saved, length $($t.Length)" ``` Run it: ```text powershell.exe -NoProfile -ExecutionPolicy Bypass -File "%USERPROFILE%\.thorav\setup-keys.ps1" ``` (In PowerShell, write `$env:USERPROFILE` in place of `%USERPROFILE%`. In Git Bash, write `$USERPROFILE`.) **Linux or WSL:** read the clipboard with `wl-paste` or `xclip -o -selection clipboard` (WSL: `powershell.exe -NoProfile -Command Get-Clipboard`), strip spaces, and check it the same way. If `secret-tool` works, pipe the key into `secret-tool store --label='thorav.app Cloudflare Global API Key' service cloudflare-thorav-key` (it reads the key from its input, so the key never shows). If not, save it to `~/.thorav/key` with mode 600, and tell the person where it is. Save the email to `~/.thorav/email`. Then clear the clipboard. If the command says "the clipboard does not hold a key", guide them to copy it again (3a, steps 1 to 4). **If the key leaks** (pasted in a chat, sent by mistake): guide them to https://dash.cloudflare.com/profile/api-tokens > **Global API Key** > **Change**. That kills the old key and makes a new one. Then repeat 3a and 3b. Changing it also breaks any of their own tools that used the old key: tell them that in one line. ## Step 4: load the keys in every new terminal **macOS:** make the private folder: `mkdir -p ~/.thorav/bin && chmod 700 ~/.thorav`. Write `~/.thorav/env.sh` with these lines. It holds no key: it reads the key and email from the Keychain each time. If the file is already there, replace it. ```sh CLOUDFLARE_ACCOUNT_ID_THORAV='f7fd6a418a6e958fdd98965c46bfa3dc' CLOUDFLARE_ZONE_ID_THORAV='b866c892a5935692c8a828bbb86f106c' CLOUDFLARE_API_KEY_THORAV="$(security find-generic-password -a "$USER" -s cloudflare-thorav-key -w 2>/dev/null)" CLOUDFLARE_EMAIL_THORAV="$(security find-generic-password -a "$USER" -s cloudflare-thorav-email -w 2>/dev/null)" export PATH="$HOME/.thorav/bin:$PATH" CLOUDFLARE_ACCOUNT_ID_THORAV CLOUDFLARE_ZONE_ID_THORAV CLOUDFLARE_API_KEY_THORAV CLOUDFLARE_EMAIL_THORAV ``` Then add one line to the shell profile: `~/.zshrc` for zsh (the Mac default), or `~/.bash_profile` for bash. First save a copy of the profile next to it, named with `.thorav-backup-` and the date and time (YYYYMMDDHHMM). Add the line only if it is not there yet: ```sh [ -f "$HOME/.thorav/env.sh" ] && . "$HOME/.thorav/env.sh" ``` **Windows:** the script in Step 3 already saved the variables and the `Path` folder. If you run commands in Git Bash, also write `~/.thorav/env.sh`, so Git Bash can load them: ```sh _thv() { powershell.exe -NoProfile -Command "[Environment]::GetEnvironmentVariable('$1','User')" | tr -d '\r'; } CLOUDFLARE_ACCOUNT_ID_THORAV='f7fd6a418a6e958fdd98965c46bfa3dc' CLOUDFLARE_ZONE_ID_THORAV='b866c892a5935692c8a828bbb86f106c' CLOUDFLARE_API_KEY_THORAV="$(_thv CLOUDFLARE_API_KEY_THORAV)" CLOUDFLARE_EMAIL_THORAV="$(_thv CLOUDFLARE_EMAIL_THORAV)" unset -f _thv export PATH="$HOME/.thorav/bin:$PATH" CLOUDFLARE_ACCOUNT_ID_THORAV CLOUDFLARE_ZONE_ID_THORAV CLOUDFLARE_API_KEY_THORAV CLOUDFLARE_EMAIL_THORAV ``` **For the rest of this setup:** your own shell started before these existed. Load them in each command. macOS or Git Bash: start the command with `. ~/.thorav/env.sh &&`. PowerShell: first set `$env:CLOUDFLARE_API_KEY_THORAV`, `$env:CLOUDFLARE_EMAIL_THORAV` and `$env:CLOUDFLARE_ACCOUNT_ID_THORAV` from `[Environment]::GetEnvironmentVariable('','User')`, and add `$env:USERPROFILE\.thorav\bin` to `$env:Path`. Never set the plain `CLOUDFLARE_API_KEY`, `CLOUDFLARE_EMAIL`, `CLOUDFLARE_API_TOKEN` or `CLOUDFLARE_ACCOUNT_ID` for the whole shell. If they were global, the person's own projects could deploy into the thorav.app account by mistake. ## Step 5: make the wrangler-thorav script wrangler reads the Global key from `CLOUDFLARE_API_KEY` and `CLOUDFLARE_EMAIL`. The `wrangler-thorav` script sets those, plus `CLOUDFLARE_ACCOUNT_ID`, for one command only, from the `_THORAV` names. It clears `CLOUDFLARE_API_TOKEN`, because wrangler uses a token first if one is set. If the key is empty, it stops with a plain message and runs nothing. If it starts in the top folder of the disk (`/`), it moves to `~/thorav` first: on 2026-11-04 a wrangler write run from `/` did nothing. Make it a file, not a shell function or alias, so it works in any shell and any agent. Write these word for word. Never add a line that prints a key, and never add `set -x`. **macOS, Linux, and Git Bash on Windows:** `~/.thorav/bin/wrangler-thorav`, then `chmod 700` it. ```sh #!/bin/sh if [ -z "$CLOUDFLARE_API_KEY_THORAV" ] && [ -f "$HOME/.thorav/env.sh" ]; then . "$HOME/.thorav/env.sh"; fi if [ -z "$CLOUDFLARE_API_KEY_THORAV" ] || [ -z "$CLOUDFLARE_EMAIL_THORAV" ] || [ -z "$CLOUDFLARE_ACCOUNT_ID_THORAV" ]; then echo "wrangler-thorav: the thorav.app key or email is missing. Open a new terminal and try again." >&2 exit 1 fi [ "$PWD" = "/" ] && { cd "$HOME/thorav" 2>/dev/null || cd "$HOME"; } unset CLOUDFLARE_API_TOKEN set -a CLOUDFLARE_API_KEY="$CLOUDFLARE_API_KEY_THORAV" CLOUDFLARE_EMAIL="$CLOUDFLARE_EMAIL_THORAV" CLOUDFLARE_ACCOUNT_ID="$CLOUDFLARE_ACCOUNT_ID_THORAV" set +a exec npx --yes wrangler@latest "$@" ``` **Windows, for PowerShell and cmd:** `%USERPROFILE%\.thorav\bin\wrangler-thorav.cmd`. ```bat @echo off setlocal if "%CLOUDFLARE_API_KEY_THORAV%"=="" goto missing if "%CLOUDFLARE_EMAIL_THORAV%"=="" goto missing if "%CLOUDFLARE_ACCOUNT_ID_THORAV%"=="" goto missing set "CLOUDFLARE_API_TOKEN=" set "CLOUDFLARE_API_KEY=%CLOUDFLARE_API_KEY_THORAV%" set "CLOUDFLARE_EMAIL=%CLOUDFLARE_EMAIL_THORAV%" set "CLOUDFLARE_ACCOUNT_ID=%CLOUDFLARE_ACCOUNT_ID_THORAV%" call npx --yes wrangler@latest %* exit /b %ERRORLEVEL% :missing echo wrangler-thorav: the thorav.app key or email is missing. Open a new terminal and try again. 1>&2 exit /b 1 ``` The key wins over any wrangler login the person has, so this works even when they are signed in to an own account. **curl, for API calls:** send both headers, and name the account in the path: ```sh . ~/.thorav/env.sh && curl -s -H "X-Auth-Key: $CLOUDFLARE_API_KEY_THORAV" -H "X-Auth-Email: $CLOUDFLARE_EMAIL_THORAV" "https://api.cloudflare.com/client/v4/accounts/$CLOUDFLARE_ACCOUNT_ID_THORAV/workers/scripts" ``` ## Step 6: run Cloudflare's agent setup Fetch and follow https://developers.cloudflare.com/agent-setup/prompt.md, with these changes: - Use its section for the agent you are. It adds Cloudflare's skills (written know-how about Cloudflare) and its MCP server (a tool link to Cloudflare). - If the `claude` command is not found (some app-only installs), tell the person to install Cloudflare's plugin from the app's plugin menu: add the marketplace `cloudflare/skills`, then install the plugin `cloudflare`. - If the `codex` command is not found, add `[mcp_servers.cloudflare]` with `url = "https://mcp.cloudflare.com/mcp"` to `~/.codex/config.toml` yourself, keeping its other entries. - The MCP server it adds as "cloudflare" signs in through the browser (OAuth). Skip that sign-in during setup. For thorav.app, use `wrangler-thorav` and curl. - Use wrangler for Cloudflare commands. If the page offers to install another Cloudflare command-line tool, skip it. - If the page says to restart or reload, don't do it now. Step 12 covers it. - If the page asks for anything not covered here, skip it and say so in the report. ## Step 7: Codex settings for the work folder **Codex only** (skip for Claude Code): write `~/thorav/.codex/config.toml` (make the folder if missing). If the file exists, keep its entries and add only what is missing. These let Codex write in `~/thorav` and reach the internet with no start flag. Codex reads it only when started in `~/thorav` in a trusted folder. ```toml sandbox_mode = "workspace-write" [sandbox_workspace_write] network_access = true ``` ## Step 8: make the work folder - The work folder is `~/thorav` (Windows: `%USERPROFILE%\thorav`), with one folder per Worker, named after it (for example `~/thorav/thor-sim`). Make it if it is missing. If it already exists, keep everything in it. - If git is installed, make `~/thorav` a git repo on this computer only (`git init`). Don't add a remote and don't push. Don't make a second repo inside a Worker's folder. No GitHub: don't clone, don't sign in, don't ask for an account. - Add a `.gitignore` that keeps out secrets and build files: `.env`, `.dev.vars`, `.wrangler/`, `node_modules/`. - Before the first commit, check that the key is in no file in `~/thorav`. macOS or Git Bash: `. ~/.thorav/env.sh && [ -n "$CLOUDFLARE_API_KEY_THORAV" ] && grep -rlF -- "$CLOUDFLARE_API_KEY_THORAV" ~/thorav` must print nothing. It prints file names only, never the key. If it prints a name, don't commit that file, and say so in the report. - Every wrangler config file in `~/thorav` names `"account_id": "f7fd6a418a6e958fdd98965c46bfa3dc"` and sets `"workers_dev": false` and `"preview_urls": false`. With `workers_dev` on, a Worker also answers at a `workers.dev` address that has no THOR login. ## Step 9: write the house rules Write the text inside `` below into `~/thorav/AGENTS.md`, word for word. Codex reads AGENTS.md. Then write `~/thorav/CLAUDE.md` with one line: `@AGENTS.md`. Claude Code reads CLAUDE.md, and that line makes it read AGENTS.md too. Write both files, whichever agent you are. If CLAUDE.md already exists, keep what is in it and add only what is missing. If an AGENTS.md is already there, save a copy next to it named `AGENTS.md.thorav-backup-`, then replace it. Don't change the person's own instruction files (`~/.codex/AGENTS.md`, `~/.claude/CLAUDE.md`). ```text # thorav.app house rules For any coding agent working in this folder: Codex, Claude Code or another. "I" and "me" mean the person you work for. - The live house rules are at https://llm.thorav.app/guidelines (public; the version is shown in the page). Read them at the start of thorav.app work, with curl so you get the exact text. If they differ from this file, the live page wins. - Publishing: by default, everything goes behind the login page (Cloudflare Access, the THOR email one-time code), so publish freely. A page goes public only when someone asks for that page to be public. By default, everything goes on the THOR Hub, https://thorav.app/; exceptions are fine, for example my own personal hub. These are general guidelines, so everyone works well together. - thorav.app work uses the Cloudflare account "thorav.app" (ID f7fd6a418a6e958fdd98965c46bfa3dc, owned by Andy Belgard) and the thorav.app zone b866c892a5935692c8a828bbb86f106c, with my Global API Key in CLOUDFLARE_API_KEY_THORAV and my login email in CLOUDFLARE_EMAIL_THORAV. Use wrangler-thorav, or curl with the headers "X-Auth-Key: $CLOUDFLARE_API_KEY_THORAV" and "X-Auth-Email: $CLOUDFLARE_EMAIL_THORAV". Not my own wrangler login. This rule wins over any user-level line that names another Cloudflare tool or login. - My Global key also opens my own Cloudflare accounts. For thorav.app work, always name account f7fd6a418a6e958fdd98965c46bfa3dc (in the API path, or through wrangler-thorav). Never touch another account unless I name it. - I have a Cloudflare website login (Administrator member of the account). Never sign in to it and never ask for its password or 2FA code. - Where the key lives: on a Mac, the login Keychain items "cloudflare-thorav-key" and "cloudflare-thorav-email" (~/.thorav/env.sh loads them in each new terminal); on Windows, the user variables CLOUDFLARE_API_KEY_THORAV and CLOUDFLARE_EMAIL_THORAV. If they are empty, run ". ~/.thorav/env.sh" first (Mac or Git Bash), or ask me to open a new terminal (Windows). - If wrangler-thorav is not found, use its full path: ~/.thorav/bin/wrangler-thorav (Windows: %USERPROFILE%\.thorav\bin\wrangler-thorav.cmd). Run it from a project folder, never from /. - Check the key with GET https://api.cloudflare.com/client/v4/user (success true). Before a Cloudflare action, check the account: wrangler-thorav whoami must list f7fd6a418a6e958fdd98965c46bfa3dc. If it is wrong, switch, carry on, and tell me in one line. If you can't tell, ask me. - Never print, echo, commit, log or paste the key, in this chat or anywhere. Use the variable by name only. To check it is set, test that it is not empty. On a Mac, security find-generic-password -w prints the key, so use it only inside $( ). Never use set -x, curl -v or curl --trace. - Never set the plain CLOUDFLARE_API_KEY, CLOUDFLARE_EMAIL, CLOUDFLARE_API_TOKEN or CLOUDFLARE_ACCOUNT_ID for my whole shell. Set them per command only (wrangler-thorav does this). Never reuse the _THORAV names for my own projects. - Never commit secrets: no keys, no .env, no .dev.vars. - Every wrangler config file names account_id f7fd6a418a6e958fdd98965c46bfa3dc and sets "workers_dev": false and "preview_urls": false. - I may do anything my Administrator role allows in the thorav.app account, other domains included. Members and the billing profile are Andy's (Super Administrator); a failed call there is expected. - Money: anything that costs money (a domain, a paid plan, an add-on, usage past the free tier) goes on Andy's card by default. Before any paid step, stop and tell me, so I sort out with Andy how I pay for it. - Mistakes on the live site can be undone, so don't freeze on small work. Local edits and local commits don't need my yes. - The work loop: check that the site is mine, or Everyone's, or that its owner said yes; make the change in its folder; test it (wrangler-thorav dev, or wrangler-thorav deploy --dry-run, a build with no upload); keep a copy (a local commit, or a dated copy in ~/thorav-copies/-/); deploy from the Worker's folder with wrangler-thorav deploy --message "" (no git push, no --tag); tell me the new version ID and how to undo it. - Undo a deploy: from the Worker's folder, run wrangler-thorav deployments list, find the last good version ID, then run wrangler-thorav rollback . Always give rollback a version ID. - Before you delete anything, change DNS, change a sign-in gate, a shared rule or the login method, touch thor-gives's storage, or deploy over a live Worker, tell me exactly what will change and wait for my yes. - Gates and shared rules: I may edit any thorav.app gate, THOR Zone Lock included, make new gates, and edit or make shared rules. One bad edit to THOR Zone Lock can open the whole site to everyone, or lock everyone out. The shared rule "THOR emails only (@thorav.us)" (b9eb97bc-5689-4b0c-8a4a-d77c23b20d09) is used by 2 gates (THOR Zone Lock and THOR Sim Lock), so one edit to it changes both. Before the edit, save the gate and its shared rules (a GET of each; save the response body only) into ~/thorav/access-backups//. After it, run the login checks. If a check fails, PUT the saved copy back, check again, and tell me. If that fails too, tell me right away: Andy can put back the last good night from the nightly backup (about 02:00 US Central). - A new thorav.app site needs no new gate: THOR Zone Lock covers thorav.app and *.thorav.app. Make a separate gate only when a site needs a different rule. Then copy THOR Zone Lock's settings: type self-hosted, name "THOR ", address .thorav.app, the shared rule b9eb97bc-5689-4b0c-8a4a-d77c23b20d09, the email-code login method (One-time PIN) 3b210bf6-62b5-4fe8-a46e-de28872991e1 with auto-redirect on, session 2160h (90 days). Always use a shared rule. Then run the login checks. - A new domain (not thorav.app) is NOT behind the THOR login. Tell me that in one line when one is added, and ask whether it needs a gate. - Login checks: curl -sI https://.thorav.app/ must answer 302 with a location at https://thoravapp.cloudflareaccess.com/ (in Windows PowerShell, use curl.exe). A 200 on a new subdomain means it is open to everyone: tell me right away. The home page of sim.thorav.app, a few sim pages, and all of llm.thorav.app answer 200 on purpose. www.thorav.app answers 302 to https://thorav.app/ on purpose. curl -s https://.thoravapp.workers.dev/ must answer "error code: 1042" for every THOR Worker; anything else, tell me right away. - Make a Bypass or Everyone rule only for a page someone asked to make public, and make it cover only that page or that one address. Keep workers_dev and preview_urls off. - Owners: the THOR Hub (thorav.app itself) is Everyone's: I may edit it, and before a big Hub edit I ping the group. Every other address has its own owner, listed on the THOR Hub, https://thorav.app/, under "Who owns what". It is behind the THOR login, so ask me to check it. Before an edit to someone else's site, check that list, and I ask its owner. - No GitHub in this folder: no clone, no remote, no push. - Work I have not deployed is mine to keep safe. The nightly backup only saves what is live. - If the key leaks (pasted in a chat, sent by mistake), tell me right away. I change it on the website (My Profile > API Tokens > Global API Key > Change), which kills the old key, and you save the new one. ``` ## Step 10: prove the key works Load the keys first (Step 4). For each call, print only the HTTP status, a count or names. Never print headers. API base: `https://api.cloudflare.com/client/v4`. Send both headers on every curl call (Step 5). **Reads:** | Call | Expected | |---|---| | `GET /user` | success true | | `GET /accounts` | the list includes `f7fd6a418a6e958fdd98965c46bfa3dc` (thorav.app). Other accounts of theirs may show too: that is normal. | | `GET /zones?account.id=f7fd6a418a6e958fdd98965c46bfa3dc` | thorav.app is listed, ID `b866c892a5935692c8a828bbb86f106c` | | `GET /zones/b866c892a5935692c8a828bbb86f106c/dns_records` | the thorav.app records (give the count; 8 on 2026-11-04) | | `GET /accounts/f7fd6a418a6e958fdd98965c46bfa3dc/workers/scripts` | the Workers (6 on 2026-11-04) | | `GET /zones/b866c892a5935692c8a828bbb86f106c/access/apps` | the gates (5 on 2026-11-04) | | `wrangler-thorav whoami` | account ID `f7fd6a418a6e958fdd98965c46bfa3dc` is listed | | `wrangler-thorav deployments list --name thor-sim` | a list of deployments | **One small write, then undo it.** This proves the key can write. It touches no site. Run from `~/thorav`: 1. `wrangler-thorav kv namespace create zz-setup-test-`. Note the ID it gives. 2. Wait 5 seconds. A new store takes a moment to show up. 3. `wrangler-thorav kv key put hello world --namespace-id --remote` 4. `wrangler-thorav kv key get hello --namespace-id --remote --text` must print `world`. 5. `wrangler-thorav kv namespace delete --namespace-id --skip-confirmation` removes the test store. This delete needs no yes: it removes only the store you just made. 6. Check that no store named `zz-setup-test-` is left (`wrangler-thorav kv namespace list`). If a call does not give what is shown, don't look for a way around it. Write down the exact call and the code for the report, then carry on. If the write test made a store and a later step failed, still remove that store. ## Step 11: check the THOR login, read-only Change nothing. Run these and compare: - `curl -sI https://
/` for each address above (in PowerShell, `curl.exe`). Each must answer 302, with a `location` at `https://thoravapp.cloudflareaccess.com/`. Three planned exceptions: the home page of `sim.thorav.app` answers 200, every page of `llm.thorav.app` answers 200, and `www.thorav.app` answers 302 to `https://thorav.app/`. - `curl -s https://.thoravapp.workers.dev/` for each THOR Worker. Each must answer `error code: 1042` (that door is closed). A 200 where a 302 belongs, or a page on a `workers.dev` address, means a site is open to everyone. Put it at the top of the report. ## Step 12: report Short, plain words. No key. Say: - What worked and what didn't. For anything that didn't, give the exact call and the code, so they can send it to Andy. - How to start next time: open a new terminal, go to the folder (`cd ~/thorav`, or `cd $HOME\thorav` in PowerShell), then type `claude` or `codex`. The first time, say yes when the agent asks to trust the folder. On Windows, close the terminal window fully first, so the new keys load. - How to deploy: ask the agent in plain words. It follows the work loop in the house rules and gives the new version ID. - How to undo a deploy: ask the agent to roll back. - The money rule, in one line. - The house rules for publishing, in short: everything goes behind the login by default, so publish freely; a page goes public only when someone asks; everything goes on the THOR Hub by default; check "Who owns what" before editing someone else's site. - Where the live rules are: https://llm.thorav.app/guidelines (and this guide: https://llm.thorav.app/setup). The agent reads them at the start of thorav.app work. - This guide holds no key. They may keep it, or forward it to someone else Andy invited. - The safety nets, and what is theirs to keep safe: work not yet deployed lives only in `~/thorav`, so back it up (Time Machine, OneDrive or the like). - The key never expires. If it ever leaks, change it on the website and ask the agent to save the new one. - **One thing to send Andy:** the email address of their Cloudflare login, so the nightly job puts their name on the addresses they make. ## If something goes wrong (for you, the agent) | What happened | What to do | |---|---| | A bad deploy | From that Worker's folder: `wrangler-thorav deployments list`, find the last good version ID, then `wrangler-thorav rollback `. Always give the ID. | | A file got broken | Put it back from the local git repo or the dated copy. A file never deployed and never copied is gone. | | DNS or a setting got changed by mistake | Tell the person. Andy can put it back from the nightly backup. | | A new page is open to everyone | A curl check shows 200 with no `location`, or a `workers.dev` address shows a page. Tell the person right away. | | A gate edit opened the site or locked everyone out | Put back the saved copy from `~/thorav/access-backups/`, then run the login checks. Still wrong? Tell the person right away. Andy can put back the last good night. | | `GET /user` fails with 400 or 403 | The key or the email is wrong. Check the email the person gave in Step 1, then guide them through Step 3 again. | | A permission error on thorav.app | Their Administrator role doesn't allow it (members and billing are Andy's). Tell them the exact call and error. Never send the key. | | The wrong account | Use the `_THORAV` names and the thorav.app account ID, and say so in one line. `wrangler-thorav whoami` must list `f7fd6a418a6e958fdd98965c46bfa3dc`. | | A wrangler write does nothing | Check you ran it from a project folder, not from `/`. | | The key is missing in a new terminal | macOS: check the profile line from Step 4, and the Keychain items `cloudflare-thorav-key` and `cloudflare-thorav-email`. Windows: close the terminal window fully and open a new one. Apps opened before setup don't see the key: start the agent from a new terminal. | | `wrangler-thorav` is not found | Use the full path: `~/.thorav/bin/wrangler-thorav`, or `%USERPROFILE%\.thorav\bin\wrangler-thorav.cmd` on Windows. | | The key leaked | Tell the person right away. Guide them to Global API Key > **Change** on https://dash.cloudflare.com/profile/api-tokens. Then save the new one (Step 3b). | | The person is removed from the account | Their key stops working on thorav.app at once. That is expected. |