brindle 0.2.1__tar.gz → 0.3.1__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.
Files changed (124) hide show
  1. {brindle-0.2.1 → brindle-0.3.1}/PKG-INFO +123 -12
  2. {brindle-0.2.1 → brindle-0.3.1}/README.md +122 -11
  3. {brindle-0.2.1 → brindle-0.3.1}/pyproject.toml +3 -1
  4. {brindle-0.2.1 → brindle-0.3.1}/src/brindle/agents.py +108 -13
  5. {brindle-0.2.1 → brindle-0.3.1}/src/brindle/autopilot.py +5 -0
  6. {brindle-0.2.1 → brindle-0.3.1}/src/brindle/builtin_agents/developer-light.md +2 -2
  7. {brindle-0.2.1 → brindle-0.3.1}/src/brindle/ci_adapters.py +83 -11
  8. {brindle-0.2.1 → brindle-0.3.1}/src/brindle/ci_client.py +368 -13
  9. {brindle-0.2.1 → brindle-0.3.1}/src/brindle/ci_federation.py +250 -0
  10. {brindle-0.2.1 → brindle-0.3.1}/src/brindle/ci_hosts.py +65 -6
  11. {brindle-0.2.1 → brindle-0.3.1}/src/brindle/cli.py +72 -7
  12. brindle-0.3.1/src/brindle/company_identity.py +531 -0
  13. brindle-0.3.1/src/brindle/company_login.py +416 -0
  14. {brindle-0.2.1 → brindle-0.3.1}/src/brindle/config.py +6 -2
  15. {brindle-0.2.1 → brindle-0.3.1}/src/brindle/cost.py +12 -1
  16. {brindle-0.2.1 → brindle-0.3.1}/src/brindle/cull.py +73 -4
  17. {brindle-0.2.1 → brindle-0.3.1}/src/brindle/doctor.py +137 -0
  18. brindle-0.3.1/src/brindle/identity_lock.py +71 -0
  19. brindle-0.3.1/src/brindle/keys_cmds.py +121 -0
  20. brindle-0.2.1/src/brindle/pro/credentials.py → brindle-0.3.1/src/brindle/keystore.py +145 -39
  21. {brindle-0.2.1 → brindle-0.3.1}/src/brindle/legacy.py +12 -1
  22. {brindle-0.2.1 → brindle-0.3.1}/src/brindle/mcp_server.py +16 -0
  23. brindle-0.3.1/src/brindle/model_access.py +293 -0
  24. {brindle-0.2.1 → brindle-0.3.1}/src/brindle/native/runner.py +4 -1
  25. brindle-0.3.1/src/brindle/pane_auth.py +87 -0
  26. {brindle-0.2.1 → brindle-0.3.1}/src/brindle/pipeline.py +70 -0
  27. {brindle-0.2.1 → brindle-0.3.1}/src/brindle/pool.py +15 -11
  28. {brindle-0.2.1 → brindle-0.3.1}/src/brindle/pricing.py +2 -1
  29. {brindle-0.2.1 → brindle-0.3.1}/src/brindle/pro/account.py +78 -8
  30. {brindle-0.2.1 → brindle-0.3.1}/src/brindle/pro/auth.py +29 -6
  31. brindle-0.3.1/src/brindle/pro/credentials.py +53 -0
  32. {brindle-0.2.1 → brindle-0.3.1}/src/brindle/pro/managed_models.py +53 -3
  33. {brindle-0.2.1 → brindle-0.3.1}/src/brindle/pro/org_profiles.py +33 -0
  34. {brindle-0.2.1 → brindle-0.3.1}/src/brindle/pro/team_policy.py +282 -5
  35. {brindle-0.2.1 → brindle-0.3.1}/src/brindle/procs.py +23 -0
  36. {brindle-0.2.1 → brindle-0.3.1}/src/brindle/profiles.py +33 -2
  37. {brindle-0.2.1 → brindle-0.3.1}/src/brindle/providers.py +278 -9
  38. {brindle-0.2.1 → brindle-0.3.1}/src/brindle/quota.py +14 -0
  39. {brindle-0.2.1 → brindle-0.3.1}/src/brindle/rewind.py +2 -1
  40. {brindle-0.2.1 → brindle-0.3.1}/src/brindle/secrets.py +54 -8
  41. brindle-0.3.1/src/brindle/self_serve.py +344 -0
  42. brindle-0.3.1/src/brindle/signin_pause.py +384 -0
  43. {brindle-0.2.1 → brindle-0.3.1}/src/brindle/tasks.py +8 -0
  44. {brindle-0.2.1 → brindle-0.3.1}/src/brindle/view.py +12 -1
  45. {brindle-0.2.1 → brindle-0.3.1}/src/brindle/workspaces.py +27 -7
  46. {brindle-0.2.1 → brindle-0.3.1}/.gitignore +0 -0
  47. {brindle-0.2.1 → brindle-0.3.1}/LICENSE +0 -0
  48. {brindle-0.2.1 → brindle-0.3.1}/SCHEDULE-A +0 -0
  49. {brindle-0.2.1 → brindle-0.3.1}/src/brindle/__init__.py +0 -0
  50. {brindle-0.2.1 → brindle-0.3.1}/src/brindle/__main__.py +0 -0
  51. {brindle-0.2.1 → brindle-0.3.1}/src/brindle/account.py +0 -0
  52. {brindle-0.2.1 → brindle-0.3.1}/src/brindle/airgap.py +0 -0
  53. {brindle-0.2.1 → brindle-0.3.1}/src/brindle/antigravity.py +0 -0
  54. {brindle-0.2.1 → brindle-0.3.1}/src/brindle/budget.py +0 -0
  55. {brindle-0.2.1 → brindle-0.3.1}/src/brindle/builtin_agents/__init__.py +0 -0
  56. {brindle-0.2.1 → brindle-0.3.1}/src/brindle/builtin_agents/backend-auditor.md +0 -0
  57. {brindle-0.2.1 → brindle-0.3.1}/src/brindle/builtin_agents/developer-codex.md +0 -0
  58. {brindle-0.2.1 → brindle-0.3.1}/src/brindle/builtin_agents/developer-heavy.md +0 -0
  59. {brindle-0.2.1 → brindle-0.3.1}/src/brindle/builtin_agents/developer-local.md +0 -0
  60. {brindle-0.2.1 → brindle-0.3.1}/src/brindle/builtin_agents/developer.md +0 -0
  61. {brindle-0.2.1 → brindle-0.3.1}/src/brindle/builtin_agents/qa.md +0 -0
  62. {brindle-0.2.1 → brindle-0.3.1}/src/brindle/builtin_agents/reviewer-codex.md +0 -0
  63. {brindle-0.2.1 → brindle-0.3.1}/src/brindle/builtin_agents/reviewer-local.md +0 -0
  64. {brindle-0.2.1 → brindle-0.3.1}/src/brindle/builtin_agents/reviewer.md +0 -0
  65. {brindle-0.2.1 → brindle-0.3.1}/src/brindle/builtin_agents/subagent.md +0 -0
  66. {brindle-0.2.1 → brindle-0.3.1}/src/brindle/builtin_agents/supervisor.md +0 -0
  67. {brindle-0.2.1 → brindle-0.3.1}/src/brindle/builtin_rules/__init__.py +0 -0
  68. {brindle-0.2.1 → brindle-0.3.1}/src/brindle/builtin_rules/security/backend.md +0 -0
  69. {brindle-0.2.1 → brindle-0.3.1}/src/brindle/builtin_rules/style/minimal-diff.md +0 -0
  70. {brindle-0.2.1 → brindle-0.3.1}/src/brindle/builtin_rules/tests/only.md +0 -0
  71. {brindle-0.2.1 → brindle-0.3.1}/src/brindle/codemap.py +0 -0
  72. {brindle-0.2.1 → brindle-0.3.1}/src/brindle/codex_hook.py +0 -0
  73. {brindle-0.2.1 → brindle-0.3.1}/src/brindle/conflicts.py +0 -0
  74. {brindle-0.2.1 → brindle-0.3.1}/src/brindle/cost_estimate.py +0 -0
  75. {brindle-0.2.1 → brindle-0.3.1}/src/brindle/db.py +0 -0
  76. {brindle-0.2.1 → brindle-0.3.1}/src/brindle/demo.py +0 -0
  77. {brindle-0.2.1 → brindle-0.3.1}/src/brindle/detect.py +0 -0
  78. {brindle-0.2.1 → brindle-0.3.1}/src/brindle/escapes.py +0 -0
  79. {brindle-0.2.1 → brindle-0.3.1}/src/brindle/events.py +0 -0
  80. {brindle-0.2.1 → brindle-0.3.1}/src/brindle/gates.py +0 -0
  81. {brindle-0.2.1 → brindle-0.3.1}/src/brindle/git.py +0 -0
  82. {brindle-0.2.1 → brindle-0.3.1}/src/brindle/guardrails.py +0 -0
  83. {brindle-0.2.1 → brindle-0.3.1}/src/brindle/history.py +0 -0
  84. {brindle-0.2.1 → brindle-0.3.1}/src/brindle/inbox.py +0 -0
  85. {brindle-0.2.1 → brindle-0.3.1}/src/brindle/learned_rules.py +0 -0
  86. {brindle-0.2.1 → brindle-0.3.1}/src/brindle/learning.py +0 -0
  87. {brindle-0.2.1 → brindle-0.3.1}/src/brindle/native/__init__.py +0 -0
  88. {brindle-0.2.1 → brindle-0.3.1}/src/brindle/native/client.py +0 -0
  89. {brindle-0.2.1 → brindle-0.3.1}/src/brindle/native/loop.py +0 -0
  90. {brindle-0.2.1 → brindle-0.3.1}/src/brindle/native/permissions.py +0 -0
  91. {brindle-0.2.1 → brindle-0.3.1}/src/brindle/native/serve.py +0 -0
  92. {brindle-0.2.1 → brindle-0.3.1}/src/brindle/native/tools.py +0 -0
  93. {brindle-0.2.1 → brindle-0.3.1}/src/brindle/permissions.py +0 -0
  94. {brindle-0.2.1 → brindle-0.3.1}/src/brindle/plugins.py +0 -0
  95. {brindle-0.2.1 → brindle-0.3.1}/src/brindle/policy.py +0 -0
  96. {brindle-0.2.1 → brindle-0.3.1}/src/brindle/pro/__init__.py +0 -0
  97. {brindle-0.2.1 → brindle-0.3.1}/src/brindle/pro/_files.py +0 -0
  98. {brindle-0.2.1 → brindle-0.3.1}/src/brindle/pro/audit_chain.py +0 -0
  99. {brindle-0.2.1 → brindle-0.3.1}/src/brindle/pro/audit_export.py +0 -0
  100. {brindle-0.2.1 → brindle-0.3.1}/src/brindle/pro/brief_learning.py +0 -0
  101. {brindle-0.2.1 → brindle-0.3.1}/src/brindle/pro/cost_centers.py +0 -0
  102. {brindle-0.2.1 → brindle-0.3.1}/src/brindle/pro/features.py +0 -0
  103. {brindle-0.2.1 → brindle-0.3.1}/src/brindle/pro/keys.py +0 -0
  104. {brindle-0.2.1 → brindle-0.3.1}/src/brindle/pro/learning.py +0 -0
  105. {brindle-0.2.1 → brindle-0.3.1}/src/brindle/pro/license.py +0 -0
  106. {brindle-0.2.1 → brindle-0.3.1}/src/brindle/pro/loopback.py +0 -0
  107. {brindle-0.2.1 → brindle-0.3.1}/src/brindle/pro/orgkey.py +0 -0
  108. {brindle-0.2.1 → brindle-0.3.1}/src/brindle/pro/rollout.py +0 -0
  109. {brindle-0.2.1 → brindle-0.3.1}/src/brindle/pro/settings_sync.py +0 -0
  110. {brindle-0.2.1 → brindle-0.3.1}/src/brindle/pro/status.py +0 -0
  111. {brindle-0.2.1 → brindle-0.3.1}/src/brindle/pro/team_events.py +0 -0
  112. {brindle-0.2.1 → brindle-0.3.1}/src/brindle/repo_cmds.py +0 -0
  113. {brindle-0.2.1 → brindle-0.3.1}/src/brindle/repos.py +0 -0
  114. {brindle-0.2.1 → brindle-0.3.1}/src/brindle/rule_checks.py +0 -0
  115. {brindle-0.2.1 → brindle-0.3.1}/src/brindle/savings.py +0 -0
  116. {brindle-0.2.1 → brindle-0.3.1}/src/brindle/scratch.py +0 -0
  117. {brindle-0.2.1 → brindle-0.3.1}/src/brindle/services.py +0 -0
  118. {brindle-0.2.1 → brindle-0.3.1}/src/brindle/sessions.py +0 -0
  119. {brindle-0.2.1 → brindle-0.3.1}/src/brindle/sidebar_follow.py +0 -0
  120. {brindle-0.2.1 → brindle-0.3.1}/src/brindle/status_cache.py +0 -0
  121. {brindle-0.2.1 → brindle-0.3.1}/src/brindle/tmux.py +0 -0
  122. {brindle-0.2.1 → brindle-0.3.1}/src/brindle/usage.py +0 -0
  123. {brindle-0.2.1 → brindle-0.3.1}/src/brindle/watch.py +0 -0
  124. {brindle-0.2.1 → brindle-0.3.1}/src/brindle/watch_costs.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: brindle
3
- Version: 0.2.1
3
+ Version: 0.3.1
4
4
  Summary: Run coding agents in parallel, each on its own git branch, with a supervisor that delegates, reviews, and merges
5
5
  Project-URL: Homepage, https://pawdelta.com/brindle/
6
6
  Project-URL: Documentation, https://pawdelta.com/brindle/docs/recommended-use
@@ -89,7 +89,7 @@ uv tool install --editable ~/Projects/brindle # or from a local checkout
89
89
  brindle drives Claude Code, so you need that too (`npm install -g @anthropic-ai/claude-code`).
90
90
 
91
91
  `brindle --version` prints the installed version; the tmux status bar of every brindle
92
- session shows it too (`brindle 0.2.1`). A session started before an upgrade keeps
92
+ session shows it too (`brindle 0.3.1`). A session started before an upgrade keeps
93
93
  running the old code, and shows the old number, until you restart it.
94
94
 
95
95
  ## Quick start
@@ -350,6 +350,7 @@ your own status line prints, so what you see doesn't change.
350
350
  | `brindle transfer [REPO] [--from SESSION] [-b BRANCH]` | move a scratch session's work into a real repo |
351
351
  | `brindle ls [--all]` | workspaces and agents |
352
352
  | `brindle repo add PATH [--name ALIAS] / rm ALIAS / ls` | attach other local repos to the current session so workers can go there (brindle Pro; see "Several repos in one session") |
