Repository navigation
feat(bin): add an opt-in Claude account pool chosen per launch from live quota - #1
Merged
Merged
Conversation
…ive quota config/claude-accounts lists pooled Claude logins; each Claude ship or scout launch picks the eligible login with the highest quota-axi spendPriority, after a five-hour guard, a weekly floor, and a weekly reserve on the pages account. Each member's email is verified through claude auth status --json and the quota-axi reading, so one login is never counted twice. A signed-out, duplicate, misread, or guarded member is skipped with a note; only an empty pool refuses. --account names one pooled account on fm-spawn and fm-control relaunch, the choice is recorded as account= and account_email=, and a relaunch stays on its recorded account while it remains eligible. A present config/claude-account pin still wins, and a home without the pool file launches unchanged.
… legacy relaunch account
Nitsur10
added a commit
that referenced
this pull request
Oct 9, 2026
Bring the fork up to date with upstream main again while keeping the opt-in Claude account pool from fork PR #1. Five files conflicted, each where both sides added an item to the same place, so every resolution keeps both: - bin/fm-spawn.sh usage lines list the fork's --account and upstream's --herdr-resume-lock-wait. - bin/fm-control.sh's relaunch header and resolve_relaunch_profile run the fork's pin-or-pool account check and then upstream's worker tool exclusion check, both before the old agent stops. - docs/agent-control.md and docs/configuration.md name both the Claude account pool and worker tool exclusions. - tests/fm-control-relaunch.test.sh runs both the pool relaunch tests and the tool exclusion relaunch tests.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What this does
Adds an opt-in Claude account pool (
config/claude-accounts) so a home with two Claude Max logins can spread worker launches across both by live usage, instead of pinning every launch to one login.claude auth status --json(must be signed in with an email) and read once withquota-axi --provider claude --no-credential-refresh --max-age 5m --full --json, bounded to 20 seconds and never with--profile-only, so a Keychain-backed login is readable.note:when signed out, duplicated (same email as an earlier account), read as a different email (the read fell back to another login), exhausted, under the fixed 15 percent five-hour guard, under the fixed 10 percent weekly floor, unreadable, or (for thepagesaccount) under the weeklyreserve(default 20).reserve=is the only tunable.all_modelsspendPriority, then weekly percent left, then file order. If every account is skipped after a reading, the launch refuses. If no signed-in account can be read at all, the launch takes the ordinary default login exactly as without a pool and says so; it never falls to the pages account on an unknown quota.pagesaccount, so a session that may publish claude.ai pages runs on the account that owns them.fm-spawn.sh --account <root|email>andfm-control.sh <id> relaunch --account <root|email>override the choice (sign-in check still applies; quota gates do not).account=andaccount_email=on the spawned line and task record. A relaunch stays on the recorded account while it is eligible, otherwise chooses again; a Claude task with noaccount=counts as on the ordinary login. A running conversation never changes account.config/claude-accounts, every launch is exactly unchanged, and an existingconfig/claude-accountpin always wins over a pool.Docs:
docs/configuration.md"Claude account pool (config/claude-accounts)". Tests:tests/fm-worker-account.test.sh(selection, reserve, override, skip-on-signed-out, unreadable-quota paths, duplicate email, no-pool path) andtests/fm-control-relaunch.test.sh(relaunch stays on the recorded account, legacy record withoutaccount=).Example pool file for this Mac:
How it reaches this Mac
This PR targets the fork's
main(Nitsur10/firstmate), not upstream. The live home at/Users/e8e/code/firstmateis currently atfd325b1b, the same commit this branch is based on, but itsmaintracksorigin/main(upstream kunchenguid/firstmate). The ordinary update path pulls upstream only, so after this merges the home needs a one-time fast-forward from the fork (git fetch fork && git merge --ff-only fork/mainon the home'smain, done by firstmate with no live crewmates), followed by a re-read. From then on the home carries a commit upstream does not have, so later upstream updates arrive as a merge or rebase onto fork main rather than a pure fast-forward until this is offered upstream (a separate decision). Nothing changes behaviour until aconfig/claude-accountsfile is written.Profile parity needed before
~/.claude-max1joins the poolNot applied by this PR (out of scope; firstmate applies it by hand). Read-only comparison of
~/.claudeagainst~/.claude-max1, which today holds only.claude.jsonandbackups/(nosettings.json, no skills):settings.jsonhooks:PreToolUsematcherBash->/Users/e8e/.agents/hooks/deny-dangerous.sh(the dangerous-command blocker).SessionStart->gh-axi,chrome-devtools-axi, andbash '/Users/e8e/.claude/hooks/herdr-agent-state.sh' session(absolute path, so it works from any profile once the hook entry exists).settings.jsonkeys to carry:model,modelSettings,skipDangerousModePermissionPrompt,agentPushNotifEnabled(themeandtuiare cosmetic).~/.claude/skills/no-mistakesand~/.claude/skills/synced.~/.claude/plugins/(store,synced)..credentials.json, the Keychain entry, or.claude.jsonaccount state.Related, outside this repo:
~/.local/bin/fm-usagereads~/.claude-max1with--profile-only, which shows nothing for a Keychain login; drop that flag there. Verification once nitesh@e8e.au is signed in:CLAUDE_CONFIG_DIR=~/.claude-max1 quota-axi --provider claude --no-credential-refresh --fullmust name nitesh@e8e.au; the pool also enforces this by skipping a read whose email does not match.Judgment calls
reserve=the only tunable: narrower config, fewer ways to misconfigure the guard.account=is treated as on the ordinary login at relaunch, so tasks started before the pool keep their session history and prompt cache.fm-usagefix were deferred; parity is listed above for a hand-applied step.spendPriorityrather than a new score, with weekly percent left and file order only as tie-breaks.Reviewer quiz
config/claude-accountspresent and no pin, each Claude worker launch picks the pooled login with the best live runway (spendPriority), skipping signed-out, duplicate, mismatched, unreadable, or low accounts and keeping a weekly reserve on the pages account; the choice is recorded asaccount=and kept on relaunch.~/.claude*profiles or syncs their hooks and skills, and changes nothing when the pool file is absent or aconfig/claude-accountpin exists.