design-philosophy
Skill486 starsChanged 15 days agoApache-2.0View on GitHub
Core design principles for the codebase - cognitive load, progressive disclosure, type safety, abstraction worth. Use when designing APIs, modules, or data structures.
We split this skill into the rules it gives an agent
23 rules. About 0 are common, 8 are distinctive, and 15 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.
15
Very specific
Tied to their project's names, files or tools. Probably skip.
- Common
- Distinctive
- Very specific
- Distinctive: line 13
When refactoring existing code
- Distinctive: line 14
When reviewing code for maintainability
- Very specific: line 27
Clean Imports: Use use statements at the top of files rather than inline absolute paths (e.g.
- Distinctive: line 29
Single Source of Truth for Constants: Never duplicate raw literals across byte, string, and length constants.
- Distinctive: line 33
Technical Precision: Use standard, precise terminology (e.g., Parameter vs.
- Very specific: line 48
Co-locate with Return Type: When a function's primary job is constructing, parsing, or classifying a domain type T (e.g.
- Very specific: line 49
Co-locate with Subject Type: When a function interprets, translates, or queries T (e.g.
- Distinctive: line 54
Use the type system to prevent bugs at compile time.
- Very specific: line 58
Prefer newtypes over primitives (e.g., Index instead of usize)
- Very specific: line 66
Use
Option<()>ONLY when callers chain with?: When a mutator can fail (e.g. - Very specific: line 68
Constructor Conventions (
Defaultover No-Argnew()): If a type requires no arguments for construction, derive or implement Default … - Distinctive: line 79
If understanding the abstraction requires more effort than the concrete code, don't abstract
- Distinctive: line 86
Treat errors as a user interface (UI) for developers.
- Very specific: line 90
Standardize on
miette: All custom error types (enums/structs) must derive miette::Diagnostic in addition to thiserror::Error. - Very specific: line 91
Actionable Metadata: Use #[diagnostic(help(...))] to provide hints on how to resolve the error.
- Very specific: line 92
Searchable Codes: Use #[diagnostic(code(...))] to provide unique identifiers for errors, facilitating documentation and search.
- Very specific: line 93
Preserve Context: Avoid "lossy" error conversions (like turning a rich miette::Report into a plain string).
- Very specific: line 97
Use Enums with Const Generics (Algebraic Data Type Const Params) to control behavior without runtime overhead or boilerplate.
- Very specific: line 103
Zero-Cost Behavior: Prefer const POLICY: MyEnum over runtime fields.
- Very specific: line 105
Reduce Boilerplate: Prefer const Enums over the Trait-based Strategy pattern.
- Distinctive: line 106
Type-Level Identity: Use this pattern when you want different behaviors to result in different types, enabling compile-time enforcement of …
- Very specific: line 114
No
pubfor tests: Never make a field or method pub or pub(crate) if its only external caller is a test. - Very specific: line 115
Test-Only Accessors: Keep production fields strictly scoped (private or pub(in crate::...)).
≈ “Common” is an estimate: at least 1 in 5 of the 308,232 skill 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
Design Philosophy Skill
Apply these principles when writing or reviewing code.
When to Use
- Proactively when designing new APIs, modules, or data structures
- When refactoring existing code
- When reviewing code for maintainability
Core Principles
1. Minimize Cognitive Load
Code should be easy to understand without loading too much into working memory.
Guidelines:
- Good Separation of Concerns (SoC) means fewer "things" to keep in mind
- Each module/function should have a single, clear responsibility
- Limit the number of concepts a reader must hold simultaneously
- Clean Imports: Use
usestatements at the top of files rather than inline absolute paths (e.g.crate::Type) to reduce visual noise and cognitive clutter in function bodies. - No Magic Numbers/Strings: Extract domain-specific numbers and strings (like ANSI mode integers or escape sequences) into named constants (e.g., in
tui/src/core/ansi/constants/). Do not use magic numbers directly in business logic or pattern matches, as this requires readers to memorize their meaning. - Single Source of Truth for Constants: Never duplicate raw literals across byte, string, and length constants. Follow the Constant Derivation Hierarchy:
- Atomic Primitives (Single byte/char):
u8is the SSOT (u8tocharviaascii_byte_to_charto&strviaascii_byte_to_str). - Composed Sequences (Multi-byte strings):
&stris the SSOT (&strvia compile-time concatenation/macro to&[u8]via.as_bytes()tousizevia.len()). See Constant Design Patterns inpatterns.md.
- Atomic Primitives (Single byte/char):
- Technical Precision: Use standard, precise terminology (e.g., Parameter vs. Argument) to ensure the reader's mental model matches the implementation exactly. See the Terminology Precision guide.
2. Progressive Disclosure
Reveal complexity only when needed.
Guidelines:
- Public APIs should be minimal and intuitive
- Advanced features should be discoverable but not in-your-face
- Documentation follows inverted pyramid: high-level first, details later
- Module structure should guide users from simple to advanced
- Type-Centric Co-location (Associated Functions over Floating Functions): Prefer associated functions and methods on domain types over free-floating helper functions.
- Co-locate with Return Type: When a function's primary job is constructing, parsing, or classifying a domain type
T(e.g.classify_csi_buffer -> CsiBufferKind), make it an associated function onT(CsiBufferKind::classify). - Co-locate with Subject Type: When a function interprets, translates, or queries
T(e.g.parse_ss3_command(byte) -> Option<VT100KeyCodeIR>), make it an associated method or function onT(Ss3BufferKind::decode(self)/Ss3BufferKind::parse_command(byte)). - Keep Floating When Appropriate: Reserve floating functions for high-level pipeline entry points / coordinators (e.g.
parse_keyboard_sequencereturning generic IR), multi-type algorithms, or functions returning external/standard library types (u32,String).
- Co-locate with Return Type: When a function's primary job is constructing, parsing, or classifying a domain type
3. Make Illegal States Unrepresentable
Use the type system to prevent bugs at compile time.
Guidelines:
- Prefer newtypes over primitives (e.g.,
Indexinstead ofusize) - Eliminate Boolean Soup / Boolean Blindness: Never use raw
boolflags, struct fields, function parameters, or return values in domain code (e.g.fn process(flag: bool)orfn is_default() -> bool). Replace boolean soup with self-documenting domain enums (e.g.SyntaxHighlightPipeline::R3BLMarkdowninstead ofis_file_extension_default() -> bool,TrailingNewline::Present/Absent, orHasSelection::Yes/No). Domain enums make call sites self-documenting and leverage Rust'smatchor==for explicit checking.- No
.is_*() -> boolHelpers on Domain Enums: Do NOT addpub fn is_modified(self) -> boolor similar boolean conversion helpers onto domain enums. Callers must match on the enum or compare directly against the variant (e.g.status == FormatStatus::Modified). - When
boolIs Acceptable (std& Third-Party Compatibility Only): Rawboolis permitted solely when required for compatibility withstd,clippy, or third-party crate contracts:stdcollection conventions:pub fn is_empty(&self) -> boolwhen paired withpub fn len(&self)(enforced byclippy::len_without_is_empty).stdtrait signatures and higher-order closures: implementingPartialEq::eqor passing predicate closures tostditerator/collection methods (.filter(...),.any(...),.all(...),.retain(...)).- Third-party derive macro contracts: struct fields required by derive macros such as
#[derive(clap::Parser)]CLI switch flags (#[arg(long)] pub verbose: bool).
- No
- Avoid Boolean Blindness in Mutator Returns (
Option<T>/Option<()>vs Domain Enums): Mutator methods taking&mut selfthat delete or replace text cannot return borrowed slices (Option<&str>) or metadata offsets (DocSeg) because the borrow checker forbids returning a&strborrowing fromselfacross a&mut selfmutation, and deleted bytes no longer exist in memory. Returning a text payload from a&mut selfmutator unavoidably requires an owned heap allocation (Option<String>). Return a payloadOption<T>(e.g.Option<LineMetadata>for zero-allocation metrics orOption<String>for text) ONLY when callers genuinely consume it. If no text payload is consumed by callers:- Use
Option<()>ONLY when callers chain with?: When a mutator can fail (e.g. out-of-bounds index) and callers short-circuit onNoneusing?, returnOption<()>(Some(())for success,Nonefor failure). - Use a Domain Enum when callers do NOT chain with
?: UsingOption<()>when callers do not short-circuit with?is an anti-pattern because it forces.is_some()checks (boolean blindness in disguise) and misrepresents a valid no-op state as failure (None). For sequential passes or status-reporting mutators, return an explicit domain enum (e.g.FormatStatus::Modified/FormatStatus::Unchanged).
- Use
- Constructor Conventions (
Defaultover No-Argnew()): If a type requires no arguments for construction, derive or implementDefault(#[derive(Default)]) and do NOT create a redundantpub fn new() -> Selfmethod. Use parameterized constructors (with_capacity(...)ornew(arg: Type)) only when arguments are required. - Design enums and structs so invalid combinations cannot be constructed
- Move validation from runtime to compile time where possible
- See
check-bounds-safetyskill for exemplary patterns
4. Abstractions Must Earn Their Keep
An abstraction should reduce cognitive load, not add to it.
Guidelines:
- If understanding the abstraction requires more effort than the concrete code, don't abstract
- Good abstractions match mental models developers already have
- Three similar lines of code is often better than a premature abstraction
- Abstractions should hide complexity, not just move it
5. High-Fidelity Error Handling
Treat errors as a user interface (UI) for developers. Public-facing errors must provide actionable information.
Guidelines:
- Standardize on
miette: All custom error types (enums/structs) must derivemiette::Diagnosticin addition tothiserror::Error. - Actionable Metadata: Use
#[diagnostic(help(...))]to provide hints on how to resolve the error. - Searchable Codes: Use
#[diagnostic(code(...))]to provide unique identifiers for errors, facilitating documentation and search. - Preserve Context: Avoid "lossy" error conversions (like turning a rich
miette::Reportinto a plain string). Use transparent delegation or dedicated variants to preserve the full error chain.
6. Modern Rust Patterns: ADT Const Params
Use Enums with Const Generics (Algebraic Data Type Const Params) to control behavior without runtime overhead or boilerplate. This pattern is enabled by the adt_const_params feature flag.
When to Apply:
- Proactively apply this pattern when writing new code or refactoring existing code that requires choosing between a closed set of behaviors or strategies at compile-time.
Guidelines:
- Zero-Cost Behavior: Prefer
const POLICY: MyEnumover runtime fields. This allows the compiler to prune dead code and branches at compile-time (monomorphization). Example:ScopedMutex. - Reduce Boilerplate: Prefer
constEnums over the Trait-based Strategy pattern. This centralizes logic and eliminates the need for multiple marker structs and trait implementations. - Type-Level Identity: Use this pattern when you want different behaviors to result in different types, enabling compile-time enforcement of safety rules.
7. Strict Encapsulation & Testing Hygiene
Maintain strict encapsulation boundaries in production code and do not leak internal state merely for the convenience of tests.
Guidelines:
- No
pubfor tests: Never make a field or methodpuborpub(crate)if its only external caller is a test. - Test-Only Accessors: Keep production fields strictly scoped (private or
pub(in crate::...)). If tests need to inspect or manipulate internal state, provide explicit accessor methods annotated with#[cfg(test)](e.g.,pub(crate) fn internal_state_for_testing(&self)). This cleanly compiles the escape hatch out of the production binary.
Supporting Files
patterns.md- Detailed patterns with good/bad examples
Related Skills
check-bounds-safety- Type-safe Index/Length patterns (exemplar of principle #3)organize-modules- Module organization for encapsulation (supports principle #1)write_documentation- Inverted pyramid documentation (supports principle #2)concurrency-safety- Thread safety, Chain of Custody, and Loud Lock Releases
Other versions3 projects use a version of this.
Word for word · 0
None found.
Edited · 0
None found.
Wrote their own version · 3
- microsoft/vscode★ 194ksame name
- posit-dev/positron★ 4.3ksame name
- connerkward/ckw-design-skill★ 9same 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 repository30 other files it gives its agents.
- .agents/AGENTS.mdAGENTS.md
- AGENTS.mdAGENTS.md
- build-infra/AGENTS.mdAGENTS.md
- rust-analyzer-mcp-server/AGENTS.mdAGENTS.md
- task/AGENTS.mdAGENTS.md
- llms.txtllms.txt
- analyze-log-filesSkill
- analyze-performanceSkill
- audit-taskSkill
- batch-refactor-with-sub-agentsSkill
- check-bounds-safetySkill
- check-code-qualitySkill
- check-test-coverageSkill
- code-reviewSkill
- concurrency-safetySkill
- create-commit-messageSkill
- create-prSkill
- fast-string-allocationsSkill
- fix-issueSkill
- merge-prSkill
- organize-modulesSkill
- organize-testsSkill
- release-crateSkill
- remove-crate-prefixSkill
- review-prSkill
- run-clippySkill
- safe-renamingSkill
- test-cross-platformSkill
- write-documentationSkill
- write-structured-tracingSkill
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.