353
+ | `brindle keys set/unset/list [NAME]` | store model API keys (e.g. `ANTHROPIC_API_KEY`, `OPENAI_API_KEY`) once in the OS keychain (or a 0600 file); every agent pane gets the ones its provider reads, unless you already export it. `set` reads the value from a hidden prompt or stdin, `list` shows names and the last 4 characters. `CLAUDE_CODE_OAUTH_TOKEN` (a Claude subscription token) is never stored |
353
354
  | `brindle history [--limit N] [--kind K] [--all]` | durable log of worker results, reviews, merges and milestone checks |
354
355
  | `brindle cost [--days N] [--all]` | dollar spend at list prices over the last 30 days, by model |
355
356
  | `brindle cost report [--days N] [--all]` | Pro: spend by day, profile and goal, cost per merged branch, review pass rate per worker profile |
@@ -361,7 +362,8 @@ your own status line prints, so what you see doesn't change.
361
362
  | `brindle cost estimate [--tasks N] [--weight W] [--profile P] [--reviewer R]` | what the current goal (or N tasks) is likely to cost, as a range from this repo's history (median to p80 of past worker and review runs), plus a cheaper alternative with a different reviewer; says "low confidence" when there's too little history. Also added to `set_goal` and `assign` replies (brindle Pro) |
362
363
  | `brindle learning` | whether brindle Pro's hosted learning is on for this repo, and if not, why (nothing is learned on your machine) |
363
364
  | `brindle learning seed` | Pro: sends this repo's finished routing history to the hosted learner once, so it starts with what this machine has seen. Only the usual coarse record fields leave (kind/size one-hots, counters, HMAC keys), never task text or paths. A second run sends nothing new; decisions already sent live are skipped |
364
- | `brindle account [login\|logout\|status\|upgrade\|portal\|org]` | paid features: bare `brindle account` shows what your plan has and how to get the rest (see "brindle Pro and Team" below) |
365
+ | `brindle account [login\|logout\|status\|upgrade\|portal\|seats\|org]` | paid features: bare `brindle account` shows what your plan has and how to get the rest (see "brindle Pro and Team" below) |
366
+ | `brindle login` | the same as `brindle account login`; when your org's policy has an `agent_setup` block it also signs you in to the Claude and Codex route the company chose (AWS SSO profile, `gcloud`, `az`, `claude auth login`, `codex login`), stores the Claude Code environment for brindle's panes in `~/.brindle/config.json`, and checks the pinned models. `brindle doctor --fix` does the same |
365
367
  | `brindle audit verify\|export\|pubkey\|ship\|prune` | the local tamper-evident audit log, and shipping it to your SIEM (brindle Enterprise; see "Audit log" below) |
366
368
  | `brindle watch [--all] [--once]` | the dashboard on its own (the same view as the sidebar): enter attaches, `p` peeks, `x` closes |
367
369
  | `brindle sidebar` | bring this session's sidebar into the tmux session you're in (also `Ctrl-b S` in a window without one); restarts it if it was closed |
@@ -526,6 +528,7 @@ Autopilot, merge gates and cleanup:
526
528
  | `max_agents` | `4` | workers running at once per session (`0`: no cap) |
527
529
  | `check_timeout` | `900` | seconds each check may take |
528
530
  | `check_concurrency` | `2` | check runs at once on this machine, across branches; the rest wait their turn (`0`: no cap). A run far past its last duration is reported to the supervisor |
531
+ | `fable_escalation` | on, unless the worker runs on a cloud account (Bedrock, Vertex or Foundry) | retry a failed heavy task once on `developer-heavy` (Fable) before handing it to you; `true` turns it on for a cloud account, `false` off |
529
532
  | `usage_limit` | `90` | autopilot stops pushing on at this % of your Claude usage limit |
530
533
  | `limit_cooldown_minutes` | `300` for Antigravity | how long a provider that hit its limit counts as unavailable |
531
534
  | `graphify` | if the graph is there | point agents at the repo's [graphify](https://github.com/safishamsi/graphify) code map (`false` turns it off) |
@@ -589,9 +592,9 @@ keep theirs):
589
592
  ```json
590
593
  {
591
594
  "routing": {
592
- "light": ["developer", "developer-codex", "developer-local"],
595
+ "light": ["developer-light", "developer", "developer-codex", "developer-local"],
593
596
  "medium": ["developer", "developer-codex", "developer-heavy"],
594
- "heavy": ["developer-heavy", "developer", "developer-codex"]
597
+ "heavy": ["developer", "developer-heavy", "developer-codex"]
595
598
  }
596
599
  }
597
600
  ```
@@ -599,7 +602,9 @@ keep theirs):
599
602
  No tier prefers another provider for its own sake: all-Claude or all-Codex may
600
603
  be what works best for you, and that's for the learner to find out.
601
604
 
602
- `developer-codex` runs on Codex; `developer-heavy` on Claude Fable at high effort.
605
+ `developer-light` runs on Claude Haiku at low effort; `developer` on your Claude
606
+ Code default model; `developer-codex` on Codex; `developer-heavy` on Claude Fable
607
+ at high effort.
603
608
  A profile is skipped when its CLI isn't installed (`claude`, `codex`, `agy`), the
604
609
  local model server isn't answering, or its provider is at your `usage_limit`. If
605
610
  hosted learning is on it chooses among the profiles left; otherwise the first
@@ -758,11 +763,14 @@ workflow.
758
763
 
759
764
  ```sh
760
765
  brindle account # paid features: what you have, how to use them, how to get the rest
766
+ brindle login # the same as `brindle account login`; also applies your org's agent_setup (company agent sign-in)
761
767
  brindle account login # opens your browser to sign in (--device: enter a code instead, e.g. over SSH); brindle checks the plan offline from then on
762
768
  brindle account status # your plan, features, hosted learning on or off, when the entitlement expires
763
769
  brindle account savings # what hosted learning's picks gained in this repo, this month and last: estimates, from this machine's records only
764
770
  brindle account upgrade # opens the checkout for brindle Pro (and prints its URL)
765
- brindle account portal # opens the billing portal (invoices, seats, cancellation); --org ORG for a team org
771
+ brindle account upgrade --enterprise [--trial] --seats N --org ORG # brindle Enterprise for a team org; --trial: free trial, at most 10 seats
772
+ brindle account portal # opens the billing portal (invoices, payment method, cancellation); --org ORG for a team org
773
+ brindle account seats N # set a Team or Enterprise org's seat count (billing admin); --org ORG; Stripe prorates the change
766
774
  brindle account org list # the orgs you belong to; `org use <id>` switches, `org policy` shows the current one
767
775
  brindle account org policy # the org's policy, its per-role overrides, and the policy that applies to you
768
776
  brindle account org profiles # the org's shared profiles and rule packs, and which are pinned
@@ -772,6 +780,51 @@ brindle account org member policy-role <member> <role|none> # give a member a
772
780
  brindle account org company [link <org_id> | unlink] # link orgs you own into one company; learning is pooled only within it
773
781
  ```
774
782
 
783
+ **Sign-in loss pauses agents.** While agents run, brindle checks every 30 s that
784
+ Claude and Codex are still signed in (`claude auth status` or the cloud route's
785
+ identity, re-checked only when its credentials change; `codex login status`;
786
+ Antigravity can't be checked). If one is signed out, its running agents pause
787
+ with their worktrees, commits and conversations kept, and the supervisor and
788
+ your session are told; a timeout or missing CLI never pauses, it warns once.
789
+ A wrong company identity pauses them only when the org policy enforces it
790
+ (Enterprise); otherwise it warns once. While it enforces, Claude agents run
791
+ on exactly the route brindle checked: a profile's env lines can't change the
792
+ backend, account, key or proxy, and other cloud and Claude credential variables
793
+ (`ANTHROPIC_*`, `AWS_*`, `GOOGLE_*`, `CLOUDSDK_*`, `AZURE_*`, ...) in your
794
+ environment or `brindle keys` are left out of their panes, so those agents
795
+ can't use your own AWS, Google Cloud or Azure access in their shell either.
796
+ Claude Code's own settings files can still set variables inside it; to rule
797
+ that out too, use Claude Code's managed settings. After `brindle login`,
798
+ `brindle doctor --fix` or the CLI's own login, the agents brindle paused resume
799
+ into their conversations, but only as the account they started under: if
800
+ someone else is signed in (a personal login, say) they stay paused until the
801
+ original account is back. Your own chat session is never paused, only the
802
+ workers. A cloud sign-in is re-checked only when its credential files or
803
+ variables change, so a token that expires silently isn't noticed until then.
804
+ `brindle doctor` lists agents paused for sign-in.
805
+
806
+ **Sessions stay with their identity.** Each Claude agent records the identity it
807
+ launched under (Claude org, AWS account and role, GCP project, Azure
808
+ subscription; ids only, never tokens). While a different identity is signed in,
809
+ that agent is locked: brindle refuses to resume it (`brindle continue`), rewind
810
+ it, message or hand off to it, start a new agent in its worktree (including
811
+ naming its branch for a new worker), or `peek` at it, with "This session
812
+ belongs to <org/account>; sign in as it to continue (`brindle login`)".
813
+ `brindle ls`, `watch`, the sidebar, `list_agents` and `agent_turns` show it as
814
+ `locked: <org/account>` without its conversation (usage, last activity, turn
815
+ summaries), and `depends_on` and `merge_workspace` won't pull its branch into a
816
+ session under another identity. Agents with no recorded identity (started before
817
+ this, or without a company setup) are unaffected, and so is everything while the
818
+ current identity can't be told (signed out, CLI missing).
819
+
820
+ This is a guard inside brindle, not a sandbox: on one OS user account the
821
+ worktrees, transcripts and credential files stay readable outside brindle (a
822
+ shell, another tool). Real separation needs a separate OS user or your
823
+ company's device management. Codex and Antigravity can't be told apart by
824
+ account (brindle only sees "signed in"), so their sessions are paused on
825
+ sign-out but can't be locked to one account; isolation applies to Claude routes
826
+ (subscription, Bedrock, Vertex, Foundry).
827
+
775
828
  ### Several repos in one session (brindle Pro)
776
829
 
777
830
  A session can work across several repos. Attach another local repo you own
@@ -825,6 +878,16 @@ entitlement.
825
878
  * `deny_personal_keys`: the personal model keys (`ANTHROPIC_API_KEY`,
826
879
  `OPENAI_API_KEY`, ...) are taken out of every agent pane, and a profile that
827
880
  sets one is refused.
881
+ * An org-owned key: with `provider` `anthropic` (or `openai-compatible`), set
882
+ `key_env` to the name of a variable that holds the org's key (not a personal
883
+ one like `ANTHROPIC_API_KEY`), or `key_helper` to a command, as a list of
884
+ arguments, that prints the key (for example `["vault", "kv", "get",
885
+ "-field=key", "secret/anthropic"]`). brindle runs the helper on the person's
886
+ machine, without a shell and with a timeout, each time a worker starts, and
887
+ gives the key to that worker as `ANTHROPIC_API_KEY` (`OPENAI_API_KEY` for
888
+ Codex). It passes `deny_personal_keys`; a personal key doesn't. The key never
889
+ goes through brindle's servers. When the variable is missing or the helper
890
+ fails, the worker doesn't start.
828
891
 
829
892
  Two things to know when you turn on `deny_personal_keys`:
830
893
 
@@ -985,17 +1048,31 @@ workflows call these commands:
985
1048
  commits the workflows on a `brindle/ci-setup` branch, then puts you back on
986
1049
  the branch you started on and deletes the local setup branch, so `git pull`
