Skip to content

Persist worktrees across session restore to avoid re-cloning #32

Description

@kirang89

Problem

When restoring a session (e.g., after page refresh or clicking on a previous session in the sidebar), the current implementation creates a new git worktree even if one already exists for that commit. This is because:

  1. The session.close() method in ask-forge cleans up the worktree via git worktree remove --force
  2. When a session is restored via /api/restore, if it's not in memory, we call connect() which creates a new worktree

Current Behavior

  • Session created → worktree created at workdir/<owner>/<repo>/trees/<short-sha>/
  • Session closed (disconnect, delete, or 10-min idle TTL) → worktree removed
  • Session restored (not in memory) → new worktree created (slow, re-clones)

Desired Behavior

Worktrees should persist across session restores to avoid the overhead of re-creating them. The worktree should only be cleaned up when:

  • The session is explicitly deleted by the user
  • Some longer-term cleanup policy (e.g., LRU eviction when disk space is low)

Analysis

The ask-forge library's connect() function already handles the case where a worktree exists:

const worktreePath = resolve(basePath, "trees", shortSha);
if (await exists(worktreePath)) {
    // Reuses existing worktree
    return { localPath: worktreePath, ... };
}

However, the close() method unconditionally removes the worktree:

close() {
    if (closed) return;
    closed = true;
    // Clean up worktree asynchronously (fire and forget)
    const proc = Bun.spawn(["git", "worktree", "remove", "--force", repo.localPath], ...);
}

Proposed Solution

  1. Option A: Modify ask-forge to add a keepWorktree option to close():

    close({ keepWorktree = false } = {}) {
        if (closed) return;
        closed = true;
        if (!keepWorktree) {
            // Remove worktree...
        }
    }
  2. Option B: Add a separate Session.cleanup() method that removes the worktree, and have close() only mark the session as closed without removing files.

  3. Option C: In ask-forge-web, don't call session.close() on disconnect/idle - only call it on explicit delete. This means worktrees accumulate and need separate cleanup logic.

Impact

  • Faster session restore (no git operations needed if worktree exists)
  • Better UX when refreshing pages or switching between sessions
  • Need to consider disk space management for accumulated worktrees

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions