OpenPets is a native macOS desktop pet for visible agent progress, review prompts, completion states, and lightweight animations across local coding tools.
It gives Codex Pets a shared home outside one assistant. The menu bar app, MCP server, CLI, and apps built with OpenPetsKit can all talk to the same local pet, so Codex, Claude Code, Cursor, OpenCode, Pi CLI, generic MCP clients, local apps, and scripts can report work through one visible desktop companion.
openpets-low.mp4
This repository is the desktop app, CLI, MCP server, assistant setup, and release packaging project. If you are embedding OpenPets in your own Swift app, use OpenPetsKit, the separate Swift package for the embeddable runtime and client APIs.
Install OpenPets from the latest GitHub release.
Download the app from the latest release and move it to Applications. OpenPets requires macOS 14 or later.
After installing the app, launch OpenPets from Applications. The menu bar app can wake the bundled Starcorn pet, start the local MCP server, copy the MCP URL, open the config folder, and stop the pet.
The default MCP endpoint is:
http://127.0.0.1:3001/mcp
Configure your assistant or MCP client with that endpoint. Once connected, agents can call OpenPets tools to wake the pet, show task state, update threaded messages, and play lightweight animations.
Add the recommended assistant instructions so the assistant uses the desktop pet consistently. See docs/ai-assistants for setup guidance covering OpenCode, Claude Code, Cursor, Pi CLI, and generic MCP clients.
- Show task progress, completion, review, waiting, and failure states through a visible desktop companion.
- Let multiple local tools share one pet instead of each app owning a separate status UI.
- Send notifications and animations from an MCP client, a Swift app, or CLI scripts.
- Run the bundled Starcorn pet or install custom Codex Pets using an 8x9 sprite atlas.
- Define plugin surfaces through host-owned pet-matched cloud hotspots.
- Use action URLs on notifications for lightweight follow-up flows.
OpenPets ships first-party plugins as built-in app features while the external plugin runtime is still being designed. Official plugins use the same host-owned cloud hotspot surface: a small pet-matched cloud with an SF Symbol icon, a compact value, and optional click details. Use the menu bar app's Plugins submenu to enable or disable built-in plugins.
Current official plugins:
- Battery: shows macOS battery percentage, plugged/unplugged state, time remaining or time to full when available, a Battery Settings action, and low-battery or charging pet reactions.
- Claude Code: shows separate
5hand7dquota clouds with reset time and pace details. If Claude Code is configured but usage data is missing, OpenPets shows a muted setup cloud that links to setup docs. - Codex Usage: reads Codex usage from ChatGPT's local auth token, then shows separate usage clouds for available rate-limit windows.
Plugin support is currently built-in and pull-request based. External plugin install, separate plugin repositories, sandboxed subprocess execution, and plugin update UX are planned but not shipped yet.
- Plugin ecosystem for assistant and local tool behaviors.
- Catalog of apps and agents using OpenPets.
- Pet catalog and gallery improvements for discovering and installing compatible pet bundles.
- Easier assistant onboarding for Codex, Claude Code, Cursor, OpenCode, Pi CLI, and generic MCP clients.
- Richer task states with action buttons and shared task workflows.
- Continued focus on one shared local desktop companion across multiple tools.
OpenPets exposes local MCP tools from the menu bar app:
| Tool | Purpose |
|---|---|
get_openpets_status |
Read MCP server, pet, socket, and config status. |
wake_pet |
Start or bring back the desktop pet. |
stop_pet |
Stop the desktop pet. |
notify |
Show or update a threaded message bubble with a status-driven animation. |
play_pet_animation |
Play an animation without showing text. |
stop_pet_animation |
Return the pet to idle without stopping it or clearing messages. |
clear_pet_message |
Clear one message bubble by threadId. |
ping_pet |
Confirm the pet process can receive commands. |
Valid notification statuses are running, review, done, failed, waiting, and message.
The shared pet can show multiple task bubbles at once. A notify call returns a threadId; pass that ID back on later updates to replace the same task bubble instead of creating a new one.
See Shared Pet System for the default socket topology, MCP behavior, threadId workflow, and guidance for app integrations.
Swift apps should use OpenPetsKit, the separate Swift package for embedding OpenPets. It contains the embeddable runtime, client APIs, and bundled Starcorn pet with minimal dependencies.
In Xcode, add OpenPetsKit as a package dependency:
https://github.com/alterhq/OpenPetsKit.git
In a Package.swift file, add OpenPetsKit to dependencies:
.package(url: "https://github.com/alterhq/OpenPetsKit.git", from: "0.1.0")Then add the library product to the target that should send pet commands:
.target(
name: "YourApp",
dependencies: [
.product(name: "OpenPetsKit", package: "OpenPetsKit")
]
)Import the module and send commands through the shared local pet socket:
import OpenPetsKit
let client = OpenPetsClient()
let response = try client.send(.notify(PetNotification(
title: "Build Passed",
text: "All tests completed.",
status: "done"
)))
print(response.threadId ?? "")Source builds require Swift 6.0 or later and Xcode command line tools.
From a local checkout, build the package:
cd openpets
swift buildRun the test suite:
swift testStart the menu bar app from source:
swift run openpets-menubarBuild optimized executables:
swift build -c releaseThe release binaries are written under .build/release/. Release packaging is handled by scripts/package-release.sh.
See CONTRIBUTING.md for contributor setup, workflow, and pull request guidance.
OpenPets creates a JSON config file at:
~/.config/openpets/config.json
If XDG_CONFIG_HOME is set, OpenPets uses:
$XDG_CONFIG_HOME/openpets/config.json
Default configuration:
{
"display": {
"messageAreaHeight": 56,
"scale": 0.42
},
"mcpEndpoint": "/mcp",
"mcpHost": "127.0.0.1",
"mcpPort": 3001,
"socketPath": "/tmp/openpets-UID.sock"
}Settings:
display.scale: Sprite display scale.display.messageAreaHeight: Reserved height for the message bubble area.socketPath: Unix socket used by the CLI and pet host.mcpHost: HTTP bind host for the MCP server.mcpPort: HTTP port for the MCP server.mcpEndpoint: HTTP path for the MCP endpoint.
By default, the MCP server only listens on 127.0.0.1. Binding to 0.0.0.0, ::, or an empty host can expose the MCP server to other devices on your network. Only do this on trusted networks.
Pet window positions are stored in:
~/.config/openpets/positions.json
Installed pets are stored in:
~/Library/Application Support/OpenPets/Pets/
OpenPets also discovers valid pet bundles from these user locations:
~/.codex/pets/
~/.local/share/openpets/pets/
~/.config/openpets/pets/
~/.config/openpets/Pets/
~/.config/openpets/
If XDG_DATA_HOME is set, OpenPets checks $XDG_DATA_HOME/openpets/pets/ instead of ~/.local/share/openpets/pets/.
OpenPets includes a V1 cloud-surface contract for plugins. Plugins provide semantic icon/value data plus optional detail rows; OpenPets resolves placement into host-owned hotspot slots and renders pet-matched gradient cloud hotspots. Plugins do not choose absolute screen positions or custom renderers.
Plugin support is currently built-in and pull-request based. External plugin install, separate plugin repositories, sandboxed subprocess execution, and plugin update UX are planned but not shipped yet. The built-in battery, Claude Code, and Codex Usage plugins are the first-party reference implementations.
See Plugin Cloud Surfaces for update payloads and placement rules.
OpenPets uses the Codex Pets format. A pet bundle is a directory containing a pet.json manifest and a spritesheet.
Example:
my-pet/
pet.json
spritesheet.webp
Manifest format:
{
"id": "my-pet",
"displayName": "My Pet",
"description": "A short description.",
"spritesheetPath": "spritesheet.webp"
}Spritesheets are expected to use an 8 column by 9 row atlas. The current animation rows are:
| Row | Animation |
|---|---|
| 0 | idle |
| 1 | running-right |
| 2 | running-left |
| 3 | waving |
| 4 | jumping |
| 5 | failed |
| 6 | waiting |
| 7 | running |
| 8 | review |
The spritesheet width must be divisible by 8 and the height must be divisible by 9.
The CLI is available for scripts, manual checks, and local development. For AI assistants, prefer the MCP endpoint above.
To install the CLI shim, choose Install CLI from the paw menu. This creates ~/.local/bin/openpets; add ~/.local/bin to PATH if your shell does not already include it.
Run a pet from a pet bundle directory:
openpets run --pet /path/to/starcornSend a notification to a running pet:
openpets notify --title "Build Passed" --status done --text "All tests completed."The command prints a threadId. Pass it back with --thread to replace that task's bubble instead of creating a new one:
openpets notify --thread THREAD_ID --title "Build Passed" --status done --text "All tests completed."Play an animation:
openpets animate waving --onceStop the current animation and return the pet to idle without clearing messages:
openpets stop-animationCheck connectivity:
openpets pingClear one message bubble or stop the pet process:
openpets clear --thread THREAD_ID
openpets stopAvailable animations are idle, running-right, running-left, waving, jumping, failed, waiting, running, and review.
OpenPets is intended to run locally. Be careful when enabling network access for the MCP server or passing URLs to notifications. Please report security issues privately to the maintainers.
OpenPets is released under the MIT License. See LICENSE for details.