agentleFS
nrjdalalnrjdalal/zerostarter/AGENTS.md

zerostarter

AGENTS.md65 starsChanged 12 days agoMITView on GitHub

Guidance for AI coding agents working in this repository, a Bun monorepo: the web/next app, the api/hono service, and shared packages/* (auth, config, db, env), with build-only tooling in packages/scripts. The canonical starter also carries the packages/cli npm binary and the tests/ suite, neither of which a fork takes; this guide and every skill ship to a fork whole, rebranded to its name. Start each task with the codebase-map skill to orient, then load the task skill that fits (see…

  • Reads credentials

The file

We split this AGENTS.md into the rules it gives an agent

8 rules. About 0 are common, 3 are distinctive, and 5 are very specific to this project.

  • ≈0

    Common · estimate

    Many files like this have a rule of this kind.

  • ≈3

    Distinctive · estimate

    This author's own choices. Worth a look.

  • 5

    Very specific

    Tied to their project's names, files or tools. Probably skip.

  • Common
  • Distinctive
  • Very specific
  1. Very specific:

    ALWAYS: Use @/ for imports, if applicable.

    line 15
  2. Very specific:

    ALWAYS: Put every build or tooling script in packages/scripts/src/, as TypeScript run by Bun, and declare the dependencies it imports on …

    line 17
  3. Distinctive:

    Do not comment unnecessarily.

    line 21
  4. Very specific:

    Keep comments on a single line.

    line 22
  5. Distinctive:

    NEVER: Use em-dashes (the long dash, U+2014) in code, comments, docs, or copy.

    line 23
  6. Very specific:

    ALWAYS: Follow the design skill for UI, styling, and design decisions (it holds the canonical conventions).

    line 27
  7. Distinctive:

    NEVER: Include "Co-authored-by" in commit messages.

    line 33
  8. Very specific:

    Write audit reports (any kind) to .github/notes/audits/ as dated files (YYYY-MM-DD-<topic>.md).

    line 37

≈ “Common” is an estimate: at least 1 in 5 of the 40,246 AGENTS.md files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.

Keep what fits and drop the rest. Your version, ready for your agents.
Files
AGENTS.md

AGENTS.md

Guidance for AI coding agents working in this repository, a Bun monorepo: the web/next app, the api/hono service, and shared packages/* (auth, config, db, env), with build-only tooling in packages/scripts. The canonical starter also carries the packages/cli npm binary and the tests/ suite, neither of which a fork takes; this guide and every skill ship to a fork whole, rebranded to its name. Start each task with the codebase-map skill to orient, then load the task skill that fits (see Skills).

Workflow

  • ALWAYS: Do every change in its own git worktree, never on the primary checked-out branch. Create it under .claude/worktrees/ (repo-root relative, one directory per worktree; never /tmp, home, or a sibling of the repo), and fork its branch from the latest canary: fetch first, then branch from origin/canary (git fetch origin canary && git worktree add .claude/worktrees/<name> -b <branch> origin/canary), so the change builds on current main.
  • ALWAYS: Show the user a new or altered database schema and wait for their go before generating or applying a migration. Name the choices that are costly to reverse and stop; a shape is cheap to argue about and expensive to change once rows exist, and canary shares its database with production, so applying reaches production immediately. See the db-migration skill.
  • ALWAYS: Point local database work at a disposable container (bunx pglaunch -k) set in the worktree's own .env, never the POSTGRES_URL that ships in the root .env. That one is the shared Neon database read by both canary and production, so a migration or a rename applied there reaches production immediately and under running code. Seed fake rows; real rows must never reach a screenshot or a PR. See the db-migration skill.
  • ALWAYS: Keep documentation in sync with every change. Whenever code, structure, conventions, or tooling change, update the matching docs in the same change (e.g. web/next/content/docs/, README.md, the llms.txt/llms-full.txt context routes, skill docs under .agents/skills/ and .claude/skills/, and these agent guides AGENTS.md/CLAUDE.md). Docs must never drift. See the doc-sync skill.
  • ALWAYS: When code, a convention, a command, a path, or tooling changes, review the skills in .agents/skills/ that touch it and update them in the same change, so every skill stays accurate and relevant. A skill that describes old behavior misleads every agent that loads it, which is worse than no skill. If a change makes a skill obsolete, remove it; if it reveals a gap, consider adding one.

Code

  • ALWAYS: Use @/ for imports, if applicable.
  • ALWAYS: Put every test under the repo-root tests/ directory, mirroring the path of the file it covers (api/hono/src/lib/sql.ts is tested by tests/api/hono/src/lib/sql.test.ts). One bun run test runs the suite; a package never carries its own test/ directory or test script. That script builds packages/* first, because a test reaches a shared package through its exports, which point at dist, so on a fresh checkout an unbuilt package resolves to nothing. Only the shared packages are built, not the apps: a test imports app code by source path and never through dist. tests/ is fork-excluded, so the root script no-ops where the directory is absent. Note bun test skips dot-directories, which is why .github/workflows tests live under tests/github/workflows/. An end-to-end test mirrors the router or page its requests hit and carries the .e2e.test.ts suffix (api/hono/src/routers/admin.ts is driven by tests/api/hono/src/routers/admin.e2e.test.ts), imports the stack helper at tests/stack.ts, drives the artifact over HTTP without importing app source, and skips itself when either of E2E_API_URL and E2E_WEB_URL is unset, which is how bun run test stays green without a stack; bun run test:e2e names the compose ports unless those variables say otherwise, refuses any host that is not local, and needs a local-stage stack (NODE_ENV=local with AGENT_SIGNIN_ENABLED=true) so the agent can sign in, with both OAuth credential pairs set to any value, the id and the secret of each, since a provider registers only when both halves are present and the providers snapshot lists all three.
  • ALWAYS: Put every build or tooling script in packages/scripts/src/, as TypeScript run by Bun, and declare the dependencies it imports on that package. It is a real workspace package, so turbo prune carries it into the Docker build without an extra COPY.
  • ALWAYS: Prefer a Bun-native API when the file runs under Bun and one exists (Bun.file, Bun.write, Bun.spawn); otherwise use a Node built-in with the node: protocol prefix (import { join } from "node:path", require("node:fs")), never the bare specifier. Code that runs under Node in any environment (the packages/cli npm binary in the canonical starter, web/next, where next dev runs under Node while Docker and Vercel serve it under Bun, and shared packages/env) stays on node:. See the runtime-apis skill.
  • ALWAYS: Keep enumerable lists alphabetical (A→Z), union/enum members, env-var schemas and their runtimeEnv/turbo.json mirrors, and the docs that list them, so the code and its docs stay in the same order. Use a meaningful order (flow, priority, required-then-optional) only where alphabetical would obscure intent. API response schemas are included, and they order by relevance first, then A→Z: where one key is what the response is about and the rest describe it, that key leads and the others sort after it (users, then hasNextPage, page, perPage, total). Everything else, a row's own fields included, is plain A→Z with id in its alphabetical place rather than hoisted. Sorting the subject too would put it in a different position on every endpoint, which is the drift this rule exists to prevent.
  • ALWAYS: Version every root catalog entry with a caret range (^1.2.3), never an exact pin or a tilde. packages/scripts/src/deps-manager.ts rewrites exact and tilde specs on postinstall, including specs it promotes into the catalog from a workspace dep, and reports the rest (wildcards, dist-tags, compound ranges) for a manual fix. There is no opt-out: no pin survives an install, so pinning deliberately means changing the rule in that script and recording why in .github/notes/dependencies.md.
  • Do not comment unnecessarily. Only comment if it is absolutely necessary.
  • Keep comments on a single line; do not split one across multiple // lines or use multi-line /* */ blocks.
  • NEVER: Use em-dashes (the long dash, U+2014) in code, comments, docs, or copy. Regular hyphens are fine; for a pause or aside, use a comma, colon, or period.

