herdr-grazr

skill
Guvenlik Denetimi
Uyari
Health Uyari
  • License — License: MIT
  • Description — Repository has a description
  • Active repo — Last push 0 days ago
  • Low visibility — Only 5 GitHub stars
Code Gecti
  • Code scan — Scanned 9 files during light audit, no dangerous patterns found
Permissions Gecti
  • Permissions — No dangerous permissions requested

Bu listing icin henuz AI raporu yok.

SUMMARY

A simple and reliable auto account switcher for Claude Code: rotates to a fresh account before the 5-hour or weekly rate limit hits, so no pane ever stops at the usage quota. A Herdr plugin.

README.md

grazr

grazr

Rotational grazing for Claude Code: moves the herd to a fresh account before the pasture runs out, in the middle of a message and with no restart.
A Herdr plugin.


CI macOS and Linux Python 3.9 or newer Herdr 0.8.0 or newer no dependencies MIT licence

A Claude pane goes dead when the 5-hour or weekly limit hits. Getting it back
means logging in as another account by hand. grazr does not wait for the wall.
It reads the usage Claude reports after every message, and when a window is
nearly spent it swaps which stored credential the official claude binary
reads to a fresh account. Claude picks that up on its next request, so the
switch lands mid-message. No restart, no background daemon on a timer, no
prompt to answer.

You do nothing. There is no command to run and no prompt to answer. A pane
mid-task keeps going on the fresh account, and a pane you were not watching
never shows that anything changed. You keep working as if nothing had happened,
because from where you sit, nothing did.

This is best effort. Claude's status line is debounced and a slow update can
be cancelled, so a pane that burns through its last percent inside one message
can still hit the wall. What to do then is under "What it will not do".

Requires two or more Claude subscriptions that are all yours. The badges
above carry the rest. Herdr is the comfortable way to run it, with a key, a
toast and a sidebar tag. It also runs on its own, see Without
Herdr
.

How it works ·
Install ·
Without Herdr ·
Swap on demand ·
After a swap ·
What it will not do ·
Policy

How it works

Flowchart of grazr's response to each Claude message: it reads the usage Claude hands its status line, stays put while the account has room, and otherwise swaps the stored credential to a fresh account, which Claude picks up on its next request.

You log in to each account once, with Claude's own claude auth login. grazr
never sees a password and never mints a token. It copies the credential that a
normal login already produced into a parked copy of its own, then copies it
back when that account's turn comes. The claude binary is unmodified, and it
re-reads its credential on its next request. That is what makes the swap
invisible.

grazr learns how much is left from Claude itself. After every message Claude
hands its status-line command the session's five-hour and weekly usage. grazr
sits in that command. It passes the payload on to the status line you had,
shows that line unchanged, and keeps the reading. When a threshold is crossed,
a separate process makes the swap. Claude cancels the status-line command when
the next update arrives, and a swap must never be caught half done by that.
grazr polls nothing and calls no endpoint of its own.

grazr keeps parked credentials where Claude keeps the live one. On macOS that
is the keychain, and no secret ever touches the disk. On Linux there is no
keychain: Claude's own login is a file only you can read, and a parked
credential is stored the same way, in the state directory. The other state
files hold only names, identities and the last known headroom.

Install

herdr plugin install wazum/herdr-grazr

Then enrol each account:

herdr plugin pane open --plugin wazum.grazr --entrypoint enrol

Pick s for the account you are logged into now. Pick l for each extra one.
l logs in through a throwaway config directory, so your live session is never
logged out. One keypress, no Return. q or Esc closes the pane without
changing anything.

Enrolling also connects grazr to Claude's status line and keeps the one you
have. If you later change statusLine in ~/.claude/settings.json by hand,
grazr sees no usage. It says so in a toast when a Claude pane starts, and the
action grazr: connect to Claude's status line puts it back. The disconnect
action restores your previous status line. A plugin update needs nothing from
you: Herdr puts each install in a new directory, and the status line follows
when a Claude pane starts or Herdr does.

Upgrading from 0.2? Remove LIVE_USAGE_BELOW from config.env.

