clauddy 1.1.0 → 1.3.0

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.
Files changed (3) hide show
  1. package/README.md +34 -20
  2. package/bin/clauddy.js +55 -8
  3. package/package.json +1 -1
package/README.md CHANGED
@@ -46,21 +46,21 @@ The token is saved locally (see [Data & privacy](#data--privacy)) and refreshed
46
46
  </tr>
47
47
  </table>
48
48
 
49
- Plus a welcome **wave** on launch. You can preview any state from the terminal with [`./pet`](#simulate-states-pet).
49
+ Plus a welcome **wave** on launch. You can [poke the pet from the terminal](#play-with-the-pet) too.
50
50
 
51
51
  ## Install
52
52
 
53
53
  macOS (Apple Silicon). Two ways, depending on what you want:
54
54
 
55
- ### 1. Download the app — opens at login (recommended)
55
+ ### 1. Install as an app — opens at login (recommended)
56
56
 
57
- For everyday use, grab the prebuilt app no terminal, no setup:
57
+ One command it downloads the latest release and drops it in `/Applications`:
58
58
 
59
- 1. Download the latest **`Claude Usage Monitor-…-mac.zip`** from the [**Releases**](https://github.com/renatoaug/claude-usage-monitor/releases/latest) page.
60
- 2. Unzip it and drag **Claude Usage Monitor.app** into `/Applications`.
61
- 3. First open: right-click the app → **Open** → **Open** (it's unsigned).
59
+ ```bash
60
+ curl -fsSL https://raw.githubusercontent.com/renatoaug/claude-usage-monitor/main/install.sh | bash
61
+ ```
62
62
 
63
- It registers itself in **Login Items**, so it **starts automatically** with your Mac — set it and forget it.
63
+ No Gatekeeper warning: files fetched with `curl` aren't quarantined like browser downloads, so the (unsigned) app just opens. It registers itself in **Login Items**, so it **starts automatically** with your Mac — set it and forget it.
64
64
 
65
65
  ### 2. Run it via `bunx` (no install)
66
66
 
@@ -74,6 +74,19 @@ The first run downloads Electron, so give it a moment. Handy for a quick run, bu
74
74
 
75
75
  > The app keeps its data in `~/.claude-usage-monitor`, regardless of how you run it.
76
76
 
77
+ <details>
78
+ <summary>Prefer to download the app by hand?</summary>
79
+
80
+ Grab the **`…-mac.zip`** from [Releases](https://github.com/renatoaug/claude-usage-monitor/releases/latest), unzip, and drag the app to `/Applications`. The browser quarantines it, so macOS will call it *"damaged"* — clear the flag once (Terminal needs **Full Disk Access**):
81
+
82
+ ```bash
83
+ xattr -dr com.apple.quarantine "/Applications/Claude Usage Monitor.app"
84
+ ```
85
+
86
+ The `curl` installer above avoids all of this.
87
+
88
+ </details>
89
+
77
90
  ## Controls
78
91
 
79
92
  - **Drag** the widget anywhere on screen
@@ -100,22 +113,25 @@ Settings saved from the UI live in `~/.claude-usage-monitor/config.json`, so you
100
113
  }
101
114
  ```
102
115
 
103
- ## Simulate states (`./pet`)
116
+ ## Play with the pet
104
117
 
105
- While developing the animations, force any state from the terminal — the app watches `~/.claude-usage-monitor/debug.json` and reacts live (no rebuild needed). Run from the repo root:
118
+ With the widget running, poke it from the terminal — just for fun:
106
119
 
107
120
  ```bash
108
- ./pet fire # 🔥 on fire — flames, shivers, red tint
109
- ./pet sleeping # 😴 sleeping blue zzz, closed eyes, moonlight
110
- ./pet working # 🍴 working — eats token coins and hops
111
- ./pet idle # 🙂 idle — breathe + blink
112
-
113
- ./pet poke # 💕 one-shot squish + hearts
114
- ./pet celebrate # 🎉 one-shot jump + confetti burst
115
-
116
- ./pet auto # ↩️ release control, back to real usage data
121
+ bunx clauddy poke # 💕 squish + hearts
122
+ bunx clauddy celebrate # 🎉 jump + confetti
123
+ bunx clauddy fire # 🔥 on fire
124
+ bunx clauddy sleeping # 😴 blue zzz
125
+ bunx clauddy working # 🍴 eats token coins
126
+ bunx clauddy tired # 🥵 maxed out
127
+ bunx clauddy idle # 🙂 calm
128
+ bunx clauddy auto # ↩️ back to your real usage
117
129
  ```
118
130
 
131
+ Each state is written to the data dir the running widget watches, so it reacts
132
+ live. (Installed globally? Drop the `bunx`: `clauddy poke`. Working on the repo?
133
+ `./pet <state>` does the same.)
134
+
119
135
  ## How it works
120
136
 
121
137
  - **`main.js`** — Electron main process: frameless, transparent, always-on-top window; polls usage; fires macOS notifications; watches `config.json` and `debug.json`.
@@ -150,5 +166,3 @@ your PRs.
150
166
 
151
167
  - `feat:` → minor, `fix:` → patch, `feat!:`/`BREAKING CHANGE` → major.
152
168
  - `docs:`/`chore:`/`ci:` etc. don't trigger a release.
153
- - Needs an **`NPM_TOKEN`** repo secret (an npm automation token); `GITHUB_TOKEN`
154
- is automatic.
package/bin/clauddy.js CHANGED
@@ -1,12 +1,59 @@
1
1
  #!/usr/bin/env node
2
2
 
3
- // Entry point when installed from npm / run via `bunx claude-usage-monitor`:
4
- // spawn the Electron runtime pointed at the app's main process.
5
- const { spawn } = require('node:child_process')
3
+ // `clauddy` → launch the widget (spawns Electron on main.js)
4
+ // `clauddy <state>` → poke the running widget for fun/demo (writes the state
5
+ // to the data dir the app watches; the app reacts live)
6
6
  const path = require('node:path')
7
- const electron = require('electron')
7
+ const fs = require('node:fs')
8
+ const os = require('node:os')
8
9
 
9
- const child = spawn(electron, [path.join(__dirname, '..', 'main.js')], {
10
- stdio: 'inherit',
11
- })
12
- child.on('close', (code) => process.exit(code ?? 0))
10
+ // same data dir the app uses (respects CLAUDE_CONFIG_DIR for multi-account)
11
+ const dataDir = process.env.CLAUDE_CONFIG_DIR
12
+ ? path.join(process.env.CLAUDE_CONFIG_DIR, 'usage-monitor')
13
+ : path.join(os.homedir(), '.claude-usage-monitor')
14
+
15
+ const STATES = [
16
+ 'fire',
17
+ 'sleeping',
18
+ 'working',
19
+ 'tired',
20
+ 'idle',
21
+ 'poke',
22
+ 'celebrate',
23
+ 'auto',
24
+ 'clear',
25
+ ]
26
+ const arg = process.argv[2]
27
+
28
+ if (!arg) {
29
+ // no argument → launch the app
30
+ const { spawn } = require('node:child_process')
31
+ const electron = require('electron')
32
+ const child = spawn(electron, [path.join(__dirname, '..', 'main.js')], { stdio: 'inherit' })
33
+ child.on('close', (code) => process.exit(code ?? 0))
34
+ } else if (arg === '--help' || arg === '-h') {
35
+ console.log(
36
+ [
37
+ 'clauddy — a cute desktop pet that tracks your Claude Code usage',
38
+ '',
39
+ 'Usage:',
40
+ ' clauddy launch the widget',
41
+ ' clauddy <state> poke the running widget (just for fun)',
42
+ '',
43
+ 'States: fire, sleeping, working, tired, idle, poke, celebrate, auto',
44
+ '(the widget must be running for a state to show)',
45
+ ].join('\n'),
46
+ )
47
+ } else if (STATES.includes(arg)) {
48
+ // write the state for the running app to pick up
49
+ fs.mkdirSync(dataDir, { recursive: true })
50
+ fs.writeFileSync(
51
+ path.join(dataDir, 'debug.json'),
52
+ `${JSON.stringify({ state: arg, t: Date.now() })}\n`,
53
+ )
54
+ console.log(`clauddy → ${arg} (the running widget will react)`)
55
+ } else {
56
+ console.error(`clauddy: unknown command "${arg}"`)
57
+ console.error('try: fire, sleeping, working, tired, idle, poke, celebrate, auto — or --help')
58
+ process.exit(1)
59
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "clauddy",
3
- "version": "1.1.0",
3
+ "version": "1.3.0",
4
4
  "description": "A cute desktop pet that tracks your Claude Code usage",
5
5
  "main": "main.js",
6
6
  "bin": {