write-data-type-ref
Write a reference documentation page for a specific data type in ZIO Blocks. Use when the user asks to document a data type, write an API reference for a type, or create a reference page for a class/trait/object.
Best use case
write-data-type-ref is best used when you need a repeatable AI agent workflow instead of a one-off prompt.
Write a reference documentation page for a specific data type in ZIO Blocks. Use when the user asks to document a data type, write an API reference for a type, or create a reference page for a class/trait/object.
Teams using write-data-type-ref should expect a more consistent output, faster repeated execution, less prompt rewriting.
When to use this skill
- You want a reusable workflow that can be run more than once with consistent structure.
When not to use this skill
- You only need a quick one-off answer and do not need a reusable workflow.
- You cannot install or maintain the underlying files, dependencies, or repository context.
Installation
Claude Code / Cursor / Codex
Manual Installation
- Download SKILL.md from GitHub
- Place it in
.claude/skills/write-data-type-ref/SKILL.mdinside your project - Restart your AI agent — it will auto-discover the skill
How write-data-type-ref Compares
| Feature / Agent | write-data-type-ref | Standard Approach |
|---|---|---|
| Platform Support | Not specified | Limited / Varies |
| Context Awareness | High | Baseline |
| Installation Complexity | Unknown | N/A |
Frequently Asked Questions
What does this skill do?
Write a reference documentation page for a specific data type in ZIO Blocks. Use when the user asks to document a data type, write an API reference for a type, or create a reference page for a class/trait/object.
Where can I find the source code?
You can find the source code on GitHub using the link provided at the top of the page.
SKILL.md Source
# Write Data Type Reference Page
Write a comprehensive reference documentation page for a ZIO Blocks data type.
## Target Type
$ARGUMENTS
## Step 1: Deep Source Code Research
Before writing anything, build a complete mental model of the type:
1. **Find the source file**: Use Glob to find the primary source file for the type. Check all Scala version directories (`*/src/main/scala*/`). The type may have platform-specific or version-specific variants.
2. **Read the full source**: Read the entire source file. Identify:
- The type signature (class/trait/object, type parameters, variance, extends clauses)
- All public methods, their signatures, and what they do
- Companion object methods (factory methods, smart constructors, predefined instances)
- Nested types and type aliases
- Implicit instances and extension methods
3. **Find tests**: Search `*/src/test/scala/` for test files referencing the type. Tests reveal:
- Intended usage patterns and idioms
- Edge cases and expected behavior
- Real-world examples
4. **Find existing examples**: Use Glob and Grep to locate examples in `schema-examples/` or any directory with "examples" in its name.
5. **Find usages**: Grep for the type name across the codebase to find how it's used by other modules — this reveals integration points and relationships.
6. **Read related docs**: Check `docs/` and `docs/reference/` for pages that reference this type.
7. **Search GitHub history**: Run `sbt "gh-query --verbose <TypeName>"` to search GitHub issues, PRs, and comments for discussions about the type. Use the results to:
- Understand design decisions and rationale behind the API
- Find known caveats, gotchas, or non-obvious behavior surfaced in issues
- Discover common user questions or pain points to address in the docs
- Identify changelog entries or breaking changes worth noting
- Surface examples or idioms shared by contributors in PRs
Run multiple queries as needed (e.g., the simple type name, the fully-qualified name, related feature keywords) to get thorough coverage.
## Step 2: Write the Documentation
### File Location and Frontmatter
Place the file in `docs/reference/<type-name-kebab-case>.md`:
```
---
id: <kebab-case-id>
title: "<TypeName>"
---
```
The `id` must match the filename (without `.md`).
### Document Structure
Follow this structure precisely. Every section below marked **(required)** must appear. Sections marked **(if applicable)** should only appear when relevant.
#### 1. Opening Definition (required)
Start with a concise, technical definition. Use inline code for the type signature. Explain the type parameters. State the core purpose in 1-3 sentences.
Pattern:
```
`TypeName[A]` is a **key concept in two or three words** that does X. The fundamental operations are `op1` and `op2`.
```
Then list key properties as bullet points if applicable:
```
`TypeName`:
- is purely functional and referentially transparent
- is concurrent-safe and lock-free
- updates and modifies atomically
```
The definition should be concise but informative, with enough detail about type parameters and variance. For example, the `Chunk[A]` is an immutable, indexed sequence of elements of type `A`, optimized for high-performance operations.
After the definition paragraph, include the source definition of the data type in a Scala code block (using plain `` ```scala `` without mdoc, since this is for illustration):
- Show only the structural shape — the trait/class declaration with type parameters, variance annotations, and extends clauses
- Strip method bodies, private members, and extra keywords like `final`; show only the structural shape of the type
#### 2. Motivation / Use Case (if applicable)
This section answers the following questions:
1. What is the purpose of this data type?
2. What problem does it solve?
3. Why was it created, and when should we use it?
4. What are its key advantages over alternatives? Compare with alternatives if it helps clarify.
Tools:
1. Use an ASCII art diagram showing the type structure.
2. For comparing with alternatives, use a comparison table showing key differences and advantages or use bullet points to list advantages.
3. Include a short code example showing the type in action — the "hello world" for this type.
#### 3. Installation (if applicable)
Only include this for top-level module types (e.g., `Chunk`, `Context`, `TypeId`). Skip for internal types that come as part of a larger module.
```scala
libraryDependencies += "dev.zio" %% "zio-blocks-<module>" % "<version>"
```
For cross-platform (Scala.js):
```scala
libraryDependencies += "dev.zio" %%% "zio-blocks-<module>" % "<version>"
```
Note supported Scala versions: 2.13.x and 3.x.
#### 4. Construction / Creating Instances (required)
Document all ways to create values of the type, organized by method:
- Factory methods on the companion object (`apply`, `empty`, `from*`, `of`, `derived`)
- Smart constructors
- Builder patterns
- Conversion from other types
- Predefined instances (if any)
Each method gets its own `###` subsection with a short explanation and a code example.
#### 5. Predefined Instances (if applicable)
If the companion object provides predefined instances (like `TypeId.int`, `TypeId.string`), list them organized by category with a brief table or grouped code block.
#### 6. Core Operations (Required)
Document the primary API organized by category. Group related methods under `###` subsections:
For example:
- **Element Access** (get, apply, head, etc.)
- **Transformations** (map, flatMap, filter, etc.)
- **Combining** (++, combine, merge, etc.)
- **Querying** (exists, forall, find, contains, etc.)
- **Conversion** (toList, toArray, toString, etc.)
For each group:
- List methods with brief descriptions
- Show a code example demonstrating 2-4 methods together
- Note performance characteristics inline when relevant (e.g., "O(1)", "O(n)")
For each method:
a. **Use a `####` heading** with the method name
b. **Explain what it does** in plain language
c. **Show the method signature** in a plain `scala` code block using the simplest trait interface format — just the method name, parameters, and return type, without extra keywords like `override`, `final`, `sealed`. For example:
```scala
trait Chunk[+A] {
def map[B](f: A => B): Chunk[B]
}
```
If the method is in the companion object, show it as a function in the companion object's simplest form:
```scala
object Chunk {
def apply[A](as: A*): Chunk[A]
}
```
d. **Show a usage example** in a [compile-checked code blocks with mdoc](#compile-checked-code-blocks-with-mdoc)
e. **Note important caveats** using [Docusaurus admonitions](#docusaurus-admonitions)
#### 7. Subtypes / Variants (if applicable)
If the type has important subtypes, variants, or related types (e.g., `NonEmptyChunk` for `Chunk`, `Nominal`/`Alias`/`Opaque` for `TypeId`), document each in a dedicated section. For each subtype:
- What it is and when to use it
- How to create it
- Key operations that differ from the parent/related type
- How to convert between the parent and subtype
#### 8. Comparison Sections (when applicable)
Compare with analogous concepts from Java, Scala stdlib, or theoretical CS when it adds clarity. Examples:
- "Ref vs AtomicReference in Java"
- "Ref vs State Monad"
- "Promise vs Scala's Promise"
- "Chunk vs List vs Array"
- "TypeId vs Scala's TypeTag vs Java's Class"
- "Lazy vs lazy val vs def"
#### 9. Advanced Usage / Building Blocks (when applicable)
Show how the type composes with other types or how it can be used to build higher-level abstractions.
#### 10. Integration (if applicable)
Show how this type integrates with other ZIO Blocks data types and module. For example:
- How `TypeId` is used in `Schema`
- How `Chunk` is used in `Reflect`
- How `DynamicValue` connects to `Schema` and formats
Add cross-references to related docs (e.g., `[Schema](./schema.md)`, `[Reflect](./reflect.md)`) after explaining the integration of each related type.
### Compile-checked Code Blocks with mdoc
This project uses [mdoc](https://scalameta.org/mdoc/) to compile-check all Scala code blocks in documentation. Every Scala code block must use one of the mdoc modifiers below. **Choosing the right modifier is critical** — incorrect usage causes mdoc compilation failures or broken rendered output.
#### Modifier Summary
| Modifier | Rendered Output | Scope | Use When |
|----------------------------|---------------------------|-------------------------------|--------------------------------------------------------------------------|
| `scala mdoc:compile-only` | Source code only | Isolated (no shared state) | Self-contained examples where evaluated output is NOT needed |
| `scala mdoc:silent` | Nothing (hidden) | Shared with subsequent blocks | Setting up definitions needed by later blocks |
| `scala mdoc:silent:nest` | Nothing (hidden) | Shared, wrapped in `object` | Re-defining names already in scope |
| `scala mdoc` | Source + evaluated output | Shared with subsequent blocks | When the evaluated result of expressions should be shown to the reader |
| `scala mdoc:invisible` | Nothing (hidden) | Shared with subsequent blocks | Importing hidden prerequisites |
| `scala mdoc:silent:reset` | Nothing (hidden) | Resets all prior scope | Starting a clean scope mid-document |
| `scala` (no mdoc) | Source code only | Not compiled | Pseudocode, ASCII diagrams, conceptual snippets |
#### Key Rules
- **`mdoc:compile-only`** is the **default** for structural or setup-only examples where no output needs to be shown. Each block is compiled in isolation — definitions do NOT carry over between `compile-only` blocks.
- **`mdoc:silent`** defines types/values that **subsequent blocks** can reference (scope persists until reset). Nothing is rendered. You cannot redefine the same name — use `silent:nest` for that.
- **`mdoc:silent:nest`** is like `silent` but wraps code in an anonymous `object`, allowing you to **shadow names** from earlier blocks (e.g., redefining `Person` with different fields in a later section).
- **`mdoc:silent:reset`** wipes **all** accumulated scope and starts fresh. Use when `silent:nest` wouldn't suffice (e.g., switching to a completely different topic mid-document).
- **`mdoc`** (no qualifier) shows **source + evaluated output** (REPL-style). Use this whenever you would otherwise write `// Right(42L)`, `// Some("hello")`, or any result comment — let mdoc render the actual evaluated output instead. Requires definitions to be in scope from a prior `silent`/`silent:nest` block.
- **`mdoc:invisible`** is like `silent` but signals "hidden imports only." Rare — prefer including imports in the `compile-only` block itself.
- **No mdoc** (plain `` ```scala ``) — not compiled. Use for pseudocode, ASCII diagrams, type signatures for illustration, or sbt/non-Scala syntax.
#### Choosing the Right Modifier
1. Self-contained example where output doesn't need to be shown? → `mdoc:compile-only`
2. Later blocks need these definitions? → `mdoc:silent` (first time) or `mdoc:silent:nest` (redefining)
3. Need a completely clean scope? → `mdoc:silent:reset`
4. **Showing the result of expressions** (return values, decoded output, computed values)? → `mdoc:silent` for setup + `mdoc` to render evaluated output. **Never manually write `// result` comments when mdoc can show the real output.**
5. Not real Scala? → plain `` ```scala `` or `` ```text ``
#### Pattern: Setup + Evaluated Output
When a code snippet evaluates expressions whose results are meaningful to the reader, split it into two blocks:
````
```scala mdoc:silent
import zio.blocks.schema.Into
case class Source(name: String, count: Int)
case class Target(name: String, count: Long)
val conv = Into.derived[Source, Target]
```
With `conv` in scope, we can call `into` and see the result:
```scala mdoc
conv.into(Source("events", 100))
```
````
The `mdoc` block renders as:
```
conv.into(Source("events", 100))
// val res0: Either[zio.blocks.schema.SchemaError, Target] = Right(Target(events,100))
```
Do **not** use `mdoc:compile-only` and manually write `// Right(Target("events", 100L))` — always prefer the live evaluated output from `mdoc`.
### Writing Rules
- **Be exhaustive on the public API**: Every public method on the type and its companion should be documented. Group them logically, but don't skip methods.
- **One concept per code block**: Each code block demonstrates one cohesive idea.
- **Always include imports**: Every code block must start with the necessary import statements.
- **Show evaluated output with mdoc, not comments**: When expressions have results that are meaningful to the reader (return values, decoded output, computed values), use `mdoc:silent` + `mdoc` so mdoc renders the real output. Do **not** write `// Right(42L)` or `// Some("hello")` manually — these go stale and can be wrong.
- **Prefer `val` over `var`**: Use immutable patterns everywhere.
- **Use ASCII art** for type hierarchies, data structures, and flows.
- **Link to related docs**: Use relative paths `[TypeName](./type-name.md)`.
- **Use "ZIO Blocks"** (not "zio-blocks") for the project name.
- **Don't pad**: Keep prose concise. Let the code examples do the talking. Short explanatory sentence, then code block.
- **No bare subheaders**: Never place a `###` or `####` subheader immediately after a `##` header with nothing in between. Always write at least one sentence of explanation before the first subheader — introduce the group, state the purpose, or give context. The same rule applies at every heading level: a heading must be followed by prose before any child heading.
- **No lone subheaders**: Never create a subsection with only one child. If a `##` section would have only one `###`, or a `###` would have only one `####`, remove the subheader entirely and place the content directly under the parent heading. A subheader is only justified when there are two or more siblings.
- **Every code block must be preceded by an introductory prose sentence**: The content immediately before a code block's opening fence must always be a prose sentence — never a heading alone and never blank space alone. This applies universally:
- After a heading: write at least one sentence before the first code block. Never go `#### Heading` → blank line → ` ```scala `.
- Between two consecutive code blocks: write a short bridging sentence that either summarises what the previous block set up or introduces what the next block demonstrates. Never go ` ``` ` → blank line → ` ```scala `.
- The sentence must be surrounded by blank lines on both sides (standard Markdown spacing), so the required pattern is always: prose sentence, blank line, opening ` ```scala `. The sentence must be concise (one line) and genuinely informative — not filler.
**Wrong** (heading with no intro, then two bare code blocks):
```
#### `Option`
` ``scala
implicit def optionInto[A, B](...): Into[Option[A], Option[B]]
` ``
` ``scala mdoc
Into[Option[Int], Option[Long]].into(Some(42))
` ``
```
**Right**:
```
#### `Option`
`optionInto` coerces the element type of an `Option`, passing `None` through unchanged:
` ``scala
implicit def optionInto[A, B](...): Into[Option[A], Option[B]]
` ``
Both `Some` and `None` are handled — `None` passes through without invoking `Into#into`:
` ``scala mdoc
Into[Option[Int], Option[Long]].into(Some(42))
` ``
```
- **Person**: Use "we" when walking through examples or any time you want to guide the reader through a process or example. ("we can create...", "we need to...").
- **Tense**: Use present tense ("returns", "creates", "modifies").
- **Code snippet description**: When showing example code snippets, explain what they do and why they are relevant. Don't just show code without context.
- **Referencing types, operations, and constructors**: Apply these conventions consistently in all prose, section headings, and inline code:
- **Type name alone** — when talking about the type itself, use only its name with no qualifier: "derives automatically via `As`", "`Into` is a one-way conversion".
- **Instance method** — use `TypeName#methodName` (the `#` convention signals a non-static member): `As#from`, `As#into`, `As#reverse`, `Into#into`.
- **Companion object operation or constructor** — use `TypeName.methodName` (the `.` convention signals a companion/static member): `As.derived`, `As.apply`, `Into.derived`, `Into.apply`.
### Docusaurus Admonitions
Use Docusaurus admonition syntax for adding any of `note`, `tip`, `info`, `warning`, and `danger` to highlight important information. Example for a `note`:
```
:::note
Additional context or clarification.
:::
```
## Step 3: Write Examples
Create focused `App` objects in `zio-blocks-examples/src/main/scala/<type-name-lowercase>/`. Each `App` demonstrates **one use case**. Avoid bundling unrelated scenarios into a single `App`.
### File granularity
- **One `App` per concept** — schema evolution, collection reshaping, error accumulation, etc. are separate `App` objects.
- **Small, related `App`s can share a file** — if several `App`s are short and tightly related (e.g., numeric widening variants), place them together in one file so the reader can run them in sequence.
- **Large `App`s get their own file** — if an `App` needs many types or substantial setup, give it a dedicated file.
### Conventions
- **Package**: matches the directory name (e.g., `package into` for `into/`)
- **Object**: `extends App` so each unit is independently runnable
- **Output**: use `util.ShowExpr.show(expr)` to print both the expression and its result — e.g., `show(Into[Int, Long].into(100))` prints `Into[Int, Long].into(100) => Right(100)`. Never print just the result alone; the reader should see what was evaluated without looking at the source. The `show` helper lives in `zio-blocks-examples/src/main/scala/util/ShowExpr.scala` and is powered by `sourcecode.Text` to capture the source text at compile time.
- **Naming**: name files after the scenario(s) they contain (e.g., `IntoSchemaEvolutionExample.scala`, `IntoCollectionsExample.scala`) not just the type name
### What to Cover
Each `App` should:
- Focus on **one coherent use case**
- Use **realistic domain types** (`Person`, `Order`, `Address`) rather than abstract `Source`/`Target`
- Cover the **happy path and at least one failure/edge case**
- Be **self-contained** — all types and imports are defined within the file
### Example: multiple small Apps in one file
```scala
package mytype
import zio.blocks.schema.Into
import util.ShowExpr.show
// Small related examples share a file — reader runs them one after another
object IntoWideningExample extends App {
show(Into[Int, Long].into(100))
show(Into[Float, Double].into(3.14f))
}
object IntoNarrowingExample extends App {
show(Into[Long, Int].into(42L))
show(Into[Long, Int].into(Long.MaxValue))
}
```
### Example: large App in its own file
```scala
// IntoSchemaEvolutionExample.scala
package mytype
import zio.blocks.schema.Into
import util.ShowExpr.show
object IntoSchemaEvolutionExample extends App {
case class PersonV1(name: String, age: Int)
case class PersonV2(name: String, age: Long, email: Option[String])
val migrate = Into.derived[PersonV1, PersonV2]
show(migrate.into(PersonV1("Alice", 30)))
show(migrate.into(PersonV1("Bob", 25)))
}
```
## Step 4: Integrate
After writing the reference page and examples:
1. If updating an existing file, edit it in place.
2. If creating a new file, place it in the appropriate `docs/reference/` subdirectory based on where it logically belongs and update `sidebars.js` to add it to the sidebar.
3. **Update `docs/index.md`**: Add the new page under the appropriate section in the "Documentation" heading.
4. **Cross-reference**: Add links from related existing docs to the new page.
5. **Verify all links**: Ensure relative links in the new page and in updated pages are correct.
## Step 5: Review
After writing, re-read the document and verify:
- All method signatures match the actual source code
- All code examples would compile with `mdoc`
- The frontmatter `id` matches what `sidebars.js` expects (if an entry exists)
- The document is self-contained—a reader shouldn't need to look at the source code to understand the type's API
- The example file compiles and runs without errorsRelated Skills
write-edition
Run the complete Cycle Pulse edition production pipeline — 6 desk agents, compile, verify, Mara audit.
write-beads
Convert a Technical Design Document into a BEADS.md file for agent implementation
wikidata-search
Search for items and properties on Wikidata and retrieve entity details, claims, and external identifiers. Supports both keyword search (Wikidata Action API) and semantic/hybrid search (Wikidata Vector Database), plus direct entity retrieval (Special:EntityData) and structured querying (WDQS SPARQL).
typespec-m365-copilot-typespec-create-agent
Generate a complete TypeSpec declarative agent with instructions, capabilities, and conversation starters for Microsoft 365 Copilot Use when: the task directly matches typespec create agent responsibilities within plugin typespec-m365-copilot. Do not use when: a more specific framework or task-focused skill is clearly a better match.
typespec-create-agent
Generate a complete TypeSpec declarative agent with instructions, capabilities, and conversation starters for Microsoft 365 Copilot
type-inference-validation
Static type inference and validation for navigation paths
twelve-data-automation
Automate Twelve Data tasks via Rube MCP (Composio). Always search tools first for current schemas.
supadata-automation
Automate Supadata tasks via Rube MCP (Composio). Always search tools first for current schemas.
session-log-data
Describes the data files available in the coding agent environment after copilot-setup-steps runs. Use when analyzing downloaded session logs or aggregated usage data.
senior-data-scientist
World-class data science skill for statistical modeling, experimentation, causal inference, and advanced analytics. Expertise in Python (NumPy, Pandas, Scikit-learn), R, SQL, statistical methods, A/B testing, time series, and business intelligence. Includes experiment design, feature engineering, model evaluation, and stakeholder communication. Use when designing experiments, building predictive models, performing causal analysis, or driving data-driven decisions.
senior-data-engineer
World-class data engineering skill for building scalable data pipelines, ETL/ELT systems, and data infrastructure. Expertise in Python, SQL, Spark, Airflow, dbt, Kafka, and modern data stack. Includes data modeling, pipeline orchestration, data quality, and DataOps. Use when designing data architectures, building data pipelines, optimizing data workflows, or implementing data governance.
scientific-papers-to-dataset
Build structured datasets from academic papers. Use when the user wants to extract structured data from scientific literature, traverse citation graphs, search OpenAlex for papers, or create datasets from PDFs for research purposes.