{"id":"6387ad63-6d15-422e-9908-948bb2fc4638","shortId":"xXeFbK","kind":"skill","title":"kamae","tagline":"Kamae (構え) — robust server-side TypeScript design. Functional domain modeling with\ndiscriminated unions, pure state transitions, Result types, schema-validated boundaries,\nand PII protection.\n\nTRIGGER when: writing TypeScript domain models, use cases, repositories, state transiti","description":"# Kamae — Functional Domain Modeling in TypeScript\n\nSix topic files cover the principles. Read only the file(s) relevant to the current task. The library guides under `result-libraries/` and `validation-libraries/` are read on demand based on the project's `package.json`.\n\n## Step 0: Load applicable rules\n\nBefore any other step, glob and Read rules in priority order:\n\n1. `.claude/rules/*.md` (project-level overrides at the working-tree root)\n2. `~/.claude/rules/*.md` (user-global preferences)\n3. `../../rules/defaults/*.md` relative to this `SKILL.md` (plugin defaults)\n\nFor each file:\n\n- Read the YAML frontmatter. Skip the rule unless `applies-to` is `kamae` or `*`.\n- Group by `name`. For each `name`, keep only the highest-tier instance (1 > 2 > 3); within a tier the lexicographically last filename wins.\n- Apply the body of each surviving rule throughout the remaining steps. A `library-preference` rule overrides Step 1 detection; a `convention` rule shapes generated code; an `override` rule replaces guidance from a specific topic file.\n\nIf no rules are found, proceed with the plugin defaults already documented in [`../../rules/defaults/`](../../rules/defaults/).\n\nSee [`../../rules/README.md`](../../rules/README.md) for the rule format.\n\n## Step 1: Detect project libraries\n\nRead `package.json` once. Note which Result library and validation library are present:\n\n- Result libraries — match the first present in priority `neverthrow` > `byethrow` > `fp-ts` > `option-t`. Load the matching guide under [`result-libraries/`](./result-libraries/) when error-handling is in scope.\n- Validation libraries — match the first present in priority `zod` > `valibot` > `arktype`. Load the matching guide under [`validation-libraries/`](./validation-libraries/) when boundary or branded-type work is in scope.\n\nIf none are present, ask the user before proceeding.\n\n## Step 2: Apply the topic relevant to the task\n\nEach topic below is one file. Read it lazily — only the file(s) you need for the current task.\n\n### Type-Driven Domain Modeling — [domain-modeling.md](./domain-modeling.md)\n\nRepresent states with discriminated unions using `kind` as the unified discriminant. Use `type` (not `interface`), Companion Object pattern, branded types via the project's validation library, `Readonly<>`, function property notation, and one-concept-per-file structure.\n\n### State Transitions — [state-modeling.md](./state-modeling.md)\n\nExpress transitions with pure functions. Argument types constrain valid source states; return types make targets explicit. Invalid transitions become compile errors. Use `assertNever` for exhaustiveness.\n\n### Error Handling — [error-handling.md](./error-handling.md)\n\nTreat errors as values via `Result`. Define error types as discriminated unions so callers branch exhaustively. Do not throw exceptions in domain code.\n\n### Boundary Defense — [boundary-defense.md](./boundary-defense.md)\n\nValidate every external input (API requests, DB results, file/queue/env) with a schema at runtime. Trust types inside the domain. Do not use type assertions — `as const` and `as const satisfies Type` are the only allowed forms; when the type is unknown, parse through a validation-library schema instead. Apply `Sensitive<T>` to PII fields; the validation schema auto-wraps them.\n\n### Declarative Style — [declarative-style.md](./declarative-style.md)\n\nUse `filter` / `map` / `reduce` with companion-object predicates instead of imperative loops. Model domain events as immutable records.\n\n### Test Data — [test-data.md](./test-data.md)\n\nDefine fixtures with `as const satisfies Type` to preserve discriminant literal types and prevent widening.\n\n## Examples\n\nWorked end-to-end examples are in [examples/](./examples/). Read them only when the topic guide cites a specific example.\n\n## Applying These Principles\n\nThese are recommendations, not strict rules. Use judgment based on context. If you deviate from a principle, state the reason in a comment. Justifiable reasons include: external library requires class inheritance, immutable object creation cost is a measured performance concern, or a different pattern has been adopted by team agreement.","tags":["kamae","iwasa-kosui","agent-skills"],"capabilities":["skill","source-iwasa-kosui","skill-kamae","topic-agent-skills"],"categories":["kamae-ts"],"synonyms":[],"warnings":[],"endpointUrl":"https://skills.sh/iwasa-kosui/kamae-ts/kamae","protocol":"skill","transport":"skills-sh","auth":{"type":"none","details":{"cli":"npx skills add iwasa-kosui/kamae-ts","source_repo":"https://github.com/iwasa-kosui/kamae-ts","install_from":"skills.sh"}},"qualityScore":"0.465","qualityRationale":"deterministic score 0.47 from registry signals: · indexed on github topic:agent-skills · 31 github stars · SKILL.md body (4,173 chars)","verified":false,"liveness":"unknown","lastLivenessCheck":null,"agentReviews":{"count":0,"score_avg":null,"cost_usd_avg":null,"success_rate":null,"latency_p50_ms":null,"narrative_summary":null,"summary_updated_at":null},"enrichmentModel":"deterministic:skill-github:v1","enrichmentVersion":1,"enrichedAt":"2026-05-18T19:04:28.077Z","embedding":null,"createdAt":"2026-05-10T13:04:29.883Z","updatedAt":"2026-05-18T19:04:28.077Z","lastSeenAt":"2026-05-18T19:04:28.077Z","tsv":"'/../rules/defaults':119,217,218 '/../rules/readme.md':220,221 '/.claude/rules':112 '/boundary-defense.md':445 '/declarative-style.md':510 '/domain-modeling.md':348 '/error-handling.md':418 '/examples':559 '/result-libraries':267 '/state-modeling.md':389 '/test-data.md':533 '/validation-libraries':294 '0':83 '1':98,157,186,227 '2':111,158,315 '3':118,159 'adopt':620 'agreement':623 'allow':480 'alreadi':214 'api':450 'appli':139,168,316,495,571 'applic':85 'applies-to':138 'argument':395 'arktyp':285 'ask':309 'assert':469 'assertnev':412 'auto':504 'auto-wrap':503 'base':76,582 'becom':408 'bodi':170 'boundari':24,296,442 'boundary-defense.md':444 'branch':433 'brand':299,367 'branded-typ':298 'byethrow':252 'caller':432 'case':35 'cite':567 'class':603 'claude/rules':99 'code':193,441 'comment':596 'companion':364,517 'companion-object':516 'compil':409 'concept':382 'concern':613 'const':471,474,538 'constrain':397 'context':584 'convent':189 'cost':608 'cover':48 'creation':607 'current':59,340 'data':531 'db':452 'declar':507 'declarative-style.md':509 'default':126,213 'defens':443 'defin':425,534 'demand':75 'design':9 'detect':187,228 'deviat':587 'differ':616 'discrimin':14,352,359,429,543 'document':215 'domain':11,32,41,345,440,464,525 'domain-modeling.md':347 'driven':344 'end':552,554 'end-to-end':551 'error':270,410,415,420,426 'error-handl':269 'error-handling.md':417 'event':526 'everi':447 'exampl':549,555,558,570 'except':438 'exhaust':414,434 'explicit':405 'express':390 'extern':448,600 'field':499 'file':47,54,129,203,328,334,384 'file/queue/env':454 'filenam':166 'filter':512 'first':247,279 'fixtur':535 'form':481 'format':225 'found':208 'fp':254 'fp-ts':253 'frontmatt':133 'function':10,40,376,394 'generat':192 'glob':91 'global':116 'group':144 'guid':63,262,289,566 'guidanc':198 'handl':271,416 'highest':154 'highest-ti':153 'immut':528,605 'imper':522 'includ':599 'inherit':604 'input':449 'insid':462 'instanc':156 'instead':494,520 'interfac':363 'invalid':406 'judgment':581 'justifi':597 'kama':1,2,39,142 'keep':150 'kind':355 'last':165 'lazili':331 'level':103 'lexicograph':164 'librari':62,67,71,181,230,237,240,244,266,276,293,374,492,601 'library-prefer':180 'liter':544 'load':84,259,286 'loop':523 'make':403 'map':513 'match':245,261,277,288 'md':100,113,120 'measur':611 'model':12,33,42,346,524 'name':146,149 'need':337 'neverthrow':251 'none':306 'notat':378 'note':234 'object':365,518,606 'one':327,381 'one-concept-per-fil':380 'option':257 'option-t':256 'order':97 'overrid':104,184,195 'package.json':81,232 'pars':487 'pattern':366,617 'per':383 'perform':612 'pii':26,498 'plugin':125,212 'predic':519 'prefer':117,182 'present':242,248,280,308 'preserv':542 'prevent':547 'principl':50,573,590 'prioriti':96,250,282 'proceed':209,313 'project':79,102,229,371 'project-level':101 'properti':377 'protect':27 'pure':16,393 'read':51,73,93,130,231,329,560 'readon':375 'reason':593,598 'recommend':576 'record':529 'reduc':514 'relat':121 'relev':56,319 'remain':177 'replac':197 'repositori':36 'repres':349 'request':451 'requir':602 'result':19,66,236,243,265,424,453 'result-librari':65,264 'return':401 'robust':4 'root':110 'rule':86,94,136,174,183,190,196,206,224,579 'runtim':459 'satisfi':475,539 'schema':22,457,493,502 'schema-valid':21 'scope':274,304 'see':219 'sensit':496 'server':6 'server-sid':5 'shape':191 'side':7 'six':45 'skill' 'skill-kamae' 'skill.md':124 'skip':134 'sourc':399 'source-iwasa-kosui' 'specif':201,569 'state':17,37,350,386,400,591 'state-modeling.md':388 'step':82,90,178,185,226,314 'strict':578 'structur':385 'style':508 'surviv':173 'target':404 'task':60,322,341 'team':622 'test':530 'test-data.md':532 'throughout':175 'throw':437 'tier':155,162 'topic':46,202,318,324,565 'topic-agent-skills' 'transit':18,387,391,407 'transiti':38 'treat':419 'tree':109 'trigger':28 'trust':460 'ts':255 'type':20,300,343,361,368,396,402,427,461,468,476,484,540,545 'type-driven':342 'typescript':8,31,44 'unifi':358 'union':15,353,430 'unknown':486 'unless':137 'use':34,354,360,411,467,511,580 'user':115,311 'user-glob':114 'valibot':284 'valid':23,70,239,275,292,373,398,446,491,501 'validation-librari':69,291,490 'valu':422 'via':369,423 'widen':548 'win':167 'within':160 'work':108,301,550 'working-tre':107 'wrap':505 'write':30 'yaml':132 'zod':283 '構え':3","prices":[{"id":"c89a8f1a-a50d-4a61-a536-3881f1137251","listingId":"6387ad63-6d15-422e-9908-948bb2fc4638","amountUsd":"0","unit":"free","nativeCurrency":null,"nativeAmount":null,"chain":null,"payTo":null,"paymentMethod":"skill-free","isPrimary":true,"details":{"org":"iwasa-kosui","category":"kamae-ts","install_from":"skills.sh"},"createdAt":"2026-05-10T13:04:29.883Z"}],"sources":[{"listingId":"6387ad63-6d15-422e-9908-948bb2fc4638","source":"github","sourceId":"iwasa-kosui/kamae-ts/kamae","sourceUrl":"https://github.com/iwasa-kosui/kamae-ts/tree/main/skills/kamae","isPrimary":false,"firstSeenAt":"2026-05-10T13:04:29.883Z","lastSeenAt":"2026-05-18T19:04:28.077Z"}],"details":{"listingId":"6387ad63-6d15-422e-9908-948bb2fc4638","quickStartSnippet":null,"exampleRequest":null,"exampleResponse":null,"schema":null,"openapiUrl":null,"agentsTxtUrl":null,"citations":[],"useCases":[],"bestFor":[],"notFor":[],"kindDetails":{"org":"iwasa-kosui","slug":"kamae","github":{"repo":"iwasa-kosui/kamae-ts","stars":31,"topics":["agent-skills"],"license":"mit","html_url":"https://github.com/iwasa-kosui/kamae-ts","pushed_at":"2026-05-10T19:29:20Z","description":null,"skill_md_sha":"ffbd07d44a9d6babb463b536751b89b499ae165a","skill_md_path":"skills/kamae/SKILL.md","default_branch":"main","skill_tree_url":"https://github.com/iwasa-kosui/kamae-ts/tree/main/skills/kamae"},"layout":"multi","source":"github","category":"kamae-ts","frontmatter":{"name":"kamae","license":"MIT","description":"Kamae (構え) — robust server-side TypeScript design. Functional domain modeling with\ndiscriminated unions, pure state transitions, Result types, schema-validated boundaries,\nand PII protection.\n\nTRIGGER when: writing TypeScript domain models, use cases, repositories, state transitions,\nerror handling, boundary validation, or PII handling on the server side; designing types\nfor business logic; implementing entity/value-object semantics in TS.\nSKIP: frontend React/Vue components, browser code, build tooling, code generation scripts,\npure infrastructure-as-code; code unrelated to domain logic."},"skills_sh_url":"https://skills.sh/iwasa-kosui/kamae-ts/kamae"},"updatedAt":"2026-05-18T19:04:28.077Z"}}