Skip to content

fix: name remote sessions after the workspace - #1037

Merged
janicduplessis merged 5 commits into
appandflow:mainfrom
jamesacklin:fix/unique-remote-session-name
Sep 24, 2026
Merged

janicduplessis merged 5 commits into
appandflow:mainfrom
jamesacklin:fix/unique-remote-session-name

Conversation

@jamesacklin

@jamesacklin jamesacklin commented Sep 24, 2026 •

Copy link
Copy Markdown
Contributor

Description

Remote sessions were named from projectShortcut, which is the app directory's basename, so every worktree of a monorepo app got the same name (stim-tlon-mobile) for both the EAS session (ownedSessionName) and the agent-device session and profile (sessionNameFor).

agent-device stores remote connection state per session name (~/.agent-device/remote-connections/<session>.json). With two worktrees on --remote eas or --remote proxy at once, the second one's connect --force rewrites the connection the first is using. That part is inferred from agent-device's layout. What was observed on stock 1.8.0 is every worktree's session and connection file named stim-tlon-mobile.

Solution

resolveRemoteContext now derives the name from the workspace root instead of taking a label from the caller: ownedDeviceLabel(root), the same worktree-plus-app label local simulators and AVDs use, followed by workspaceId(root), the 16-hex path hash local simulators fall back to when their name is taken. For example, stim-tlon-wt2-tlon-mobile-<hash>. The name shows which worktree owns a session in the EAS dashboard, is the same on every run, and needs no stored state. The hash is always added, because unlike local simulators there is no cheap way to check whether a remote name is already in use, and two worktrees or repos can share a folder name.

Trade-off: a remote session opened by an older Stim under the plain stim-<label> name is not carried over. Run stim stop before upgrading.

  • --remote eas: after an upgrade mid-session, stim stop still ends the old EAS session by its recorded id.
  • --remote proxy: the first run after an upgrade rewrites the profile under the new name, so neither its pre-connect close nor stim stop releases an agent-device session left under the old name. That session has to be closed by hand under its old name, and until then the daemon may report the device as in use. This comes from reading the code and was not reproduced against a real daemon.

Test plan

  • pnpm test packages/stim-cli/src/__tests__/device-remote.test.ts -t "names its own": two workspaces whose app directories are both named app (a/app, b/app) get different agent-device session and EAS names, of the form stim-app-<16 hex>.
  • Full checks pass on this branch merged with current main: format:check, lint, build, typecheck, knip, pnpm test (154 files, 4710 passed, 18 skipped), test:runtime.
  • Real tools: an earlier revision of this branch, which added a UUID suffix, was run on v1.8.0 with agent-device 0.21.13 and eas-cli 24.7.0 against the iOS EAS Simulator. Two worktrees of one Expo app each had a live session at the same time, each with its own connection file and remote daemon, and each drove only its own device. The current names use the same characters ([a-z0-9-]) and are shorter, but have not been run against EAS again.
  • Not exercised: --remote proxy against a real daemon (unit tests only), and Android.

A note for anyone reproducing the two-worktree run: an EAS agent-device lease went inactive after roughly a minute without a command. The next command then allocated a new lease that the session refused (Lease does not match session owner), and the session was unusable from then on. That also happens with one worktree and is unrelated to this change.

Every worktree of a repository resolves the same project label, so remote
runs from two worktrees both named their agent-device session, tenant and
run `stim-<label>` and their EAS session the same. agent-device keeps one
local connection per session name, so the second worktree's connect took
over the first's connection.

resolveRemoteContext now suffixes the label with a random UUID, stored as
remoteLabel in the workspace state so later runs reuse it. A workspace
that already records a remote session keeps the plain label until that
session ends, because the remote agent-device session stays bound to the
name it was opened under.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
jamesacklin and others added 3 commits September 24, 2026 14:31
Resolve the node:fs import in device-remote.ts: main moved JSON reads to
readJsonObject and dropped readFileSync; this branch adds randomUUID.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@janicduplessis janicduplessis changed the title fix: give each workspace its own remote session name fix: name remote sessions after the workspace Sep 24, 2026
@janicduplessis
janicduplessis merged commit 482900b into appandflow:main Sep 24, 2026
8 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants