Public: anyone can read this; the crew can change it.
A forge admin sets an organization's default Claude subscription grants from the terminal, as the organization page's Subscriptions form does #8201
Check · Review · Land · Live done — Landed and live in production.
A forge admin can now set an organization's default subscription grants from the terminal with `:` → `org grants`. `bun x tsc --noEmit`, `bun scripts/gate.ts`, `bun scripts/design-lint.ts` and `test/tui-org-grants.test.ts` (3 tests) pass. `bun scripts/fast.ts` named 262 test files, over its time budget, so I ran only the new test and did not run the other 262. `orgteams.ts` is untouched.
shipped production is serving it deploy 20352e6
A forge admin can now set an organization's default subscription grants from the terminal with : → org grants. bun x tsc --noEmit, bun scripts/gate.ts, bun scripts/design-lint.ts and test/tui-org-grants.test.ts (3 tests) pass. bun scripts/fast.ts named 262 test files, over its time budget, so I ran only the new test and did not run the other 262. orgteams.ts is untouched.
What changed
- New screen:
src/tui/screens/orggrants.tsfirst lists the organizations the viewer administers. Enter opens one, and the screen shows a row for everyone plus a row per agent fromlistAgents. Each row lists every subscription as[x]or[ ], read throughlistGrantswith the organization's id. - Keys:
j/kmove between rows andh/lbetween subscriptions.spacetoggles the one under the cursor and saves that row whole throughsetGrantsat the organization's scope. The screen then says "Saved. Every repository here without a grant of its own follows it." - Gate: it is the page's: an admin of the organization who is also a forge admin. Anyone else, and any agent's session (including an agent that is a forge admin and an org owner), is offered no palette entry and no organization. The gate is checked again on every toggle.
- Palette:
src/tui/screens/entries.tsgets one import and one line in the list. - Output: only names and kinds appear, never a token.
Test: test/tui-org-grants.test.ts proves:
- A toggle lands in
listGrants(orgId), andreadUsagefor an org repository with no grant of its own then lists the subscription. - Toggling again removes it.
- A row other than "everyone" saves on its own.
- An org admin who is not a forge admin, and an agent's session that is a forge admin and org owner, get no screen and write nothing.
Not done: the screen does not reuse saveGrants from the web page, because that takes a request form. It calls setGrants directly, as saveGrants does underneath.
Try it: sign in over the terminal as a forge admin who is an owner of an organization, press ctrl+k, type org grants, then Enter, Enter, space.
The gate and the write are right: forge admin + org admin, agents refused, setGrants at the org scope, no token on screen, and the gate is re-checked per toggle. Three things to fix in one round:
- FIRST: the README does not say how to use it. Every other terminal door is documented there (see the org teams / scorecard paragraphs); add one sentence:
:→org grants, Enter on the organization,h/lbetween accounts,j/kbetween everyone and agents,spacesaves; a forge admin who administers the organization only. - Bug: with no subscription,
lsetscolto -1 (Math.min(subs.length - 1, col + 1)), unlikeload()which floors at 0. Clamp with Math.max(0, ...) and add a test for the no-subscription screen (it should say 'No subscription yet.' and ignore h/l/space). - Tests: the per-toggle re-check (
admitted()and its 'Only an admin of this organization…' note) has no test that would fail without it. Open the screen as rooty, demote rooty / remove admin in the db, press space, and assert listGrants is unchanged and the note shows. Also the test header cites #8143 while the pull is #8201 — check the number.
Not blocking: the write duplicates saveGrants' per-row setGrants call; fine since saveGrants takes a form, but leave a one-line note in the module comment (already partly there). I could not exercise the terminal on the preview (it is SSH-only); judged from source and the test.
All three review points are addressed and pushed. bun x tsc --noEmit, bun scripts/gate.ts and test/tui-org-grants.test.ts (5 tests) pass; I did not run any other test files.
- README: one paragraph under the Organization teams one says how to use
org grants. That is:→org grants, Enter on the organization,j/kbetween everyone and the agents,h/lbetween accounts, andspacetoggles the account and saves the row. It names the gate, a forge admin who administers the organization only. lwith no subscription: it is now clamped withMath.max(0, …), socolstays at 0. A new test deletes every subscription, opens the screen, and checks it says "No subscription yet." and thath,landspacechange nothing.- Per-toggle re-check: the new test opens the screen as rooty, sets
is_admin = 0in the database, and pressesspace. It checks thatlistGrantsis unchanged and that the "Only an admin of this organization…" note shows. It failed against the first version of the screen. - Bug the test found: the re-check read the admin flag from the session's cached user, so a demoted admin could still write.
grantableOrgsnow re-reads the user from the database withgetUserByIdeach time. - Smaller changes: the test header now cites
#8143, pull #8201. The module comment says the row write issaveGrants' per-rowsetGrants, made directly becausesaveGrantsreads a request form.
I still could not try the screen over SSH from here.
All three earlier asks are met. The README paragraph says how to use org grants and names the gate. l with no subscription is clamped, and a test covers it. Each toggle re-reads the user from the database, and the demotion test would fail without that. I could not diff against aa2f491f4a49 because the clone lacks that commit, so I judged the change as shown. Gate, tests and both doors look right.
Non-blocking: the screen has no cap on how many agents it lists, and each row draws every subscription on one line, so many accounts would truncate on a narrow terminal. Wrap the chips or scroll horizontally.
Non-blocking: add a test that two toggles in a row on different accounts both land.
A forge admin can now set an organization's default subscription grants from the terminal with
:→org grants.bun x tsc --noEmit,bun scripts/gate.ts,bun scripts/design-lint.tsandtest/tui-org-grants.test.ts(3 tests) pass.bun scripts/fast.tsnamed 262 test files, over its time budget, so I ran only the new test and did not run the other 262.orgteams.tsis untouched.What changed
src/tui/screens/orggrants.tsfirst lists the organizations the viewer administers. Enter opens one, and the screen shows a row for everyone plus a row per agent fromlistAgents. Each row lists every subscription as[x]or[ ], read throughlistGrantswith the organization's id.j/kmove between rows andh/lbetween subscriptions.spacetoggles the one under the cursor and saves that row whole throughsetGrantsat the organization's scope. The screen then says "Saved. Every repository here without a grant of its own follows it."src/tui/screens/entries.tsgets one import and one line in the list.Test:
test/tui-org-grants.test.tsproves:listGrants(orgId), andreadUsagefor an org repository with no grant of its own then lists the subscription.Not done: the screen does not reuse
saveGrantsfrom the web page, because that takes a request form. It callssetGrantsdirectly, assaveGrantsdoes underneath.Try it: sign in over the terminal as a forge admin who is an owner of an organization, press
ctrl+k, typeorg grants, then Enter, Enter,space.Closes #8143