agentleFS
pc-stylepc-style/x-md/AGENTS.md

x-md

AGENTS.md192 starsChanged 8 days agoMITView on GitHub

  • Where files are headingNew AGENTS.md files have more rules about keeping secrets out of the code, and fewer about code style.

    Of the AGENTS.md files we read, the 31,700 first seen in the last six months, against the older ones: the kind of rule that gained most share, and the kind that lost most. About files like this in general, not this one, and an estimate, since a kind is a pattern in the words.

  • In this repository7 other files it gives its agents.

The file

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

1 rule. About 0 are common, 0 are distinctive, and 1 is very specific to this project.

  • ≈0

    Common · estimate

    Many files like this have a rule of this kind.

  • ≈0

    Distinctive · estimate

    This author's own choices. Worth a look.

  • 1

    Very specific

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

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

    Every API failure goes through lib/apierror.ts: RFC 9457 problem details built from ERROR_CATALOG, which is the single source of the …

    line 14

≈ “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

x-md

  • Authorization: Treat only actions explicitly requested by the user, plus work and verification directly required to complete that request, as authorized. Ask before expanding scope or taking an external, irreversible, or account-changing action. Never treat an inferred benefit or your own judgment as user approval.
  • Landing: index.html (src/main.ts), shared chrome markup in src/chrome.ts and its behaviour in src/chrome-setup.ts; keep markup builders out of chrome-setup.ts, since it is a render-blocking chunk on every page. Docs: Blume MDX in docs/, configured by blume.config.ts, mounted at /docs. Build Blume before Vite; Vite preserves the generated docs in dist.
  • Tokens are the Tailwind v4 @theme block in src/tokens.css (shared by the landing page and Blume) (ink, ink-2, ink-3, ink-4, surface, raised, raised-2, line, hair, accent, accent-deep, accent-soft, cyan, dark code/code-ink/code-dim). Use them, not hex.
  • Look: dark by default on the landing, docs and content pages (green-black #080b09, the brand green with dark text for the primary action); a stored choice of light still wins, and the light theme is warm paper #f7f6f2 with deep green #146c43. Satoshi, pill buttons, 16px cards, near-black code panes. The landing hero and closing call to action are .night bands that stay dark in both themes. Not pcstyle.dev styling.
  • Landing copy frame (Theo's feedback): "Tweets are just markdown now", what-you-see vs what-your-agent-sees curl comparison in the #how bento, skill install under #agents. No stack or provider talk on the landing page.
  • Motion: load-time motion (the hero card's scan from the post as x.com shows it to its Markdown, the hero horizon rising) is CSS keyed off html[data-motion], which the index.html head script sets only when motion is allowed; scroll motion (the #how panes, the closing name typed in front of the host) is GSAP + ScrollTrigger in setupMotion (src/motion.ts), gated by gsap.matchMedia. Mouse-only touches (the card light, the hero card's scan line following the pointer) are src/pointer.ts, which main.ts loads only for a hover-capable fine pointer. The prerendered markup is always the finished state, so JavaScript off and reduced motion show it without animation.
  • Gradients: the live gradients are named canvases (canvas[data-gradient]) that src/gradient-canvas.ts mounts with the definitions in src/gradients.ts, one kind of light per dark band: aurora over Greenshine's horizon in the hero, an eclipse under the mid-page statement, fluted glass in the skill card, dawn behind the closing name, and the project's own chrome inside the headline's "markdown" and the closing "mdfrom". Their MIT engine is vendored in src/gradient-engine/, trimmed to the kinds those use (mesh, limb, chrome, aurora, radial-glow, rise, fluted); add a kind by copying its GLSL and WGSL twins from the served engine and registering it in kinds.ts. Local edits are strict-mode fixes, the data-painted marker in mount.ts, and squaring by hand (or flooring at 0) wherever a shader calls pow() on a base that can go negative, which is undefined on some GPUs (marked x-md:); check every newly copied shader for that. The page also runs three gradients.sh Pro components, ported from React to plain functions in src/gradients-pro/ (marked x-md:): Spotlight Grid on the card grids (pointer.ts), Border Beam round the converter (main.ts) and the Glow Tabs light (tabs.ts). The Pro presets and components are used under the owner's Pro license and tagged to that account: keep each file's license line and closing tag line, never copy any of it elsewhere, and do not add other Pro presets or components without the owner's say-so. Preset values may be customized (gradients.sh presets are meant to be tuned); each definition says which values it changed. Every canvas sits over something that already paints (each *-sky box's prerendered CSS fallback, the chrome words' static fill) except the hero's aurora, which is extra light over the arc (its full-band stand-in cost the throttled trace bench about 400 ms of first paint), and gradient-canvas.ts skips the live engine when WebGL2 is missing or the renderer is detected as software (SwiftShader, llvmpipe and similar), so a headless bench or screenshot that falls back to SwiftShader measures the fallback, not the live canvas.
  • Status URLs serve Markdown by default. Discord, Telegram, and Slack preview bots get Open Graph HTML from lib/embed.ts via api/convert.ts; GET /oembed rewrites to api/oembed.ts.
  • Landing content is pre-rendered at build time: src/landing.ts holds the markup, src/vite-prerender-plugin.ts writes it into index.html, and src/main.ts only enhances what is already there. The page must stay readable with JavaScript off, so put content in landing.ts, not in a runtime DOM build.
  • The public pages carry a page-weight budget. Webfonts are self-hosted and subset to the range the site renders: scripts/build-fonts.ts writes the content-hashed faces into public/fonts/, src/style.css declares the landing ones, blume.config.ts declares the docs ones from the same files, and every page preloads all three landing faces (500, 700, and the 900 for its h1) so none of them waits on style recalculation. bun run fonts:build re-subsets (needs fontTools and the network), bun run fonts:check verifies the committed files offline, and src/fonts.test.ts fails if any rendered copy, docs page or OpenAPI description uses a character the subset drops. The stylesheet is inlined into each page by src/vite-inline-stylesheet-plugin.ts, and vite.config.ts gives src/style.css a chunk of its own so no lazily loaded chunk lists the deleted file as a preload dependency (Chrome's parser fetched a disabled marker link anyway, a 404 on every visit). GSAP, the gradient engine, the Pro lights, PostHog and Web Analytics load off the critical path (src/motion.ts, src/gradient-canvas.ts, src/gradients-pro/, src/posthog.ts, src/deferred.ts). Measure a change with bun bench/frontend-load.ts and node bench/frontend-trace.mjs before keeping it.
  • middleware.ts (Vercel Routing Middleware) does Accept-based content negotiation for /, /docs/*, /about, /contact, /privacy, /terms: Accept: text/markdown or ?mode=agent rewrites to the page's .md sibling, an unsatisfiable Accept is 406, and every response gets Vary: Accept plus RFC 8288 discovery Links. The parser is lib/negotiate.ts. A new negotiated page needs both a .md sibling and a matcher entry.
  • Every API failure goes through lib/apierror.ts: RFC 9457 problem details built from ERROR_CATALOG, which is the single source of the machine code, its status, title, and resolution. Add a code there, not inline — lib/openapi.ts, api/index.ts, and docs/errors.mdx all render from it.
  • Routes are versioned: /api/v1/* is the stable machine surface, the permalink routes are the unversioned product surface, and /api/convert and /api/browse are deprecated aliases that must keep emitting Deprecation/Sunset/successor-version (setDeprecationHeaders in lib/apierror.ts). The published policy is docs/versioning.mdx; keep it, x-api-lifecycle in lib/openapi.ts, and the versioning block in api/index.ts in agreement.
  • Quotas live in lib/quotas.ts and are advertised by lib/ratelimit-headers.ts. Policy names ship in response headers and the OpenAPI document, so renaming one is a breaking change.
  • packages/sdk is the mdfromx npm package (plain client plus mdfromx/effect). Its types, Effect Schemas and error classes are generated from public/openapi.json by scripts/build-sdk.ts; fix a wrong field in lib/openapi.ts, never in the generated files. A change users of the package will notice needs a changeset (bunx changeset, then commit the .changeset/*.md file). Releases go through Changesets: merging pending changesets opens a "Version Packages" PR, and merging that PR is what publishes to npm. CI does not start on that bot PR by itself, so close and reopen it to get the required build check, or merge it with the admin bypass.
  • lib/openapi.ts is the OpenAPI 3.1 source; bun scripts/build-openapi.ts renders the committed public/openapi.json and --check fails when it is stale. Discovery documents are hand-written under public/ and public/.well-known/ (llms.txt, agents.md, auth.md, pricing.md, ard.json, ai-catalog.json, api-catalog, mcp/server-card.json); Vite copies public/ last, which is how openapi.json overrides blume's own.
  • The MCP server at /mcp speaks two protocol eras through one dispatch: modern (2026-07-28, stateless, version in MCP-Protocol-Version and params._meta, results carry resultType and cache hints) and legacy (2025-11-25 and earlier, initialize handshake, untouched result shape). finalizeResult in lib/mcp.ts is what stamps the modern fields; negotiateProtocol is legacy-only and must never answer 2026-07-28, which removed initialize. Regenerate public/server.json and public/.well-known/mcp/server-card.json from registryManifest()/serverCard() when either changes — a test pins them.
  • Deploy: Vercel after bun run build. vercel.json configures dist, the API handlers, and the public route rewrites.
  • Live search provider: lib/xsearch.ts; public allowance is a fixed 10 per IP per 15 min plus a shared pool computed in lib/pool.ts. Counters live in lib/ratelimit.ts (shared Redis via lib/redis.ts, memory fallback). FxTwitter search, the tier above it, sits behind a circuit breaker in lib/browse.ts whose state is shared through lib/kv.ts, so one instance's failed probe cools down the fleet and the cooldown doubles per consecutive failure. Keep provider internals and capacity math out of public prose; describe it as a custom-built provider.
  • Checks before pushing: bun run test and bun run build (the build already starts with tsc). After touching lib/openapi.ts, run bun run openapi:build and then bun run sdk:build, and commit the regenerated public/openapi.json and packages/sdk/src/**/generated/ — the build rewrites both in place, so openapi:check and sdk:check only ever catch a stale committed copy, which is their job in CI. main is protected by a ruleset: open a PR, the build and CodeRabbit checks must pass, a Preview deployment is required, commits must be signed, and the branch must be up to date with main. No approvals are required; merges are squash or merge, not rebase.
  • Reviews: CodeRabbit reviews every PR by default. Greptile's automatic reviews are off; it is an extra layer for PRs that could break something or need more testing than the unit suite gives: a public route, response shape, error code, quota, the OpenAPI document or SDK, the MCP server, middleware.ts negotiation, caching, the upstream providers, or the build and deploy config. For those, comment @greptile on the PR, with a line of focus when it helps (@greptile check the deprecated aliases still send Sunset). With the repository's Greptile environment active, that review runs TREX, which starts the app and tests the change end to end. Skip it for copy, docs, styling, and other low-risk PRs.

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.