You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Your π secrets now follow you across machines β a vault can be shared with your workspace, and every Mac you own (and every teammate you invite) reads and writes the same secrets. The server never holds a value: your device has a keypair, the vault's key is sealed to each device's public key, and each secret is encrypted under that key before it leaves the Mac. The server stores ciphertext and nothing else, so it can only ever be trusted with what it cannot read. Sharing it β the drawer's Share this vault with <workspace> turns a local vault into a shared one; the header then shows the workspace's name, a shared badge and the key version. A teammate's machine is added by fingerprint: both sides show the same string, you compare them out of band, and only then is the key sealed to that device. Devices is a new tab on the workspace's Team page. The desktop's keypair never leaves the machine it was made on, and Weft's servers can't substitute their own β a fingerprint that doesn't match stops the grant before any key is produced. Working in it β the drawer pulls changes when it opens and follows them live, a teammate's edit shows in the event log beside the secrets (who did what, never a value), and if your change loses a race the row says so: "Sam changed API_KEY in development β keep your edit?", with both ways out. Reads work offline from the local shadow; writes made offline queue up and drain in order, and nothing is dropped while a conflict is unresolved. When people leave β removing a teammate can rotate the shared vaults: the key version is bumped, a fresh key is made on your own Mac and sealed to the machines that stay, and every value is re-encrypted under it, so the plaintext they held stops being worth anything. Weft then names the values to change at their providers β the names only. A vault's recovery key is 24 words that open it when every machine is gone: Touch ID asks, the words appear once to write down, Weft keeps no copy, and asking again makes a new one so the old words stop working. The schema is supabase/migrations/20261027163113_team_vault.sql; the crypto is electron/vault-crypto.cjs, the sync engine electron/vault-sync.cjs, the grant flow electron/vault-grant.cjs, the rotation electron/vault-rotate.cjs and the recovery key electron/vault-recovery.cjs, with the workspace side in app/[orgSlug]/team/devices/ and app/api/team/vaults/.
Esc now says where it took you β pressing Esc on a bare board flips between the columns and the list sheet, and a small pane now pops under the board/list toggle naming the view you landed in ("List view. Esc goes back."). It hangs off the toggle rather than taking a row, so it costs no vertical space on a small screen, and it closes itself after a moment or on its β. The hint is driven by the board's own Escape layer, so it appears on exactly the Escape that moves the view: with a thread, the new-thread dialog, the browser pane or a closable drawer open, or with Esc typed in a field, the view stays put and no pane appears. Escape from a page in the browser pane now reaches the board too β a focused page swallowed the key, and it arrived as a raw key-down that the pane's replay dropped, so the flip never happened from inside a page. The pane is components/ViewHint.tsx with its state and timer in lib/use-view-hint.ts, the flip's hook lib/use-escape-view.ts, and the pane's Escape rule electron/pane-escape.cjs.
Changed
The model picker closes when you pick, and every row is a model β no more "Let Claude Code choose" or "Let the model choose" in a model menu: each row is the model that will actually run, and a menu with nothing picked shows the model its CLI runs. Codex and Goose, whose model lives in their own config, each keep one row for it (Codex's configured model, Your BYOK model). The list is taller, so more models fit before it scrolls, and it closes on a pick β the field sits inside a label, and the click that used to refocus the input and reopen the list is cancelled now. The Goose group lists your provider's models, not a fixed set β a menu's Goose rows are the provider you set up (Settings β Models β Bring your own key): OpenRouter's anthropic/claude-opus-4.1 never shows under Anthropic any more, and a local Ollama shows the id it runs. A Goose id is recognised through the provider catalog, so a model still routes to Goose, and a Goose row's value is prefixed so it can't be mistaken for another CLI's same id. Name your models β Settings β Models β Bring your own key has a Model names section: a name beside a model id ("Big Opus" for anthropic/claude-opus-4.1), and every model menu in Weft shows that name with the id beside it. The id field offers your provider's own model ids as suggestions. The picker is components/ModelTypeahead.tsx and components/ModelSelect.tsx, the rows lib/model-options.ts and lib/new-thread.ts, the provider's models lib/goose-provider.ts, and the naming UI components/GooseNamedModels.tsx with lib/use-named-models.ts and the settings route.
Fixed
A Goose model is no longer dropped when a thread starts. Picking a model from a Bring-your-own-key provider and starting a thread with it ran on the provider's default instead of the model you picked, with nothing to say so: the id was checked against a pattern that allowed neither the "/" in an OpenRouter id (anthropic/claude-opus-4.1) nor the ":" in a local tag, so it was read as no model at all. The check now allows the characters a real model id uses, and the "goose:" prefix a picker adds comes off at the card's edge, because a card's model is the id the CLI takes. (lib/new-card.ts)