Problem / use case
When I create a workspace, its branch is cut from my local origin/<base> remote-tracking ref — whatever it happened to be at my last manual fetch. If a teammate has pushed since (or I just haven't fetched in a while), the new workspace silently starts from a stale base. I usually only notice after the agent has done work, and then have to rebase/merge origin/main inside the workspace — exactly the manual step isolated workspaces are meant to avoid.
Concretely: I branch feature workspaces off origin/develop several times a day across a few repos. Any push by a colleague between my fetches means a stale start, a surprise merge, and occasionally conflicts the agent introduced against already-moved code.
Root cause (current behavior)
task_create in src-tauri/src/lib.rs branches directly off the local ref with no preceding fetch:
let base_full = args.base_branch.unwrap_or_else(|| proj.base_branch.clone()); // e.g. "origin/develop"
// ...
git(&["branch", "--no-track", &branch, &base_full], &repo) // uses whatever origin/develop points at locally
// ...
git(&["worktree", "add", wt_arg, &branch], &repo)
The only git calls before the branch is cut are worktree prune/list and rev-parse — no fetch/pull/remote update anywhere in the create path (single- or multi-repo). So freshness depends entirely on the user having fetched recently.
Conductor already does this — it fetches from origin before creating a workspace, so the new branch is based on the latest remote commit even if the local checkout is behind. This is a straight parity gap.
Proposed solution
Before the git branch --no-track <branch> <base_full> call, do a best-effort, time-bounded fetch of just the base ref:
// base_full = "origin/develop" -> remote="origin", ref="develop"; skip if base is a local branch (no remote prefix)
// best-effort: never block or fail workspace creation on it
let _ = git_fetch_base(&repo, remote, base_branch); // git fetch --prune <remote> <base-branch>, bounded
- A single-ref fetch (
git fetch <remote> <base>) updates refs/remotes/<remote>/<base> and is fast — no need to fetch all refs.
- Same insertion in the multi-repo path (host + each member around the
worktree add sites), each honoring its own remote/base_branch.
task_create already runs off the IPC handler thread (per the comment at its top), so the added network call won't block the UI.
Critical: it must never hang or block create
A naive fetch-before-create is dangerous precisely because of auth/network. Guard it so a dead remote can't wedge workspace creation:
- Env:
GIT_TERMINAL_PROMPT=0 and GIT_SSH_COMMAND="ssh -oBatchMode=yes -oConnectTimeout=10" so a credential-less remote fails fast instead of prompting.
- A hard timeout on the fetch (e.g. 10–15s) with the child killed on expiry.
- Fetch failure is non-fatal — log it and proceed to branch off the existing local ref. Offline / auth-broken must still create the workspace, just from the stale ref (today's behavior), never an error.
Scope / config
- A toggle (global pref and/or
.termic.yaml per-project), default on, e.g. fetch_before_create: true, so users on flaky networks can opt out.
- Optional nicety: surface a subtle "fetching base…" state during create, but the minimal version needs no new IPC surface — it's internal to the existing create command.
Note
I currently work around this with an external launchd LaunchAgent that runs git fetch --prune across all my Termic repos every 30s, which keeps the local origin/* refs current so workspaces start fresh. That works, but doing the fetch at create-time (targeted, bounded) is the right home for it and removes the polling.
Problem / use case
When I create a workspace, its branch is cut from my local
origin/<base>remote-tracking ref — whatever it happened to be at my last manual fetch. If a teammate has pushed since (or I just haven't fetched in a while), the new workspace silently starts from a stale base. I usually only notice after the agent has done work, and then have to rebase/mergeorigin/maininside the workspace — exactly the manual step isolated workspaces are meant to avoid.Concretely: I branch feature workspaces off
origin/developseveral times a day across a few repos. Any push by a colleague between my fetches means a stale start, a surprise merge, and occasionally conflicts the agent introduced against already-moved code.Root cause (current behavior)
task_createinsrc-tauri/src/lib.rsbranches directly off the local ref with no preceding fetch:The only git calls before the branch is cut are
worktree prune/listandrev-parse— nofetch/pull/remote updateanywhere in the create path (single- or multi-repo). So freshness depends entirely on the user having fetched recently.Conductor already does this — it fetches from origin before creating a workspace, so the new branch is based on the latest remote commit even if the local checkout is behind. This is a straight parity gap.
Proposed solution
Before the
git branch --no-track <branch> <base_full>call, do a best-effort, time-bounded fetch of just the base ref:git fetch <remote> <base>) updatesrefs/remotes/<remote>/<base>and is fast — no need to fetch all refs.worktree addsites), each honoring its ownremote/base_branch.task_createalready runs off the IPC handler thread (per the comment at its top), so the added network call won't block the UI.Critical: it must never hang or block create
A naive fetch-before-create is dangerous precisely because of auth/network. Guard it so a dead remote can't wedge workspace creation:
GIT_TERMINAL_PROMPT=0andGIT_SSH_COMMAND="ssh -oBatchMode=yes -oConnectTimeout=10"so a credential-less remote fails fast instead of prompting.Scope / config
.termic.yamlper-project), default on, e.g.fetch_before_create: true, so users on flaky networks can opt out.Note
I currently work around this with an external launchd LaunchAgent that runs
git fetch --pruneacross all my Termic repos every 30s, which keeps the localorigin/*refs current so workspaces start fresh. That works, but doing the fetch at create-time (targeted, bounded) is the right home for it and removes the polling.