character-touch-lab

Community@xinsong854/character-touch-lab
Community skill — not reviewed. It was shared by 安诺涅 and has not been checked by Neta. Read SKILL.md below before letting an agent use it.
Use it in Cohub

Paste this into your agent's chat — it fetches the skill and follows it.

Use the skill: character-touch-lab. Run `npx -y @neta-art/neta-search-cli@latest skills use @xinsong854/character-touch-lab --via site` and follow what it prints. Read its complete output, redirecting it to a temporary file first if necessary, and resolve relative paths from the skill directory it prints.
Install from a terminal
npx -y @neta-art/neta-search-cli@latest skills use @xinsong854/character-touch-lab
Summary

Turn one of your characters into a squishy toy you can pet, poke and squeeze right in the browser.

  • You get a published web page with one character standing on a little pedestal, ready to be pressed, dragged, poked and tugged.
  • The body dents under your finger and bounces back with a jelly wobble. Hats and bows squish along with it.
  • Each body part reacts differently, and the character speaks short lines in its own voice. Each line is marked as quoted or newly written.
  • Gentle, short strokes fill a five-heart mood meter and make the eyes happy. Rough squeezing lowers it, and the character asks for a softer touch.
  • Pick a bird, a fluffy ball or a paper-cut creature look. Works best for a character with a clear personality and signature accessories.
SKILL.md
# Character Touch Lab

Turn one character into a touchable web toy: a procedurally built or simple-mesh body standing on a pedestal, soft-body deformation under the finger (press dents, drag stretches, release bounces), distinct reactions per body part, procedural sound, and a trust/mood meter that rewards gentle short strokes and ignores rough handling. The user leaves with a published web Work they can pet in the browser.

Read this file fully before generating anything or writing files. Resolve relative paths from this skill's directory.

## Language

Reply in the user's language, whatever language this file is in. This holds for every message of the run, above all the final handover; translate what the scripts print, don't paste it. Text the user sees in the deliverable — Work title, page title, buttons, labels, captions — follows the user's language; text the user typed stays as they wrote it.

## When to use / when not

Use when the user wants one character, creature or prop they can touch, pet, squish, poke or shake in the browser — a "touch booth", squishy toy, petting station or stress-relief toy.

Not for chat or voice interaction with a character (that is create-roleplay / companion-onboarding), not for a full room or diorama the character lives in (that is a room skill), not for a dress-up or paper-doll page. If asked for those, say this skill makes a touchable toy and stop.

## Inputs

| Item | Required | Counts as given when |
|---|---|---|
| Character | yes | the user names a character of this world, or links/points at a portrait; "make one for everyone" does not count |
| Body plan | no — default `bird` | one of `bird`, `blob`, `creature` (see references/body-plans.md); infer from the character's look when the user does not say |
| Reaction text source | no — default write in-character lines from the material | the user points at existing quotes/voice lines to reuse, or says "no dialogue" (then the toy stays sound-only) |

If the character is missing: ask once, in one message, before building — then stop. If everything is given, do not ask anything and do not wait for a go-ahead: build through to delivery.

## How it works (what the agent must keep)

The touch engine has three layers. Read `references/engine.md` for the full spec and copy `templates/` as the starting point — do not write the physics from scratch.

1. **Soft-body deformation shader.** One shared vertex-shader deform pass on every part of the toy (body, head, accessories — hats and bows must squish *with* the body, never stay rigid). Inputs: up to N press slots (position + radius + current offset), global squash, shear, head yaw/roll, lift. Presses are radial bumps `Σ offset · exp(-d²/r²)` around press centers.
2. **Gestures.** Pointer down on the toy = grab (raycast the pickable meshes, disable camera orbit). Move = drag along the camera-facing plane at the grab point. Release = spring back with a slight overshoot ("jelly wobble"). Distinguish: gentle stroke (short distance, low speed) vs pinch/pull vs quick tap (short press, no move) vs press-and-hold. Sliding too far past the body slips the grab with a squeak and re-grabs at the new point.
3. **Mood/trust.** Only gentle, short-amplitude strokes raise mood (movement delta per frame under a threshold, total drag under ~0.45 body units). Hard squeezes and long presses leave the deformation but *lower* mood; the character politely asks for a gentler hand rather than suffering. Long-idle gives one soft check-in line, never a needy loop. Show mood as 5 hearts; over ~55 the eyes switch to happy arcs and hearts particle.

