GitHub (VSCode extension — proof of concept)
A GitHub companion for VSCode. Browse and manage your repositories across
every signed-in gh account and org from a dedicated GitHub view, with a
status-bar surface for your accounts and sync state. One of its core features
is a first-class git worktree workflow for the bare-repo layout:
~/Repos/host/owner/repo/ ← container (holds .bare + flat worktrees)
├── .bare/ ← bare clone
├── .git ← "gitdir: ./.bare"
├── main/ ← worktree (flat sibling)
└── feature-login/ ← worktree (flat slug of "feature/login")
Worktrees are created as flat siblings of .bare; branch slashes are slugified (feature/login → feature-login). Each worktree is added to the workspace as its own root, labelled repo/branch (configurable depth) so you can tell repo and branch apart in the Explorer.
Features
- Repository management — list, clone, and open repos across accounts/orgs from the GitHub tree view.
- Worktree workflow — bare-repo layout with flat sibling worktrees and repo+branch identity.
- Autosync — keep clones and branches reconciled with the remote on a configurable cadence.
- Accounts status bar — the GitHub glyph with a cached, auto-refreshing account overview.
Built for VSCode 1.120+ (tested on 1.123), git 2.50; distributed as a local .vsix (no marketplace).
Run it (Extension Development Host)
npm install
npm run compile # or: npm run watch
Then open this folder in VSCode and press F5 ("Run Extension"). A second VSCode window launches with the extension loaded.
Make a test repo
./scripts/make-demo-repo.sh # creates ~/wt-demo/...
# Open the printed worktree folder (…/cool-repo/main) in the dev-host window
Try the features
In the Extension Development Host, with a worktree folder open:
- One file UI: every opened worktree/repo is a root in the multi-root Explorer. Git working-tree roots are auto-labelled with parent path segments (
msx.github.label.parentDepth, e.g. repo/branch); the bare container (the folder holding .bare + the .git pointer) keeps its plain folder name, since its worktrees are already visible inside it.
- Source Control view shows all repositories side by side — worktree-based and ordinary single-branch repos — in the built-in Repositories list.
- Create a worktree like creating a branch: the New Worktree button in the Source Control view title. Type a name → branch + worktree + added to the workspace, in one step.
- Source Control view →
··· overflow → Worktrees ▸ — the full worktree menu.
- File Explorer → right-click → Worktrees ▸ — same menu from the Explorer.
- Right-click a repository in the SCM Repositories view → Open Branch as Worktree…
- Command palette →
Worktrees: — all commands.
| Command |
What it does |
| New Worktree… / Open Branch as Worktree… |
Unified picker: open a local/remote branch as a worktree, or type a name to create a new branch. Per-item $(empty-window) button opens in a new window. |
| Add Worktree to Workspace… |
Add an existing on-disk worktree as a labelled root. |
| Add All Worktrees |
Add every worktree of the repo as a root. |
| Remove Worktree… |
git worktree remove (+ force prompt if dirty) and drop the root; offers to delete the branch. |
| Cleanup Stale Worktrees |
Prune + remove worktrees whose branch is merged / upstream [gone]. |
| Open Worktree in New Window… |
Open a worktree in a separate window. |
| Clone Repository (Worktree Layout)… |
Bootstrap host/owner/repo/.bare from a remote URL and open the default branch. |
| Re-apply Worktree Labels |
Recompute root labels from current settings. |
GitHub view
A dedicated GitHub activity-bar view browses everything reachable through your gh CLI logins and clones it straight into the worktree layout. It mirrors the bulk PowerShell sync (Checkout-GitHubRepo.ps1), but lazily and on demand:
github.com (host — desc: account login)
MariusStorhaug ‹you› (personal owner)
PowerShell master ● cloned
master ✓ worktree
feature/new ✓ worktree local
feature/…
PSModule … (orgs)
- Host → Owner → Repo → Branch, spanning every authenticated host (
gh auth status). Owners are your personal account(s) (tagged ‹you›) plus their orgs (gh api user/orgs). Authentication and the multi-account model are specified in docs/auth.md.
- Lazy: orgs+repos load when a host/owner is expanded; branches (
gh api repos/{owner}/{repo}/branches) load only when a repo is expanded.
- Local-state decorations: cloned repos show
● cloned; branches checked out as worktrees show ✓ worktree; a locally-created branch not yet pushed to the remote also shows local; the default branch is marked.
- Everything is cached in-memory; the title-bar Refresh (and the inline refresh button on every host/owner/repo row) clears the matching cache and re-queries
gh, then recursively warms that subtree (hosts → owners → repos → branches) so collapsed levels expand instantly. The walk runs with bounded concurrency behind subtle status-bar progress and is cancellable; hidden/disowned scopes are skipped.
| On |
Command |
What it does |
| Repo |
New Branch (Worktree)… (inline +) |
Create a branch as a worktree under the repo. On an already-cloned repo it opens the full New Worktree picker (type a name to create, or pick a local/remote branch to open) — the same picker as the Source Control side; on an uncloned repo it's a lightweight name prompt that bare-clones as part of the create. The branch is published (git push -u, when autoSync.publishNewBranches is on) and the new row appears live — ✓ worktree, carrying local until the push lands — with no Refresh, and you stay on the GitHub view. |
| Branch |
Create Branch From This… (inline $(git-branch-create)) |
Branch off the clicked branch row: prompts for the new name, then bases the new worktree on that branch — its local head refs/heads/<branch> if present, else the remote-tracking origin/<branch>. Same publish + live in-place update (no Refresh, stays on the view) as New Branch (Worktree). |
| Host / Owner / Repo / Branch |
View in Browser |
Open the item on its GitHub/GHE web UI — host home, owner page, repo page, or the branch's tree. Also available in the Explorer (right-click any file/folder) and the Source Control view (repo row + changed file), which open the path on origin at …/blob|tree/<branch>/<path>. |
| Host / Owner / Repo / Branch |
View in Finder / Explorer |
Reveal the level's on-disk folder in the OS file manager — labelled View in Finder (macOS), View in File Explorer (Windows), or View in File Manager (Linux). Sits directly under View in Browser and is reveal-only like it — it never clones. Host / Owner reveal the aggregate folder (<reposRoot>/<host>[/<owner>]), Repo the container (…/<owner>/<repo>, holding .bare + every worktree), Branch its worktree; a level with nothing cloned yet shows a "nothing on disk to reveal yet" notice instead. |
| Host / Owner / Repo / Branch |
Maintenance ▸ (right-click submenu) |
Set this scope's capabilities. Each leaf — Fetch · Pull · Clone new · Publish · Materialize all · Track renames · Adopt layout · Adopt folder name · Prune gone · Prune merged · Delete absent — is a tri-state toggle (Inherit · On · Off). Pull carries Scope (Default · All) and Source (Origin · Upstream); Clone new carries Scope (Bare · Default · All). A trailing group offers Layout ▸ (Inherit · Regular · Worktree), the Presets (Mirror · Fresh, never delete · Disown (Ignore) · Reset all), and Remove local copy…. The row shows a badge of its effective on caps (inherited parenthesised; ⊘ ignored when disowned). On a branch (a worktree scope) only Pull is meaningful; the other leaves target the parent repo. Full spec: docs/modes.md. |
| Host / Owner / Repo / Branch |
Maintenance ▸ Disown (Ignore) / Reset all |
Disown (Ignore) stamps every capability to explicit off across the subtree — the durable "stop managing this" barrier (it survives a folder deletion, since the override lives in the machine-local metadata store, not in the repos tree). Reset all clears the subtree's overrides back to inherit. Neither deletes anything on disk; pair with Remove local copy… to also delete the bytes (one modal lists what's on disk, ⚠-flags dirty/unpushed folders; a whole-host removal requires typing the host name). |
| Host / Owner / Repo |
Hide (inline eye) |
The inline eye toggles a scope's hidden display flag — $(eye) hides the row, $(eye-closed) (visible after Show Hidden Sections) un-hides it. Cosmetic only: hiding does not change whether the scope is managed. Gated by msx.github.showEyeIcon. Disowning a scope is the separate Maintenance ▸ Disown (Ignore) action. |
GitHub view title (…) |
Show / Hide Eye Icon |
View-wide toggle for the inline eye on all host/owner/repo rows, persisted in the msx.github.showEyeIcon user setting (default shown). Hiding the eye is cosmetic — right-click Maintenance ▸ (incl. Hide and Disown) still works. |
GitHub view title (…) |
Show / Hide Add to Workspace Icon |
View-wide toggle for the inline Add to Workspace button on all rows (host/owner/repo/branch), persisted in msx.github.showAddToWorkspaceIcon (default shown). Cosmetic — the action stays under right-click. |
GitHub view title (…) |
Show / Hide Open in New Window Icon |
View-wide toggle for the inline Open in New Window button on all rows, persisted in msx.github.showOpenInNewWindowIcon (default shown). Cosmetic — the action stays under right-click. |
GitHub view title (…) |
Default Maintenance ▸ |
Set the global default for each capability — the base of the cascade — written to the msx.github.auto.<cap> settings, plus the cloneScope / pullScope / pullSource / repoLayout sub-choices. Every capability defaults off out of the box. |
GitHub view title (…) |
Reset all… |
Factory reset: clear every per-scope and per-worktree override across all hosts and restore the global auto.<cap> defaults (all off), then decide the fate of every cloned folder. One modal lists what's on disk and offers Keep files / Delete all (Esc cancels, Keep is the default) — or a plain Reset when nothing is cloned; a whole-host Delete all still requires typing the host name. Reuses the shared delete-safety envelope (unsafe folders flagged + stashed). |
| GitHub view title |
Add Repos Root to Workspace / Open Repos Root in New Window |
Title-bar buttons (beside Sync Now / Refresh) that add the whole reposRoot (e.g. ~/Repos) as a workspace root or open it in a new window — the top of the aggregate hierarchy. Plain-folder open: never clones; if nothing is cloned under the root yet you get a "nothing cloned under … yet" notice instead of an empty folder. |
| Host / Owner / Repo / Branch |
Add to Workspace / Open in New Window |
Add the level's folder to the workspace (or open it in a new window) — now available at every level. Host / Owner open the aggregate folder (<reposRoot>/<host>[/<owner>]) as a plain workspace root with no cloning (a single click must never bulk-clone an org); VSCode's git detection surfaces the nested worktrees, and a not-yet-populated folder yields the "nothing cloned" notice. Repo opens the repo container itself (<reposRoot>/<host>/<owner>/<repo>, the folder holding .bare + every checked-out worktree as a subfolder) — an existing container opens as-is, otherwise the repo is bare-cloned and the default branch checked out on demand so the folder isn't .bare-only. Branch targets the branch's worktree — bare-cloning the repo and git worktree add-ing a flat sibling (local or remote-tracking) on demand if needed, adding it to the workspace, and revealing it in Source Control. Both actions appear as inline buttons (Add to Workspace then Open in New Window) on every row, each toggleable independently from the view title's … overflow (msx.github.showAddToWorkspaceIcon / msx.github.showOpenInNewWindowIcon); they remain in the right-click menu regardless. Host/owner/repo rows additionally carry an inline refresh button (re-fetch that node's children). |
| Repo |
Clone All Branches (inline $(list-tree)) |
Bare-clone the repo if needed, then lay down a worktree for every remote branch — regardless of the repo's effective clone scope. Materialise-only: it never opens a folder or adds anything to the workspace; the repo/branch rows just flip cloud → ✓ worktree in place on completion (no Refresh). Idempotent — existing worktrees are reused (ensureWorktree), so on an already-cloned repo it fills in any missing branch worktrees. Always available — inline button and right-click — regardless of capabilities, since the underlying op is harmless to repeat. |
| Branch |
Clone into Worktree (inline $(repo-clone)) |
Bare-clone the repo if needed, then materialise this one remote branch as a flat-sibling worktree — without opening it or adding it to the workspace (the materialise-only counterpart to Add to Workspace, which also opens + reveals). The row flips cloud → ✓ worktree in place on completion (no Refresh). Always available — inline button and right-click — on remote-only (cloud) branch rows. |
| Repo |
Clone (Worktree Layout) |
Bare-clone into <reposRoot>/<host>/<owner>/<repo>/.bare, checking out worktrees per the repo's effective clone scope (bare → none, default → default branch, all → every remote branch), then opens the default-branch worktree. (A one-shot, scope-respecting clone; right-click menu only, shown when cloneNew is not effective for the repo — the inline clone button is then Clone All Branches. When cloneNew is on, the repo is cloned automatically; a disowned scope is left alone.) |
| Repo |
Adopt Layout… |
When the repo's effective repoLayout is worktree but the slot on disk holds a regular (non-bare) clone — typically created by an agent or a person who ran a plain git clone — migrate the container to the correct bare+worktrees layout while preserving full working-tree diff fidelity. The algorithm snapshots the existing working tree, dismantles the regular clone, bare-clones from the remote, creates a worktree for the current branch, wipes it clean, then restores only the files that were present in the snapshot. Files that were deleted since the last commit remain absent after migration, so git diff reflects the original state exactly — including deletions. Confirmation-gated; warns if unpushed commits are present. Shown on any repo row with a ⚠ non-bare badge; available regardless of capabilities. Full spec: docs/repo-layout.md. |
| Owner |
Clone All Repositories… |
Bulk bare-clone every repo in the owner, each per its effective clone scope (modal confirm + cancellable progress, per-repo error tolerance). (Inline button + right-click menu; shown when cloneNew is not effective at the owner scope.) |
| Host |
Clone All Repositories… |
Bulk bare-clone every repo across every (non-disowned) owner under the host — the host-level counterpart to the owner action (modal confirm showing the total scale + cancellable progress, per-repo error tolerance). (Inline button + right-click menu; shown when cloneNew is not effective at the host scope.) |
Clones use the HTTPS URL (https://<host>/<owner>/<repo>.git) so they ride your existing gh credential/SSO sessions. Routine, hands-off cloning is driven by the cloneNew capability (enable it on a scope via right-click Maintenance ▸); the explicit Clone All Branches (repo) and Clone into Worktree (branch) buttons cover the on-demand case regardless of capabilities.
Autosync
Each scope (host / owner / repo / worktree) carries a set of maintenance capabilities — small, independently-togglable switches that each enable exactly one reconcile behaviour. Capabilities are tri-state (on / off / inherit) and cascade down the hierarchy. Every capability's global default is off: a fresh install does nothing — no fetch, no clone, no delete — until you enable a capability at some scope. The full model (exact semantics, inheritance, the reconcile algorithm, the safety envelope) is specified in docs/modes.md; this is the overview.
Capabilities are reconciled against gh/git on Refresh, on Sync Now, and on a background schedule (autoSync.intervalMinutes, default 5 min; autoSync.fetchIntervalMinutes, default 15, throttles the per-repo network fetch). Set them per node from the view: right-click a host/owner/repo/worktree row → Maintenance ▸, then toggle each capability (Inherit · On · Off) or apply a Preset (Mirror · Fresh, never delete · Disown (Ignore) · Reset all). The title bar has Sync Now ($(cloud-download)), Refresh, and Add Repos Root to Workspace / Open Repos Root in New Window (which open the whole reposRoot as a plain folder, no cloning); its … overflow toggles Hide / Show Hidden Sections (hidden sections are hidden by default), Show / Hide Eye Icon (msx.github.showEyeIcon), and Show / Hide Add to Workspace Icon / Show / Hide Open in New Window Icon (msx.github.showAddToWorkspaceIcon / msx.github.showOpenInNewWindowIcon). Every row shows a compact badge of its effective on capabilities (inherited ones parenthesised); a fully-disowned row shows ⊘ ignored.
| Group |
Capability |
Behaviour |
| Refresh |
fetch |
git fetch --prune so origin/* reflects the remote. The cheap, safe foundation the other network caps reuse. |
|
pull |
Fast-forward in-scope worktrees. pullScope = the default-branch worktree (default) or every worktree (all); pullSource = origin, or upstream to fast-forward a fork from upstream/<branch> then push to origin (Sync fork). FF-only — skips dirty/diverged, never switches branches. |
| Grow |
cloneNew |
Clone any not-yet-cloned repo in scope, honouring cloneScope (bare/default/all) and repoLayout (regular/worktree). Add-only; never deletes. |
|
publish |
git push -u managed branches lacking an upstream — the publish, don't withhold primitive that makes pruning safe. |
|
materializeAll |
Ensure every remote branch has a worktree (worktree-layout repos). |
| Identity |
trackRenames |
Mirror a remote rename as a move (rename folder + re-point .bare), not delete-and-reclone. |
| Repair |
adoptLayout |
Migrate a non-bare clone sitting in a worktree-layout slot to the bare+worktrees layout, preserving full working-tree diff fidelity. See docs/repo-layout.md. |
|
adoptFolderName |
Rename a worktree's folder to match its branch after the branch is renamed in place — via git worktree move (repairs the .bare links), never a bare directory rename. Local, offline, non-destructive; the local-branch counterpart to trackRenames. |
| Prune |
pruneBranches |
Remove worktrees whose upstream is [gone] and delete the local branch. Squash-merge safe; never the default branch. |
|
pruneMerged |
Also remove worktrees whose branch is fully merged into the default branch. |
|
deleteAbsent |
Remove repo containers / owner folders no longer present remotely. The largest blast radius; fully governed by the safety envelope. |
Resolution is by nearest set scope: a repo inherits from its owner, an owner from its host, a host from the global msx.github.auto.<cap> default. An explicit child value always wins — including turning a capability back off under a scope that turned it on (tri-state is essential: off must be distinguishable from unset). The sub-choices cloneScope, pullScope, and pullSource resolve by the same walk, each from its own global default. Overrides and per-folder identity live in metadata.json files written at each level (<reposRoot>/, <host>/, <owner>/, <repo>/): a node's override sits in its parent's file (so it survives the node's own deletion), its identity in its own file. Config travels with the reposRoot tree and is human-inspectable.
Ignore & Remove local copy. Maintenance ▸ Disown (Ignore) stamps every capability to explicit off at the scope, fully disowning it and everything beneath from all inherited capabilities — the durable "stop managing this" barrier (it lives in the machine-local metadata store under the extension's global storage, not in the repos tree, so it survives a later folder deletion). Un-ignore clears the stamped entry back to inherit. The inline eye toggles a scope's hidden display flag (cosmetic — hide a row without changing whether it is managed), gated by msx.github.showEyeIcon. Remove local copy… is a separate, one-shot action that deletes a scope's managed folder from disk now; it is not a persistent capability. Disown + Remove local copy together = "stop managing this and delete the bytes."
Clone layout (repoLayout). Every clone path — cloneNew, the explicit clone actions, and on-demand Add to Workspace — respects the effective repoLayout for the repo (regular | worktree, resolved by nearest-set-ancestor from msx.github.repoLayout, default regular). regular produces a plain git clone with one working directory; worktree produces the bare+worktrees container. Override per host/owner/repo via Maintenance ▸ Layout ▸. See docs/repo-layout.md for the full resolution rules and capability interactions.
Clone scope decides how much cloneNew checks out: bare (only .bare + the .git pointer), default (one worktree for the default branch), or all (a worktree per remote branch). It resolves by nearest set scope exactly like a capability — repo → owner → host → the global msx.github.cloneScope default — and is stored in the same metadata.json child entry. Every clone path honours the effective scope — the manual Clone / Clone All / Clone Repository (Worktree Layout) actions and cloneNew clone-adds — so e.g. a host with cloneNew on at bare scope stages its repos as bare containers in the background, while a single repo at all keeps every remote branch checked out.
What deleteAbsent removes, scoped to where it's set:
- host = deleteAbsent → owner folders under
…/<host>/ no longer in your authoritative org list (you left/lost the org).
- owner = deleteAbsent → repo containers under
…/<host>/<owner>/ no longer present remotely (repo deleted/renamed).
- Worktree removal (an upstream-
[gone] or merged branch) is pruneBranches/pruneMerged, not deleteAbsent.
Safety model: publish, don't withhold
Safety comes from getting your work onto the remote, not from refusing to clean up:
- Publish ASAP. Every branch the extension creates/opens is pushed with
git push -u origin <branch> immediately (gated by autoSync.publishNewBranches, default on). Each reconcile re-publishes managed branches that still lack an upstream (e.g. an earlier offline push). Committed work therefore lives on the remote, so cleanup is non-destructive to real work. Push failures are logged, never blocking. We never set tracking config without a successful push — doing so would point an upstream at a ref that doesn't exist remotely, which the prune logic would then read as [gone] and delete.
- Stash scratch before removing. Before removing a stale worktree, any uncommitted changes are
git stash push -u'd (gated by autoSync.stashBeforeDelete, default on). The stash lives in .bare, so it survives worktree removal and stays recoverable.
Deletion signals
- Branch/worktree cleanup uses remote-branch absence, not merge state. A reconcile runs
git fetch --prune; a managed worktree whose branch had an upstream that is now [gone] is removed and its local branch deleted. This catches branches deleted after a squash merge (where git branch --merged would never list them). Branches with no upstream (never published / failed push) are never auto-deleted. The default branch is never removed. A failed fetch ⇒ no prune-deletes that cycle.
- Folder deletion uses authoritative
gh listings. Driven only by a gh api --paginate call that exits 0 (HTTP 200, all pages fetched). Any page error ⇒ non-authoritative ⇒ zero folder deletes that cycle (clone-adds may still proceed). Only directories that are clearly ours (bare-repo containers; for owner folders, every child is one) are ever candidates.
Circuit breakers (for the destructive folder deletes)
autoSync.maxDeletesPerRun (default 50): a scheduled run that would delete more folders than this skips all folder deletes and notifies. Branch-worktree pruning is not limited.
- A scheduled folder delete skips any container holding unpushed commits, unpublished branches, or uncommitted changes (logged). Sync Now (and whole-tree Refresh) instead opens a modal listing every path to delete — flagging the unsafe ones — and force-deletes on your confirmation. This is the explicit override, and it guards against an auth blip returning an authoritative-but-empty set.
- All destructive paths share one envelope.
deleteAbsent, pruneBranches/pruneMerged, and the one-shot Remove local copy all funnel into the same queue + confirm / circuit-breaker / unsafe-skip envelope, so a disowned repo under an otherwise-managed owner is still removed by an explicit Remove local copy. A whole-host removal is never done on a schedule and, on Sync Now, requires typing the host name to confirm.
Notifications (msx.github.notify.*)
Autosync reconciles and tree-command outcomes flow through one configurable notifier: a button-less summary toast (collapsible, severity-routed) with a [Details] link that opens the full report. Tune it with notify.level (off / errors / changes / all), the per-category notify.events toggles, and notify.detailsSurface; notify.statusBarOnly mutes toasts entirely. The GitHub output channel is the always-on log regardless. See docs/notifications.md for the full design.
Settings (msx.github.*)
| Key |
Default |
Purpose |
reposRoot |
~/Repos |
Base for the clone bootstrap layout. |
cloneScope |
default |
Global default clone scope: bare (.bare only) | default (default-branch worktree) | all (every remote branch). Override per host/owner/repo via Maintenance ▸ Clone new ▸ Scope; honoured by every clone path including cloneNew. Applies only when repoLayout is worktree. |
repoLayout |
regular |
Global default on-disk layout for cloned repos: regular (standard git clone, one working directory) | worktree (bare+worktrees layout). Override per host/owner/repo via Maintenance ▸ Layout ▸; cascades through the hierarchy. regular is the default — worktree layout must be opted in. See docs/repo-layout.md. |
cloneConcurrency |
4 |
Max heavy git ops (bare clones + git worktree add) run in parallel across the GitHub view. One shared limiter bounds all clone/worktree fan-out — Clone All (owner/host), all-scope multi-branch clones, on-demand opens, and autosync clone-adds — so total in-flight work never exceeds this however the callers nest. 1 = fully serial; max 16. |
branchSeparator |
- |
Replaces / in flat worktree folder names. |
label.parentDepth |
1 |
Parent path segments prepended to a working-tree root's folder name (0=branch, 1=repo/branch, 2=owner/repo/branch). |
autoLabel |
true |
Auto-relabel working-tree roots with parent depth; bare-repo containers stay plain. Multi-root only. |
label.separator |
/ |
Separator within the label. |
label.useRealBranch |
false |
Show real branch (with slashes) instead of the folder slug. |
label.format |
"" |
Optional template (overrides parentDepth) for working-tree roots. Tokens: ${host} ${owner} ${repo} ${branch} ${folder}. |
hideBare |
true |
Hide .bare via files.exclude. |
openMode |
addToWorkspace |
Default action after create/open. |
revealInSourceControl |
true |
After adding a worktree, open it as a repo in the Source Control view and focus it. |
newBranchBase |
origin/HEAD |
Default start point for new branches. |
fetchBeforeBranchList |
false |
Fetch before populating the picker. |
cleanup.staleWhen |
both |
merged | upstreamGone | both. |
paginate |
true |
Fetch all repos per owner in the GitHub view by following every page (gh api --paginate). Off ⇒ a single page of paginationSize repos. |
paginationSize |
100 |
Repos requested per API page (per_page): the page size while paginating, the single-page cap when paginate is off. GitHub caps this at 100. |
includeArchived |
false |
Include archived repos in the GitHub view. |
includeForks |
true |
Include forks in the GitHub view. |
excludeOwners |
[] |
Org names to hide from the GitHub view; supports * (e.g. psmodule-*). Personal accounts are never excluded. |
showEyeIcon |
true |
Show the inline eye (ignore toggle) on host/owner/repo rows. Toggle view-wide from the title … overflow. |
showAddToWorkspaceIcon |
true |
Show the inline Add to Workspace button on every row (host/owner/repo/branch). Toggle view-wide from the title … overflow; the action stays in the right-click menu when hidden. |
showOpenInNewWindowIcon |
true |
Show the inline Open in New Window button on every row (host/owner/repo/branch). Toggle view-wide from the title … overflow; the action stays in the right-click menu when hidden. |
auto.<cap> |
false |
Global default for each maintenance capability — auto.fetch, auto.pull, auto.cloneNew, auto.publish, auto.materializeAll, auto.trackRenames, auto.adoptLayout, auto.adoptFolderName, auto.pruneBranches, auto.pruneMerged, auto.deleteAbsent. Each defaults off; override per host/owner/repo/worktree via Maintenance ▸. Full semantics in docs/modes.md. |
pullScope |
default |
Breadth of the pull capability: default (default-branch worktree only) | all (every checked-out worktree). |
pullSource |
origin |
Source for the pull capability: origin (FF from origin/<branch>) | upstream (forks: FF from upstream/<branch> then push to origin, à la GitHub's Sync fork; behaves as origin for non-forks). |
autoSync.intervalMinutes |
5 |
Background reconcile cadence in minutes; 0 disables the schedule (Refresh / Sync Now still work). |
autoSync.fetchIntervalMinutes |
15 |
Throttles the per-repo git fetch inside the reconcile loop: a container is refetched only when this many minutes have elapsed since its last fetch. 0 = never fetch on a schedule. Sync Now ignores the throttle. |
auto.adoptLayout |
false |
The adoptLayout capability's global default (also in the auto.<cap> family above). When on, the scheduler may automatically migrate non-bare containers in worktree-layout slots to bare+worktrees — only when there are no unpushed commits, no active VSCode workspace roots in the container, and sufficient disk space. The explicit Adopt Layout… action always works regardless. See docs/repo-layout.md. |
autoSync.publishNewBranches |
true |
push -u branches on create/open and re-publish managed branches lacking an upstream each reconcile. |
autoSync.stashBeforeDelete |
true |
git stash push -u uncommitted changes before removing a stale worktree (stash survives in .bare). |
autoSync.maxDeletesPerRun |
50 |
Scheduled runs exceeding this skip all folder deletes and notify. Doesn't limit branch pruning. |
notify.level |
changes |
Master notification floor: off | errors | changes | all. changes (default) toasts only when a run changed something or errored. Governs autosync reconciles and tree commands. |
notify.events |
(all on except skip) |
Per-category on/off map (one key per NotifyCategory). An event shows only when its key is true and it clears notify.level. |
notify.detailsSurface |
document |
Where the [Details] link opens the full report: document (read-only Markdown virtual doc) | output (the GitHub output channel). |
notify.maxItemsInToast |
5 |
Item names listed per category in the expanded summary before +N more (0 = counts only). The report always lists all. |
notify.statusBarOnly |
false |
Suppress all toasts; reflect outcomes only in the status-bar item + output channel. |
git.autoConfigure |
true |
Master switch for on-clone git auto-config (the git.* keys below). Applied to .bare/config right after the initial fetch; every step best-effort. |
git.setUserIdentity |
true |
Set user.name/user.email from the owning gh account (profile name → login; primary email → profile email → <id>+<login>@users.noreply.<host>). Skipped when no account resolves. |
git.pullRebase |
false |
Value for pull.rebase: false | true | merges | unset (write nothing). |
git.originFetchRefspec |
+refs/heads/*:refs/remotes/origin/* |
remote.origin.fetch set before the initial fetch so every remote branch mirrors under origin/*. |
git.setBranchUpstream |
true |
Set branch.<default>.remote=origin + .merge=refs/heads/<default> so the default worktree tracks origin/<default>. |
git.forkUpstream |
full |
Forks: full (parent URL + upstream fetch refspec) | refspecOnly (fetch refspec only — blocks a later git remote add upstream) | off. |
git.windowsLongPaths |
true |
Windows only: set core.longpaths=true at --system scope, once per session, best-effort. |
On-clone git configuration (git.*)
Every bare clone — the manual Clone (Worktree Layout), the GitHub view's Clone / Clone All, and autosync clone-adds — funnels through one path that, right after the initial fetch, applies a set of git defaults to the container's shared .bare/config (so every worktree inherits them). Each step is independently toggleable via msx.github.git.* and best-effort: a gh/network/scope failure is logged to the GitHub output channel and never fails the clone.
- Identity (
git.setUserIdentity) — user.name/user.email from the owning gh account; skipped when no account resolves (e.g. a manual clone on a host you have no gh login for).
pull.rebase (git.pullRebase) — default false; unset leaves git's own default.
- Origin refspec (
git.originFetchRefspec) — set before the fetch so all remote branches mirror under refs/remotes/origin/* (required by the worktree layout).
- Default-branch tracking (
git.setBranchUpstream) — branch.<default>.remote/merge, so the default worktree tracks origin/<default> (default resolved via git symbolic-ref --short HEAD, robust on a bare repo).
- Fork upstream (
git.forkUpstream) — for repos gh reports as forks, add an upstream remote pointing at the parent (default full = parent clone URL + fetch refspec).
- Windows long paths (
git.windowsLongPaths) — core.longpaths=true at --system scope (Windows only, once per session).
Applies at clone time only — existing clones aren't retroactively reconfigured. Turn the whole thing off with git.autoConfigure=false.
Known limitations
- SCM provider row label: the built-in git provider shows each repository by its on-disk folder basename (the branch slug). Repo identity is carried by the multi-root Explorer label (ends with
repo/branch), not the SCM row.
- The bottom-bar branch glyph is owned by the built-in git extension and exposes no third-party menu point; worktree creation lives in the Source Control view's title button and repository-row menu instead.
- Re-labelling the first workspace root triggers a window reload (VSCode API behaviour).
| |