petdex-cc 0.1.0 → 0.1.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +229 -165
- package/README_CN.md +240 -164
- package/dist/src/cli/install.d.ts.map +1 -1
- package/dist/src/cli/install.js +70 -13
- package/dist/src/cli/install.js.map +1 -1
- package/dist/src/petdex-api/download.d.ts +6 -1
- package/dist/src/petdex-api/download.d.ts.map +1 -1
- package/dist/src/petdex-api/download.js +26 -15
- package/dist/src/petdex-api/download.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,247 +1,311 @@
|
|
|
1
|
-
<
|
|
2
|
-
<img src="https://img.shields.io/badge/version-0.1.0-8b5cf6?style=flat-square" />
|
|
3
|
-
<img src="https://img.shields.io/badge/platform-Windows%20%7C%20macOS%20%7C%20Linux-0ea5e9?style=flat-square" />
|
|
4
|
-
<img src="https://img.shields.io/badge/node-%3E%3D18-22c55e?style=flat-square" />
|
|
5
|
-
<img src="https://img.shields.io/badge/license-MIT-f59e0b?style=flat-square" />
|
|
6
|
-
<img src="https://img.shields.io/badge/pets-1569%20available-ec4899?style=flat-square" />
|
|
7
|
-
</p>
|
|
8
|
-
|
|
9
|
-
<h1 align="center">
|
|
10
|
-
<br />
|
|
11
|
-
<code>petdex-cc</code>
|
|
12
|
-
<br />
|
|
13
|
-
<sub><b>Desktop Pet Companion for Claude Code</b></sub>
|
|
14
|
-
<br />
|
|
15
|
-
<sub><i>Animated pets that react to your coding in real-time</i></sub>
|
|
16
|
-
</h1>
|
|
17
|
-
|
|
18
|
-
<p align="center">
|
|
19
|
-
<a href="./README_CN.md">中文文档</a>
|
|
20
|
-
</p>
|
|
1
|
+
<div align="center">
|
|
21
2
|
|
|
22
|
-
|
|
3
|
+
# petdex-cc
|
|
23
4
|
|
|
24
|
-
|
|
5
|
+
**Desktop Pet Companion for Claude Code**
|
|
25
6
|
|
|
26
|
-
|
|
27
|
-
> Install with one command. Watch your pet come alive as you code.
|
|
7
|
+
*Animated pets that live on your screen and react to your coding in real-time*
|
|
28
8
|
|
|
29
|
-
|
|
9
|
+
[](https://www.npmjs.com/package/petdex-cc)
|
|
10
|
+
[]()
|
|
11
|
+
[]()
|
|
12
|
+
[]()
|
|
13
|
+
[](https://petdex.crafter.run)
|
|
30
14
|
|
|
31
|
-
|
|
15
|
+
[English](./README.md) · [中文文档](./README_CN.md)
|
|
32
16
|
|
|
33
|
-
|
|
17
|
+
</div>
|
|
34
18
|
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
19
|
+
---
|
|
20
|
+
|
|
21
|
+
## What is petdex-cc?
|
|
22
|
+
|
|
23
|
+
petdex-cc brings **animated desktop pets** to your Claude Code workflow. Pick any pet from [Petdex](https://petdex.crafter.run/) (1,569+ community pets), install with one command, and your companion appears on your desktop — reading code with you, celebrating completions, cheering you through errors, and growing stronger as you code.
|
|
24
|
+
|
|
25
|
+
> **How is this different from `npx petdex install`?**
|
|
26
|
+
> The original `petdex` command gives you a basic pet. `petdex-cc` adds a deep **Claude Code integration layer** — hooks into your coding workflow, a level progression system, AI-generated speech, time-aware greetings, and interactive effects. Your pet isn't just decoration — it *lives* in your coding session.
|
|
27
|
+
|
|
28
|
+
### Features at a glance
|
|
44
29
|
|
|
45
|
-
|
|
30
|
+
- **Real-time reactions** — pet changes animation when you read, edit, run commands, complete tasks, or hit errors
|
|
31
|
+
- **8-level progression** — Byte → Process → Thread → Module → Kernel → Neural → Quantum → Singularity, with escalating visual effects
|
|
32
|
+
- **AI speech bubbles** — context-aware dialogue generated by Claude (or built-in preset lines)
|
|
33
|
+
- **Time-aware greetings** — morning, lunch, afternoon, evening, night, and midnight messages in Chinese
|
|
34
|
+
- **Interactive** — drag your pet anywhere, right-click for menu, rapid-click easter egg
|
|
35
|
+
- **System tray** — show/hide, about, quit from the taskbar
|
|
36
|
+
- **State persistence** — level and event count survive restarts (HMAC-signed, tamper-resistant)
|
|
37
|
+
- **1,569+ pets** — browse [petdex.crafter.run](https://petdex.crafter.run/) and install any community pet
|
|
38
|
+
|
|
39
|
+
---
|
|
46
40
|
|
|
47
41
|
## Quick Start
|
|
48
42
|
|
|
49
43
|
### Prerequisites
|
|
50
44
|
|
|
51
45
|
- [Node.js](https://nodejs.org/) >= 18
|
|
52
|
-
- [Claude Code](https://docs.anthropic.com/en/docs/claude-code) installed
|
|
46
|
+
- [Claude Code](https://docs.anthropic.com/en/docs/claude-code) installed
|
|
53
47
|
|
|
54
|
-
### Install
|
|
48
|
+
### Install
|
|
55
49
|
|
|
56
50
|
```bash
|
|
57
|
-
# Browse pets → https://petdex.crafter.run/
|
|
58
|
-
#
|
|
51
|
+
# 1. Browse pets → https://petdex.crafter.run/
|
|
52
|
+
# 2. Find one you like, note the slug (e.g. "boba")
|
|
53
|
+
# 3. Install:
|
|
59
54
|
|
|
60
55
|
npx petdex-cc install boba
|
|
61
56
|
```
|
|
62
57
|
|
|
63
|
-
|
|
58
|
+
Your pet appears on the desktop immediately and starts reacting to Claude Code.
|
|
64
59
|
|
|
65
|
-
|
|
60
|
+
### Popular pets
|
|
66
61
|
|
|
67
|
-
|
|
62
|
+
| Slug | Name | Description |
|
|
63
|
+
|---|---|---|
|
|
64
|
+
| `boba` | Boba | Tiny otter sipping bubble tea |
|
|
65
|
+
| `doraemon` | Doraemon | Blue robot-cat from the future |
|
|
66
|
+
| `noir-webling` | Noir Webling | Monochrome spider detective |
|
|
67
|
+
| `ikun-hoops` | IKUN Hoops | Hoodie chick with a basketball |
|
|
68
|
+
| `ddo-zvzo` | ddo-zvzo | Purple mascot with sunglasses |
|
|
69
|
+
| `mochi` | Mochi | Orange-and-white chibi cat |
|
|
68
70
|
|
|
69
|
-
|
|
71
|
+
> Browse all 1,569+ pets at [**petdex.crafter.run**](https://petdex.crafter.run/)
|
|
70
72
|
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
petdex-cc stop Stop the desktop pet
|
|
75
|
-
petdex-cc list Browse available pets from Petdex
|
|
76
|
-
petdex-cc switch <slug> Switch to a different pet
|
|
77
|
-
petdex-cc status Show current pet status & level
|
|
78
|
-
petdex-cc uninstall Remove hooks and pet data
|
|
79
|
-
petdex-cc config Configure API key and settings
|
|
80
|
-
```
|
|
73
|
+
---
|
|
74
|
+
|
|
75
|
+
## What Your Pet Does
|
|
81
76
|
|
|
82
|
-
|
|
77
|
+
Every Claude Code action triggers a pet reaction:
|
|
78
|
+
|
|
79
|
+
| Claude Code event | Pet animation | Speech bubble |
|
|
80
|
+
|---|---|---|
|
|
81
|
+
| Session starts | Waving | "Let's get to work!" |
|
|
82
|
+
| Reading a file | Review | "Reading filename..." |
|
|
83
|
+
| Editing a file | Idle | "Edited filename" |
|
|
84
|
+
| Running a command | Running | "Running command..." |
|
|
85
|
+
| Searching (Glob/Grep) | Waiting | "Searching..." |
|
|
86
|
+
| Tool fails | Failed | "Oops, something went wrong" + AI encouragement |
|
|
87
|
+
| Task completes | Jumping | "Task complete!" + AI celebration |
|
|
88
|
+
| Claude stops | Jumping | "Task complete!" (60% AI speech) |
|
|
89
|
+
| Claude errors | Failed | Error message + AI comfort |
|
|
90
|
+
| Idle (10+ min) | Waving | Time-aware Chinese greeting |
|
|
91
|
+
| Level up | Current state | "Level up! Kernel!" + all effects activate |
|
|
92
|
+
|
|
93
|
+
### Pet interactions
|
|
94
|
+
|
|
95
|
+
- **Drag** — click and drag to move your pet anywhere
|
|
96
|
+
- **Right-click** — context menu with Show/Hide, About, Quit
|
|
97
|
+
- **System tray** — right-click the tray icon for menu
|
|
98
|
+
- **Easter egg** — rapidly click your pet for escalating reactions (2 → 4 → 6 → 9 → 12 → 15 clicks)
|
|
99
|
+
|
|
100
|
+
---
|
|
83
101
|
|
|
84
102
|
## Level System
|
|
85
103
|
|
|
86
|
-
Your pet
|
|
104
|
+
Your pet levels up based on cumulative Claude Code events. Each level unlocks new visual effects:
|
|
87
105
|
|
|
88
|
-
|
|
|
89
|
-
|
|
90
|
-
| 1 | **Byte** | 0 | Base pet |
|
|
91
|
-
| 2 | **Process** | 50 |
|
|
92
|
-
| 3 | **Thread** | 200 | Rotating aura ring |
|
|
93
|
-
| 4 | **Module** | 500 |
|
|
94
|
-
| 5 | **Kernel** | 1,000 | Floating light particles |
|
|
95
|
-
| 6 | **Neural** | 2,000 | Pink
|
|
96
|
-
| 7 | **Quantum** | 5,000 | Cyan
|
|
97
|
-
| 8 | **Singularity** | 10,000 | Golden halo + all effects |
|
|
106
|
+
| Lv | Name | Events | Color | Effect |
|
|
107
|
+
|:---:|---|---:|---|---|
|
|
108
|
+
| 1 | **Byte** | 0 | Silver | Base pet |
|
|
109
|
+
| 2 | **Process** | 50 | Green | Breathing glow |
|
|
110
|
+
| 3 | **Thread** | 200 | Blue | Rotating aura ring |
|
|
111
|
+
| 4 | **Module** | 500 | Purple | Enhanced aura |
|
|
112
|
+
| 5 | **Kernel** | 1,000 | Amber | Floating light particles |
|
|
113
|
+
| 6 | **Neural** | 2,000 | Pink | Particle storm |
|
|
114
|
+
| 7 | **Quantum** | 5,000 | Cyan | Energy field |
|
|
115
|
+
| 8 | **Singularity** | 10,000 | Gold | Golden halo + all effects |
|
|
98
116
|
|
|
99
|
-
|
|
117
|
+
---
|
|
100
118
|
|
|
101
119
|
## AI Speech
|
|
102
120
|
|
|
103
|
-
When
|
|
121
|
+
When an Anthropic API key is available (auto-detected from Claude Code settings or set via `petdex-cc config`), your pet generates **context-aware speech**:
|
|
122
|
+
|
|
123
|
+
| Scene | Trigger | Example AI response |
|
|
124
|
+
|---|---|---|
|
|
125
|
+
| `task_complete` | Task finishes | "做得好!继续加油!" |
|
|
126
|
+
| `error` | Tool fails | "别担心,bugs难免的~" |
|
|
127
|
+
| `idle` | Idle 10+ minutes | "还在吗?" |
|
|
128
|
+
| `level_up` | Level threshold crossed | "升级啦!太厉害了!" |
|
|
129
|
+
|
|
130
|
+
- **2-minute cooldown** between AI calls (level-ups bypass this)
|
|
131
|
+
- **5-second timeout** — falls back to preset lines if API is slow
|
|
132
|
+
- **No API key?** Built-in preset lines work great — 7 task lines, 5 error lines, 5 idle lines, 4 level-up lines
|
|
133
|
+
|
|
134
|
+
---
|
|
135
|
+
|
|
136
|
+
## CLI Reference
|
|
137
|
+
|
|
138
|
+
```bash
|
|
139
|
+
petdex-cc install <slug> # Download pet, configure hooks, and launch
|
|
140
|
+
petdex-cc start # Start the desktop pet
|
|
141
|
+
petdex-cc stop # Gracefully stop the pet
|
|
142
|
+
petdex-cc list # Browse all pets from Petdex registry
|
|
143
|
+
petdex-cc switch <slug> # Switch pets at runtime (downloads if needed)
|
|
144
|
+
petdex-cc status # Show pet name, level, events, running status
|
|
145
|
+
petdex-cc uninstall # Remove hooks, stop pet, delete all data
|
|
146
|
+
petdex-cc config [options] # Configure settings
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
### Config options
|
|
104
150
|
|
|
105
|
-
|
|
106
|
-
-
|
|
107
|
-
-
|
|
108
|
-
-
|
|
151
|
+
```bash
|
|
152
|
+
petdex-cc config --api-key <key> # Anthropic API key for AI speech
|
|
153
|
+
petdex-cc config --api-base-url <url> # API base URL
|
|
154
|
+
petdex-cc config --cooldown <minutes> # AI call cooldown (default: 2)
|
|
155
|
+
```
|
|
109
156
|
|
|
110
|
-
|
|
157
|
+
> API credentials are auto-detected from `~/.claude/settings.json` — most users don't need manual config.
|
|
111
158
|
|
|
112
|
-
|
|
159
|
+
---
|
|
160
|
+
|
|
161
|
+
## Architecture
|
|
162
|
+
|
|
163
|
+
```
|
|
164
|
+
┌─────────────────────────────────────────────────┐
|
|
165
|
+
│ Claude Code │
|
|
166
|
+
│ (tool use, task complete, errors, idle, etc.) │
|
|
167
|
+
└──────────────────────┬──────────────────────────┘
|
|
168
|
+
│ hooks (settings.json)
|
|
169
|
+
▼
|
|
170
|
+
┌──────────────────┐
|
|
171
|
+
│ bridge.ps1/.sh │ async, 10s timeout
|
|
172
|
+
└────────┬─────────┘
|
|
173
|
+
│ HTTP POST /event
|
|
174
|
+
▼
|
|
175
|
+
┌─────────────────────────────────────────────────┐
|
|
176
|
+
│ petdex-cc (Electron) │
|
|
177
|
+
│ │
|
|
178
|
+
│ ┌──────────────┐ ┌──────────┐ ┌────────────┐ │
|
|
179
|
+
│ │ event-mapper │ │ storage │ │ ai-speech │ │
|
|
180
|
+
│ │ event → action│ │ level, XP │ │ Claude Haiku│ │
|
|
181
|
+
│ └──────┬───────┘ └─────┬────┘ └─────┬──────┘ │
|
|
182
|
+
│ │ │ │ │
|
|
183
|
+
│ └─────────┬───────┘ │ │
|
|
184
|
+
│ ▼ │ │
|
|
185
|
+
│ ┌─────────────────┐ │ │
|
|
186
|
+
│ │ IPC to window │◀─────────────┘ │
|
|
187
|
+
│ └────────┬────────┘ │
|
|
188
|
+
└──────────────────┼──────────────────────────────────┘
|
|
189
|
+
▼
|
|
190
|
+
┌──────────────────┐
|
|
191
|
+
│ Pet Window (HTML) │ transparent, always-on-top
|
|
192
|
+
│ │
|
|
193
|
+
│ ┌─── sprite ───┐ │ 9 animation states
|
|
194
|
+
│ │ bubble │ │ 3s / 8s auto-dismiss
|
|
195
|
+
│ │ badge │ │ Lv tag + color
|
|
196
|
+
│ │ effects │ │ glow/aura/particles/halo
|
|
197
|
+
│ └──────────────┘ │
|
|
198
|
+
└──────────────────┘
|
|
199
|
+
```
|
|
200
|
+
|
|
201
|
+
---
|
|
113
202
|
|
|
114
203
|
## Developer Setup
|
|
115
204
|
|
|
116
205
|
```bash
|
|
117
|
-
# Clone the repo
|
|
118
206
|
git clone https://github.com/devnomad-byte/petdex-cc.git
|
|
119
207
|
cd petdex-cc
|
|
120
|
-
|
|
121
|
-
# Install dependencies
|
|
122
208
|
npm install
|
|
123
|
-
|
|
124
|
-
# Build
|
|
125
209
|
npm run build
|
|
126
210
|
|
|
127
|
-
#
|
|
211
|
+
# Run in dev mode
|
|
128
212
|
npx electron .
|
|
129
213
|
|
|
130
|
-
#
|
|
214
|
+
# Install globally for CLI
|
|
131
215
|
npm link
|
|
132
216
|
petdex-cc install boba
|
|
133
217
|
```
|
|
134
218
|
|
|
135
|
-
### Project
|
|
219
|
+
### Project structure
|
|
136
220
|
|
|
137
221
|
```
|
|
138
222
|
petdex-cc/
|
|
139
|
-
├── bin/cli.ts
|
|
223
|
+
├── bin/cli.ts CLI entry point (8 commands)
|
|
140
224
|
├── src/
|
|
141
|
-
│ ├── main/
|
|
142
|
-
│ │ ├── index.ts
|
|
143
|
-
│ │ ├── server.ts
|
|
144
|
-
│ │ ├── ai-speech.ts
|
|
145
|
-
│ │ ├── storage.ts
|
|
146
|
-
│ │ ├── tray.ts
|
|
147
|
-
│ │ └── event-mapper.ts
|
|
148
|
-
│ ├── renderer/
|
|
149
|
-
│ │ ├── index.html
|
|
150
|
-
│ │ ├── renderer.ts
|
|
151
|
-
│ │ ├── pet-sprite.ts
|
|
152
|
-
│ │ ├── bubble.ts
|
|
153
|
-
│ │ ├── click-through.ts
|
|
154
|
-
│ │
|
|
155
|
-
│
|
|
156
|
-
│ ├──
|
|
157
|
-
│
|
|
225
|
+
│ ├── main/ Electron main process
|
|
226
|
+
│ │ ├── index.ts Window creation, event loop, IPC
|
|
227
|
+
│ │ ├── server.ts HTTP server (hooks → pet, port 17321)
|
|
228
|
+
│ │ ├── ai-speech.ts AI speech via Anthropic Messages API
|
|
229
|
+
│ │ ├── storage.ts HMAC-signed state persistence
|
|
230
|
+
│ │ ├── tray.ts System tray with cat-face icon
|
|
231
|
+
│ │ └── event-mapper.ts 8 hook events → pet actions
|
|
232
|
+
│ ├── renderer/ Electron renderer (pet UI)
|
|
233
|
+
│ │ ├── index.html Transparent window + CSS effects
|
|
234
|
+
│ │ ├── renderer.ts IPC coordination + level effects
|
|
235
|
+
│ │ ├── pet-sprite.ts 9-state spritesheet engine
|
|
236
|
+
│ │ ├── bubble.ts Speech bubble system
|
|
237
|
+
│ │ ├── click-through.ts Transparent click pass-through
|
|
238
|
+
│ │ ├── drag.ts Drag + click easter egg
|
|
239
|
+
│ │ └── context-menu.ts Right-click menu
|
|
240
|
+
│ ├── cli/ CLI command implementations
|
|
241
|
+
│ ├── hooks/ Claude Code hooks (register/unregister)
|
|
242
|
+
│ │ ├── register.ts Writes to ~/.claude/settings.json
|
|
243
|
+
│ │ ├── write-scripts.ts Cross-platform bridge scripts
|
|
244
|
+
│ │ ├── bridge.ps1 Windows PowerShell bridge
|
|
245
|
+
│ │ └── bridge.sh Unix bash bridge
|
|
246
|
+
│ ├── petdex-api/ Petdex registry client
|
|
247
|
+
│ │ ├── client.ts Manifest fetch + slug lookup
|
|
248
|
+
│ │ └── download.ts Streaming download with progress
|
|
249
|
+
│ └── shared/ Shared types and constants
|
|
158
250
|
```
|
|
159
251
|
|
|
160
|
-
|
|
252
|
+
---
|
|
161
253
|
|
|
162
|
-
|
|
163
|
-
|---|---|
|
|
164
|
-
| `npm run build` | TypeScript compile + bundle renderer |
|
|
165
|
-
| `npm run check` | Type-check without emitting |
|
|
166
|
-
| `npx electron .` | Start pet from compiled output |
|
|
254
|
+
## Configuration Reference
|
|
167
255
|
|
|
168
|
-
|
|
256
|
+
### Auto-detected settings
|
|
169
257
|
|
|
170
|
-
|
|
258
|
+
petdex-cc reads these from `~/.claude/settings.json` automatically:
|
|
171
259
|
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
bridge.ps1 / bridge.sh
|
|
177
|
-
│
|
|
178
|
-
▼
|
|
179
|
-
HTTP POST /event (localhost)
|
|
180
|
-
│
|
|
181
|
-
▼
|
|
182
|
-
┌───────────────┐
|
|
183
|
-
│ petdex-cc │
|
|
184
|
-
│ (Electron) │
|
|
185
|
-
│ │
|
|
186
|
-
│ event-mapper │──▶ pet action + speech bubble
|
|
187
|
-
│ storage │──▶ level up detection
|
|
188
|
-
│ ai-speech │──▶ AI-generated responses
|
|
189
|
-
└───────────────┘
|
|
190
|
-
│
|
|
191
|
-
▼
|
|
192
|
-
Desktop pet window
|
|
193
|
-
```
|
|
194
|
-
|
|
195
|
-
<br />
|
|
260
|
+
| Setting | Used for |
|
|
261
|
+
|---|---|
|
|
262
|
+
| `ANTHROPIC_AUTH_TOKEN` | API key for AI speech |
|
|
263
|
+
| `ANTHROPIC_BASE_URL` | API endpoint for AI speech |
|
|
196
264
|
|
|
197
|
-
|
|
265
|
+
### Manual config
|
|
198
266
|
|
|
199
|
-
|
|
267
|
+
Stored in `~/.petdex-cc/config.json`:
|
|
200
268
|
|
|
201
269
|
```bash
|
|
202
|
-
|
|
203
|
-
petdex-cc config --api-key <your-key> --api-base-url <url>
|
|
204
|
-
|
|
205
|
-
# Or it auto-detects from Claude Code settings (~/.claude/settings.json)
|
|
270
|
+
petdex-cc config --api-key <key> --api-base-url <url> --cooldown 2
|
|
206
271
|
```
|
|
207
272
|
|
|
208
|
-
###
|
|
273
|
+
### Data locations
|
|
209
274
|
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
| Hook Event | Trigger |
|
|
275
|
+
| Path | Contents |
|
|
213
276
|
|---|---|
|
|
214
|
-
|
|
|
215
|
-
| `
|
|
216
|
-
| `
|
|
217
|
-
|
|
|
218
|
-
| `
|
|
219
|
-
| `SessionStart` | Claude Code starts or resumes |
|
|
220
|
-
| `SessionEnd` | Claude Code session ends |
|
|
221
|
-
| `TaskCompleted` | A task is marked complete |
|
|
277
|
+
| `~/.petdex-cc/pets/<slug>/` | Downloaded spritesheet + pet.json |
|
|
278
|
+
| `~/.petdex-cc/data/state.json` | Level, events, pet slug (HMAC-signed) |
|
|
279
|
+
| `~/.petdex-cc/data/state.sig` | HMAC-SHA256 signature |
|
|
280
|
+
| `~/.petdex-cc/hooks/` | Bridge scripts |
|
|
281
|
+
| `~/.petdex-cc/config.json` | User config (API key, cooldown) |
|
|
222
282
|
|
|
223
|
-
|
|
283
|
+
---
|
|
224
284
|
|
|
225
|
-
##
|
|
285
|
+
## Hooks Reference
|
|
226
286
|
|
|
227
|
-
|
|
287
|
+
petdex-cc registers these hooks in `~/.claude/settings.json`:
|
|
228
288
|
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
289
|
+
| Hook | Matcher | What triggers it |
|
|
290
|
+
|---|---|---|
|
|
291
|
+
| `PostToolUse` | `Read\|Edit\|Write\|Bash\|Glob\|Grep` | After any tool call |
|
|
292
|
+
| `PostToolUseFailure` | — | After a tool call fails |
|
|
293
|
+
| `Stop` | — | Claude finishes a response |
|
|
294
|
+
| `StopFailure` | — | Claude stops with error |
|
|
295
|
+
| `Notification` | `idle_prompt` | User is idle |
|
|
296
|
+
| `SessionStart` | `startup\|resume` | Claude Code launches or resumes |
|
|
297
|
+
| `SessionEnd` | — | Claude Code session ends |
|
|
298
|
+
| `TaskCompleted` | — | A task is marked complete |
|
|
233
299
|
|
|
234
|
-
|
|
300
|
+
---
|
|
235
301
|
|
|
236
302
|
## License
|
|
237
303
|
|
|
238
|
-
MIT
|
|
239
|
-
|
|
240
|
-
<br />
|
|
304
|
+
[MIT](./LICENSE)
|
|
241
305
|
|
|
242
306
|
---
|
|
243
307
|
|
|
244
|
-
<
|
|
245
|
-
<sub>Built
|
|
308
|
+
<div align="center">
|
|
309
|
+
<sub>Built for the <a href="https://docs.anthropic.com/en/docs/claude-code">Claude Code</a> community</sub><br />
|
|
246
310
|
<sub>Pets powered by <a href="https://petdex.crafter.run/">Petdex</a></sub>
|
|
247
|
-
</
|
|
311
|
+
</div>
|
package/README_CN.md
CHANGED
|
@@ -1,133 +1,219 @@
|
|
|
1
|
-
<
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
<p align="center">
|
|
19
|
-
<a href="./README.md">English</a>
|
|
20
|
-
</p>
|
|
1
|
+
<div align="center">
|
|
2
|
+
|
|
3
|
+
# petdex-cc
|
|
4
|
+
|
|
5
|
+
**Claude Code 桌面宠物伴侣**
|
|
6
|
+
|
|
7
|
+
*住在屏幕上的动画宠物,实时响应你的每一次编码操作*
|
|
8
|
+
|
|
9
|
+
[](https://www.npmjs.com/package/petdex-cc)
|
|
10
|
+
[]()
|
|
11
|
+
[]()
|
|
12
|
+
[]()
|
|
13
|
+
[](https://petdex.crafter.run/zh)
|
|
14
|
+
|
|
15
|
+
[English](./README.md) · [中文文档](./README_CN.md)
|
|
16
|
+
|
|
17
|
+
</div>
|
|
21
18
|
|
|
22
19
|
---
|
|
23
20
|
|
|
24
|
-
|
|
21
|
+
## petdex-cc 是什么?
|
|
25
22
|
|
|
26
|
-
|
|
27
|
-
> 一条命令安装,宠物立刻出现在你的桌面上。
|
|
23
|
+
petdex-cc 为你的 Claude Code 工作流带来**动画桌面宠物**。从 [Petdex 宠物库](https://petdex.crafter.run/zh)(1,569+ 款社区宠物)挑选一只,一条命令安装,宠物立刻出现在桌面上 —— 陪你读代码、庆祝任务完成、在你遇到错误时加油打气,随你的编码而成长。
|
|
28
24
|
|
|
29
|
-
|
|
25
|
+
> **和 `npx petdex install` 有什么区别?**
|
|
26
|
+
> 原始的 `petdex` 命令提供基础宠物展示。`petdex-cc` 额外增加了**深度 Claude Code 集成** —— 通过 hooks 接入你的编码流程,包含等级成长系统、AI 生成语音、时段问候、互动特效。你的宠物不只是一个装饰,它*参与*你的编码过程。
|
|
30
27
|
|
|
31
|
-
|
|
28
|
+
> **目前仅支持 Claude Code,后续将扩展到 Cursor、Windsurf、Copilot 等 AI 编码工具。**
|
|
32
29
|
|
|
33
|
-
|
|
30
|
+
### 功能一览
|
|
34
31
|
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
| 你升级了 | 宠物发光、闪烁、庆祝 |
|
|
32
|
+
- **实时反应** —— 你读文件、编辑代码、运行命令、完成任务、遇到错误时,宠物同步改变动画
|
|
33
|
+
- **8 级成长体系** —— Byte → Process → Thread → Module → Kernel → Neural → Quantum → Singularity,逐级解锁视觉特效
|
|
34
|
+
- **AI 语音气泡** —— 基于 Claude 生成的上下文感知中文对话(无 API Key 时使用内置台词)
|
|
35
|
+
- **时段问候** —— 早上好、午安、下午茶、下班、晚安、凌晨问候
|
|
36
|
+
- **互动体验** —— 拖拽宠物、右键菜单、快速点击彩蛋
|
|
37
|
+
- **系统托盘** —— 任务栏图标,可显示/隐藏、查看关于、退出
|
|
38
|
+
- **状态持久化** —— 等级和事件数重启不丢失(HMAC 签名防篡改)
|
|
39
|
+
- **1,569+ 款宠物** —— 浏览 [petdex.crafter.run/zh](https://petdex.crafter.run/zh),安装任意社区宠物
|
|
44
40
|
|
|
45
|
-
|
|
41
|
+
---
|
|
46
42
|
|
|
47
43
|
## 快速开始
|
|
48
44
|
|
|
49
45
|
### 环境要求
|
|
50
46
|
|
|
51
47
|
- [Node.js](https://nodejs.org/) >= 18
|
|
52
|
-
- 已安装 [Claude Code](https://docs.anthropic.com/en/docs/claude-code)
|
|
48
|
+
- 已安装 [Claude Code](https://docs.anthropic.com/en/docs/claude-code)
|
|
53
49
|
|
|
54
|
-
###
|
|
50
|
+
### 安装
|
|
55
51
|
|
|
56
52
|
```bash
|
|
57
|
-
# 浏览宠物 → https://petdex.crafter.run/
|
|
58
|
-
#
|
|
53
|
+
# 1. 浏览宠物 → https://petdex.crafter.run/zh
|
|
54
|
+
# 2. 看中哪只,记下它的 slug(比如 "boba")
|
|
55
|
+
# 3. 安装:
|
|
59
56
|
|
|
60
57
|
npx petdex-cc install boba
|
|
61
58
|
```
|
|
62
59
|
|
|
63
|
-
|
|
60
|
+
宠物立刻出现在桌面上,开始响应你的 Claude Code 操作。
|
|
64
61
|
|
|
65
|
-
|
|
62
|
+
### 热门宠物
|
|
66
63
|
|
|
67
|
-
|
|
64
|
+
| Slug | 名称 | 描述 |
|
|
65
|
+
|---|---|---|
|
|
66
|
+
| `boba` | Boba | 喝着珍珠奶茶的小水獭 |
|
|
67
|
+
| `doraemon` | 哆啦A梦 | 来自未来的蓝色机器猫 |
|
|
68
|
+
| `noir-webling` | Noir Webling | 戴礼帽的单色蜘蛛侦探 |
|
|
69
|
+
| `ikun-hoops` | IKUN Hoops | 穿卫衣拿篮球的小鸡 |
|
|
70
|
+
| `ddo-zvzo` | ddo-zvzo | 会戴墨镜的紫色吉祥物 |
|
|
71
|
+
| `mochi` | Mochi | 橘白色可爱小猫 |
|
|
68
72
|
|
|
69
|
-
|
|
73
|
+
> 浏览全部 1,569+ 款宠物 → [**petdex.crafter.run/zh**](https://petdex.crafter.run/zh)
|
|
70
74
|
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
75
|
+
---
|
|
76
|
+
|
|
77
|
+
## 你的宠物会做什么
|
|
78
|
+
|
|
79
|
+
Claude Code 的每一次操作都会触发宠物反应:
|
|
80
|
+
|
|
81
|
+
| Claude Code 事件 | 宠物动画 | 语音气泡 |
|
|
82
|
+
|---|---|---|
|
|
83
|
+
| 会话开始 | 挥手 | "Let's get to work!" |
|
|
84
|
+
| 读取文件 | 审视 | "Reading 文件名..." |
|
|
85
|
+
| 编辑文件 | 待机 | "Edited 文件名" |
|
|
86
|
+
| 运行命令 | 奔跑 | "Running command..." |
|
|
87
|
+
| 搜索文件 | 等待 | "Searching..." |
|
|
88
|
+
| 工具失败 | 垂头 | "Oops, something went wrong" + AI 鼓励 |
|
|
89
|
+
| 任务完成 | 跳跃 | "Task complete!" + AI 庆祝 |
|
|
90
|
+
| Claude 停止 | 跳跃 | "Task complete!"(60% 概率触发 AI) |
|
|
91
|
+
| Claude 报错 | 垂头 | 错误信息 + AI 安慰 |
|
|
92
|
+
| 空闲 10+ 分钟 | 挥手 | 时段问候(中文) |
|
|
93
|
+
| 等级提升 | 当前状态 | "Level up! Kernel!" + 特效激活 |
|
|
81
94
|
|
|
82
|
-
|
|
95
|
+
### 互动操作
|
|
96
|
+
|
|
97
|
+
- **拖拽** —— 点击拖动宠物到屏幕任意位置
|
|
98
|
+
- **右键** —— 上下文菜单:显示/隐藏、关于、退出
|
|
99
|
+
- **系统托盘** —— 右下角任务栏图标
|
|
100
|
+
- **彩蛋** —— 快速连续点击宠物,触发递进式反应(2 → 4 → 6 → 9 → 12 → 15 次)
|
|
101
|
+
|
|
102
|
+
---
|
|
83
103
|
|
|
84
104
|
## 等级系统
|
|
85
105
|
|
|
86
|
-
你的宠物随你的编码而成长。每次 Claude Code
|
|
106
|
+
你的宠物随你的编码而成长。每次 Claude Code 操作算一次事件,累积升级:
|
|
87
107
|
|
|
88
|
-
| 等级 | 名称 | 所需事件数 | 视觉效果 |
|
|
89
|
-
|
|
90
|
-
| 1 | **Byte** | 0 | 基础宠物 |
|
|
91
|
-
| 2 | **Process** | 50 |
|
|
92
|
-
| 3 | **Thread** | 200 | 旋转光环 |
|
|
93
|
-
| 4 | **Module** | 500 |
|
|
94
|
-
| 5 | **Kernel** | 1,000 | 漂浮光点粒子 |
|
|
95
|
-
| 6 | **Neural** | 2,000 |
|
|
96
|
-
| 7 | **Quantum** | 5,000 |
|
|
97
|
-
| 8 | **Singularity** | 10,000 | 金色光环 + 全部特效 |
|
|
108
|
+
| 等级 | 名称 | 所需事件数 | 颜色 | 视觉效果 |
|
|
109
|
+
|:---:|---|---:|---|---|
|
|
110
|
+
| 1 | **Byte** | 0 | 银色 | 基础宠物 |
|
|
111
|
+
| 2 | **Process** | 50 | 绿色 | 呼吸式发光 |
|
|
112
|
+
| 3 | **Thread** | 200 | 蓝色 | 旋转光环 |
|
|
113
|
+
| 4 | **Module** | 500 | 紫色 | 增强光环 |
|
|
114
|
+
| 5 | **Kernel** | 1,000 | 琥珀 | 漂浮光点粒子 |
|
|
115
|
+
| 6 | **Neural** | 2,000 | 粉色 | 粒子风暴 |
|
|
116
|
+
| 7 | **Quantum** | 5,000 | 青色 | 能量场 |
|
|
117
|
+
| 8 | **Singularity** | 10,000 | 金色 | 金色光环 + 全部特效 |
|
|
98
118
|
|
|
99
|
-
|
|
119
|
+
---
|
|
100
120
|
|
|
101
121
|
## AI 语音
|
|
102
122
|
|
|
103
|
-
|
|
123
|
+
当 Anthropic API Key 可用时(自动从 Claude Code 设置读取,或通过 `petdex-cc config` 配置),宠物会生成**上下文感知的中文语音**:
|
|
124
|
+
|
|
125
|
+
| 场景 | 触发时机 | AI 生成示例 |
|
|
126
|
+
|---|---|---|
|
|
127
|
+
| `task_complete` | 任务完成 | "做得好!继续加油!" |
|
|
128
|
+
| `error` | 工具失败 | "别担心,bugs难免的~" |
|
|
129
|
+
| `idle` | 空闲超过 10 分钟 | "还在吗?" |
|
|
130
|
+
| `level_up` | 等级跨越阈值 | "升级啦!太厉害了!" |
|
|
131
|
+
|
|
132
|
+
- **2 分钟冷却** —— 连续 AI 调用间隔(升级时自动跳过冷却)
|
|
133
|
+
- **5 秒超时** —— API 响应超过 5 秒自动回退到预设台词
|
|
134
|
+
- **没有 API Key?** 内置预设台词完全够用 —— 7 条任务、5 条错误、5 条空闲、4 条升级
|
|
135
|
+
|
|
136
|
+
---
|
|
137
|
+
|
|
138
|
+
## 命令参考
|
|
104
139
|
|
|
105
|
-
|
|
106
|
-
-
|
|
107
|
-
-
|
|
108
|
-
-
|
|
140
|
+
```bash
|
|
141
|
+
petdex-cc install <slug> # 下载宠物、配置 hooks、启动
|
|
142
|
+
petdex-cc start # 启动桌面宠物
|
|
143
|
+
petdex-cc stop # 优雅停止宠物
|
|
144
|
+
petdex-cc list # 浏览 Petdex 宠物库
|
|
145
|
+
petdex-cc switch <slug> # 运行时切换宠物(自动下载)
|
|
146
|
+
petdex-cc status # 查看宠物名称、等级、事件数、运行状态
|
|
147
|
+
petdex-cc uninstall # 移除 hooks、停止宠物、删除所有数据
|
|
148
|
+
petdex-cc config [选项] # 配置设置
|
|
149
|
+
```
|
|
109
150
|
|
|
110
|
-
|
|
151
|
+
### 配置选项
|
|
152
|
+
|
|
153
|
+
```bash
|
|
154
|
+
petdex-cc config --api-key <key> # Anthropic API Key(用于 AI 语音)
|
|
155
|
+
petdex-cc config --api-base-url <url> # API 基础 URL
|
|
156
|
+
petdex-cc config --cooldown <分钟> # AI 调用冷却时间(默认 2 分钟)
|
|
157
|
+
```
|
|
111
158
|
|
|
112
|
-
|
|
159
|
+
> API 凭据会自动从 `~/.claude/settings.json` 读取,大多数用户无需手动配置。
|
|
160
|
+
|
|
161
|
+
---
|
|
162
|
+
|
|
163
|
+
## 架构设计
|
|
164
|
+
|
|
165
|
+
```
|
|
166
|
+
┌─────────────────────────────────────────────────┐
|
|
167
|
+
│ Claude Code │
|
|
168
|
+
│ (工具调用、任务完成、错误、空闲等事件) │
|
|
169
|
+
└──────────────────────┬──────────────────────────┘
|
|
170
|
+
│ hooks(写入 settings.json)
|
|
171
|
+
▼
|
|
172
|
+
┌──────────────────┐
|
|
173
|
+
│ bridge.ps1/.sh │ 异步,10 秒超时
|
|
174
|
+
└────────┬─────────┘
|
|
175
|
+
│ HTTP POST /event
|
|
176
|
+
▼
|
|
177
|
+
┌─────────────────────────────────────────────────┐
|
|
178
|
+
│ petdex-cc(Electron 主进程) │
|
|
179
|
+
│ │
|
|
180
|
+
│ ┌──────────────┐ ┌──────────┐ ┌────────────┐ │
|
|
181
|
+
│ │ event-mapper │ │ storage │ │ ai-speech │ │
|
|
182
|
+
│ │ 事件 → 动作 │ │ 等级、XP │ │ Claude Haiku│ │
|
|
183
|
+
│ └──────┬───────┘ └─────┬────┘ └─────┬──────┘ │
|
|
184
|
+
│ │ │ │ │
|
|
185
|
+
│ └─────────┬───────┘ │ │
|
|
186
|
+
│ ▼ │ │
|
|
187
|
+
│ ┌─────────────────┐ │ │
|
|
188
|
+
│ │ IPC → 渲染窗口 │◀─────────────┘ │
|
|
189
|
+
│ └────────┬────────┘ │
|
|
190
|
+
└──────────────────┼──────────────────────────────────┘
|
|
191
|
+
▼
|
|
192
|
+
┌──────────────────┐
|
|
193
|
+
│ 宠物窗口(HTML) │ 透明、始终置顶
|
|
194
|
+
│ │
|
|
195
|
+
│ ┌─── sprite ───┐ │ 9 种动画状态
|
|
196
|
+
│ │ 气泡 │ │ 3s / 8s 自动消失
|
|
197
|
+
│ │ 等级徽章 │ │ 等级标签 + 颜色
|
|
198
|
+
│ │ 特效 │ │ 光晕/光环/粒子/光环
|
|
199
|
+
│ └──────────────┘ │
|
|
200
|
+
└──────────────────┘
|
|
201
|
+
```
|
|
202
|
+
|
|
203
|
+
---
|
|
113
204
|
|
|
114
205
|
## 开发者安装
|
|
115
206
|
|
|
116
207
|
```bash
|
|
117
|
-
# 克隆仓库
|
|
118
208
|
git clone https://github.com/devnomad-byte/petdex-cc.git
|
|
119
209
|
cd petdex-cc
|
|
120
|
-
|
|
121
|
-
# 安装依赖
|
|
122
210
|
npm install
|
|
123
|
-
|
|
124
|
-
# 构建
|
|
125
211
|
npm run build
|
|
126
212
|
|
|
127
|
-
#
|
|
213
|
+
# 开发模式启动
|
|
128
214
|
npx electron .
|
|
129
215
|
|
|
130
|
-
#
|
|
216
|
+
# 全局安装使用 CLI
|
|
131
217
|
npm link
|
|
132
218
|
petdex-cc install boba
|
|
133
219
|
```
|
|
@@ -136,112 +222,102 @@ petdex-cc install boba
|
|
|
136
222
|
|
|
137
223
|
```
|
|
138
224
|
petdex-cc/
|
|
139
|
-
├── bin/cli.ts
|
|
225
|
+
├── bin/cli.ts CLI 入口(8 个命令)
|
|
140
226
|
├── src/
|
|
141
|
-
│ ├── main/
|
|
142
|
-
│ │ ├── index.ts
|
|
143
|
-
│ │ ├── server.ts
|
|
144
|
-
│ │ ├── ai-speech.ts
|
|
145
|
-
│ │ ├── storage.ts
|
|
146
|
-
│ │ ├── tray.ts
|
|
147
|
-
│ │ └── event-mapper.ts
|
|
148
|
-
│ ├── renderer/
|
|
149
|
-
│ │ ├── index.html
|
|
150
|
-
│ │ ├── renderer.ts
|
|
151
|
-
│ │ ├── pet-sprite.ts
|
|
152
|
-
│ │ ├── bubble.ts
|
|
153
|
-
│ │ ├── click-through.ts
|
|
154
|
-
│ │
|
|
155
|
-
│
|
|
156
|
-
│ ├──
|
|
157
|
-
│
|
|
227
|
+
│ ├── main/ Electron 主进程
|
|
228
|
+
│ │ ├── index.ts 窗口创建、事件循环、IPC
|
|
229
|
+
│ │ ├── server.ts HTTP 服务器(hooks → 宠物,端口 17321)
|
|
230
|
+
│ │ ├── ai-speech.ts AI 语音(Anthropic Messages API)
|
|
231
|
+
│ │ ├── storage.ts HMAC 签名状态持久化
|
|
232
|
+
│ │ ├── tray.ts 系统托盘(像素猫脸图标)
|
|
233
|
+
│ │ └── event-mapper.ts 8 种 hook 事件 → 宠物动作
|
|
234
|
+
│ ├── renderer/ Electron 渲染进程(宠物 UI)
|
|
235
|
+
│ │ ├── index.html 透明窗口 + CSS 特效
|
|
236
|
+
│ │ ├── renderer.ts IPC 协调 + 等级特效
|
|
237
|
+
│ │ ├── pet-sprite.ts 9 状态精灵图引擎
|
|
238
|
+
│ │ ├── bubble.ts 语音气泡系统
|
|
239
|
+
│ │ ├── click-through.ts 透明点击穿透
|
|
240
|
+
│ │ ├── drag.ts 拖拽 + 点击彩蛋
|
|
241
|
+
│ │ └── context-menu.ts 右键菜单
|
|
242
|
+
│ ├── cli/ CLI 命令实现
|
|
243
|
+
│ ├── hooks/ Claude Code hooks 注册
|
|
244
|
+
│ │ ├── register.ts 写入 ~/.claude/settings.json
|
|
245
|
+
│ │ ├── write-scripts.ts 跨平台 bridge 脚本
|
|
246
|
+
│ │ ├── bridge.ps1 Windows PowerShell bridge
|
|
247
|
+
│ │ └── bridge.sh Unix bash bridge
|
|
248
|
+
│ ├── petdex-api/ Petdex 注册中心客户端
|
|
249
|
+
│ │ ├── client.ts 清单获取 + slug 查询
|
|
250
|
+
│ │ └── download.ts 流式下载 + 进度回调
|
|
251
|
+
│ └── shared/ 共享类型和常量
|
|
158
252
|
```
|
|
159
253
|
|
|
160
|
-
|
|
254
|
+
---
|
|
161
255
|
|
|
162
|
-
|
|
163
|
-
|---|---|
|
|
164
|
-
| `npm run build` | TypeScript 编译 + 打包渲染器 |
|
|
165
|
-
| `npm run check` | 仅类型检查 |
|
|
166
|
-
| `npx electron .` | 从编译输出启动宠物 |
|
|
256
|
+
## 配置参考
|
|
167
257
|
|
|
168
|
-
|
|
258
|
+
### 自动检测
|
|
169
259
|
|
|
170
|
-
|
|
260
|
+
petdex-cc 自动从 `~/.claude/settings.json` 读取以下配置:
|
|
171
261
|
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
bridge.ps1 / bridge.sh
|
|
177
|
-
│
|
|
178
|
-
▼
|
|
179
|
-
HTTP POST /event (localhost)
|
|
180
|
-
│
|
|
181
|
-
▼
|
|
182
|
-
┌───────────────┐
|
|
183
|
-
│ petdex-cc │
|
|
184
|
-
│ (Electron) │
|
|
185
|
-
│ │
|
|
186
|
-
│ event-mapper │──▶ 宠物动作 + 语音气泡
|
|
187
|
-
│ storage │──▶ 升级检测
|
|
188
|
-
│ ai-speech │──▶ AI 生成的回复
|
|
189
|
-
└───────────────┘
|
|
190
|
-
│
|
|
191
|
-
▼
|
|
192
|
-
桌面宠物窗口
|
|
193
|
-
```
|
|
194
|
-
|
|
195
|
-
<br />
|
|
262
|
+
| 配置项 | 用途 |
|
|
263
|
+
|---|---|
|
|
264
|
+
| `ANTHROPIC_AUTH_TOKEN` | AI 语音的 API Key |
|
|
265
|
+
| `ANTHROPIC_BASE_URL` | AI 语音的 API 端点 |
|
|
196
266
|
|
|
197
|
-
|
|
267
|
+
### 手动配置
|
|
198
268
|
|
|
199
|
-
|
|
269
|
+
存储在 `~/.petdex-cc/config.json`:
|
|
200
270
|
|
|
201
271
|
```bash
|
|
202
|
-
|
|
203
|
-
petdex-cc config --api-key <your-key> --api-base-url <url>
|
|
204
|
-
|
|
205
|
-
# 或者自动从 Claude Code 设置中读取(~/.claude/settings.json)
|
|
272
|
+
petdex-cc config --api-key <key> --api-base-url <url> --cooldown 2
|
|
206
273
|
```
|
|
207
274
|
|
|
208
|
-
###
|
|
209
|
-
|
|
210
|
-
petdex-cc 自动注册以下 Claude Code hooks:
|
|
275
|
+
### 数据目录
|
|
211
276
|
|
|
212
|
-
|
|
|
277
|
+
| 路径 | 内容 |
|
|
213
278
|
|---|---|
|
|
214
|
-
|
|
|
215
|
-
| `
|
|
216
|
-
| `
|
|
217
|
-
|
|
|
218
|
-
| `
|
|
219
|
-
| `SessionStart` | Claude Code 启动或恢复时 |
|
|
220
|
-
| `SessionEnd` | Claude Code 会话结束时 |
|
|
221
|
-
| `TaskCompleted` | 任务标记完成时 |
|
|
279
|
+
| `~/.petdex-cc/pets/<slug>/` | 下载的精灵图 + pet.json |
|
|
280
|
+
| `~/.petdex-cc/data/state.json` | 等级、事件数、宠物 slug(HMAC 签名) |
|
|
281
|
+
| `~/.petdex-cc/data/state.sig` | HMAC-SHA256 签名 |
|
|
282
|
+
| `~/.petdex-cc/hooks/` | Bridge 脚本 |
|
|
283
|
+
| `~/.petdex-cc/config.json` | 用户配置(API Key、冷却时间) |
|
|
222
284
|
|
|
223
|
-
|
|
285
|
+
---
|
|
224
286
|
|
|
225
|
-
##
|
|
287
|
+
## Hooks 参考
|
|
226
288
|
|
|
227
|
-
|
|
289
|
+
petdex-cc 在 `~/.claude/settings.json` 中注册以下 hooks:
|
|
228
290
|
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
291
|
+
| Hook | 匹配器 | 触发时机 |
|
|
292
|
+
|---|---|---|
|
|
293
|
+
| `PostToolUse` | `Read\|Edit\|Write\|Bash\|Glob\|Grep` | 工具调用之后 |
|
|
294
|
+
| `PostToolUseFailure` | — | 工具调用失败时 |
|
|
295
|
+
| `Stop` | — | Claude 完成响应时 |
|
|
296
|
+
| `StopFailure` | — | Claude 停止并报错时 |
|
|
297
|
+
| `Notification` | `idle_prompt` | 空闲通知 |
|
|
298
|
+
| `SessionStart` | `startup\|resume` | Claude Code 启动或恢复时 |
|
|
299
|
+
| `SessionEnd` | — | Claude Code 会话结束时 |
|
|
300
|
+
| `TaskCompleted` | — | 任务标记完成时 |
|
|
233
301
|
|
|
234
|
-
|
|
302
|
+
---
|
|
235
303
|
|
|
236
|
-
##
|
|
304
|
+
## 后续计划
|
|
305
|
+
|
|
306
|
+
- [ ] 支持 Cursor
|
|
307
|
+
- [ ] 支持 Windsurf
|
|
308
|
+
- [ ] 支持 GitHub Copilot
|
|
309
|
+
- [ ] 更多宠物互动动作
|
|
310
|
+
- [ ] 宠物换装系统
|
|
237
311
|
|
|
238
|
-
|
|
312
|
+
---
|
|
313
|
+
|
|
314
|
+
## 许可证
|
|
239
315
|
|
|
240
|
-
|
|
316
|
+
[MIT](./LICENSE)
|
|
241
317
|
|
|
242
318
|
---
|
|
243
319
|
|
|
244
|
-
<
|
|
245
|
-
<sub>为 Claude Code 社区用心打造</sub><br />
|
|
246
|
-
<sub>宠物来自 <a href="https://petdex.crafter.run/">Petdex</a></sub>
|
|
247
|
-
</
|
|
320
|
+
<div align="center">
|
|
321
|
+
<sub>为 <a href="https://docs.anthropic.com/en/docs/claude-code">Claude Code</a> 社区用心打造</sub><br />
|
|
322
|
+
<sub>宠物来自 <a href="https://petdex.crafter.run/zh">Petdex</a></sub>
|
|
323
|
+
</div>
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"install.d.ts","sourceRoot":"","sources":["../../../src/cli/install.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"install.d.ts","sourceRoot":"","sources":["../../../src/cli/install.ts"],"names":[],"mappings":"AAoDA,wBAAsB,OAAO,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAoEzD"}
|
package/dist/src/cli/install.js
CHANGED
|
@@ -10,28 +10,79 @@ import { writeBridgeScripts } from "../hooks/write-scripts.js";
|
|
|
10
10
|
import { spawn } from "node:child_process";
|
|
11
11
|
import { getDefaultState, saveState } from "../main/storage.js";
|
|
12
12
|
import { stop } from "./stop.js";
|
|
13
|
+
// ANSI escape codes
|
|
14
|
+
const C = {
|
|
15
|
+
reset: "\x1b[0m",
|
|
16
|
+
bold: "\x1b[1m",
|
|
17
|
+
dim: "\x1b[2m",
|
|
18
|
+
green: "\x1b[32m",
|
|
19
|
+
magenta: "\x1b[35m",
|
|
20
|
+
cyan: "\x1b[36m",
|
|
21
|
+
yellow: "\x1b[33m",
|
|
22
|
+
red: "\x1b[31m",
|
|
23
|
+
};
|
|
24
|
+
const SPINNER_FRAMES = ["⣾", "⣽", "⣻", "⢿", "⡿", "⣟", "⣯", "⣷"];
|
|
25
|
+
let spinnerTimer = null;
|
|
26
|
+
function startSpinner(msg) {
|
|
27
|
+
let i = 0;
|
|
28
|
+
process.stdout.write(` ${C.dim}${SPINNER_FRAMES[0]} ${msg}${C.reset}`);
|
|
29
|
+
spinnerTimer = setInterval(() => {
|
|
30
|
+
i = (i + 1) % SPINNER_FRAMES.length;
|
|
31
|
+
process.stdout.write(`\r ${C.dim}${SPINNER_FRAMES[i]} ${msg}${C.reset}`);
|
|
32
|
+
}, 70);
|
|
33
|
+
}
|
|
34
|
+
function stopSpinner(msg) {
|
|
35
|
+
if (spinnerTimer) {
|
|
36
|
+
clearInterval(spinnerTimer);
|
|
37
|
+
spinnerTimer = null;
|
|
38
|
+
}
|
|
39
|
+
process.stdout.write(`\r ${C.green}✔${C.reset} ${msg}\n`);
|
|
40
|
+
}
|
|
41
|
+
function step(label) {
|
|
42
|
+
process.stdout.write(` ${C.dim}⟳${C.reset} ${label}...`);
|
|
43
|
+
}
|
|
44
|
+
function stepDone(label) {
|
|
45
|
+
process.stdout.write(`\r ${C.green}✔${C.reset} ${label} \n`);
|
|
46
|
+
}
|
|
13
47
|
const CLAUDE_DIR = join(homedir(), ".claude");
|
|
14
48
|
export async function install(slug) {
|
|
15
49
|
if (!existsSync(CLAUDE_DIR)) {
|
|
16
|
-
console.error(
|
|
50
|
+
console.error(`\n ${C.red}✖${C.reset} Claude Code not detected. Install Claude Code first.\n`);
|
|
17
51
|
process.exit(1);
|
|
18
52
|
}
|
|
19
|
-
|
|
53
|
+
// Header
|
|
54
|
+
console.log("");
|
|
55
|
+
console.log(` ${C.magenta}${C.bold}petdex-cc${C.reset} ${C.dim}v0.1.0${C.reset}`);
|
|
56
|
+
console.log(` ${C.dim}─────────────────────────────${C.reset}`);
|
|
57
|
+
// Step 1: Lookup
|
|
58
|
+
step("Searching Petdex");
|
|
20
59
|
const pet = await findPetBySlug(slug);
|
|
21
60
|
if (!pet) {
|
|
22
|
-
|
|
61
|
+
process.stdout.write(`\r ${C.red}✖${C.reset} Pet "${C.bold}${slug}${C.reset}" not found on Petdex.\n\n`);
|
|
23
62
|
process.exit(1);
|
|
24
63
|
}
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
const
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
64
|
+
stepDone(`Found ${C.cyan}${C.bold}${pet.displayName}${C.reset} ${C.dim}(${pet.kind})${C.reset}`);
|
|
65
|
+
// Step 2: Download with progress bar
|
|
66
|
+
const progressBar = (info) => {
|
|
67
|
+
const pct = info.bytesTotal > 0 ? Math.min(100, Math.round((info.bytesDone / info.bytesTotal) * 100)) : 0;
|
|
68
|
+
const filled = Math.round(pct / 3.33);
|
|
69
|
+
const empty = 30 - filled;
|
|
70
|
+
const bar = "█".repeat(filled) + "░".repeat(empty);
|
|
71
|
+
const mb = (info.bytesDone / 1024 / 1024).toFixed(1);
|
|
72
|
+
const totalMb = info.bytesTotal > 0 ? (info.bytesTotal / 1024 / 1024).toFixed(1) : "?";
|
|
73
|
+
process.stdout.write(`\r ${C.dim}⣟${C.reset} ${C.cyan}${info.phase}${C.reset} ${C.dim}[${bar}]${C.reset} ${C.bold}${pct}%${C.reset} ${C.dim}${mb}/${totalMb}MB${C.reset}`);
|
|
74
|
+
};
|
|
75
|
+
const paths = await downloadPetAssets(pet, progressBar);
|
|
76
|
+
stopSpinner(`${C.cyan}${pet.displayName}${C.reset} assets downloaded`);
|
|
77
|
+
// Step 3: Bridge scripts
|
|
78
|
+
step("Writing bridge scripts");
|
|
31
79
|
writeBridgeScripts();
|
|
32
|
-
|
|
80
|
+
stepDone("Bridge scripts ready");
|
|
81
|
+
// Step 4: Hooks
|
|
82
|
+
step("Registering Claude Code hooks");
|
|
33
83
|
registerHooks();
|
|
34
|
-
|
|
84
|
+
stepDone("Hooks configured");
|
|
85
|
+
// Step 5: Init state
|
|
35
86
|
saveState(getDefaultState(slug));
|
|
36
87
|
// Kill any existing pet process
|
|
37
88
|
stop();
|
|
@@ -45,9 +96,15 @@ export async function install(slug) {
|
|
|
45
96
|
}
|
|
46
97
|
}
|
|
47
98
|
catch { }
|
|
48
|
-
|
|
99
|
+
// Step 6: Start
|
|
100
|
+
step(`Launching ${pet.displayName}`);
|
|
49
101
|
await startElectron();
|
|
50
|
-
|
|
102
|
+
stepDone(`${C.cyan}${pet.displayName}${C.reset} is now on your desktop`);
|
|
103
|
+
// Final output
|
|
104
|
+
console.log("");
|
|
105
|
+
console.log(` ${C.green}✨ Installed!${C.reset} ${C.bold}${pet.displayName}${C.reset} is ready to go.`);
|
|
106
|
+
console.log(` ${C.dim}Your pet will react to Claude Code in real-time.${C.reset}`);
|
|
107
|
+
console.log("");
|
|
51
108
|
}
|
|
52
109
|
async function startElectron() {
|
|
53
110
|
const require = createRequire(import.meta.url);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"install.js","sourceRoot":"","sources":["../../../src/cli/install.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAA4B,MAAM,SAAS,CAAC;AAC/D,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAC1C,OAAO,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAClC,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AACzC,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAC5C,OAAO,EAAE,aAAa,EAAE,MAAM,yBAAyB,CAAC;AACxD,OAAO,EAAE,iBAAiB,EAAE,MAAM,2BAA2B,CAAC;AAC9D,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AACrD,OAAO,EAAE,kBAAkB,EAAE,MAAM,2BAA2B,CAAC;AAC/D,OAAO,EAAE,KAAK,EAAE,MAAM,oBAAoB,CAAC;AAC3C,OAAO,EAAE,eAAe,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAC;AAChE,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAEjC,MAAM,UAAU,GAAG,IAAI,CAAC,OAAO,EAAE,EAAE,SAAS,CAAC,CAAC;AAE9C,MAAM,CAAC,KAAK,UAAU,OAAO,CAAC,IAAY;IACxC,IAAI,CAAC,UAAU,CAAC,UAAU,CAAC,EAAE,CAAC;QAC5B,OAAO,CAAC,KAAK,CAAC,
|
|
1
|
+
{"version":3,"file":"install.js","sourceRoot":"","sources":["../../../src/cli/install.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,6 +1,11 @@
|
|
|
1
1
|
import type { PetManifestEntry } from "./client.js";
|
|
2
2
|
export declare function getPetDir(slug: string): string;
|
|
3
|
-
export
|
|
3
|
+
export type ProgressCallback = (info: {
|
|
4
|
+
phase: string;
|
|
5
|
+
bytesDone: number;
|
|
6
|
+
bytesTotal: number;
|
|
7
|
+
}) => void;
|
|
8
|
+
export declare function downloadPetAssets(pet: PetManifestEntry, onProgress?: ProgressCallback): Promise<{
|
|
4
9
|
spritesheetPath: string;
|
|
5
10
|
petJsonPath: string;
|
|
6
11
|
}>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"download.d.ts","sourceRoot":"","sources":["../../../src/petdex-api/download.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAIpD,wBAAgB,SAAS,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAE9C;AAQD,wBAAsB,iBAAiB,CACrC,GAAG,EAAE,gBAAgB,
|
|
1
|
+
{"version":3,"file":"download.d.ts","sourceRoot":"","sources":["../../../src/petdex-api/download.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAIpD,wBAAgB,SAAS,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAE9C;AAQD,MAAM,MAAM,gBAAgB,GAAG,CAAC,IAAI,EAAE;IACpC,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,MAAM,CAAC;CACpB,KAAK,IAAI,CAAC;AAgCX,wBAAsB,iBAAiB,CACrC,GAAG,EAAE,gBAAgB,EACrB,UAAU,CAAC,EAAE,gBAAgB,GAC5B,OAAO,CAAC;IAAE,eAAe,EAAE,MAAM,CAAC;IAAC,WAAW,EAAE,MAAM,CAAA;CAAE,CAAC,CAY3D;AAED,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAWrD"}
|
|
@@ -11,26 +11,37 @@ function resolveExtension(url) {
|
|
|
11
11
|
return ".png";
|
|
12
12
|
return ".webp";
|
|
13
13
|
}
|
|
14
|
-
|
|
14
|
+
async function downloadWithProgress(url, destPath, phase, onProgress) {
|
|
15
|
+
const response = await fetch(url);
|
|
16
|
+
if (!response.ok) {
|
|
17
|
+
throw new Error(`Failed to download ${url}: ${response.status} ${response.statusText}`);
|
|
18
|
+
}
|
|
19
|
+
const total = parseInt(response.headers.get("content-length") || "0", 10);
|
|
20
|
+
const reader = response.body?.getReader();
|
|
21
|
+
if (!reader)
|
|
22
|
+
throw new Error("No response body");
|
|
23
|
+
const chunks = [];
|
|
24
|
+
let done = 0;
|
|
25
|
+
for (;;) {
|
|
26
|
+
const { value, done: ended } = await reader.read();
|
|
27
|
+
if (ended)
|
|
28
|
+
break;
|
|
29
|
+
chunks.push(value);
|
|
30
|
+
done += value.length;
|
|
31
|
+
if (onProgress)
|
|
32
|
+
onProgress({ phase, bytesDone: done, bytesTotal: total || done });
|
|
33
|
+
}
|
|
34
|
+
const buffer = Buffer.concat(chunks);
|
|
35
|
+
fs.writeFileSync(destPath, buffer);
|
|
36
|
+
}
|
|
37
|
+
export async function downloadPetAssets(pet, onProgress) {
|
|
15
38
|
const petDir = getPetDir(pet.slug);
|
|
16
39
|
fs.mkdirSync(petDir, { recursive: true });
|
|
17
40
|
const spritesheetExt = resolveExtension(pet.spritesheetUrl);
|
|
18
41
|
const spritesheetPath = path.join(petDir, `spritesheet${spritesheetExt}`);
|
|
19
42
|
const petJsonPath = path.join(petDir, "pet.json");
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
if (!spritesheetResponse.ok) {
|
|
23
|
-
throw new Error(`Failed to download spritesheet for ${pet.slug}: ${spritesheetResponse.status} ${spritesheetResponse.statusText}`);
|
|
24
|
-
}
|
|
25
|
-
const spritesheetBuffer = Buffer.from(await spritesheetResponse.arrayBuffer());
|
|
26
|
-
fs.writeFileSync(spritesheetPath, spritesheetBuffer);
|
|
27
|
-
// Download pet.json
|
|
28
|
-
const petJsonResponse = await fetch(pet.petJsonUrl);
|
|
29
|
-
if (!petJsonResponse.ok) {
|
|
30
|
-
throw new Error(`Failed to download pet.json for ${pet.slug}: ${petJsonResponse.status} ${petJsonResponse.statusText}`);
|
|
31
|
-
}
|
|
32
|
-
const petJsonBuffer = Buffer.from(await petJsonResponse.arrayBuffer());
|
|
33
|
-
fs.writeFileSync(petJsonPath, petJsonBuffer);
|
|
43
|
+
await downloadWithProgress(pet.spritesheetUrl, spritesheetPath, "spritesheet", onProgress);
|
|
44
|
+
await downloadWithProgress(pet.petJsonUrl, petJsonPath, "metadata", onProgress);
|
|
34
45
|
return { spritesheetPath, petJsonPath };
|
|
35
46
|
}
|
|
36
47
|
export function isPetDownloaded(slug) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"download.js","sourceRoot":"","sources":["../../../src/petdex-api/download.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,SAAS,CAAC;AACzB,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAGlC,MAAM,UAAU,GAAG,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,EAAE,YAAY,CAAC,CAAC;AAEtD,MAAM,UAAU,SAAS,CAAC,IAAY;IACpC,OAAO,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,MAAM,EAAE,IAAI,CAAC,CAAC;AAC7C,CAAC;AAED,SAAS,gBAAgB,CAAC,GAAW;IACnC,MAAM,QAAQ,GAAG,IAAI,GAAG,CAAC,GAAG,CAAC,CAAC,QAAQ,CAAC;IACvC,IAAI,QAAQ,CAAC,QAAQ,CAAC,MAAM,CAAC;QAAE,OAAO,MAAM,CAAC;IAC7C,OAAO,OAAO,CAAC;AACjB,CAAC;
|
|
1
|
+
{"version":3,"file":"download.js","sourceRoot":"","sources":["../../../src/petdex-api/download.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED