Skip to content
| Marketplace
Sign in
Visual Studio Code>Other>Codex PetNew to Visual Studio Code? Get it now.
Codex Pet

Codex Pet

DinohouseDigitalLLC

|
41 installs
| (0) | Free
A sprite-sheet pet that walks around a VS Code panel, similar to vscode-pets.
Installation
Launch VS Code Quick Open (Ctrl+P), paste the following command, and press enter.
Copied to clipboard
More Info

Codex Pet

A minimal VS Code extension, in the spirit of vscode-pets, that plays a Codex pet sprite sheet in its own Activity Bar side panel.

Status

Loads any pet that follows the Codex v2 pet spec (pet.json + spritesheet.webp) from the bundled pets/<pet-id>/ folder, plus any pet dropped into the user pets folder (see Codex Pet: Open Pets Folder below) — that folder lives outside the extension install directory, so pets you add there survive extension updates/reinstalls. Multiple pets can be present at once — pick which one loads via command or setting (see below). A user pet with the same id as a bundled one takes precedence. If no pet is found, or its spritesheet fails to load, the pet renders as a placeholder blob so the movement/animation logic is still visible.

Commands

  • Codex Pet: Reveal Pet View (codexPet.start) — opens/focuses the Activity Bar view. The pet(s) shown are resolved from codexPet.selectedPets (if non-empty), then codexPet.selectedPet, then the last pet(s) picked via "Choose Pets...", or the only pet if there's just one. If none of those resolve and multiple pets exist, prompts with a picker.
  • Codex Pet: Choose Pets... (codexPet.choosePets) — shows a multi-select picker and switches the view to the chosen pet(s) immediately, remembering the choice for next time. How many you can select at once is gated by your highest-level pet: 1 pet slot by default, a 2nd unlocks at level 5, a 3rd at level 15, a 4th at level 30 — locked slots are shown in the picker (🔒) so the next unlock is visible before it's reachable. codexPet.choosePet still works as an alias for this command.
  • Codex Pet: Open Pets Folder (codexPet.openPetsFolder) — reveals your persistent user pets folder in Finder/Explorer (creating it if needed), so you can drop in a new pet folder that survives extension updates.
  • Codex Pet: Install Claude Code Hooks... (codexPet.installClaudeCodeHooks) — adds the hooks described below to ~/.claude/settings.json (with a confirmation dialog first). Safe to re-run: it only adds hooks that aren't already there, and never touches unrelated hooks you've configured.

Reacting to Claude Code activity

If claude-code is listed in codexPet.aiActivitySources (it is by default), the pet plays a "busy" animation (the review sprite state) with a small speech bubble while Claude Code is actively working, and returns to normal idle/walk behavior once it's done. The bubble shows what it's doing when available — the current tool name (e.g. "Bash", "Edit") during tool use, or "Thinking" while a prompt is being processed.

Separately, whenever one or more Claude Code sessions need something from you — finished responding and waiting on a prompt, or blocked on a permission dialog — a small red count badge appears on the pet; hovering it shows which session(s) are waiting, labeled with the session's first prompt (truncated to 60 chars) if available, falling back to the workspace folder name otherwise — there's no real "chat title" to read from Claude Code, so the first prompt is the closest stand-in.

This works by watching per-session status files under ~/.codex-pet/sessions/ (one JSON file per session, e.g. claude-code-<session-id>.json, containing { "source", "state": "busy" | "waiting", "updatedAt": <ms>, "label": <string | null>, "cwd": <string | null>, "title": <string | null> }). A busy status older than 30s is treated as stale and ignored, so a crashed session can't leave the pet stuck animating. A waiting status can sit for much longer before being dropped (default 4 hours, via codexPet.waitingStaleMinutes) since a session can legitimately wait on a human for a long time — this timeout only exists to eventually clean up sessions that crashed after finishing a response but before ending.

Claude Code reports into these files via its hooks mechanism. The first time the extension activates with hooks missing, it offers to install them for you; you can also trigger this anytime via Codex Pet: Install Claude Code Hooks..., or do it by hand by adding to ~/.claude/settings.json:

{
  "hooks": {
    "PreToolUse": [{ "hooks": [{ "type": "command", "command": "~/.codex-pet/report-status.sh claude-code busy" }] }],
    "UserPromptSubmit": [{ "hooks": [{ "type": "command", "command": "~/.codex-pet/report-status.sh claude-code busy Thinking" }] }],
    "Notification": [{ "hooks": [{ "type": "command", "command": "~/.codex-pet/report-status.sh claude-code waiting" }] }],
    "Stop": [{ "hooks": [{ "type": "command", "command": "~/.codex-pet/report-status.sh claude-code waiting" }] }],
    "SessionEnd": [{ "hooks": [{ "type": "command", "command": "~/.codex-pet/report-status.sh claude-code end" }] }]
  }
}

