schema-first-development
Skill78 starsChanged 6 days agoApache-2.0View on GitHub
Focused schema-first guidance for this repo's effect/Schema and @beep/schema patterns. Use when adding or refactoring schemas, replacing exported interface/type data models, fixing schema-first lint violations, modeling literal domains or tagged unions, applying schema defaults or transformations, decoding external input, or reviewing schema code for repo-law compliance.
In this repository38 other files it gives its agents.
- AGENTS.mdAGENTS.md
- explorations/AGENTS.mdAGENTS.md
- adhdSkill
- atom-reactivity-specialistSkill
- browser-qa-loopSkill
- closeoutSkill
- codex-findingsSkill
- crispenSkill
- effect-first-developmentSkill
- exploreSkill
- grillingSkill
- grill-meSkill
- grill-with-docsSkill
- jsdoc-annotation-specialistSkill
- motion-evidence-reviewSkill
- onepassword-secret-refsSkill
- ontology-architectSkill
- ontology-conceptualizerSkill
- ontology-curatorSkill
- ontology-foundational-auditorSkill
- ontology-mapperSkill
- ontology-requirementsSkill
- ontology-scoutSkill
- ontology-validatorSkill
- operator-handoffSkill
- orchestrateSkill
- plasma-sensitive-entrySkill
- portlessSkill
- qa-session-opsSkill
- quality-review-fix-loopSkill
- reflectSkill
- remote-development-agentsSkill
- shadcnSkill
- sparql-expertSkill
- teachSkill
- turborepoSkill
- unslopSkill
- yeetSkill
The file
Show its rules and text
We split this skill into the rules it gives an agent
28 rules. About 0 are common, 4 are distinctive, and 24 are very specific to this project.
≈0
Common · estimate
Many files like this have a rule of this kind.
≈4
Distinctive · estimate
This author's own choices. Worth a look.
24
Very specific
Tied to their project's names, files or tools. Probably skip.
- Common
- Distinctive
- Very specific
- Distinctive: line 13
Use this skill for schema-heavy work in this repository.
- Distinctive: line 15
Treat schema-first rules as enforced repository law, not style preference.
- Very specific: line 22
Keep Schema as the source of truth for pure data models.
- Very specific: line 39
Check local Effect v4 source for nontrivial Schema API choices.
- Distinctive: line 46
Prefer exact upstream or repo-local helpers over memory and ad-hoc plumbing.
- Very specific: line 55
Check upstream effect/Schema first, then reuse @beep/schema and existing local schemas before inventing new checks.
- Very specific: line 69
Prefer Effect schema codecs.
- Very specific: line 73
No exported pure-data interface or type literal remains.
- Very specific: line 74
No schema value ends with Schema.
- Very specific: line 83
Prefer import * as S from "effect/Schema" and canonical Effect aliases.
- Very specific: line 84
Create file-local identity composers with @beep/identity/packages.
- Distinctive: line 89
Use named intermediate schemas for reused concepts.
- Very specific: line 90
Prefer LiteralKit for named literal domains: its keyed API (.Enum, .is, match, .toTaggedUnion(...)) plus the S.Literals members it inherits …
- Very specific: line 94
Prefer MappedLiteralKit when a protocol/code mapping needs both encoded and decoded literal helper surfaces.
- Very specific: line 96
Do not add as const to inline array literals passed directly to LiteralKit(...).
- Very specific: line 103
Use S.toTaggedUnion("<field>") for discriminators such as kind, status, type, subtype, profile, or family.
- Very specific: line 105
Use S.TaggedUnion(...) only for canonical _tag object unions.
- Very specific: line 109
Prefer schema-derived tagged-union helpers (.cases, .guards, .isAnyOf, .match) when constructing, guarding, or branching on a schema tagged …
- Very specific: line 111
Use S.OptionFromNullOr, S.OptionFromNullishOr and S.OptionFromOptionalKey for absence at the boundary.
- Very specific: line 115
Use S.OptionFrom* when the wire/schema field is optional or nullish.
- Very specific: line 120
Use O.all({...}) for all-or-nothing fixed-shape composition.
- Very specific: line 125
Prefer built-in schema constructors and checks before S.makeFilter(...).
- Very specific: line 126
Treat broad exported/domain/boundary primitives such as S.String, S.Number, and unbounded arrays as prompts to ask whether the schema …
- Very specific: line 129
If you need a custom reusable check, include identifier, title, and description.
- Very specific: line 131
Use S.is(schema) for guards, S.toEquivalence(schema) for comparisons, and Arbitrary.schema(schema) (effect/Arbitrary) for schema-modeled …
- Very specific: line 133
Use S.fromJsonString(S.Unknown) or S.fromJsonString(schema) for JSON string boundaries.
- Very specific: line 135
Use S.decodeUnknownEffect / S.decodeEffect and S.encodeUnknownEffect / S.encodeEffect by default.
- Very specific: line 145
Use effect-first-development when the task is broader than schema work, including service/layer wiring and typed error flow outside schema …
≈ “Common” is an estimate: at least 1 in 5 of the 350,495 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
Schema-First Development
Use this skill for schema-heavy work in this repository.
Treat schema-first rules as enforced repository law, not style preference. The primary sources are:
standards/effect-first-development.mdpackages/tooling/tool/cli/src/commands/Lint/SchemaFirst.tsstandards/schema-first.inventory.jsonc
Keep Schema as the source of truth for pure data models.
Workflow
- Classify the task.
- New schema or domain model
- Refactor from exported
interface/ type literal - Boundary decode, transform, or defaulting work
- Literal domain or tagged union modeling
- Review or lint-fix
- Load only the reference file you need.
- Repository laws:
references/repo-laws.md - Local shared schema primitives:
references/local-primitives.md - Pattern selection and anti-patterns:
references/pattern-catalog.md - Real repository examples:
references/examples.md
- Check local Effect v4 source for nontrivial Schema API choices.
.repos/effectpoints to$HOME/YeeBois/references/effect/effect, the Effect child of the reference workspace; Effectmainis v4.
- Start with
.repos/effect/packages/effect/SCHEMA.md. - Confirm behavior in
.repos/effect/packages/effect/src/Schema.tsor the specialized module (SchemaAST,SchemaGetter,SchemaIssue,SchemaRepresentation,SchemaTransformation) when using advanced APIs. - Prefer exact upstream or repo-local helpers over memory and ad-hoc plumbing.
- Apply the laws in this order.
- Model pure data with
Schemafirst. - Model plain object data as a branded
S.Opaqueover an annotatedS.Struct(S.TaggedStructfor_tagdata). KeepS.Class/S.TaggedClass/S.Error/S.TaggedErrorfor errors, persisted entities, schemas with instance members, and.extendchains. Every schema class and Opaque declaration carries{ readonly brand: unique symbol }. - Check upstream
effect/Schemafirst, then reuse@beep/schemaand existing local schemas before inventing new checks. Where upstream covers afoundation/modelingconcept's intent, its covered facets retire in the same PR that migrates their consumers, with no alias; the whole concept retires unless the lines reading its uncovered members outnumber the lines using its covered facets (ADAPT, per the facet census instandards/architecture/DECISIONS.md"Upstream-First Foundation/Modeling"). - Move normalization, defaults, nullable handling, and JSON parsing into the schema.
- Annotate reusable non-class schemas with
.pipe($I.annoteSchema(...))(LiteralKitincluded); classes take$I.annote(...)as their trailing argument. - Derive guards, equivalence, arbitraries, codecs, tagged-union helpers, and literal helpers from the schema instead of writing parallel helpers.
- Prefer Effect schema codecs; map schema errors with
Effect.mapError(...)when the error leaves the local helper/module boundary.
- Verify before finishing.
- No exported pure-data
interfaceor type literal remains. - No schema value ends with
Schema. - Non-class schemas export same-name runtime type aliases.
- Tagged unions use the repo-preferred construction.
- Finite variants are modeled as discriminated unions instead of optional payload bags.
- JSON boundaries use schema codecs, not native JSON helpers.
Fast Rules
- Prefer
import * as S from "effect/Schema"and canonical Effect aliases. - Create file-local identity composers with
@beep/identity/packages. - Plain data is
class X extends S.Opaque<X, { readonly brand: unique symbol }>()(S.Struct({...}).pipe($I.annoteSchema("X", {...}))) {}. Construct withX.make(...); there is nonew X(...)and no.extend. Annotate the Struct inside the pipe, becauseX.annotate(...)drops the statics. Seereferences/repo-laws.mdsection 2. - Use named intermediate schemas for reused concepts.
- Prefer
LiteralKitfor named literal domains: its keyed API (.Enum,.is,match,.toTaggedUnion(...)) plus theS.Literalsmembers it inherits (.literals,.pick(...),.mapMembers(...)). UseS.Literalsfor anonymous inline unions never referenced by name. - Prefer
MappedLiteralKitwhen a protocol/code mapping needs both encoded and decoded literal helper surfaces. - Do not add
as constto inline array literals passed directly toLiteralKit(...); its const type parameters preserve the literal tuple. - Model finite variants, lifecycle states, status/result cases, and case-specific payloads as discriminated unions, not one optional/nullish payload bag.
- Decode external optional/nullish case bags into internal tagged models when compatibility requires the wire shape.
- Use
S.toTaggedUnion("<field>")for discriminators such askind,status,type,subtype,profile, orfamily. - Use
S.TaggedUnion(...)only for canonical_tagobject unions. - Fix a tag with
S.TaggedStruct/S.TaggedClass/S.TaggedError, and any other required single-literal field withS.tag(v), neverS.Literal(v);bun run beep laws schema-tag-idioms --checkenforces it. - Prefer schema-derived tagged-union helpers (
.cases,.guards,.isAnyOf,.match) when constructing, guarding, or branching on a schema tagged union. - Use
S.OptionFromNullOr,S.OptionFromNullishOrandS.OptionFromOptionalKeyfor absence at the boundary. Optional fields use exact keys (EF-40):S.optionalKey,S.withDecodingDefaultKey,S.OptionFromOptionalKey, never theirundefined-admitting siblings. - Use
S.OptionFrom*when the wire/schema field is optional or nullish. If runtimeOptionvalues are already being shaped into an object, preferO.getSomesStruct({...})(@beep/utils) for heterogeneous struct spreads with known keys — runtime-identical toR.getSomesbut type-preserving per key; reserveR.getSomes({...})for homogeneous dynamic-key dictionaries. UseO.all({...})for all-or-nothing fixed-shape composition. (Amended 2026-07-05 — seestandards/architecture/DECISIONS.md.) - Use
S.withConstructorDefault(...),S.withDecodingDefaultKey(...), andS.decodeTo(...)withSchemaTransformationfor normalization and fallback behavior. - Prefer built-in schema constructors and checks before
S.makeFilter(...). - Treat broad exported/domain/boundary primitives such as
S.String,S.Number, and unbounded arrays as prompts to ask whether the schema should be more precise. - If you need a custom reusable check, include
identifier,title, anddescription. - Use
S.is(schema)for guards,S.toEquivalence(schema)for comparisons, andArbitrary.schema(schema)(effect/Arbitrary) for schema-modeled property tests. - Use
S.fromJsonString(S.Unknown)orS.fromJsonString(schema)for JSON string boundaries. - Use
S.decodeUnknownEffect/S.decodeEffectandS.encodeUnknownEffect/S.encodeEffectby default. Reach forS.decodeUnknownResult,S.decodeResult, orS.decodeUnknownOptiononly for deliberate non-throwing synchronous helpers; do not teach or addS.decodeSync,S.decodeUnknownSync,S.encodeSync, orS.encodeUnknownSync. If a legacy synchronous wrapper must still throw, convert Result failures withResult.getOrThrowWith(...)so raw schema issues do not escape the boundary.
Escalation
- Use
effect-first-developmentwhen the task is broader than schema work, including service/layer wiring and typed error flow outside schema modeling.
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.

