.gemini/commands/strict-development-rules.md
These rules apply strictly to all code modifications and additions within the Gemini CLI project.
waitFor from
packages/cli/src/test-utils/async.ts instead of vi.waitFor for all
waitFor calls within packages/cli. NEVER use fixed waits (e.g.,
await delay(100)). Always use waitFor with a predicate to ensure tests are
stable and fast. Using the wrong waitFor can result in flaky tests and act
warnings.act to wrap all blocks in tests that change component
state. Use render or renderWithProviders from
packages/cli/src/test-utils/render.tsx instead of render from
ink-testing-library directly. This prevents spurious act warnings. If test
cases specify providers directly, consider whether the existing
renderWithProviders should be modified.toMatchSnapshot to verify that rendering works as
expected rather than matching against the raw content of the output. When
modifying snapshots, verify the changes are intentional and do not hide
underlying bugs.fs, os, child_process) ONLY at the top of
the file. Ideally, avoid mocking these dependencies altogether.vi.restoreAllMocks() in afterEach to prevent test pollution.vi.useFakeTimers() for tests involving time-based logic to avoid
flakiness.any in tests; prefer proper types or
unknown with narrowing.packages/cli)setState and Side Effects: NEVER trigger side effects from within the
body of a setState callback. Use a reducer or useRef if necessary. These
cases have historically introduced multiple bugs; typically, they should be
resolved using a reducer.ResizeObserver as needed.useKeyPress.ts from
the Gemini CLI package rather than the standard ink library. This library
supports reporting multiple keyboard events sequentially in the same React
frame (critical for slow terminals). Handling this correctly often requires
reducers to ensure multiple state updates are handled gracefully without
overriding values. Refer to text-buffer.ts for a canonical example.console.log, console.warn, or console.error in
the code.undefined rather than true as a default if the state is truly unknown).
Carefully manage useEffect dependencies. Prefer a reducer whenever
practical. NEVER disable react-hooks/exhaustive-deps; fix the code to
correctly declare dependencies instead.if statements where switch statements
could be used. Keep AppContainer minimal; refactor complex logic into React
hooks. Evaluate whether business logic should be added to hookSystem.ts or
integrated into packages/core rather than packages/cli.packages/core)initialize() methods). Services should be stateless where possible,
or use the centralized Storage service for persistence.coreEvents bus (from
packages/core/src/utils/events.ts) for asynchronous communication between
services or to notify the UI of state changes. Avoid tight coupling between
services.debugLogger from packages/core/src/utils/debugLogger.ts
for internal logging instead of console. Ensure all shell operations use
spawnAsync from packages/core/src/utils/shell-utils.ts for consistent
error handling and promise management. Handle filesystem errors gracefully
using isNodeError from packages/core/src/utils/errors.ts.packages/core/src/tools/ and
register them in packages/core/src/tools/tool-registry.ts. Export all new
public services, utilities, and types from packages/core/src/index.ts.packages/core.
packages/cli should ONLY contain UI/Ink components, command-line argument
parsing, and user interaction logic.ConfirmationBus or Output abstractions for communicating with the user
from Core.coreEvents. If a service imports another just to notify it of a change, use
an event instead.packages/cli/src/config/settingsSchema.ts. If a setting has
showInDialog: true, it MUST be documented in
docs/get-started/configuration.md. Ensure requiresRestart is correctly
set.debugLogger for rethrown errors to avoid duplicate logging.packages/cli/src/ui/key/keyBindings.ts and document them in
docs/cli/keyboard-shortcuts.md. Be careful of keybindings that require the
Meta key, as only certain meta key shortcuts are supported on Mac. Avoid
function keys and shortcuts commonly bound in VSCode.checkExhaustive in the default clause of switch statements to ensure
all cases are handled.!) unless absolutely necessary.any and unknown in both CLI and Core
packages. unknown is only allowed if it is immediately narrowed using type
guards or Zod validation.@typescript-eslint/no-floating-promises.KeypressContext.tsx and
terminalCapabilityManager.ts.ITERM_SESSION_ID may be present when users run
VSCode from within iTerm, even if the terminal is not iTerm.