claude-powernap 0.3.0__tar.gz

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.
@@ -0,0 +1,7 @@
1
+ __pycache__/
2
+ *.pyc
3
+ .DS_Store
4
+ dist/
5
+ build/
6
+ *.egg-info/
7
+ .venv/
@@ -0,0 +1,96 @@
1
+ # Changelog
2
+
3
+ All notable changes to this project will be documented in this file.
4
+ Format: [Keep a Changelog](https://keepachangelog.com/en/1.1.0/);
5
+ versioning: [SemVer](https://semver.org/).
6
+
7
+ ## [0.3.0] - 2026-07-18
8
+
9
+ ### Added
10
+ - **PyPI packaging**: installable via `pip install claude-powernap` /
11
+ `uvx claude-powernap setup`; new `setup` / `remove` CLI subcommands replace
12
+ the platform installer scripts (install.sh/.ps1 remain as thin wrappers).
13
+ - **Claude Code plugin**: the repo is its own marketplace —
14
+ `/plugin marketplace add asiagenawi/claude-powernap` then
15
+ `/plugin install powernap@claude-powernap`. Hooks activate with no file
16
+ deployment; `/powernap:watcher` schedules the OS-level fallback watcher;
17
+ `/powernap:status` and `/powernap:toggle` included
18
+ (`watcher-setup`/`watcher-remove` CLI subcommands back them).
19
+ - `claude-powernap version` command.
20
+ - CI: package build + wheel install + entry-point smoke test job; PyPI
21
+ publish workflow on GitHub releases (trusted publishing).
22
+
23
+ ### Changed
24
+ - Repo restructured to a src-layout Python package (`src/claude_powernap/`);
25
+ install logic consolidated into one cross-platform code path.
26
+
27
+ ### Fixed (pre-release audit)
28
+ - Rescue paths now share one ledger — a warned session that then hard-hit
29
+ the limit can no longer be resumed twice (forked).
30
+ - macOS liveness check fails toward "alive" on lsof errors, matching Windows.
31
+ - Warnings are no longer emitted (and marked delivered) on Stop events,
32
+ where injected context reaches no model turn.
33
+ - Local estimation dedupes by request/message id — `claude --resume` copies
34
+ history into a new transcript and previously double-counted it.
35
+ - Keychain: full-keychain enumeration (`dump-keychain`) now runs only on a
36
+ cache miss, never on the steady-state path; check cadence has a 15s floor.
37
+ - Usage requests self-identify as `claude-powernap/<version>` (verified
38
+ accepted) instead of a claude-cli User-Agent.
39
+ - uvx installs embed a stable system interpreter (not uv's collectible
40
+ cache path) into hooks/shims/scheduled jobs; re-running setup repairs a
41
+ stale interpreter in existing hooks.
42
+ - Account switches also reset burn-rate samples; source flips
43
+ (endpoint↔local) reset them too, preventing phantom burn spikes.
44
+ - Warn keys bucket the reset time to the hour, so endpoint drift can't
45
+ re-warn mid-window; an active weekly stop suppresses the contradictory
46
+ 5h resume instruction.
47
+ - Watcher dry-run is truly read-only; rescue retries on failed resumes;
48
+ resumed/notified ledgers prune after 24h; cwd is shell-quoted (and falls
49
+ back to home when deleted) in resume commands.
50
+ - `status` reads state under the lock; `--debug` never writes unlocked.
51
+ - Partial `token_weights` config merges over defaults instead of crashing
52
+ the scan; multi-machine calibration guarded by a substantial-usage floor
53
+ and smoothing; missing-budget rescans throttled to hourly.
54
+ - Empty hook session_id falls back to the transcript filename.
55
+ - Removed a stale committed wheel from `dist/` (would have broken future
56
+ publishes); sdist excludes demo/CI files; README/SECURITY corrections
57
+ (Keychain enumeration disclosure, honest UA, cadence and trigger accuracy,
58
+ uninstall matrix per install method, sleep/`caffeinate` caveat, absolute
59
+ image URLs for PyPI).
60
+
61
+ ## [0.2.0] - 2026-07-18
62
+
63
+ ### Added
64
+ - **Burn-rate prediction**: warnings also fire when the recent burn rate
65
+ projects the limit within `safety_margin_min` minutes — catches fast
66
+ (subagent-heavy) burns the static threshold misses.
67
+ - **Adaptive check cadence**: 30s above 80% usage, every hook event above 90%.
68
+ - **Pause ledger + rescue**: every pause is recorded; the watcher resumes
69
+ napping sessions whose in-session alarm died (sleep/reboot/crash).
70
+ - **Weekly guard** (opt-in, `weekly_guard: true`): warn/pause on the weekly
71
+ window; pauses without scheduling a resume since weekly resets are days out.
72
+ - **Account-switch detection**: per-account cached state clears automatically
73
+ on `/login` to a different account.
74
+ - **Cross-platform state locking**: concurrent sessions can no longer race
75
+ state.json (fcntl/msvcrt; 12-process CI test).
76
+
77
+ ## [0.1.0] - 2026-07-18
78
+
79
+ Initial release.
80
+
81
+ ### Added
82
+ - Usage monitor hook (`PostToolUse`/`UserPromptSubmit`/`Stop`): warns the live
83
+ session at a configurable threshold (default 90%) of the 5-hour window,
84
+ with the pause-checkpoint-reschedule protocol injected into context.
85
+ - Hybrid usage source: exact numbers from the OAuth usage endpoint with
86
+ automatic fallback to local transcript estimation, continuously calibrated
87
+ against endpoint truth.
88
+ - Fallback watcher: detects sessions that hard-hit the limit, waits for the
89
+ reset, and resumes them visibly (new terminal window) — with a
90
+ never-fork-a-live-session guarantee; notifies instead when in doubt.
91
+ - `claude-powernap on|off|status|log` CLI.
92
+ - Platforms: macOS (Keychain/launchd/osascript), Linux incl. WSL
93
+ (credentials file/systemd user timer/notify-send, terminal auto-detect),
94
+ native Windows experimental (Task Scheduler/toasts/wt).
95
+ - CI: full install→monitor→hook→watcher→uninstall cycle on macOS, Ubuntu,
96
+ and Windows runners.
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 asiagenawi
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,218 @@
1
+ Metadata-Version: 2.4
2
+ Name: claude-powernap
3
+ Version: 0.3.0
4
+ Summary: Your Claude Code session sees the 5-hour limit coming, checkpoints its work, and resumes itself when the window resets.
5
+ Project-URL: Homepage, https://github.com/asiagenawi/claude-powernap
6
+ Project-URL: Changelog, https://github.com/asiagenawi/claude-powernap/blob/main/CHANGELOG.md
7
+ Author: asiagenawi
8
+ License-Expression: MIT
9
+ License-File: LICENSE
10
+ Keywords: anthropic,auto-resume,claude,claude-code,rate-limit,usage-limit
11
+ Classifier: Development Status :: 4 - Beta
12
+ Classifier: Environment :: Console
13
+ Classifier: Intended Audience :: Developers
14
+ Classifier: Operating System :: MacOS
15
+ Classifier: Operating System :: Microsoft :: Windows
16
+ Classifier: Operating System :: POSIX :: Linux
17
+ Classifier: Programming Language :: Python :: 3
18
+ Classifier: Topic :: Software Development :: Build Tools
19
+ Requires-Python: >=3.9
20
+ Description-Content-Type: text/markdown
21
+
22
+ # claude-powernap
23
+
24
+ [![CI](https://github.com/asiagenawi/claude-powernap/actions/workflows/ci.yml/badge.svg)](https://github.com/asiagenawi/claude-powernap/actions/workflows/ci.yml)
25
+ [![Release](https://img.shields.io/github/v/release/asiagenawi/claude-powernap)](https://github.com/asiagenawi/claude-powernap/releases)
26
+ [![License: MIT](https://img.shields.io/badge/license-MIT-blue.svg)](https://github.com/asiagenawi/claude-powernap/blob/main/LICENSE)
27
+ ![Platform](https://img.shields.io/badge/platform-macOS%20%7C%20Linux%20%7C%20Windows-lightgrey)
28
+ ![Deps](https://img.shields.io/badge/deps-stdlib%20only-brightgreen)
29
+
30
+ **Your Claude Code session sees the usage limit coming, saves its work, and
31
+ resumes itself when the window resets. You do nothing.**
32
+
33
+ *(Demo below is an illustrative mock-up of a real cycle the tool ran.)*
34
+
35
+ ![claude-powernap demo: a session gets warned at 91%, checkpoints, pauses, and self-resumes after the window resets](https://raw.githubusercontent.com/asiagenawi/claude-powernap/main/demo/powernap.gif)
36
+
37
+ ## The problem
38
+
39
+ You kick off a long Claude Code automation — a big refactor, a batch
40
+ migration, an overnight research run. You check back three hours later and
41
+ find it died 40 minutes in:
42
+
43
+ ```
44
+ You've hit your session limit · resets 3:00am
45
+ ```
46
+
47
+ Everything since the last commit is in limbo. The context that session had
48
+ built up is sitting frozen mid-thought. And the limit reset hours ago — the
49
+ session just had no way to know, no way to save itself, and no way to come
50
+ back. Your subscription's 5-hour window reset while your automation sat
51
+ dead in a terminal.
52
+
53
+ ## The idea
54
+
55
+ A session that's *about* to hit the limit still has tokens left. That's
56
+ enough budget to do something smarter than die:
57
+
58
+ 1. **A hook watches your usage** (every ~2 min normally, tightening to ~15s
59
+ near the limit; zero workflow changes). It knows your exact window percentage and reset time — the same
60
+ numbers Claude Code's own `/usage` screen shows.
61
+ 2. **At 90% — or earlier if your burn rate projects the limit within ~9
62
+ minutes — the session itself gets warned**: the hook injects a message
63
+ into the live conversation: *"you're at 91%, window resets at 3:00am,
64
+ pause now."*
65
+ 3. **Claude wraps up gracefully**: finishes the current step, writes a
66
+ checkpoint file (what's done, what's in flight, exact next steps), and —
67
+ when the session has a scheduled-tasks capability — schedules a one-shot
68
+ task for just after the reset. Then it idles.
69
+ 4. **At reset, the session wakes itself** — same terminal, same context,
70
+ reads its checkpoint, keeps going. Sessions without a scheduler instead
71
+ checkpoint and tell you when to send any message to resume — and the
72
+ watcher (below) still notifies or reopens as needed.
73
+
74
+ If the estimate is ever wrong and a session hard-hits the wall anyway, a
75
+ background watcher catches that too: after the reset it reopens the session
76
+ in a visible terminal window with the "continue from your checkpoint" prompt
77
+ already submitted. If the original window is still open, you get a
78
+ notification instead — it will never fork a live session.
79
+
80
+ ## How it compares
81
+
82
+ | | warns before the limit | session saves its work | resumes automatically | needs tmux |
83
+ |---|---|---|---|---|
84
+ | **claude-powernap** | ✅ | ✅ | ✅ same session | no |
85
+ | usage monitors (ccusage, claude-monitor) | ⚠️ warns *you*, not the session | ❌ | ❌ | — |
86
+ | auto-retriers (unsnooze, claude-auto-retry, …) | ❌ reacts after death | ❌ dies mid-thought | ✅ | mostly yes |
87
+
88
+ Free, privacy-first, local-only, no dependencies (Python 3 stdlib only). macOS, Linux (incl.
89
+ WSL), native Windows (experimental).
90
+
91
+ ## Install
92
+
93
+ As a Claude Code plugin (inside any Claude Code session):
94
+
95
+ ```
96
+ /plugin marketplace add asiagenawi/claude-powernap
97
+ /plugin install powernap@claude-powernap
98
+ ```
99
+
100
+ The plugin activates the monitoring hooks immediately. The one thing a
101
+ plugin can't do itself is register the fallback watcher (an OS-level
102
+ background job) — so on first run the hook notices it's missing and has the
103
+ session offer you the one command to set it up (or run `/powernap:watcher`
104
+ yourself anytime). Also ships `/powernap:status` and `/powernap:toggle
105
+ on|off`.
106
+
107
+ From PyPI (all platforms):
108
+
109
+ ```bash
110
+ uvx claude-powernap setup # or: pipx install claude-powernap && claude-powernap setup
111
+ ```
112
+
113
+ Or from a clone, if you'd rather read what you run first:
114
+
115
+ ```bash
116
+ git clone https://github.com/asiagenawi/claude-powernap.git && cd claude-powernap
117
+ ./install.sh # macOS / Linux / WSL — same as `claude-powernap setup`
118
+ ```
119
+
120
+ Native Windows clone (PowerShell 7 recommended): `.\install.ps1`
121
+
122
+ Pick ONE install method — plugin or pip/clone. (Both at once is harmless —
123
+ the shared state throttle makes duplicate checks no-ops — but pointless.)
124
+
125
+ That's the whole setup. Every Claude Code session on the machine is covered —
126
+ no per-project config, no special launcher, no flags to remember. Start your
127
+ long automations exactly the way you already do.
128
+
129
+ Setup is deliberately boring and inspectable: it copies a few Python files
130
+ to `~/.claude/claude-powernap/`, merges three hook entries into
131
+ `~/.claude/settings.json` (backing it up first), and schedules the fallback
132
+ watcher (launchd / systemd user timer / Task Scheduler).
133
+ `claude-powernap remove` (or `./uninstall.sh`) reverses all of it. If you
134
+ set `CLAUDE_CONFIG_DIR`, setup follows it — run setup from a normal shell,
135
+ not from inside a Claude Code session, so the right settings file is edited.
136
+
137
+ On macOS the first usage check may trigger one Keychain prompt — the monitor
138
+ reads Claude Code's own OAuth token to ask Anthropic for your real usage
139
+ numbers (see Caveats). Click "Always Allow".
140
+
141
+ ## Toggle
142
+
143
+ ```bash
144
+ claude-powernap on # enable everything
145
+ claude-powernap off # disable everything
146
+ claude-powernap status # current 5h + weekly usage, watcher state
147
+ claude-powernap log # what the watcher and monitor have been doing
148
+ ```
149
+
150
+ ## Configure — `~/.claude/claude-powernap/config.json`
151
+
152
+ | key | default | meaning |
153
+ |---|---|---|
154
+ | `enabled` | `true` | master switch (what `on`/`off` flips) |
155
+ | `threshold_pct` | `90` | warn/pause threshold for the 5h window |
156
+ | `check_interval_s` | `120` | base seconds between checks (auto-tightens to 30s above 80%, every event above 90%) |
157
+ | `safety_margin_min` | `9` | also warn when the current burn rate projects the limit within this many minutes |
158
+ | `weekly_guard` | `false` | opt-in: also warn/pause on the **weekly** window (no auto-resume — its reset is days away) |
159
+ | `weekly_threshold_pct` | `90` | weekly-guard warning threshold |
160
+ | `endpoint_enabled` | `true` | `false` = fully local estimation only |
161
+ | `terminal_app` | `Terminal` | macOS: `Terminal`/`iTerm2`; Linux: terminal binary name (auto-detected if unset) |
162
+ | `resume_grace_min` | `3` | schedule resume this long after reset |
163
+ | `headless_resume_extra_args` | `[]` | extra flags for last-resort headless resume |
164
+ | `local_budget_weighted_tokens` | `null` | manual budget for local estimation |
165
+ | `token_weights` | in/out/cache | per-token-type weights for local estimation |
166
+
167
+ ## Plays by the rules
168
+
169
+ claude-powernap works *with* the usage limit, not around it:
170
+
171
+ - **Zero extra usage.** The same quota, consumed the same way. It never
172
+ gets you more tokens — it just stops a session from dying mid-thought
173
+ and picks the work back up when your own window resets.
174
+ - **Genuine client, official hooks.** Everything runs inside the real
175
+ Claude Code client through its documented hooks system. It never spoofs
176
+ a client identity and never touches permission systems.
177
+ - **Privacy-first, local-only.** Checkpoints, transcripts, config — all of
178
+ it stays on your machine. The one outbound call is the same usage query
179
+ the built-in `/usage` screen makes, and `endpoint_enabled: false` turns
180
+ even that off.
181
+
182
+ ## Caveats
183
+
184
+ - **Undocumented usage endpoint** — exact percentages come from the same
185
+ unpublished API `/usage` uses (read-only, via the OAuth token already on
186
+ your machine; a ToS gray area). Handled: if the endpoint fails or
187
+ you set `endpoint_enabled: false`, the tool switches automatically to
188
+ local transcript estimation, self-calibrated whenever endpoint data was
189
+ available.
190
+ - **The paused session must stay open** — that's the point. If its alarm
191
+ dies anyway (sleep, reboot, crash), the watcher notices the missed wake-up
192
+ and resumes the session itself.
193
+ - **Windows is experimental** — Windows can't reliably tell whether a session
194
+ is still open, so the watcher errs toward caution there: when unsure it
195
+ notifies you instead of auto-resuming (one click, never a forked session).
196
+ CI runs the full cycle on real Windows runners. WSL users: use
197
+ `./install.sh` inside WSL.
198
+ - **Sleep beats timers** — a sleeping laptop fires nothing: the in-session
199
+ alarm and the watcher both wait until the machine wakes, then the watcher
200
+ catches up (rescuing any missed wake-ups). For unattended overnight runs
201
+ keep the machine awake, e.g. `caffeinate -is` on macOS.
202
+ - **Linux notes**: terminal emulator auto-detected; headless servers fall
203
+ through to headless resume; `loginctl enable-linger $USER` keeps the
204
+ watcher running while logged out.
205
+
206
+ ## Uninstall
207
+
208
+ By install method:
209
+
210
+ | installed via | uninstall with |
211
+ |---|---|
212
+ | plugin | run `python3 ~/.claude/claude-powernap/cli.py watcher-remove` (if you set up the watcher), then `/plugin uninstall powernap` |
213
+ | PyPI | `claude-powernap remove` (add `--purge` to delete config/state too), **then** `pip uninstall claude-powernap` — in that order |
214
+ | clone | `./uninstall.sh` (or `--purge`); Windows: `.\uninstall.ps1` (or `-Purge`) |
215
+
216
+ ## License
217
+
218
+ MIT
@@ -0,0 +1,197 @@
1
+ # claude-powernap
2
+
3
+ [![CI](https://github.com/asiagenawi/claude-powernap/actions/workflows/ci.yml/badge.svg)](https://github.com/asiagenawi/claude-powernap/actions/workflows/ci.yml)
4
+ [![Release](https://img.shields.io/github/v/release/asiagenawi/claude-powernap)](https://github.com/asiagenawi/claude-powernap/releases)
5
+ [![License: MIT](https://img.shields.io/badge/license-MIT-blue.svg)](https://github.com/asiagenawi/claude-powernap/blob/main/LICENSE)
6
+ ![Platform](https://img.shields.io/badge/platform-macOS%20%7C%20Linux%20%7C%20Windows-lightgrey)
7
+ ![Deps](https://img.shields.io/badge/deps-stdlib%20only-brightgreen)
8
+
9
+ **Your Claude Code session sees the usage limit coming, saves its work, and
10
+ resumes itself when the window resets. You do nothing.**
11
+
12
+ *(Demo below is an illustrative mock-up of a real cycle the tool ran.)*
13
+
14
+ ![claude-powernap demo: a session gets warned at 91%, checkpoints, pauses, and self-resumes after the window resets](https://raw.githubusercontent.com/asiagenawi/claude-powernap/main/demo/powernap.gif)
15
+
16
+ ## The problem
17
+
18
+ You kick off a long Claude Code automation — a big refactor, a batch
19
+ migration, an overnight research run. You check back three hours later and
20
+ find it died 40 minutes in:
21
+
22
+ ```
23
+ You've hit your session limit · resets 3:00am
24
+ ```
25
+
26
+ Everything since the last commit is in limbo. The context that session had
27
+ built up is sitting frozen mid-thought. And the limit reset hours ago — the
28
+ session just had no way to know, no way to save itself, and no way to come
29
+ back. Your subscription's 5-hour window reset while your automation sat
30
+ dead in a terminal.
31
+
32
+ ## The idea
33
+
34
+ A session that's *about* to hit the limit still has tokens left. That's
35
+ enough budget to do something smarter than die:
36
+
37
+ 1. **A hook watches your usage** (every ~2 min normally, tightening to ~15s
38
+ near the limit; zero workflow changes). It knows your exact window percentage and reset time — the same
39
+ numbers Claude Code's own `/usage` screen shows.
40
+ 2. **At 90% — or earlier if your burn rate projects the limit within ~9
41
+ minutes — the session itself gets warned**: the hook injects a message
42
+ into the live conversation: *"you're at 91%, window resets at 3:00am,
43
+ pause now."*
44
+ 3. **Claude wraps up gracefully**: finishes the current step, writes a
45
+ checkpoint file (what's done, what's in flight, exact next steps), and —
46
+ when the session has a scheduled-tasks capability — schedules a one-shot
47
+ task for just after the reset. Then it idles.
48
+ 4. **At reset, the session wakes itself** — same terminal, same context,
49
+ reads its checkpoint, keeps going. Sessions without a scheduler instead
50
+ checkpoint and tell you when to send any message to resume — and the
51
+ watcher (below) still notifies or reopens as needed.
52
+
53
+ If the estimate is ever wrong and a session hard-hits the wall anyway, a
54
+ background watcher catches that too: after the reset it reopens the session
55
+ in a visible terminal window with the "continue from your checkpoint" prompt
56
+ already submitted. If the original window is still open, you get a
57
+ notification instead — it will never fork a live session.
58
+
59
+ ## How it compares
60
+
61
+ | | warns before the limit | session saves its work | resumes automatically | needs tmux |
62
+ |---|---|---|---|---|
63
+ | **claude-powernap** | ✅ | ✅ | ✅ same session | no |
64
+ | usage monitors (ccusage, claude-monitor) | ⚠️ warns *you*, not the session | ❌ | ❌ | — |
65
+ | auto-retriers (unsnooze, claude-auto-retry, …) | ❌ reacts after death | ❌ dies mid-thought | ✅ | mostly yes |
66
+
67
+ Free, privacy-first, local-only, no dependencies (Python 3 stdlib only). macOS, Linux (incl.
68
+ WSL), native Windows (experimental).
69
+
70
+ ## Install
71
+
72
+ As a Claude Code plugin (inside any Claude Code session):
73
+
74
+ ```
75
+ /plugin marketplace add asiagenawi/claude-powernap
76
+ /plugin install powernap@claude-powernap
77
+ ```
78
+
79
+ The plugin activates the monitoring hooks immediately. The one thing a
80
+ plugin can't do itself is register the fallback watcher (an OS-level
81
+ background job) — so on first run the hook notices it's missing and has the
82
+ session offer you the one command to set it up (or run `/powernap:watcher`
83
+ yourself anytime). Also ships `/powernap:status` and `/powernap:toggle
84
+ on|off`.
85
+
86
+ From PyPI (all platforms):
87
+
88
+ ```bash
89
+ uvx claude-powernap setup # or: pipx install claude-powernap && claude-powernap setup
90
+ ```
91
+
92
+ Or from a clone, if you'd rather read what you run first:
93
+
94
+ ```bash
95
+ git clone https://github.com/asiagenawi/claude-powernap.git && cd claude-powernap
96
+ ./install.sh # macOS / Linux / WSL — same as `claude-powernap setup`
97
+ ```
98
+
99
+ Native Windows clone (PowerShell 7 recommended): `.\install.ps1`
100
+
101
+ Pick ONE install method — plugin or pip/clone. (Both at once is harmless —
102
+ the shared state throttle makes duplicate checks no-ops — but pointless.)
103
+
104
+ That's the whole setup. Every Claude Code session on the machine is covered —
105
+ no per-project config, no special launcher, no flags to remember. Start your
106
+ long automations exactly the way you already do.
107
+
108
+ Setup is deliberately boring and inspectable: it copies a few Python files
109
+ to `~/.claude/claude-powernap/`, merges three hook entries into
110
+ `~/.claude/settings.json` (backing it up first), and schedules the fallback
111
+ watcher (launchd / systemd user timer / Task Scheduler).
112
+ `claude-powernap remove` (or `./uninstall.sh`) reverses all of it. If you
113
+ set `CLAUDE_CONFIG_DIR`, setup follows it — run setup from a normal shell,
114
+ not from inside a Claude Code session, so the right settings file is edited.
115
+
116
+ On macOS the first usage check may trigger one Keychain prompt — the monitor
117
+ reads Claude Code's own OAuth token to ask Anthropic for your real usage
118
+ numbers (see Caveats). Click "Always Allow".
119
+
120
+ ## Toggle
121
+
122
+ ```bash
123
+ claude-powernap on # enable everything
124
+ claude-powernap off # disable everything
125
+ claude-powernap status # current 5h + weekly usage, watcher state
126
+ claude-powernap log # what the watcher and monitor have been doing
127
+ ```
128
+
129
+ ## Configure — `~/.claude/claude-powernap/config.json`
130
+
131
+ | key | default | meaning |
132
+ |---|---|---|
133
+ | `enabled` | `true` | master switch (what `on`/`off` flips) |
134
+ | `threshold_pct` | `90` | warn/pause threshold for the 5h window |
135
+ | `check_interval_s` | `120` | base seconds between checks (auto-tightens to 30s above 80%, every event above 90%) |
136
+ | `safety_margin_min` | `9` | also warn when the current burn rate projects the limit within this many minutes |
137
+ | `weekly_guard` | `false` | opt-in: also warn/pause on the **weekly** window (no auto-resume — its reset is days away) |
138
+ | `weekly_threshold_pct` | `90` | weekly-guard warning threshold |
139
+ | `endpoint_enabled` | `true` | `false` = fully local estimation only |
140
+ | `terminal_app` | `Terminal` | macOS: `Terminal`/`iTerm2`; Linux: terminal binary name (auto-detected if unset) |
141
+ | `resume_grace_min` | `3` | schedule resume this long after reset |
142
+ | `headless_resume_extra_args` | `[]` | extra flags for last-resort headless resume |
143
+ | `local_budget_weighted_tokens` | `null` | manual budget for local estimation |
144
+ | `token_weights` | in/out/cache | per-token-type weights for local estimation |
145
+
146
+ ## Plays by the rules
147
+
148
+ claude-powernap works *with* the usage limit, not around it:
149
+
150
+ - **Zero extra usage.** The same quota, consumed the same way. It never
151
+ gets you more tokens — it just stops a session from dying mid-thought
152
+ and picks the work back up when your own window resets.
153
+ - **Genuine client, official hooks.** Everything runs inside the real
154
+ Claude Code client through its documented hooks system. It never spoofs
155
+ a client identity and never touches permission systems.
156
+ - **Privacy-first, local-only.** Checkpoints, transcripts, config — all of
157
+ it stays on your machine. The one outbound call is the same usage query
158
+ the built-in `/usage` screen makes, and `endpoint_enabled: false` turns
159
+ even that off.
160
+
161
+ ## Caveats
162
+
163
+ - **Undocumented usage endpoint** — exact percentages come from the same
164
+ unpublished API `/usage` uses (read-only, via the OAuth token already on
165
+ your machine; a ToS gray area). Handled: if the endpoint fails or
166
+ you set `endpoint_enabled: false`, the tool switches automatically to
167
+ local transcript estimation, self-calibrated whenever endpoint data was
168
+ available.
169
+ - **The paused session must stay open** — that's the point. If its alarm
170
+ dies anyway (sleep, reboot, crash), the watcher notices the missed wake-up
171
+ and resumes the session itself.
172
+ - **Windows is experimental** — Windows can't reliably tell whether a session
173
+ is still open, so the watcher errs toward caution there: when unsure it
174
+ notifies you instead of auto-resuming (one click, never a forked session).
175
+ CI runs the full cycle on real Windows runners. WSL users: use
176
+ `./install.sh` inside WSL.
177
+ - **Sleep beats timers** — a sleeping laptop fires nothing: the in-session
178
+ alarm and the watcher both wait until the machine wakes, then the watcher
179
+ catches up (rescuing any missed wake-ups). For unattended overnight runs
180
+ keep the machine awake, e.g. `caffeinate -is` on macOS.
181
+ - **Linux notes**: terminal emulator auto-detected; headless servers fall
182
+ through to headless resume; `loginctl enable-linger $USER` keeps the
183
+ watcher running while logged out.
184
+
185
+ ## Uninstall
186
+
187
+ By install method:
188
+
189
+ | installed via | uninstall with |
190
+ |---|---|
191
+ | plugin | run `python3 ~/.claude/claude-powernap/cli.py watcher-remove` (if you set up the watcher), then `/plugin uninstall powernap` |
192
+ | PyPI | `claude-powernap remove` (add `--purge` to delete config/state too), **then** `pip uninstall claude-powernap` — in that order |
193
+ | clone | `./uninstall.sh` (or `--purge`); Windows: `.\uninstall.ps1` (or `-Purge`) |
194
+
195
+ ## License
196
+
197
+ MIT
@@ -0,0 +1,35 @@
1
+ # Security
2
+
3
+ ## What this tool touches
4
+
5
+ - **Reads** Claude Code's OAuth token. macOS: a `security
6
+ find-generic-password` lookup of the cached Claude Code credentials entry;
7
+ on a cache miss only, it runs `security dump-keychain` once to find the
8
+ right entry name — that command lists metadata (names, not secrets) for
9
+ the whole login keychain. Linux/Windows: reads
10
+ `~/.claude/.credentials.json`. The token is used in memory for one request
11
+ and never written anywhere.
12
+ - **Periodic outbound HTTPS requests** to `api.anthropic.com` (the usage
13
+ endpoint — the same query the built-in `/usage` screen makes), at most one
14
+ per check interval (120s normally, down to 15s near the limit). Requests
15
+ identify themselves honestly as `claude-powernap/<version>`. This is the
16
+ only network traffic the tool ever makes; disable with
17
+ `endpoint_enabled: false` for fully-offline operation.
18
+ - **Edits** `~/.claude/settings.json` to register three hooks (a backup copy
19
+ `settings.json.powernap-backup` is written first; `claude-powernap remove`
20
+ reverses the edit).
21
+ - **Reads** your local Claude Code transcripts (`~/.claude/projects/`) for
22
+ token math and limit detection. Nothing from them leaves your machine.
23
+ - **Schedules** the fallback watcher via launchd / systemd user timer /
24
+ Task Scheduler, running as your user.
25
+
26
+ ## Supply chain
27
+
28
+ Python 3 standard library only — no pip packages, no npm, no curl|bash. What
29
+ you clone is what runs: ~1,400 lines of Python you can read first.
30
+
31
+ ## Reporting a vulnerability
32
+
33
+ Use GitHub's private vulnerability reporting on this repository
34
+ (Security → Report a vulnerability). Best-effort response from a single
35
+ maintainer.
@@ -0,0 +1,6 @@
1
+ # claude-powernap installer (native Windows). Idempotent.
2
+ # Thin wrapper: all logic lives in the package CLI (`claude-powernap setup`).
3
+ $ErrorActionPreference = "Stop"
4
+ Set-Location (Split-Path -Parent $MyInvocation.MyCommand.Path)
5
+ $env:PYTHONPATH = "src"
6
+ python -m claude_powernap setup
@@ -0,0 +1,7 @@
1
+ #!/bin/bash
2
+ # claude-powernap installer (macOS / Linux / WSL). Idempotent.
3
+ # Thin wrapper: all logic lives in the package CLI (`claude-powernap setup`).
4
+ set -euo pipefail
5
+ cd "$(dirname "$0")"
6
+ command -v python3 >/dev/null || { echo "ERROR: python3 required"; exit 1; }
7
+ PYTHONPATH=src exec python3 -m claude_powernap setup
@@ -0,0 +1,37 @@
1
+ [build-system]
2
+ requires = ["hatchling>=1.27"]
3
+ build-backend = "hatchling.build"
4
+
5
+ [project]
6
+ name = "claude-powernap"
7
+ version = "0.3.0"
8
+ description = "Your Claude Code session sees the 5-hour limit coming, checkpoints its work, and resumes itself when the window resets."
9
+ readme = "README.md"
10
+ license = "MIT"
11
+ license-files = ["LICENSE"]
12
+ requires-python = ">=3.9"
13
+ authors = [{ name = "asiagenawi" }]
14
+ keywords = ["claude", "claude-code", "anthropic", "usage-limit", "rate-limit", "auto-resume"]
15
+ classifiers = [
16
+ "Development Status :: 4 - Beta",
17
+ "Environment :: Console",
18
+ "Intended Audience :: Developers",
19
+ "Operating System :: MacOS",
20
+ "Operating System :: POSIX :: Linux",
21
+ "Operating System :: Microsoft :: Windows",
22
+ "Programming Language :: Python :: 3",
23
+ "Topic :: Software Development :: Build Tools",
24
+ ]
25
+
26
+ [project.urls]
27
+ Homepage = "https://github.com/asiagenawi/claude-powernap"
28
+ Changelog = "https://github.com/asiagenawi/claude-powernap/blob/main/CHANGELOG.md"
29
+
30
+ [project.scripts]
31
+ claude-powernap = "claude_powernap.cli:main"
32
+
33
+ [tool.hatch.build.targets.wheel]
34
+ packages = ["src/claude_powernap"]
35
+
36
+ [tool.hatch.build.targets.sdist]
37
+ exclude = ["demo", ".github", "scripts", ".claude-plugin", "hooks", "commands"]
@@ -0,0 +1,2 @@
1
+ """claude-powernap: proactive 5-hour-limit pause-and-resume for Claude Code."""
2
+ __version__ = "0.3.0"
@@ -0,0 +1,4 @@
1
+ from .cli import main
2
+
3
+ if __name__ == "__main__":
4
+ main()
@@ -0,0 +1,6 @@
1
+ [Unit]
2
+ Description=claude-powernap fallback watcher (resume Claude Code sessions after limit reset)
3
+
4
+ [Service]
5
+ Type=oneshot
6
+ ExecStart=/usr/bin/env python3 %h/.claude/claude-powernap/fallback_watch.py
@@ -0,0 +1,9 @@
1
+ [Unit]
2
+ Description=Run claude-powernap fallback watcher every 2 minutes
3
+
4
+ [Timer]
5
+ OnBootSec=2min
6
+ OnUnitActiveSec=2min
7
+
8
+ [Install]
9
+ WantedBy=timers.target