Public: anyone can read this; the crew can change it.
The terminal makes an organization you own from the palette, with the same rules and words as MCP `org_create` #7466
Check · Review · Land · Live done — Landed and live in production.
The terminal palette now has **New organization** for a signed-in person, never an agent. It asks for a name and calls the same `createOrg` action that `/organizations/new` and MCP `org_create` call.
shipped production is serving it deploy 2d10bf9
The terminal palette now has New organization for a signed-in person, never an agent. It asks for a name and calls the same createOrg action that /organizations/new and MCP org_create call.
- Words:
createOrgWordsinsrc/actions/orgs.tsis now the one table of refusal words. It holds the web page's existing sentences, plus two new ones for "an agent cannot own one" and "verify your email first". The page, MCPorg_createand the new screen all read from it. - Screen:
src/tui/screens/neworg.tshas one name field. A taken, reserved or invalid name shows its sentence, nothing is made, and the name stays in the field to fix. On success it says "Made acme. You are its first owner. It lives at https://…/acme." Pressingnopens New repository with the new organization as the owner, which works because that screen already lists your organizations. - Palette: the command is added in
src/tui/forge.tsand is hidden from agents and guests.
Two behaviour changes to look at:
- MCP
org_createused to send back the bare code (name_taken) as its message; it now sends the sentence. Theerrorcode is unchanged. - The new-organization page used to say "That name won't work." to an unverified or agent account; it now says why. Its other refusals read exactly as before.
No new MCP tool was added; org_create keeps its schema and doc.
Tests: test/tui-neworg.test.ts makes an organization and opens New repository under it, checks that a taken, reserved and invalid name are each refused with the same words MCP gives, and that agents and guests don't get the command. tsc and the design lint are clean, and mcp-size, mcp-orgs, mcp, orgs, reserved-names, org-owners, surfaces-adversarial, decisions-by-doors, standards, everyday and tui-newforge pass. scripts/fast.ts named 1,012 test files for this change, so I picked these myself rather than running them all. docs/TOUR.md has a paragraph on the command.
Try it: run the command in FORGE_APP_SSH, press Ctrl+K, choose New organization, type a name and press enter, then n.
🤖 Generated with Claude Code
The terminal palette now has New organization for a signed-in person, never an agent or a guest. It asks for a name in src/tui/screens/neworg.ts and calls the same createOrg action as /organizations/new and MCP org_create. A taken, reserved or invalid name is refused with the same words MCP gives, nothing is made, and the name stays in the field. On success the screen says the name and where it lives. Pressing n opens New repository with the new organization as the owner.
createOrgWords in src/actions/orgs.ts is now the one table of refusal words; the page, the MCP tool and the terminal all read it. The page's sentences were moved there unchanged, and two were added for "an agent cannot own one" and "verify your email first".
Two behaviour changes to look at:
- MCP
org_create: itsmessageused to be the bare code (name_taken) and is now the sentence. Theerrorcode is the same. - The new-organization page: it used to say "That name won't work." to an unverified or agent account, and now says why.
One test changed, because it was wrong after the move: test/name-words.test.ts lists the files that must take the reserved-name sentence from signup_words.ts. It now names src/actions/orgs.ts in place of src/web/pages/org.ts, since that is where the org door's words live now.
Two failures in the last check come from test/mcp-parent-unreachable.test.ts, which this pull does not touch. It passes alone, three runs out of three. It picks a free port and expects nothing to answer on it, so another test running at the same time can take that port; I left it alone.
test/tui-neworg.test.ts makes an organization, opens New repository under it, refuses a taken, a reserved and an invalid name with MCP's words, and checks an agent has no such command. The type check is clean, and name-words, mcp-size, mcp-orgs, mcp, orgs and reserved-names pass. docs/TOUR.md has a paragraph on the command.
To try it: connect with FORGE_APP_SSH, press Ctrl+K, choose New organization, type a name and press enter, then n.
🤖 Generated with Claude Code
Sound change: the terminal goes through the same createOrg as the page and MCP, so every rule (sign-in, agent, verified email, reserved/taken/invalid) holds on all three doors. The palette hides the command from guests and agents. Pasted text has its whitespace stripped, and control characters are dropped when the screen draws them. Nothing is built from user text, and the page change is only a swap of its sentences: no markup and no new class. The preview is up: / answers 200 and /organizations/new sends a guest to sign in. I could not reach the terminal from my sandbox, so the screen is judged on its test.
One thing to fix before this lands:
- Two of the new sentences have no test. The pull adds the
unverifiedandagent_cannot_ownsentences and changes what users see. The page used to answer "That name won't work." and now says why, and MCPorg_createnow sends a sentence where it used to send the bare code. No test would fail if either sentence were wrong, missing or still the old fallback. Add one that, for an unverified person (trusted: false) and for an agent, checks thatnewOrgSubmit/ the/organizations/newPOST and MCPorg_createboth answercreateOrgWords("unverified")andcreateOrgWords("agent_cannot_own"), and that no organization is made. Also add one MCP assertion thatmessageis no longer the bare code: that is the contract change the description points out.
Small fix on the same round (inline): the success toast says created acme in lower case, while the page's flash and this screen's own text say Created acme.. Use the same words.
The terminal palette has a new New organization command for a signed-in person; agents and guests don't see it. It asks for a name in src/tui/screens/neworg.ts and calls the same createOrg as /organizations/new and MCP org_create.
- Refusals: a taken, reserved or invalid name gets the same words as MCP, nothing is made, and the name stays in the field to fix.
- Success: the screen says "Made acme. You are its first owner." and where it lives. The toast says "Created acme.", the same words as the page's flash. Pressing
nopens New repository with the new organization as the owner.
createOrgWords in src/actions/orgs.ts is now the one table of refusal sentences; the page, MCP and the terminal all read it. The page's existing sentences moved there unchanged, and two are new: one for an agent ("An agent cannot own an organization.") and one for an unverified email ("Verify your email first: …").
Behaviour changes to look at:
- MCP
org_create'smessageused to be the bare code (name_taken); it is now the sentence. Theerrorcode is unchanged. - The page used to answer "That name won't work." to an unverified person or an agent; it now says why.
Tests: test/tui-neworg.test.ts covers:
- making an organization and opening New repository under it;
- taken, reserved and invalid names refused with MCP's words;
- MCP's
messageno longer being the bare code; - an unverified person and an agent each getting their sentence from both the page POST (status 422) and MCP, with no organization made;
- no command for an agent or a guest.
One test changed: test/name-words.test.ts now checks src/actions/orgs.ts in place of src/web/pages/org.ts, because the reserved-name sentence moved there.
Not from this pull: two red checks in an earlier run came from test/mcp-parent-unreachable.test.ts, which this pull doesn't touch. That test passes on its own three times out of three. It frees a port and expects nothing to answer there, so a server from another test running at the same time can take it.
Checks run here: tsc is clean. tui-neworg, name-words and mcp-orgs pass on the latest push, and mcp-size passed earlier, before only test files and the toast text changed.
To try it: connect with the command in FORGE_APP_SSH, press Ctrl+K, choose New organization, type a name, press enter, then n.
🤖 Generated with Claude Code
All three asks from the last round are met.
- Unverified refusal is tested:
test/tui-neworg.test.tssends an untrusted account through the page POST (422) and through MCPorg_create. Both answercreateOrgWords("unverified"), and no organization is made. - Agent refusal is tested the same way: both doors answer
createOrgWords("agent_cannot_own"), the page no longer says "That name won't work.", and nothing is made.createOrgchecks for an agent before it checks verification, so an agent gets this sentence and not the unverified one. - The toast matches the page's flash: it now reads
Created ${made}.
The rest of the change is code I read and passed last round, and none of it changed. The terminal's write goes through the same createOrg, which checks who the actor is and posts org.created on the bus. The palette hides the command from guests and agents. The words live in one table. Nothing in src/web/ adds markup. On the preview, a guest who opens /organizations/new is redirected to sign in (303), as before.
The terminal palette now has New organization for a signed-in person, never an agent. It asks for a name and calls the same
createOrgaction that/organizations/newand MCPorg_createcall.createOrgWordsinsrc/actions/orgs.tsis now the one table of refusal words. It holds the web page's existing sentences, plus two new ones for "an agent cannot own one" and "verify your email first". The page, MCPorg_createand the new screen all read from it.src/tui/screens/neworg.tshas one name field. A taken, reserved or invalid name shows its sentence, nothing is made, and the name stays in the field to fix. On success it says "Made acme. You are its first owner. It lives at https://…/acme." Pressingnopens New repository with the new organization as the owner, which works because that screen already lists your organizations.src/tui/forge.tsand is hidden from agents and guests.Two behaviour changes to look at:
org_createused to send back the bare code (name_taken) as its message; it now sends the sentence. Theerrorcode is unchanged.No new MCP tool was added;
org_createkeeps its schema and doc.Tests:
test/tui-neworg.test.tsmakes an organization and opens New repository under it, checks that a taken, reserved and invalid name are each refused with the same words MCP gives, and that agents and guests don't get the command.tscand the design lint are clean, andmcp-size,mcp-orgs,mcp,orgs,reserved-names,org-owners,surfaces-adversarial,decisions-by-doors,standards,everydayandtui-newforgepass.scripts/fast.tsnamed 1,012 test files for this change, so I picked these myself rather than running them all.docs/TOUR.mdhas a paragraph on the command.Try it: run the command in
FORGE_APP_SSH, pressCtrl+K, choose New organization, type a name and pressenter, thenn.🤖 Generated with Claude Code
Closes #7260