yaml — Claude Code skill: YAML wire format for json-render
Streaming YAML parser for json-render that turns code fences into JSON Patch. Built for progressive rendering and surgical spec edits via stream.
npx skills add vercel-labs/json-render --skill yaml -a claude-codeWhat yaml does
The skill adds YAML as an alternative to JSONL in @json-render/core. The parser reads YAML line-by-line, emits JSON Patch operations via diffing, and recognizes four fence types: yaml-spec (full spec), yaml-edit (partial merge per RFC 7396), yaml-patch (JSON Patch per RFC 6902), and diff (unified diff).
yamlPrompt generates a system prompt in two modes: standalone (LLM outputs only YAML) and inline (LLM wraps YAML in fences inside conversational responses). pipeYamlRender plugs into AI SDK as a TransformStream that converts fences into patches for json-render.
Requires TypeScript and the @json-render/yaml package. For multi-turn edits, pass previousSpec so yaml-patch applies to the current state before the next yaml-edit.
What it helps with
- parse YAML as a stream and emit JSON Patch operations
- generate AI prompts with YAML format instructions
- convert YAML fences from LLM stream into json-render patches
- apply RFC 7396 merge and RFC 6902 patch to a spec via YAML
- make surgical spec edits without rewriting the entire object
Example prompts for the agent
- add
yamlPromptto the system prompt for the component catalog - set up
pipeYamlRenderfor the stream withpreviousSpecfrom the current spec - use
createYamlStreamCompilerto parse YAML chunks as they arrive
How to install yaml
1Skills CLI (Vercel)
npx skills add vercel-labs/json-render --skill yaml -a claude-code2Manually: put the files in place
~/.claude/skills/yaml/SKILL.mdCopy the whole skill folder; for one project use .claude/skills/yaml/
1Skills CLI (Vercel)
npx skills add vercel-labs/json-render --skill yaml -a codex2Manually: put the files in place
.agents/skills/yaml/SKILL.mdFor all projects use ~/.agents/skills/
1Skills CLI (Vercel)
npx skills add vercel-labs/json-render --skill yaml -a cursor2Manually: put the files in place
.cursor/skills/yaml/SKILL.mdCursor also reads .agents/skills/ and .claude/skills/
1GitHub CLI
gh skill install vercel-labs/json-render yaml2Manually: put the files in place
.github/skills/yaml/SKILL.md1Skills CLI (Vercel)
npx skills add vercel-labs/json-render --skill yaml -a gemini-cli2Platform CLI
gemini skills install https://github.com/vercel-labs/json-render --path skills/yamlManually: put the files in place
.devin/skills/yaml/SKILL.mdThe legacy .windsurf/skills/ path still works
Skills CLI (Vercel)
npx skills add vercel-labs/json-render --skill yaml -a opencodeClaude.ai
Zip the folder and upload it in Settings → Capabilities → Skills
Step by step, with commands for each platform: How to install skills in Claude Code: five ways
Questions about yaml
How to install yaml in Claude Code?
Run npx skills add vercel-labs/json-render --skill yaml -a claude-code. The skill will appear in ~/.claude/skills/yaml/SKILL.md.
What does the yaml skill do?
It adds YAML wire format to json-render: parses YAML as a stream, emits JSON Patch, generates prompts, and converts AI SDK fences into patches.
What's the difference between yaml-edit and yaml-patch?
yaml-edit does a deep merge per RFC 7396 (partial YAML merges with the current spec), while yaml-patch applies JSON Patch operations per RFC 6902 (add, remove, replace).
Source text
SKILL.md · Apache-2.0
---
name: yaml
description: YAML wire format for json-render with streaming parser, prompt generation, and AI SDK transform. Use when working with @json-render/yaml, YAML-based spec streaming, yaml-spec/yaml-edit fences, or YAML prompt generation.
---
# @json-render/yaml
YAML wire format for `@json-render/core`. Progressive rendering and surgical edits via streaming YAML.
## Key Concepts
- **YAML wire format**: Alternative to JSONL that uses code fences (`yaml-spec`, `yaml-edit`, `yaml-patch`, `diff`)
- **Streaming parser**: Incrementally parses YAML, emits JSON Patch operations via diffing
- **Edit modes**: Patch (RFC 6902), merge (RFC 7396), and unified diff
- **AI SDK transform**: `TransformStream` that converts YAML fences into json-render patches
## Generating YAML Prompts
```typescript
import { yamlPrompt } from "@json-render/yaml";
import { catalog } from "./catalog";
// Standalone mode (LLM outputs only YAML)
const systemPrompt = yamlPrompt(catalog, {
mode: "standalone",
editModes: ["merge"],
customRules: ["Always use dark theme"],
});
// Inline mode (LLM responds conversationally, wraps YAML in fences)
const chatPrompt = yamlPrompt(catalog, { mode: "inline" });
```
Options:
- `system` (string) — Custom system message intro
- `mode` ("standalone" | "inline") — Output mode, default "standalone"
- `customRules` (string[]) — Additional rules appended to prompt
- `editModes` (EditMode[]) — Edit modes to document, default ["merge"]
## AI SDK Transform
Use `pipeYamlRender` as a drop-in replacement for `pipeJsonRender`:
```typescript
import { pipeYamlRender } from "@json-render/yaml";
import { createUIMessageStream, createUIMessageStreamResponse } from "ai";
const stream = createUIMessageStream({
execute: async ({ writer }) => {
writer.merge(pipeYamlRender(result.toUIMessageStream()));
},
});
return createUIMessageStreamResponse({ stream });
```
For multi-turn edits, pass the previous spec:
```typescript
pipeYamlRender(result.toUIMessageStream(), {
previousSpec: currentSpec,
});
```
The transform recognizes four fence types:
- `yaml-spec` — Full spec, parsed progressively line-by-line
- `yaml-edit` — Partial YAML deep-merged with current spec (RFC 7396)
- `yaml-patch` — RFC 6902 JSON Patch lines; applied to the working spec, so later `yaml-edit` fences see them
- `diff` — Unified diff applied to serialized spec
## Streaming Parser (Low-Level)
```typescript
import { createYamlStreamCompiler } from "@json-render/yaml";
const compiler = createYamlStreamCompiler<Spec>();
// Feed chunks as they arrive from any source
const { result, newPatches } = compiler.push("root: main\n");
compiler.push("elements:\n main:\n type: Card\n");
// Flush remaining data at end of stream
const { result: final } = compiler.flush();
// Reset for next stream (optionally with initial state)
compiler.reset({ root: "main", elements: {} });
```
Methods: `push(chunk)`, `flush()`, `getResult()`, `getPatches()`, `reset(initial?)`
## Edit Modes (from @json-render/core)
The YAML package uses the universal edit mode system from core:
```typescript
import { buildEditInstructions, buildEditUserPrompt } from "@json-render/core";
import type { EditMode } from "@json-render/core";
// Generate edit instructions for YAML format
const instructions = buildEditInstructions({ modes: ["merge", "patch"] }, "yaml");
// Build user prompt with current spec context
const userPrompt = buildEditUserPrompt({
prompt: "Change the title to Dashboard",
currentSpec: spec,
config: { modes: ["merge"] },
format: "yaml",
serializer: (s) => yamlStringify(s, { indent: 2 }).trimEnd(),
});
```
## Fence Constants
For custom parsing, use the exported constants:
```typescript
import {
YAML_SPEC_FENCE, // "```yaml-spec"
YAML_EDIT_FENCE, // "```yaml-edit"
YAML_PATCH_FENCE, // "```yaml-patch"
DIFF_FENCE, // "```diff"
FENCE_CLOSE, // "```"
} from "@json-render/yaml";
```
## Key Exports
| Export | Description |
|--------|-------------|
| `yamlPrompt` | Generate YAML system prompt from catalog |
| `createYamlTransform` | AI SDK TransformStream for YAML fences |
| `pipeYamlRender` | Convenience pipe wrapper (replaces `pipeJsonRender`) |
| `createYamlStreamCompiler` | Streaming YAML parser with patch emission |
| `YAML_SPEC_FENCE` | Fence constant for yaml-spec |
| `YAML_EDIT_FENCE` | Fence constant for yaml-edit |
| `YAML_PATCH_FENCE` | Fence constant for yaml-patch |
| `DIFF_FENCE` | Fence constant for diff |
| `FENCE_CLOSE` | Fence close constant |
| `diffToPatches` | Re-export: object diff to JSON Patch |
| `deepMergeSpec` | Re-export: RFC 7396 deep merge |
© vercel-labs · Apache-2.0 · vercel-labs/json-render