open-design/docs/codex-pets.md
Zakaria a46764fb1b
Some checks failed
ci / Validate workspace (push) Has been cancelled
landing-page-ci / Validate landing page (push) Has been cancelled
landing-page-deploy / Deploy landing page (push) Has been cancelled
github-metrics / Generate repository metrics SVG (push) Has been cancelled
first-commit
2026-05-04 14:58:14 -04:00

3.6 KiB

Codex pets

The pet companion in the web app can adopt pets packaged by the upstream Codex hatch-pet skill. This doc explains where those pets live, how Open Design discovers them, and what to do if you do not have Codex installed.

Where pets live

The daemon scans this directory on every list request:

${CODEX_HOME:-$HOME/.codex}/pets/<pet-id>/
  pet.json          # { id, displayName, description, spritesheetPath }
  spritesheet.webp  # 1536x1872 8x9 atlas (.png / .gif also accepted)

CODEX_HOME is honoured if set; otherwise the daemon falls back to ~/.codex/pets/. Both paths follow the upstream Codex conventions.

The scan is implemented in apps/daemon/src/codex-pets.ts and surfaced through GET /api/codex-pets (list) and GET /api/codex-pets/:id/spritesheet (raw bytes). The web pet settings panel calls these endpoints from apps/web/src/components/pet/PetSettings.tsx under the "Recently hatched" section.

I do not have Codex installed

You do not need Codex to use Open Design. The pet companion ships with built-in pets that work out of the box. The "Recently hatched" section will simply stay empty until something appears under ${CODEX_HOME:-$HOME/.codex}/pets/.

You have three ways to populate it without running Codex:

  1. Sync the public catalogs. Run node --experimental-strip-types scripts/sync-community-pets.ts (see the script header for flags). It downloads pets from the community catalogs into the canonical Codex layout, then they show up under "Recently hatched" on the next refresh.
  2. Drop a pet folder in by hand. Create ~/.codex/pets/<your-pet>/ with a pet.json and a spritesheet.webp (8x9 atlas). The daemon does not require Codex to be installed — it only needs the directory.
  3. Run the vendored skill in any chat agent. The hatch-pet skill is vendored under skills/hatch-pet/. Any agent that can execute skills (Codex, or any other) can run it end-to-end and write into the same directory.

If ~/.codex/pets/ does not exist, the daemon does not auto-create it — empty list is returned and the UI shows "no recently hatched pets yet". Creating the directory is intentionally an explicit user step so the daemon never writes outside OD_DATA_DIR / project-owned paths without a user opting in.

Manifest shape

The pet.json manifest is read defensively — every field is treated as optional and validated as a string before use. The shape we honour:

{
  "id": "shiba-pomegranate",
  "displayName": "Shiba Pom",
  "description": "Friendly pixel-art shiba.",
  "spritesheetPath": "spritesheet.webp"
}

Notes:

  • The folder name is the on-disk identity. The list endpoint reports the sanitised folder name as the public id so that /api/codex-pets/:id/spritesheet can resolve it directly even when manifest.id differs from the folder name (e.g. the manifest declares spaces or punctuation that get sanitised away).
  • spritesheetPath is resolved relative to the pet folder and is rejected if it would escape the folder. If unset, we fall back to spritesheet.webp, then .png, then .gif.
  • Any field that is not a non-empty string is ignored and the UI falls back to a sensible default (folder name → display name, empty description, etc.).
  • Daemon registry + manifest validation: apps/daemon/src/codex-pets.ts
  • HTTP routes (list + spritesheet): apps/daemon/src/server.ts
  • Web list / adopt UI: apps/web/src/components/pet/PetSettings.tsx
  • Shared response types: packages/contracts/src/api/registry.ts
  • Vendored skill source: skills/hatch-pet/
  • Community catalog sync script: scripts/sync-community-pets.ts