Skip to content

Commit ef65498

Browse files
authored
Format strict-development-rules command (#19484)
1 parent 261788c commit ef65498

1 file changed

Lines changed: 116 additions & 38 deletions

File tree

Lines changed: 116 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -1,64 +1,142 @@
11
# Gemini CLI Strict Development Rules
22

3-
These rules apply strictly to all code modifications and additions within the Gemini CLI project.
3+
These rules apply strictly to all code modifications and additions within the
4+
Gemini CLI project.
45

56
## Testing Guidelines
67

7-
* **Async/Await**: Always use `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.
8-
* **React Testing**: Use `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.
9-
* **Snapshots**: Use `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.
10-
* **Parameterized Tests**: Use parameterized tests where it reduces duplicated lines. Give the parameters explicit types to ensure the tests are type-safe.
11-
* **Mocks Management**:
12-
* Mock critical dependencies (`fs`, `os`, `child_process`) ONLY at the top of the file. Ideally, avoid mocking these dependencies altogether.
13-
* Reuse existing mocks and fakes rather than creating new ones.
14-
* Avoid mocking the file system whenever possible. If using the real file system is too difficult, consider writing an integration test instead.
15-
* Always call `vi.restoreAllMocks()` in `afterEach` to prevent test pollution.
16-
* Use `vi.useFakeTimers()` for tests involving time-based logic to avoid flakiness.
17-
* **Typing in Tests**: Avoid using `any` in tests; prefer proper types or `unknown` with narrowing.
8+
- **Async/Await**: Always use `waitFor` from
9+
`packages/cli/src/test-utils/async.ts` instead of `vi.waitFor` for all
10+
`waitFor` calls within `packages/cli`. NEVER use fixed waits (e.g.,
11+
`await delay(100)`). Always use `waitFor` with a predicate to ensure tests are
12+
stable and fast. Using the wrong `waitFor` can result in flaky tests and `act`
13+
warnings.
14+
- **React Testing**: Use `act` to wrap all blocks in tests that change component
15+
state. Use `render` or `renderWithProviders` from
16+
`packages/cli/src/test-utils/render.tsx` instead of `render` from
17+
`ink-testing-library` directly. This prevents spurious `act` warnings. If test
18+
cases specify providers directly, consider whether the existing
19+
`renderWithProviders` should be modified.
20+
- **Snapshots**: Use `toMatchSnapshot` to verify that rendering works as
21+
expected rather than matching against the raw content of the output. When
22+
modifying snapshots, verify the changes are intentional and do not hide
23+
underlying bugs.
24+
- **Parameterized Tests**: Use parameterized tests where it reduces duplicated
25+
lines. Give the parameters explicit types to ensure the tests are type-safe.
26+
- **Mocks Management**:
27+
- Mock critical dependencies (`fs`, `os`, `child_process`) ONLY at the top of
28+
the file. Ideally, avoid mocking these dependencies altogether.
29+
- Reuse existing mocks and fakes rather than creating new ones.
30+
- Avoid mocking the file system whenever possible. If using the real file
31+
system is too difficult, consider writing an integration test instead.
32+
- Always call `vi.restoreAllMocks()` in `afterEach` to prevent test pollution.
33+
- Use `vi.useFakeTimers()` for tests involving time-based logic to avoid
34+
flakiness.
35+
- **Typing in Tests**: Avoid using `any` in tests; prefer proper types or
36+
`unknown` with narrowing.
1837

1938
## React Guidelines (`packages/cli`)
2039

21-
* **`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.
22-
* **Rendering**: Do not introduce infinite rendering loops. Avoid synchronous file I/O in React components as it will hang the UI. Do not implement new logic for custom string measurement or string truncation. Use Ink layout instead, leveraging `ResizeObserver` as needed.
23-
* **Keyboard Handling**: Keyboard handling MUST go through `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.
24-
* **Logging**: Do not leave `console.log`, `console.warn`, or `console.error` in the code.
25-
* **State & Effects**: Ensure state initialization is explicit (e.g., use `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.
26-
* **Context & Props**: Avoid excessive property drilling. Leverage existing providers, extend them, or propose a new one if necessary. Only use providers for properties that are consistent across the entire application.
27-
* **Code Structure**: Avoid complex `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`.
40+
- **`setState` and Side Effects**: NEVER trigger side effects from within the
41+
body of a `setState` callback. Use a reducer or `useRef` if necessary. These
42+
cases have historically introduced multiple bugs; typically, they should be
43+
resolved using a reducer.
44+
- **Rendering**: Do not introduce infinite rendering loops. Avoid synchronous
45+
file I/O in React components as it will hang the UI. Do not implement new
46+
logic for custom string measurement or string truncation. Use Ink layout
47+
instead, leveraging `ResizeObserver` as needed.
48+
- **Keyboard Handling**: Keyboard handling MUST go through `useKeyPress.ts` from
49+
the Gemini CLI package rather than the standard ink library. This library
50+
supports reporting multiple keyboard events sequentially in the same React
51+
frame (critical for slow terminals). Handling this correctly often requires
52+
reducers to ensure multiple state updates are handled gracefully without
53+
overriding values. Refer to `text-buffer.ts` for a canonical example.
54+
- **Logging**: Do not leave `console.log`, `console.warn`, or `console.error` in
55+
the code.
56+
- **State & Effects**: Ensure state initialization is explicit (e.g., use
57+
`undefined` rather than `true` as a default if the state is truly unknown).
58+
Carefully manage `useEffect` dependencies. Prefer a reducer whenever
59+
practical. NEVER disable `react-hooks/exhaustive-deps`; fix the code to
60+
correctly declare dependencies instead.
61+
- **Context & Props**: Avoid excessive property drilling. Leverage existing
62+
providers, extend them, or propose a new one if necessary. Only use providers
63+
for properties that are consistent across the entire application.
64+
- **Code Structure**: Avoid complex `if` statements where `switch` statements
65+
could be used. Keep `AppContainer` minimal; refactor complex logic into React
66+
hooks. Evaluate whether business logic should be added to `hookSystem.ts` or
67+
integrated into `packages/core` rather than `packages/cli`.
2868

2969
## Core Guidelines (`packages/core`)
3070

31-
* **Services**: Implement services as classes with clear lifecycle management (e.g., `initialize()` methods). Services should be stateless where possible, or use the centralized `Storage` service for persistence.
32-
* **Cross-Service Communication**: Prefer using the `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.
33-
* **Utilities**: Use `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`.
34-
* **Exports & Tooling**: Add new tools to `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`.
71+
- **Services**: Implement services as classes with clear lifecycle management
72+
(e.g., `initialize()` methods). Services should be stateless where possible,
73+
or use the centralized `Storage` service for persistence.
74+
- **Cross-Service Communication**: Prefer using the `coreEvents` bus (from
75+
`packages/core/src/utils/events.ts`) for asynchronous communication between
76+
services or to notify the UI of state changes. Avoid tight coupling between
77+
services.
78+
- **Utilities**: Use `debugLogger` from `packages/core/src/utils/debugLogger.ts`
79+
for internal logging instead of `console`. Ensure all shell operations use
80+
`spawnAsync` from `packages/core/src/utils/shell-utils.ts` for consistent
81+
error handling and promise management. Handle filesystem errors gracefully
82+
using `isNodeError` from `packages/core/src/utils/errors.ts`.
83+
- **Exports & Tooling**: Add new tools to `packages/core/src/tools/` and
84+
register them in `packages/core/src/tools/tool-registry.ts`. Export all new
85+
public services, utilities, and types from `packages/core/src/index.ts`.
3586

3687
## Architectural Audit (Package Boundaries)
3788

38-
* **Logic Placement**: Non-UI logic (e.g., model orchestration, tool implementation, git/filesystem operations) MUST reside in `packages/core`. `packages/cli` should ONLY contain UI/Ink components, command-line argument parsing, and user interaction logic.
39-
* **Environment Isolation**: Core logic must not assume a TUI environment. Use the `ConfirmationBus` or `Output` abstractions for communicating with the user from Core.
40-
* **Decoupling**: Actively look for opportunities to decouple services using `coreEvents`. If a service imports another just to notify it of a change, use an event instead.
89+
- **Logic Placement**: Non-UI logic (e.g., model orchestration, tool
90+
implementation, git/filesystem operations) MUST reside in `packages/core`.
91+
`packages/cli` should ONLY contain UI/Ink components, command-line argument
92+
parsing, and user interaction logic.
93+
- **Environment Isolation**: Core logic must not assume a TUI environment. Use
94+
the `ConfirmationBus` or `Output` abstractions for communicating with the user
95+
from Core.
96+
- **Decoupling**: Actively look for opportunities to decouple services using
97+
`coreEvents`. If a service imports another just to notify it of a change, use
98+
an event instead.
4199

42100
## General Gemini CLI Design Principles
43101

44-
* **Settings**: Use settings for user-configurable options rather than adding new command line arguments. Add new settings to `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.
45-
* **Logging**: Use `debugLogger` for rethrown errors to avoid duplicate logging.
46-
* **Keyboard Shortcuts**: Define all new keyboard shortcuts in `packages/cli/src/config/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.
102+
- **Settings**: Use settings for user-configurable options rather than adding
103+
new command line arguments. Add new settings to
104+
`packages/cli/src/config/settingsSchema.ts`. If a setting has
105+
`showInDialog: true`, it MUST be documented in
106+
`docs/get-started/configuration.md`. Ensure `requiresRestart` is correctly
107+
set.
108+
- **Logging**: Use `debugLogger` for rethrown errors to avoid duplicate logging.
109+
- **Keyboard Shortcuts**: Define all new keyboard shortcuts in
110+
`packages/cli/src/config/keyBindings.ts` and document them in
111+
`docs/cli/keyboard-shortcuts.md`. Be careful of keybindings that require the
112+
`Meta` key, as only certain meta key shortcuts are supported on Mac. Avoid
113+
function keys and shortcuts commonly bound in VSCode.
47114

48115
## TypeScript Best Practices
49116

50-
* Use `checkExhaustive` in the `default` clause of `switch` statements to ensure all cases are handled.
51-
* Avoid using the non-null assertion operator (`!`) unless absolutely necessary.
52-
* **STRICT TYPING**: Strictly forbid `any` and `unknown` in both CLI and Core packages. `unknown` is only allowed if it is immediately narrowed using type guards or Zod validation.
53-
* NEVER disable `@typescript-eslint/no-floating-promises`.
54-
* Avoid making types nullable unless strictly necessary, as it hurts readability.
117+
- Use `checkExhaustive` in the `default` clause of `switch` statements to ensure
118+
all cases are handled.
119+
- Avoid using the non-null assertion operator (`!`) unless absolutely necessary.
120+
- **STRICT TYPING**: Strictly forbid `any` and `unknown` in both CLI and Core
121+
packages. `unknown` is only allowed if it is immediately narrowed using type
122+
guards or Zod validation.
123+
- NEVER disable `@typescript-eslint/no-floating-promises`.
124+
- Avoid making types nullable unless strictly necessary, as it hurts
125+
readability.
55126

56127
## TUI Best Practices
57128

58-
* **Terminal Compatibility**: Consider how changes might behave differently across terminals (e.g., VSCode terminal, SSH, Kitty, default Mac terminal, iTerm2, Windows terminal). If modifying keyboard handling, integrate deeply with existing files like `KeypressContext.tsx` and `terminalCapabilityManager.ts`.
59-
* **iTerm**: Be aware that `ITERM_SESSION_ID` may be present when users run VSCode from within iTerm, even if the terminal is not iTerm.
129+
- **Terminal Compatibility**: Consider how changes might behave differently
130+
across terminals (e.g., VSCode terminal, SSH, Kitty, default Mac terminal,
131+
iTerm2, Windows terminal). If modifying keyboard handling, integrate deeply
132+
with existing files like `KeypressContext.tsx` and
133+
`terminalCapabilityManager.ts`.
134+
- **iTerm**: Be aware that `ITERM_SESSION_ID` may be present when users run
135+
VSCode from within iTerm, even if the terminal is not iTerm.
60136

61137
## Code Cleanup
62138

63-
* **Refactoring**: Actively clean up code duplication, technical debt, and boilerplate ("AI Slop") when working in the codebase.
64-
* **Prompts**: Be aware that changes can impact the prompts sent to Gemini CLI and affect overall quality.
139+
- **Refactoring**: Actively clean up code duplication, technical debt, and
140+
boilerplate ("AI Slop") when working in the codebase.
141+
- **Prompts**: Be aware that changes can impact the prompts sent to Gemini CLI
142+
and affect overall quality.

0 commit comments

Comments
 (0)