{
  "markdown": "<p align=\"center\">\n  <img src=\"banner.png\" alt=\"claude-5h-window-spread\">\n</p>\n\n# claude-5h-window-spread\n\n**Stop hitting your 5h cap. Spread your day across more windows.**\n\nFor devs who hit Claude Pro/Max cap daily. Get up to 33% more cap from the same plan. No cloud. No credentials. One install.\n\n```bash\n/plugin install claude-5h-window-spread@dpt-plugins\n/window-spread setup\n```\n\n---\n\n## The problem\n\n**17:20 on a Tuesday.** 40 minutes before quitting time. You're mid-debug, one fix from done. Cap hits. Locked out. Can't ship the change, can't finish the thread, can't even reply to your colleague's question.\n\nWindow resets at 19:00. By then you're at dinner. Tomorrow you'll start over.\n\nClaude Pro/Max gives you a 5-hour rolling window from your first message. **One window.** Cap typically lands ~40 minutes before the window expires when you're working hard. If your afternoon window started at 12:20, it dies at 17:20 — just before you stop. The last hour of your day evaporates.\n\n| Time  | What happens                                                          |\n| ----- | --------------------------------------------------------------------- |\n| 08:30 | Morning message. W1 opens 8:30-13:30.                                 |\n| 12:20 | Lunch. W1 expires by 13:30 — already past lunch boundary.             |\n| 13:00 | Back at desk. W2 opens whenever you send the first afternoon message. |\n| 17:20 | **Cap hit. Locked out.** 40 min of dense afternoon debug ruined.      |\n| 18:00 | You walk away. Last hour of progress: lost.                           |\n| 19:00 | W2 finally resets. You're not at the keyboard.                        |\n\nThis is the heavy-use dev day on Pro/Max. The lockouts always seem to land at the worst time.\n\n---\n\n## The fix\n\nSend 4 silent pings throughout the day. Each one anchors a fresh 5h window.\n\n### Without plugin — 3 windows, each absorbs an entire work block\n\n```mermaid\ngantt\n    title One workday — natural usage\n    dateFormat HH:mm\n    axisFormat %H:%M\n\n    section Work\n    Block 1 (3h50)   :work1, 08:30, 230m\n    Block 2 (4h)     :work2, 14:00, 240m\n    Evening (3h)     :work3, 20:00, 180m\n\n    section Windows\n    W1 — 4h crammed  :crit, w1, 08:30, 300m\n    W2 — 4h crammed  :crit, w2, 14:00, 300m\n    W3 — 3h evening  :w3,   20:00, 300m\n```\n\nEach window gets a full block. W1 and W2 are at HIGH cap risk — 4h of dense work compressed into one 5h window each.\n\n### With claude-5h-window-spread — 4 windows, work splits across them\n\n```mermaid\ngantt\n    title One workday — with claude-5h-window-spread\n    dateFormat HH:mm\n    axisFormat %H:%M\n\n    section Work\n    Block 1 (3h50)   :work1, 08:30, 230m\n    Block 2 (4h)     :work2, 14:00, 240m\n    Evening (3h)     :work3, 20:00, 180m\n\n    section Windows\n    W1 — 2h30 work   :done, w1, 06:00, 300m\n    W2 — 3h20 work   :done, w2, 11:00, 300m\n    W3 — 3h work     :done, w3, 16:00, 300m\n    W4 — 2h evening  :done, w4, 21:00, 300m\n```\n\nBlock 1 splits at 11:00 (W1 → W2). Block 2 splits at 16:00 (W2 → W3). Evening splits at 21:00 (W3 → W4). **No window ever absorbs an entire work block. Up to 33% more effective cap.**\n\n---\n\n## Install\n\n```\n/plugin marketplace add Digital-Process-Tools/claude-marketplace\n/plugin install claude-5h-window-spread@dpt-plugins\n```\n\nThat's it. Works on macOS, Linux, Windows. Uses local cron — no cloud, no API keys, no auth dance.\n\n---\n\n## Usage\n\n### Setup your schedule\n\n```\n/window-spread setup\n```\n\nThe skill asks your work pattern in plain language:\n\n```\nSkill:  What time do you start work?\nYou:    8h30\nSkill:  Lunch break?\nYou:    12h20 to 14h\nSkill:  When do you stop?\nYou:    18h, then evening session 20-23\nSkill:  Weekdays only?\nYou:    yes\n\nOptimal: 4 pings at 6 / 11 / 16 / 21\nMax work per window: 3h20 (vs 4h natural)\nApply?\n```\n\nConfirm. Done. Pings install via launchd / cron / Task Scheduler.\n\n### Check installed pings\n\n```\n/window-spread status\n```\n\nLists installed pings with next fire times.\n\n### Re-tune\n\nRe-run `/window-spread setup` with a different work pattern. Install is destructive-replace — old pings are removed before new ones are written.\n\n### On Linux: what happens to the rest of your crontab\n\nInstall and uninstall rewrite your whole crontab, so they read it first and keep\neverything that is not a window-spread entry. If that read fails — a permissions\nproblem on the cron spool, a home directory that is not mounted, no `crontab`\nbinary on `PATH` — **nothing is written**. The command reports what it could not\nread and exits non-zero, rather than replacing your crontab with only its own\nlines.\n\nA user with genuinely no crontab yet is not that case: `crontab -l` says\n`no crontab for <user>` there, and install proceeds normally.\n\nIf you are certain the crontab is empty and want to install anyway:\n\n```bash\npython3 scripts/window-spread.py install pings.json --force-replace-crontab\n```\n\nThat flag **discards whatever is in the crontab**. There is no backup.\n\n### What `install` checks, and where\n\nInstall is destructive-replace: it removes your existing window-spread entries\nbefore writing new ones. So everything it checks, it checks **before** that\nremoval — a refusal never costs you the pings you already had.\n\n**Ping times, on every platform.** A ping must be a zero-padded 24h time,\n`HH:MM`, from `00:00` to `23:59`. Anything else is refused and nothing is\ntouched. This used to be enforced only as a side effect of the code that split\nthe hour from the minute, which the Windows path never ran.\n\n**The command, per platform** — because what a scheduler can carry differs:\n\n| Platform | Scheduler | Rule for `--command` |\n| --- | --- | --- |\n| Linux | cron | No newline, carriage return, or bare `%` |\n| macOS | launchd | No control characters except tab and newline; valid UTF-8 |\n| Windows | Task Scheduler | None imposed by this tool |\n\nThe rules differ in **both** directions, which is why there is no single one. A\nnewline is fatal on cron and harmless on launchd; a control character is\nharmless on cron and cannot be represented on launchd at all.\n\nOn Linux, a crontab entry is a single line and cron treats an unescaped `%` as\na newline, so a `--command` containing a newline, a carriage return or a bare\n`%` is refused — otherwise it would split into a second entry that runs on its\nown schedule and that `uninstall` cannot see. Write `\\%` for a literal percent\nsign.\n\nOn macOS the job is a launchd property list, built with a real plist serialiser\nrather than by pasting the command into an XML template. A command containing\n`&`, `<` or `>` — `claude -p 'a && b'`, a redirect — is encoded correctly\ninstead of producing a document launchd cannot parse. What remains is XML's own\nlimit: a C0 control character cannot appear in a plist, and a carriage return\nthat *can* be written is normalised to a newline when the document is read, so\nlaunchd would run something other than what you typed. Both are refused rather\nthan silently rewritten.\n\nWindows imposes no command rule here. `schtasks /tr` applies its own quoting to\n`cmd /c <command>` and that has not been measured on a Windows machine, so no\nrule is claimed for it.\n\n### On macOS: a failed install tries to put your previous ping back\n\nIf launchd refuses the new job, the plist that was there before is written back\nand reloaded. The result carries a `\"restored\"` field saying whether that\nworked — `false` if there was no previous plist to restore, or if reloading it\nalso failed. Previously the old job was unloaded and its file overwritten\nbefore anything checked the new one, so a rejected job simply cost you the\nworking one.\n\n---\n\n## How it works\n\nClaude Pro/Max windows are **5 hours from your first message**. They reset only when expired.\n\nThe math:\n\n1. You can have at most **24 / 5 ≈ 4-5 windows per day**\n2. Each window has its own cap (messages + tokens)\n3. The longer you cram into one window, the higher cap-hit risk\n\nThe algorithm:\n\n1. Take your work blocks\n2. Enumerate ping schedules with 1-5 pings, every consecutive pair ≥5h apart (Anthropic's window-reset rule). Windows can have gaps — your laptop just sits idle between blocks.\n3. Validate each block is fully covered by either a single window or a contiguous run of windows\n4. Pick the schedule that minimizes max work-hours per window, then fewest pings, then prefers round hours (HH:00)\n\nThe result: pings placed wherever they help most, possibly with idle gaps. Each work block split as evenly as the 5h granularity allows.\n\nFor someone with two shifts (5-10am + 6-10pm), this produces something like `02:30 / 07:30 / 15:00 / 20:00` — gap from 12:30 to 15:00 is dead time, and that's fine.\n\n---\n\n## Compared to alternatives\n\n| Tool                                    | Local           | Cross-platform | Multi-window spread | Analytics |\n| --------------------------------------- | --------------- | -------------- | ------------------- | --------- |\n| **claude-5h-window-spread**             | ✅              | ✅             | ✅ (4-window math)  | ✅        |\n| `vdsmon/claude-warmup`                  | ❌ (GH Actions) | ✅             | ❌ (single ping)    | ❌        |\n| `nomadictuba2005/claude-session-keeper` | ✅              | ✅             | ❌ (5h interval)    | ❌        |\n| Anthropic Routines                      | ❌ (cloud)      | ✅             | ❌                  | ❌        |\n| Anthropic Desktop Tasks                 | ✅              | ❌ (no Linux)  | ❌                  | ❌        |\n\n---\n\n## What it doesn't do\n\n- Doesn't reduce token usage. Cap is the same per window — you just have more windows.\n- Doesn't bypass any limit. Uses the windows exactly as designed.\n- Doesn't run when your machine is asleep. Local cron requires the laptop awake.\n\n---\n\n## Not for you if\n\n- You never hit the 5h cap\n- You only use Claude Code casually (a few messages a day)\n- You can't keep your machine awake during your work hours\n\nFor everyone else who's been locked out at 11am — keep reading.\n\n---\n\n## Development\n\nPure stdlib Python. No build step, no deps, no virtualenv required.\n\n### Run tests\n\n```bash\npython3 -m unittest tests.test_window_spread\n```\n\n79 tests cover time parsing, block parsing, simulation math, the optimization algorithm, the natural baseline, and the `compute` subcommand end-to-end.\n\n### Pre-push hook\n\nA pre-push hook at `.githooks/pre-push` runs the full test suite before any push. Enable once per clone:\n\n```bash\ngit config core.hooksPath .githooks\n```\n\nFailed tests block the push. Bypass with `git push --no-verify` (discouraged).\n\n### Manual run\n\n```bash\npython3 scripts/window-spread.py compute --blocks \"8:30-12:20,14:00-18:00,20:00-23:00\"\n```\n\nOutputs JSON. Pipe to `jq` for pretty-printing or to `python3 scripts/window-spread.py install -` to apply via claude-code-scheduler.\n\n## License\n\nSource-available. Commercial redistribution prohibited. See [LICENSE](LICENSE).\n\nBuilt by [Digital Process Tools](https://github.com/Digital-Process-Tools) in Toulouse, France.\n\n---\n\n> \"I hit my limit on a Tuesday afternoon, mid-debug. If this plugin had been installed, the lockout wouldn't have happened. So I built it.\"\n",
  "bytes": 11087,
  "sha": "9864befacb0af1d0e5a96ee2003d3ad72c6e565f19a89a104b0c12c12bbb3a77",
  "repo_slug": "digital-process-tools/claude-5h-window-spread",
  "fonte": "repo",
  "truncated": false,
  "api": "https://agentalog.com/api/listings/plg_digital_process_tools_claude_5h_window_s_183e5a8e/readme"
}