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.
mini-world
Officialneta-search/mini-world
Use it in Cohub
Paste this into your agent's chat — it fetches the skill and follows it.
Use the skill: mini-world. Run `npx -y @neta-art/neta-search-cli@latest skills use neta-search/mini-world --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 neta-search/mini-world
Summary
A tiny planet your characters can explore, zoomed from globe to walkable ground with forests, deserts and oceans.
Zoom from a whole little planet down to walking on its surface, with forest, desert and ocean areas named the way you asked.
Walk, swim automatically in the ocean, and drag objects from a model library onto the ground to decorate the world.
Collect hidden wonders scattered around the planet into a discovery book as you explore.
Day turns to night and weather shifts between sunny, cloudy, rainy and snowy, changing the sky, fog and light.
Anyone can open and play it right away with no login; works best for worlds with a cosy, adventurous cast of characters and places.
SKILL.md
# Mini World
A Mini World is a **small spherical planet you can hold and walk on**. Zoomed out
it reads as a globe; zoomed in it becomes walkable surface with distinct regions
(forest, desert, ocean). Movement, camera, placement, weather, and asset
generation all live on the sphere — nothing is flat.
This skill is the **production contract AND a runnable template**. The verified
runtime lives in `templates/runtime/`; scripts live in `scripts/`; the rules that
must hold on every build are below.
Resolve every relative path from this skill directory. Nothing here depends on a
particular Space, account, credential, or artwork — copy the template into a new
`works/web/<slug>/` and re-point the Cohub work id (see `references/cohub-runtime.md`).
## Contract
### When to pick it
The user wants a child-friendly spherical 3D exploration world — a small planet you zoom from globe to surface, with distinct regions, automatic swimming, placeable objects, a generated-component library, time & weather and discovery collecting — or wants to add / fix camera, facing, placement, weather or generated-component features in one.
### Stop when the pick is wrong
A flat (non-spherical) scene, a non-exploration web page, or a generic 3D asset-authoring job is not this skill. A world that must log in to browse / play / place violates the guest-first contract — this skill never does that.
### No intake questionnaire — build straight from the request
This skill **does not ask an opening round**, however open the request is ("make a little planet for
this world" is enough). Do not run the `questionnaire` skill and do not ask setup questions in chat
before building: take the world's own characters and places, the regions the request names (else
the template's), the default
tone (cosy discovery), the default time & weather, and decide the rest yourself. Name those choices in
one clause when you hand over the Work — the creator changes them afterwards, on a world that already
plays. The only stops are the hard ones under "Stop when input is missing".
### Input
Required: none beyond the intent — the verified runtime lives in `templates/runtime/` and is copied into a new `works/web/<slug>/`. Nothing here is a reason to ask (see "No intake questionnaire").
Optional: a roster of placeable objects, Blender-authored asset packs, time / weather defaults.
### Transform
(no opening questions) → copy `templates/runtime/` → set the Cohub work id in `cohub-runtime.js` → build / extend per the non-negotiable rules (sphere math, input interaction, asset architecture, guest-first auth, persistence, time & weather) → run `scripts/verify.mjs` on the Work folder (deterministic + Playwright suites, report saved in the Work) → publish the static folder.
### Deliver
A browser-playable static Work published to a Cohub public share, opened from the Work page so `space.id` is available for generation; a changelog entry for every published version; the URL, folder, verification result and known limitations; the Work itself handed over as an `interaction-components` work card (see Output / delivery).
### Explicitly not doing
Any login (or Cohub request) for opening, playing, browsing the library, placing objects, changing weather or local saves; a fixed part-count on generated components; making terrain / ocean / wonder-beacon placeable; treating `localStorage` as a remote save; shipping a GLB without a primitive / procedural fallback.
### Stop when input is missing
No browser / Playwright available for the required suites. Generation access denied with no guest fallback path (guest play must keep working and the error must be recoverable). A template copy without a re-pointed Cohub work id.
## Cases
### should
「做一个可缩放、能游泳、能放置模型的小星球探索世界。」
Expect: this skill — no opening questions; the spherical runtime, guest-first, deterministic + browser suites run, published with a changelog entry, the defaults it chose named in the handoff.
### shouldNot
「做一个平面的 2D 地图页面。」
Expect: not this skill — flat, not a spherical exploration world.
### missing
"Publish this world." (no browser / Playwright to run the required suites)
Expect: stop; the deterministic and Playwright suites must pass before delivery.
### theme
「只要森林和雪原两个区域,天气默认下雪。」
Expect: same skill — regions on the sphere plus a weather default; guest-first still holds.
## Start here
1. Copy `templates/runtime/` into `works/web/<slug>/`.
2. Set the Cohub work id / broker origin in `cohub-runtime.js`.
3. Build / extend per the rules below.
4. Run the self-check with this skill's script on the Work folder — see
"Verification" for the exact command, pass mark and report file.
5. Publish the static folder; keep a changelog entry per published version.
6. Hand over the Work card (see "Output / delivery") — next-steps options do not
replace it.
## Core experience (non-negotiable)
- The world is a **sphere** (`R = 24`): `world-math.js` gives `terrain()`, `walk()`,
`tangent()`, `transport()`, continents, `PLACES`, and 12 `WONDERS`.
- Moving walks along the surface via `walk(normal, direction, distance)`; the
explorer's "up" is always the local surface normal.
- Zoom spans **whole planet ⇄ ground**. The camera **anchors on the explorer's
current surface point** — moving the explorer and then zooming must keep the
explorer as the focus (no drift).
- **Swimming is automatic** when the explorer enters ocean terrain.
- **Named regions are the whole region list.** When the request names regions, the
region nav (`.destination` buttons), `labels` and region heading list exactly those,
in that number, each labelled with the request's own wording in full — in the
visible button caption and heading, not a shorter canon name and not only in
`title`/`aria-label`. Give each its own land kind in `world-math.js` (continents, `PLACES`,
adding or retiring kinds to match the count). The ocean stays as unnamed,
swimmable base water: unless the request names a water region, delete its nav button
and its `labels` key — never invent a name for it or add it as an extra region.
- Collecting wonders fills a persistent discovery book.
## Input interaction contract (these were real bugs — do not regress)
- **Mouse drag**: zoomed OUT → orbit the planet; zoomed IN → steer the explorer.
Wheel / pinch zoom always stays anchored on the explorer.
- **WASD / arrows** follow the explorer's current facing.
- **Facing**: forward moves face forward, back faces backward, left/right and all
four diagonals are consistent; joystick and tap-to-walk also face the travel
direction. (`tests/facing-browser.mjs` asserts this.)
- **Space ALWAYS jumps**, even when a HUD button (sound, zoom, map, back, pause,
changelog, delete) currently has focus, and it must NOT activate that button.
Intercept both `keydown` and `keyup`. Long-press must not repeat-jump. A focused
text input still types spaces normally.
- Touch: joystick, drag-to-look, pinch-zoom, tap-to-walk, large child-friendly
action buttons.
- **Mobile header**: on narrow viewports the top action buttons must wrap onto
their own row and **never overlap** each other or the zoom rail. (The shipped
build had `#weather` absolutely positioned on top of `#components`; the
`components-browser` suite catches it by asserting the button is clickable.)
## Asset architecture
- A catalog with **stable model ids** (`model-catalog.js`, 25 built-ins) and
reusable prototypes; the explorer and environment are registered once.
- **Placeable objects** are separate instances, aligned to the surface (upright,
base at local ground `y=0`), persisted with a stable id + surface normal,
selectable, and removable. Global terrain / ocean / wonder-beacon are NOT
placeable and must throw `/cannot be placed/`.
- **Generated components** (`generated-components.js`) are validated before they
enter the catalog: whitelisted primitives (`ball cone cylinder box rock gem
ring`), hex colors, bounded position/scale/rotation, and a **1 MB** total payload
cap. **Do not impose a fixed part-count** — let the model choose complexity for
the request.
- Generated components land in the catalog, are searchable, export to Three.js
JSON, and can be dragged onto the planet.
## Auth contract (guest-first — the most important rule)
- **Opening, playing, browsing the asset library, placing objects, changing
weather, and local saves must NEVER trigger login or any Cohub request.**
- Auth is obtained **only** when the user submits a generated component; that is
exactly **one** authorization flow (`generation-access.js` / `auth-gate.js`).
- If the viewer denies, keep guest play fully working and show a recoverable
error on the generation form. Never re-prompt from a timer, page load,
asset-library open, weather change, placement, or normal gameplay.
- Guest state is cached in `localStorage` and must not claim to be saved remotely.
## Persistence
- `world-persistence.js` writes `.neta/mini-world/state.json` in the Cohub World:
generated component definitions, placements, and climate.
- Startup prefers the world file; `localStorage` is an **offline fallback** only.
- Remote writes happen only when generation access is active; 401/403 revokes it.
- Caps: 20 components, 60 placements.
## Time & weather
- `climate.js` / `weather.js`: a flowing clock (morning → day → dusk → night) and
modes **Auto, Sunny, Cloudy, Rainy, Snowy**.
- Weather drives sky color, fog color/distance, sun color/brightness, ambient
light, sea tint, clouds, and rain/snow particles.
- **Particles follow the explorer's current surface normal**, not the world
origin. Weather fog must NOT hide the planet when zoomed out.
- "Save to world" persists `clockHours`, `weatherSelection`, `timeRunning`.
## Blender asset packs (high-complexity authored assets)
When a world needs detail beyond primitives, author it in Blender:
1. Create `blender/build_assets.py` in the Work source; keep a reproducible
`.blend` source plus a `.glb` game asset under `blender/out/`.
2. Run it headless through this skill's launcher (handles the sandbox's missing
`libSM.so.6` / `libICE.so.6` and Blender's `4.5/scripts` tree without root):
```bash
cd <work>/blender
<skill>/scripts/blender-headless.sh --python build_assets.py
```
3. Named objects/materials, clean transforms, applied scale, origin at the asset
base, reasonable mesh density; export glTF 2.0, Y-up, selected objects only.
4. Copy GLB into the Work's `assets/` and load with Three.js `GLTFLoader`.
5. **Always keep a primitive/procedural fallback** if the GLB fails to load.
See `references/blender-pipeline.md`.
## Verification (must pass before delivery)
**The self-check is this skill's script, run on the Work folder you will publish** —
not a hand-rolled loop over the suites, not a copy in `/tmp`:
```bash
cd works/web/<slug> && mkdir -p qa && set -o pipefail && \
node <skill>/scripts/verify.mjs . --serve --regions "<name 1>|<name 2>|…" 2>&1 | tee qa/verify-report.txt
```
`--regions` takes the region names exactly as the request wrote them (omit it only
when the request names none); it fails unless the region nav has exactly that many
buttons and each name appears in full in one button's visible text.
- **Pass** = exit code 0 and the report ends with `N/N checks passed` and
`mini-world verification OK`. Anything else is not verified: fix the build (or
update the Work's own `tests/` where you deliberately renamed regions, counts or
labels) and re-run the same command until it passes.
- If `playwright` does not resolve from the Work folder, link a `node_modules` that
has it before running, and remove the link before publishing.
- Re-run it after the last code change before the final publish; the report at
`works/web/<slug>/qa/verify-report.txt` is what you cite as the verification result.
What the suites cover — deterministic (no browser):
- `node --test templates/runtime/tests/*.test.mjs` — land regions stay distinct and
swimmable water exists; every wonder sits in its named region; walking preserves the
sphere; weather modes/clock resolve correctly; 22 placeable types + forbidden
ids throw; models sit upright with base at ground without mutating prototypes.
Browser (Playwright):
- **Guest path**: open, browse library, place + delete, save weather, reload —
**zero** `api.cohub` / `gateway.cohub` / `work-auth` requests, zero popups.
- **Auth path**: submitting generation triggers context + authorize, and
**nothing more**; denial keeps play working and the button re-enabled.
- Camera: orbit out / steer in / wheel zoom anchored to explorer.
- Facing consistency across regions and diagonals; space-jump focus regression.
- Modal layouts at desktop + 3 mobile widths; **no console errors**.
## Output / delivery
- A browser-playable static Work published to a Cohub public share, opened from
the Work page so `space.id` is available for generation.
- A changelog entry for **every** published version.
- Report URL, folder, verification result, and known limitations plainly.
- **Hand the Work over as a card, not only in prose.** In the final reply — before any
next-steps options, which never stand in for it — load the
`interaction-components` skill and put one `link` card on its own line pointing at
the published Work itself: `"target": { "type": "work", "workId": "<cohubWorkId>" }`,
where `<cohubWorkId>` is the UUID from this turn's `neta work publish web <work-dir>`
result (`data.cohubRegisterTask.data.cohubWorkId`), or — if that field is not echoed —
the `cohubWorkId` written into `<work-dir>/meta.json` by that publish. **The slug /
folder name is not a Work id** and opens nothing. Set the card's `fallback` to the
Work's name plus `data.previewUrl` from that same result. Never link the Work as a
`world-file` (`index.html`) or as an `external-url`, and never invent the id — if
publish did not return `ok: true` and a `cohubWorkId`, it is not delivered yet. If you
published more than one folder, the card points at the one you are handing over.