report-status.sh itself is (re)written to ~/.codex-pet/ by the extension on every activation, so it's always present once the extension has run once — the hooks above just need to call it. Claude Code pipes the hook's JSON payload (which includes session_id, cwd, and for PreToolUse, tool_name; for UserPromptSubmit, prompt) on stdin; the script picks those up automatically to key each session's file and label the bubble, unless an explicit label is passed as a third argument (as UserPromptSubmit does with Thinking). The first UserPromptSubmit's prompt text is kept as that session's title from then on, ignoring later prompts, so the waiting badge's tooltip stays stable across a conversation. end (SessionEnd) deletes that session's file instead of writing a state.

If you installed hooks before this per-session tracking landed, re-run Codex Pet: Install Claude Code Hooks... — the old Stop/SessionEnd commands (which reported idle) will be recognized as missing and the current ones added alongside them; remove the stale idle lines from ~/.claude/settings.json by hand afterward.

Reacting to GitHub Copilot activity (experimental)

GitHub Copilot Chat has no hooks/lifecycle mechanism like Claude Code's, and VS Code doesn't yet expose a public API for observing Copilot Chat request status (microsoft/vscode#310951 is open but unshipped). So instead of a real signal, adding copilot to codexPet.aiActivitySources (off by default) uses a heuristic: bursts of large or multi-part text-document edits look more like an agent streaming changes than someone typing key-by-key, so the extension treats those as "busy" and reports it into ~/.codex-pet/sessions/copilot-copilot.json (same status-file protocol as Claude Code above, with a fixed "Copilot" label). Copilot has no equivalent of Claude Code's Stop hook, so it never reports waiting — only busy, cleared back to nothing once the edit burst quiets down.

This is a guess, not a real signal — it can also fire on pastes, snippet expansion, formatters, find/replace, or other bulk edits from any source, not just Copilot. Enable it if you want a rough "something is editing a lot" indicator; leave it off if false positives bother you.

Adding a pet

Drop a folder under either the bundled pets/<pet-id>/ (repo-only, ships with the extension) or, for pets that should stick around across updates, the folder opened by Codex Pet: Open Pets Folder. Each pet folder needs:

  • pet.json — { "id", "displayName", "description", "spritesheetPath", "kind" }
  • the spritesheet file it points to (typically spritesheet.webp)

Then run Codex Pet: Choose Pet... to pick it up — no reload or code changes needed, the folders are scanned fresh each time a pet is resolved.

Settings

Setting Default Description
codexPet.location panel Where the pet view shows: panel (bottom, next to Terminal), sidebar (Activity Bar, next to Explorer/Git), or both (each location runs its own independent pet).
codexPet.selectedPet "" Pet id or folder name under pets/ to always load. Empty = last picked pet. Ignored when selectedPets is non-empty.
codexPet.selectedPets [] Pet ids/folder names to show at once, in draw order. Takes precedence over selectedPet. Capped by your unlocked slot count (see "Choose Pets..." above); extra entries are ignored.
codexPet.walkSpeed 40 Pixels/second while running.
codexPet.moveChance 0.5 Probability (0-1) of starting a move vs. a stationary animation each cycle.
codexPet.minActionDuration 1500 Minimum ms spent in one action before picking a new one.
codexPet.maxActionDuration 3500 Maximum ms spent in one action before picking a new one.
codexPet.idleAnimationSpeed 1 Speed multiplier for stationary idle animations (idle, wave, jump, waiting, review, failed). Doesn't affect walk/run.
codexPet.aiActivitySources ["claude-code"] Which AI tools trigger the busy animation + speech bubble: claude-code, copilot (experimental heuristic), both, or empty to disable. See below.
codexPet.waitingStaleMinutes 240 (4h) How long (minutes) a Claude Code session can sit in the "waiting for you" state before its badge entry is dropped as stale (crash cleanup only — doesn't affect normal waiting).
codexPet.xpEnabled true Whether the pet earns XP/levels from coding activity (AI tool activity, editor edits, terminal use, git commits, clicks). Progress (and level) is tracked separately per pet.
codexPet.petGrowthEnabled false Whether the pet's sprite size grows with its level, from petGrowthMinScale at level 1 up to petGrowthMaxScale at petGrowthMaxLevel. Both are multipliers of codexPet.petScale. Requires xpEnabled.
codexPet.petGrowthMinScale 0.7 Size multiplier at level 1, when growth is enabled.
codexPet.petGrowthMaxScale 1.5 Size multiplier at petGrowthMaxLevel, when growth is enabled.
codexPet.petGrowthMaxLevel 20 Level at which the pet reaches petGrowthMaxScale. Growth is linear from level 1, then caps.

Timing settings (walkSpeed, moveChance, min/maxActionDuration) apply live to an already-open view — no reload needed. Changing selectedPet swaps the pet in the open view immediately too.

Sprite sheet layout (Codex v2 pet spec)

Every Codex pet spritesheet is a fixed 1536×1872px, 8-column × 9-row grid of 192×208px cells, magenta (#ff00ff) color-keyed background, one row per animation state:

Row State
0 idle
1 running right
2 running left
3 waving
4 jumping
5 failed
6 waiting
7 running
8 review

(Grid size and row order per codexpets.org.) The official Codex app owns frame timing/sequencing itself — pet packages only ship the manifest and image. Since this extension is its own renderer, that same grid geometry plus our own per-row frame counts/fps/loop live in media/sprite-config.json (shared across all pets, not per-pet). Per-row frame counts aren't part of the published spec, so those were eyeballed from the bundled sample sheets under pets/ (e.g. pets/hoggie/spritesheet.webp) — double check them against a pet's spritesheet if an animation looks like it's looping into a blank/magenta frame.

Current behavior

  • Every minActionDuration-maxActionDuration ms, randomly either starts moving (using the runRight/runLeft row for the chosen direction) or plays a stationary animation picked from idleStates (idle, wave, jump, waiting, review, failed).

  • While moving, walks across the bottom of the view and reverses direction at the edges.

  • Clicking the pet interrupts whatever it's doing and plays a random animation from reactionStates (wave, jump by default, configurable in media/sprite-config.json) for a fixed ~1.2s, with a small heart particle popping up as feedback, then resumes normal idle/walk behavior.

  • While the cursor is anywhere over the view, every shown pet runs toward it horizontally instead of wandering randomly, queuing up side by side rather than stacking, and settles into idle once it's underneath. If the cursor stops roughly above a pet, that pet jumps to try to reach it (on its own ~1.2s cooldown so it doesn't jump nonstop). Moving the cursor off the view resumes normal random idle/walk behavior for all of them.

  • Each pet earns XP (and levels shown as a small badge on its sprite) from active coding: a git commit is a flat one-off bonus to every shown pet, and clicking a pet gives it a small rate-limited bonus. Active-minute XP (AI-tool activity, editor edits, terminal use) is a shared pool across however many pets are shown — it grows sublinearly with pet count (showing more pets earns more total XP, but not proportionally more) and splits with catch-up weighting so a lower-level pet in the group gets a bigger share. Leveling up plays a jump + heart celebration. Progress persists per pet across restarts and updates; disable with codexPet.xpEnabled. Optionally (codexPet.petGrowthEnabled, off by default), the pet's sprite size grows with its level too, from a smaller starting size up to 1.5x the configured scale — and once a pet reaches codexPet.petGrowthMaxLevel, it gets a golden badge outline and a slow sparkle aura, so leveling further still has a visible payoff after size growth caps out.

  • On top of the active-minute pool, a few multipliers reward showing up regularly and sticking around, all additive and applied before the per-pet split:

    • Daily streak: +10% per consecutive weekday (Mon–Fri) you're active, capping at +100% on day 10. Weekends don't advance or break it — it's neutral, not required and not penalized. Missing a single weekday is forgiven (e.g. active Thu, off Fri, active Mon → streak intact); missing two weekdays in a row resets it.
    • Session streak: +10% per 30 continuous active minutes in one sitting, capping at +100% at 5 hours. A gap of up to 30 minutes just pauses the clock (it doesn't reset); a gap over 90 minutes resets it to zero.
    • Weekend bonus: flat +20% for any active minute on Sat/Sun.
    • Late-night bonus: flat +20% for any active minute between 10pm and 6am local time, any day.

    These stack freely (no combined ceiling) — commit XP and click XP are unaffected either way.

Privacy & Security

Codex Pet makes no network requests — no analytics, telemetry, or third-party services, and no runtime dependencies at all. Everything it does stays on your machine:

  • AI activity tracking (see above) only reads event metadata — tool names, timestamps, and the first ~20 characters of your first prompt per session (kept as a stable label for the waiting-badge tooltip). It never reads file contents, git commit messages/diffs, or terminal output.
  • Status files for in-progress AI sessions live at ~/.codex-pet/sessions/*.json and are deleted when a session ends (or after the configured staleness window).
  • XP/level/streak progress is stored in this extension's own VS Code global storage (xp.json, streak.json), plus a couple of small flags in VS Code's globalState (last-selected pet(s), whether you've dismissed the hooks-install prompt).
  • Claude Code hooks: installing them (via the command, or the one-time prompt on activation) edits ~/.claude/settings.json to add a few lines that shell out to ~/.codex-pet/report-status.sh. That script is written to disk by the extension but only ever executed by Claude Code's own hook mechanism, never by the extension itself — and nothing is installed without your explicit confirmation in the dialog first.
  • The extension never spawns subprocesses or execs external commands itself.

To remove all of Codex Pet's data, delete ~/.codex-pet/ and uninstall the extension (VS Code cleans up its own global storage automatically).

Development

See docs/DEVELOPMENT.md for building and running from source, and packaging/installing a local .vsix.

Not implemented (see vscode-pets for reference if you want these later)

  • Multiple simultaneous pets shown at once (one at a time for now)
  • Persisting pet position/state across window reloads
  • Sound effects, click-to-interact, throw-ball
  • Reacting to Codex CLI activity (Claude Code is wired up via real hooks, and Copilot has an experimental heuristic — see the sections above). waiting/failed are still just triggered randomly for variety.
  • Contact us
  • Jobs
  • Privacy
  • Manage cookies
  • Terms of use
  • Trademarks
© 2026 Microsoft