987
1050
  after merging the setup pull request is clean (commit or stash your changes
988
- first: it refuses to start with uncommitted work).
1051
+ first: it refuses to start with uncommitted work). With your own cloud
1052
+ (`--credential bedrock|vertex|foundry`, keyless GitHub OIDC) it can read the
1053
+ IDs from the deployment template's outputs instead of asking:
1054
+ `--from-stack NAME [--region R]` (AWS CloudFormation), `--from-terraform DIR`
1055
+ (Google) or `--from-deployment NAME -g RG` (Azure). They are defaults for
1056
+ `--cloud-var`, which still overrides them, and every ID is format-checked. A
1057
+ missing `aws`, `terraform` or `az` CLI or output is an error that names the
1058
+ `--cloud-var` to pass instead. Vertex AI and Microsoft Foundry are in
1059
+ **preview** (not yet verified end to end): `init` refuses them unless you pass
1060
+ `--preview` or set `BRINDLE_CI_PREVIEW_CLOUDS=1`, and `doctor` marks them
1061
+ `(preview)`. Bedrock is generally available.
989
1062
  - `brindle ci doctor`: which provider CLIs and credential names a runner has, and
990
- which providers CI may use on this repository.
1063
+ which providers CI may use on this repository. `--models` also makes one tiny
1064
+ call per pinned model and says why any is refused (a quota, a form not filled in).
991
1065
  - `brindle ci start`: start a run for an issue, a goal text or a dispatched run,
992
1066
  or a validation of a pull request.
993
1067
  - `brindle ci run`: run what was started: the supervisor and the result upload,
994
1068
  or the pull request's checks and reviews and the evidence upload.
995
1069
  - `brindle ci report`: tell the service how the workflow's jobs ended.
996
1070
 
997
- Credential names are reported, never values. On a repository owned by a GitHub
998
- organization, a provider signed in only with a personal subscription is not used.
1071
+ Credential names are reported, never values. CI uses API keys, cloud sign-ins
1072
+ (Bedrock, Vertex, Foundry) or identity federation only: a provider signed in
1073
+ only with a subscription (`CLAUDE_CODE_OAUTH_TOKEN`, a Codex ChatGPT login) is
1074
+ not used, on personal and organization repositories alike. Add an API key
1075
+ secret instead.
999
1076
 
1000
1077
  Fix builds only fix the default branch's *required* status checks, and a new
1001
1078
  repository has none. When the default branch requires none, `brindle ci init`
@@ -1228,7 +1305,7 @@ it's signed in without a plan that includes it, is reported to its supervisor.
1228
1305
  | Provider | Key login (environment variables) |
1229
1306
  |---|---|
1230
1307
  | `claude` | yes: `ANTHROPIC_API_KEY`, `ANTHROPIC_AUTH_TOKEN`, `CLAUDE_CODE_OAUTH_TOKEN`, or Bedrock/Vertex/Foundry (`CLAUDE_CODE_USE_BEDROCK`, `CLAUDE_CODE_USE_VERTEX`, `CLAUDE_CODE_USE_FOUNDRY`) |
1231
- | `codex` | yes: `OPENAI_API_KEY`, `CODEX_API_KEY` |
1308
+ | `codex` | yes: `OPENAI_API_KEY`, `CODEX_API_KEY`. With Codex signed in with ChatGPT (checked on Codex CLI 0.162.0): interactive `codex`, which brindle runs in agent panes, ignores both keys and uses the ChatGPT plan, and only `codex login --with-api-key` switches it to a key; headless `codex exec` (Brindle-CI) bills `CODEX_API_KEY` over the login and ignores `OPENAI_API_KEY`. `brindle doctor` and `brindle keys set` say so, and `auth: api_key` on an interactive Codex profile is refused under a ChatGPT login (run `codex login --with-api-key`, or use `auth: subscription`) |
1232
1309
  | `antigravity` | `GEMINI_API_KEY`, only with `"modelProvider": "gemini"` in `agy`'s `settings.json` (see [Google Antigravity](#google-antigravity)); otherwise `agy`'s own browser sign-in |
1233
1310
 
1234
1311
  Workers that run unattended should use key login where the CLI supports it.
@@ -1240,6 +1317,16 @@ needs no browser step. Put the key in your environment, or in a profile's
1240
1317
  `brindle doctor` names the variable each CLI gets, from your shell or from
1241
1318
  which profiles.
1242
1319
 
1320
+ A profile chooses between the two with `auth`:
1321
+
1322
+ | `auth:` | What the worker signs in with |
1323
+ |---|---|
1324
+ | `auto` (default) | A key from your environment or `brindle keys` if there is one, else the CLI's own login. |
1325
+ | `subscription` | Always the CLI's own login: brindle strips that provider's API keys from the pane. |
1326
+ | `api_key` | Only a key: the worker refuses to start without one. |
1327
+
1328
+ Your org's `deny_personal_keys` (Enterprise) still applies on top of `auth`.
1329
+
1243
1330
  ### Cheap workers
1244
1331
 
1245
1332
  By default a Claude Code worker loads everything your own `claude` does: your
@@ -1626,6 +1713,30 @@ marks the agent idle and delivers any queued message. Codex has no Stop hook, so
1626
1713
  an autopilot supervisor on Codex that turn end is also where brindle tells it to keep
1627
1714
  going, with the same limit on reminders as Claude Code.
1628
1715
 
1716
+ ### Using your company's access
1717
+
1718
+ Two ways to run brindle's agents on your company's Claude (Bedrock, Vertex,
1719
+ Foundry, a Team or Enterprise plan) and Codex, without handling keys:
1720
+
1721
+ - **Your org sets it up (brindle Team).** When your org's policy has an
1722
+ `agent_setup` block, `brindle login` (and `brindle doctor --fix`) signs you
1723
+ in to the route the company chose and `brindle doctor` shows which identity
1724
+ each agent uses. It always wins over anything below.
1725
+ - **You set it up yourself (any plan).** When your org has no `agent_setup`,
1726
+ `brindle login` looks, read-only, at what this machine is already signed in
1727
+ to: Claude Code's managed settings (if your IT configures Claude Code,
1728
+ brindle just uses it), `claude auth status`, AWS SSO profiles in
1729
+ `~/.aws/config`, the active `gcloud` project, the active `az` subscription
1730
+ and `codex login status`. It never reads tokens or credential files. It
1731
+ proposes what it found ("Use Bedrock (AWS 1234…, role Dev, us-east-1)?");
1732
+ the default is no, and with no terminal it is always no. A yes is saved as
1733
+ `"agent_setup"` in `~/.brindle/config.json`, in the same format as the org
1734
+ policy's (`enforce` is never applied to it), and `brindle doctor` labels it
1735
+ as self-serve and says who is billed.
1736
+
1737
+ You must be authorized to use any company credentials you connect: brindle only
1738
+ signs in with the access you already have, it doesn't grant any.
1739
+
1629
1740
  ## Google Antigravity
1630
1741
 
1631
1742
  brindle runs Google Antigravity's terminal agent, `agy`, as well as Claude Code and
@@ -59,7 +59,7 @@ uv tool install --editable ~/Projects/brindle # or from a local checkout
59
59
  brindle drives Claude Code, so you need that too (`npm install -g @anthropic-ai/claude-code`).
