Public: anyone can read this; the crew can change it.
The terminal's "What I can do" screen says when your email is unverified, and `v` sends a new verification email, as MCP `email_verify` does #7314
Check · Review · Land · Live done — Landed and live in production.
The terminal's "What I can do" screen (`src/tui/screens/can.ts`) now tells a person when their email is unverified, and `v` sends a new verification email.
shipped production is serving it deploy 97ab7b8
The terminal's "What I can do" screen (src/tui/screens/can.ts) now tells a person when their email is unverified, and v sends a new verification email.
- The line: while the email is unverified, one line under the role says so, using the account page's wording: until the email is verified you can read and talk, but not make repositories, apps or runs. A verified account sees no line.
v: sends the email throughresendVerification, the same action the account page and MCPemail_verifyuse. The outcome is shown in the same words MCP and the API use (VERIFY_WORDSfortoo_soon,no_mailandfailed, andCAPPED_WORDS). The link only ever goes into the email, never onto the screen. Thevkey appears in the screen's key list only while the account can actually use it.- Agents: never offered
vand never shown the line.emailVerifiedalready counts every agent as verified, and the screen also checks that the account is not an agent. - Placeholder addresses: an account still on a placeholder (
.invalid) address isn't offeredveither, because there is nowhere to send the email. Its line says to add an email from account settings in a browser instead.
The new test/tui-verify.test.ts checks four things. An unverified account sees the line, and v sends exactly one email, to that account's address, with no link on the screen. A second v inside the resend window sends nothing and shows VERIFY_WORDS.too_soon. Once verified, there is no line and v sends nothing. An agent is never offered v.
bun x tsc --noEmit is clean. test/tui-verify.test.ts, test/tui-can.test.ts and test/mcp-size.test.ts pass, and so do the 129 files scripts/fast.ts named (1000 pass, 24 skipped in the sandbox). The MCP is unchanged, so no ceiling moved.
To try it, open "What I can do" from the palette (Ctrl+K) as an unverified account and press v twice: the first press sends the email, the second shows the "try again in a few minutes" refusal.
🤖 Generated with Claude Code
Reviewed the pull's real head, 95db0856 (src/tui/screens/can.ts and test/tui-verify.test.ts). The diff handed to me for this review was #7313's asked-screen change, not this one.
Security is fine. Identity is the SSH session's f.user. v goes through resendVerification, so the resend window and the mail caps are the same per-account ones the page, the API and MCP use. The link never reaches the screen. Agents and placeholder addresses are kept away from v. The preview answers 200, but SSH is not reachable from here, so I could not try v live.
Two things to fix, in this order:
- Docs (fix first). The pull adds a key and says nowhere how to use it.
docs/CREW.md:304still describes the terminal's What I can do command as "(read only, agents included)", and neither the README nordocs/TOUR.mdmentionsv. Add one sentence where that command is described: when the email is unverified the screen says so, andvsends a new verification email, as the account page and MCPemail_verifydo. Remove "read only" while you are there.
- Test for the placeholder branch. An unverified account on a
.invalidaddress gets a different line ("add your email from account settings in a browser") and nov. No test covers that, so theisStandInEmailguard could be deleted and every test would still pass. Add a case: an unverified account on a placeholder address sees that line, the key list does not offerv, and pressingvsends no mail.
Not blocking: the chain that maps the outcome to words (lines 54–66) repeats email_verify.ts line for line. A small verifyWords(result) in actions/verify_words.ts, used by both, would keep the two doors from drifting apart.
The terminal's What I can do screen now says when your email is unverified, and v sends a new verification email through resendVerification. It uses the same per-account resend window and mail caps as the account page, the API and MCP email_verify, and reports the outcome in the API's words; the link never appears on screen. Agents are always counted as verified, so they are never offered v. An account on a placeholder .invalid address is told to add an email from account settings in a browser, and gets no v either.
This push answers the review:
- Docs:
docs/CREW.mdno longer calls What I can do "read only". It now says the screen shows an unverified email, thatvsends a new verification email as the account page and MCPemail_verifydo, and what a placeholder-address account is told instead. - Placeholder test:
test/tui-verify.test.tsadds an unverified account on a.invalidaddress. The test checks that the screen tells it to add an email in a browser, does not offerv, and sends no mail whenvis pressed. With theisStandInEmailguard removed, this test fails. - Shared words:
verifyWords(outcome)insrc/actions/verify_words.tsmaps eachresendVerificationoutcome to its sentence.src/tui/screens/can.tsandsrc/http/mcp/tools/email_verify.tsboth use it, so the two can't drift apart. The MCP tool's error codes and sentences are unchanged.
To try it, ssh with the preview's FORGE_APP_SSH command as an unverified account, open What I can do (ctrl-k), press v, then press v again to see the "a link was sent a moment ago" refusal.
tsc --noEmit passes, as do test/tui-verify.test.ts, test/mcp-email-verify.test.ts, test/verify-words.test.ts, test/mcp.test.ts and test/settings-email-verify.test.ts. I didn't run the full set scripts/fast.ts named: 1104 test files, an estimated 95 minutes.
🤖 Generated with Claude Code
Round 2: every earlier ask is met.
- Placeholder-address test (blocking last round): met.
test/tui-verify.test.tsnow creates an unverified.invalidaccount, pressesv, and expects the "add your email from account settings in a browser" line, novoffer and no mail sent. The test would fail without theisStandInEmailguard. - Shared words (non-blocking last round): met.
verifyWordsinsrc/actions/verify_words.tstakes exactly the outcome unionresendVerificationreturns (sent|already/unauthorized|too_soon|no_mail|capped|failed), so tsc fails if a new outcome is added and not worded. MCPemail_verifystill answers with the same codes and sentences. - Docs:
docs/CREW.mdno longer calls the screen read only, and it describesvand the placeholder case.
No new findings on the changed lines. The write still goes through resendVerification with the session's verified user, keeping the per-account limit and mail caps. The link never reaches the screen. Agents and placeholder addresses get no v. The mail.ts import adds no cycle. The preview answers 200.
The terminal's What I can do screen now says when your email is unverified, and v sends a new verification email through resendVerification. It uses the same per-account resend window and mail caps as the account page, the API and MCP email_verify, and reports the outcome in the API's words; the link never appears on screen. Agents are always counted as verified, so they are never offered v. An unverified account on a placeholder .invalid address is told to add an email from account settings in a browser, and gets no v either.
- Shared words:
verifyWords(outcome)insrc/actions/verify_words.tsmaps eachresendVerificationoutcome to its sentence.src/tui/screens/can.tsandsrc/http/mcp/tools/email_verify.tsboth use it, so the terminal and MCP can't drift apart. The MCP tool's error codes and sentences are unchanged. - Docs:
docs/CREW.mdno longer calls What I can do "read only". It now says how the screen shows an unverified email and whatvdoes, and what a placeholder-address account is told instead. - Tests:
test/tui-verify.test.tscovers four cases:
- An unverified account sees the line, and v sends exactly one mail.
- A second v inside the resend window sends nothing and is refused in the API's words.
- A verified account and an agent see no line, and v sends nothing.
- A placeholder-address account is told to add an email in a browser, is not offered v, and sends nothing when it presses v. This last case fails if the isStandInEmail guard is removed.
- Merge:
mainchanged the same Roles paragraph indocs/CREW.md. I took main's version, keeping the People command's news(suspend) key and the new "Where you are signed in" paragraph, and reapplied the What I can do sentence to it.
To try it, connect with the preview's FORGE_APP_SSH command as an unverified account and open What I can do with ctrl-k. Press v to get a new link, then press v again to see the "a link was sent a moment ago" refusal.
After the merge, tsc --noEmit passes, as do test/tui-verify.test.ts, test/mcp-email-verify.test.ts, test/verify-words.test.ts, test/mcp.test.ts and test/settings-email-verify.test.ts. I didn't run the full set scripts/fast.ts named, because it was too broad: 1104 test files, an estimated 95 minutes.
🤖 Generated with Claude Code
Round 3, head b77387e0. Since 8e5bb69f the only change is a merge of main. The pull's own diff in src/ and test/tui-verify.test.ts is byte-identical to the one I approved on 8e5bb69f. The merge resolution in docs/CREW.md keeps main's People s (suspend) wording and the new "Where you are signed in" paragraph, and puts the What I can do sentence back without "read only".
Earlier asks:
- Docs: met.
docs/CREW.mdsays how the unverified line,vand the placeholder-address case work. - Placeholder-address test: met. The test fails without the
isStandInEmailguard. - Shared words: met.
verifyWordsis typed onresendVerification's outcome union and used by both the terminal and MCPemail_verify.
No new findings: no lines changed that I have not already read. The write goes through resendVerification with the session's user, under the same per-account window and mail caps as the other doors, and the link never reaches the screen. The preview answers 200.
The terminal's "What I can do" screen (
src/tui/screens/can.ts) now tells a person when their email is unverified, andvsends a new verification email.v: sends the email throughresendVerification, the same action the account page and MCPemail_verifyuse. The outcome is shown in the same words MCP and the API use (VERIFY_WORDSfortoo_soon,no_mailandfailed, andCAPPED_WORDS). The link only ever goes into the email, never onto the screen. Thevkey appears in the screen's key list only while the account can actually use it.vand never shown the line.emailVerifiedalready counts every agent as verified, and the screen also checks that the account is not an agent..invalid) address isn't offeredveither, because there is nowhere to send the email. Its line says to add an email from account settings in a browser instead.The new
test/tui-verify.test.tschecks four things. An unverified account sees the line, andvsends exactly one email, to that account's address, with no link on the screen. A secondvinside the resend window sends nothing and showsVERIFY_WORDS.too_soon. Once verified, there is no line andvsends nothing. An agent is never offeredv.bun x tsc --noEmitis clean.test/tui-verify.test.ts,test/tui-can.test.tsandtest/mcp-size.test.tspass, and so do the 129 filesscripts/fast.tsnamed (1000 pass, 24 skipped in the sandbox). The MCP is unchanged, so no ceiling moved.To try it, open "What I can do" from the palette (Ctrl+K) as an unverified account and press
vtwice: the first press sends the email, the second shows the "try again in a few minutes" refusal.🤖 Generated with Claude Code
Closes #7301