Reaction lines: one small line-bank per event (touch / part taps / squeeze / release / trust / idle / greeting), 2–4 lines each, written in the character's own voice from their material — temperament first, not generic cute-pet stock. Tag each line as quoted-from-source or newly written; show the tag in the UI. Never pet-speak ("master", purring) unless the character actually talks that way.

## Steps

1. Read the character: `node /mods/neta/neta atom list` → `atom get <id>` (or the linked portrait). Extract temperament, speech register, signature accessories. → note them in `$RUN/brief.md`.
2. Choose a body plan (see `references/body-plans.md`): `bird` (implicit-surface blob + head sphere, hat/bow/rose accessories), `blob` (fur-shell ball with two eyes), `creature` (2D SVG paper-cut with bone-chain rocking). Copy `templates/` to `$RUN/site/` and adapt the build.
3. Write the line-bank `site/assets/dialogue.js` (event → lines with tags and source refs), in the character's voice, in the user's language.
4. Build the page: three.js (vendored or CDN), MeshToon materials, gradient map, canvas grain texture, outline by back-face hull. Full spec: `references/engine.md`.
5. Check: `node scripts/check.mjs $RUN/site` — verifies dialogue events cover the required keys, no raw `alert`, locale dictionary present, index.html parses; writes `$RUN/qa.json`. Exit non-zero on failure.
6. Register and publish: see Deliver.

`$RUN` = `_runs/character-touch-lab/<timestamp>/` under the workspace root for intermediate files. If the user asks for outputs elsewhere, pass that folder to the scripts; never move the run folder afterwards.

## Deliver

A **web Work**.

- `node /mods/neta/neta work init web works/webs/<slug> --title "<title in the user's language>"` → build into that folder → `node /mods/neta/neta work publish web works/webs/<slug> --title "<same title>"`.
- Before handing over, check the core content: the toy deforms on press and springs back on release, every dialogue event key has at least one line, mood hearts react to gentle strokes, no untagged dialogue.

Then, as the last step — the run is not delivered until it is done:

7. **Hand over with a card.** One `interaction-components` link card on its own line, target `{ "type": "work", "workId": "<id>" }`, the id taken from the publish output (fallback: `cohubWorkId` in `works/webs/<slug>/meta.json`). Never a made-up id, a folder or a `world-file` link to `index.html`. Then one or two lines on what it is, in the user's language.

## Out of scope

- Do not change world settings or delete files that existed before the run.
- Do not modify memory, character cards, installed scripts, existing Works or roleplays.
- Make only the touch-booth Work asked for; do not act on your own next-step suggestions.
- No model generation of any kind in this skill: the toy is procedural geometry + canvas textures. If the user wants a portrait-based mesh, that is a different skill.

## When to stop

- Missing character: ask once, then stop.
- The character's material is too thin to voice (no temperament, no lines anywhere): build the toy sound-only and say so in the handover — do not invent a personality.
- WebGL unavailable in the target context: still deliver the SVG paper-cut plan (`creature`), which needs no WebGL.

## Gotchas

- Register your own pointerdown handler **before** constructing OrbitControls, or the camera eats the grab event.
- Springs need fixed small substeps (cap the frame dt, step physics at ≤ 1/120 s) or low frame rates make the body explode.
- The pick ray must subtract the lift offset — deformation lives in the shader, so geometry under the finger is not where the mesh data says it is.
- Hats/accessories must share the deform uniforms; a rigid hat floating over a squashed body reads as broken.
- `navigator.vibrate` is a nice-to-have; guard it, it is missing on desktop Safari.
- Dialogue boxes must not re-show the same line twice in a row; keep a last-index map per event.