claude-rpc 0.6.0 → 0.6.1
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 +145 -144
- package/package.json +1 -1
- package/src/install.js +7 -0
- package/src/version.js +1 -1
package/README.md
CHANGED
|
@@ -8,36 +8,39 @@
|
|
|
8
8
|
# claude-rpc
|
|
9
9
|
|
|
10
10
|
**Discord Rich Presence for [Claude Code](https://claude.com/claude-code).**
|
|
11
|
-
Your model, project, current tool, tokens, and lifetime stats —
|
|
11
|
+
Your live model, project, current tool, tokens, and lifetime stats — in your Discord profile. Driven by the hooks Claude Code already fires. Zero polling between sessions.
|
|
12
12
|
|
|
13
13
|
[](LICENSE)
|
|
14
14
|
[](https://nodejs.org)
|
|
15
15
|
[](https://claude.com/claude-code)
|
|
16
16
|
[](https://discord.com/developers/docs/topics/rpc)
|
|
17
|
+
[](https://github.com/rar-file/claude-rpc/releases/latest)
|
|
17
18
|
|
|
18
19
|
</div>
|
|
19
20
|
|
|
20
21
|
---
|
|
21
22
|
|
|
22
23
|
<div align="center">
|
|
23
|
-
<img src="docs/demo.gif" width="560" alt="Discord Rich Presence card
|
|
24
|
+
<img src="docs/demo.gif" width="560" alt="Discord Rich Presence card showing Claude Code working in claude-rpc on Opus 4.7" />
|
|
24
25
|
</div>
|
|
25
26
|
|
|
26
|
-
|
|
27
|
+
A small Node daemon that takes the lifecycle events Claude Code already fires and pipes them into the Discord rich-presence card on your profile. Your friends see what you're building; your future self gets lifetime stats. Built solo, on weekends.
|
|
27
28
|
|
|
28
|
-
|
|
29
|
+
## install
|
|
30
|
+
|
|
31
|
+
**Windows (no Node required)** — [grab the portable exe from the latest release](https://github.com/rar-file/claude-rpc/releases/latest):
|
|
29
32
|
|
|
30
33
|
```sh
|
|
31
34
|
claude-rpc setup
|
|
32
35
|
claude-rpc start
|
|
33
36
|
```
|
|
34
37
|
|
|
35
|
-
That's
|
|
38
|
+
That's the whole pitch. Open Claude Code in any project — the daemon picks it up within a second. Something looks wrong? `claude-rpc doctor`.
|
|
36
39
|
|
|
37
|
-
The Discord *desktop* app must be running
|
|
40
|
+
The Discord *desktop* app must be running. The browser client doesn't expose the local IPC bridge that Rich Presence uses.
|
|
38
41
|
|
|
39
42
|
<details>
|
|
40
|
-
<summary><b>
|
|
43
|
+
<summary><b>other platforms / from source</b></summary>
|
|
41
44
|
|
|
42
45
|
```sh
|
|
43
46
|
git clone https://github.com/rar-file/claude-rpc.git
|
|
@@ -47,99 +50,77 @@ node ./src/cli.js setup
|
|
|
47
50
|
node ./src/cli.js start
|
|
48
51
|
```
|
|
49
52
|
|
|
50
|
-
Or `npm install -g claude-rpc` for the global bin.
|
|
53
|
+
Or `npm install -g claude-rpc` for the global bin. Both modes survive `npm update` without losing your `clientId` — user config lives under the per-OS config dir, not inside `node_modules`.
|
|
51
54
|
</details>
|
|
52
55
|
|
|
53
56
|
<details>
|
|
54
|
-
<summary><b>
|
|
57
|
+
<summary><b>use your own Discord app</b></summary>
|
|
55
58
|
|
|
56
|
-
A working Discord application is bundled into the default config — you don't need to register your own to get started.
|
|
59
|
+
A working public Discord application is bundled into the default config — you don't need to register your own to get started. If you want a different app name on the card, create one in the [Discord Developer Portal](https://discord.com/developers/applications), copy the Application ID, and drop it into your config:
|
|
57
60
|
|
|
58
61
|
```sh
|
|
59
|
-
# Linux
|
|
62
|
+
# Linux
|
|
60
63
|
echo '{ "clientId": "YOUR_ID" }' > ~/.config/claude-rpc/config.json
|
|
61
|
-
#
|
|
62
|
-
echo { "clientId": "YOUR_ID" } >
|
|
64
|
+
# macOS
|
|
65
|
+
echo '{ "clientId": "YOUR_ID" }' > ~/Library/Application\ Support/claude-rpc/config.json
|
|
66
|
+
# Windows (PowerShell)
|
|
67
|
+
'{ "clientId": "YOUR_ID" }' | Set-Content $env:APPDATA\claude-rpc\config.json
|
|
63
68
|
```
|
|
64
69
|
|
|
65
|
-
|
|
70
|
+
`claude-rpc upgrade-config` if you're carrying forward a v0.3-era file.
|
|
66
71
|
</details>
|
|
67
72
|
|
|
68
|
-
##
|
|
73
|
+
## what claude-rpc does
|
|
69
74
|
|
|
70
|
-
|
|
75
|
+
### on discord
|
|
71
76
|
|
|
72
|
-
|
|
73
|
-
| :--- | :--- |
|
|
74
|
-
| 🔴 **Live status** | Model, project, current tool/file, and token counts update as you work |
|
|
75
|
-
| 🎞️ **Status art** | Large image swaps between *working*, *thinking*, *idle*, *stale*, *notification* |
|
|
76
|
-
| 🔁 **Rotation frames** | Cycle through today's stats, streak, top file, lifetime totals, anything you template |
|
|
77
|
-
| 🐙 **Auto GitHub button** | When your cwd is a git repo with a github origin, a *View on GitHub* button appears |
|
|
78
|
-
| 🔒 **Privacy mode** | Per-project `.claude-rpc.json`, runtime `claude-rpc private` toggle, glob-pattern matchers, and auto-detection of GitHub private repos via `gh` |
|
|
77
|
+
A card that updates as you work. The large image swaps between five states (working / thinking / idle / stale / notification — those gifs at the top of this README). The two lines of text rotate through frames you template — current file, today's hours, lifetime totals, top hotspot, code churn, cost — and the daemon skips frames whose required template variables are empty. The `SessionEnd` hook clears the card instantly when you close Claude Code; no "is it still running?" timeout.
|
|
79
78
|
|
|
80
|
-
|
|
79
|
+
A *View on GitHub →* button appears automatically when your cwd is a git repo with a github origin. The daemon checks `.git/config` directly — no shell-out, no surprise GH API call.
|
|
81
80
|
|
|
82
|
-
|
|
83
|
-
| :--- | :--- |
|
|
84
|
-
| 📊 **All-time aggregates** | Hours, prompts, tokens, streaks, hotspots, lines changed, languages, cost, bash usage, web domains, subagent runs — incremental scanner over `~/.claude/projects/*.jsonl` |
|
|
85
|
-
| 💰 **Cost estimate** | Per-model spend (Opus/Sonnet/Haiku) using public list prices — editable in `src/pricing.js` |
|
|
86
|
-
| 🧠 **Insights** | `claude-rpc insights` generates 3–5 contextual lines: weekly trend, peak weekday, hotspot file, cost pace, streak progress |
|
|
87
|
-
| 🖥️ **CLI dashboard** | `claude-rpc status` — heatmap, hour histogram, top tools / files / projects / languages / bash commands / cost |
|
|
88
|
-
| 🌐 **Web dashboard** | `claude-rpc serve` — range selector (7d / 30d / 90d / 1y / All), live SSE updates, project drilldown, day-detail modal, theme toggle |
|
|
89
|
-
| 🪪 **Badges & cards** | `claude-rpc badge --metric hours --range 7d` (Shields-style SVG) and `claude-rpc card --range year` (poster-style summary) |
|
|
90
|
-
| ⚙️ **Config GUI** | Electron app — six tabs: Presence, Discord, Assets, Timing, Daemon, Stats |
|
|
81
|
+
### on your machine
|
|
91
82
|
|
|
92
|
-
|
|
83
|
+
Three local surfaces, all reading the same `~/.claude-rpc/aggregate.json`:
|
|
93
84
|
|
|
94
85
|
<table>
|
|
95
86
|
<tr>
|
|
96
|
-
<td align="center" width="50%"><b>
|
|
97
|
-
<td align="center" width="50%"><b>
|
|
87
|
+
<td align="center" width="50%"><b>web dashboard</b><br/><sub><code>claude-rpc serve</code> · port 47474</sub><br/><br/><img src="docs/dashboard.png" alt="Web dashboard with range selector, activity chart, heatmap, cost panel, languages stack, and leaderboards" /></td>
|
|
88
|
+
<td align="center" width="50%"><b>settings gui</b><br/><sub><code>npm run dashboard</code> · Electron</sub><br/><br/><img src="docs/electron.png" alt="Electron config editor with Presence / Discord / Assets / Timing / Daemon / Stats tabs" /></td>
|
|
98
89
|
</tr>
|
|
99
90
|
</table>
|
|
100
91
|
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
| `start` | Start the daemon (detached) |
|
|
109
|
-
| `stop` | Stop the daemon |
|
|
110
|
-
| `restart` | Stop then start |
|
|
111
|
-
| `status` | Current session + all-time stats (interactive TUI or `--dump`) |
|
|
112
|
-
| `today` | Today's stats + 24h histogram |
|
|
113
|
-
| `week` | This week's stats + daily breakdown |
|
|
114
|
-
| `serve` | Open the local web dashboard (port 47474) |
|
|
115
|
-
| `preview` | Show how each rotation frame renders right now |
|
|
116
|
-
| `scan` / `rescan`| Incremental / forced re-parse of `~/.claude/projects` |
|
|
117
|
-
| `backfill <dir>` | Import transcripts from any folder (backup, other machine) |
|
|
118
|
-
| `insights` | Print 3–5 auto-generated insight lines |
|
|
119
|
-
| `badge` | Render a Shields-style SVG (`--metric` `--range` `--out`)|
|
|
120
|
-
| `card` | Poster-style SVG summary (`--range year\|month\|week\|all`) |
|
|
121
|
-
| `private` / `public` / `privacy` | Per-cwd visibility toggles + status |
|
|
122
|
-
| `doctor` | Diagnostic checklist — common-failure triage |
|
|
123
|
-
| `tail` / `logs` | Tail the daemon log |
|
|
124
|
-
| `daemon` | Run the daemon in the foreground (debug) |
|
|
92
|
+
```text
|
|
93
|
+
claude-rpc status (TUI — heatmap, hour histogram, leaderboards)
|
|
94
|
+
claude-rpc today (today's stats, focused)
|
|
95
|
+
claude-rpc week (weekday breakdown)
|
|
96
|
+
claude-rpc preview (every rotation frame rendered with real data)
|
|
97
|
+
claude-rpc insights (3–5 auto-generated lines: trend, peak, hotspot)
|
|
98
|
+
```
|
|
125
99
|
|
|
126
|
-
|
|
100
|
+
The web dashboard pushes updates via SSE; the TUI refreshes on a 3-second tick.
|
|
101
|
+
|
|
102
|
+
### beyond your machine
|
|
127
103
|
|
|
128
|
-
|
|
104
|
+
Shields-style badges and a poster-style summary card you can paste into a README or a Discord message:
|
|
129
105
|
|
|
130
106
|
```sh
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
npm run dist:mac # → .dmg
|
|
135
|
-
npm run dist:win # → portable .exe
|
|
107
|
+
claude-rpc badge --metric hours --range 7d --out claude-hours.svg
|
|
108
|
+
claude-rpc badge --metric streak --out claude-streak.svg
|
|
109
|
+
claude-rpc card --range year --out year-on-claude.svg
|
|
136
110
|
```
|
|
137
111
|
|
|
138
|
-
|
|
112
|
+
<div align="center">
|
|
113
|
+
<img src="site/examples/year-on-claude.svg" width="560" alt="Year-on-claude card — hours, prompts, tokens, lines, cost, daily activity strip" />
|
|
114
|
+
</div>
|
|
139
115
|
|
|
140
|
-
|
|
116
|
+
Live equivalents when the daemon is up:
|
|
141
117
|
|
|
142
|
-
|
|
118
|
+
- `http://127.0.0.1:47474/api/badge.svg?metric=hours&range=7d`
|
|
119
|
+
- `http://127.0.0.1:47474/api/card.svg?range=year`
|
|
120
|
+
|
|
121
|
+
Cost numbers come from `src/pricing.js`, seeded with **approximate** public list prices. Your actual Claude Code subscription bill is unrelated.
|
|
122
|
+
|
|
123
|
+
## three pieces, glued by json files
|
|
143
124
|
|
|
144
125
|
```
|
|
145
126
|
Claude Code Discord desktop
|
|
@@ -157,104 +138,124 @@ Three cooperating pieces, glued by JSON files on disk.
|
|
|
157
138
|
└────────────┘
|
|
158
139
|
```
|
|
159
140
|
|
|
160
|
-
|
|
161
|
-
2. **Daemon** (`src/daemon.js`) — Long-running. Connects to Discord's local IPC, watches the state file plus periodic transcript scans, pushes presence frames every few seconds. Exponential backoff with jitter on reconnect.
|
|
162
|
-
3. **Scanner** (`src/scanner.js`) — Walks `~/.claude/projects/**/*.jsonl` transcripts for all-time aggregates. Cached at `~/.claude-rpc/aggregate.json` for incremental updates.
|
|
141
|
+
No database, no message bus, no background polling when Claude Code isn't running. State on disk you can `cat` and `jq`. The single runtime dependency is `@xhayper/discord-rpc`.
|
|
163
142
|
|
|
164
|
-
|
|
143
|
+
1. **hook** ([`src/hook.js`](src/hook.js)) — Claude Code spawns it on every lifecycle event. Parses the JSON from stdin and mutates the shared state file. Runs in ~20ms.
|
|
144
|
+
2. **daemon** ([`src/daemon.js`](src/daemon.js)) — long-running. Connects to Discord's local IPC, watches the state file, pushes presence frames every few seconds. Exponential backoff with jitter on reconnect; `daemon.log` rotates at 5 MB.
|
|
145
|
+
3. **scanner** ([`src/scanner.js`](src/scanner.js)) — walks `~/.claude/projects/**/*.jsonl` for all-time aggregates (active time, prompts, tools, tokens, streaks, hotspots, lines, languages, cost, bash, web, subagents). Incremental — re-parses only changed files.
|
|
146
|
+
|
|
147
|
+
Persistent state, all human-readable JSON:
|
|
165
148
|
|
|
166
149
|
| Path | What |
|
|
167
150
|
| ---- | ---- |
|
|
168
151
|
| `$TMPDIR/claude-rpc/state.json` | Current session, volatile |
|
|
169
152
|
| `~/.claude-rpc/aggregate.json` | All-time aggregates |
|
|
170
153
|
| `~/.claude-rpc/scan-cache.json` | Per-transcript scan cache |
|
|
154
|
+
| `~/.claude-rpc/private-list.json` | Runtime privacy toggles |
|
|
171
155
|
| `~/.claude/settings.json` | Hook registrations (managed by `setup`) |
|
|
172
156
|
|
|
173
|
-
User config lives at `%APPDATA%\claude-rpc\config.json` (Windows), `~/Library/Application Support/claude-rpc/config.json` (macOS), or `$XDG_CONFIG_HOME/claude-rpc/config.json` (Linux). It only needs to hold *overrides* —
|
|
157
|
+
User config lives at `%APPDATA%\claude-rpc\config.json` (Windows), `~/Library/Application Support/claude-rpc/config.json` (macOS), or `$XDG_CONFIG_HOME/claude-rpc/config.json` (Linux). It only needs to hold *overrides* — every key has a baked default. `{ "clientId": "..." }` is a complete config file. Defaults live in [`src/default-config.js`](src/default-config.js); the loader deep-merges over them.
|
|
174
158
|
|
|
175
|
-
|
|
176
|
-
<summary><b>Configuration reference</b></summary>
|
|
177
|
-
|
|
178
|
-
Every key is optional. The shipped defaults work out of the box. Override what you want:
|
|
179
|
-
|
|
180
|
-
| Key | Default | Notes |
|
|
181
|
-
| ------------------------- | ------- | ------------------------------------------------------------------- |
|
|
182
|
-
| `clientId` | bundled | Discord application ID (a working public app ships by default) |
|
|
183
|
-
| `updateIntervalMs` | `4000` | How often the daemon pushes to Discord |
|
|
184
|
-
| `rotationIntervalMs` | `12000` | How fast rotation frames cycle |
|
|
185
|
-
| `rescanIntervalSec` | `300` | How often transcripts are re-aggregated |
|
|
186
|
-
| `idleThresholdSec` | `60` | No activity for this long → status `idle` |
|
|
187
|
-
| `staleSessionMin` | `5` | No activity (minutes) → status `stale`; presence cleared |
|
|
188
|
-
| `notificationWindowSec` | `8` | How long the `notification` status sticks |
|
|
189
|
-
| `showElapsed` | `true` | Include the elapsed timer |
|
|
190
|
-
| `activityType` | `0` | `0` Playing, `2` Listening, `3` Watching, `5` Competing |
|
|
191
|
-
| `statusAssets` | gifs | Image per status (working / thinking / idle / stale / notification) |
|
|
192
|
-
| `presence.byStatus` | full | Per-status template block (preferred over `rotation`) |
|
|
193
|
-
| `presence.rotation` | — | Legacy: flat array of `{ details, state, requires? }` |
|
|
194
|
-
| `presence.buttons` | one | Up to 2 `{ label, url }` buttons |
|
|
195
|
-
| `presence.largeImageKey` | gif | Fallback large image when no `statusAssets` match |
|
|
196
|
-
| `presence.largeImageText` | tpl | Tooltip on hover |
|
|
197
|
-
| `privacy.patterns` | `[]` | Glob list of cwd basenames to treat as private |
|
|
198
|
-
| `privacy.mode` | hidden | What `patterns` does — `hidden` / `name-only` / `public` |
|
|
199
|
-
|
|
200
|
-
Image precedence: `statusAssets[status]` → `modelAssets[opus|sonnet|haiku]` → `presence.largeImageKey`.
|
|
159
|
+
## privacy
|
|
201
160
|
|
|
202
|
-
|
|
161
|
+
Per-project, runtime, or auto-detected — whichever fits how you work.
|
|
203
162
|
|
|
204
|
-
|
|
205
|
-
<
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
| ----------------------- | ------------------ |
|
|
211
|
-
| `{statusVerbose}` | `Working` |
|
|
212
|
-
| `{project}` | `claude-rpc` |
|
|
213
|
-
| `{modelPretty}` | `Opus 4.7` |
|
|
214
|
-
| `{currentToolPretty}` | `Edit` |
|
|
215
|
-
| `{currentFilePretty}` | `src/app/page.tsx` |
|
|
216
|
-
| `{tokensFmt}` | `2.3k` |
|
|
217
|
-
| `{messagesLabel}` | `8 prompts` |
|
|
218
|
-
| `{todayHours}` | `56m` |
|
|
219
|
-
| `{weekHours}` | `3.1h` |
|
|
220
|
-
| `{streakLabel}` | `7-day streak` |
|
|
221
|
-
| `{allHours}` | `52h` |
|
|
222
|
-
| `{allTokensFmt}` | `2.82B` |
|
|
223
|
-
| `{peakHour}` | `22:00` |
|
|
224
|
-
| `{topEditedFile}` | `index.html` |
|
|
225
|
-
| `{linesAddedFmt}` | `24k` |
|
|
226
|
-
| `{topLanguage}` | `TypeScript` |
|
|
227
|
-
| `{todayCostFmt}` | `$1.23` |
|
|
228
|
-
| `{allCostFmt}` | `$89.42` |
|
|
229
|
-
| `{gitBranch}` | `main` |
|
|
230
|
-
|
|
231
|
-
Run `claude-rpc preview` to see every frame rendered with your real data, including which ones would be hidden by their `requires`. Run `claude-rpc vars` for the full machine-readable list.
|
|
163
|
+
```jsonc
|
|
164
|
+
// drop at your project root: <project>/.claude-rpc.json
|
|
165
|
+
{ "private": true } // shortcut for visibility: "hidden"
|
|
166
|
+
{ "visibility": "name-only" } // project name only, no file/tool detail
|
|
167
|
+
{ "projectName": "redacted" } // show this name on Discord instead
|
|
168
|
+
```
|
|
232
169
|
|
|
233
|
-
|
|
170
|
+
Or from the command line, in any project:
|
|
234
171
|
|
|
235
|
-
|
|
172
|
+
```sh
|
|
173
|
+
claude-rpc private # add cwd to ~/.claude-rpc/private-list.json
|
|
174
|
+
claude-rpc public # remove cwd
|
|
175
|
+
claude-rpc privacy # show the resolved visibility for the current dir
|
|
176
|
+
```
|
|
177
|
+
|
|
178
|
+
Or globally, in `config.json`:
|
|
179
|
+
|
|
180
|
+
```json
|
|
181
|
+
{ "privacy": { "patterns": ["client-*", "secret-stuff"], "mode": "hidden" } }
|
|
182
|
+
```
|
|
183
|
+
|
|
184
|
+
If [`gh`](https://cli.github.com/) is installed and authenticated, GitHub-private repos auto-hide (`privacy.githubPrivateMode`, default `hidden` — opt out with `privacy.autoDetectGithubPrivate: false`). 5-minute cache, 1.5s timeout, silent skip when `gh` isn't there.
|
|
185
|
+
|
|
186
|
+
Aggregates and local dashboards are never affected. Privacy is a one-way valve between local state and Discord.
|
|
187
|
+
|
|
188
|
+
## customizing the card
|
|
236
189
|
|
|
237
190
|
```sh
|
|
238
|
-
claude-rpc
|
|
239
|
-
claude-rpc
|
|
240
|
-
claude-rpc badge --metric cost --range 30d --out claude-cost.svg
|
|
241
|
-
claude-rpc badge --metric lines --range all --out claude-lines.svg
|
|
191
|
+
claude-rpc preview # render every rotation frame with your real data
|
|
192
|
+
claude-rpc vars # dump the full template-variable list as JSON
|
|
242
193
|
```
|
|
243
194
|
|
|
244
|
-
|
|
195
|
+
Frames have a `requires` field; the daemon skips a frame when any of its required vars resolve empty / zero. Write seven frames knowing only the relevant ones render.
|
|
196
|
+
|
|
197
|
+
```jsonc
|
|
198
|
+
"idle": {
|
|
199
|
+
"details": "Idle in {project}",
|
|
200
|
+
"state": "{modelPretty} · {todayHours} today",
|
|
201
|
+
"rotation": [
|
|
202
|
+
{ "details": "This week · {weekHours}", "state": "{weekPromptsLabel} · {weekTokensFmt} tokens",
|
|
203
|
+
"requires": ["weekActiveMs"] },
|
|
204
|
+
{ "details": "Code churn · {linesAddedFmt} added",
|
|
205
|
+
"state": "{linesNetFmt} net · {topLanguage}",
|
|
206
|
+
"requires": ["topLanguage"] }
|
|
207
|
+
]
|
|
208
|
+
}
|
|
209
|
+
```
|
|
245
210
|
|
|
246
|
-
|
|
211
|
+
The full default config is in [`src/default-config.js`](src/default-config.js) — that's the canonical list of every key. ~140 template variables are available; `claude-rpc vars` is the source of truth.
|
|
212
|
+
|
|
213
|
+
## commands
|
|
214
|
+
|
|
215
|
+
| Command | What it does |
|
|
216
|
+
| ---------------- | ------------ |
|
|
217
|
+
| `setup` | Install Claude Code hooks (test-fires one synthetic SessionStart to prove the pipe works) |
|
|
218
|
+
| `uninstall` | Remove Claude Code hooks |
|
|
219
|
+
| `upgrade-config` | Re-run idempotent migrations on `config.json` |
|
|
220
|
+
| `start` / `stop` / `restart` | Lifecycle for the detached daemon |
|
|
221
|
+
| `status` | Interactive TUI — heatmap, hour histogram, leaderboards (`--dump` for plain output) |
|
|
222
|
+
| `today` / `week` | Focused views (today's stats, weekday breakdown) |
|
|
223
|
+
| `serve` | Open the local web dashboard (port 47474) |
|
|
224
|
+
| `preview` | Render every rotation frame against real state |
|
|
225
|
+
| `scan` / `rescan`| Incremental / forced re-parse of `~/.claude/projects` |
|
|
226
|
+
| `backfill <dir>` | Import transcripts from any folder (backup, other machine) |
|
|
227
|
+
| `insights` | Print 3–5 auto-generated lines about your week |
|
|
228
|
+
| `badge` | Shields-style SVG (`--metric` `--range` `--out`) |
|
|
229
|
+
| `card` | Poster-style SVG (`--range year\|month\|week\|all`) |
|
|
230
|
+
| `private` / `public` / `privacy` | Per-cwd visibility toggles + status |
|
|
231
|
+
| `doctor` | Diagnostic checklist with one-line fix hints |
|
|
232
|
+
| `tail` / `logs` | Tail the daemon log |
|
|
233
|
+
| `daemon` | Run the daemon in the foreground (debugging) |
|
|
234
|
+
| `vars` | Dump the full template-var list as JSON |
|
|
247
235
|
|
|
248
|
-
|
|
236
|
+
Exit codes: `0` ok · `1` user error · `2` system error · `3` wrong state. `--version` and `--help` work as expected.
|
|
249
237
|
|
|
250
|
-
|
|
238
|
+
## troubleshooting
|
|
251
239
|
|
|
252
|
-
**
|
|
240
|
+
**First step is always `claude-rpc doctor`.** It checks Node version, hook registration, daemon liveness, Discord IPC connection, aggregate freshness, and privacy resolution — with a one-line fix hint per failure.
|
|
253
241
|
|
|
254
|
-
**
|
|
242
|
+
- **Discord doesn't show anything.** Discord *desktop* must be running. The browser client doesn't expose the local IPC bridge. `claude-rpc tail` shows what the daemon is actually doing.
|
|
243
|
+
- **Hooks don't fire.** `claude-rpc setup` re-registers them and now test-fires a synthetic `SessionStart` end-to-end, so a broken hook command surfaces immediately. Restart Claude Code afterwards so it re-reads its hook config.
|
|
244
|
+
- **Config error.** Bad JSON in `config.json` no longer crashes anything — the daemon logs one line and falls back to baked defaults. `claude-rpc tail` shows the parse error verbatim.
|
|
245
|
+
- **Old binary path baked into hooks.** Common after manual exe replacement. `claude-rpc setup` rewrites hook entries to point at the canonical install location.
|
|
246
|
+
|
|
247
|
+
## development
|
|
248
|
+
|
|
249
|
+
```sh
|
|
250
|
+
npm test # 134 tests, ~1.7s
|
|
251
|
+
npm run start # run daemon in foreground
|
|
252
|
+
npm run serve # web dashboard against your real data
|
|
253
|
+
npm run dashboard # Electron settings GUI (dev mode)
|
|
254
|
+
npm run build:exe # SEA single-file binary for the current OS
|
|
255
|
+
```
|
|
255
256
|
|
|
256
|
-
|
|
257
|
+
Tests are `node --test` with zero deps. The CI pipeline ([release.yml](.github/workflows/release.yml)) gates the matrix build and the npm publish behind the test job. Every public export of `src/*.js` is exercised at least once.
|
|
257
258
|
|
|
258
|
-
##
|
|
259
|
+
## license
|
|
259
260
|
|
|
260
261
|
[MIT](LICENSE) © Archer Simmons
|
package/package.json
CHANGED
package/src/install.js
CHANGED
|
@@ -282,6 +282,12 @@ function verifyHookPipe(exePath) {
|
|
|
282
282
|
const args = IS_PACKAGED || IS_NPM_INSTALL
|
|
283
283
|
? ['hook', 'SessionStart']
|
|
284
284
|
: [HOOK_SCRIPT, 'SessionStart'];
|
|
285
|
+
// Windows + npm-install: the global bin is `claude-rpc.cmd` (a batch shim),
|
|
286
|
+
// and Node's spawn doesn't apply PATHEXT — calling `claude-rpc` raw fails
|
|
287
|
+
// with ENOENT. shell:true makes cmd.exe do the resolution, mirroring how
|
|
288
|
+
// Claude Code actually invokes the hook string at runtime. Args are static
|
|
289
|
+
// and trusted; no injection surface.
|
|
290
|
+
const useShell = IS_NPM_INSTALL && process.platform === 'win32';
|
|
285
291
|
let result;
|
|
286
292
|
try {
|
|
287
293
|
result = spawnSync(cmd, args, {
|
|
@@ -289,6 +295,7 @@ function verifyHookPipe(exePath) {
|
|
|
289
295
|
encoding: 'utf8',
|
|
290
296
|
timeout: 3000,
|
|
291
297
|
windowsHide: true,
|
|
298
|
+
shell: useShell,
|
|
292
299
|
});
|
|
293
300
|
} catch (e) {
|
|
294
301
|
return { ok: false, detail: `spawn failed: ${e.message}` };
|