agentleFS
boazsegevboazsegev/omoya/skills/programming-api-design/SKILL.md

programming-api-design

Skill1 starsChanged 6 days agoMITView on GitHub

This skill should be used when designing or reviewing local APIs for modules, libraries or functions; not HTTP/REST or OpenAPI.

We split this skill into the rules it gives an agent

9 rules. About 0 are common, 8 are distinctive, and 1 is 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.

  • 1

    Very specific

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

  • Common
  • Distinctive
  • Very specific
  1. Distinctive:

    Keep one implementation per behavior.

    line 14
  2. Distinctive:

    Every public symbol documents: preconditions, ownership and lifetime of inputs and outputs, side effects, idempotency, complexity when not …

    line 19
  3. Distinctive:

    Use one error strategy per layer, following the language skill.

    line 20
  4. Distinctive:

    Keep the surface minimal: private by default.

    line 22
  5. Distinctive:

    Default to safe behavior: least privilege, validated input at the boundary, opaque handles over exposed internals.

    line 23
  6. Distinctive:

    Don't over-engineer. Not every edge case is relevant.

    line 24
  7. Distinctive:

    Keep names whose form the language or a framework requires, such as constructors, operator hooks and interface methods.

    line 30
  8. Distinctive:

    Never add a required parameter, remove a field or narrow accepted input in a published API.

    line 43
  9. Very specific:

    Treat added struct fields, enum values and return fields as non-breaking only when callers are documented to tolerate them …

    line 45

≈ “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.

Keep what fits and drop the rest. Your version, ready for your agents.
Files
SKILL.md

API Design

Deliver APIs as signatures with contract comments, plus happy-path, error-path and composition examples.

Units

  • Give each unit one responsibility. If describing it needs "and", split it.
  • Build features by composing small units. Options may tune one behavior; give distinct behaviors their own functions instead of switching modes inside one.
  • Keep one implementation per behavior; reuse it instead of copying logic between units.
  • Callers use public contracts only, never another unit's internal state or helpers.

Contract

  • Every public symbol documents: preconditions, ownership and lifetime of inputs and outputs, side effects, idempotency, complexity when not obvious, and each failure (condition, caller action, retry safety).
  • Use one error strategy per layer, following the language skill; never mix throwing and result values for the same failure class.
  • Separate commands from queries: queries never mutate; retryable commands are idempotent.
  • Keep the surface minimal: private by default; export only what callers need.
  • Default to safe behavior: least privilege, validated input at the boundary, opaque handles over exposed internals.
  • Don't over-engineer. Not every edge case is relevant. Example: if system is out of memory you have bigger problems than code correctness.

Naming

  • Order name parts from general to specific: the thing acted on first, the action last (<subject><action>). Nest further subjects the same way (<module><subject><action>).
  • Spell names in the project's or language's case and separator style; the word order stays the same: tableBuild, table_build, table.build, note-create/note-destroy.
  • Keep names whose form the language or a framework requires, such as constructors, operator hooks and interface methods.

Signatures

  • Take 0–3 positional arguments; move optional settings into an options struct or object. Order: subject or context first, required before optional, inputs before outputs, options last.
  • Symmetric pairs share names and argument order (file.read/file.write, File.open/file.close, poolInit/poolDestroy).
  • Make every call site state its meaning: replace positional flags with named options or separate functions (render(doc, { draft: true }) or draftRender(doc), not render(doc, true, false)).
  • Type a multi-valued mode with the language's checked form, not free strings: an enum in C or Zig, a string-literal union in TypeScript, a documented string set validated at entry in JavaScript.
  • Distinguish adjacent same-type parameters with named fields (copy({ src, dst })) or, in typed languages, distinct types (UserId/GroupId).
  • Return the useful value so calls compose; return a struct for multiple values.

Evolution

  • Never add a required parameter, remove a field or narrow accepted input in a published API. Add optional fields with defaults; put new required behavior in a new function.
  • Deprecate before removal; state the replacement and removal version.
  • Treat added struct fields, enum values and return fields as non-breaking only when callers are documented to tolerate them (zero-initialized structs, default/else branches).

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.

Reviews can't be read right now.

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.