google-gemini / google-gemini/gemini-cli

Blocking Synchronous I/O on the Main Thread Causes UI Stutter

Open
#28,395 2 comments 0 reactions 0 assignees View on GitHub
area/core effort/medium kind/bug priority/p2 Stale status/bot-triaged
Dominant language
TypeScript
Stars
107k
Forks
14.6k
Avg merge
2d 3h
Merged PRs (30d)
45

Description

# Performance: Replace blocking filesystem operations in `shell.execute` with asynchronous APIs

**Category:** Performance
**Priority:** High

## Affected Components
- `packages/core/src/tools/shell.ts`
- `packages/cli` (React Ink UI)

## Summary

The shell tool performs synchronous filesystem operations (`fs.mkdtempSync`) on the main Node.js event loop immediately before spawning shell processes. Since the CLI UI is rendered using React Ink on the same event loop, these synchronous operations can briefly block rendering, resulting in input latency, dropped frames, and less responsive streaming output.

## Current Behavior

The temporary directory used for shell execution is created synchronously:

```ts
tempDir = fs.mkdtempSync(path.join(os.tmpdir(), 'gemini-shell-'));
```

Although this operation is typically fast, it can become noticeably slower on busy systems, network-mounted filesystems (e.g. WSL/NFS), or under heavy concurrent tool execution.

## Expected Behavior

Filesystem operations in the shell execution path should be non-blocking so the React Ink UI remains responsive during tool execution and streaming.

## Steps to Reproduce

1. Run multiple shell tool invocations in quick succession.
2. While commands are executing, type into the CLI input.
3. Observe occasional input lag or UI stuttering.

## Impact

- Reduced UI responsiveness during shell execution.
- Increased input latency while the agent is running commands.
- Brief interruptions in streamed terminal output.

## Suggested Solution

Replace synchronous filesystem operations in the shell execution path with their asynchronous equivalents.

A minimal implementation would:

- Replace `fs.mkdtempSync(...)` with `await fsPromises.mkdtemp(...)`.
- Audit the same execution path for other `*Sync` filesystem calls and replace them where appropriate.

Since `execute()` is already asynchronous, this change should integrate naturally without affecting behavior.

## Testing

- Verify all existing shell execution tests continue to pass.
- Add or update performance tests to ensure concurrent shell executions do not introduce unnecessary event loop blocking.
- Manually verify the CLI remains responsive while multiple shell commands are executing.

## Acceptance Criteria

- [ ] No synchronous filesystem operations remain in `shell.execute`.
- [ ] Existing functionality is preserved.
- [ ] CLI responsiveness is maintained during concurrent shell executions.
- [ ] All related tests pass.

Contributor guide

Open the contributing guide

Research direction

Start in packages/core/src/tools/shell.ts, inspect execute() and identify all synchronous filesystem calls in its shell-execution path. Review the related shell execution tests and packages/cli React Ink integration before changing the async flow. Done means no synchronous filesystem operations remain in shell.execute, existing behavior and tests are preserved, and concurrent commands do not block CLI responsiveness.

Written by the indexing model from the issue text.

Assessment

Tech stack
node.js, typescript
Domain
cli, performance
Issue type
Bug
Difficulty
3/5
Estimated time
1-2 days
Activity status
Active
Clarity
Mostly clear
Newbie friendliness
72/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.