Then list them in the order you want them used:

$EDITOR "$(herdr plugin config-dir wazum.grazr)/config.env"
REMAINING_SESSION=15     # rotate when the 5-hour window has less than this left
REMAINING_WEEKLY=10      # what is left below this expires unused at the weekly reset
ACCOUNTS="work personal" # preference order, first with headroom wins
ENABLED=1
DRY_RUN=0                # 1 = log the decision, do not swap

grazr never moves back to an account just because it recovered. The one
exception is a weekly reset. When the week on the account you are on has just
reset, and another account still has at least ten points more than the weekly
threshold in a week that ends sooner, grazr moves there. What that account
has left goes first, or it expires unused at its reset. Less than ten points
is not worth two swaps.

The same happens in the last day of an account's week. A session swap hours
before a weekly reset leaves that week's remainder parked, so once the parked
account's week ends within 24 hours, its session has room again, and it has
those ten points, grazr goes back for it.

When every account is below the thresholds, grazr moves to the one with the
most left on its lowest window, once that is ten points more than the account
you are on. Otherwise it stays, and you keep working until the wall.

Whatever an account has left when grazr moves off it stays there until that
window resets, so a large weekly margin is a large weekly loss. Raise it only
if you use the same account elsewhere, such as on claude.ai, and want a
reserve for that.

Start with DRY_RUN=1 for a day. Every decision is written to grazr.log in
the plugin's state directory, ~/.local/state/herdr/plugins/wazum.grazr, with a
timestamp, since the status line's own output is the bar. The log also says what
a window had left when it reset. If that is often well above your threshold, the
threshold is higher than it needs to be. After a swap it logs the first reading
on the new account next to what that account had when it was parked. The drop
is what the swap cost: a token refresh and a cold prompt cache on every pane.

Turn Herdr's toasts on

Herdr toasts are off by default, so grazr's notification will not show
until you turn them on. herdr notification show also exits 0 when it shows
nothing, so grazr reads the JSON to find out. Add this to
~/.config/herdr/config.toml:

[ui.toast]
delivery = "herdr"
delay_seconds = 1

[ui.toast.herdr]
position = "bottom-right"

Then run herdr server reload-config. Pick terminal instead of herdr if
you work over SSH, or system for macOS Notification Centre.

A plugin toast lasts about three seconds and there is no setting for it, so
grazr keeps the text to one short line and plays a sound. Pick system or
terminal delivery to read it at your own pace, or set
HERDR_DISABLE_SOUND=1 for silence.

Herdr drops a toast while another one is on screen. For the "every account is
low" message, grazr notices and says it again next time instead of assuming
you read it. A rotation is announced once, so a dropped toast still leaves the
swap in grazr.log.

Without Herdr

grazr needs Python 3 and the claude binary, nothing else. Herdr adds the
install command, the key, the toast and the sidebar tag. Without it, state and
config live in ~/.grazr, and every entry point is a plain command:

git clone https://github.com/wazum/herdr-grazr.git
cd herdr-grazr
python3 grazr.py enrol      # once per account: s for this login, l for another
python3 grazr.py install    # connect Claude's status line, keeping yours
$EDITOR ~/.grazr/config.env # thresholds and ACCOUNTS, as above

From then on grazr rotates on its own. python3 grazr.py status shows the
accounts and what they have left, python3 grazr.py swap moves to the next
account with headroom, swap <account> to the one you name, and uninstall
puts your status line back. A git pull is the update.

What you do without: a swap is written to grazr.log only, since the toast is
Herdr's. Make the swap command a shell alias if you want a key.

Swap on demand

Sometimes you do not want to wait for the threshold. The session is at 93% and
a long task is about to start, so you would rather be on a fresh account first.
grazr has an action for that. Bind it to a key in
~/.config/herdr/config.toml:

[[keys.command]]
key = "prefix+shift+s"
type = "plugin_action"
command = "wazum.grazr.swap"
description = "grazr: swap account now"

