Skip to main content

Docs Concepts

License heartbeat and auto-resume

When you activate your Power Claude license, the server returns a short-lived session token (NOT your license key itself). That token is what the proxy and extension actually use day-to-day. The license-key JWT stays on disk and is consulted only to renew the session.

The heartbeat is what keeps the session token fresh.

The lifecycle

  1. Activation. Client posts license JWT to /auth/activate.php. Server verifies the Ed25519 signature, checks jti usage, returns a session token + expiry (default 24h).
  2. Heartbeat. Every ~6 hours (or sooner if expires_in < 1h), the client posts the current session token to /auth/refresh.php. Server returns a new token with a fresh 24h expiry.
  3. Suspended sessions. If the client is offline when a heartbeat would have fired, it queues the refresh for when network returns. Up to 7 days offline is tolerated before the session is considered abandoned and re-activation is required.
  4. Revocation. If your license is revoked server-side (e.g., chargeback), the next heartbeat returns 401, the client wipes its session token, and the user is prompted to re-activate.

Why a session token, not the license key

The license JWT is long-lived and powerful. Sending it on every request would mean: every rotation of credentials touches the long-lived secret, every captured request leaks the long-lived secret, every revocation requires re-authing every client. The session token is intentionally short-lived so:

  • Compromise of an in-flight session token has a 24-hour blast radius
  • Revocation propagates within 6 hours (or instantly on next request)
  • The license JWT lives in disk-only storage and is read only during activation/refresh

Auto-resume across machine restarts

The session token persists in ~/.power-claude/state/session.json (mode 0600). When you reboot, the watchdog brings the proxy back up; the proxy reads the session token; if it's still within expiry, no user interaction is needed. The dashboard, extension, and CLI all observe proxy_running: true and session_active: true within seconds.

If the saved session token has expired (you were offline for >24h), the proxy will request a refresh on next use; if the heartbeat succeeds, everything works without a prompt. Only if both the session token AND the refresh fail does the user see "license expired — re-activate."

Inspecting heartbeat state

pc status --json | jq '{session_active, session_expires_at, last_heartbeat_at, next_heartbeat_at}'

Healthy output: session_active: true, next_heartbeat_at is in the near future (≤6h), last_heartbeat_at is within the last 12h.

What does NOT trigger a heartbeat

  • Every API call. Heartbeats are time-based, not request-based — they don't add per-request latency.
  • Switching active account during rotation. Account rotation is local; the license is independent.
  • Toggling Power Mode or any client setting.