Skip to content

Remote workrooms in the app: create, open and delete (Nightly only) #253

Closed

Description

@joelmoss

Parent

Part of #154 (remote agent sessions). Phase 4. Design doc docs/designs/remote-workrooms.md: Phase 4 "Remote deletion needs its own path too (C5)", Success Criteria, and Next Steps item 5 ("Remote UI remains Nightly-only until the success criteria pass").

What to build

The first time the shipped app creates a remote workroom. Everything Phase 3 built is only reachable from tests today: registerRemoteSession (PersistentSessionService) and AgentBootstrap.ensure are called only by the test suite.

  • Create. From the app, create a remote workroom for a locally registered project: derive it from the project's base (Portable derivation on the container driver: the base machine and deriveFromBase #252), connect its host, bootstrap the agent, and open a terminal pane on the far side with the repo present. The UI says plainly that a remote workroom belongs to a local project.
  • Open. A remote workroom in the sidebar reconnects its host and its panes the way Phase 3's transport does, and Changes, History, the diff viewer, the Files tree and the PR/CI badges work against it through the agent.
  • Delete. Remote deletion is its own path: destroy the box and cancel the workroom's broker grant, with the teardown script run on the far side first. delete-project --with-workrooms cascades to it for each remote workroom.
  • Nightly only. The remote UI is behind the Nightly channel until the Phase 4 success criteria pass on two real providers.

Acceptance criteria

  • In a Nightly build, creating a remote workroom opens a terminal on the far side with the repo checked out.
  • Changes, History, the diff viewer, the Files tree and the PR/CI badges work against it, and agree with what the same commands report on the box.
  • Quitting and reopening the app reconnects the remote workroom and repaints its panes.
  • Deleting a remote workroom destroys the box and cancels its grant: the broker refuses any further mint for it.
  • delete-project --with-workrooms removes the project's remote workrooms the same way.
  • A stable-channel build shows no remote UI.

Blocked by

#252 (portable derivation).

Filed by Claude Code at the owner's request, 2026-09-27.

Activity

  1. joelmoss commented on Oct 1, 2026

    @joelmoss
    OwnerAuthor

    Gaps left by #249 for this issue to close. #249 was merged in #275 (76191a0f) on 2026-10-01.

    #249 makes every delete path refuse a remote workroom, with the code RemoteWorkroomUnsupported. It does this so that teardown never runs against a local path of the same name, and so that config never drops the only record of a paid machine. The remote delete path in this issue has to replace these refusals:

    • CLI: Service.refuseRemote (internal/workroom/workroom.go). It is called from Delete and at the start of RunTeardown, so it covers delete, interactive delete and the --with-workrooms cascade.
    • CLI: the remote-workroom check in cmd/delete_project.go. It refuses in all three modes, not only with --from-disk.
    • App: the up-front guards in AppStore.deleteWorkroom and AppStore.deleteProject.

    Known gaps:

    1. A destroyed host has no exit. A workroom whose host has state: "destroyed" shows the HostDestroyed warning (the "Host destroyed" state in the app). It cannot be deleted, because every delete path refuses it. Today the only way to remove it is to edit the config by hand. The remote delete path should treat "already destroyed" as a no-op destroy, and then remove the entry.
    2. The delete confirmation text is wrong for remote rows. In the app, the confirmation for a remote workroom still says that deleting removes the workroom's directory and runs the teardown script. The refusal only appears after the user confirms. The text needs a remote variant: destroy the box, cancel the grant, and run teardown on the far side.
    3. Implicit and explicit project removal behave differently on purpose. When a project's last workroom is removed, RemoveWorkroom keeps the project if it carries a host. An explicit delete-project drops the project. The design doc records this under "As built (Remote host descriptors in config, and host-gated warnings #249)". Check that this is still what we want once the remote delete path exists.
    4. Session restore doesn't check availability. PersistentSessionRecovery.recover calls TerminalSessions.materializeLivePersistentSessions. That function calls ensureSurfaceCreated (TerminalSessions.swift:2219) for every restored pane whose local session is still live, and it never checks TerminalTarget.unavailability. So if a workroom has turned remote since its pane was saved, its old local shell is reattached in a hidden surface. A .directoryMissing target has the same gap, which existed before Remote host descriptors in config, and host-gated warnings #249. When a target is unavailable, keep its restored tab state but leave it out of recovery. The fix touches Core/Session/, so macapp/AGENTS.md rule 3 calls for an adversarial review. This is the open CodeRabbit thread on feat: remote host descriptors in config, and host-gated warnings #275, and acceptance criterion 3 here (quit and reopen) goes through this path.

    🤖 Left by Claude Code

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

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions