diff --git a/packages/coding-agent/CHANGELOG.md b/packages/coding-agent/CHANGELOG.md index c85c8ac8e..17f92c741 100644 --- a/packages/coding-agent/CHANGELOG.md +++ b/packages/coding-agent/CHANGELOG.md @@ -1,6 +1,9 @@ # Changelog ## [Unreleased] +### Fixed + +- Fixed excessive subprocess spawns by caching git status for 1 second in the footer component ## [3.3.1337] - 2026-01-03 diff --git a/packages/coding-agent/src/modes/interactive/components/footer.ts b/packages/coding-agent/src/modes/interactive/components/footer.ts index 20883bba6..784125f84 100644 --- a/packages/coding-agent/src/modes/interactive/components/footer.ts +++ b/packages/coding-agent/src/modes/interactive/components/footer.ts @@ -58,6 +58,10 @@ export class FooterComponent implements Component { private autoCompactEnabled: boolean = true; private hookStatuses: Map = new Map(); + // Git status caching (1s TTL to avoid excessive subprocess spawns) + private cachedGitStatus: { staged: number; unstaged: number; untracked: number } | null = null; + private gitStatusLastFetch = 0; + constructor(session: AgentSession) { this.session = session; } @@ -165,8 +169,14 @@ export class FooterComponent implements Component { /** * Get git status indicators (staged, unstaged, untracked counts). * Returns null if not in a git repo. + * Cached for 1s to avoid excessive subprocess spawns. */ private getGitStatus(): { staged: number; unstaged: number; untracked: number } | null { + const now = Date.now(); + if (now - this.gitStatusLastFetch < 1000) { + return this.cachedGitStatus; + } + try { const output = execSync("git status --porcelain 2>/dev/null", { encoding: "utf8", @@ -200,8 +210,12 @@ export class FooterComponent implements Component { } } - return { staged, unstaged, untracked }; + this.cachedGitStatus = { staged, unstaged, untracked }; + this.gitStatusLastFetch = now; + return this.cachedGitStatus; } catch { + this.cachedGitStatus = null; + this.gitStatusLastFetch = now; return null; } }