60
60
 
61
61
  `brindle --version` prints the installed version; the tmux status bar of every brindle
62
- session shows it too (`brindle 0.2.1`). A session started before an upgrade keeps
62
+ session shows it too (`brindle 0.3.1`). A session started before an upgrade keeps
63
63
  running the old code, and shows the old number, until you restart it.
64
64
 
65
65
  ## Quick start
@@ -320,6 +320,7 @@ your own status line prints, so what you see doesn't change.
320
320
  | `brindle transfer [REPO] [--from SESSION] [-b BRANCH]` | move a scratch session's work into a real repo |
321
321
  | `brindle ls [--all]` | workspaces and agents |
322
322
  | `brindle repo add PATH [--name ALIAS] / rm ALIAS / ls` | attach other local repos to the current session so workers can go there (brindle Pro; see "Several repos in one session") |
323
+ | `brindle keys set/unset/list [NAME]` | store model API keys (e.g. `ANTHROPIC_API_KEY`, `OPENAI_API_KEY`) once in the OS keychain (or a 0600 file); every agent pane gets the ones its provider reads, unless you already export it. `set` reads the value from a hidden prompt or stdin, `list` shows names and the last 4 characters. `CLAUDE_CODE_OAUTH_TOKEN` (a Claude subscription token) is never stored |
323
324
  | `brindle history [--limit N] [--kind K] [--all]` | durable log of worker results, reviews, merges and milestone checks |
324
325
  | `brindle cost [--days N] [--all]` | dollar spend at list prices over the last 30 days, by model |
325
326
  | `brindle cost report [--days N] [--all]` | Pro: spend by day, profile and goal, cost per merged branch, review pass rate per worker profile |
@@ -331,7 +332,8 @@ your own status line prints, so what you see doesn't change.
331
332
  | `brindle cost estimate [--tasks N] [--weight W] [--profile P] [--reviewer R]` | what the current goal (or N tasks) is likely to cost, as a range from this repo's history (median to p80 of past worker and review runs), plus a cheaper alternative with a different reviewer; says "low confidence" when there's too little history. Also added to `set_goal` and `assign` replies (brindle Pro) |
332
333
  | `brindle learning` | whether brindle Pro's hosted learning is on for this repo, and if not, why (nothing is learned on your machine) |
333
334
  | `brindle learning seed` | Pro: sends this repo's finished routing history to the hosted learner once, so it starts with what this machine has seen. Only the usual coarse record fields leave (kind/size one-hots, counters, HMAC keys), never task text or paths. A second run sends nothing new; decisions already sent live are skipped |
334
- | `brindle account [login\|logout\|status\|upgrade\|portal\|org]` | paid features: bare `brindle account` shows what your plan has and how to get the rest (see "brindle Pro and Team" below) |
335
+ | `brindle account [login\|logout\|status\|upgrade\|portal\|seats\|org]` | paid features: bare `brindle account` shows what your plan has and how to get the rest (see "brindle Pro and Team" below) |
336
+ | `brindle login` | the same as `brindle account login`; when your org's policy has an `agent_setup` block it also signs you in to the Claude and Codex route the company chose (AWS SSO profile, `gcloud`, `az`, `claude auth login`, `codex login`), stores the Claude Code environment for brindle's panes in `~/.brindle/config.json`, and checks the pinned models. `brindle doctor --fix` does the same |
335
337
  | `brindle audit verify\|export\|pubkey\|ship\|prune` | the local tamper-evident audit log, and shipping it to your SIEM (brindle Enterprise; see "Audit log" below) |
336
338
  | `brindle watch [--all] [--once]` | the dashboard on its own (the same view as the sidebar): enter attaches, `p` peeks, `x` closes |
337
339
  | `brindle sidebar` | bring this session's sidebar into the tmux session you're in (also `Ctrl-b S` in a window without one); restarts it if it was closed |
@@ -496,6 +498,7 @@ Autopilot, merge gates and cleanup:
496
498
  | `max_agents` | `4` | workers running at once per session (`0`: no cap) |
497
499
  | `check_timeout` | `900` | seconds each check may take |
498
500
  | `check_concurrency` | `2` | check runs at once on this machine, across branches; the rest wait their turn (`0`: no cap). A run far past its last duration is reported to the supervisor |
501
+ | `fable_escalation` | on, unless the worker runs on a cloud account (Bedrock, Vertex or Foundry) | retry a failed heavy task once on `developer-heavy` (Fable) before handing it to you; `true` turns it on for a cloud account, `false` off |
499
502
  | `usage_limit` | `90` | autopilot stops pushing on at this % of your Claude usage limit |
500
503
  | `limit_cooldown_minutes` | `300` for Antigravity | how long a provider that hit its limit counts as unavailable |
501
504
  | `graphify` | if the graph is there | point agents at the repo's [graphify](https://github.com/safishamsi/graphify) code map (`false` turns it off) |
@@ -559,9 +562,9 @@ keep theirs):
559
562
  ```json
560
563
  {
561
564
  "routing": {
562
- "light": ["developer", "developer-codex", "developer-local"],
565
+ "light": ["developer-light", "developer", "developer-codex", "developer-local"],
563
566
  "medium": ["developer", "developer-codex", "developer-heavy"],
564
- "heavy": ["developer-heavy", "developer", "developer-codex"]
567
+ "heavy": ["developer", "developer-heavy", "developer-codex"]
565
568
  }
566
569
  }
567
570
  ```
@@ -569,7 +572,9 @@ keep theirs):
569
572
  No tier prefers another provider for its own sake: all-Claude or all-Codex may
570
573
  be what works best for you, and that's for the learner to find out.
571
574
 
572
- `developer-codex` runs on Codex; `developer-heavy` on Claude Fable at high effort.
575
+ `developer-light` runs on Claude Haiku at low effort; `developer` on your Claude
576
+ Code default model; `developer-codex` on Codex; `developer-heavy` on Claude Fable
577
+ at high effort.
573
578
  A profile is skipped when its CLI isn't installed (`claude`, `codex`, `agy`), the
574
579
  local model server isn't answering, or its provider is at your `usage_limit`. If
575
580
  hosted learning is on it chooses among the profiles left; otherwise the first
@@ -728,11 +733,14 @@ workflow.
728
733
 
