Skip to content

Latest commit

 

History

History
122 lines (101 loc) · 7.05 KB

File metadata and controls

122 lines (101 loc) · 7.05 KB

AGENTS.md — Agent Pets

Entry point for AI coding agents (Codex et al.). Read this first, then the handoff + follow-ups docs linked at the bottom.

What this is

A native macOS menu-bar app: animated pixel "pets" that sit on your screen and react to your coding agent's state (idle / coding / researching / waiting / done / blocked / error / long-running). Driven by Claude Code / Codex hooks, an HTTP API, an MCP server, and a CLI. SwiftPM + AppKit + SwiftUI, macOS 14+, zero external dependencies.

Build / run / test

swift build                         # build all targets
swift test                          # 192 tests, 0 failures (the green baseline)
./scripts/verify_runtime_assets.sh  # "runtime assets verified" + "verified 12 roster creatures"
git diff --check                    # must be clean
python3 scripts/test_slice_sprites.py   # sprite slicer self-test (needs Pillow)

# Run the app for live testing. NOTE: ./script/build_and_run.sh --verify is FLAKY in
# headless/asleep-display envs (the `open -n` bundle launch sometimes never binds the port).
# The bare binary binds reliably:
nohup .build/debug/AgentPets >/tmp/agentpets.log 2>&1 &
#   poll: lsof -nP -iTCP:47771 -sTCP:LISTEN
.build/debug/agent-pets spawn --id d1 --name Demo --state coding --appearance fox
.build/debug/agent-pets remove d1 ; pkill -x AgentPets

The local HTTP API listens on 127.0.0.1:47771 (GET/POST /v1/pets, .../state, .../appearance, .../end, DELETE /v1/pets/<id>, POST /v1/layout/lineup, /v1/demo).

Targets

  • AgentPetsCore — pure logic (models, config resolution, stores, hooks, MCP planning). The only unit-tested target (Tests/AgentPetsCoreTests, @testable import AgentPetsCore).
  • AgentPets — the macOS app (AppKit/SwiftUI overlay, dashboard, services). Executable target — NOT covered by the test target. Verify app code with swift build + the runtime/screenshot checks, not XCTest.
  • AgentPetsCLI (agent-pets) — CLI + hook driver.
  • AgentPetsMCP (agent-pets-mcp) — stdio MCP server (set_status, set_pet).

HARD INVARIANTS — do not regress

  • Overlay rendering is fragile and hard-won. Do NOT change SpriteFrameView windowing, PetPanelMetrics (panel 128 > sprite 72), or PetView centering. Per-pet scale is a SwiftUI .scaleEffect clamped to 0.7–1.6 (SessionStore.scaleRange). If you touch overlay rendering: rebuild, spawn pets at scale extremes across done/waiting/error/coding, screencapture -x, confirm full bodies / no clipping BEFORE committing.
  • Sprite manifests are state-keyed and SQUARE. Each Resources/Pets/<id>/manifest.json maps all 8 AgentPetState raw values → {file, frames, fps, loop}; frameWidth == frameHeight (SpriteFrameView windows square cells). verify_runtime_assets.sh enforces this.
  • API stays back-compat. appearanceId is a free string; unknown/legacy ids coerce to the default via PetAppearance.resolved(for:). New model fields decode-if-present with safe defaults. Hook driver always exits 0.
  • SessionStore is a plain class, not ObservableObject. UI bridges via the .agentPetsStoreChanged NotificationCenter signal (same path the HTTP API uses).
  • Atomic conventional commits ending with the trailer: Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> (swap to your own attribution as appropriate). Keep swift test green per commit. Branch for feature work; do not commit to main without intent.

Adding a pet sprite (the data-driven roster)

Roster = Sources/AgentPetsCore/Resources/roster.json (metadata) + per-creature folders Sources/AgentPets/Resources/Pets/<id>/. To add one: download a CC0 source into downloads/ (gitignored), write scripts/sprite_recipes/<id>.json, run python3 scripts/slice_sprites.py scripts/sprite_recipes/<id>.json, add a .copy("Resources/Pets/<id>") to Package.swift, add the roster.json entry + a CREDITS.md row, then verify + swift test. Full procedure + gotchas: docs/superpowers/agent-pets-working-handoff.md → "Pet Roster & Sprites".

Read next

  • docs/superpowers/2026-06-07-codex-handoff.md — full orientation + repo map for picking this up.
  • docs/superpowers/2026-06-07-followups.md — prioritized backlog + every known caveat.
  • docs/superpowers/agent-pets-working-handoff.md — running handoff (dashboard + roster details).
  • docs/superpowers/agent-pets-progress-tracker.md — milestone status.

AgentPets Village (standalone browser game)

Game/ contains AgentPets Village, a self-contained Animal Crossing-inspired browser game (plain HTML5/JS, zero dependencies, no build step) that reuses the CC0 creature sprites as its villager cast. It is fully independent of the Swift targets — nothing in Package.swift references it, and it must stay launchable on its own (./Game/play.sh or opening Game/index.html).

  • Verify with node --test "Game/tests/*.test.mjs" (logic suite + headless boot smoke test; needs Node 18+). Keep this green like swift test.
  • Pure logic lives in Game/js/village.*.js (browser VG namespace + CommonJS exports for the tests); browser-only code in Game/js/engine.*.js, ui.js, main.js. Classic scripts only — no ES modules, so file:// keeps working.
  • Game/assets/pets/ is a copy of Sources/AgentPets/Resources/Pets/ (plus Game/js/sprites.data.js, generated from the manifests). If roster art changes, refresh the copies.
  • Saves are versioned localStorage JSON merged over fresh defaults (village.state.js deserialize) — add new fields with safe defaults, never break old saves.

AgentPets Village 2 + Burrow engine (Game2/)

Game2/ is a Cargo workspace: burrow (a from-scratch 2D engine, zero crate dependencies, targets wasm32-unknown-unknown through a hand-rolled extern "C" ABI with zero wasm imports) and village2 (the comprehensive Animal Crossing-inspired game). The JS host is Game2/web/host.js. The v1 JS game in Game/ stays playable and untouched.

  • Verify with cd Game2 && cargo test (73 native tests) and node --test "Game2/tests-node/*.test.mjs" (headless sessions driving the actual wasm — Node can instantiate it because the ABI imports nothing). Keep both green.
  • Build/ship with Game2/build.sh: regenerates sprite tables (tools/gen_sprites.py — keeps game/src/data/sprites_gen.rs and web/sprites.host.js in lockstep with the Game/assets/pets manifests), compiles release wasm, base64-embeds it into web/game.wasm.js (so file:// works), and syncs sprite assets. The generated web/game.wasm.js IS committed so a clone plays with no toolchain — rerun build.sh and commit it after Rust changes.
  • ABI invariants (engine/src/platform.rs + web/host.js must agree): draw commands are 12 f32s; Sfx repr(u32) ids match host's SFX table; key codes match Button::from_code and host KEY_CODES. Saves are versioned JSON in localStorage key agentpets-village2-save, merged over defaults — never break old saves.
  • Engine code never touches browser APIs; if it can't run under cargo test, it doesn't belong in engine/ or game/.