UI

  • ALWAYS: Follow the design skill for UI, styling, and design decisions (it holds the canonical conventions). Update it in the same change when a convention changes.
  • ALWAYS: For any frontend or UI change, verify it in a real browser with agent-browser before opening or updating a PR; drive the actual page or flow, do not rely on type-check and lint alone. Run the end-to-end flow when the change spans it or when asked. Capture screenshots and attach them to the PR with gh pr comment --attach. See the ui-verify skill.

Commits

  • Make atomic commits in the Conventional Commits format. See the gh-commit skill.
  • NEVER: Include "Co-authored-by" in commit messages.

Working notes

  • Write audit reports (any kind) to .github/notes/audits/ as dated files (YYYY-MM-DD-<topic>.md). Audits are transient working docs: delete one once its findings are fully addressed (shipped or consciously won't-fixed) so the directory does not accumulate stale records.
  • Track planned, in-progress, and parked work in .github/notes/plans/ (an index plus one file per item), not in dated audit files or scattered across issues; issues are the inbox, folded in and closed once captured.
  • A fork starts both directories itself: .github/notes/ is the starter's own working record and does not ship.

Logging in (agents)

Signs in as LocalAgent (agent@local.host). The route is gated: set AGENT_SIGNIN_ENABLED=true in .env first (it is off by default, so the route 404s without it and a deployed default env never exposes it). Then click Login (agents) in the dev UI, or use curl:

WEB=$(bunx portless get zerostarter); API=$(bunx portless get api.zerostarter)
curl -sS -c cookies.txt -X POST -H "Origin: $WEB" "$API/api/agents/sign-in-as"
curl -sS -b cookies.txt "$API/api/v1/user"

Local-only (needs NODE_ENV=local and AGENT_SIGNIN_ENABLED=true) and requires a trusted Origin header. See api/hono/src/routers/agents.ts if needed.

Skills

Skills live in .agents/skills (symlinked to .claude/skills and .github/skills, so every agent tool reads the same files). Each is a SKILL.md with a description trigger and a literal procedure; only the description is scanned until a skill matches. Start with codebase-map to orient, then load the task skill that fits. Custom skills are maintained in this repo; vendored skills are copied verbatim from an upstream project (re-vendor to update, do not hand-edit).

Custom

<!-- skills:custom -->
SkillDescription
add-packageAdd a new shared workspace package under packages/*.
api-endpointAdd a typed Hono API endpoint or WebSocket route: router, OpenAPI docs, validation envelope, and RPC client wiring.
auditRefresh every dependency and version pin to its latest release, run the dependency security audit, and maintain .github/notes/dependencies.md.
codebase-mapOrient in this repo: which file to edit for a change, how a change ripples across the stack, and how to search the code.
db-migrationCreate and apply a Drizzle schema change.
designFollow and maintain the app's UI conventions.
devStart, restart, and verify the ZeroStarter dev stack. bun run dev serves portless named .localhost URLs (branch-prefixed in a worktree); resolve them with bunx portless get.
doc-syncSync docs and skills so they never drift from the code.
docker-testBuild and smoke-test the Docker images with docker compose, and run the golden end-to-end suite against them.
fontsAdd, swap, or remove a self-hosted web font (latin variable woff2 from fontsource, localized via next/font/local).
gh-commitCreate atomic commits in the conventional format.
iceboxIcebox a raised-but-undecided concern instead of forcing a plan-or-dismiss call: record it with no verdict so the context survives.
ignore-syncMirror .gitignore to .dockerignore.
releaseCut a production release by promoting canary to main.
runtime-apisPrefer Bun-native APIs, else Node built-ins with the node: prefix.
shadcn-syncRun and reconcile the shadcn component sync (bun run sync:shadcn).
skills-managerKeep the AGENTS.md skills tables generated from skill descriptions, and understand how a fork syncs its skills from upstream.
ui-verifyVerify a frontend or UI change in a real browser.
<!-- /skills:custom -->

Vendored (upstream, copied verbatim)

<!-- skills:vendored -->
SkillDescription
agent-browserBrowser automation CLI for AI agents.
portlessSet up and use portless for named local dev server URLs (e.g. https://myapp.localhost instead of http://localhost:3000).
<!-- /skills:vendored -->

Download now (ZIP)

Does it work?

Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.

No reviews yet

People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.

  • It worked
  • Partly
  • It didn't
What did you use it for? e.g. Reviewing pull requests in a Rails app

Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.

Your trail

Files you open will collect here, so you can find them again.

Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.

Now do this for your own.

Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.