Then run herdr server reload-config. The key moves you to the first account
in ACCOUNTS with headroom, which is the choice the automatic path would make,
and announces it in the usual toast. It does not ask whether the account you
are leaving still has room. You asked for the move, so it moves. DRY_RUN=1
applies here too. ENABLED=0 does not, since that flag only quiets the
automatic path. If every other account is spent, the key swaps nothing and says
so in a toast, naming the account that frees up first and the window you are
waiting on, and in herdr plugin log.

To move to one account in particular, name it. Outside Herdr, hand it the
directories Herdr would, as the status line does:

HERDR_PLUGIN_STATE_DIR="${XDG_STATE_HOME:-$HOME/.local/state}/herdr/plugins/wazum.grazr" \
HERDR_PLUGIN_CONFIG_DIR="$(herdr plugin config-dir wazum.grazr)" \
HERDR_BIN_PATH="$(command -v herdr)" \
python3 path/to/grazr.py swap personal

It is the same swap the key makes: same lock, toast, log and DRY_RUN. Only
the target is yours. You can name any enrolled account, by name or id, in
ACCOUNTS or not. If you name the account you are on, or one that is not
enrolled, nothing happens and grazr says so. The same goes for an account
below your thresholds: the next message would move you off it again, so
grazr refuses, like the key does, and tells you when that account frees up.
Herdr actions take no arguments, so this one is for scripts and for clients
that let you pick the account.

After a swap

grazr's toast after a rotation: now on personal

grazr says which account it moved to, in a toast and in grazr.log. To see
what is enrolled and what each account has left:

herdr plugin pane open --plugin wazum.grazr --entrypoint status

Remote Control disconnects

Claude's Remote Control belongs to the signed-in account, so it disconnects on
every swap. Restart it with /remote-control in each pane you care about.
grazr says so in its notification, but it will not type the command for you.
That would mean writing into panes that may be mid-turn, and grazr never
touches the screen.

The account in your sidebar

A toast is gone in three seconds. grazr also publishes the active account as
a $grazr token on every Claude pane, so the sidebar keeps saying which
account you are on.

grazr's tag in the Herdr sidebar: this pane is on the account named work

Herdr shows a token only where your own sidebar row asks for it. Add $grazr
to a row in ~/.config/herdr/config.toml, keeping whatever rows you already
have:

[ui.sidebar.agents]
rows = [
  ["state_icon", "workspace", "tab"],
  [{ token = "agent" }],
  [{ token = "$grazr", fg = "#b5ead7" }],
  [{ token = "terminal_title_stripped" }],
]

Each entry in rows is one line, and a row with three tokens on it runs out of
width, so give the tag its own.

Then run herdr server reload-config. A pane picks up the tag when Claude
starts in it, and a rotation repaints every pane. Panes already open are still
blank, so fill them in once:

herdr plugin action invoke wazum.grazr.tag

A pane you have scrolled up in keeps its old tag until you scroll back down,
because repainting one can jump it to the bottom.

What it will not do

  • Act on a reading from an account it has left. A session keeps reporting the
    old account until its next request, and grazr tells those readings apart by
    the window's reset time and drops them.
  • Touch a pane that already hit the wall. grazr swaps before that. If a pane
    does show a limit, press Esc and send again, and it goes out on the new
    account.

Policy

grazr rotates between subscriptions that all belong to the person running it.
It never shares credentials, never routes requests through another client, and
never changes the claude binary.

Anthropic's public documents do not limit how many accounts one person may
have, and they do not cover switching between two of your own plans. The Claude
Code docs call CLAUDE_CONFIG_DIR "Useful for running multiple accounts side
by side", and they list switching accounts as a normal answer to a usage limit.

Two clauses point the other way, and no document settles them. Advertised
limits "assume ordinary, individual usage of Claude Code". The Consumer Terms
forbid reaching the services "through automated or non-human means, whether
through a bot, script, or otherwise". grazr is a script on the credential path,
not on the request path. But Anthropic has not said whether chaining personal
plans counts as ordinary use, and it can enforce without notice. Anthropic's
own answer to a limit is usage credits. Read the current terms and decide for
yourself.

Yorumlar (0)

Sonuc bulunamadi