Autonomous multi-project dev orchestrator for Claude Code — works through per-project TODOs, escalates only genuinely in-doubt decisions via Telegram, and survives 5-hour usage-limit resets automatically.
Python
1
61 commits
updated Sep 12, 2026
Your Claude Code TODOs, worked while you're not watching.
Work around the clock to squeeze the latest drop of juice from Claude Code. Most of your 5-hour window goes idle once you step away — squeezer keeps working through it instead of letting that paid-for capacity sit unused. A background daemon that works through your project TODOs while you're away or rate-limited, texts you over Telegram, escalates only the in-doubt calls, and survives 5-hour usage resets automatically — with a fully autonomous mode so your nights stay yours.
It always keeps a configurable slice of the window free so you can grab manual control the moment something looks off, and an optional human-in-loop mode hands control back to you at the start of every fresh window (or once a day) instead of running fully unattended.
There's no tmux session and no interactive pane to babysit: the daemon
spawns a fresh headless claude -p --resume <session-id> turn whenever
there's work to do, resuming the same ongoing conversation each time, and
rides out Pro-plan rate-limit resets by simply waiting for the next window.
# 1. Add this repo as a plugin marketplace source, then install it, then:
/squeezer:setup
That one command walks you through registering your projects, setting up
the Telegram bot, and installing the background daemon as an OS service
(launchd on macOS, systemd --user on Linux). It's idempotent — safe to
re-run any time. Full step-by-step details are in Setup below.
This repo is generic on purpose: no private project names, paths, or
secrets are committed. Everything project-specific lives in your local
SQUEEZER_HOME (default ~/.config/squeezer) — entirely separate from
wherever this plugin package itself is installed, so upgrading the plugin
never touches your registered projects, secrets, or state.
daemon/daemon.py is the only long-running process — installed as a
launchd (macOS) or systemd --user (Linux) service by /squeezer:setup,
so it survives reboots and crashes on its own. It long-polls Telegram,
paces continuation turns against the token budget, and (in human-in-loop
mode) asks what to work on next.claude -p --resume <session-id> process,
--add-dir'd into every project in config.json, run with cwd set to
SQUEEZER_HOME so it picks up CLAUDE.md/ESCALATION_POLICY.md/ROUTINE.md/
todos/ from there.no_reserve_hours in
config.json — hours when no one needs it free to grab manual control,
default 02:00–07:00 local time. Set it to null to disable.hooks/budget_guard.sh sums real token usage from the session's own
transcript and blocks further tool calls once the configured reserve is
breached — enforced in code, not by asking the model nicely.telegram_send MCP tool to proactively notify you or
escalate, per ESCALATION_POLICY.md.See templates/CLAUDE.md.template (copied to SQUEEZER_HOME/CLAUDE.md on
setup) for the full operating policy a running instance follows.
SQUEEZER_HOME/state/worklog.md is the only durable record of why the
orchestrator did what it did — which task it picked and on what grounds,
what it escalated, what you replied over Telegram, what it deliberately
chose not to do. After a few weeks that history is only answerable by
opening a large file and reading it. The /why feature asks it a question
in plain English and gets back the decision, the reasoning behind it, and
the ## <date> heading it came from.
From the command line:
SQUEEZER_HOME=retrieval-demo python3 daemon/worklog_query.py \
"why does elevation use a --settings overlay instead of --dangerously-skip-permissions?"
runs against the placeholder worklog shipped in retrieval-demo/
(never your real SQUEEZER_HOME — see its own README) and answers something
like:
Elevation rejected `--dangerously-skip-permissions`: unscoped, bypasses tool
sandboxing entirely — could read `~/.ssh/id_rsa` or overwrite `~/.zshrc`.
Chose `--settings` overlay with `autoMode.allow` instead: scoped to lifting
`soft_deny`-class actions only, never touches `~/.claude/settings.json`, no
leak into human's interactive sessions. `hard_deny` stays untouched
regardless — permanent floor, no runtime override.
Citation: `## 2026-09-04 — Telegram TOTP elevation: why 2FA, and why this
design specifically`
Against a real install, just drop SQUEEZER_HOME=retrieval-demo and ask
about your own history. From Telegram, /why <question> does the same
thing but is answered instantly — handled inline next to /pause and
/resume, never queued behind a worker turn.
Limitations, stated plainly:
claude -p runs with all tools disabled (--tools "") on purpose.
Found the hard way: with tools enabled, a query about squeezer's own
design once answered from a spec file on disk instead of the worklog
actually in the prompt — correct-sounding, uncited, and silently wrong
source. Disabling tools makes the worklog the only thing it can see.claude -p; a one-line question costs roughly as many
input tokens as the log is long, and that only grows over time.MAX_WORKLOG_CHARS (400,000 characters) the log is truncated to its most
recent portion before being sent, so questions about older decisions stop
being answerable. The answer says when this happened rather than quietly
replying from a partial record. How long that takes depends entirely on
how much the instance writes — the worklog this was measured against grew
~3.4KB/day, which is roughly a year; a busier one gets there far sooner.The first design for this was a real retrieval pipeline: an entry parser, inverse-document-frequency-weighted term scoring, a decision-marker boost, a recency tiebreak, and token-budgeted selection with a minimum-entry floor.
It was all cut before any code was written, after measuring the corpus — about 13.8k tokens against a 200k-token context window. The whole worklog fits in one prompt, so every one of those components could only make recall worse than sending everything, in exchange for a token saving nobody needs on a hand-triggered query. What shipped instead reads the file and asks the question, and recall is 100% by construction because nothing selects between entries.
That cut is the main trade-off in this feature, and it is what the
truncation and cost limitations above are the price of. The reasoning, the
measurement, and the two thresholds that would justify building the ranker
after all are recorded in
planning/.
Set "mode": "human_in_loop" in config.json, or send /manual to the bot
anytime (/auto switches back). In this mode, whenever a fresh 5-hour budget
window opens — or, with "human_in_loop": {"ask_cadence": "daily"}, once a
day right at no_reserve_hours.start — the daemon messages you the top open
TODO items and waits for a reply before doing anything else. You can reply
with a number, describe any other task, or name a brand-new project path to
register; you can also cap that session's spend (e.g. "cap it at 40%"), which
the daemon enforces as a hard stop. You're never asked or blocked during
no_reserve_hours — the daemon just runs fully automatically through the
night either way.
Add this repo as a plugin marketplace source and install it, then run:
/squeezer:setup
This walks you through registering your projects, setting up the Telegram bot, and installing the background daemon as an OS service. It's idempotent — safe to re-run any time (e.g. after adding a project).
/squeezer:setup seeds SQUEEZER_HOME/config.json from
templates/config.example.json. Replace the placeholder entries with your
own:
{
"name": "example-project-1",
"path": "/absolute/path/to/example-project-1",
"notes": "what this project is / any constraints the agent should know"
}
Each project needs git — if one doesn't have it yet, run git init in it
first (no remote required). This gives the agent an undo mechanism before
it's allowed to touch that project; /squeezer:setup's validation step
refuses to register a project with no git history until you do this.
todos/<project>/TODO.md for each registered projectUse templates/TODO.md.example as the format reference — a structured
checklist, not freeform notes. If a project already has its own informal
TODO.md at its repo root, leave it alone: the agent treats that as
read-only reference material, never as a task source.
/newbot,
and save the token it gives you./squeezer:setup fetches getUpdates and prints your numeric chat_id
and user_id so only you can drive the bot. Every inbound message is
checked against both — not just the chat, but the actual sender — so it
stays locked to you even if the bot is ever added to a group.Nothing in this repo needs to change — it's generic plugin code. Install the
plugin on the new machine and run /squeezer:setup again with that
machine's real projects; SQUEEZER_HOME is where all machine/user-specific
state lives.
/plugin uninstall removes squeezer from Claude Code's plugin list, but it
doesn't know squeezer also registered a background OS service and edited
your global ~/.claude/settings.json statusLine during /squeezer:setup.
Run /squeezer:uninstall (before or after) to tear those down — it stops
the daemon service and strips just squeezer's own line from the statusLine,
leaving any other chained statusline command (e.g. claude-hud) intact. It
never touches SQUEEZER_HOME — your registered projects, TODOs, worklog,
and Telegram credentials are yours to remove by hand if you actually want
them gone.
See templates/ESCALATION_POLICY.md.template (copied to
SQUEEZER_HOME/ESCALATION_POLICY.md on setup) for what the agent handles
autonomously vs. what it escalates to you over Telegram.
Send /elevate <6-digit code> <hours> (hours: 2, 4, 8, or 24) to temporarily
widen what the daemon can do unattended — it layers a scoped authorization
onto the next turn so auto-mode's classifier can cross soft_deny-class
restrictions with your explicit consent. hard_deny and every credential/
sandbox protection stay completely untouched, no matter what. /lockdown
ends an active elevation immediately. Run /squeezer:2fa-setup once to
enroll a TOTP secret (Google Authenticator or any compatible app) before
using either command.
Issues and PRs welcome — especially reports of escalation-policy edge cases or daemon reliability bugs. If squeezer is saving you a rate-limit window's worth of babysitting, a star on the repo is the easiest way to help other Claude Code users find it.
61 commits
Python
99.7%
Autonomous multi-project dev orchestrator for Claude Code — works through per-project TODOs, escalates only genuinely in-doubt decisions via Telegram, and survives 5-hour usage-limit resets automatically.
Python
1
61 commits
updated Sep 12, 2026
Your Claude Code TODOs, worked while you're not watching.
Work around the clock to squeeze the latest drop of juice from Claude Code. Most of your 5-hour window goes idle once you step away — squeezer keeps working through it instead of letting that paid-for capacity sit unused. A background daemon that works through your project TODOs while you're away or rate-limited, texts you over Telegram, escalates only the in-doubt calls, and survives 5-hour usage resets automatically — with a fully autonomous mode so your nights stay yours.
It always keeps a configurable slice of the window free so you can grab manual control the moment something looks off, and an optional human-in-loop mode hands control back to you at the start of every fresh window (or once a day) instead of running fully unattended.
There's no tmux session and no interactive pane to babysit: the daemon
spawns a fresh headless claude -p --resume <session-id> turn whenever
there's work to do, resuming the same ongoing conversation each time, and
rides out Pro-plan rate-limit resets by simply waiting for the next window.
# 1. Add this repo as a plugin marketplace source, then install it, then:
/squeezer:setup
That one command walks you through registering your projects, setting up
the Telegram bot, and installing the background daemon as an OS service
(launchd on macOS, systemd --user on Linux). It's idempotent — safe to
re-run any time. Full step-by-step details are in Setup below.
This repo is generic on purpose: no private project names, paths, or
secrets are committed. Everything project-specific lives in your local
SQUEEZER_HOME (default ~/.config/squeezer) — entirely separate from
wherever this plugin package itself is installed, so upgrading the plugin
never touches your registered projects, secrets, or state.
daemon/daemon.py is the only long-running process — installed as a
launchd (macOS) or systemd --user (Linux) service by /squeezer:setup,
so it survives reboots and crashes on its own. It long-polls Telegram,
paces continuation turns against the token budget, and (in human-in-loop
mode) asks what to work on next.claude -p --resume <session-id> process,
--add-dir'd into every project in config.json, run with cwd set to
SQUEEZER_HOME so it picks up CLAUDE.md/ESCALATION_POLICY.md/ROUTINE.md/
todos/ from there.no_reserve_hours in
config.json — hours when no one needs it free to grab manual control,
default 02:00–07:00 local time. Set it to null to disable.hooks/budget_guard.sh sums real token usage from the session's own
transcript and blocks further tool calls once the configured reserve is
breached — enforced in code, not by asking the model nicely.telegram_send MCP tool to proactively notify you or
escalate, per ESCALATION_POLICY.md.See templates/CLAUDE.md.template (copied to SQUEEZER_HOME/CLAUDE.md on
setup) for the full operating policy a running instance follows.
SQUEEZER_HOME/state/worklog.md is the only durable record of why the
orchestrator did what it did — which task it picked and on what grounds,
what it escalated, what you replied over Telegram, what it deliberately
chose not to do. After a few weeks that history is only answerable by
opening a large file and reading it. The /why feature asks it a question
in plain English and gets back the decision, the reasoning behind it, and
the ## <date> heading it came from.
From the command line:
SQUEEZER_HOME=retrieval-demo python3 daemon/worklog_query.py \
"why does elevation use a --settings overlay instead of --dangerously-skip-permissions?"
runs against the placeholder worklog shipped in retrieval-demo/
(never your real SQUEEZER_HOME — see its own README) and answers something
like:
Elevation rejected `--dangerously-skip-permissions`: unscoped, bypasses tool
sandboxing entirely — could read `~/.ssh/id_rsa` or overwrite `~/.zshrc`.
Chose `--settings` overlay with `autoMode.allow` instead: scoped to lifting
`soft_deny`-class actions only, never touches `~/.claude/settings.json`, no
leak into human's interactive sessions. `hard_deny` stays untouched
regardless — permanent floor, no runtime override.
Citation: `## 2026-09-04 — Telegram TOTP elevation: why 2FA, and why this
design specifically`
Against a real install, just drop SQUEEZER_HOME=retrieval-demo and ask
about your own history. From Telegram, /why <question> does the same
thing but is answered instantly — handled inline next to /pause and
/resume, never queued behind a worker turn.
Limitations, stated plainly:
claude -p runs with all tools disabled (--tools "") on purpose.
Found the hard way: with tools enabled, a query about squeezer's own
design once answered from a spec file on disk instead of the worklog
actually in the prompt — correct-sounding, uncited, and silently wrong
source. Disabling tools makes the worklog the only thing it can see.claude -p; a one-line question costs roughly as many
input tokens as the log is long, and that only grows over time.MAX_WORKLOG_CHARS (400,000 characters) the log is truncated to its most
recent portion before being sent, so questions about older decisions stop
being answerable. The answer says when this happened rather than quietly
replying from a partial record. How long that takes depends entirely on
how much the instance writes — the worklog this was measured against grew
~3.4KB/day, which is roughly a year; a busier one gets there far sooner.The first design for this was a real retrieval pipeline: an entry parser, inverse-document-frequency-weighted term scoring, a decision-marker boost, a recency tiebreak, and token-budgeted selection with a minimum-entry floor.
It was all cut before any code was written, after measuring the corpus — about 13.8k tokens against a 200k-token context window. The whole worklog fits in one prompt, so every one of those components could only make recall worse than sending everything, in exchange for a token saving nobody needs on a hand-triggered query. What shipped instead reads the file and asks the question, and recall is 100% by construction because nothing selects between entries.
That cut is the main trade-off in this feature, and it is what the
truncation and cost limitations above are the price of. The reasoning, the
measurement, and the two thresholds that would justify building the ranker
after all are recorded in
planning/.
Set "mode": "human_in_loop" in config.json, or send /manual to the bot
anytime (/auto switches back). In this mode, whenever a fresh 5-hour budget
window opens — or, with "human_in_loop": {"ask_cadence": "daily"}, once a
day right at no_reserve_hours.start — the daemon messages you the top open
TODO items and waits for a reply before doing anything else. You can reply
with a number, describe any other task, or name a brand-new project path to
register; you can also cap that session's spend (e.g. "cap it at 40%"), which
the daemon enforces as a hard stop. You're never asked or blocked during
no_reserve_hours — the daemon just runs fully automatically through the
night either way.
Add this repo as a plugin marketplace source and install it, then run:
/squeezer:setup
This walks you through registering your projects, setting up the Telegram bot, and installing the background daemon as an OS service. It's idempotent — safe to re-run any time (e.g. after adding a project).
/squeezer:setup seeds SQUEEZER_HOME/config.json from
templates/config.example.json. Replace the placeholder entries with your
own:
{
"name": "example-project-1",
"path": "/absolute/path/to/example-project-1",
"notes": "what this project is / any constraints the agent should know"
}
Each project needs git — if one doesn't have it yet, run git init in it
first (no remote required). This gives the agent an undo mechanism before
it's allowed to touch that project; /squeezer:setup's validation step
refuses to register a project with no git history until you do this.
todos/<project>/TODO.md for each registered projectUse templates/TODO.md.example as the format reference — a structured
checklist, not freeform notes. If a project already has its own informal
TODO.md at its repo root, leave it alone: the agent treats that as
read-only reference material, never as a task source.
/newbot,
and save the token it gives you./squeezer:setup fetches getUpdates and prints your numeric chat_id
and user_id so only you can drive the bot. Every inbound message is
checked against both — not just the chat, but the actual sender — so it
stays locked to you even if the bot is ever added to a group.Nothing in this repo needs to change — it's generic plugin code. Install the
plugin on the new machine and run /squeezer:setup again with that
machine's real projects; SQUEEZER_HOME is where all machine/user-specific
state lives.
/plugin uninstall removes squeezer from Claude Code's plugin list, but it
doesn't know squeezer also registered a background OS service and edited
your global ~/.claude/settings.json statusLine during /squeezer:setup.
Run /squeezer:uninstall (before or after) to tear those down — it stops
the daemon service and strips just squeezer's own line from the statusLine,
leaving any other chained statusline command (e.g. claude-hud) intact. It
never touches SQUEEZER_HOME — your registered projects, TODOs, worklog,
and Telegram credentials are yours to remove by hand if you actually want
them gone.
See templates/ESCALATION_POLICY.md.template (copied to
SQUEEZER_HOME/ESCALATION_POLICY.md on setup) for what the agent handles
autonomously vs. what it escalates to you over Telegram.
Send /elevate <6-digit code> <hours> (hours: 2, 4, 8, or 24) to temporarily
widen what the daemon can do unattended — it layers a scoped authorization
onto the next turn so auto-mode's classifier can cross soft_deny-class
restrictions with your explicit consent. hard_deny and every credential/
sandbox protection stay completely untouched, no matter what. /lockdown
ends an active elevation immediately. Run /squeezer:2fa-setup once to
enroll a TOTP secret (Google Authenticator or any compatible app) before
using either command.
Issues and PRs welcome — especially reports of escalation-policy edge cases or daemon reliability bugs. If squeezer is saving you a rate-limit window's worth of babysitting, a star on the repo is the easiest way to help other Claude Code users find it.
61 commits
Python
99.7%