This skill should be used when the user asks to "create an ADT", "scaffold a discriminated union", "add a tagged union", "create Effect Schema union", or needs to create algebraic data types following the ADT library pattern with proper member files and barrel exports.
/plugin marketplace add jasonkuhrt/claude-marketplace/plugin install library-adt@jasonkuhrtThis skill inherits all available tools. When active, it can use any tool Claude has access to.
Scaffold ADT (Algebraic Data Type) unions with discriminated member types.
Before creating any ADT, read the convention documents:
~/.claude/docs/conventions/namespace-module.md — Core _.ts/__.ts pattern~/.claude/docs/conventions/library-adt.md — ADT-specific patternsStructure:
src/lib/<adt-name>/
├── _.ts # export * as AdtName from './__.js'
├── __.ts # exports member namespaces + union
├── <adt-name>.ts # Union definition
├── <member-a>.ts # Member type
└── <member-b>.ts # Member type
Steps:
src/lib/<adt-name>/ (kebab-case matching ADT name)__.ts)__.ts exporting members as namespaces + union exports_.ts pointing to __.ts// <member>.ts
import * as S from 'effect/Schema'
export class MemberName extends S.TaggedClass<MemberName>()('AdtNameMemberName', {
// fields...
}) {
static is = S.is(MemberName)
}
Naming Rules:
VersionedDocumentVersioned// <adt-name>.ts
import * as S from 'effect/Schema'
import { MemberA } from './member-a.js' // Direct import, NOT from __.ts
import { MemberB } from './member-b.js'
export const AdtName = S.Union(MemberA, MemberB)
export type AdtName = typeof AdtName.Type
__.ts)// __.ts
export * from './<adt-name>.js'
export * as MemberA from './member-a.js'
export * as MemberB from './member-b.js'
// added.ts
export class Added extends S.TaggedClass<Added>()('LifecycleEventAdded', {
schema: SchemaRef,
revision: Revision,
}) {
static is = S.is(Added)
}
// removed.ts
export class Removed extends S.TaggedClass<Removed>()('LifecycleEventRemoved', {
schema: SchemaRef,
revision: Revision,
}) {
static is = S.is(Removed)
}
// lifecycle-event.ts
import { Added } from './added.js'
import { Removed } from './removed.js'
export const LifecycleEvent = S.Union(Added, Removed)
export type LifecycleEvent = typeof LifecycleEvent.Type
// __.ts
export * as Added from './added.js'
export * from './lifecycle-event.js'
export * as Removed from './removed.js'
// _.ts
export * as LifecycleEvent from './__.js'
// Import ONLY from namespace (_.js)
import { LifecycleEvent } from '#lifecycle-event'
// Access members via namespace
const added = LifecycleEvent.Added.make({ schema, revision })
const removed = LifecycleEvent.Removed.make({ schema, revision })
// Type check
if (LifecycleEvent.Added.is(event)) {
// event is Added
}
_.js, never from __.js.make() constructor from tagged classes, never manual object constructionAdtNameMemberName) for global uniquenessUse when working with Payload CMS projects (payload.config.ts, collections, fields, hooks, access control, Payload API). Use when debugging validation errors, security issues, relationship queries, transactions, or hook behavior.