729
734
  ```sh
730
735
  brindle account # paid features: what you have, how to use them, how to get the rest
736
+ brindle login # the same as `brindle account login`; also applies your org's agent_setup (company agent sign-in)
731
737
  brindle account login # opens your browser to sign in (--device: enter a code instead, e.g. over SSH); brindle checks the plan offline from then on
732
738
  brindle account status # your plan, features, hosted learning on or off, when the entitlement expires
733
739
  brindle account savings # what hosted learning's picks gained in this repo, this month and last: estimates, from this machine's records only
734
740
  brindle account upgrade # opens the checkout for brindle Pro (and prints its URL)
735
- brindle account portal # opens the billing portal (invoices, seats, cancellation); --org ORG for a team org
741
+ brindle account upgrade --enterprise [--trial] --seats N --org ORG # brindle Enterprise for a team org; --trial: free trial, at most 10 seats
742
+ brindle account portal # opens the billing portal (invoices, payment method, cancellation); --org ORG for a team org
743
+ brindle account seats N # set a Team or Enterprise org's seat count (billing admin); --org ORG; Stripe prorates the change
736
744
  brindle account org list # the orgs you belong to; `org use <id>` switches, `org policy` shows the current one
737
745
  brindle account org policy # the org's policy, its per-role overrides, and the policy that applies to you
738
746
  brindle account org profiles # the org's shared profiles and rule packs, and which are pinned
@@ -742,6 +750,51 @@ brindle account org member policy-role <member> <role|none> # give a member a
742
750
  brindle account org company [link <org_id> | unlink] # link orgs you own into one company; learning is pooled only within it
743
751
  ```
744
752
 
753
+ **Sign-in loss pauses agents.** While agents run, brindle checks every 30 s that
754
+ Claude and Codex are still signed in (`claude auth status` or the cloud route's
755
+ identity, re-checked only when its credentials change; `codex login status`;
756
+ Antigravity can't be checked). If one is signed out, its running agents pause
757
+ with their worktrees, commits and conversations kept, and the supervisor and
758
+ your session are told; a timeout or missing CLI never pauses, it warns once.
759
+ A wrong company identity pauses them only when the org policy enforces it
760
+ (Enterprise); otherwise it warns once. While it enforces, Claude agents run
761
+ on exactly the route brindle checked: a profile's env lines can't change the
762
+ backend, account, key or proxy, and other cloud and Claude credential variables
763
+ (`ANTHROPIC_*`, `AWS_*`, `GOOGLE_*`, `CLOUDSDK_*`, `AZURE_*`, ...) in your
764
+ environment or `brindle keys` are left out of their panes, so those agents
765
+ can't use your own AWS, Google Cloud or Azure access in their shell either.
766
+ Claude Code's own settings files can still set variables inside it; to rule
767
+ that out too, use Claude Code's managed settings. After `brindle login`,
768
+ `brindle doctor --fix` or the CLI's own login, the agents brindle paused resume
769
+ into their conversations, but only as the account they started under: if
770
+ someone else is signed in (a personal login, say) they stay paused until the
771
+ original account is back. Your own chat session is never paused, only the
772
+ workers. A cloud sign-in is re-checked only when its credential files or
773
+ variables change, so a token that expires silently isn't noticed until then.
774
+ `brindle doctor` lists agents paused for sign-in.
775
+
776
+ **Sessions stay with their identity.** Each Claude agent records the identity it
777
+ launched under (Claude org, AWS account and role, GCP project, Azure
778
+ subscription; ids only, never tokens). While a different identity is signed in,
779
+ that agent is locked: brindle refuses to resume it (`brindle continue`), rewind
780
+ it, message or hand off to it, start a new agent in its worktree (including
781
+ naming its branch for a new worker), or `peek` at it, with "This session
782
+ belongs to <org/account>; sign in as it to continue (`brindle login`)".
783
+ `brindle ls`, `watch`, the sidebar, `list_agents` and `agent_turns` show it as
784
+ `locked: <org/account>` without its conversation (usage, last activity, turn
785
+ summaries), and `depends_on` and `merge_workspace` won't pull its branch into a
786
+ session under another identity. Agents with no recorded identity (started before
787
+ this, or without a company setup) are unaffected, and so is everything while the
788
+ current identity can't be told (signed out, CLI missing).
789
+
790
+ This is a guard inside brindle, not a sandbox: on one OS user account the
791
+ worktrees, transcripts and credential files stay readable outside brindle (a
792
+ shell, another tool). Real separation needs a separate OS user or your
793
+ company's device management. Codex and Antigravity can't be told apart by
794
+ account (brindle only sees "signed in"), so their sessions are paused on
795
+ sign-out but can't be locked to one account; isolation applies to Claude routes
796
+ (subscription, Bedrock, Vertex, Foundry).
797
+
745
798
  ### Several repos in one session (brindle Pro)
746
799
 
747
800
  A session can work across several repos. Attach another local repo you own
@@ -795,6 +848,16 @@ entitlement.
795
848
  * `deny_personal_keys`: the personal model keys (`ANTHROPIC_API_KEY`,
796
849
  `OPENAI_API_KEY`, ...) are taken out of every agent pane, and a profile that
797
850
  sets one is refused.
851
+ * An org-owned key: with `provider` `anthropic` (or `openai-compatible`), set
852
+ `key_env` to the name of a variable that holds the org's key (not a personal
853
+ one like `ANTHROPIC_API_KEY`), or `key_helper` to a command, as a list of
854
+ arguments, that prints the key (for example `["vault", "kv", "get",
855
+ "-field=key", "secret/anthropic"]`). brindle runs the helper on the person's
856
+ machine, without a shell and with a timeout, each time a worker starts, and
857
+ gives the key to that worker as `ANTHROPIC_API_KEY` (`OPENAI_API_KEY` for
858
+ Codex). It passes `deny_personal_keys`; a personal key doesn't. The key never
859
+ goes through brindle's servers. When the variable is missing or the helper
860
+ fails, the worker doesn't start.
798
861
 
799
862
  Two things to know when you turn on `deny_personal_keys`:
800
863
 
@@ -955,17 +1018,31 @@ workflows call these commands:
955
1018
  commits the workflows on a `brindle/ci-setup` branch, then puts you back on
956
1019
  the branch you started on and deletes the local setup branch, so `git pull`
957
1020
  after merging the setup pull request is clean (commit or stash your changes
958
- first: it refuses to start with uncommitted work).
1021
+ first: it refuses to start with uncommitted work). With your own cloud
1022
+ (`--credential bedrock|vertex|foundry`, keyless GitHub OIDC) it can read the
1023
+ IDs from the deployment template's outputs instead of asking:
1024
+ `--from-stack NAME [--region R]` (AWS CloudFormation), `--from-terraform DIR`
1025
+ (Google) or `--from-deployment NAME -g RG` (Azure). They are defaults for
1026
+ `--cloud-var`, which still overrides them, and every ID is format-checked. A
1027
+ missing `aws`, `terraform` or `az` CLI or output is an error that names the
1028
+ `--cloud-var` to pass instead. Vertex AI and Microsoft Foundry are in
1029
+ **preview** (not yet verified end to end): `init` refuses them unless you pass
1030
+ `--preview` or set `BRINDLE_CI_PREVIEW_CLOUDS=1`, and `doctor` marks them
1031
+ `(preview)`. Bedrock is generally available.
959
1032
  - `brindle ci doctor`: which provider CLIs and credential names a runner has, and
