[FEATURE] Configurable fetch TTL for `worktree.baseRef: "fresh"` — 24h is too coarse for multi-session-per-day workflows

Status Open
Reported on v2.1.220
Maintainer reply None cached
Activity 0 comments · opened Aug 8, 2026

Preflight Checklist

  • [x] I have searched existing requests and this feature hasn't been requested yet
  • [x] This is a single feature request (not multiple features)

Problem Statement

Since v2.1.208, a worktree.baseRef: "fresh" worktree fetches the default branch before branching — but only when the repository hasn't been fetched in the last 24 hours. For workflows running several parallel sessions a day whose PRs merge quickly (the exact workflow session worktrees exist to serve), main moves many times inside that window, so worktrees are still routinely cut from a stale cached origin/HEAD — "fresh" in name only.

Real data from one ordinary day on our repo (Claude Code 2.1.220, desktop app session worktrees, macOS arm64, default branch main on GitHub, worktree.baseRef unset):

Merged PRs on 2026-08-07 (UTC): #3 21:23:00Z, #2 22:06:35Z, #4 22:40:11Z, #6 22:58:43Z — four merges to main in 96 minutes, each from a different parallel session's worktree.

A session worktree created at 22:56:03Z was cut from 720a404 (the #4 merge commit — correct at that instant):

$ git reflog show <branch> --date=iso
720a404 <branch>@{2026-08-08 01:56:03 +0300}: branch: Created from refs/remotes/origin/main

PR #6 merged 2m40s later. The locally cached origin/main then stayed at 720a404 for ~13 hours into 2026-08-08 (verified mid-morning: git rev-parse origin/main720a404 while gh api .../branches/mainb45bf40). Any worktree created during those hours started one PR behind, because a fetch inside the 24h TTL had already stamped the window. At this merge velocity that is the common case, not the edge case: the faster sessions merge, the more stale every subsequent same-day worktree starts.

Proposed Solution

A worktree.fetchTtl setting (seconds), default 86400 to preserve current behavior, 0 meaning "always fetch before cutting a "fresh" worktree":

{
  "worktree": {
    "baseRef": "fresh",
    "fetchTtl": 0
  }
}

The cost is already bounded by the v2.1.208 mechanism itself: the fetch is capped at five seconds with graceful fallback to the cached ref on failure. The machinery exists; only the TTL is tuned for a trunk that moves daily rather than hourly.

Alternative shape, if a new setting is unwanted: always fetch for "fresh" worktree creation specifically (keeping the 24h TTL for other consumers of the cached ref). Worktree creation is rare, latency-tolerant, and the single moment where staleness converts into merge conflicts later.

Alternative Solutions

  • Current workaround: a rebase-onto-origin/main-before-push convention in CLAUDE.md/memory. It catches staleness at the far end, at the cost of larger rebase conflicts and sessions reading day-old code the whole time they work.
  • A SessionStart hook running git fetch origin main && git merge --ff-only origin/main — works, but re-implements per-repo what "fresh" already promises.
  • GitHub Copilot's coding agent solves the same problem structurally (fetch at every task start against a persistent clone); this request is the equivalent knob for Claude Code's local-first model.

Priority

Medium - Would be very helpful

Feature Category

Configuration and settings

Use Case Example

  1. Morning: three parallel desktop sessions each land a PR to main within an hour; the last merge triggers no fetch (TTL window stamped at ~09:00).
  2. Afternoon: a fourth session starts; its worktree is cut from the cached origin/main, three PRs behind.
  3. The session builds on code that was already replaced, then hits avoidable rebase conflicts at push time.
  4. With fetchTtl: 0, step 2 costs at most five extra seconds and the worktree starts at the true tip.

Additional Context

Related, complementary requests about base selection rather than base freshness: #23622 (choose base branch when creating a worktree), #74091 (per-call baseRef on the Agent tool).

View original on GitHub ↗