Skip to content

Git Sync Settings - Credential Prompt Control#1761

Open
mrinc wants to merge 2 commits intopingdotgg:mainfrom
mrinc:t3code/git-usage-audit
Open

Git Sync Settings - Credential Prompt Control#1761
mrinc wants to merge 2 commits intopingdotgg:mainfrom
mrinc:t3code/git-usage-audit

Conversation

@mrinc
Copy link
Copy Markdown

@mrinc mrinc commented Apr 5, 2026

Closes #1467

Problem

t3code performs a background git fetch every ~15 seconds to compute ahead/behind counts.
When a repository uses SSH remotes and the user's SSH agent (e.g. 1Password) requires
interactive confirmation, this causes repeated authentication dialogs that steal focus
and get killed by the 5-second fetch timeout before the user can respond.

Solution

Add server settings under a new "Git Sync" section in Settings.
All defaults preserve the current behaviour so existing users are unaffected.

Setting Type Default What it does
Background git polling Select "all" All sessions — all sessions poll (current behaviour). Active session only — only the focused session polls; sidebar background-thread queries pause. Disabled — no automatic git sync at all.
Quiet background fetches Toggle OFF Suppresses credential prompts during automatic git fetches by setting GIT_TERMINAL_PROMPT=0, SSH_ASKPASS="", GIT_ASKPASS="", GCM_INTERACTIVE=never on the fetch subprocess. Useful with SSH agents like 1Password.

How It Works

Polling Mode (gitPollingMode)

  • "all" (default) — Every session and the sidebar poll for git status on their normal intervals (15s for active, 60s for sidebar threads). Server-side upstream fetch runs every 15s. No change from current behaviour.
  • "active-session" — The active/focused session polls normally. Sidebar thread status queries stop polling (refetchInterval: false). Server-side upstream fetch still runs when triggered by the active session's status query.
  • "disabled" — All client-side polling intervals are disabled (refetchInterval: false, refetchOnWindowFocus: false). Server-side refreshStatusUpstreamIfStale early-returns without executing git fetch. Manual operations (push, pull, checkout) still work.

Quiet Background Fetches (gitQuietBackgroundChecks)

When enabled, the fetchUpstreamRefForStatus function passes environment variables to the git fetch subprocess that suppress all interactive credential prompts:

Variable Purpose
GIT_TERMINAL_PROMPT=0 Prevents git from prompting on the terminal
SSH_ASKPASS="" Prevents SSH from spawning an askpass helper (e.g. 1Password dialog)
GIT_ASKPASS="" Prevents git's own askpass mechanism
GCM_INTERACTIVE=never Prevents Git Credential Manager from showing dialogs (Windows)

If credentials are already cached/loaded in the agent, the fetch succeeds silently. If not, it fails silently (the fetch already has allowNonZeroExit: true and the caller wraps it in Effect.ignoreCause).

This toggle is visually disabled when polling mode is "disabled" since there are no background fetches to quiet.

Architecture

Data Flow

Settings UI (Select / Switch)
  → useUpdateSettings() → ServerSettingsService.updateSettings(patch)
  → settings.json on disk (sparse: only non-default values stored)
  → PubSub → WebSocket subscription → client atom update → component re-render

Server-Side (Effect layers)

GitCoreLive now depends on ServerSettingsService (yielded in makeGitCore). Settings are read via serverSettings.getSettings with Effect.catch(() => Effect.succeed(null)) fallback so settings errors don't break git operations.

Client-Side (React Query)

gitStatusQueryOptions and gitBranchSearchInfiniteQueryOptions accept an optional { pollingEnabled } parameter that controls refetchInterval, refetchOnWindowFocus, and refetchOnReconnect. Each consumer component derives pollingEnabled from settings.gitPollingMode.

Files Changed (15 files, +184 / -29)

Schema & Contracts

  • packages/contracts/src/settings.ts — Add GitPollingMode literal type ("all" | "active-session" | "disabled"), gitPollingMode field (default "all"), and gitQuietBackgroundChecks boolean (default false) to ServerSettings + ServerSettingsPatch

Server — Git Fetch Control

  • apps/server/src/git/Layers/GitCore.ts (+52 / -14)
    • Add env field to ExecuteGitOptions interface and forward it through executeGitexecute → subprocess spawn
    • Import ServerSettingsService, yield it in makeGitCore
    • refreshStatusUpstreamIfStale: early-return when gitPollingMode === "disabled"
    • fetchUpstreamRefForStatus: read gitQuietBackgroundChecks, conditionally set quiet env vars on the fetch subprocess