960
- which providers CI may use on this repository.
1033
+ which providers CI may use on this repository. `--models` also makes one tiny
1034
+ call per pinned model and says why any is refused (a quota, a form not filled in).
961
1035
  - `brindle ci start`: start a run for an issue, a goal text or a dispatched run,
962
1036
  or a validation of a pull request.
963
1037
  - `brindle ci run`: run what was started: the supervisor and the result upload,
964
1038
  or the pull request's checks and reviews and the evidence upload.
965
1039
  - `brindle ci report`: tell the service how the workflow's jobs ended.
966
1040
 
967
- Credential names are reported, never values. On a repository owned by a GitHub
968
- organization, a provider signed in only with a personal subscription is not used.
1041
+ Credential names are reported, never values. CI uses API keys, cloud sign-ins
1042
+ (Bedrock, Vertex, Foundry) or identity federation only: a provider signed in
1043
+ only with a subscription (`CLAUDE_CODE_OAUTH_TOKEN`, a Codex ChatGPT login) is
1044
+ not used, on personal and organization repositories alike. Add an API key
1045
+ secret instead.
969
1046
 
970
1047
  Fix builds only fix the default branch's *required* status checks, and a new
971
1048
  repository has none. When the default branch requires none, `brindle ci init`
@@ -1198,7 +1275,7 @@ it's signed in without a plan that includes it, is reported to its supervisor.
1198
1275
  | Provider | Key login (environment variables) |
1199
1276
  |---|---|
1200
1277
  | `claude` | yes: `ANTHROPIC_API_KEY`, `ANTHROPIC_AUTH_TOKEN`, `CLAUDE_CODE_OAUTH_TOKEN`, or Bedrock/Vertex/Foundry (`CLAUDE_CODE_USE_BEDROCK`, `CLAUDE_CODE_USE_VERTEX`, `CLAUDE_CODE_USE_FOUNDRY`) |
1201
- | `codex` | yes: `OPENAI_API_KEY`, `CODEX_API_KEY` |
1278
+ | `codex` | yes: `OPENAI_API_KEY`, `CODEX_API_KEY`. With Codex signed in with ChatGPT (checked on Codex CLI 0.162.0): interactive `codex`, which brindle runs in agent panes, ignores both keys and uses the ChatGPT plan, and only `codex login --with-api-key` switches it to a key; headless `codex exec` (Brindle-CI) bills `CODEX_API_KEY` over the login and ignores `OPENAI_API_KEY`. `brindle doctor` and `brindle keys set` say so, and `auth: api_key` on an interactive Codex profile is refused under a ChatGPT login (run `codex login --with-api-key`, or use `auth: subscription`) |
1202
1279
  | `antigravity` | `GEMINI_API_KEY`, only with `"modelProvider": "gemini"` in `agy`'s `settings.json` (see [Google Antigravity](#google-antigravity)); otherwise `agy`'s own browser sign-in |
1203
1280
 
1204
1281
  Workers that run unattended should use key login where the CLI supports it.
@@ -1210,6 +1287,16 @@ needs no browser step. Put the key in your environment, or in a profile's
1210
1287
  `brindle doctor` names the variable each CLI gets, from your shell or from
1211
1288
  which profiles.
1212
1289
 
1290
+ A profile chooses between the two with `auth`:
1291
+
1292
+ | `auth:` | What the worker signs in with |
1293
+ |---|---|
1294
+ | `auto` (default) | A key from your environment or `brindle keys` if there is one, else the CLI's own login. |
1295
+ | `subscription` | Always the CLI's own login: brindle strips that provider's API keys from the pane. |
1296
+ | `api_key` | Only a key: the worker refuses to start without one. |
1297
+
1298
+ Your org's `deny_personal_keys` (Enterprise) still applies on top of `auth`.
1299
+
1213
1300
  ### Cheap workers
1214
1301
 
1215
1302
  By default a Claude Code worker loads everything your own `claude` does: your
@@ -1596,6 +1683,30 @@ marks the agent idle and delivers any queued message. Codex has no Stop hook, so
1596
1683
  an autopilot supervisor on Codex that turn end is also where brindle tells it to keep
1597
1684
  going, with the same limit on reminders as Claude Code.
1598
1685
 
1686
+ ### Using your company's access
1687
+
1688
+ Two ways to run brindle's agents on your company's Claude (Bedrock, Vertex,
1689
+ Foundry, a Team or Enterprise plan) and Codex, without handling keys:
1690
+
1691
+ - **Your org sets it up (brindle Team).** When your org's policy has an
1692
+ `agent_setup` block, `brindle login` (and `brindle doctor --fix`) signs you
1693
+ in to the route the company chose and `brindle doctor` shows which identity
1694
+ each agent uses. It always wins over anything below.
1695
+ - **You set it up yourself (any plan).** When your org has no `agent_setup`,
1696
+ `brindle login` looks, read-only, at what this machine is already signed in
1697
+ to: Claude Code's managed settings (if your IT configures Claude Code,
1698
+ brindle just uses it), `claude auth status`, AWS SSO profiles in
1699
+ `~/.aws/config`, the active `gcloud` project, the active `az` subscription
1700
+ and `codex login status`. It never reads tokens or credential files. It
1701
+ proposes what it found ("Use Bedrock (AWS 1234…, role Dev, us-east-1)?");
1702
+ the default is no, and with no terminal it is always no. A yes is saved as
1703
+ `"agent_setup"` in `~/.brindle/config.json`, in the same format as the org
1704
+ policy's (`enforce` is never applied to it), and `brindle doctor` labels it
1705
+ as self-serve and says who is billed.
1706
+
1707
+ You must be authorized to use any company credentials you connect: brindle only
1708
+ signs in with the access you already have, it doesn't grant any.
1709
+
1599
1710
  ## Google Antigravity
1600
1711
 
1601
1712
  brindle runs Google Antigravity's terminal agent, `agy`, as well as Claude Code and
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "brindle"
3
- version = "0.2.1"
3
+ version = "0.3.1"
4
4
  description = "Run coding agents in parallel, each on its own git branch, with a supervisor that delegates, reviews, and merges"
5
5
  readme = "README.md"
6
6
  requires-python = ">=3.11"
@@ -52,6 +52,8 @@ audit_export = "brindle.pro.audit_export:make"
52
52
  dev = [
53
53
  "pytest>=8",
54
54
  "pytest-xdist>=3.8.0",
55
+ "python-hcl2>=8.1.4",
56
+ "pyyaml>=6.0.3",
55
57
  ]
56
58
 
57
59
  [build-system]