Repository navigation
Locked out of my own chat: pressing enter only shows "Continue this chat here?" #2072
Description
Summary
A person can be locked out of their own chat on their only computer. The chat opens and shows its history, but pressing enter brings back "Continue this chat here?", and pressing continue here does nothing visible. The only way back in is an undocumented combination of an environment variable and a flag.
The root cause is a version gap between the codeaf client and the hosted sync service. Around it are about a dozen bugs and UX problems that turn one server-side gap into a lockout with no way out. This issue lists all of them from the person's side. #2070 and #2071 hold the deeper detail for some of them.
Principle: the chat on this computer is the person's. Sync is a convenience on top. No state of the sync service, a lease, or another device should ever stop a person from writing to a chat on the computer in front of them.
What a person meets, in order
- They pair two computers, work in a chat on one, then go back to the other.
- Home shows the same chat two or three times: two identical
<title> 28 turns · <machine> 16mrows and a third row with the same title and no count. - Opening the chat shows "Continue this chat here?". Pressing
continue herecloses the card and nothing opens. No message. - They unpair the other computer to simplify things.
codeaf devices revoke <name> --allsaysno device called "<name>" is paired with this machine, whilecodeaf deviceslists that exact name. Without--allit works. - Home now offers "Continue 's latest chat here?" for the device they just removed.
- Opening a duplicate row offers "open separately / discard / leave them". Discarding both copies cleans Home, but the chat still shows the card, now saying "this chat was last held here", on the only computer they use.
- They open the chat directly with
codeaf chat --session <path>. It opens with full history. Typing a message and pressing enter brings the card back. They can't send. - The chat shows two lines they can't act on: "calls are not being sealed, so rewind cannot reach them: the sync service must be updated before chats can move; codeaf's operators update the hosted service, or run this build of codeaf relay for your own service".
- They turn sync off with
CODEAF_SYNC_URL=off. Home now shows only chats from a week ago or more; every current chat is gone from the list. - They open the chat with sync off. It fails: "the background engine for this folder started with a different environment than this terminal and is still in use…" along with an
engine --stopcommand that would interrupt their other window. - What finally works:
CODEAF_SYNC_URL=off codeaf chat --no-host --session <path-to-transcript.jsonl>. Nobody would find that. - Separately, trying to reach the computer without ssh (
codeaf serve) fails witherror code: 522(Reaching a paired computer without ssh fails on the hosted relay #2071).
Bugs and causes
Code citations are origin/dev at 66fa77e.
A. Lockout: no writes when the service can't do a conditional take — the blocker
- When a chat's lease has lapsed (
wasFree), writing needsAcquire(RequireConditional: true)(internal/syncsetup/drive.go:271-286).continue heredoes too (internal/handoff/handoff.go:140). - The client only allows that when the service sends
codeaf-conditional-takes(internal/directory/http.go:97-106). Otherwise it returnsErrConditionalTake. - The relay source in dev has sent that header since 2026-10-23 (
relay/hosted/src/routes.js:111, Wormhole: your codeaf follows you between computers (on by default) #1888 and Relay: coordination as a Raft group, and joined computers can lead #1950). The deployed hosted service doesn't, so every lapsed chat on every client of this build can't be written. - The window falls back to "only shows its local copy", and each enter shows the takeover card again instead of saying why.
B. Client and hosted service can drift apart unnoticed
Nothing stops a client build from requiring service behaviour that isn't deployed: no version handshake, no deploy gate, no CI check that the live service answers what the shipped client requires.
C. continue here fails silently (#2070)
takeRemoteStatereturns early whilehomeTakingis set, and successful landings never clear it (internal/tui3/homepanel_continue.go:298).- In a fresh window, the
ErrConditionalTakesentence is put on Home's say line, which the person doesn't see when the card closes.
D. "Continue this chat here?" on the only computer
The card says "this chat was last held here" and still asks. With no other live holder, there is nothing to continue from.
E. Duplicate rows and the meaning of a branch row (#2070)
- Branch copies (
N turns · <device>,internal/chatlist/copy.go:39,174) show as identical rows next to the main chat. - Local rows are keyed by transcript path, machine rows by cell id (
homepanel_sessions.go:24-36,homepanel_machines.go:169-200). - Nothing on the row says it is a leftover copy, and nothing says whether "discard" loses anything.
F. A removed device is still offered
After codeaf devices revoke, Home still offers "Continue 's latest chat here?".
G. devices revoke --all misses computers that sync chats
stopAllByName sends --all to the first kind that can stop several, which is the serve device book, never the synced-chats kind (cmd/codeaf/devices.go:160-170). Without --all, kindOf finds it. The same name works or fails depending on a flag that only means "every device with this name".
H. Turning sync off hides current chats
With CODEAF_SYNC_URL=off, Home lists only legacy chats. Current chats live in the copy root (<project>/.moving/<id>, internal/cell/copy.go:27), which is only listed through sync. Sync off should mean "don't talk to the service", not "forget my chats".
I. Sync off can't be used while another window is open
The background engine refuses a terminal with a different environment and offers only engine --stop, which interrupts the other window. --no-host works but isn't mentioned.
J. Store-busy shows the wrong reason (#2070)
The engine's "store writer is still busy after waiting 30 seconds" falls through to "the chat could not be put in this folder" (homepanel_heldelsewhere.go:374). It never names the program holding the store.
K. --host takes onto the wrong computer (#2070)
Under codeaf chat --host B, sync and takeover run on the connecting computer while Home's rows come from B (chatv3_host.go:599 → chatv3_surface.go:86).
L. Messages written for operators, not people
- "calls are not being sealed, so rewind cannot reach them" and "codeaf's operators update the hosted service, or run this build of codeaf relay" don't tell the person what still works, what doesn't, or what to do.
error code: 522is printed raw (Reaching a paired computer without ssh fails on the hosted relay #2071).
M. The folder name .moving reads like a stuck transfer
Every current chat lives under .moving/. Anyone checking state by hand reads it as "half-moved" and may try to clean it up, which would delete their chats.
Acceptance (end to end, each one a two-device or one-device test on the hosted service)
Never locked out
- With the hosted service missing any capability the client wants (e.g. conditional takes), a chat whose lease has lapsed and that no other device holds live can still be written on this computer. The person types, presses enter, and gets a reply. The turn is kept locally and published when the service allows. No card is shown.
- When another device holds the chat live, pressing enter says so in one line naming the device, with
continue hereas the action. It is never just the card again with no reason. - There is no state of sync, lease, relay or device list in which a person can read a chat on this computer but has no visible way to write to it.
Service and client stay compatible
- The release and deploy pipeline fails if the live hosted service doesn't answer a capability the client being shipped requires. A client never ships ahead of the service it depends on.
- A client talking to an older service keeps every feature that doesn't need the new capability, and says in one plain sentence which feature waits for the update.
Continue here
- Pressing
continue hereeither opens the chat within a few seconds or shows one line saying why, with retry. Three continues in a row in one window all work. - On a computer that last held the chat, with no other live holder, no card is shown. The chat just opens.
Home
- Each chat appears once. Leftover copies show as a small marker on that row ("2 copies from "), not as identical rows. Opening the marker says plainly what is in each copy and whether discarding loses anything.
- A removed device never appears in any offer, row or card.
Devices
-
codeaf devices revoke <name>andcodeaf devices revoke <name> --allboth remove a computer listed bycodeaf devices, whichever kind it is.
Sync off
- With sync off, Home lists every chat on this computer, current and legacy, and each opens and can be written.
- Turning sync off while another window is open either applies to the new window without touching the other one, or says exactly what to run.
--no-hostis offered when it is the answer.
Messages
- Every message about sync tells the person what still works, what doesn't, and the one thing they can do. No operator instructions, no raw upstream bodies.
-
codeaf doctorreports a lapsed lease that can't be retaken, a client/service capability gap, leftover copies and removed devices still referenced.codeaf doctor --fixrepairs what is safe to repair and says what it did.
Storage
- The folder holding current chats has a name that doesn't suggest something in flight, or carries a README saying it is the live store and must not be removed.
Related: #2070 (continue here, duplicate rows, store-busy reason, --host), #2071 (reaching a computer without ssh on the hosted relay), #1982 and #1986 (closed, earlier sealing and two-computer issues).
Seen on the dev channel build of 2026-10-29 against the hosted sync service on 2026-10-30.
Activity
Never lock the only computer out of its chat on an older sync service
Open this computer's lapsed chat without a question, and never offer …
Say plainly what waits for a sync service update, and document it
Offer --no-host when sync settings differ, and explain the .moving fo…
Never lock a person out of their own chat on an older sync service (#…
AbirAbbas commentedon Oct 30, 2026
Status after #2075 and #2078 (both merged into
dev):codeaf doctor/doctor --fixfor a busy store, unfinished continues, duplicate rows and lapsed holds (Continue a chat from another computer every time, and let doctor repair sync (#2070) #2078).codeaf-release service.Sync off keeps every chat, and a copied older chat can no longer be w…
AbirAbbas commentedon Oct 31, 2026
Everything here has landed on
dev:--hostconsistent, one chat per row,codeaf doctor/--fix): Continue a chat from another computer every time, and let doctor repair sync (#2070) #2078RELAY_DEPLOY_PRODUCTIONis set.dev: a rewind or a take onto a copied older chat dropped itscopy-readymarker, and opening the original afterwards removed the copy.Two doctor items were left out on purpose:
POST /v1/dir/acquire), and doctor must not create anything on the service.codeaf-release servicekeeps that probe.