# Texel: full documentation > Agent-first Minecraft skin creator. Skins are JSON specs (a palette plus ordered drawing operations) that compile deterministically to 64×64 PNGs, so AI agents can write, render, review and refine them. Follow the Skin Agent Protocol: brief → read → draft → render → review → patch → ship. Source: https://texel-skins.vercel.app/llms.txt --- # Skin Agent Protocol > The loop an AI agent follows to design, test and ship a Minecraft skin with Texel. Version `texel/1`. A skin is **data, not pixels**: a JSON *spec* made of a palette and an ordered list of drawing operations. The spec compiles deterministically to a 64×64 PNG. Because the source is structured, an agent can reason about it, diff it, patch one layer at a time, and verify every step. ## The loop ``` BRIEF → READ → DRAFT → RENDER → REVIEW → PATCH ──┐ ▲ │ └──────────────────────┘ … → SHIP ``` ### 1. Brief Write down what you are making before touching pixels. Put it in the spec's `description`: reviewers (you, later) compare the render against it. > "A desert ranger: tan skin, sun-bleached cloak with hood on the hat layer, leather belt with pouches, dusty boots. Classic arms." Requests can arrive in any language. Answer the person in their language and write `description` in it too (the studio shows it to them); keep palette keys and layer `id`s in plain ASCII English. Don't open with a round of questions: make tasteful choices for anything unspecified, state them in one line, and let the person steer while they watch (see *Live session*). ### 2. Read | Resource | Why | | --- | --- | | [/agent.md](https://texel-skins.vercel.app/agent.md) | This protocol, the spec reference and the art guide in **one file**. Fetch it instead of the three pages separately. | | [/docs/spec.md](https://texel-skins.vercel.app/docs/spec.md) | The format: selectors, coordinates, every op. **Required.** | | [/docs/art-guide.md](https://texel-skins.vercel.app/docs/art-guide.md) | Where eyes go, how to shade, what makes skins look good. | | [/schema/skinspec.v1.json](https://texel-skins.vercel.app/schema/skinspec.v1.json) | JSON Schema for validation / structured output. | | [/examples/index.json](https://texel-skins.vercel.app/examples/index.json) | Complete, working specs to learn from or fork. | | [/docs/api.md](https://texel-skins.vercel.app/docs/api.md) | How to render: browser, URL, WebMCP, or CLI. | ### 3. Draft 1. **Palette first.** For each material (skin, hair, shirt, pants, shoes, metal…) define a base color plus derived tones: `"shirtDark": "shirt:-10"`. 2–4 tones per material. 2. **Broad → fine.** Start with `fill` on `all` (so no base pixel is transparent), then fill whole parts, then bands (`rect` with only `y`/`h`), then shading and texture on those broad areas (`gradient`, `shade`, `noise`), then small details (`pixels`, `points`, `line`). Texture goes *before* details: `noise` and `shade` change every pixel in their area, so running them last smears eyes, collars and buttons. Later layers overwrite earlier ones, so don't fill an area you repaint completely afterwards; the review flags those layers as `overwritten-layer`. 3. **Paint one side, mirror the other.** Design `rightArm`/`rightLeg`, then `mirror` them. Add asymmetric details *after* the mirror. 4. **Use the overlay** (`@overlay`) for things that stick out: hair tufts, hoods, helmets, jackets, backpacks. 5. **Give layers `id`s** for anything you might revisit (`"id": "eyes"`), so patches are surgical. ### 4. Render Pick whichever interface your runtime has. They all run the same compiler: - **Code execution:** `curl -O https://texel-skins.vercel.app/texel.mjs && node texel.mjs build skin.json -o skin.png --sheet sheet.png`. - **MCP:** `texel_render` returns the review and the sheet image. - **Browser agent:** open `/studio/`, then call `window.texel.setSpec(spec)` (or the WebMCP tool `texel_set_spec`). - **URL only:** open `/studio/?view=inspect#spec=` and take a screenshot. #### Live session When a person is waiting on the skin, let them watch it being made instead of seeing only the end result. Start the session **before your first draft** and give them the URL: - **Code execution:** run `node texel.mjs live skin.json --open` in the background. It prints a studio URL (`/studio/?live=`); every time you save `skin.json` their tab updates. Keep using `build` for your own review. - **MCP:** call `texel_live` and share the returned URL; every `texel_render` then shows up in their tab. - **Browser agent:** work in a studio tab the person can see; `window.texel` updates it directly. They can react mid-way ("shorter hair", "more pink") and you patch, instead of starting over after the reveal. ### 5. Review Every render returns a **review**: `score` (0–100 technical health), `issues` (with `path`, `code` and a `hint`), `stats`, and a **text render** of the front and back views, so even text-only agents can see the result. Then look at it. The score only checks hygiene; it cannot tell whether the skin looks good. Screenshot `/studio/?view=inspect` (3D angles + flat sheet) or open the `--sheet` PNG and judge it against the rubric: | # | Check | Pass when | | --- | --- | --- | | R1 | Brief match | Every feature in `description` is visible. | | R2 | Face | Eyes, brows and mouth read clearly at 1× in the front view. | | R3 | Silhouette | Head, torso, arms and legs are distinguishable by color/value. | | R4 | Shading | Light comes from above: top rows lighter, bottoms and inner sides darker. | | R5 | Texture | No large perfectly flat areas (use noise jitter 2–5 or patterns). | | R6 | All sides | Back and sides are designed, not just filled. | | R7 | Depth | The overlay layer adds at least one 3D element (hair, hood, collar, gear). | | R8 | Hygiene | Review has 0 errors and 0 warnings. | ### 6. Patch Change the smallest thing that fixes the weakest rubric item, then render again. In the browser: `texel.updateLayer("eyes", { rows: [...] })`, `texel.addLayers([...])`, `texel.toggleLayer(3)`. With files: edit the JSON and rebuild. Stop when R1–R8 all pass, or after ~6 iterations with diminishing returns. ### 7. Ship Deliver three things: 1. The **share link**: `node texel.mjs share skin.json`, `texel_share` or `texel.shareURL()`. It is short (`/s/`) and opens the exact skin in the studio, where the person can also download the PNG. 2. The **PNG** (CLI `build` output, `texel_save`, or `texel.download()`), uploaded at minecraft.net or any launcher with the model (classic/slim) matching `model`. 3. The **spec JSON**, the editable source. Give the file path; paste the JSON into the chat only when you cannot save files. ### Continuing a skin Asked to change an existing skin, start from its link: `node texel.mjs pull -o skin.json` (MCP: `texel_pull`), keep a copy of the original, go live, and change only what was asked by patching the layers involved. Check with `diff` that nothing else moved, and ship a new link: links are immutable, so every version has its own. ## Contract - Compilation is deterministic: same spec → same PNG, byte for byte, in every interface. - Compilation never throws. Invalid layers are skipped and reported; valid ones still render. - Layers apply in order; later layers overwrite earlier ones (no blending). - Issue `code`s are stable identifiers you can branch on. --- # Skin spec reference > Complete reference for the Texel skin spec (`version: 1`): structure, colors, selectors, coordinates and all 13 operations. ## Shape ```json { "$schema": "/schema/skinspec.v1.json", "version": 1, "name": "Explorer", "description": "What this skin should look like (the brief).", "model": "classic", "palette": { "skin": "#d9a066", "skinShade": "skin:-8", "shirt": "#2f8f83" }, "legend": { "S": "skin", "s": "skinShade", "W": "#ffffff", "E": "#2d5ba8" }, "layers": [ { "op": "fill", "target": "all", "color": "skin" }, { "op": "fill", "target": "body", "color": "shirt" }, { "op": "pixels", "target": "head.front", "y": 4, "rows": ["SWESSEWS"] } ] } ``` | Key | Type | Notes | | --- | --- | --- | | `version` | `1` | Required. | | `model` | `"classic"` \| `"slim"` | Arm width 4px or 3px. Default `classic`. | | `palette` | object | Name → color. Names: letters, digits, `_`, `-`; start with a letter. | | `legend` | object | Single char → color, for `pixels` rows. `.` and `_` are reserved. | | `layers` | array | Operations, applied top to bottom. Required. | | `name`, `description`, `author`, `tags` | metadata | `description` is the brief. | ## Colors A color expression is one of: - `#rgb`, `#rrggbb`, `#rrggbbaa` - `transparent` - a palette key: `"shirt"` - any of the above plus `:`: shift HSL lightness by *n* points: `"shirt:-12"`, `"#88aaff:+6"` Palette entries may reference each other, which is the idiomatic way to build tone ramps: ```json "palette": { "cloth": "#7a5c3e", "clothLight": "cloth:+10", "clothDark": "cloth:-12", "clothDeep": "cloth:-24" } ``` Base-layer pixels must be opaque (Minecraft renders transparent base pixels black). Overlay pixels are either opaque or `transparent`. Avoid partial alpha. ## Model anatomy The character faces you. **`right`/`left` are the character's own sides**: `rightArm` appears on the viewer's *left* in the front view. | Part | front / back (w×h) | right / left (w×h) | top / bottom (w×h) | | --- | --- | --- | --- | | `head` | 8×8 | 8×8 | 8×8 | | `body` | 8×12 | 4×12 | 8×4 | | `rightArm`, `leftArm` (classic) | 4×12 | 4×12 | 4×4 | | `rightArm`, `leftArm` (slim) | 3×12 | 4×12 | 3×4 | | `rightLeg`, `leftLeg` | 4×12 | 4×12 | 4×4 | Every part has two layers: `base` (the body) and `overlay` (a slightly larger shell: hat, jacket, sleeves, pants). Overlay starts fully transparent. ### Face-local coordinates Each operation works in **face-local coordinates**: `(0, 0)` is the top-left pixel of the face *as seen from outside the model*. Drawing is clipped to the face, so it never bleeds into neighbours. - On `front`, x grows toward the character's left (viewer's right). - On `right`, x=0 is the back edge and the last column touches the front. - On `left`, x=0 touches the front and the last column is the back edge. - On `back`, x grows toward the character's right. - On `top`, the last row touches the front. Negative `x`/`y` count from the far edge: `"y": -2` means "the last 2 rows" when `h` is omitted. ## Selectors `target` picks one or more faces: ``` [.][@] ``` | Piece | Values | | --- | --- | | parts | `head` `body` `rightArm` `leftArm` `rightLeg` `leftLeg` · groups: `arms` `legs` `limbs` `all` | | faces | `top` `bottom` `right` `front` `left` `back` · groups: `sides` (the four vertical faces), `all` (default) | | layer | `base` (default), `overlay`, `both` | Join alternatives with `+`: `"head.top+back"`, `"arms+legs.sides"`. An array of selectors is a union. Examples: `"all"` · `"head.front"` · `"legs.sides"` · `"body.front+back@overlay"` · `"arms.top@both"`. When a selector matches several faces, the operation runs **once per face** in that face's local coordinates. `{"op":"rect","target":"legs.sides","y":-2,"color":"boots"}` paints the bottom two rows all the way around both legs. ## Area options `rect`, `clear`, `gradient`, `pattern`, `noise` and `shade` accept an optional area: `x`, `y` (default 0, negatives from the far edge), `w`, `h` (default: to the edge). Omit all four for the whole face. ## Operations Every op accepts `id` (string handle for patching), `note` (free text) and `enabled` (`false` skips it). ### fill Paint whole faces. ```json { "op": "fill", "target": "legs", "color": "pants" } ``` ### rect Paint an area. With only `y`/`h` it becomes a band. ```json { "op": "rect", "target": "body.sides", "y": 8, "h": 1, "color": "belt" } ``` ### clear Make an area transparent (overlay only, in practice). ```json { "op": "clear", "target": "head.front@overlay", "x": 1, "y": 3, "w": 6, "h": 2 } ``` ### pixels Pixel art as strings: one string per row, one char per pixel. Chars come from the op's `legend`, then the top-level `legend`. `.` keeps the existing pixel, `_` erases it. `x`/`y` offset the grid. ```json { "op": "pixels", "target": "head.front", "rows": [ "HHHHHHHH", "HhHHHhHH", "HSSSSSSH", "SDDSSDDS", "SWESSEWS", "SSSssSSS", "SSsMMsSS", "SSSSSSSS" ] } ``` ### points Individual pixels. ```json { "op": "points", "target": "body.front", "points": [[3, 8], [4, 8]], "color": "buckle" } ``` ### line Bresenham line between two points (inclusive). ```json { "op": "line", "target": "body.front@overlay", "from": [1, 0], "to": [7, 7], "color": "strap" } ``` ### gradient Linear blend `from` → `to`, `vertical` (top→bottom, default) or `horizontal`. `steps` posterizes into N bands; pixel art usually wants 3–5. ```json { "op": "gradient", "target": "legs.sides", "from": "steelLight", "to": "steelDark", "steps": 4 } ``` ### pattern Repeating pattern: `checker` (first two colors), `stripes-h`, `stripes-v`, `diagonal` (cycles all colors). `size` = cell size in px. A color of `"."` keeps the existing pixel. ```json { "op": "pattern", "target": "body", "kind": "checker", "colors": ["steel", "steelDark"] } ``` ### noise Seeded, deterministic texture. `colors` + `density` (0–1, default 0.2) scatters colors; `jitter` (0–50) randomly shifts the lightness of existing pixels by ±jitter points. Use either or both. `seed` defaults to the layer index. ```json { "op": "noise", "target": "body.sides", "jitter": 4, "seed": 3 } ``` ### shade Shift lightness of existing pixels by `amount` (−100…100). The workhorse for depth. ```json { "op": "shade", "target": "rightLeg.left+back", "amount": -7 } ``` ### copy Copy one face (`from` must select exactly one) onto target faces. `flip`: `h`, `v`, `hv`. Sizes are resampled if they differ. ```json { "op": "copy", "from": "head.right", "to": "head.left", "flip": "h" } ``` ### mirror Mirror a whole part onto another (left/right faces swap, everything flips horizontally). `layer`: `base`, `overlay`, `both` (default). ```json { "op": "mirror", "from": "rightArm", "to": "leftArm" } ``` ### symmetrize Make faces left-right symmetric by copying one half onto the other. `source`: `left` (default, low x) or `right`. ```json { "op": "symmetrize", "target": "head.front" } ``` ## Texture map (for importing / debugging) UV origin of each box in the 64×64 PNG. Within a box of size w×h×d at (u, v): top `(u+d, v)`, bottom `(u+d+w, v)`, right `(u, v+d)`, front `(u+d, v+d)`, left `(u+d+w, v+d)`, back `(u+2d+w, v+d)`. | Part | base (u, v) | overlay (u, v) | | --- | --- | --- | | head | 0, 0 | 32, 0 | | body | 16, 16 | 16, 32 | | rightArm | 40, 16 | 40, 32 | | leftArm | 32, 48 | 48, 48 | | rightLeg | 0, 16 | 0, 32 | | leftLeg | 16, 48 | 0, 48 | ## Review issue codes | Code | Level | Meaning | | --- | --- | --- | | `bad-json`, `bad-spec`, `no-layers` | error | Spec cannot be read. | | `unknown-op`, `missing-key`, `bad-selector`, `bad-color`, `unknown-char`, `bad-number`, `out-of-range`, `bad-point`, … | error | Layer skipped. | | `unknown-key`, `version`, `clipped` | warning | Ignored input / pixels outside the face. | | `base-transparent` | warning | Base pixels left transparent (render black in-game). | | `blank-face` | warning | `head.front` has fewer than 3 colors. | | `flat-surface` | info | A visible face is ≥90% one color. | | `few-colors` | info | Fewer than 6 colors overall. | | `hat-covers-face` | info | Hat layer is fully opaque over the face. | | `unused-palette` | info | Palette keys never referenced. | | `overwritten-layer` | info | A layer is completely painted over by later layers, so it does nothing. The `fill` on `all` safety net is exempt. | Score = 100 − 25 per error − 8 per warning − 2 per info (transparent-base penalty capped at 20). --- # Skin art guide > Practical pixel-art rules for 64×64 Minecraft skins, written for agents: where features go, how to shade, and the mistakes that make skins look amateur. ## The face (head.front, 8×8) The face is 8 pixels wide, so every pixel is a decision. A reliable layout: | Row | Content | | --- | --- | | 0–1 | Hair (or helmet/hat) | | 2 | Forehead, hair fringe on the edges (x=0 and x=7) | | 3 | Eyebrows (hair color or darker), optional but adds expression | | 4 | Eyes: white at x=1 and x=6, iris at x=2 and x=5 | | 5 | Cheeks; nose as 1–2 slightly darker skin pixels at x=3–4 | | 6 | Mouth: 2–4 pixels centered, a *darker skin tone*, not black | | 7 | Chin / jaw, beard if any | ``` HHHHHHHH H hair h hair highlight HhHHHhHH S skin s skin shadow HSSSSSSH D brow W eye white SDDSSDDS E iris M mouth SWESSEWS SSSssSSS SSsMMsSS SSSSSSSS ``` Rules of thumb: - Eyes 2 px wide (white + iris) read best. Iris toward the center gives a friendly look; toward the edges looks surprised. - Never outline the face in black. Contrast comes from value, not lines. - Hair should wrap: continue it on `head.top`, `head.back` and the upper/back part of `head.right` / `head.left`. ## Body landmarks | Area | Where | | --- | --- | | Collar / neckline | `body.front` rows 0–1 | | Belt | `body.sides` row 8 or 9 (1 px) | | Pants start | `body.sides` rows 9/10–11 (so the waist continues onto the legs) | | Sleeves | `arms.sides` rows 0–3 (short) or 0–9 (long) | | Hands | `arms.sides` last 2–3 rows + `arms.bottom` | | Shoes | `legs.sides` last 2–3 rows + `legs.bottom` | | Knees | `legs.front` row 5–6 | ## Shading Minecraft's lighting is flat, so skins carry their own shading. Assume light from **above and slightly in front**. 1. **Tone ramp per material:** 3 to 4 tones: highlight (+8…+12), base, shadow (−8…−12), deep (−20…−28). Define them in the palette with `:` shifts. 2. **Top-down:** lighter on top rows/`top` faces, darker toward the bottom of each part. `gradient` with `steps: 3–5`, or `shade` on the last row. 3. **Inner and back faces darker:** limbs' inner faces (`rightArm.left`, `rightLeg.left`, …) and `back` faces by −6…−10. 4. **Separate overlapping parts:** the row where sleeves end, where shirt meets pants, and where boots begin should have a 1 px shadow. 5. **Texture, not noise soup:** `noise` with `jitter` 2–5 for cloth/metal grain; 6+ looks dirty. Don't jitter faces or small details. 6. **Hue-shift shadows** for richer art: shadows slightly cooler/more saturated, highlights warmer. (Pick explicit hex tones for that instead of `:` shifts.) ## Color - 15–60 distinct colors is typical for a good skin. Fewer than 6 looks flat. - 1 dominant hue, 1–2 secondary, 1 accent (small area, high saturation: buckles, eyes, gems, lights). - Keep adjacent parts at different *values* (lightness), not just hues. Silhouettes must read in grayscale. - Avoid pure `#000000` and pure `#ffffff` in large areas. ## The overlay layer The overlay is a shell 0.5 px (head) / 0.25 px (body, limbs) outside the base. It is what makes skins feel 3D. - **Hair volume:** extend hair on `head.*@overlay` a pixel or two past the base hairline. - **Hoods / helmets:** fill `head@overlay`, then `clear` where the face should show. - **Jackets, scarves, belts with pouches, backpacks:** `body.*@overlay`. - **Cuffs, gloves, boot tops:** `arms/legs.*@overlay` bands. - Keep overlay pixels fully opaque or fully transparent. ## Workflow that works 1. `fill all` with the dominant skin/suit color (no transparent base). 2. Fill parts: head, body, arms, legs. 3. Bands: sleeves, belt, pants, shoes. 4. Head: `pixels` for the face, hair on top/back/sides (`copy` right → left with `flip: "h"`). 5. Shading and texture on the broad areas: `gradient` / `shade` / `noise`. 6. Details on one side (they stay crisp because they come after the texture); `mirror` limbs; then asymmetric details. 7. Overlay pass. 8. Review, screenshot, patch. ## Common mistakes | Mistake | Fix | | --- | --- | | Transparent base pixels | Start with `{ "op": "fill", "target": "all", "color": "…" }`. | | Mixing up left/right | `rightArm` is on the **viewer's left** in the front view. | | Arms painted 4 px wide on a slim model | Slim arm fronts are 3 px wide; use `pixels` rows of 3 chars. | | Forgetting back and sides | Check `back`, `right` and `left` views in the review. | | Black outlines everywhere | Use darker tones of the local color instead. | | `noise` / `shade` as the last layers | They also hit eyes, collars and buttons. Texture broad areas first, then paint details. | | Same value head/body/legs | Vary lightness between parts. | --- # Skin families > Generate many related skins (teams, factions, rarity tiers, colorways) from one base spec and a small set of patches. One file, dozens of consistent skins. A **family** is a document with `"kind": "family"`, a `base` skin spec, and members defined by `variants` (explicit list), a `matrix` (cartesian product of axes), or both. ```json { "version": 1, "kind": "family", "name": "Guild uniforms", "base": { "version": 1, "palette": { "primary": "#9b2f2f", "trim": "#e0a940" }, "layers": [ ... ] }, "matrix": { "guild": { "ember": { "palette": { "primary": "#9b2f2f" } }, "tide": { "palette": { "primary": "#2c5d9b" } } }, "rank": { "recruit": { "disable": ["trim"] }, "captain": { "enable": ["cape", "insignia"] } } } } ``` This expands to four members: `ember-recruit`, `ember-captain`, `tide-recruit`, `tide-captain`. See the complete [guild example](https://texel-skins.vercel.app/examples/families/guild.json). ## Variant patches Every variant (and every matrix axis value) is a patch applied to a copy of the base: | Key | Effect | | --- | --- | | `palette` | Merged over the base palette. The main way to recolor. | | `legend` | Merged over the base legend. | | `enable` | Layer ids to switch on (removes `enabled: false`). | | `disable` | Layer ids to switch off. | | `layers` | Layers appended after the base layers. | | `model` | Override `classic` / `slim`. | | `name`, `description`, `tags` | Member metadata. | Matrix patches are applied in axis order, so later axes win on conflicts. ## Designing a good family 1. **Perfect the base first.** Render it alone until it passes the rubric; every flaw is multiplied by the member count. 2. **Name colors by role, not hue.** `primary`, `secondary`, `trim`, `accent`, so variants only swap values. Derive shades from them (`"primaryDark": "primary:-12"`) and the whole ramp follows. 3. **Optional details get ids.** Capes, badges, helmets, rank stripes: add them to the base with `"enabled": false` and an `id`, then `enable` them per variant. Several layers can share one id and toggle together. 4. **Distinguishable at a glance.** Check the lineup: members should differ in value or silhouette, not just hue. 5. **Member ids** are lowercase letters, digits and `-`. Matrix ids join axis values with `-`. The limit is 256 members. ## Rendering families | Interface | How | | --- | --- | | MCP | `texel_render_family` (lineup image + score table), `texel_save_family` | | CLI | `node texel.mjs family guild.json -o skins/ --lineup lineup.png` | The **lineup** shows each member's front and back, in expansion order (variants first, then matrix combinations). --- # Install as a tool > Give any agent native Texel tools: an MCP server (with an interactive 3D viewer for MCP Apps hosts), a Claude Code plugin, and a portable Agent Skill. ## MCP server `texel-mcp.mjs` is a single file with no install step: the compiler, docs, examples, schemas and the 3D viewer are embedded. Requires Node 18+. ```bash curl -O https://texel-skins.vercel.app/texel-mcp.mjs ``` ### Claude Code ```bash claude mcp add texel --scope user -- node /absolute/path/texel-mcp.mjs ``` Files are written to the directory the server runs in. Pin it with `--env TEXEL_WORKSPACE=/path/to/skins` or the `--workspace ` flag. ### Claude Desktop, Cursor, VS Code and other clients ```json { "mcpServers": { "texel": { "command": "node", "args": ["/absolute/path/texel-mcp.mjs", "--workspace", "/absolute/path/skins"] } } } ``` ### What the server provides | Kind | Name | Purpose | | --- | --- | --- | | tool | `texel_render` | Compile + review; returns the review sheet image. Opens the 3D viewer in MCP Apps hosts. | | tool | `texel_live` | Start a live session: returns a studio URL where the person watches every `texel_render`. | | tool | `texel_share` | Short share link (`/s/`) for a spec. | | tool | `texel_pull` | The spec behind a share link, to keep developing an existing skin. | | tool | `texel_validate` | Fast error check, no images. | | tool | `texel_save` | Write `.png`, `.skin.json` and optional sheet to the workspace. | | tool | `texel_render_family` | Expand a family; lineup image + per-member scores. | | tool | `texel_save_family` | Write every member plus `lineup.png`. | | tool | `texel_import_png` | Turn an existing skin PNG into an editable spec. | | tool | `texel_diff` | Which faces a change touched, with a pixel mask. | | tool | `texel_get_example`, `texel_read_docs` | Offline examples and docs. | | resource | `texel://docs/{page}`, `texel://examples/{id}`, `texel://schema/{name}` | Same content as resources. | | resource | `ui://texel/viewer` | MCP App: interactive 3D preview with a feedback box that posts back to the chat. | | prompt | `design_skin`, `continue_skin`, `design_family`, `critique_skin` | Protocol runbooks with arguments. | All write tools are confined to the workspace directory; paths outside it are rejected. ## Claude Code plugin The repository is also a plugin marketplace. The plugin bundles the MCP server and the `minecraft-skin-design` skill: ```bash claude plugin marketplace add Brunovncs/texel claude plugin install texel@texel ``` ## Agent Skill The [`minecraft-skin-design`](https://texel-skins.vercel.app/skills/minecraft-skin-design/SKILL.md) skill follows the open Agent Skills format (a `SKILL.md` with `name` and `description` frontmatter). Copy the folder into your agent's skills directory. For Claude Code, `~/.claude/skills/minecraft-skin-design/`. It teaches the protocol and works with either the MCP tools or the CLI. --- # Agent interfaces > Four ways to render a Texel spec: browser JavaScript API, WebMCP tools, URL, and a zero-dependency Node CLI. All share the same deterministic compiler. Plus live sessions (the person watches while the agent works) and short share links. ## 1. Browser: `window.texel` Open `/studio/`. Every method is synchronous unless noted and returns plain JSON-serializable data. | Method | Returns | Notes | | --- | --- | --- | | `help()` | string | Quick reference (markdown). | | `getSpec()` | object | Current spec. | | `setSpec(spec)` | Review | Replace the spec (object or JSON string), render, return the review. | | `addLayers(layers, index?)` | Review | Insert layers (default: append). | | `updateLayer(idOrIndex, patch)` | Review | Shallow-merge `patch` into one layer. | | `removeLayer(idOrIndex)` | Review | Delete a layer. | | `toggleLayer(idOrIndex, enabled?)` | Review | Enable/disable without deleting. | | `setPalette(patch)` | Review | Merge palette entries (`null` deletes a key). | | `review()` | Review | `{ ok, score, issues, stats, ascii, next }`. | | `reviewMarkdown()` | string | Review as markdown, with text render. | | `validate(spec)` | Issue[] | Check a spec without loading it. | | `setView({ yaw, pitch, overlay, animate })` | void | Pose the 3D preview for screenshots. | | `textureDataURL()` | string | The 64×64 skin PNG as a data URL. | | `sheetDataURL()` | string | Review sheet (front, back, right, left, texture) PNG. | | `shareURL()` | Promise<string> | Short link (`/s/`) that reopens this exact spec; falls back to a long `#z=` link offline. | | `download(filename?)` | void | Save the PNG. | | `examples()` | Promise<object> | The example index. | | `loadExample(id)` | Promise<Review> | Load `explorer`, `knight`, `robot`, `astronaut`. | ```js const r = texel.setSpec(mySpec); if (!r.ok) console.log(r.issues); texel.updateLayer('eyes', { rows: ['SWESSEWS'] }); texel.setView({ yaw: -30, pitch: -10 }); // then screenshot texel.download('ranger.png'); ``` The studio also exposes stable DOM hooks: `#spec-input` (the JSON textarea), `#preview-3d`, `#review-sheet`, `#review-json` (a `