{"id":50587796,"url":"https://github.com/felipetodev/petdex-dock","last_synced_at":"2026-06-05T07:30:45.402Z","repository":{"id":355716873,"uuid":"1228358450","full_name":"felipetodev/petdex-dock","owner":"felipetodev","description":"🐾 A tiny Codex Pet living at the edge of your desktop","archived":false,"fork":false,"pushed_at":"2026-05-04T22:42:38.000Z","size":1655,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-05-05T00:26:40.766Z","etag":null,"topics":["codex","codex-pets","electron"],"latest_commit_sha":null,"homepage":"","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/felipetodev.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":"AGENTS.md","dco":null,"cla":null}},"created_at":"2026-05-03T23:32:36.000Z","updated_at":"2026-05-04T23:18:28.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/felipetodev/petdex-dock","commit_stats":null,"previous_names":["felipetodev/petdex-dock"],"tags_count":2,"template":false,"template_full_name":null,"purl":"pkg:github/felipetodev/petdex-dock","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/felipetodev%2Fpetdex-dock","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/felipetodev%2Fpetdex-dock/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/felipetodev%2Fpetdex-dock/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/felipetodev%2Fpetdex-dock/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/felipetodev","download_url":"https://codeload.github.com/felipetodev/petdex-dock/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/felipetodev%2Fpetdex-dock/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":33934344,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-06-05T02:00:06.157Z","response_time":120,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["codex","codex-pets","electron"],"created_at":"2026-06-05T07:30:44.761Z","updated_at":"2026-06-05T07:30:45.395Z","avatar_url":"https://github.com/felipetodev.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# PetDex Dock\n\nhttps://github.com/user-attachments/assets/7d02a17e-1b13-41db-9523-8b75c7d59021\n\nVirtual pet companion for macOS that lives in your Dock.\n\n## Overview\n\nPetDex Dock brings Codex/animated pixel pets to your desktop. It creates a frameless, always-on-top window that displays your pet near the macOS Dock. The pet follows the mouse, animates in various states.\n\nUses the [PetDex public gallery](https://petdex.crafter.run/) for Codex-compatible animated pets.\n\n## macOS Install Notice\n\nPetDex Dock is distributed directly through GitHub Releases. It is not registered with Apple, not published on the Mac App Store, and current release builds are not signed/notarized with an Apple Developer ID.\n\nBecause of that, macOS Gatekeeper may show a warning such as:\n\n\u003e \"PetDex Dock\" is damaged and can't be opened. You should move it to the Trash.\n\nThis does not necessarily mean the downloaded app is corrupted. It is a common macOS protection shown for apps downloaded from the internet when Apple cannot verify a Developer ID signature and notarization ticket.\n\nHow to bypass the warning and open PetDex Dock:\n\n1. Download the `.dmg` from GitHub Releases.\n2. Open the `.dmg` and drag `PetDex Dock.app` into `/Applications`.\n3. Remove the macOS quarantine flag:\n\n```bash\nxattr -dr com.apple.quarantine \"/Applications/PetDex Dock.app\"\n```\n\n4. Open `PetDex Dock.app` from `/Applications`.\n\n## Pets Directory\n\nPets are installed to `~/.codex/pets/{petId}/` and must contain:\n\n```\n~/.codex/pets/{petId}/\n├── pet.json          # { id, displayName, description }\n└── spritesheet.webp  # 512x576px (8 cols x 9 rows of 64x64 frames)\n```\n\n### Install a Pet\n\n```bash\n# check available pets on https://petdex.crafter.run\nnpx petdex install [pet] # e.g. npx petdex install clippy\n```\n\n## Animation System\n\nAll pets share the same animation states (rows in spritesheet):\n\n| Row | Animation | Frames |\n|-----|-----------|--------|\n| 0   | idle      | 6      |\n| 1   | runRight  | 8      |\n| 2   | runLeft   | 8      |\n| 3   | waving    | 4      |\n| 4   | jumping   | 5      |\n| 5   | failed    | 8      |\n| 6   | waiting   | 6      |\n| 7   | running   | 6      |\n| 8   | review    | 6      |\n\n## CLI Event Bridge\n\nPetDex Dock listens for local CLI events at:\n\n```bash\nhttp://127.0.0.1:17321/event\n```\n\nSend a pet state with:\n\n```bash\ncurl -X POST http://127.0.0.1:17321/event \\\n  -H 'content-type: application/json' \\\n  -d '{\"source\":\"manual\",\"state\":\"running\"}'\n```\n\nSupported payload:\n\n```json\n{\n  \"source\": \"codex|claude|opencode|manual\",\n  \"state\": \"running|waiting|failed|review|idle\",\n  \"message\": \"optional\"\n}\n```\n\nExternal CLI events override the normal roaming animation while the CLI state is active. Mouse movement is ignored while a CLI override is active; the override ends when another CLI event arrives or when the CLI sends `idle`.\n\n### Claude Code Example\n\nClaude Code HTTP hooks can post directly to the local bridge. Add this shape to your Claude settings if you want a project-local test:\n\n```json\n{\n  \"hooks\": {\n    \"PreToolUse\": [\n      {\n        \"matcher\": \"*\",\n        \"hooks\": [\n          {\n            \"type\": \"http\",\n            \"url\": \"http://127.0.0.1:17321/event\",\n            \"body\": { \"source\": \"claude\", \"state\": \"running\" }\n          }\n        ]\n      }\n    ],\n    \"Notification\": [\n      {\n        \"hooks\": [\n          {\n            \"type\": \"http\",\n            \"url\": \"http://127.0.0.1:17321/event\",\n            \"body\": { \"source\": \"claude\", \"state\": \"waiting\" }\n          }\n        ]\n      }\n    ],\n    \"Stop\": [\n      {\n        \"hooks\": [\n          {\n            \"type\": \"http\",\n            \"url\": \"http://127.0.0.1:17321/event\",\n            \"body\": { \"source\": \"claude\", \"state\": \"review\" }\n          }\n        ]\n      }\n    ]\n  }\n}\n```\n\n### OpenCode Example\n\nCreate a global OpenCode plugin at `~/.config/opencode/plugins/petdex.js`, or a project-local plugin at `.opencode/plugins/petdex.js`:\n\n```js\nconst endpoint = 'http://127.0.0.1:17321/event';\n\nasync function send(state, message) {\n  const payload = { source: 'opencode', state, ...(message ? { message } : {}) };\n\n  await fetch(endpoint, {\n    method: 'POST',\n    headers: { 'content-type': 'application/json' },\n    body: JSON.stringify(payload)\n  }).catch(() =\u003e {});\n}\n\nfunction mapEventToState(type) {\n  if (type === 'permission.asked') return 'waiting';\n  if (type === 'session.error') return 'failed';\n  if (type === 'session.idle') return 'idle';\n  if (type === 'session.status') return 'running';\n  if (type === 'tool.execute.before') return 'running';\n  if (type === 'tool.execute.after') return 'review';\n  return null;\n}\n\nexport const PetDexPlugin = async ({ client }) =\u003e {\n  await client.app.log({\n    body: {\n      service: 'petdex',\n      level: 'info',\n      message: 'PetDex OpenCode plugin loaded'\n    }\n  });\n\n  return {\n    event: async ({ event }) =\u003e {\n      const state = mapEventToState(event.type);\n\n      await client.app.log({\n        body: {\n          service: 'petdex',\n          level: 'info',\n          message: `OpenCode event: ${event.type}`,\n          extra: { event }\n        }\n      });\n\n      if (state) {\n        await send(state, event.type);\n      }\n    }\n  };\n};\n```\n\n### Codex Example\n\nEnable Codex hooks in `~/.codex/config.toml`:\n\n```toml\n[features]\ncodex_hooks = true\n```\n\nCreate `~/.codex/hooks/petdex.cjs`:\n\n```js\nconst http = require('http');\n\nconst EVENT_STATES = {\n  SessionStart: 'running',\n  UserPromptSubmit: 'running',\n  PreToolUse: 'running',\n  PermissionRequest: 'waiting',\n  PostToolUse: 'review',\n  Stop: 'idle'\n};\n\nfunction readStdin() {\n  return new Promise((resolve) =\u003e {\n    let input = '';\n    process.stdin.setEncoding('utf8');\n    process.stdin.on('data', chunk =\u003e { input += chunk; });\n    process.stdin.on('end', () =\u003e resolve(input));\n  });\n}\n\nfunction postEvent(event) {\n  return new Promise((resolve) =\u003e {\n    const payload = JSON.stringify(event);\n    const request = http.request({\n      hostname: '127.0.0.1',\n      port: 17321,\n      path: '/event',\n      method: 'POST',\n      headers: {\n        'content-type': 'application/json',\n        'content-length': Buffer.byteLength(payload)\n      },\n      timeout: 1000\n    }, response =\u003e {\n      response.resume();\n      response.on('end', resolve);\n    });\n\n    request.on('error', resolve);\n    request.on('timeout', () =\u003e {\n      request.destroy();\n      resolve();\n    });\n    request.end(payload);\n  });\n}\n\n(async () =\u003e {\n  const rawInput = await readStdin();\n  let input = {};\n\n  try {\n    input = rawInput ? JSON.parse(rawInput) : {};\n  } catch {\n    input = {};\n  }\n\n  const hookName = typeof input.hook_event_name === 'string' ? input.hook_event_name : 'Unknown';\n  const state = EVENT_STATES[hookName] || 'review';\n  const toolName = typeof input.tool_name === 'string' ? input.tool_name : '';\n  const message = toolName ? `${hookName}:${toolName}` : hookName;\n\n  await postEvent({ source: 'codex', state, message });\n\n  if (hookName === 'Stop') {\n    process.stdout.write(JSON.stringify({ continue: true }));\n  }\n})();\n```\n\nCreate `~/.codex/hooks.json`:\n\n```json\n{\n  \"hooks\": {\n    \"SessionStart\": [{ \"matcher\": \"startup|resume|clear\", \"hooks\": [{ \"type\": \"command\", \"command\": \"node ~/.codex/hooks/petdex.cjs\" }] }],\n    \"UserPromptSubmit\": [{ \"hooks\": [{ \"type\": \"command\", \"command\": \"node ~/.codex/hooks/petdex.cjs\" }] }],\n    \"PreToolUse\": [{ \"matcher\": \"*\", \"hooks\": [{ \"type\": \"command\", \"command\": \"node ~/.codex/hooks/petdex.cjs\" }] }],\n    \"PermissionRequest\": [{ \"matcher\": \"*\", \"hooks\": [{ \"type\": \"command\", \"command\": \"node ~/.codex/hooks/petdex.cjs\" }] }],\n    \"PostToolUse\": [{ \"matcher\": \"*\", \"hooks\": [{ \"type\": \"command\", \"command\": \"node ~/.codex/hooks/petdex.cjs\" }] }],\n    \"Stop\": [{ \"hooks\": [{ \"type\": \"command\", \"command\": \"node ~/.codex/hooks/petdex.cjs\", \"timeout\": 5 }] }]\n  }\n}\n```\n\nRestart Codex after changing hook configuration.\n\n## Configuration\n\nStored in `~/Library/Application Support/petdex-dock/config.json`:\n\n```json\n{\n  \"activePet\": \"gutsy\",\n  \"position\": { \"x\": 100, \"y\": 200 },\n  \"fps\": 12,\n  \"petMode\": \"dock\"\n}\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ffelipetodev%2Fpetdex-dock","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ffelipetodev%2Fpetdex-dock","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ffelipetodev%2Fpetdex-dock/lists"}