Client — Polling Interval Control

  • apps/web/src/lib/gitReactQuery.ts — Add optional pollingEnabled param to gitStatusQueryOptions and gitBranchSearchInfiniteQueryOptions; controls refetchInterval, refetchOnWindowFocus, refetchOnReconnect
  • apps/web/src/components/Sidebar.tsx — Sidebar thread polling enabled only when gitPollingMode === "all"
  • apps/web/src/components/ChatView.tsx — Derive pollingEnabled from gitPollingMode !== "disabled"
  • apps/web/src/components/DiffPanel.tsx — Same pattern
  • apps/web/src/components/GitActionsControl.tsx — Same pattern (added useSettings import)
  • apps/web/src/components/BranchToolbarBranchSelector.tsx — Same pattern for both status and branch search queries (added useSettings import)

Settings UI

  • apps/web/src/components/settings/SettingsPanels.tsx (+80)
    • New GIT_POLLING_MODE_LABELS constant
    • New "Git Sync" SettingsSection between Providers and Advanced with:
      • Background git pollingSelect with three options (All sessions / Active session only / Disabled)
      • Quiet background fetchesSwitch toggle, disabled when polling mode is "Disabled"
    • Both rows have reset buttons and descriptive helper text
image

Test Files — New Layer Dependency

Adding ServerSettingsService as a dependency of GitCoreLive requires providing ServerSettingsService.layerTest() in test layer stacks:

  • apps/server/src/git/Layers/GitCore.test.ts
  • apps/server/src/git/Layers/GitManager.test.ts
  • apps/server/src/checkpointing/Layers/CheckpointStore.test.ts
  • apps/server/src/orchestration/Layers/CheckpointReactor.test.ts
  • apps/server/src/workspace/Layers/WorkspaceEntries.test.ts
  • apps/server/src/workspace/Layers/WorkspaceFileSystem.test.ts

Verification

  • Build: npx turbo run build — all 5 tasks pass
  • Server startup: node dist/bin.mjs — starts cleanly on :3773, no errors
  • Runtime: Verified Effect.catch (not Effect.catchAll) is the correct API for Effect 4.0 beta

Note

Add Git Sync settings to control background polling mode and credential prompts

  • Adds two new server settings: gitPollingMode (all | active-session | disabled) and gitQuietBackgroundChecks (boolean), configurable via a new Git Sync section in the General Settings panel.
  • When gitPollingMode is disabled, background upstream status refresh is skipped server-side in GitCore, and all client-side git status/branch polling (Sidebar, ChatView, DiffPanel, GitActionsControl, BranchToolbarBranchSelector) is suspended.
  • When gitQuietBackgroundChecks is enabled, background git fetches suppress interactive credential prompts by setting GIT_TERMINAL_PROMPT=0, GIT_ASKPASS, SSH_ASKPASS empty, and GCM_INTERACTIVE=never.
  • Behavioral Change: gitPollingMode defaults to all and gitQuietBackgroundChecks defaults to false, preserving existing behavior for users who have not changed settings.

Macroscope summarized a789d30.

…prompts

Background git fetches every 15s trigger repeated 1Password/SSH agent popups
when credentials aren't cached (fixes pingdotgg#1467). Adds a new "Git Sync" settings
section with a polling mode selector (All sessions / Active session only /
Disabled) and a quiet background fetches toggle that suppresses credential
prompts via GIT_TERMINAL_PROMPT=0, SSH_ASKPASS="", etc. All defaults preserve
existing behaviour.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@coderabbitai
Copy link
Copy Markdown

coderabbitai bot commented Apr 5, 2026

Important

Review skipped

Auto reviews are disabled on this repository. Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: 70d19775-c677-4711-8105-eb7c31f9d646

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@github-actions github-actions bot added size:L 100-499 changed lines (additions + deletions). vouch:unvouched PR author is not yet trusted in the VOUCHED list. labels Apr 5, 2026
@macroscopeapp
Copy link
Copy Markdown
Contributor

macroscopeapp bot commented Apr 5, 2026

Approvability

Verdict: Needs human review

This PR adds a new user-facing feature with two git sync settings that control background polling behavior and credential prompt suppression. The changes affect runtime behavior across multiple server and client components, modifying how and whether git fetches occur. New feature introduction with runtime behavior changes warrants human review.

You can customize Macroscope's approvability policy. Learn more.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size:L 100-499 changed lines (additions + deletions). vouch:unvouched PR author is not yet trusted in the VOUCHED list.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Background git status refresh triggers SSH passphrase prompt and cancels it

1 participant