Engineering minimalism
Skill ats4321/claude-engineering-skills/skills/engineering-minimalism
The doctrine skill — decide whether code should exist at all before deciding how to write it. Auto-load when adding features, dependencies, abstractions, config, tests, or security measures; when reviewing a design or PR for over-engineering; when tempted by a framework, wrapper, or "for later" scaffolding; or when the user asks to simplify, trim, or justify complexity. Provides the decision ladder (real need → codebase → stdlib → platform → existing dep → one line → minimal new code), deletion-over-addition, proportionality sizing, guardrail-vs-boundary honesty, and the small-sharp-tool architecture — plus the explicit list of places minimalism must NOT be applied.From its SKILL.md
npx -y skills add ats4321/claude-engineering-skills --skill engineering-minimalismAssembled from the repository path, not quoted from the project. Check it against their README if it does not work.
One thing to look at
- 0 stars0 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.
SKILL.md
15.4 KB, ~3.6k tokens by cl100k_base, as published. Nobody here has run it
Engineering Minimalism
Purpose
Most engineering failures are additions: the dependency that broke transitively, the abstraction nobody needed, the config for a value that never changes. This skill is the decision procedure for whether code should exist at all, and for sizing everything — security, tests, abstraction — to the actual, written-down need. Doctrine (owner-confirmed 2026-07-04): local-first, minimal dependencies, security proportional to a written threat model, no over-engineering.
When to Use / When NOT to Use
Use when:
- About to write new code, add a dependency, introduce an abstraction, or create a file.
- Reviewing a design/PR that smells of speculation ("we might need", "for flexibility", "future-proof").
- Asked to simplify, trim, or justify existing complexity.
- Sizing a test suite, a security posture, or a config surface for a project.
- An LLM feature is proposed — run the ladder before
llm-integration-reliability; the cheapest reliable call is none.
Do NOT use when:
- Auditing security of an existing trust boundary → load
security-review-playbook(this skill sizes the posture; that one verifies it). - Deciding how to test what you've decided to build → load
validation-and-testing. - Choosing/pinning a dependency you've already justified adding → load
dependency-management. - Making changes safely to existing systems → load
change-control. - Investigating whether a claimed need is real → load
research-methodologyto establish the fact, then return here to size the response.
Core Methodology
1. Run the decision ladder
For every proposed piece of code, stop at the FIRST rung that holds:
Proposed code
├── 1. Is the need real, today?
│ Speculative ("might need") → DO NOT BUILD. Record one line why.
├── 2. Already in this codebase?
│ Helper/util/pattern exists → REUSE it. Grep before you write.
├── 3. Stdlib does it? → USE stdlib.
├── 4. Platform primitive covers it?
│ (DB constraint over app code, CSS over JS, OS feature over daemon)
│ → USE the primitive.
├── 5. An ALREADY-INSTALLED dependency solves it? → USE it.
│ (Never add a NEW dependency for what a few lines can do.)
├── 6. Can it be one line? → ONE line.
└── 7. Only then: write the MINIMUM new code that works.
The ladder runs after you understand the problem — read the code the change touches first. The smallest change in the wrong place is a second bug, not minimalism.
2. Prefer deletion over addition
Before adding, ask what this change lets you remove. A fix that deletes the buggy path beats a fix that guards it. Strip what the deployment shape forbids; remove the flag nobody sets; fold the two similar functions into one. Diff sign matters: negative-line PRs deserve celebration, not suspicion. Ship deletions and cleanups in their own commit — change-control governs the diff you are shipping now; never bundle cleanup into an unrelated fix.
3. Choose boring over clever
Clever is what someone decodes at 3am. Given two working solutions of similar size, take the one a zero-context junior reads correctly on the first pass. Boring is a feature: it is greppable, teachable, and diffable. (Boring ≠ flimsy: between two equally simple options, take the one correct on edge cases.)
4. Size everything by proportionality
Nothing is "as much as possible"; everything is "as much as the written need demands":
- Security → proportional to a written threat model. Write 3–10 lines: who attacks, through what surface, what's at stake. Harden that surface; skip theater elsewhere. No threat model = no basis for any hardening decision.
- Tests → concentrated on the highest-risk surface first (money, security, data loss, parsers), not spread evenly for a coverage number. An acknowledged gap ("no tests yet") beats a decorative suite.
- Abstraction → introduced at the second or third concrete duplication, never the first anticipation. No interface with one implementation; no factory for one product; no config for a value that never changes.
- Dependencies → each one is an attack surface, an upgrade treadmill, and a transitive-breakage lottery ticket. When you must depend, pin ranges you have actually tested.
5. Be honest about guardrails vs boundaries
- A boundary is enforced and cannot be bypassed by a determined party (process isolation, auth check, DB constraint).
- A guardrail catches accidents and CAN be bypassed (a string blocklist, a lint rule, a confirmation prompt).
- Both are legitimate. Lying about which is which is not. Document guardrails AS guardrails, with the bypass named — a guardrail sold as a boundary creates false safety, which is worse than none. (These definitions live here; the review procedure for classifying and documenting each protective measure is owned by
security-review-playbookStep 4.)
6. Architect as small sharp tools
Prefer a few small modules, each doing one thing, over one framework doing everything. Symptoms of health: each module explainable in a sentence; total core small enough to read in a sitting; modules joined by narrow, explicit contracts. Symptoms of disease: a "core" module everything imports, layers that only forward calls, plugin systems with one plugin.
7. Know when NOT to be minimal
Never simplify away:
- Trust-boundary input validation — every external input is hostile until validated.
- Error handling that prevents data loss — the write path is not the place for optimism.
- Real security measures backed by the threat model (never delete these to "reduce lines").
- Accessibility basics.
- Anything the user explicitly requested — build it in full; ship, don't re-argue.
- The calibration knob for physical hardware — real clocks drift, real sensors read off; leave the tuning parameter a minimal model can't foresee.
Minimalism review checklist
- Every new file/function justified by a ladder rung, stated
- No new dependency without: need is real + no stdlib/platform/existing-dep alternative + pinned
- No abstraction without ≥2 concrete existing users
- No config knob for a value with one realistic setting
- Something considered for deletion in this change
- Security items trace to a written threat model line
- Tests concentrated on the highest-risk surface; gaps acknowledged in writing
- Every guardrail labeled as a guardrail, bypass named
- Nothing from the step-7 never-minimize list was trimmed
Discovery Commands
Audit any repo for accidental complexity:
# Size reality check: how big is this actually?
find . -name "*.py" -not -path "*/.git/*" -not -path "*/node_modules/*" | xargs wc -l | tail -1
find . -name "*.js" -o -name "*.ts" | grep -v node_modules | xargs wc -l | tail -1
# Dependency surface (each line is a liability)
grep -A 30 '"dependencies"' package.json 2>/dev/null
grep -A 30 "dependencies" pyproject.toml 2>/dev/null
# Speculative scaffolding markers
grep -rn -E "TODO|FIXME|XXX|for later|future" --include="*.py" --include="*.js" --include="*.ts" . | grep -v node_modules
# One-implementation interfaces / single-use factories (candidates for deletion)
grep -rn -E "class \w+(Interface|Base|Abstract|Factory)" --include="*.py" --include="*.ts" .
# Config knobs — how many are ever set to a non-default?
find . -name "*.env.example" -o -name "config*.json" -o -name "settings*.py" | grep -v node_modules
# Dead exports / unused helpers (grep each suspicious symbol's callers)
grep -rn "def suspicious_helper\|export function suspiciousHelper" . && grep -rn "suspicious_helper(" . | grep -v "def "
# Where did complexity arrive? (large additions in history — commit and its size shown together)
git log --format="%h %s" --shortstat | head -60
# Is there a written threat model to size security against?
grep -rin "threat model\|security boundary" --include="*.md" . | grep -v node_modules
Failure Modes & Anti-patterns
| Symptom | Mistake | Correction |
|---|---|---|
| Framework built for a feature nobody asked for | Skipped ladder rung 1 (need not real) | Write the need in one line first; no need → no code |
| Same util re-implemented three files over | Skipped rung 2 (didn't grep) | Grep before writing; reuse is the shortest diff |
New dep for something json/pathlib/fetch does | Skipped rungs 3–5 | Stdlib/platform/existing dep first, always |
| Transitive breakage from an unpinned dep | Dep added without pin or test | Pin ranges you tested; see dependency-management |
| Interface with exactly one implementation | Abstraction before duplication | Inline it; abstract at the 2nd–3rd concrete use |
| Config file where every value has one setting | Flexibility theater | Constants in code; config only for values that truly vary |
| Security checklist applied uniformly everywhere | Hardening without a threat model | Write the threat model; harden what it names, skip the rest |
| Blocklist described as making the tool "safe" | Guardrail sold as boundary | Label it a guardrail; name the bypass in the docs |
| 90% coverage, zero tests on the parser/auth path | Coverage-number testing | Risk-first: test the surface whose failure costs most |
| "Cleanup" PR that removed input validation | Minimalism applied at a trust boundary | Step-7 list is exempt — restore it |
| Growing pile of TODO/for-later scaffolding | Building for imagined futures | Delete scaffolding; later can scaffold for itself |
| CI/CD pipeline for a single-user local tool | Process disproportionate to the project | Match process weight to project weight |
Repository Examples
Case study: ragit — small sharp tools + honest gaps (as of 2026-07-04)
~/ragit — local RAG CLI: 4 modules (~665 lines total), each doing one thing (cli / indexer / llm / retriever) — step 6 embodied. Dependencies pinned after a real transitive break: chromadb>=0.4.0,<0.5.0 + numpy<2.0, commits a1ad63ed and 0a06ae9b "Pin numpy for chromadb 0.4" — proportional dependency discipline, applied after evidence, not speculatively. Custom exceptions carry actionable messages ("Run ragit index {path} first") — small effort, high leverage. No tests, acknowledged as a gap rather than papered over with a decorative suite. Install: python3 -m pip install -e ..
Case study: agentix — guardrail honesty + written threat model (as of 2026-07-04)
~/agentix — ~700-line agent framework. README states the threat model in one line: "the security boundary is you and the model you point it at, not the code." The shell blocklist ["rm -rf /", "sudo", "mkfs"] is documented as a guardrail NOT a boundary — explicitly bypassable (e.g. "rm -rf /" with two spaces) — step 5 verbatim. Real hardening sits where the threat model points: np.load(allow_pickle=False), tool timeouts (shell 30s, python 15s, web 15s). Tests use pytest monkeypatch only — no mock framework added for what stdlib-adjacent tooling covers.
Case study: prism — risk-proportional testing (as of 2026-07-04)
~/prism — AI PR reviewer under ~1000 lines core. Test suite is tests/test_security.py only — coverage concentrated where failure costs most, matching the hardening commits 51b92c9 "security: add payload size limit, concurrency cap, repo name validation, Ollama timeout" and b011239 "tests: add security path coverage for signature, repo validation, size limit". Security arrived sized to named risks, then tests followed the same list — proportionality in both directions.
Case study: cross-cutting — the doctrine in aggregate (as of 2026-07-04)
Across ~/agentix, ~/prism, ~/ragit, ~/NYTW, ~/orphy: every repo is local-first (local Ollama over cloud APIs where possible); zero CI/CD anywhere (single-maintainer local tools — process sized to project); minimal dependency lists; zero TODO/FIXME markers in any repo (no for-later scaffolding); NYTW's quiz uses Node's native test runner instead of adding a framework (ladder rung 4); agentix/prism/ragit each under ~1000 lines core. ASVER: "Remove server build from package.json for static deployment" — deletion driven by what the deployment shape forbids (motive partly inferred — requires verification).
Validation Criteria
You applied this skill correctly when:
- Every addition in the diff names its ladder rung, and nothing stopped at rung 7 that a higher rung covered.
- The PR removes at least as much as it defensibly can — deletion was considered, and the answer is recorded.
- New dependencies: zero, or each one carries a one-line justification + pin.
- Every security measure traces to a line in a written threat model; every guardrail is labeled with its bypass.
- Tests map to a ranked risk list, and remaining gaps are written down, not hidden.
- Nothing on the never-minimize list (trust-boundary validation, data-loss handling, real security, accessibility, explicit requests) was trimmed.
- The new code passes the mechanical readability proxy: no identifier needs a comment to decode, no nesting deeper than three levels, and nothing outside the file is required to follow the logic.
Provenance & Maintenance
- Sources:
~/ragit,~/agentix,~/prism,~/NYTW,~/orphy,~/asver— investigated 2026-07-04. Doctrine (local-first, minimal deps, security proportional to a written threat model, no over-engineering) owner-confirmed 2026-07-04. Repo facts are illustrations; the ladder and proportionality rules stand on their own. - Assumptions: line counts (~665 ragit, ~700 agentix, <1000 prism core), the "zero TODO/FIXME across repos" observation, and the "zero CI/CD" observation are point-in-time. ASVER's deletion motive is (partly inferred — requires verification). Anything beyond the listed facts is (hypothesis — requires verification).
- Re-verification commands:
cd ~/ragit && find . -name "*.py" -not -path "./.git/*" | xargs wc -l | tail -1 && git show --stat 0a06ae9b cd ~/agentix && grep -in "boundary\|blocklist" README.md | head cd ~/prism && ls tests/ && git log --oneline -6 grep -rn -E "TODO|FIXME" ~/ragit ~/agentix ~/prism --include="*.py" | head - Likely to drift: line counts (repos grow), the no-tests gap in ragit (may be closed), prism's security-only test posture (suite may broaden), TODO-free status, dependency pins.
- Maintenance checklist:
- Re-run re-verification commands; update counts and re-stamp dates.
- If ragit gains tests or prism broadens its suite, update those case studies.
- Re-confirm the doctrine with the owner if project priorities shift.
- Confirm cross-referenced skills (
security-review-playbook,validation-and-testing,dependency-management,change-control,research-methodology,llm-integration-reliability) still exist under those directory names.
What ships with it
Read from the repository
Just SKILL.md. No reference files, no scripts.
Gives 0 of the 12 instructions most project setup skills give in ~3.6k tokens
Counted across 999 of the 1,637 authors here whose files we hold, read 2026-08-07
- Ask one question at a timein 29 of 999, across 28 files
- Detect the package manager from lockfilesin 28 of 999, across 9 files
- Present findings to the userin 26 of 999, across 5 files
- Explore current repo statein 24 of 999, across 3 files
- Update the agent skills block in place if it existsin 24 of 999, across 3 files
- Install husky lint-staged and prettierin 23 of 999, across 4 files
- Create the lintstagedrc filein 22 of 999, across 3 files
- Commit all changed filesin 22 of 999, across 3 files
- Run lint-staged to verify it worksin 22 of 999, across 3 files
- Create the husky pre-commit filein 21 of 999, across 2 files
- Create a prettierrc file if missingin 21 of 999, across 2 files
- Initialize huskyin 21 of 999, across 2 files
Said here and by no other author read
- stop at the first decision ladder rung that holds
- record one line why for speculative features not built
- search the codebase for existing code before writing
- use stdlib before adding new dependencies
- prefer platform primitives over custom code
- prefer deletion over addition when fixing bugs
Grouped from the skills themselves: near-identical wordings counted once, and counted by distinct author, so one author publishing three of these counts once. Length counted with cl100k_base; the agent that loads this file may tokenize it differently.