claude-code-standards
CLAUDE.md1 starsChanged 13 days agoMITView on GitHub
This file enters context in every project, every session and every agent turn — it is the most expensive instruction file there is. Only the rule itself goes here; rationale, history and measurements move to docs/decision-log.md (standards/00 §6a). Size gate: scripts/md-budget.tsv. Detailed standards live in standards/ (paths are relative to the plugin root) — index: standards/README.md or the software-standards skill. Project-specific rules live in the project's own CLAUDE.md and override the rules here — with one exception, #29. - English…
- Reads credentials
- Deletes or force-pushes
- Commits and pushes
In this repository5 other files it gives its agents.
- board-planSkill
- configSkill
- software-standardsSkill
- test-inventorySkill
- working-modeSkill
The file
Show its rules and text
We split this CLAUDE.md into the rules it gives an agent
13 rules. About 0 are common, 8 are distinctive, and 5 are very specific to this project.
≈0
Common · estimate
Many files like this have a rule of this kind.
≈8
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
- Distinctive: line 26
Small step first: Before a large refactor, propose a small patch and wait for approval.
- Very specific: line 30
One API — web and mobile consume the same contract: No platform-specific endpoints.
- Distinctive: line 31
Authorization is fail-closed: Default is DENIED. Never build semantics where "I forgot to configure it" means "open to everyone".
- Distinctive: line 33
Tests get updated: If a file that has tests was touched, its tests are updated.
- Distinctive: line 35
Ask before adding a dependency: Write down why it is needed, what the alternative is, and its maintenance cost, then wait for approval.
- Distinctive: line 40
Report the truth: If tests are red, say so with the output.
- Very specific: line 52
If the task spans multiple files or layers (API + client, migration + code, i18n tr+en), did all of them change?
- Distinctive: line 53
If something is knowingly deferred, list it explicitly in the final report — never skip it silently.
- Very specific: line 61
First
git fetchand updatedev: Do not branch from a stale base. - Very specific: line 62
Create a new branch (or worktree) off
devand work there: Never commit directly on dev. - Distinctive: line 87
Scope: EVERY test address the system might send a message to — e2e (web and mobile), seed/e2e accounts in the test environment, data …
- Distinctive: line 100
When the code is done, unit tests are written (#8), then the tests run once.
- Very specific: line 104
Every promotion to test and to prod WARNS "e2e was NOT run" and carries on, never read as a pass.
≈ “Common” is an estimate: at least 1 in 5 of the 26,980 CLAUDE.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.
Files
Global Working Rules
This file enters context in every project, every session and every agent turn — it is the most expensive instruction file there is. Only the rule itself goes here; rationale, history and measurements move to
docs/decision-log.md(standards/00§6a). Size gate:scripts/md-budget.tsv. Detailed standards live instandards/(paths are relative to the plugin root) — index:standards/README.mdor thesoftware-standardsskill. Project-specific rules live in the project's ownCLAUDE.mdand override the rules here — with one exception, #29.
Language
- English throughout — prose, headings, file and folder names, identifiers, commit messages and comments. There is no second language in this rule set.
- User-facing text is never a raw string → an i18n key (the primary locale is mandatory, the secondary one ships as a placeholder).
Default stack
.NET (Web API) + PostgreSQL/SQLite · React + Vite + TypeScript · React Native/Expo · Playwright (web e2e) · Maestro (mobile e2e) · GitHub Actions.
Invariant rules (apply to every project)
- Small step first. Before a large refactor, propose a small patch and wait for approval. No unrequested "while I was in there" improvements.
- Single source of truth. Hard-coded URL / IP / port / host / API key is forbidden. Each tier has exactly one config module; other files never read
process.env/import.meta.env/IConfigurationdirectly, they take a named import from that module. Fallbacks exist for DEV only and are defined in one place. - Secrets never enter the repository. Passwords, tokens, connection strings, certificates → env / secret store. The repo holds only
.env.example. If a secret leaks: rotate first, clean up second. - Backward compatibility is mandatory. APIs and databases evolve additively only. Fields and endpoints are never deleted, renamed or retyped; they are marked obsolete and keep returning real values. →
standards/08-backward-compatibility.md - One API — web and mobile consume the same contract. No platform-specific endpoints; differences are resolved in the UI layer. Business logic never lives on the client. →
standards/07-api-design.md - Authorization is fail-closed. Default is DENIED. Never build semantics where "I forgot to configure it" means "open to everyone". Every endpoint checks authorization in the backend; the check in the UI is UX only.
- Validation in two places. On the client for UX, in the API for security. Client-side validation is never sufficient on its own.
- Tests get updated. If a file that has tests was touched, its tests are updated. If there are no tests, say so explicitly. A behaviour change is never merged untested.
- Never leave a 300+ line file. Split it at its natural boundaries (modal, list renderer, form, sub-service). Splitting must not change behaviour; the main file stays an orchestrator.
- Ask before adding a dependency. Write down why it is needed, what the alternative is, and its maintenance cost, then wait for approval.
- No magic strings. Constants become enums/consts. Enum switches always carry a
defaultbranch (forward compatibility). - Date format
dd/mm/yyyy. Locale-awaretoLocaleDateString/Intland dot-separated formats are forbidden. Transport and storage are always UTC ISO-8601. - Search is always case- and accent-insensitive. "sisman" ↔ "Şişman", "istanbul" ↔ "İstanbul" must match. Raw
.Contains/.ToLower().Contains()/LIKEis forbidden; a central normalizer is used. - A new rule is never left verbal. Once a permanent decision is made, write it in the same turn to the relevant
CLAUDE.md(project) or to the rule set'sstandards/(global). Do not finish the task while skipping this step. - Report the truth. If tests are red, say so with the output; name any step that was skipped. Never report completion on the basis of "it probably works".
- Setup is documented. Every project carries
SETUP.md+.env.example+ a secret/token inventory (what it is, where to get it, where it is stored, who owns it, rotation). Any change that adds a tool, env var or secret updates these in the same PR. A clean machine must be set up by following the document, without guesswork. - A single origin is preferred. The API is served under the UI's domain (
app.example.com/api/*); a separateapi.subdomain is the exception and requires an ADR. The SPA fallback must not cover/api/*. - A backup is only a backup if it has been tested. 3-2-1 rule (one copy off-server), encrypted, one restore drill per month, and a record of the drill. A failed backup and a backup that never ran are alarmed separately. Not just the database: user files, configuration, certificates and secrets are all in scope. Take a manual backup before any
DROPor bulk update. - Security scanning is automatic. Secret scan + dependency CVE on every push; SAST on pull requests; OWASP ZAP baseline after the test deploy. Before a release, the OWASP Top 10 mapping table is reviewed (
standards/15-security.md§12). Critical/high findings block the merge. SAST and SECRET SCANNING are steps in every project and also run locally (scripts/codeql-scan.sh,gitleaks detect); CI calls the same script with the same thresholds — never two different rules in two places. A script that runs every gate in the pipeline locally must exist (scripts/merge-gate.sh→gate-core.sh) so verification does not stop when CI is down. A gate that did not run did not pass — it is reported as "skipped" and the result is not green. False positives are suppressed only through justified triage; the rule itself is never switched off. →standards/15-security.md§13a-13c - An autonomous background agent is never started without asking. Nothing that keeps running turn after turn without user intervention —
/loopautonomous mode, a self-retriggeringScheduleWakeuploop, a cron/schedule-based agent — is set up without explicit prior approval. If such a job is already running, report it proactively: what it is doing, what it is waiting for, what it is consuming, how to stop it. Never leave it running silently.
- ⚠️ APPROVED, but CONDITIONALLY. The conditions and stop rules are in
modes/autonomous-run.md— task list, definition of done, stall brake, STOP on any irreversible action; no money stop. If any condition is absent the run does not start and this rule applies in full again. 21-23. [Delegated to #27 / removed] The numbers are preserved so references do not break; the original text and rationale are indocs/decision-log.md§21-23.
- A self-administered completeness check is mandatory before saying "done". Immediately before reporting a task as "done / finished / complete", in the same turn and without being asked, I apply this checklist to myself:
- Re-read the user's original request (do not rely on a summarised memory of it) and verify item by item that every point in it is satisfied.
- Were edge cases and error paths considered? (empty list, null, unauthorized access, concurrency, backward compatibility.)
- Were tests (#8), build/lint/format, and where relevant the SETUP.md/.env.example/secret inventory updates (#16) actually run?
- If the task spans multiple files or layers (API + client, migration + code, i18n
tr+en), did all of them change? - If something is knowingly deferred, list it explicitly in the final report — never skip it silently.
- Say "done" only after passing the check.
→ the request list, evidence and forbidden patterns:
standards/00-working-method.md§4a; rationale and application notes:docs/decision-log.md§24
- The gate is SHARED and runs at every promotion; running e2e is OPTIONAL (#33). Two layers:
scripts/gate-core.sh <dev|test|prod>is the SHARED STEP SET (canonical copy in the configuration repository, a committed copy in every project); the project'sscripts/merge-gate.shis the orchestrator and CALLS it. A gate cannot depend on a path outside the repository (CI runners lack the configuration).gate-core.sh <target> --listprints what would run.
feature/* → devanddev → test: EVERYTHING EXCEPT RUNNING E2E (the step list is instandards/13-pr-and-review.md§4), with coverage as #29 says; a missing e2e spec is a warning, never blocking (#33).- A step that did not run did not pass. A missing tool is reported as SKIPPED and the result is INCOMPLETE, never green; the exit code is the gate.
- A project may ADD steps to the shared gate; it may never remove one. → the step list:
standards/13-pr-and-review.md§4; rationale:docs/decision-log.md§25
- Once the work is planned: pull
dev→ branch/worktree offdev→ work there → one commit per task, merged todevthrough a gate. The order is binding: - First
git fetchand updatedev. Do not branch from a stale base. - Create a new branch (or worktree) off
devand work there. Never commit directly ondev. - Each task is committed on its own (its own commit(s), the task named in the message) — never mixed into another task's commit. Ready branches reach
dev/testas ONE batch: one review, one test run, one gate on the merged result — a producer (agent, background task) finishes its code and tests (at most a narrow run of its own piece), hands off, and is never reviewed or gated alone; the auditor also judges the test and gate results and sends findings back; fixes go on their own branch;devnever impliestest; never squashed. →standards/13-pr-and-review.md§8 - Claude performs the
dev/test/prodmerges and pushes as the configuration says (#34) — never--force, not over a red gate (#25, #33). - The formatter/linter runs once at the END of the task list, not on every merge (#25).
- ⚠️ The configuration repository's own layout: branches
dev/test/prod. The live config is the installedadyusufplugin, copied fromprodby/plugin update; work happens in a separatedevworktree and reaches the live config only by promotion, which Claude performs (standards/00-working-method.md§7a). → rationale:docs/decision-log.md§26
- The operating mode (A/B/C/D/E) is selectable per project; the selection IS the approval. The mode determines agent usage, review and approval policy together. Single source:
modes/README.md; the selection lives in the project's.claude/modefile. To change it:/adyusuf:working-mode <letter>.
- A Skill (no agents) · B Selective (
analyst/test-writer/doc-writer) · C Full team (9 roles) — DEFAULT (the configuration'smode) · D Wide team (14 roles) · E Fan-out (Workflow). The Agent Teams modes (X/Y/Z) are archived and not offered —modes/archive/. - ⚠️ No agents in A; in B/C/D/E choosing the mode is the approval — no separate question before a call, and the agent count plus estimated cost are reported at the end of the turn. Automatic delegation counts as a call too. In C/D/E review is two-layered: the
qaagent performs the first pass and I verify the critical findings. - ⚠️ The mode never loosens any of these: approval on irreversible work (deploy,
DROP, force push, sending anything to the outside world), a red-gate promotion (#26), the completeness check before "done" (#24), secrets staying out of the repo (#3). <letter> <model>(e.g.C sonnet) runs only the Opus agents on<model>; the letter alone = every agent on its defined model →modes/README.md› Model override.- How to apply: never ask the mode at session start. Order: a session choice → the project's
.claude/mode→ the configuration'smode(default C, Opus agents onsonnet). Change it with/adyusuf:working-mode(session, project) or/adyusuf:config(the defaults). The agents of the mode and their models can be adjusted per role (/adyusuf:config,agents.*). →modes/README.md› Session start;docs/decision-log.md§27
- On every pass the auditor CHECKS for gaps and errors, SENDS WORK BACK, and GETS IT FIXED; cost is reported at every handoff. On every turn that uses agents:
- The completeness-check block is mandatory. Every role whose output someone else will rely on (every role except the four the orchestrator audits instead) closes its report with an evidence block: Verification (command run / range read) · Item mapping (each requested item → file:line) · Not covered → Result: serious gap NO | YES. The block is written even when the pass is clean. The orchestrator writes one line per handoff (evidenced
✅ clean+ cost) and the full block at the end of the turn and on every "YES"; it never swallows the role's own block. ⚠️ This is a check, not a question: the auditor does not ask "is anything missing?" — not the user, not the producing role. What cannot be verified does not count as fine. - If something is missing it is SENT BACK, not escalated to the user. The work returns to its producer (
qa→developer/me →qaagain); the hand-back carries what is missing · with what evidence · what to do. It reaches the user only for the stop reasons in §5 and at the ceiling — and even then as a status report, not a question. - One clean pass is enough. A single "no serious gap" is sufficient for a handoff. The
Verificationline must carry the command that was run or the range that was read. On "YES" the work goes back; when the fix arrives, the same verification that surfaced the finding is re-run. Ceiling: the same work is sent back at most twice (3 passes); if it is still not resolved the chain stops and the user is informed, with unclosed findings listed individually as open findings. A "serious gap" is anything that affects behaviour, security, backward compatibility or data, or that leaves a requested item unmet. - No handoff while a finding is open — the auditor gets it fixed. A hand-back is not a note, it is an order. A finding closes only by (a) being fixed and evidenced, (b) the user explicitly saying "don't", or (c) being reported as an open finding with an out-of-scope justification — no finding is ever dropped silently. The end-of-turn report shows closed vs. still open.
- Three audit gaps are closed:
analystalso returns the command that produced its finding ·devopsoutput goes throughqa·product-manageroutput goes to user approval. → detailmodes/role-selection.md§2a, §3, §5-§8; rationaledocs/decision-log.md§28
- Line coverage of AT LEAST 80% in every codebase — one written exception.
- The measure: line coverage, every codebase SEPARATELY — backend · web · mobile Android · mobile iOS. Never averaged. An unmeasured codebase does not count as passing; it is reported as "not measured" and still blocks the push.
- The denominator must be honest: only generated code is excluded (EF migrations +
ModelSnapshot,obj/,*.g.cs,*.Designer.cs,.d.ts, the tests, e2e/config). The exclusion list lives in one place, with a reason per entry. Removing hand-written product code from the list is loosening the threshold → forbidden. Sole exception: mod glue,standards/10-test-strategy.md§7.2a. - The gate: the coverage step is in the shared gate (#25) and runs before a push where
coverage_before_push.<t>is yes (#34); below the threshold → exit code ≠ 0. CI calls the same core with the same threshold. - No loosening: the threshold is not lowered and the exception above is the only one. A project's
CLAUDE.mdCANNOT override this rule. - Fake coverage is forbidden: e2e does not count towards this figure. Writing assertion-free tests is the same as loosening the threshold — an added test must catch a fault under mutation (
standards/10-test-strategy.md§7). - Adoption: the first session opened in a project measures coverage, installs the gate if there is none, and reports the gap along with a plan to close it. No measured push passes until the gap is closed. → rationale:
docs/decision-log.md§29
- Email in test data goes to a REAL mailbox:
<account>+<variable>@gmail.com.
- Scope: EVERY test address the system might send a message to — e2e (web and mobile), seed/e2e accounts in the test environment, data entered by hand in the integration environment, invitation/link recipients.
- Forbidden: fake domains —
.test,.local,example.com,sample.*. - Single source: the address is produced by one helper in the tests (the base is overridable via env, e.g.
E2E_EMAIL_BASE); addresses are never written by hand into a spec or seed (#2). - Out of scope: tests whose sender is faked. → detail
standards/11-playwright.md§4; rationaledocs/decision-log.md§30
- The run cycle (e2e AND every test/gate run →
standards/00§11; parallelism/reuse → §12): full run → identify failures → fix → run only what was fixed → I decide on a full re-run.
- The WHOLE suite runs first, without stopping at the first failure. Failures are classified: product bug · stale spec · data/fixture · environment.
- Failures are fixed — each fix in its own commit; fixes may share one gate and one merge (#26). Raising retries or loosening assertions does not count as a fix.
- Then ONLY the fixed tests (and those they could affect) run.
- ⚠️ E2E is optional (#33): if run, only against code on
test; verification ondevis unit tests + tsc/lint (#25). - I decide whether to repeat the full suite and report the reasoning: repeat it if the fix touched something shared · if the promotion record requires a full run · if some failures were environmental; if the fix is limited to a single spec, a targeted run is enough.
- A run that hit an environment limit is invalid; it is not read as a product failure — parallelism is lowered and the run repeated. → detail
standards/11-playwright.md§9a; rationaledocs/decision-log.md§31
- Order: ALL the code first → then unit tests are written → then unit tests run; e2e is optional (#33).
- The planned work's code is written in full; tests are not run after every small change.
- When the code is done, unit tests are written (#8), then the tests run once; anything red is fixed and only the relevant tests re-run.
- E2E is optional and never run by a gate (#33).
- #26 still holds: each task gets its own commit and reaches
devthrough a gate — alone or in a batch — once its unit run is green. → rationale:docs/decision-log.md§32
- E2E is OPTIONAL — no gate runs it and it never blocks a promotion (user decision 03/10/2026: not enough resources to run it).
- Every promotion to
testand toprodWARNS "e2e was NOT run" and carries on, never read as a pass. Run it by hand or withGATE_RUN_E2E=1(a red result then blocks like any step). test → prodchecks neither thetestbranch nor the test environment (04/10/2026, general rule): it WARNS;GATE_CHECK_TEST_DEPLOY=1verifies the deployed SHA and a mismatch then blocks. The missing-spec check stays a warning. →docs/decision-log.md§33
- Merges, pushes and the gates before them follow the configuration (
/adyusuf:config), not questions. When the code is done: merge wheremerge.<t>is yes, run the gates wheregates_before_push.<t>is yes, push wherepush.<t>is yes, then wait for green CI whereci_after_push.<t>is yes; before deployingtest/prod, run e2e ondev/testwheree2e_before_deploy.<t>is yes. A red gate, CI run or e2e blocks every later target. A gate set to no is NOT run and the merge commit carriesGate-Waived: <gates> (neden: configuration); before aprodmerge list those lines in the report. Never ask what a setting answers. A gate that did not run did not pass; coverage followscoverage_before_push.<t>(#29). →standards/13-pr-and-review.md§8a;docs/decision-log.md§34
Never-do list
The full list, including the items tied to numbered rules: docs/decision-log.md § Never-do list.
- ❌ Business logic / validation / authorization decided on the client alone
- ❌ Connecting to the database directly from a client
- ❌ Committing dead code that has been commented out
- ❌ Opening a PR without running the formatter (
dotnet format, Prettier/ESLint) - ❌ Deleting or renaming a field/endpoint (= delete + add)
- ❌
SELECT *, N+1 queries, a list endpoint without pagination - ❌ A swallowed exception (
catch {}), an error with no log - ❌ Writing PII / tokens / passwords to the log
- ❌ Loosening tests "so they pass", papering over a flaky test with
retry - ❌ Pushing to
main, or toprodoutside a promotion - ❌ Without user approval: production deploy, DB
DROP,git push --force, deleting data, sending a message or publishing to an external service - ❌ An untested backup ("we have backups" is not enough — a restore drill is performed)
- ❌ Invoking any agent outside the active mode's role set — including
migration-reviewerand other plugins' agents that shadow these role names (ours areadyusuf:<role>). ⚠️test-writeris not banned: it is one of B's three roles. The protection is the role set, never a name list → #27, #28
Working method (for Claude)
The full protocol is in standards/00-working-method.md (plan → approval →
execute, verification, context discipline, parallel sessions, work that requires
approval). In short: read a file before editing it · for work touching multiple
files, present a short plan first · never say "it works" without running build +
the relevant tests + lint/format, and if you did not run them say "I did not
run them" · when uncertain, finish the independent work first, then ask one
clear question · commit only your own diff and never use --force · get approval
for irreversible work (deploy, DROP, sending anything outward, deleting files).
STATUS REPORTING during a long gate/run (PERMANENT, all projects)
Report progress as a short markdown table in the reply. No Artifact dashboard,
no published board; the session's plan file (standards/22) is an extra record only.
The table carries: the item · its state · the measured figure, with the signal it was read from · what it is waiting on. Keep it to the rows that matter; a blocked row states the reason, not a percentage.
⚠️ Every figure is MEASURED, never invented — if it cannot be measured, the
row says "cannot be measured". A long run's output is never piped into something
that buffers (tail/head): write it to a log file and read the table from
that. A step that did not run is reported as "did not run", never as passing.
⚠️ Name background tasks by cost: FREE - <name> if no model runs, else the model
name (Sonnet 5.5 - <name>) — and a non-FREE task names its model wherever it is reported.
→ Detailed rules: standards/00-working-method.md §10, §10c.
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
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.

