Developer tooling reference
The developer tooling reference: the package.json scripts and the remy commands, pinned tools, secrets, agent skills and the Cloudflare services behind the docs.
The tooling
npm run # every script, with what it runs
npm run setup # the pinned skills, MCP, the flow's guard, the installation's checks
npm run auth -- --help # the Better Auth CLI
npm run wrangler -- --help
npm run auth:infopackage.json is the entry, as in every TypeScript project: its scripts run every project command.
Node is pinned by .node-version and package.json's engines; every tool is a dependency of
@joeblew999/remy-ui, so every app that installs the package gets the same versions with no pin of its
own: Wrangler, Playwright, TypeScript, the Chrome DevTools tools, the Modern Web Guidance CLI, the
Codex CLI. gh is the machine's, and Claude Code (the translator) is the machine's own, the one the
subscription is logged into. A script that is one tool is written as that tool ("logs": "wrangler tail --format json"); anything with logic is TypeScript, a remy command of the package
(packages/ui/src/cli, type-checked on every check) or, for what is one app's own, a scripts/*.ts of
that app (the plan).
npx remy verify doctor prints the versions of the CLIs the tooling runs.
Better Auth runs in remy-auth's own Worker on a D1 database (DB in wrangler.jsonc), with its
options in src/auth/options.ts. Its scripts are remy-auth's own, in package.json:
npm run auth:generate -- <name> # LOCAL: what the options need beyond migrations/, as the next numbered migration
npm run auth:migrate # LOCAL: apply migrations/ and migrations-demo/ to Wrangler's local D1 databases
npm run local # LOCAL: .dev.vars when missing, the migrations, the guard's fixture (dev, build and start run it)
npm run auth:mail -- you@example.com # LOCAL: the sign-in codes captured for an address, from the running Worker
npm run auth:provision # Prints what the deployed sign-in needs on Cloudflare; creates nothingnpm run local (the app's "local" script, which npm run dev, npm run build and dev:start run
first) writes .dev.vars, applies the migrations and installs the guard's oRPC v1 fixture (tests/guard/v1),
so dev, preview and every check start on the current schema with nothing to remember. auth:generate
runs the pinned CLI through src/auth/cli.ts, which compares the options with a throwaway SQLite
database built from migrations/, so it writes only what is not there yet; change the options, then
generate, never edit Better Auth's tables by hand. To sign in locally: npm run dev, open
/en/app/account and press one of the seeded people, or enter any address and read its code with
auth:mail. No mail is sent locally: the local environment keeps it in the Worker's outbox instead
(the environment table in src/auth/environment.ts, explained;
staging has the seeded people too and sends mail for real; any other environment is production,
where mail is sent through Cloudflare Email Service and nobody is seeded). The deployed
database, its migrations and the BETTER_AUTH_SECRET Worker secret are created on the owner's
request only: auth:provision prints the steps, and until the database exists the deploy refuses,
because Wrangler would otherwise create it by itself.
These are developer/operator tools. Remy end-user CLI login and delegated API calls
remain part of the service milestone. Both apps are live on Cloudflare; the production deploy uploads to
origins.production in remy.config.ts, and dev:promote runs it, on the owner's request only.
Package upgrades
npm run packages -- check # Preview available updates
npm run packages -- upgrade # Apply latest versions, including majors, then the installation's checksThe scripts and commands
Every app on the package has the same scripts; npm run lists them. The flow and the hand tools are
scripts; the rest are remy commands (npx remy <command>), one module each in packages/ui/src/cli.
| Scripts and commands | Purpose |
|---|---|
npm run dev:status, dev:start, dev:change, dev:land, dev:promote, dev:release, dev:done | The flow (how we work) |
npm run dev, build, preview | The app: hot reload, the production build with a Wrangler dry run, the built Worker on the preview port (the GUI) |
npm run test -- every|quick|only <words>|smoke|google|cwv|remote|live|consumers|report | The browser checks at every level; the suite is GitHub's after a landing, only <words> is the one run a step does not own |
npm run check -- [plans|single-copies|routes|types|unit|translations|docs] | The check (dev:change), or one part of it |
npm run setup, npx remy verify [setup|tooling|doctor], npm run upgrade -- <version> | An installation: its checks, the tooling invariants, the CLI versions; moving an app to a release |
npm run packages -- check|upgrade|pack|notes|bumped|publish|tag|release | A repository that publishes packages (the command line) |
npx remy cloudflare deploy|staging|docs-deploy|versions|urls|preview|preview-delete | Deployments, what each is running, an app's page URLs, a throwaway check Worker (the command line) |
npm run logs, errors, wrangler, npm run observe -- events|ai-usage|ai-check|gateway | Live logs, the Cloudflare CLI, stored logs and the AI's usage, setup and gateway (below) |
npm run docs -- dev|build|check|test [remote]|preview|answers on|off|publish|questions|provision|init|observe | The docs Worker, @joeblew999/remy-ui's, over an app's docs/ (writing docs); remy-auth alone: npm run docs:cli, the Fumadocs CLI in the package |
npx remy i18n check [messages|docs] [--list], i18n translate | Translations: the offline checks (a warning in the check, the gate at a release), the one writer dev:land runs on main (one writer) |
npm run plans -- status|check|close|park|open | The plans rule (plans) |
npx remy skills install|list|remove, npx remy mcp register|verify|status, npx remy rules | The pinned agent skills, MCP registration, the rules block in an app's AGENTS.md (below) |
npm run shots -- <page> [--phone] [--dark] [--all] [--video], npm run browser, browser:start, browser:stop, npm run web | Screenshots, the Chrome DevTools CLI and session, Modern Web Guidance (below) |
npm run api -- spec [origin] [--urls] | The OpenAPI document a running Worker serves |
npm run codex, codex:resume, claude, claude:resume | Start or resume an agent session (below) |
remy-auth's own: npm run auth…, ui:components, ui:blocks, ui:theme, ui:verify, ui:version, template:check, release-checks, generate, local, test:consumers | Better Auth, the shadcn files, the release's own checks, what this repository generates and prepares |
npm run packages -- upgrade uses the locally pinned npm-check-updates to move npm
dependencies past existing version pins, saves exact versions, installs them and
refreshes package-lock.json, then runs the installation's checks.
Peer conflicts fail visibly; the command does not use npm's --force or
--legacy-peer-deps. Review the manifest/lockfile diff and any major-version
migration requirements. If installation fails after manifest updates, resolve the
reported conflict before using npm run setup; no automatic rollback discards your edits.
Workspace dependencies are upgraded too; the local @joeblew999/remy-ui and @joeblew999/remy-auth-contract references are excluded
from registry upgrades. Node and the skill-source pins are managed separately.
Verification
The flow is four steps: dev:change (the check, seconds, after every change), dev:land (commit,
main, push, staging; GitHub runs the heavy checks), dev:promote (production) and dev:release, with
dev:start and dev:done around a piece of work and dev:status to look; a gate in every heavy
command refuses it outside them. The rule is in
how we work, the commands in
the command line.
npx remy verify is the release's gate: dev:release runs it. An installation ends with
npx remy verify setup (npm run setup, npm run packages -- upgrade and npm run upgrade run it): about
a minute, no browser. Nobody runs the gate while coding (dev:change is the check); by hand, on
purpose, it is REMY_FLOW=hand npx remy verify. The installation's checks are the dependencies against the
lockfile, MCP registration, the flow's guard, the CLI versions, the tooling invariants (npx remy verify tooling: every package.json matches the lockfile, the Wrangler configuration keeps previews off and
observability on, the workflows name only scripts that exist, every installed skill comes from a
pinned source with its Claude link), then the check. They use the existing local installation and
do not provision Cloudflare resources. The gate then runs every browser check of ours in every
language (npm run test -- every) against the production artifact in local Workers using installed
Chrome, then the consumer fixture. Google's audits are not in it: npm run test -- google and
npm run test -- cwv, which the release runs after it. No deployment is performed. See the GUI proof for scope and commands.
Start or reload your agent
VS Code Codex extension
Open this repository in VS Code and use the Codex sidebar. The extension ships
its own executable; the project's npm CLI installation serves terminal users.
The Codex CLI and IDE extension share MCP configuration.
Our project registration writes .codex/config.toml; trust the project in Codex
so that project configuration can load. VS Code's .vscode/mcp.json configures
its own MCP client and is not the Codex extension's configuration file.
After changing skills or MCP configuration:
- Run
npx remy mcp registerin the repository terminal. - Save your work, open the Command Palette (
Cmd+Shift+Pon macOS), and run Developer: Reload Window. - Reopen the Codex sidebar and continue the conversation. Verify that the agent can call the newly configured tools; registration alone does not prove a connection.
npm run codex:resume launches a terminal session; it does not reload the extension.
The installed code CLI has no documented reload-window flag, so reloading uses
VS Code's built-in command rather than a shell wrapper that pretends to restart it.
Terminal agents
After npm run setup, use the installed Codex or Claude Code CLI:
npm run codex # New Codex conversation
npm run codex:resume # Resume latest Codex conversation in this project
npm run claude # New Claude conversation
npm run claude:resume # Resume latest Claude conversation in this projectTo reload skills and MCP configuration, exit the current agent with /exit, then
run its :resume script from your terminal. Use /mcp inside the agent to check the
connection. Pass additional upstream options after --, for example
npm run codex -- --help. Setup installs the pinned official
@openai/codex CLI locally, and the
Codex scripts use that executable directly rather than relying on your shell PATH.
npm run packages -- upgrade updates it alongside the other dependencies. Authenticate when
prompted. Claude Code is installed separately; launching Codex does not require it.
Agent skills
The skill sources are the pins of
packages/ui/src/cli/skills.ts: Better Auth, Cloudflare, Chrome DevTools, Modern Web
Guidance, shadcn, Playwright CLI, GitHub release and TanStack Router/Start. TanStack's skills are
named one by one, including its react-router skill (the React bindings), which replaced Remix's
skill of the same name: skills install flat by name, so the two cannot coexist. TanStack Form's
skills are not installed: they live only on its v2 alpha branches and describe the 2.0 alpha API, not
the 1.x we pin; add them when we move to Form 2. Install the skills locally:
npx remy skills install
npx remy skills listTo reinstall from scratch, run npx remy skills remove then npx remy skills install.
Skills live in .agents/skills/; .claude/skills/ links to the same files.
The remy skill: the platform's rules for every repo's agents
Beside the pinned skills, remy skills install installs remy from the installed package
(./node_modules/@joeblew999/remy-ui/skills), so its version is the package's. It is
generated from these developer docs (how we work, the principles, tooling, the command line, the UI
package, writing docs, the GUI) by remy-auth's generate script, which every pack and release runs
(packages/ui/skill.mjs); the docs stay the one source. In an app, npx remy rules keeps a marked
block in AGENTS.md pointing its agents at the skill and naming the version; npm run setup and
npm run upgrade run it, so an upgrade changes the rules the agents read in the same step.
remy-auth's own AGENTS.md is a pointer to Agents: start here.
The installer records provenance in skills-lock.json. Re-running installation
restores the selected skills from the pinned sources; update their source commits deliberately to adopt upstream
changes. Only skills-lock.json is committed; the installed skills and their Claude links are
ignored and recreated by npm run setup or npx remy skills install.
npx remy skills list shows what is installed; the skills plan
tracks dependencies without an official skill. Reload an existing agent session
if newly installed skills are not yet visible.
To add a source, only from the library's own maintainers:
- Pin it in
pinsinpackages/ui/src/cli/skills.tsashttps://github.com/<owner>/<repo>/tree/<commit>, using the commit fromgit ls-remote https://github.com/<owner>/<repo> HEAD, naming the skills to take rather than'*'when the repository also ships contributor-only skills. - Run
npx remy skills remove,npx remy skills installandnpx remy verify tooling(seconds), which reads the pins and rejects installed skills from unpinned sources.
MCP registration
Skills provide instructions and workflows; MCP provides callable tools. Chrome DevTools uses both. Modern Web Guidance uses its CLI, and many auth/Cloudflare skills also work through the existing CLIs; a skill does not automatically require an MCP server.
npx remy mcp register # Also runs during npm run setup
npx remy mcp verify # Also runs in the installation's checks
npx remy mcp status # Requires both Codex and Claude CLIsRegistration (packages/ui/src/cli/mcp.ts) writes the chrome-devtools entry to
project-local .codex/config.toml and .mcp.json. Each client launches the app's own
chrome-devtools-mcp (isolated, headless, telemetry off) with an absolute path. Generated files
contain machine-specific paths and are gitignored; rerun registration after moving the checkout.
Unrelated settings and servers are preserved. Changed existing files receive a
.bak recovery copy; TOML serialization can normalize formatting and comments.
The server uses the pinned npm package, an isolated headless Chrome profile, and
has tool telemetry and CrUX uploads disabled. The MCP process is separate from the
CLI's browser:start/browser:stop session; the agent client manages its lifetime.
Reload the agent after registration. Codex only loads project configuration in a
trusted project. Claude may show Pending approval for a new project MCP server;
review it in Claude's /mcp interface. Registration does not bypass client trust or
approval settings. See Codex MCP configuration
and Claude MCP scopes.
remy mcp verify checks configuration, not a live connection. remy mcp status shows what
the clients see (Claude also checks connectivity for approved servers).
Browser tooling
Google's Chrome DevTools agent tools
provide browser interaction, screenshots, accessibility inspection, network/cookie
debugging, Lighthouse and performance analysis. Install Google Chrome separately;
the browser is not installed by project setup. The CLI is experimental and pinned with
the other npm tools, so npm run packages -- upgrade updates it too.
npm run browser:start # Isolated, headless Chrome session
npm run browser -- new_page http://localhost:3000
npm run browser -- list_pages
npm run browser -- take_snapshot 1 # Use the returned page ID
npm run browser -- click 1 "UID_FROM_SNAPSHOT"
npm run browser:stopRun npm run browser:start -- --headless=false for a visible window. Start once
per session; subsequent CLI calls reuse the background daemon. Starting again
restarts that daemon. These sessions use a temporary Chrome profile; the start script
disables tool usage telemetry and CrUX URL uploads. Stop the session when finished.
Use npm run browser -- --help for upstream commands.
Modern web implementation guidance
Google's Modern Web Guidance
complements browser inspection with implementation guidance for native HTML/CSS,
forms, accessibility, performance, passkeys and browser compatibility. The main
modern-web-guidance skill is installed for both agents. The separate
chrome-extensions skill is omitted because this project is a web service and UI.
npm run web -- search "animate a dialog modal backdrop"
npm run web -- retrieve "GUIDE_ID_FROM_SEARCH"
npm run web -- listUse the locally pinned web script in this repo in place of the upstream
skill's npx modern-web-guidance@latest examples. npm run packages -- upgrade updates the CLI;
npx remy skills install restores the commit-pinned skill. Google's alternative skills
installer keeps our existing .agents and .claude layout without a second
installer or automatic skill updates. If a search returns no matches, use list to browse guide IDs.
Browser support defaults to the skill's Baseline Widely available policy, with fallbacks for newer features.
Cloudflare observability
The observability plan covers logs, traces, metrics,
D1 health, durable auth audit records, correlation, dashboards and alerts.
wrangler.jsonc enables logs/traces and URL query redaction for the GUI Worker.
A GUI Worker entry now emits request IDs, status and timing without logging URLs,
headers or cookies. Sign-in's durable audit records are not implemented.
npm run logs -- --help
npm run errors -- --helpBoth use the configured Worker; npm run logs also accepts an explicit Worker name.
npm run errors filters Worker invocation failures, not all HTTP error responses. Durable audit
storage, dashboards and alert delivery are open work in the observability plan.
The docs answers on Cloudflare: AI Search and AI Gateway
Two Cloudflare products sit behind the docs' Ask AI (the docs Worker), and they are easy to mix up:
- AI Search is the index (
remy-docs-pages, remy-auth's; every name here isdocs.config.ts'sask). It reads the docs itself from the R2 bucketremy-docs(one Markdown file per docs page and language,<site>/<lang>/<page>.md, synced hourly and wheneverdocs publishasks), finds the passages that match a question, and asks a Workers AI model to write the answer. - R2 holds the files AI Search reads.
docs publishmakes the bucket hold exactly the docs pages: it puts each one and deletes anything else, so a removed page leaves the answers too. - AI Gateway is the meter in front of the model. Every model call AI Search makes passes through
it (
remy-docs), and it logs each one with its cost, tokens and time (and the question). It holds no docs. Spend limits and rate limits live here;npm run docs -- observe ai-usageandai-checkread it.
Local or remote: the docs pages, the Ask AI page and all checks run locally; answering exist only on Cloudflare (AI Search has no local version). Every command says in its header comment whether it is local or remote (and production).
npm run docs -- publish # REMOTE, PRODUCTION: bucket = docs pages, the index's sync waited for, then the fixed questions (dev:promote runs it)
npm run docs -- questions # REMOTE: the fixed questions alone (docs/content/questions.json), search only, no answer written
CLOUDFLARE_ENV=ask npm run docs -- dev # LOCAL docs Worker, answers from the live index
npm run docs -- answers off # REMOTE, PRODUCTION: emergency stop, seconds, no build
npm run docs -- answers on # REMOTE, PRODUCTION: resume
fnox exec -- npm run docs -- observe ai-check # REMOTE, read only: AI Search, AI Gateway, answers paused or not
fnox exec -- npm run docs -- observe gateway # REMOTE: the gateway's settings
fnox exec -- npm run docs -- observe gateway rate-limit off # REMOTE: change a setting (read back after); also logs on|offTokens: see secrets below.
Costs: indexing is a few embeddings (a full reindex about $0.0005); a search without an answer next to nothing; an answer about $0.0001 to $0.0007, and $0 when AI Search's cache has it.
Ask AI is each app's choice: docs.config.ts's ask names its AI Search instance, R2 bucket, AI Gateway
and rate-limit namespace, and the docs Worker's Cloudflare configuration is generated from it
(docs/.remy-docs/wrangler.json). Without ask the docs have no Ask AI page, button or bindings.
npm run docs -- provision prints the commands that create an app's resources and creates nothing:
that costs money and is the owner's.
Stored history and the AI answers, read only, from Cloudflare's own APIs. The Worker, its AI Search instance and that instance's AI Gateway come from its Wrangler configuration, so an including app gets its own:
fnox exec -- npm run observe -- events # Workers Logs, last 24 h: counts by event and level, latest 10
fnox exec -- npm run observe -- events ask --since 7d --limit 20 # one per question: outcome, time, citations
fnox exec -- npm run observe -- ai-usage # AI Gateway, last 7 days: calls, cache, failures, tokens, cost, time
fnox exec -- npm run observe -- ai-check # AI Search and gateway settings against Cloudflare's advice; fails on FAILSecrets: fnox
Wrangler's login covers deploys, AI Search and Worker secrets, but cannot be granted AI Gateway or Workers Logs access. For those, the commands read tokens from the environment:
CLOUDFLARE_API_TOKENandCLOUDFLARE_ACCOUNT_ID: the shared Cloudflare token and account, the same keychain items in every joeblew999 repo.fnox.tomlnames them (values stay in the macOS keychain, never in the file);fnoxis the machine's. Run a command with them:fnox exec -- npm run observe -- ai-usage. Set one withfnox set -p keychain CLOUDFLARE_API_TOKEN <token>(never omit-p keychain: without it the value is written tofnox.tomlin plain text). It reads Workers Logs and AI Gateway, so it needs Workers Observability Read and AI Gateway Edit; AI Search is read with Wrangler's login. One token does it all (thedevtoken at https://dash.cloudflare.com/profile/api-tokens): AI Gateway Edit (which includes reading) and Workers Observability Read are the ones these commands need; changing the gateway withobserve gatewayuses the same token, and every change is read back.