engineering-standards
Skill1 starsChanged 6 months agoMITView on GitHub
Complete frontend engineering standards for code quality, React patterns, TypeScript, CSS architecture, accessibility, testing, performance, security, and code review. Apply to every code task, writing, reviewing, debugging, refactoring. These rules are non-negotiable and override convenience or speed.
8 other projects use a version of this.
Adopted by
Most recently taken up by
- gopalparashar421/agent-skillstheir own version, first seen Nov 8, 2026
- Kin9Zeus/senior-engineer-skillstheir own version, first seen Nov 1, 2026
- nirholas/three.wstheir own version, first seen Oct 13, 2026
- Slight76/engineering-standardstheir own version, first seen Oct 8, 2026
- BrentRector/claude-skillstheir own version, first seen Oct 3, 2026
- Mesteriis/Engineering-Bible-AItheir own version, first seen Jun 28, 2026
Other versions8 projects use a version of this.
Word for word · 0
None found.
Edited · 0
None found.
Wrote their own version · 8
- nirholas/three.ws★ 271same name
- BrentRector/claude-skills★ 6same name
- mykaarma/kaarma-skills★ 4same name
- Kin9Zeus/senior-engineer-skills★ 3same name
- gopalparashar421/agent-skills★ 2same name
- Ewanjohndennis/engineering-standard-skills★ 1same name
- Mesteriis/Engineering-Bible-AI★ 0same name
- Slight76/engineering-standards★ 0same name
How matches are found. Word for word: the exact same text. Edited: shares passages with this file (“99% same” means 99% of its five-word phrases also appear here; 10% or more counts). Their own version: similar meaning, or, weakest, the same name. We can’t tell which project had it first. Projects are counted among the 200 most-starred candidates, and mentions are links to the repository we found, up to 50 per site, so both counts are a floor.
In this repository8 other files it gives its agents.
The file
Show its rules and text
We split this skill into the rules it gives an agent
52 rules. 0 are common, 37 are distinctive, and 15 are very specific to this project.
0
Common
Most of the 8 edited versions we read keep these.
37
Distinctive
This author's own choices. Worth a look.
15
Very specific
Tied to their project's names, files or tools. Probably skip.
- Common
- Distinctive
- Very specific
- Distinctive: line 18
Every fetch, API call, or async operation MUST handle four states:
- Distinctive: line 25
If code only handles success, it is not production-ready.
- Very specific: line 49
Every project: strict: true, noUncheckedIndexedAccess: true, exactOptionalPropertyTypes: true.
- Very specific: line 75
All function parameters: Readonly<> when the function should not mutate them.
- Distinctive: line 76
All component props: defined as interfaces, not inline types.
- Very specific: line 77
All re-exports: export type { X } for type-only exports (isolatedModules compliance).
- Distinctive: line 108
No inline styles except truly dynamic values (computed positions, API-driven colors).
- Distinctive: line 109
No class components. Functional only.
- Very specific: line 118
Never call setState during render, derive with useMemo.
- Distinctive: line 119
Never nest hooks inside conditions or loops.
- Very specific: line 150
No derived state in store, compute with selectors or useMemo.
- Distinctive: line 158
No boolean parameters in functions, use options objects instead.
- Distinctive: line 175
No hardcoded hex values, pixel values, or font names in component CSS.
- Distinctive: line 183
No element-type selectors deeper than 2 levels.
- Distinctive: line 192
All UI output must comply with the production-ui-standard skill.
- Distinctive: line 197
No gradients on buttons. No glassmorphism.
- Distinctive: line 203
Every interactive element: keyboard-reachable and operable.
- Very specific: line 204
Every icon-only button: aria-label.
- Very specific: line 205
Every image: alt text (empty alt="" for decorative).
- Very specific: line 220
No empty catch blocks: at minimum log with context or re-throw.
- Very specific: line 225
Every switch statement: default case required.
- Distinctive: line 240
No O(n²) operations on arrays that could exceed 100 items.
- Distinctive: line 244
No layout thrashing: batch DOM reads before DOM writes.
- Distinctive: line 253
No API keys, tokens, or secrets in source code.
- Distinctive: line 254
No PII in console.log statements.
- Distinctive: line 255
All user inputs sanitized before rendering.
- Very specific: line 269
Test file: adjacent to source: Component.test.tsx.
- Very specific: line 270
Test names: describe behavior, not implementation: "shows error when API returns 400" not "calls setError".
- Distinctive: line 271
No test depends on another test's state.
- Distinctive: line 276
Every component: at least one test for render, one for interaction, one for error state.
- Distinctive: line 277
Every hook: test the contract (inputs → outputs), not the implementation.
- Distinctive: line 278
Every async operation: test both success and error paths.
- Distinctive: line 279
Every form: test validation, submission, and error display.
- Distinctive: line 296
Test user behavior, not implementation details.
- Very specific: line 329
Remove all console.log before committing.
- Distinctive: line 330
No commented-out code, git has history.
- Distinctive: line 383
Every async operation handles four states (loading, error, empty, success)
- Very specific: line 384
Every useEffect with async work has cleanup
- Distinctive: line 385
Every error path has user-facing feedback
- Distinctive: line 386
No magic numbers, no hardcoded strings, no hardcoded URLs
- Distinctive: line 392
Every interactive element keyboard-reachable
- Very specific: line 393
Every icon-only button has aria-label
- Distinctive: line 396
No color-only state indicators
- Distinctive: line 400
No secrets, tokens, or PII in source
- Distinctive: line 406
No hardcoded colors, spacing, or font values
- Distinctive: line 415
Test names describe behavior
- Distinctive: line 416
No tests depend on other tests' state
- Distinctive: line 421
No O(n²) on growing arrays
- Distinctive: line 422
No RegExp construction in render
- Distinctive: line 430
When reviewing code, score each finding 0-100.
- Distinctive: line 439
Ready to Merge: No Critical or High issues
- Very specific: line 479
Every switch over a discriminated union ends with a default branch that calls assertNever:
“Common” is measured: kept by at least 6 in 10 of the 8 edited versions of this file we could read. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.
Files
Frontend Engineering Standards
These standards apply to every line of code written, reviewed, or refactored. No exceptions for prototypes, demos, or "quick fixes." Code that violates these rules does not ship.
FOUR-STATE RULE: EVERY ASYNC OPERATION
AI generates code that works when everything goes right. Production code handles when things go wrong.
Every fetch, API call, or async operation MUST handle four states:
- Loading. Skeleton or spinner visible before data arrives
- Error. Meaningful error message, retry mechanism, or fallback
- Empty. Explicit empty state with action to resolve it
- Success. The data renders correctly
If code only handles success, it is not production-ready. Reject it on review.
// WRONG, happy path only
const { data } = await fetchUsers();
return <UserList users={data} />;
// RIGHT: all four states
function UserList() {
const { data, error, isLoading } = useUsers();
if (isLoading) return <Skeleton rows={5} />;
if (error) return <ErrorState message={error.message} onRetry={refetch} />;
if (!data?.length) return <EmptyState action={<CreateUserButton />} />;
return <Table rows={data} />;
}TYPESCRIPT
Strict Mode: Non-Negotiable
Every project: strict: true, noUncheckedIndexedAccess: true, exactOptionalPropertyTypes: true.
Forbidden Patterns
any, never. Useunknownand narrow with type guards.astype assertions, only with proof (instanceof check, discriminated union).@ts-ignore/@ts-expect-errorwithout a comment explaining why.- Non-null assertion (
!), use optional chaining or explicit guards. enum, useas constobjects instead. Enums have runtime cost and quirky behavior.
// WRONG
const value = data as UserResponse;
const name = user!.name;
enum Status { Active, Inactive }
// RIGHT
function isUserResponse(data: unknown): data is UserResponse {
return typeof data === 'object' && data !== null && 'id' in data;
}
const name = user?.name ?? 'Unknown';
const Status = { Active: 'active', Inactive: 'inactive' } as const;Required Patterns
- All function parameters:
Readonly<>when the function should not mutate them. - All component props: defined as interfaces, not inline types.
- All re-exports:
export type { X }for type-only exports (isolatedModules compliance). - Generic components: explicit constraint + default:
<T extends ElementType = 'button'>. - Discriminated unions for state machines, not boolean flags.
// WRONG, boolean flags
interface State {
isLoading: boolean;
isError: boolean;
data: User[] | null;
error: Error | null;
}
// RIGHT, discriminated union
type State =
| { status: 'idle' }
| { status: 'loading' }
| { status: 'error'; error: Error }
| { status: 'success'; data: User[] };REACT PATTERNS
Component Architecture
- One component per file. Component name matches filename.
- Compound components over prop-heavy monoliths (>8 props = split).
- Hooks extract reusable logic. Components own behavior, styles own presentation.
forwardRefcomponents MUST havedisplayName.- No inline styles except truly dynamic values (computed positions, API-driven colors).
- No class components. Functional only.
Hooks Rules
useEffectwith async work: ALWAYS include cleanup (AbortController or stale flag).useEffectdependency arrays: exhaustive or line-level eslint-disable with rationale.useMemo/useCallback: only when profiling shows measurable gain or reference stability matters.useState: prefer single state object for related state that updates together.useRef: for DOM refs, abort controllers, values that don't trigger re-renders.- Never call
setStateduring render, derive withuseMemo. - Never nest hooks inside conditions or loops.
// WRONG, no cleanup, race condition
useEffect(() => {
fetchData().then(setData);
}, [id]);
// RIGHT: abort controller, cleanup, error handling
useEffect(() => {
const controller = new AbortController();
async function load() {
try {
const result = await fetchData(id, { signal: controller.signal });
setData(result);
} catch (err) {
if (!controller.signal.aborted) {
setError(err instanceof Error ? err : new Error('Unknown error'));
}
}
}
load();
return () => controller.abort();
}, [id]);State Management
- Co-locate state where it's used. Don't hoist to global store unless 2+ unrelated components need it.
- No derived state in store, compute with selectors or
useMemo. - Context: use for dependency injection (theme, auth), not for frequently changing state.
- Async operations: dispatch started/success/failure actions. Never leave error paths unhandled.
Props
- Boolean props:
is/has/allow/enableprefix:isLoading,hasError. - Event handlers:
handleprefix for component handlers,onprefix for prop callbacks:handleClick,onClick. - No boolean parameters in functions, use options objects instead.
// WRONG
function createUser(name: string, isAdmin: boolean, sendEmail: boolean) {}
// RIGHT
function createUser(name: string, options: { isAdmin?: boolean; sendEmail?: boolean }) {}CSS ARCHITECTURE
Design System CSS
- Token-driven: every color, spacing, font size, radius, and shadow comes from CSS custom properties.
- No hardcoded hex values, pixel values, or font names in component CSS.
- Option B pattern: base selector declares structure with
--_intermediate variables, variant selectors swap values. - Data attribute selectors:
[data-variant="primary"], not class-based variants. - Plain CSS files with data attributes, no CSS-in-JS, no CSS Modules, no Tailwind in component library code.
CSS Rules
- No
!importantunless overriding third-party styles (with comment). - No element-type selectors deeper than 2 levels.
&:focus-visiblenot&:focusfor keyboard-only indicators.flex-shrink: 0on icons and fixed-width elements in flex containers.- No
:global()selectors targeting library internals. - Transitions: only on
color,background-color,border-color,opacity,transform,box-shadow. Never onpadding,margin,width,height,border-radius. - Duration: 100-150ms for hover/active, 200ms for modals. No bounce/spring/elastic easing.
Production UI Standard Compliance
All UI output must comply with the production-ui-standard skill. Key checks:
- Primary accent: blue (#2563EB light, #3B82F6 dark). Not indigo, not purple.
- Grays: Slate family (cool-toned). Not neutral gray.
- Shadows: use Slate-900 rgba, not pure black. Cards on white = border, no shadow.
- Border radius: 6px buttons/inputs, 8px cards, 12px modals. Never above 12px on rectangles.
- No gradients on buttons. No glassmorphism. No colored card backgrounds.
ACCESSIBILITY: NON-NEGOTIABLE
- Every interactive element: keyboard-reachable and operable.
- Every icon-only button:
aria-label. - Every image:
alttext (emptyalt=""for decorative). tabIndex> 0: NEVER.- Color as sole indicator: NEVER. Always pair with text, icon, or pattern.
role="button"on non-button elements: MUST also havetabIndex={0}andonKeyDown.- Focus indicators: 2px solid outline, 2px offset, visible on EVERY interactive element.
- Contrast: 4.5:1 normal text, 3:1 large text minimum. Target 7:1 where possible.
- Touch targets: 44x44px minimum on mobile.
- Reduced motion:
@media (prefers-reduced-motion: reduce)disables all animations. - Screen reader: all form inputs have associated labels, all regions have landmarks.
- Focus traps: only in modals/dialogs. Must be escapable with Escape key.
ERROR HANDLING
- No empty
catchblocks: at minimum log with context or re-throw. - API errors: distinguish 4xx (user error) from 5xx (server error) in UI messaging.
- Form validation: show inline errors, not just toasts.
- Network errors: provide retry mechanism or clear feedback.
Promise.all: handle errors, one rejection must not crash the entire batch. UsePromise.allSettledwhen partial success is acceptable.- Every
switchstatement:defaultcase required. - Null/undefined from API: never assume shape matches TypeScript interface at runtime. Validate.
// WRONG: assumes API shape
const userName = response.data.user.name;
// RIGHT, defensive
const userName = response.data?.user?.name ?? 'Unknown';PERFORMANCE
- No O(n²) operations on arrays that could exceed 100 items.
- No
new RegExp()inside render, extract to module scope oruseMemo. keyprops: stable identifiers, never array indices (unless static, never reordered).- Lazy load routes and heavy components:
React.lazy+Suspense. - No layout thrashing: batch DOM reads before DOM writes.
- Images: use
loading="lazy"for below-fold images, specifywidth/heightto prevent CLS. - Bundle: code-split at route level minimum. Monitor with build:size script.
- Memoization: profile first. Don't
useMemoeverything, measure before optimizing.
SECURITY
- No API keys, tokens, or secrets in source code.
- No PII in console.log statements.
- All user inputs sanitized before rendering.
dangerouslySetInnerHTML: ONLY with DOMPurify sanitization. Prefer avoiding entirely.eval(),new Function(),innerHTMLwith user content: FORBIDDEN.- File uploads: validate extensions AND file size. Use allowlist, not blocklist.
- CSS custom properties from user input: block
url(),@import,expression(). - Third-party scripts: load with
integrityattribute (SRI) when available. - CORS: never use
Access-Control-Allow-Origin: *in production.
TESTING
Structure
- Test file: adjacent to source:
Component.test.tsx. - Test names: describe behavior, not implementation:
"shows error when API returns 400"not"calls setError". - No test depends on another test's state.
- Mock at boundaries (API calls, browser APIs), not internal functions.
Coverage
- Every component: at least one test for render, one for interaction, one for error state.
- Every hook: test the contract (inputs → outputs), not the implementation.
- Every async operation: test both success and error paths.
- Every form: test validation, submission, and error display.
- Edge cases: empty data, null values, extremely long strings, special characters.
Patterns
// Test the four states
describe('UserList', () => {
it('shows skeleton while loading', () => { /* ... */ });
it('shows error message when fetch fails', () => { /* ... */ });
it('shows empty state when no users exist', () => { /* ... */ });
it('renders user rows on success', () => { /* ... */ });
});- Accessibility tests: use
jest-axeorvitest-axefor automated a11y checks. - No
data-testidas the primary query strategy, prefergetByRole,getByLabelText,getByText. - Test user behavior, not implementation details. Click buttons, type in inputs, verify visible output.
NAMING CONVENTIONS
Files
- Components:
PascalCase:FormUpload.tsx - Hooks:
camelCasewithuseprefix:useClickOutside.ts - Utils:
camelCase:formatDate.utils.ts - Tests:
*.test.tsx/*.test.ts - Styles:
*.css(design system),*.module.scss(app-level) - Constants:
SCREAMING_SNAKE_CASEin files,camelCasefilenames
Code
- Components:
PascalCase - Hooks:
useCamelCase - Functions/variables:
camelCase - Constants:
SCREAMING_SNAKE_CASE - Types/Interfaces:
PascalCase:interface ButtonProps - Generic type params: single uppercase letter or descriptive:
T,TElement - Boolean:
is/has/should/canprefix - Event handlers:
handleprefix (component),onprefix (prop)
GIT CONVENTIONS
- Commit format:
type(scope): description - Types:
feat,fix,refactor,style,perf,docs,test,chore,build,ci,revert - One logical change per commit.
- Remove all
console.logbefore committing. - No commented-out code, git has history.
- PR: one concern per PR. Don't mix features with refactors.
FILE SIZE LIMITS
- Components: <300 lines. Split if larger.
- Functions: <40 lines. Extract helpers if larger.
- Max nesting: 3 levels. Invert conditions or extract.
- Utils files: split when exceeding 500 lines.
- CSS files: one file per component. No monolithic stylesheets.
FORBIDDEN PATTERNS: REJECT ON SIGHT
| Pattern | Why | Fix |
any | Defeats type safety entirely | unknown + type guard |
as without proof | Lies to the compiler | Runtime check first |
| Empty catch block | Swallows errors silently | Log with context or re-throw |
console.log in committed code | Debug artifact in production | Remove before commit |
!important without comment | Specificity war | Fix selector specificity |
eslint-disable at file level | Blanket suppression | Line-level with reason |
// TODO without ticket | Never gets done | // TODO(TICKET-123): desc |
| Magic numbers | Unreadable, unmaintainable | Named constants |
| Hardcoded API URLs | Environment coupling | Config constants |
index as React key | Causes bugs on reorder | Stable unique identifier |
| Derived state in store | Stale data, extra updates | Selector or useMemo |
setState during render | Infinite loop risk | useMemo for derivations |
useEffect without cleanup | Memory leak, race condition | AbortController or stale flag |
tabIndex > 0 | Breaks natural tab order | Restructure DOM order |
| Color as sole indicator | Accessibility failure | Add text/icon/pattern |
dangerouslySetInnerHTML no sanitize | XSS vulnerability | DOMPurify or avoid |
| Fetch with only success handling | Crashes on error/empty | Four-state pattern |
| Boolean function parameters | Unreadable call sites | Options object |
| Nested ternaries | Unreadable | if/else or early return |
| Prop drilling >3 levels | Maintenance burden | Context or composition |
REVIEW CHECKLIST: RUN ON EVERY REVIEW
Pre-flight (before reading code)
- Does the PR have a clear title in commit format?
- Is it one logical change or a mixed bag?
- Are there any
console.logstatements?
Code Quality
- TypeScript strict, no
any, no unsafeas, no! - Every async operation handles four states (loading, error, empty, success)
- Every
useEffectwith async work has cleanup - Every error path has user-facing feedback
- No magic numbers, no hardcoded strings, no hardcoded URLs
- Functions under 40 lines, components under 300 lines
- Nesting under 3 levels
Accessibility
- Every interactive element keyboard-reachable
- Every icon-only button has
aria-label - Focus indicators visible on all interactive elements
- Color contrast meets 4.5:1 minimum
- No color-only state indicators
Security
- No secrets, tokens, or PII in source
- User input sanitized before rendering
- No
eval,innerHTML, or unsanitizeddangerouslySetInnerHTML
CSS
- No hardcoded colors, spacing, or font values
- Token-driven: all values from CSS custom properties
- No
!importantwithout justification - Focus-visible, not focus
- Compliant with production UI standard
Testing
- Tests exist for success, error, and edge cases
- Test names describe behavior
- No tests depend on other tests' state
- Queries use
getByRole/getByLabelText, notdata-testid
Performance
- No O(n²) on growing arrays
- No RegExp construction in render
- Stable keys on list items
- Lazy loading for routes and heavy components
CONFIDENCE THRESHOLD
When reviewing code, score each finding 0-100. Only surface findings at 85+ confidence. This prevents noise and focuses review on real issues.
Severity levels:
- Critical. Security vulnerability, data loss, crash. Must fix before merge.
- High. Logic bug, accessibility failure, missing error handling. Should fix.
- Medium. Performance issue, architectural concern, maintainability. Consider fixing.
- Low. Naming, style preference, minor improvement. Optional.
Verdict:
- Ready to Merge. No Critical or High issues
- Needs Attention. Medium issues found
- Needs Work. Critical or High issues found
THE DURABILITY LADDER FOR TYPE-LEVEL CONSTRAINTS
The rules above tell you what TypeScript patterns to use. This section tells you the meta-principle those patterns serve: every constraint that protects correctness should be encoded at the highest tier the type system supports, and only fall to a lower tier when the higher tier genuinely cannot carry it.
The ladder, ranked by ability to survive consumer turnover, codebase growth, and AI-agent-assisted refactoring:
- Type-level constraint. The compiler refuses to mix incompatible categories of data. Discriminated unions for state. Branded types for validated values. Exhaustiveness checks via
assertNeveron every switch over a union. Enforced at build time; no consumer can bypass without writing a cast that is visible in code review. - Runtime invariant. A contract check at a module boundary that fires when the assumption is violated, with a stack trace pointing at the violation site. Used when the constraint is mechanically checkable but only at runtime.
- Test as executing context. A regression test named for the constraint it protects, which fails in CI if someone changes the code without understanding the assumption. Documentation that runs.
- Name with semantic load.
MAX_BSA_REPORTABLE_TRANSFER_USDsurvives the deletion of any comment because the name itself carries the meaning.MAX_AMOUNTdoes not. Anonymous magic numbers are findings, not acceptable defaults. - Comment with link to source. The fallback when nothing higher works. Used for regulatory citations, links to incident post-mortems, vendor SLA references. Treated as a known-leaky mechanism; minimized.
A type-level constraint can be silently weakened only by a code change that produces a compile error. A runtime invariant can be silently weakened only by a code change that produces a test failure. A comment can be silently deleted by a "cleanup" PR. The ladder makes this asymmetry explicit and chooses accordingly.
BRANDED TYPES CARRY CONSTRAINTS PAST THE NARROWING
A discriminated union prevents consumers from accessing the narrowed data without checking the discriminant. It does not prevent consumers from extracting the narrowed data and passing the raw underlying type to downstream code. A branded type closes that gap.
type Brand<T, B> = T & { readonly __brand: B };
type ValidatedFile = Brand<File, 'ValidatedFile'>;
function uploadToS3(file: ValidatedFile): Promise<UploadResult> { ... }
// A raw File cannot be passed to uploadToS3.
// The type system enforces the validation boundary across consumer turnover.The standard objection: someFile as ValidatedFile bypasses the boundary. That is the point. The cast is visible in code review; a reviewer can grep for as ValidatedFile and ask why this code thinks it has a validated file. The cast is not impossible; it is visible.
Use branded types for: input that has crossed a security or validation boundary, IDs of different domains that must not be confused (UserId vs OrderId), units that must not be mixed (Milliseconds vs Seconds), and any value where the type system can carry a constraint the consumer would otherwise have to remember. The dev.to article on file validation as a security boundary walks through the discipline applied to a specific worked example.
EXHAUSTIVENESS CHECKS ARE MANDATORY ON UNIONS
Every switch over a discriminated union ends with a default branch that calls assertNever:
function assertNever(value: never): never {
throw new Error(`Unhandled variant: ${JSON.stringify(value)}`);
}
switch (result.status) {
case 'valid': return handleValid(result);
case 'rejected': return handleRejected(result);
// ... other cases
default: return assertNever(result);
}When a new variant is added, every consumer that omits it produces a compile error at the exact line where the new case must be handled. The compiler becomes the audit trail. Without exhaustiveness checking, new variants ship silently; consumers continue compiling and start returning undefined from the missed case. The cost of assertNever is two lines per switch. The cost of not adding it is incident response.
DECISION CONTEXT IN CODE-SPECIFIC FORMS
Decision context (the why behind a non-obvious choice) is encoded at the highest durability tier from the ladder above. Specific rules:
- A magic number without a name or test attached is a finding. Either it gets a semantic-loaded name, a regression test that protects it, or both.
- A retry, timeout, or threshold value tuned to an external constraint must reference the constraint in its name or in a one-line pointer to an ADR.
PAYMENT_TIMEOUT_AT_1_5X_PROVIDER_SLA_MScarries the math;PAYMENT_TIMEOUT_MSdoes not. - A regex or parsing pattern derived from a spec carries a one-line comment with the spec reference:
// per RFC 5322 section 3.4.1. Comments are the right mechanism for content that is irreducibly textual and external. - A branded type or discriminated union variant is itself decision context. The type's name and structure encode the reasoning for treating this data as a distinct category.
The rule: if a value or pattern in the code carries reasoning that the next reader cannot reconstruct from the local code alone, the reasoning is preserved at the highest available durability tier, or the code does not ship.
These standards extend the rules above with the discipline of where each rule sits on the durability ladder. The patterns from the prior sections (no any, strict flags, discriminated unions for state) are the implementation. The discipline in this section is the meta-principle those patterns serve.
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.

