Skip to content

Remote agent sessions #154

Closed
29 of 29 issues completed
Closed

Description

@joelmoss

Start an agent session on a remote server.

Design doc https://github.com/joelmoss/workroom/blob/master/docs/designs/remote-workrooms.md

Inspiration

Phase 1 — complete

Landed in #181, #182, #183, #192 (2026-09-15). wr-agent serve | attach owns every new pty. See the Phase 1 comment below.

Phase 2 — merged to master (2026-09-23)

The whole stack merged as ce284372…827033d2: #201 → #202 → #204 → #210 → #212 → #213 → #214 → #215 → #216 → #217 → #218

Review follow-ups: #220 (closed 2026-09-24), fixed in #221 (high), #222 (medium), #223 (low) and #225 (OQ19 harness). #226 fixed three fork-window test flakes (#224).

Phase 2 — what is left on #208

#206 closed as a duplicate of #211 (2026-09-22).

Phase 3 — checklist complete (2026-09-26)

The stream drivers, per the design doc's Phase 3 and Next Steps item 4. All of it is exercised end to end over ssh against the container fixture, but nothing in the shipped app creates a remote pane or connects a remote host yet: registerRemoteSession and AgentBootstrap.ensure are only called from tests until Phase 4 wires remote workrooms in.

Phase 3 follow-ups:

OQ21 (where the HostDriver lives) is answered: a Swift protocol in the Mac app.

Phase 4 — filed 2026-09-27

Provisioning, credentials, lifecycle and the UI, per the design doc's Phase 4 and Next Steps item 5. OQ20 is decided by ADR 0049 (2026-10-12), which supersedes the credential broker PR #248 first chose: Workroom runs no broker. A provider's host fetches and pushes with the provider's own GitHub credentials, so pushes are in the user's name and a remote workroom needs no Codaset account. A boxd machine uses the user's boxd git integration; an exe.dev VM uses an exe.dev GitHub integration the user adds per repository. A local container workroom keeps the Mac's gh relay (ADR 0039). The broker, the Codaset sign-in and the Mac's device key were removed in 8d7b0502 and ce812d4a. ADR: docs/adr/0049-provider-hosts-bring-their-own-git-credentials.md. Research: docs/designs/oq20-remote-git-credentials.md (PR #248). The two real providers are boxd and exe.dev.

Body updated by Claude Code at the owner's request, 2026-10-06.

#356 added to the checklist by Claude Code at the owner's request, 2026-10-07 (#348 closed as not needed).

Updated by Claude Code at the owner's request, 2026-10-08: PR #375 removed the remote-workrooms gate.

Updated by Claude Code at the owner's request, 2026-10-09: #259 shipped as #383, and #284, #286, #323, #324 and #325 are closed.

Updated by Claude Code at the owner's request, 2026-10-12: #258 closed as not planned, and ADR 0049 replaced the Codaset credential broker.

Activity

  1. joelmoss commented on Sep 15, 2026

    @joelmoss
    OwnerAuthor

    🤖 Left by Claude Code

    Phase 1 is complete

    Landed across #181, #182, #183, and closed out by #192 (2026-09-15). wr-agent serve | attach owns every new pty; the Swift daemon is retired.

    The one place the plan was wrong

    Phase 1's last bullet was "delete macapp/WorkroomSession/ once the agent has soaked for a release cycle". That gate does not do what it says: a soak drains nobody. Draining completes only for panes a user actually closes, so anyone who skips the intermediate release — or just holds a long-lived pane through an update — meets a build with no workroom-session in its bundle while their old daemon is still holding their shell.

    Traced end to end: resolveOwner answers .swiftDaemon, binaryPath is nil, attachCommand is nil, and the pane silently opens a plain shell while the real work keeps running in an orphaned daemon that now never exits.

    So the directory was split, not deleted. The half that runs terminals is gone (SessionDaemon, SessionPTY, the daemon subcommand). The half that connects to them stays, and can never become a daemon itself. It self-obsoletes — retirement is a TODOS.md entry with written criteria rather than a deletion waiting on a calendar.

    Compatibility is measured, not assumed: the shipped v2.0.0 binary is pinned as a test fixture and the suite drives this build against it on every run (reattach + replay, typing, exit status, list/info/ownership/kill, version handshake both ways). WorkroomSessionProtocol is frozen while the shim ships.

    Two plan items closed as answered-differently

    • OQ14, "what is the local rollback?" — there is none, and the question was aimed at the wrong risk. The proposed mitigation (keep the Swift daemon selectable for one release) was never built and can't be now. The failure that strands users isn't a bad agent, it's the app updating at all. A rollback would not have fixed that; forward compatibility does.
    • "The local switchover is riskier than the remote feature" — right about the seam, wrong about the remedy. Three routing bugs and two create-on-attach hazards came out of exactly that boundary, none of them found by the differential harness.

    Needs a human decision at release time

    Rolling back to v2.0.0 replaces the contents of open terminals with fresh shells (the old daemon creates on attach for an id it doesn't hold), and updating again does not bring them back — both helpers then claim the id and the daemon wins. The sessions aren't destroyed; wr-agent outlives the app and they stay reachable from the CLI.

    This is a release-note item, not a code one. Text to lift: docs/designs/remote-workrooms.md → Phase 1 Results → Outstanding item 5.

    Still open for later phases

    1. A Linux wr-agent as a published build artifact (Phase 3 needs it; Phase 1 doesn't).
    2. OQ21 — where the HostDriver lives.
  2. joelmoss commented on Sep 19, 2026

    @joelmoss
    OwnerAuthor

    🤖 Left by Claude Code (at the owner's request).

    #211 (agent-backed file service) is implemented as draft PR #212, the top of the stack (#201 → #202 → #204 → #210 → #212). It adds Service::File to wr-agent (protocol 3): directory listing, descriptor-verified raw reads, and change notification with agent-side coalescing, plus the app-side routing for all three watch sites. All eight acceptance criteria on #211 are met; details, what changed since the engineering review, and what was deferred are in the status comment there.

    Two things worth knowing at this level:

    • Local failure policy. A local host never loses its files to its agent: if the agent is missing, dead, too old or fails mid-request at the transport level, listing and reading run natively. A remote host has no native path, so its unavailability stays an explicit failure. That is the rule the remaining services (status, interchangeability) should follow for anything a local host can do without an agent.
    • Design doc (docs/designs/remote-workrooms.md) now documents the File service and its known limits (any directory a same-user peer names is served, so a path allowlist is still the deferred remote-registration work; a daemonizing child of jj can inherit the jj barrier descriptor).

    Remaining in Phase 2: #207 (agent-aware GitHub status) and #208 (interchangeability services). #206 ("Agent-backed file access and notifications") has the same scope as #211 and looks superseded by it; I have not closed it, so that is your call.

  3. 14 remaining items

  4. added
    remoteRemote workrooms: hosts, providers, the far-side agent and broker
    on Oct 3, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or requestready-for-humanremoteRemote workrooms: hosts, providers, the far-side agent and broker

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions