clauddy 1.27.0 → 1.28.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.
package/preload.js CHANGED
@@ -16,6 +16,10 @@ contextBridge.exposeInMainWorld('api', {
16
16
  onCodexDetected: (cb) => ipcRenderer.on('codex-detected', (_e, r) => cb(r)),
17
17
  codexEnable: (on) => ipcRenderer.send('codex-enable', on),
18
18
  onCodex: (cb) => ipcRenderer.on('codex', (_e, c) => cb(c)),
19
+ cursorDetect: () => ipcRenderer.send('cursor-detect'),
20
+ onCursorDetected: (cb) => ipcRenderer.on('cursor-detected', (_e, r) => cb(r)),
21
+ cursorEnable: (on) => ipcRenderer.send('cursor-enable', on),
22
+ onCursor: (cb) => ipcRenderer.on('cursor', (_e, c) => cb(c)),
19
23
  onRealUsage: (cb) => ipcRenderer.on('real-usage', (_e, u) => cb(u)),
20
24
  onAuthState: (cb) => ipcRenderer.on('auth-state', (_e, s) => cb(s)),
21
25
  onProfile: (cb) => ipcRenderer.on('profile', (_e, p) => cb(p)),
package/reminders.js CHANGED
@@ -4,7 +4,7 @@ function createReminders({ load, save, now = Date.now }) {
4
4
  let delivered = {}
5
5
  const valid = (r) =>
6
6
  r &&
7
- ['claude', 'codex'].includes(r.provider) &&
7
+ ['claude', 'codex', 'cursor'].includes(r.provider) &&
8
8
  typeof r.key === 'string' &&
9
9
  typeof r.label === 'string' &&
10
10
  Number.isFinite(r.at) &&
@@ -25,7 +25,8 @@ function createReminders({ load, save, now = Date.now }) {
25
25
  return {
26
26
  list: () => pending.map((r) => ({ ...r })),
27
27
  arm(reminder) {
28
- if (!valid(reminder) || reminder.at <= now() || reminder.at > now() + 7 * 86400000)
28
+ // Cursor's budget is a billing cycle, so a reset can be a month out
29
+ if (!valid(reminder) || reminder.at <= now() || reminder.at > now() + 32 * 86400000)
29
30
  return false
30
31
  persist([...pending.filter((r) => r.key !== reminder.key), { ...reminder }])
31
32
  return true
@@ -28,18 +28,22 @@
28
28
  // Activity freshness is separate from quota freshness: Codex can work while
29
29
  // its last rate-limit reading is old. Ignore abandoned activity snapshots.
30
30
  const FRESH_MS = 60000
31
- const SLEEP_MS = 300000 // main's default sleepThresholdMs; Codex has no flag of its own
32
- function currentActivity(claude, codex, now = Date.now()) {
31
+ const SLEEP_MS = 300000 // main's default sleepThresholdMs; Codex and Cursor have no flag of their own
32
+ // each source is its last payload, or null while it isn't connected
33
+ function currentActivity({ claude = null, codex = null, cursor = null } = {}, now = Date.now()) {
33
34
  const fresh = (at) => Number.isFinite(at) && now - at <= FRESH_MS
34
35
  const providers = []
35
36
  if (claude?.active && fresh(claude.ts)) providers.push('claude')
36
37
  if (codex?.active && fresh(codex.lastSeen)) providers.push('codex')
37
- // only Claude's logs say *what* it's doing; two workers share one scene
38
- const activity = providers.join() === 'claude' ? claude.activity || 'working' : 'working'
39
- const asleep = [
40
- claude && !!claude.sleeping,
41
- codex && !!codex.lastSeen && now - codex.lastSeen >= SLEEP_MS,
42
- ].filter((v) => v !== null && v !== undefined)
38
+ if (cursor?.active && fresh(cursor.lastSeen)) providers.push('cursor')
39
+ // Claude's and Cursor's logs say *what* they're doing; Codex's don't, and
40
+ // two workers share one scene
41
+ const solo = providers.length === 1 ? { claude, cursor }[providers[0]] : null
42
+ const activity = solo?.activity || 'working'
43
+ const idle = (s) => s && !!s.lastSeen && now - s.lastSeen >= SLEEP_MS
44
+ const asleep = [claude && !!claude.sleeping, idle(codex), idle(cursor)].filter(
45
+ (v) => v !== null && v !== undefined,
46
+ )
43
47
  return { providers, activity, sleeping: asleep.length > 0 && asleep.every(Boolean) }
44
48
  }
45
49
  const api = { createActivityTracker, currentActivity }
@@ -12,6 +12,7 @@
12
12
  <svg width="0" height="0" style="position: absolute" aria-hidden="true">
13
13
  <symbol id="logo-claude" viewBox="0 0 24 24"><path d="m4.7144 15.9555 4.7174-2.6471.079-.2307-.079-.1275h-.2307l-.7893-.0486-2.6956-.0729-2.3375-.0971-2.2646-.1214-.5707-.1215-.5343-.7042.0546-.3522.4797-.3218.686.0608 1.5179.1032 2.2767.1578 1.6514.0972 2.4468.255h.3886l.0546-.1579-.1336-.0971-.1032-.0972L6.973 9.8356l-2.55-1.6879-1.3356-.9714-.7225-.4918-.3643-.4614-.1578-1.0078.6557-.7225.8803.0607.2246.0607.8925.686 1.9064 1.4754 2.4893 1.8336.3643.3035.1457-.1032.0182-.0728-.164-.2733-1.3539-2.4467-1.445-2.4893-.6435-1.032-.17-.6194c-.0607-.255-.1032-.4674-.1032-.7285L6.287.1335 6.6997 0l.9957.1336.419.3642.6192 1.4147 1.0018 2.2282 1.5543 3.0296.4553.8985.2429.8318.091.255h.1579v-.1457l.1275-1.706.2368-2.0947.2307-2.6957.0789-.7589.3764-.9107.7468-.4918.5828.2793.4797.686-.0668.4433-.2853 1.8517-.5586 2.9021-.3643 1.9429h.2125l.2429-.2429.9835-1.3053 1.6514-2.0643.7286-.8196.85-.9046.5464-.4311h1.0321l.759 1.1293-.34 1.1657-1.0625 1.3478-.8804 1.1414-1.2628 1.7-.7893 1.36.0729.1093.1882-.0183 2.8535-.607 1.5421-.2794 1.8396-.3157.8318.3886.091.3946-.3278.8075-1.967.4857-2.3072.4614-3.4364.8136-.0425.0304.0486.0607 1.5482.1457.6618.0364h1.621l3.0175.2247.7892.522.4736.6376-.079.4857-1.2142.6193-1.6393-.3886-3.825-.9107-1.3113-.3279h-.1822v.1093l1.0929 1.0686 2.0035 1.8092 2.5075 2.3314.1275.5768-.3218.4554-.34-.0486-2.2039-1.6575-.85-.7468-1.9246-1.621h-.1275v.17l.4432.6496 2.3436 3.5214.1214 1.0807-.17.3521-.6071.2125-.6679-.1214-1.3721-1.9246L14.38 17.959l-1.1414-1.9428-.1397.079-.674 7.2552-.3156.3703-.7286.2793-.6071-.4614-.3218-.7468.3218-1.4753.3886-1.9246.3157-1.53.2853-1.9004.17-.6314-.0121-.0425-.1397.0182-1.4328 1.9672-2.1796 2.9446-1.7243 1.8456-.4128.164-.7164-.3704.0667-.6618.4008-.5889 2.386-3.0357 1.4389-1.882.929-1.0868-.0062-.1579h-.0546l-6.3385 4.1164-1.1293.1457-.4857-.4554.0608-.7467.2307-.2429 1.9064-1.3114Z" /></symbol>
14
14
  <symbol id="logo-openai" viewBox="0 0 24 24"><path d="M22.2819 9.8211a5.9847 5.9847 0 0 0-.5157-4.9108 6.0462 6.0462 0 0 0-6.5098-2.9A6.0651 6.0651 0 0 0 4.9807 4.1818a5.9847 5.9847 0 0 0-3.9977 2.9 6.0462 6.0462 0 0 0 .7427 7.0966 5.98 5.98 0 0 0 .511 4.9107 6.051 6.051 0 0 0 6.5146 2.9001A5.9847 5.9847 0 0 0 13.2599 24a6.0557 6.0557 0 0 0 5.7718-4.2058 5.9894 5.9894 0 0 0 3.9977-2.9001 6.0557 6.0557 0 0 0-.7475-7.0729zm-9.022 12.6081a4.4755 4.4755 0 0 1-2.8764-1.0408l.1419-.0804 4.7783-2.7582a.7948.7948 0 0 0 .3927-.6813v-6.7369l2.02 1.1686a.071.071 0 0 1 .038.052v5.5826a4.504 4.504 0 0 1-4.4945 4.4944zm-9.6607-4.1254a4.4708 4.4708 0 0 1-.5346-3.0137l.142.0852 4.783 2.7582a.7712.7712 0 0 0 .7806 0l5.8428-3.3685v2.3324a.0804.0804 0 0 1-.0332.0615L9.74 19.9502a4.4992 4.4992 0 0 1-6.1408-1.6464zM2.3408 7.8956a4.485 4.485 0 0 1 2.3655-1.9728V11.6a.7664.7664 0 0 0 .3879.6765l5.8144 3.3543-2.0201 1.1685a.0757.0757 0 0 1-.071 0l-4.8303-2.7865A4.504 4.504 0 0 1 2.3408 7.872zm16.5963 3.8558L13.1038 8.364 15.1192 7.2a.0757.0757 0 0 1 .071 0l4.8303 2.7913a4.4944 4.4944 0 0 1-.6765 8.1042v-5.6772a.79.79 0 0 0-.407-.667zm2.0107-3.0231l-.142-.0852-4.7735-2.7818a.7759.7759 0 0 0-.7854 0L9.409 9.2297V6.8974a.0662.0662 0 0 1 .0284-.0615l4.8303-2.7866a4.4992 4.4992 0 0 1 6.6802 4.66zM8.3065 12.863l-2.02-1.1638a.0804.0804 0 0 1-.038-.0567V6.0742a4.4992 4.4992 0 0 1 7.3757-3.4537l-.142.0805L8.704 5.459a.7948.7948 0 0 0-.3927.6813zm1.0976-2.3654l2.602-1.4998 2.6069 1.4998v2.9994l-2.5974 1.4997-2.6067-1.4997Z" /></symbol>
15
+ <symbol id="logo-cursor" viewBox="0 0 24 24"><path d="M11.503.131 1.891 5.678a.84.84 0 0 0-.42.726v11.188c0 .3.162.575.42.724l9.609 5.55a1 1 0 0 0 .998 0l9.61-5.55a.84.84 0 0 0 .42-.724V6.404a.84.84 0 0 0-.42-.726L12.497.131a1.01 1.01 0 0 0-.996 0M2.657 6.338h18.55c.263 0 .43.287.297.515L12.23 22.918c-.062.107-.229.064-.229-.06V12.335a.59.59 0 0 0-.295-.51l-9.11-5.257c-.109-.063-.064-.23.061-.23" /></symbol>
15
16
  </svg>
16
17
  <div id="card">
17
18
  <div id="account-chip" hidden title="Switch account">
@@ -205,9 +206,9 @@
205
206
  <span id="mini-acct-name"></span>
206
207
  <span id="mini-acct-plan" class="plan-badge" hidden></span>
207
208
  </div>
208
- <div class="mini-line"><span id="mini-dot"></span><span id="mini-workers" class="activity-logos" role="img" hidden><span data-provider="claude"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="#logo-claude" /></svg></span><span data-provider="codex"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="#logo-openai" /></svg></span></span><span id="mini-text">idle</span></div>
209
+ <div class="mini-line"><span id="mini-dot"></span><span id="mini-workers" class="activity-logos" role="img" hidden><span data-provider="claude"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="#logo-claude" /></svg></span><span data-provider="codex"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="#logo-openai" /></svg></span><span data-provider="cursor"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="#logo-cursor" /></svg></span></span><span id="mini-text">idle</span></div>
209
210
  <div id="mini-pct-row"><span id="mini-pct">0%</span> <span class="lbl">session</span></div>
210
- <!-- Dual-service dock: two glanceable readings, one shared pet. -->
211
+ <!-- Multi-service dock: a glanceable reading per service, one shared pet. -->
211
212
  <div id="mini-dual">
212
213
  <button type="button" class="mini-source" data-provider="claude">
213
214
  <svg class="mini-logo" viewBox="0 0 24 24" aria-hidden="true"><use href="#logo-claude" /></svg><span class="mini-source-name">Claude</span><span class="mini-track"><i id="mini-claude-bar"></i></span><b id="mini-claude-value">—</b>
@@ -215,15 +216,19 @@
215
216
  <button type="button" class="mini-source" data-provider="codex">
216
217
  <svg class="mini-logo" viewBox="0 0 24 24" aria-hidden="true"><use href="#logo-openai" /></svg><span class="mini-source-name">Codex</span><span class="mini-track"><i id="mini-codex-bar"></i></span><b id="mini-codex-value">—</b>
217
218
  </button>
219
+ <button type="button" class="mini-source" data-provider="cursor">
220
+ <svg class="mini-logo" viewBox="0 0 24 24" aria-hidden="true"><use href="#logo-cursor" /></svg><span class="mini-source-name">Cursor</span><span class="mini-track"><i id="mini-cursor-bar"></i></span><b id="mini-cursor-value">—</b>
221
+ </button>
218
222
  </div>
219
223
  <div id="mini-reset" hidden></div>
220
224
  <button type="button" id="mini-reminder" class="reminder-toggle" hidden></button>
221
225
  </div>
222
226
 
223
- <div id="pet-activity" class="activity-logos" role="img" hidden><span data-provider="claude"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="#logo-claude" /></svg></span><span data-provider="codex"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="#logo-openai" /></svg></span></div>
227
+ <div id="pet-activity" class="activity-logos" role="img" hidden><span data-provider="claude"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="#logo-claude" /></svg></span><span data-provider="codex"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="#logo-openai" /></svg></span><span data-provider="cursor"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="#logo-cursor" /></svg></span></div>
224
228
  <section id="pet-glance" aria-label="Session usage">
225
229
  <button type="button" data-provider="claude" id="glance-claude"><svg class="mini-logo" viewBox="0 0 24 24" aria-hidden="true"><use href="#logo-claude" /></svg><span>Claude</span><b id="glance-claude-value">—</b></button>
226
230
  <button type="button" data-provider="codex" id="glance-codex"><svg class="mini-logo" viewBox="0 0 24 24" aria-hidden="true"><use href="#logo-openai" /></svg><span>Codex</span><b id="glance-codex-value">—</b></button>
231
+ <button type="button" data-provider="cursor" id="glance-cursor"><svg class="mini-logo" viewBox="0 0 24 24" aria-hidden="true"><use href="#logo-cursor" /></svg><span>Cursor</span><b id="glance-cursor-value">—</b></button>
227
232
  <span id="glance-empty" hidden>Connect an account in Settings.</span>
228
233
  <button type="button" id="pet-restore" aria-label="Open compact monitor" title="Open compact monitor"><svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M14 4h6v6M20 4l-7 7M10 20H4v-6M4 20l7-7" /></svg></button>
229
234
  </section>
@@ -241,23 +246,24 @@
241
246
 
242
247
  <!-- session + weekly (real usage; needs login) -->
243
248
  <div id="home-success" hidden>✓ Logged in — your real usage is live</div>
244
- <!-- Both services stay one click away, below the pet. -->
249
+ <!-- Every connected service stays one click away, below the pet. -->
245
250
  <div id="harness-tabs" role="tablist" aria-label="Monitored service">
246
251
  <button id="tab-claude" type="button" role="tab" data-provider="claude" aria-selected="true" aria-controls="service-panel" tabindex="0"><svg class="tab-logo" viewBox="0 0 24 24" aria-hidden="true"><use href="#logo-claude" /></svg><span>Claude</span><span class="tab-value" id="tab-claude-value">—</span><span class="tab-alert" hidden>!</span></button>
247
252
  <button id="tab-codex" type="button" role="tab" data-provider="codex" aria-selected="false" aria-controls="service-panel" tabindex="-1"><svg class="tab-logo" viewBox="0 0 24 24" aria-hidden="true"><use href="#logo-openai" /></svg><span>Codex</span><span class="tab-value" id="tab-codex-value">—</span><span class="tab-alert" hidden>!</span></button>
253
+ <button id="tab-cursor" type="button" role="tab" data-provider="cursor" aria-selected="false" aria-controls="service-panel" tabindex="-1"><svg class="tab-logo" viewBox="0 0 24 24" aria-hidden="true"><use href="#logo-cursor" /></svg><span>Cursor</span><span class="tab-value" id="tab-cursor-value">—</span><span class="tab-alert" hidden>!</span></button>
248
254
  </div>
249
255
  <div id="service-panel" role="tabpanel" aria-labelledby="tab-claude">
250
256
  <div id="limits">
251
257
  <div id="limits-meters">
252
258
  <div class="meter">
253
- <div class="meter-top"><span>current session</span><span id="session-pct">0%</span></div>
259
+ <div class="meter-top"><span id="session-label">current session</span><span id="session-pct">0%</span></div>
254
260
  <div class="track"><div class="fill" id="session-fill"></div></div>
255
261
  <div class="sub" id="session-sub">no active session</div>
256
262
  <button type="button" id="reminder-toggle" class="reminder-toggle" hidden></button>
257
263
  <div class="sub proj" id="session-proj" hidden></div>
258
264
  </div>
259
265
  <div class="meter">
260
- <div class="meter-top"><span>weekly · all models</span><span id="week-pct">0%</span></div>
266
+ <div class="meter-top"><span id="week-label">weekly · all models</span><span id="week-pct">0%</span></div>
261
267
  <div class="track"><div class="fill week" id="week-fill"></div></div>
262
268
  <div class="sub" id="week-sub">—</div>
263
269
  </div>
@@ -320,7 +326,26 @@
320
326
  </div>
321
327
 
322
328
  <div class="settings-label connections-label">Connections</div>
323
- <div id="account">
329
+ <!-- one tile per service; a click opens its card below -->
330
+ <div id="conn-tiles">
331
+ <button type="button" class="conn-tile" id="conn-claude" data-conn="claude" aria-expanded="false" aria-controls="account">
332
+ <span class="connection-avatar claude-avatar"><svg class="connection-logo" viewBox="0 0 24 24" aria-hidden="true"><use href="#logo-claude" /></svg><i class="conn-check" hidden aria-hidden="true">✓</i></span>
333
+ <span class="conn-name">Claude</span>
334
+ <span class="conn-state" id="conn-claude-state">Connect</span>
335
+ </button>
336
+ <button type="button" class="conn-tile" id="conn-codex" data-conn="codex" aria-expanded="false" aria-controls="codex-settings">
337
+ <span class="connection-avatar codex-avatar"><svg class="connection-logo" viewBox="0 0 24 24" aria-hidden="true"><use href="#logo-openai" /></svg><i class="conn-check" hidden aria-hidden="true">✓</i></span>
338
+ <span class="conn-name">Codex</span>
339
+ <span class="conn-state" id="conn-codex-state">Connect</span>
340
+ </button>
341
+ <button type="button" class="conn-tile" id="conn-cursor" data-conn="cursor" aria-expanded="false" aria-controls="cursor-settings">
342
+ <span class="connection-avatar cursor-avatar"><svg class="connection-logo" viewBox="0 0 24 24" aria-hidden="true"><use href="#logo-cursor" /></svg><i class="conn-check" hidden aria-hidden="true">✓</i></span>
343
+ <span class="conn-name">Cursor</span>
344
+ <span class="conn-state" id="conn-cursor-state">Connect</span>
345
+ </button>
346
+ </div>
347
+ <div id="connections">
348
+ <div id="account" class="conn-panel">
324
349
  <!-- who you are comes first: the list, then the login for whichever
325
350
  account is active — so "add" and the code field sit together -->
326
351
  <div id="acc-connected" class="connect-block connection-card">
@@ -354,7 +379,7 @@
354
379
  </div>
355
380
 
356
381
  <!-- Codex: opt-in, read from its local logs — nothing to log into here -->
357
- <div id="codex-settings" class="connection-card">
382
+ <div id="codex-settings" class="connection-card conn-panel">
358
383
  <span class="codex-avatar connection-avatar"><svg class="codex-logo" viewBox="0 0 24 24" aria-hidden="true"><use href="#logo-openai" /></svg></span>
359
384
  <div class="connection-copy">
360
385
  <div class="connection-heading"><b>Codex</b><span id="codex-plan" class="plan-badge" hidden></span></div>
@@ -375,6 +400,29 @@
375
400
  </div>
376
401
  </div>
377
402
 
403
+ <!-- Cursor: opt-in, through the Cursor app's own login on this machine -->
404
+ <div id="cursor-settings" class="connection-card conn-panel">
405
+ <span class="cursor-avatar connection-avatar"><svg class="cursor-logo" viewBox="0 0 24 24" aria-hidden="true"><use href="#logo-cursor" /></svg></span>
406
+ <div class="connection-copy">
407
+ <div class="connection-heading"><b>Cursor</b><span id="cursor-plan" class="plan-badge" hidden></span></div>
408
+ <span class="connection-caption" id="cursor-connected-caption">Connected on this device</span>
409
+ <span id="cursor-hint" class="connection-hint">Track Cursor alongside Claude, in this pet.</span>
410
+ </div>
411
+ <div class="codex-actions">
412
+ <button id="cursor-connect" class="connection-btn" aria-label="Connect Cursor"><svg class="cursor-logo" viewBox="0 0 24 24" aria-hidden="true"><use href="#logo-cursor" /></svg><span>Connect</span></button>
413
+ <span id="cursor-setup" hidden>
414
+ <button id="cursor-retry" class="connection-btn">Retry</button>
415
+ <button id="cursor-setup-cancel" class="codex-x" title="Cancel" aria-label="Cancel">
416
+ <svg class="ic" viewBox="0 0 24 24" aria-hidden="true"><path d="M18 6 6 18M6 6l12 12" /></svg>
417
+ </button>
418
+ </span>
419
+ <button id="cursor-disconnect" class="codex-x connection-remove" title="Disconnect Cursor" aria-label="Disconnect Cursor">
420
+ <svg class="ic" viewBox="0 0 24 24" aria-hidden="true"><path d="M18 6 6 18M6 6l12 12" /></svg>
421
+ </button>
422
+ </div>
423
+ </div>
424
+ </div>
425
+
378
426
  <div class="settings-label">Preferences</div>
379
427
  <div id="set-rows">
380
428
  <span class="seg settings-segment" id="set-mode">