Basic Cohub abilities. Most agents already have these mounted; listed here for reference.
Platform Published by the Neta team.
Official Made by the Neta team.
Verified Reviewed by the Neta team.
Community Shared by a Cohub user. Not reviewed — read SKILL.md before you use it.
character-phone
Verified@xixi/character-phone
With improvements from @baize
Use it in Cohub
Paste this into your agent's chat — it fetches the skill and follows it.
Use the skill: character-phone. Run `npx -y @neta-art/neta-search-cli@latest skills use @xixi/character-phone --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.
npx -y @neta-art/neta-search-cli@latest skills use @xixi/character-phone
Summary
Turn one character's phone into a playable screen players unlock and explore.
Builds a full phone: lock screen, chats, calls, photos, notes, and calendar, all from one character's story
Every contact is someone from your world, and each one replies to players in character, knowing only what they'd really know
Pick the chat app's look: WeChat, WhatsApp, Telegram, LINE, Discord, or X style messaging
Works best for a character with a rich cast around them and a specific night or moment to set the scene
Players sign in and chat using their own credits, so you don't pay for the conversations they have
Improvements from other creators
baize@baize1 adopted suggestion
SKILL.md
# Character Phone
You build **one character's phone** as a Web Work. The player picks it up, unlocks it and goes through it: chats,
calls, photos, notes and calendar all tell the same story. They can message the people in it, and each person
answers as themselves, knowing only what that person would know.
Everything visual and interactive is already built. Your job is **content**: read the world, decide whose phone
and which moment, cast the contacts, write the data file and personas, make the images, and check it. The engine
renders fourteen apps and six chat skins from one file, `data/phone.js`.
**You produce:** one published phone Work (a link), its `data/phone.js` and its `assets/` images.
**You check:** `check.mjs` ends ok, `qa.mjs` ends ok, and you have looked at every screenshot it saves.
`<skill>` below is this skill's folder, `.agents/skills/character-phone`, or the folder `skills use` reports if the
skill lives elsewhere. `<slug>` is the Work's folder name under `works/webs/`. Commands run from the world root.
```
SKILL.md this workflow
CHANGELOG.md what changed in each version
references/ read the one you need, when you need it
world-reading.md canon first: sources, cast ledger, timeline, empty / non-modern / IP worlds
cast-and-personas.md who is in the phone, how they are saved, persona prompts that stay in character
data-schema.md every field of data/phone.js, app by app
content-craft.md making the phone feel lived-in: threads across apps, hooks, secrets, sizes
skins.md WeChat · WhatsApp · Telegram · LINE · Discord · X, and other apps → nearest skin
images.md image plan, the style line, prompts, framing, scripts/assets.mjs
publish-and-gate.md sign-in gate, scopes, publish, the cover, what to tell the creator, troubleshooting
scripts/ world-scan · new-phone · assets · check · persona-test · qa · cover (Node ≥ 18)
template/ the engine copied into every phone (do not edit per phone; data goes in data/)
examples/xixi/phone.js full example: zh · WeChat · 24 photos · 7 personas (an original character)
examples/watson/phone.js compact example: en · WhatsApp · no generated images · modern AU of a classic
tests/ node --test: engine, examples, scaffold, checks, directory rules
vendor/studio-login-gate/ the Neta sign-in gate (from the studio-login-gate skill), installed into every phone
```
## Rules that do not bend
1. **Canon first.** Everything the world says about the owner and the cast is used as given; names and relations
stay exactly as written. You invent only what the world leaves open (a shop, a teacher, a delivery
station, yesterday's chat), and the invented details never contradict canon. Keep a short ledger of
canon vs invented while you work. See `references/world-reading.md`.
2. **Each contact knows only what they would know.** A shopkeeper knows the owner as a customer. Only the
closest people know the secrets. Write each persona's knowledge from *their* side.
3. **One consistent "now".** Within the moment the creator chose (step 2), pick one date and time for the phone. Every timestamp, unread badge, weather, calendar
entry and "today" is consistent with it.
4. **The gate is always on.** Every phone opens behind the Neta sign-in gate. Players use their own credits for
AI replies, and the Work's publisher scopes stay `[]`. `new-phone.mjs` installs it. Never remove it, add a
bypass, or put a model key anywhere.
5. **Minors.** If the owner is, or looks like, a child or teen, set `minor: true`. Every persona then gets a
safety line, and no persona flirts with the owner. Decide this from canon; don't ask.
6. **Offstage.** Talk to the creator about their world and the phone, not about files, scripts or URLs on
cohub.live. Hand over the finished Work with the `interaction-components` skill. Talk to the creator in the
language they write in — every progress note, question and the final hand-over, from the first turn to the
last — even though this skill is written in English. Names and lines quoted from the phone stay as they are
in the data. If the creator asks for a specific language for replies or the hand-over, that request wins.
7. **The world's settings are the creator's.** Read `world/WORLD.md` and the materials; never edit them.
In particular never replace the world's `visualStyle` (step 6). Everything this skill writes lives in the
phone's own Work folder.
8. **No credentials, nothing sent out.** The scripts run offline and never read, print or send a token, key or
account detail, and nothing in this skill needs one. Real AI replies happen only inside the published Work,
on each player's own credits.
## Workflow
### 1 · Read the world
```bash
node <skill>/scripts/world-scan.mjs . # digest: config, materials, mention graph, works
node <skill>/scripts/world-scan.mjs . --focus "<name>" # full cards of one character and everyone tied to them
```
Read the full cards of the likely owners and their circle. Build the **cast ledger**: each person, how they relate
to each candidate owner, what they know, how they talk, and the source line. If the world is empty, or the
character lives elsewhere (a nieta.art OC link, an uploaded file, a known IP), follow
`references/world-reading.md`. Don't invent a cast for a character you haven't read.
### 2 · One question round
Use the `questionnaire` skill (one consolidated round) unless the ask already settles these. **Whose phone**,
**the moment** and (in a non-modern world) **AU or in-world device** each change the whole phone if guessed
wrong, so you never pick them yourself: when the ask leaves only one of them open, ask that one as a short chat
question with 2–3 concrete options, and stop until the creator answers. Writing `data/phone.js` or generating
any image before they are settled is a failed run. The skin and the image budget have defaults; they never
need a question on their own.
- **Whose phone.** Offer the 2–4 characters with the richest ties, and say in a few words what each phone would hold.
- **Chat app skin.** Default by the world's language: Chinese → WeChat, Japanese → LINE, English → WhatsApp.
Offer the others: Telegram, Discord (fits a guild, server or online friend group), X (DMs plus a public life).
Map any other app to the nearest skin (`references/skins.md`).
- **The moment.** A canon scene ("the night before the duel"), right after a known event, or a quiet ordinary
night. This sets "now" and what everyone is waiting for. It counts as given only when the ask names a time,
event or scene; "make X's phone" alone does not give it, even when the owner, skin, contacts and images are
all named. Offer 2–3 moments from the owner's canon (one line each: when, and what is unresolved that night).
- **Only if the world is not modern:** a modern-day AU (same people and relations, today's phone), or an in-world
device with the apps renamed (a crystal, a ledger, a spirit board). See `references/world-reading.md`.
- **Images:** none (avatars become initials and photos are in-page screenshots), light (~8: wallpaper,
key avatars, a few photos), or full (~20–30). More images cost the creator more generation credits.
Things you decide yourself: the phone's language (from the world; it sets the phone's content and interface, not
the language you talk to the creator in), cast size, the apps and how they look.
### 3 · Plan the phone (in your head or a scratch file outside the Work folder)
- **Contacts** = the owner's canon ties + the people their life implies (`references/cast-and-personas.md`):
family, school or work, the shop they always go to, a delivery station, a doctor, a landlord, a group chat or
two, a couple of service accounts, one wrong number or scam text. Most phones have 6–10 people who can answer
and 10–20 entries in total.
- **3–5 threads** that run across apps. The same fact shows up in a chat, the calendar, a note and a photo, and
something is unresolved *tonight*. Plus one deeper layer: a locked note, a recently deleted photo, a draft
never sent, an unanswered voicemail (`references/content-craft.md`).
- **Passcode** that the world explains (a canon date or number), with a hint the player can work out.
### 4 · Scaffold
```bash
node /mods/neta/neta work init web works/webs/<slug> --title "<Name>'s Phone"
node <skill>/scripts/new-phone.mjs works/webs/<slug> --lang zh|en --skin wechat|whatsapp|telegram|line|discord|x
```
This copies the engine, writes a starter `data/phone.js`, installs the gate, and sets `cohubWorkScopes: []`.
Re-run with `--update` any time to refresh engine files. `data/` and `assets/` are never touched.
### 5 · Write `data/phone.js`
Replace the starter completely. The schema is in `references/data-schema.md`. The quality bar is
`examples/xixi/phone.js`; for a non-Chinese phone, also look at `examples/watson/phone.js`. Write the personas
with `references/cast-and-personas.md`. Validate early, before any images exist:
```bash
node <skill>/scripts/check.mjs works/webs/<slug> --no-assets
```
### 6 · Images (skip for the "none" budget)
Read the `generate` skill before generating anything. The world's `visualStyle` (`world/WORLD.md`) is the
creator's setting: **use it as it is and never replace it.** It may be a style-library object, a style id or
the creator's own words; `assets.mjs --style` reads all three. Only when the field is empty do you fill it, the
platform way. Never run `neta config set … --field visualStyle` on a world that already has one, not even to
make a script pass — if `--style` fails on a set field, that is a bug in this skill; write the style line by
hand from the field instead.
The platform does not add that style to your prompts, so every prompt ends with the line this command prints:
```bash
node <skill>/scripts/assets.mjs --style # the Style line for every prompt
node <skill>/scripts/assets.mjs works/webs/<slug> --needed # what the data still lacks
node /mods/neta/neta generate image --prompt "<scene text>. <the Style line>" --work-title "<Name>'s photos · <id>"
node <skill>/scripts/assets.mjs works/webs/<slug> img <id> "<Name>'s photos · <id>" # or av / stk; source = title, work id or path
```
A small subject in an avatar can be framed tighter: `av <id> <source> --zoom 1.6 --focus 62,40`. Prompts,
framing and consistency rules are in `references/images.md`.
### 7 · Check, test, look
```bash
node <skill>/scripts/check.mjs works/webs/<slug> # must end ok:true — fix every ✖
node <skill>/scripts/persona-test.mjs works/webs/<slug> --all --prompt # read what each contact is told
node <skill>/scripts/persona-test.mjs works/webs/<slug> <id> --say "…" # the request that contact would get
node <skill>/scripts/qa.mjs works/webs/<slug> --deep --skins all # screenshots, then read the sheets
```
`qa.mjs` runs a temporary copy with a mock gate, so no sign-in and no credits are used, and the Work folder is
never modified. It walks sleep → lock → wrong and right passcode → home → leaving an app by the home indicator
(the home screen must stay in place while the app closes, nothing may linger — not even a photo viewer — and
every home icon must have its tile) → going back inside an app (a tap on the back chevron, back mid-slide,
re-opening mid-slide, a drag from the left edge: the top page must end in place and the pages under it out of
sight, nothing half-way) → every app → a chat round-trip with a mock AI → reload (history must persist) → a
cleared browser on the same account (history must come back from the player's private space —
`persistedAcrossDevices`). `--deep` adds the viewer, the locked note, the hidden album (the passcode must open
exactly the photos listed in the data file, and the library must show none of them), call, voicemail, profile,
article, transfer, feed, web page, screen time and anniversary. `--skins all` adds every tab of all six skins.
Open the contact sheets it prints and look at every screen: empty panels, overflowing text, wrong dates, a
contact who knows too much.
Real replies come from the published Work. After publishing, play one contact yourself; it uses your own credits.
### 8 · Publish, cover and hand over
```bash
node /mods/neta/neta work publish web works/webs/<slug>
```
The cover that publishing makes is the sign-in card. Replace it with the lock screen (`references/publish-and-gate.md`,
"The cover"). Then tell the creator, in a sentence or two of world voice and in the language they write in: whose phone it is, what's waiting on it
tonight, and that anyone who opens it signs in with Neta and chats on their own credits. Hand over the Work with
`interaction-components`, and close with the `next-steps` skill if it's available (e.g. another character's
phone, the same phone a week later, a roleplay with one of the contacts).
### 9 · Later changes
Edit `data/phone.js` → `check.mjs` → `qa.mjs` → publish again. Players keep their own chat history per account,
in their own private space, on any device; **Settings → General → Transfer or Reset** clears it for a player.
When you tell the creator, say it plainly: the first visit asks for one consent and creates a private space for the
phone's records (named "<title> · My space" on English phones); later visits reuse it and the conversations are all
there, on any device.
## Quality bar (check before you call it done)
- The lock screen hooks in five seconds: 3–5 notifications that make you want to unlock.
- Every app has real content tied to the owner. No placeholder text, and no app is empty unless that is a choice
(hide it with `apps.hide`).
- Facts agree across apps: dates, names, amounts, who knows what.
- Each persona sounds unmistakably like that person in two lines, refuses to know what they shouldn't, and treats
a stranger holding the phone the way that person would.
- Going home from any app is instant and the home screen is sharp and in place the whole time: only the app
moves (a compositor-only zoom into its icon); the home screen never zooms, dims, blurs or hides.
- Going back inside an app always lands: the page stack is the truth and every move settles to it, on the
animation's end or a timer. Moves animate transform and opacity only — never `filter` (some browsers leave a
filter animation frozen on its first frame: a page parked half-way, a home screen left blurred) — and an
engine watchdog finishes any animation that outlives its end. Keep it that way when you extend the engine. The wallpaper
is exported at full resolution (`assets.mjs` does it; `check.mjs` warns below 1300 px).
- The hidden album opens only with the passcode, shows exactly its photos, and the library shows none of them.
- The Work's cover is the lock screen (`thumbnail.source` is `manual`), not the sign-in card.
- `check.mjs` is ok:true, `qa.mjs` is ok:true, and you have looked at every screenshot.
## Maintaining this skill
`node --test <skill>/tests/` covers the engine, interface strings, examples, scaffold, checks and the directory
rules (name, description, files, no secret-looking text, no credential use). `node --test <skill>/vendor/studio-login-gate/tests/`
covers the gate. Run `qa.mjs` on both examples after any engine change. Record each version in `CHANGELOG.md`, and
bump `template/VERSION.json` whenever the package changes.
## Credits
The sign-in gate is the `studio-login-gate` skill (vendored in `vendor/studio-login-gate/`). If a newer
`studio-login-gate` is installed in the world, `new-phone.mjs` and `check.mjs` use that one instead.