agentleFS
afaraha8403afaraha8403/balakit/AGENTS.md

balakit

AGENTS.md1 starsChanged 8 days agoMITView on GitHub

Standing rules for OpenCode, Codex, Cursor, and GitHub Copilot, generated from this repository's rules/*.mdc. Edit the source rules, then run the sync script to regenerate this file. Applies to every task in this repo. Project-scoped rules extend or override these. On conflict (within these rules): safety & secrets > correctness > simplicity > brevity. Never compress away a security, data-loss, or accessibility safeguard to satisfy Caveman or Simplicity. Caveman Mode (defined): Terse, compressed prose for the human. Fragments over sentences.…

  • Reads credentials
  • Commits and pushes

The file

Show its rules and text

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

40 rules. About 1 is common, 27 are distinctive, and 12 are very specific to this project.

  • ≈1

    Common · estimate

    Many files like this have a rule of this kind.

  • ≈27

    Distinctive · estimate

    This author's own choices. Worth a look.

  • 12

    Very specific

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

  • Common
  • Distinctive
  • Very specific
  • could be automatic: a setting could enforce it
  1. Distinctive:

    State assumptions: Do this before coding. Genuinely blocked?

    line 38
  2. Distinctive:

    Ask only when it pays: Ask when blocked, or when a choice is costly / hard to reverse.

    line 39
  3. Distinctive:

    Push back: Not a yes-machine. Bad human approach?

    line 41
  4. Distinctive:

    Attack the premise: After two failed fixes that share one premise, census which actors hold the imbalance, then question the premise …

    line 42
  5. Distinctive:

    Name the data shape first: before writing logic, name the types or structures the work will move through.

    line 56
  6. Distinctive:

    Duplicate > Abstraction: No abstractions for single-use code.

    line 58
  7. Distinctive:

    Leave adjacent code alone: No side-effect refactoring or formatting tweaks.

    line 67
  8. Distinctive:

    Match existing style: Always.

    line 68
  9. Very specific:

    Strict filesystem: Ask before creating files.

    line 73
  10. Very specific:

    Windows-safe commands: Avoid &&. Use separate lines/scripts.

    line 74
  11. Very specific:

    Protect secrets [CRITICAL]: Never commit .env, credentials, API keys.

    line 75
  12. Very specific:

    Env vars: Update .env.example in same change.

    line 76
  13. Distinctive:

    Prove it on the real artifact: run the feature, read the actual value, inspect the diff.

    line 84
  14. Very specific:

    Atomic: Update CHANGELOG.md in same commit/PR.

    line 95
  15. Very specific:

    Update CHANGELOG.md (at project root) whenever you or the user:

    line 102
  16. Distinctive:

    Add a new feature

    line 104
  17. Distinctive:

    Remove or deprecate something user-facing

    line 107
  18. Distinctive:

    Do not add trivial edits (typos, comment-only, formatting-only) unless the user asks.

    line 109
  19. Very specific:

    If CHANGELOG.md does not exist, create it with a title, an ## [Unreleased] section, and add the relevant entry/entries.

    line 156
  20. Distinctive:

    If removing the comment wouldn't confuse a future reader, delete it.

    line 170
  21. Distinctive:

    Every part of a module's public surface — exported functions, types, classes, constants — gets a documentation comment in your language's …

    line 192
  22. Distinctive:

    Document a parameter only when its name isn't self-explanatory.

    line 195
  23. Distinctive:

    Document the return only when it isn't obvious from the function name.

    line 196
  24. Distinctive:

    Document every error/exception the function can raise as part of its contract.

    line 197
  25. Distinctive:

    Add an example for non-trivial public APIs and shared utilities.

    line 198
  26. Distinctive:

    Don't duplicate what the language already expresses — let the type system, signatures, and tooling do their job.

    line 199
  27. Distinctive:

    When documentation strings are generated into a public API surface (OpenAPI/Swagger, SDK docs, generated reference sites, schema …

    line 203
  28. Distinctive:

    Run the project's generate or sync step (if any), then its tests and any version-consistency check.

    line 229
  29. Very specific:

    Commit. Tag that commit: git tag -a vX.Y.Z -m "vX.Y.Z".

    line 230
  30. Very specific:

    If the tag workflow fails after the GitHub Release exists, do not publish a different version locally to "catch up." Fix the secret/token, …

    line 233
  31. Distinctive:

    Every test must earn its place by preventing a bug that would affect users.

    line 246
  32. Distinctive:

    Follow whatever layout the project already uses.

    line 258
  33. Distinctive:

    Use the test runner the project already adopts.

    line 262
  34. Distinctive:

    Keep end-to-end tests pointed at a deployed/staging-like environment rather than hard-coded local URLs when the project's flow expects that.

    line 264
  35. Distinctive:

    Do not write E2E tests speculatively.

    line 278
  36. Very specific:

    Never commit API keys, tokens, passwords, or database URLs in any file — including config, .env, source code, or test fixtures.

    line 283
  37. Very specific:

    Use local-only secret files (e.g.

    line 284
  38. Common:

    Use the platform's secret manager for deployed environments.

    line 285
  39. Very specific:

    Prefer an automated secret scanner (e.g.

    line 286
  40. Distinctive:

    If you skip tests, say so in chat with the reason — never in a code comment.

    line 290

≈ “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
<!-- GENERATED FILE — do not edit by hand. Source of truth: rules/*.mdc · Regenerate: ./sync.sh or sync.ps1 -->

Project Rules

Standing rules for OpenCode, Codex, Cursor, and GitHub Copilot, generated from this repository's rules/*.mdc. Edit the source rules, then run the sync script to regenerate this file.

<!-- from rules/base.mdc -->

Base Rules

Applies to every task in this repo. Project-scoped rules extend or override these.

The Meta-Principle

The human is monitoring you in the IDE. They can see everything. Your job is to minimize the mistakes they need to catch while maximizing the useful work you produce.

On conflict (within these rules): safety & secrets > correctness > simplicity > brevity. Never compress away a security, data-loss, or accessibility safeguard to satisfy Caveman or Simplicity.

AI Behavior & Communication (Dual-Mode)

Caveman Mode (defined): Terse, compressed prose for the human. Fragments over sentences. Drop filler and articles (a/an/the). Use symbols (→, =, vs) and logical emojis (🐛, 🚀, 🛑, 📝) so the human scans fast. Compress style only — never correctness — and leave code, paths, URLs, and commands verbatim. (Mirrors the Caveman skill at its full level: "why use many token when few token do trick.")

Reason fully, speak Caveman. Caveman constrains the surfaced message, not your thinking. Plan and reason at full fidelity internally; compress only the text the human reads. Brevity is an output constraint, never a reasoning shortcut.

Two registers — pick by surface:

1. Chat + summaries → Caveman. Goal: instant human "aha" at minimum tokens.

2. Artifacts → Standard Professional Mode. Code, comments, JSDoc, architecture plans, CHANGELOG.md, commit messages, and docs stay highly detailed, articulate, and properly formatted for future developers. Never Caveman.

Post-Change Summary (Caveman). On any turn that modifies files, end with this exact block (skip it on read-only / answer-only turns):

  • ✅ CHANGES: [file] — [short reason, e.g. "Auth logic → fixed login bug"]
  • ⏭️ BYPASSED: [file/concept] — [reason, e.g. "Out of scope", "Wait for human"]
  • ⚠️ CONCERNS: [files, or "none"] — [edge cases / risks found]
  • For any in-code concern, also inject the matching tag at the line: // BUG:, // FIXME:, // TODO:, // CONCERN:, // OPTIMIZE:.

Think Before Coding

No assumptions. No hidden confusion. Surface tradeoffs.

  • State assumptions: Do this before coding. Genuinely blocked? Stop → name the confusion → ask.
  • Ask only when it pays: Ask when blocked, or when a choice is costly / hard to reverse. Otherwise pick the sane default, act, and state the call in one line. Don't stall on reversible decisions.
  • Surface tradeoffs: On real forks, present options → let human pick. No silent high-stakes choices.
  • Push back: Not a yes-machine. Bad human approach? Explain downside → propose alternative. Accept override.
  • Attack the premise: After two failed fixes that share one premise, census which actors hold the imbalance, then question the premise instead of writing a third fix that assumes it.

Simplicity First (Lazy, Not Negligent)

Best code = the code you never wrote. Write only what the task needs.

Climb the ladder before writing code → stop at the first rung that works:

  1. Need it? → No: skip it (YAGNI).
  2. Stdlib does it? → Use it.
  3. Native platform feature? → Use it.
  4. Installed dependency? → Use it. No new dep for what a higher rung covers.
  5. One line? → One line.
  6. Only then: the minimum that works.
  • Naive → Optimize: Build correct naive version first. Verify. Optimize later. Correctness > Performance.
  • Name the data shape first: before writing logic, name the types or structures the work will move through. Downstream code should become obvious from that shape.
  • Only requested features: Build exact request. No unasked "flexibility," no speculative abstraction.
  • Duplicate > Abstraction: No abstractions for single-use code. Stateful or branchy logic belongs in a type, a table, or a state machine — not a growing if-chain.
  • Validate at trust boundaries: user input, external API — and not internal glue. Make illegal states unrepresentable at those boundaries.
  • Build the lever: non-trivial bulk work (migrations, sweeps, similar edits) is a rerunnable script or codemod, not a pile of hand edits.
  • Refine: 200 lines → 50 lines.
  • NEVER cut [non-negotiable]: trust-boundary validation, data-loss handling, security, accessibility. Code stays small because it is necessary, not golfed.

Surgical Changes & Code Discipline

Touch only what is needed. Clean your own mess.

  • Fix cause, not symptom: Change must trace directly to request. Do not add a guard that silences a crash; reproduce, then fix the cause.
  • Leave adjacent code alone: No side-effect refactoring or formatting tweaks. Redesign from first principles only when the new requirement invalidates the current shape.
  • Match existing style: Always.
  • Explain "Why": Articulate, clear inline comments or JSDoc for why, not what (Standard Mode).
  • Dead code hygiene: List unreachable code after refactor. Ask to delete. No silent corpses. Remove dead weight before adding the new path. When reshaping an internal API, migrate callers and delete the old path in the same change.

Filesystem, Environment & Execution

  • Strict filesystem: Ask before creating files. No .md unless instructed.
  • Windows-safe commands: Avoid &&. Use separate lines/scripts. Use PowerShell.
  • Protect secrets [CRITICAL]: Never commit .env, credentials, API keys.
  • Env vars: Update .env.example in same change. Comment purpose, format, source.

Goal-Driven Execution & Validation

Tests = safety net. Changesets = record.

  • Test-first: Complex logic? Write failing test → implement → pass. Show both.
  • Establish criteria: - Validation: failing test → pass.
    • Bug: failing reproduction → pass.
    • Refactor: pass before → pass after.
  • Prove it on the real artifact: run the feature, read the actual value, inspect the diff. Compiling, a delegate summary, or "it looks right" is not proof.
  • Sequence verifiable units: multi-step work checks each unit before the next. Do not batch verification at the end.
  • Minimize reader load: a competent reader should answer "where does X come from?" in thirty seconds. Collapse one-caller wrappers and shrink mutable scope.
  • Skipped tests: Explain in chat, not code comments.

Change Log Maintenance

Maintain human-readable history (Standard Mode - No Caveman).

  • Version: SemVer ([Major].[Minor].[Patch]).
  • Grouping: [Unreleased] on top; group entries under Features / Fixes / Changes. A project changelog rule (e.g. rules/changelog.mdc), if present, is authoritative.
  • Chronological: Newest top.
  • Human-Centric: Clear, articulate impact descriptions. No pure technical logs.
  • Atomic: Update CHANGELOG.md in same commit/PR.
<!-- from rules/changelog.mdc -->

Changelog maintenance

When to update

Update CHANGELOG.md (at project root) whenever you or the user:

  • Add a new feature
  • Ship a significant fix (bug fix that affects behavior or correctness)
  • Make a notable change (refactor, config, dependency, or UX change worth documenting)
  • Remove or deprecate something user-facing

Do not add trivial edits (typos, comment-only, formatting-only) unless the user asks.

Format (grouped by type)

  • Unreleased at top. The first section is ## [Unreleased] for changes not yet in a release.
  • Released versions below. Each release has a section ## [vX.Y.Z] or ## [X.Y.Z] (e.g. ## [v0.0.1-beta.7], ## [1.0.0]). Use the exact version string that will be tagged (with or without leading v).
  • Newest release first under Unreleased. When you cut a release, the previous [Unreleased] content can be moved under a new ## [vX.Y.Z] section.
  • Group by type. Within each version section, organize entries under three subsections: ### Features, ### Fixes, ### Changes.
  • No type prefix. Items do not need **Feature:**, **Fix:**, or **Change:** prefixes since they are grouped by section.
  • One line per item; keep text concise.

Structure:

## Changelog

### [Unreleased]

#### Features
- Short description of new feature.
- Another feature.

#### Fixes
- Bug fix description.
- Another fix.

#### Changes
- Refactor or UX change description.

### [v0.0.1-beta.7]

#### Features
- Something shipped in this version.

#### Changes
- Another change.

### [v0.0.1-beta.6]
- ...

Releases and GitHub

If the project uses a tag-triggered release workflow, it typically looks in CHANGELOG.md for a section whose heading matches the pushed tag (e.g. ## [v1.2.3] or ## [1.2.3]) and uses that section as the release notes body. Add the version section before tagging so the release notes are populated; if it's missing, the release should still succeed with a default body.

If the file is missing

If CHANGELOG.md does not exist, create it with a title, an ## [Unreleased] section, and add the relevant entry/entries.

<!-- from rules/comments.mdc -->

Comments & Documentation

Default to zero comments

Names document code. Add an inline comment only when the WHY is non-obvious:

  • A hidden constraint not visible in the code.
  • A subtle invariant a reader might violate.
  • A workaround for a specific bug (link the upstream issue).
  • Behavior a competent reader would find surprising.

If removing the comment wouldn't confuse a future reader, delete it.

Never write

  • Restatements of the code — increment counter above counter++.
  • Task / ticket references — added for CAN-123, fixes billing bug.
  • Caller references — used by the contacts module.
  • Change history — was async before, removed old logic.
  • Commented-out code.
  • Banner comments — === SECTION ===.

Authorized Tracking Tags (Exception)

You MUST use the following authorized tags to track technical debt and risks (as required by the Global Rules), using your language's comment syntax. These should cleanly describe the issue for IDE tracking:

  • BUG: — For critical, immediate issues.
  • FIXME: — For broken code or technical debt needing refactor.
  • TODO: — For general planned work.
  • CONCERN: — For edge cases or architectural risks.
  • OPTIMIZE: — For performance improvements or clean-up tasks.

Document every exported symbol

Every part of a module's public surface — exported functions, types, classes, constants — gets a documentation comment in your language's convention (doc comment, docstring, etc.). Internal/private helpers only get one when the WHY is non-obvious.

  • The first line is a one-sentence summary ending with a period.
  • Document a parameter only when its name isn't self-explanatory. Never restate information the signature already carries (e.g. the type, in a typed language).
  • Document the return only when it isn't obvious from the function name.
  • Document every error/exception the function can raise as part of its contract.
  • Add an example for non-trivial public APIs and shared utilities.
  • Don't duplicate what the language already expresses — let the type system, signatures, and tooling do their job.

Externally-surfaced docs

When documentation strings are generated into a public API surface (OpenAPI/Swagger, SDK docs, generated reference sites, schema descriptions), those strings ship to external consumers — write them for API users, not just your team.

  • Describe every public field/parameter with a short user-facing sentence.
  • Map each endpoint/handler summary to the generated summary and description.
  • Declare at least one example response for each public route.
<!-- from rules/release.mdc -->

Release version lockstep

One version. The git tag, package.json "version", CHANGELOG heading, and npm publish are the same semver. Never tag or publish a version that is not already committed in package.json.

Identity

SurfaceFormExample
package.json "version"no leading v1.14.0 or 1.15.0-beta.1
git tagv + that stringv1.14.0 or v1.15.0-beta.1
CHANGELOG heading## [vX.Y.Z] (or without v)## [v1.14.0]
npmthat same package.json versionbalakit@1.14.0 (latest) or dist-tag beta

Generated version fields (plugin or marketplace manifests, lockfiles) follow package.json. Bump package.json only, then run the project's generate or sync step. Never hand-edit generated versions.

Order

  1. Cut CHANGELOG [Unreleased] into ## [vX.Y.Z].
  2. Set package.json "version" to X.Y.Z (no v).
  3. Run the project's generate or sync step (if any), then its tests and any version-consistency check.
  4. Commit. Tag that commit: git tag -a vX.Y.Z -m "vX.Y.Z".
  5. Push the tag only after the commit is on the release branch. The v* workflow creates the GitHub Release and runs npm publish. Do not also gh release create or npm publish locally — that duplicates the tag and can publish a different version than the tag.

If the tag workflow fails after the GitHub Release exists, do not publish a different version locally to "catch up." Fix the secret/token, then re-run the same tag job (make gh release create a no-op if the release already exists).

npm auth

GitHub Actions NPM_TOKEN must be an npm Automation token (bypasses 2FA). Publish/classic tokens fail CI with EOTP.

Procedure: release-deploy skill + skills/release-deploy/projects/<owner>-<repo>.md.

<!-- from rules/testing.mdc -->

Testing

Philosophy

Every test must earn its place by preventing a bug that would affect users. Do not write tests to hit a coverage number. If you cannot explain what bug a test would catch, do not write it.

Favor integration tests over unit tests. Test real code paths — input validated, work performed, result returned. Reserve unit tests for complex business logic: pricing calculations, date handling, permission resolution. Do not write unit tests for glue code or tests that mock everything away. If a test would still pass when every imported function returns undefined, rewrite the assertion or delete the test.

Folder Convention

Mirror the source structure under a single top-level tests location (or your framework's convention), separating tiers clearly:

  • Unit tests — complex business logic only.
  • Integration tests — the default tier for most behavior.
  • End-to-end tests — full-stack flows.

Follow whatever layout the project already uses; do not impose a new one mid-project.

Tooling

  • Use the test runner the project already adopts. Do not introduce an additional test framework without team agreement.
  • Match the existing assertion style, fixtures, and mocking approach.
  • Keep end-to-end tests pointed at a deployed/staging-like environment rather than hard-coded local URLs when the project's flow expects that.

When to Write Tests

A behavior change in a PR requires a test that exercises that behavior. "Behavior change" means: what the user sees or what the API returns is different. Refactors that preserve behavior do not require new tests — existing tests should still pass.

Bug fixes: Write the failing test first. The test is the proof the bug existed and that the fix works. If the cheap local test path is unclear, expensive, integration-heavy, or not requested, say so in chat with the closest executable check you will run instead. Prefer no test over a mock-only "regression" that would still pass if every imported function returned undefined.

Prove behavior on the real artifact (the function the user calls, the CLI, the running app) — not a proxy, a self-report, or "it compiles."

End-to-End Tests

E2E tests are often slow and run against a deployed environment rather than locally. Do not write E2E tests that assume a local server or a specific hard-coded URL unless the project is set up for that.

Do not write E2E tests speculatively. Only write them after the user confirms the feature is done. When a feature implementation appears complete, proactively ask the user (Caveman format):

  • "Feature done? Write E2E?"

Secrets [CRITICAL]

Never commit API keys, tokens, passwords, or database URLs in any file — including config, .env, source code, or test fixtures.

  • Use local-only secret files (e.g. .env.local, .dev.vars) that are gitignored.
  • Use the platform's secret manager for deployed environments.
  • Prefer an automated secret scanner (e.g. gitleaks) in pre-commit hooks and CI to enforce this.

Skipping Tests

If you skip tests, say so in chat with the reason — never in a code comment. Acceptable reasons:

  1. The path is provably unreachable.
  2. An existing test already covers the exact behavior.
  3. The human explicitly overrode the test requirement.

Conditional rules

Apply these only when working on matching files:

  • seo-ai-search (globs: **/*.{astro,ts,tsx,jsx,vue,svelte,md,mdx}) — Universal guidelines for SEO and AI-search implementation — meta tags, JSON-LD, llms.txt, crawlability, and adversarial security. → see rules/seo-ai-search.mdc

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.