Skip to content

feat: start a new chat session in a managed worktree (web, iOS, Android)#100788

Merged
steipete merged 1 commit into
mainfrom
feat/session-worktrees
Jul 6, 2026
Merged

feat: start a new chat session in a managed worktree (web, iOS, Android)#100788
steipete merged 1 commit into
mainfrom
feat/session-worktrees

Conversation

@steipete

@steipete steipete commented Jul 6, 2026

Copy link
Copy Markdown
Contributor

Related: #100534 — completes the session-level trigger deferred from #100535.

What Problem This Solves

Managed worktrees (#100535) could only be created by Workboard automations, the CLI, or the admin RPC. The everyday flow — "start this new chat in an isolated checkout", the composer toggle every major coding agent ships — did not exist: sessions.create had no workspace notion, so all chats ran directly in the agent's workspace and parallel sessions on one repo collided.

Why This Change Was Made

Adds a worktree flag to sessions.create (additive; governed by the method's existing operator.write scope — unlike the admin-gated worktrees.* RPCs it never takes an arbitrary repoRoot, only the agent's own configured workspace, which write-scope chat runs already mutate): the gateway materializes a managed worktree of the agent's workspace repo (ownerKind: "session", owner = the session key, idempotent per key), persists its path as the session's spawnedCwd — which chat runs, CLI commands, and the session file browser already honor — and returns { worktree: { id, path, branch } }. Agent summaries gain workspaceGit (true when the workspace or an ancestor is a git checkout, matching the service's own repo discovery) so clients can gate the affordance. All three clients expose it: the web sidebar gets a split New-Chat action, iOS and Android add "New Chat in Worktree" menu actions, all gated on workspaceGit. Deleting a session lossless-removes its worktree (snapshot-backed, dirty trees kept); idle GC treats recent session activity as worktree activity via an owner-activity hook, so a daily-used session's checkout can never be swept while only-abandoned ones expire.

Non-goals: repo picker / branch-name input (agent workspace, auto names only), exposing raw cwd to non-plugin clients, config surface (zero new keys).

User Impact

Users can start any new chat in an isolated worktree — one button on web, a menu action on iOS/Android — when the agent's workspace is a git repo. The agent then works on its own openclaw/<name> branch in its own checkout: parallel sessions stop stepping on each other and on the user's own edits. Cleanup is automatic and loss-proof: deleting the session removes a clean worktree (with a restore snapshot) and keeps a dirty one, and abandoned session worktrees age out via the existing GC with snapshots.

New-chat worktree action (web sidebar, gated on workspaceGit):

Session worktree button

Live-test state on the Worktrees page — three session worktrees active, one restorable after its session was deleted:

Worktrees page

Evidence

Live end-to-end on a real gateway (isolated state dir, port 19801, real OpenAI model turn):

  • agents.list reports workspaceGit: true; sidebar shows the split action on a fresh page load
  • Button/RPC → session + worktree: centralized path, openclaw/wt-* branch checked out, .worktreeinclude copied .env, .openclaw/worktree-setup.sh ran, spawnedCwd persisted
  • Real agent turn (gpt-5.5) wrote hello-from-worktree.txt inside the worktree; the source workspace stayed untouched
  • sessions.delete: dirty worktree kept (fail-safe); clean worktree removed with OpenClaw worktree snapshot: run-end pinned at refs/openclaw/snapshots/<id> and branch deleted; appears as Restorable in the UI (second screenshot)
  • Repeated create for the same key reuses the existing worktree (one live registry row)

Gates on Blacksmith Testbox (Linux, Node 24): oxlint 0/0 on touched paths; 14 focused test files green (worktrees service incl. owner-activity GC, sessions.create/delete lifecycle + cwd propagation into agent runs, maintenance hook wiring, protocol schema, workboard, UI e2e chat flow, navigation); tsgo:prod + tsgo:test + tsgo:test:ui; ui:build; full pnpm build; ui:i18n:check + native:i18n:check. Codex autoreview (gpt-5.5) iterated to clean — its findings (subdirectory-workspace preflight rejection, unused import) are fixed with a regression test.

Adds an additive worktree flag to sessions.create so any new chat can run in an
isolated managed worktree of the agent's git workspace, with the branch checked
out and .worktreeinclude provisioning applied. The session's spawnedCwd points at
the matching subdirectory inside the worktree so chat runs, CLI, and the file
browser execute there. agents.list gains workspaceGit (workspace or an ancestor
is a git checkout) to gate the affordance; web sidebar, iOS, and Android expose a
New-Chat-in-worktree action. Uses the method's operator.write scope, but the
.openclaw/worktree-setup.sh step runs only for operator.admin callers since it
executes repo code. Deleting the session, or leaving via a plain New Chat, clears
the cwd and lossless-removes the worktree; idle GC treats recent session activity
as worktree activity so an active session's checkout is never swept.

Live-verified end-to-end on a real gateway; follow-up to #100535 (issue #100534).
@openclaw-barnacle openclaw-barnacle Bot added docs Improvements or additions to documentation app: android App: android app: ios App: ios app: web-ui App: web-ui gateway Gateway runtime agents Agent runtime and tooling size: XL maintainer Maintainer-authored PR labels Jul 6, 2026
@steipete
steipete merged commit b4b1984 into main Jul 6, 2026
83 of 88 checks passed
@steipete
steipete deleted the feat/session-worktrees branch July 6, 2026 09:23

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 7a419f5904

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

private var chatActionsMenu: some View {
Menu {
Button {
Task { await self.viewModel?.startNewSession() }

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Disable New Chat while a response is pending

When a run is still pending, this new iOS menu path stays enabled and calls startNewSession directly. The pending-run guard in OpenClawChatViewModel.performSend only protects slash-command sends, and IOSGatewayChatTransport.CreateSessionParams does not send emitCommandHooks, so the gateway's parent-active check is skipped; tapping this during a response switches chats and leaves the active run attached to the old session.

Useful? React with 👍 / 👎.

Comment on lines +97 to +99
let current = path.resolve(start);
for (;;) {
if (existsSync(path.join(current, ".git"))) {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Resolve symlinked workspaces before Git preflight

For an agent workspace that is a symlink to a subdirectory inside a Git repo, path.resolve keeps the symlink path, so this ancestor walk never reaches the real repo's .git even though git -C <workspace> rev-parse --show-toplevel succeeds and ManagedWorktreeService.create would accept it. Because both the UI capability and sessions.create now rely on this helper, valid symlinked subdirectory workspaces incorrectly hide or reject the worktree chat action.

Useful? React with 👍 / 👎.

github-actions Bot pushed a commit to Desicool/openclaw that referenced this pull request Jul 7, 2026
…aw#100788)

Adds an additive worktree flag to sessions.create so any new chat can run in an
isolated managed worktree of the agent's git workspace, with the branch checked
out and .worktreeinclude provisioning applied. The session's spawnedCwd points at
the matching subdirectory inside the worktree so chat runs, CLI, and the file
browser execute there. agents.list gains workspaceGit (workspace or an ancestor
is a git checkout) to gate the affordance; web sidebar, iOS, and Android expose a
New-Chat-in-worktree action. Uses the method's operator.write scope, but the
.openclaw/worktree-setup.sh step runs only for operator.admin callers since it
executes repo code. Deleting the session, or leaving via a plain New Chat, clears
the cwd and lossless-removes the worktree; idle GC treats recent session activity
as worktree activity so an active session's checkout is never swept.

Live-verified end-to-end on a real gateway; follow-up to openclaw#100535 (issue openclaw#100534).
giodl73-repo pushed a commit to giodl73-repo/openclaw that referenced this pull request Jul 8, 2026
…aw#100788)

Adds an additive worktree flag to sessions.create so any new chat can run in an
isolated managed worktree of the agent's git workspace, with the branch checked
out and .worktreeinclude provisioning applied. The session's spawnedCwd points at
the matching subdirectory inside the worktree so chat runs, CLI, and the file
browser execute there. agents.list gains workspaceGit (workspace or an ancestor
is a git checkout) to gate the affordance; web sidebar, iOS, and Android expose a
New-Chat-in-worktree action. Uses the method's operator.write scope, but the
.openclaw/worktree-setup.sh step runs only for operator.admin callers since it
executes repo code. Deleting the session, or leaving via a plain New Chat, clears
the cwd and lossless-removes the worktree; idle GC treats recent session activity
as worktree activity so an active session's checkout is never swept.

Live-verified end-to-end on a real gateway; follow-up to openclaw#100535 (issue openclaw#100534).
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

agents Agent runtime and tooling app: android App: android app: ios App: ios app: web-ui App: web-ui docs Improvements or additions to documentation gateway Gateway runtime maintainer Maintainer-authored PR size: XL

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant