# Contributor handoff — google-gemini/gemini-cli

> Canonical page: https://codevetter.com/unpack/gemini-cli/agent-handoff

# Contributor handoff — google-gemini/gemini-cli

Scanned commit d5b3e3accb26000d273abf16e0f1dd83aa5428a9 (2026-09-21). Generated by codevetter codevetter 1.12.0 on 2026-09-22.

An agent editing this repo should treat packages/core and packages/cli as separate layers (core must not import cli), keep the Config god-object edits minimal, route all tool gating through the PolicyEngine/MessageBus rather than ad-hoc checks, and always run the colocated vitest file plus typecheck before considering a change done. Build is `npm run bundle` (esbuild → bundle/gemini.js); quick dev loop is `npm run start` / `npm start -- -p '...'` after build. Conventions: ESM with .js import specifiers for .ts files, Apache license header enforced by eslint, debugLogger instead of console.*, proper-lockfile/proper JSONL append for session files. Traps: two-process relaunch means env changes need GEMINI_CLI_NO_RELAUNCH=1 to debug the real process; posttest triggers a full build; Ink is a forked package via npm overrides.
- Read-first files for any agentic-loop change: packages/core/src/core/client.ts (GeminiClient), turn.ts (event types Turn/GeminiEventType), geminiChat.ts (stream+retry), scheduler/scheduler.ts (tool execution), config/config.ts (wiring). CLI-side entry: packages/cli/index.ts then src/gemini.tsx main(). — [packages/core/src/core/client.ts](https://github.com/google-gemini/gemini-cli/blob/d5b3e3accb26000d273abf16e0f1dd83aa5428a9/packages/core/src/core/client.ts) [packages/core/src/core/turn.ts](https://github.com/google-gemini/gemini-cli/blob/d5b3e3accb26000d273abf16e0f1dd83aa5428a9/packages/core/src/core/turn.ts) [packages/core/src/scheduler/scheduler.ts](https://github.com/google-gemini/gemini-cli/blob/d5b3e3accb26000d273abf16e0f1dd83aa5428a9/packages/core/src/scheduler/scheduler.ts) [packages/cli/src/gemini.tsx](https://github.com/google-gemini/gemini-cli/blob/d5b3e3accb26000d273abf16e0f1dd83aa5428a9/packages/cli/src/gemini.tsx)
- Build/dev commands: `npm run bundle` produces bundle/gemini.js (esbuild, includes generated git commit info and devtools bundle); `npm run start` runs scripts/start.js with NODE_ENV=development; `npm run build` builds packages only. — [package.json#L20-47](https://github.com/google-gemini/gemini-cli/blob/d5b3e3accb26000d273abf16e0f1dd83aa5428a9/package.json#L20-L47) [esbuild.config.js](https://github.com/google-gemini/gemini-cli/blob/d5b3e3accb26000d273abf16e0f1dd83aa5428a9/esbuild.config.js) [scripts/start.js](https://github.com/google-gemini/gemini-cli/blob/d5b3e3accb26000d273abf16e0f1dd83aa5428a9/scripts/start.js) [scripts/build.js](https://github.com/google-gemini/gemini-cli/blob/d5b3e3accb26000d273abf16e0f1dd83aa5428a9/scripts/build.js)
- Test commands: `npm run test:ci --workspace @google/gemini-cli-core` for core unit tests; `npm run test:integration:sandbox:none` for e2e without sandbox; `npm run typecheck` across workspaces; `npm run preflight` = clean+ci+format+build+lint+typecheck+test:ci (slow, full gate). — [package.json#L48-72](https://github.com/google-gemini/gemini-cli/blob/d5b3e3accb26000d273abf16e0f1dd83aa5428a9/package.json#L48-L72) [.github/workflows/ci.yml#L188-194](https://github.com/google-gemini/gemini-cli/blob/d5b3e3accb26000d273abf16e0f1dd83aa5428a9/.github/workflows/ci.yml#L188-L194) [CONTRIBUTING.md](https://github.com/google-gemini/gemini-cli/blob/d5b3e3accb26000d273abf16e0f1dd83aa5428a9/CONTRIBUTING.md)
- Imports must use ESM `.js` specifiers referencing the compiled names (e.g. './utils/cleanup.js'), the repo is "type":"module" everywhere, and every file needs the SPDX Apache header enforced by eslint-plugin-headers. — [package.json#L7](https://github.com/google-gemini/gemini-cli/blob/d5b3e3accb26000d273abf16e0f1dd83aa5428a9/package.json#L7) [packages/cli/src/gemini.tsx#L43-101](https://github.com/google-gemini/gemini-cli/blob/d5b3e3accb26000d273abf16e0f1dd83aa5428a9/packages/cli/src/gemini.tsx#L43-L101) [package.json#L126](https://github.com/google-gemini/gemini-cli/blob/d5b3e3accb26000d273abf16e0f1dd83aa5428a9/package.json#L126)
- Logging convention: never use console.log/console.error in library paths — ConsolePatcher intercepts them; use debugLogger (debug/error/warn) for diagnostics and coreEvents.emitFeedback for user-facing messages so headless JSON output stays clean. — [packages/cli/src/ui/utils/ConsolePatcher.ts](https://github.com/google-gemini/gemini-cli/blob/d5b3e3accb26000d273abf16e0f1dd83aa5428a9/packages/cli/src/ui/utils/ConsolePatcher.ts) [packages/cli/src/gemini.tsx#L583-592](https://github.com/google-gemini/gemini-cli/blob/d5b3e3accb26000d273abf16e0f1dd83aa5428a9/packages/cli/src/gemini.tsx#L583-L592) [packages/core/src/utils/events.ts](https://github.com/google-gemini/gemini-cli/blob/d5b3e3accb26000d273abf16e0f1dd83aa5428a9/packages/core/src/utils/events.ts)
- Tool-approval changes must go through the PolicyEngine + MessageBus confirmation flow (checkPolicy → resolveConfirmation → MessageBusType.ToolConfirmationRequest); bypassing it (e.g. auto-executing in a new tool) defeats --approval-mode/--yolo/plan-mode semantics and enterprise admin policies. — [packages/core/src/scheduler/scheduler.ts#L10-13](https://github.com/google-gemini/gemini-cli/blob/d5b3e3accb26000d273abf16e0f1dd83aa5428a9/packages/core/src/scheduler/scheduler.ts#L10-L13) [packages/core/src/scheduler/policy.ts](https://github.com/google-gemini/gemini-cli/blob/d5b3e3accb26000d273abf16e0f1dd83aa5428a9/packages/core/src/scheduler/policy.ts) [packages/core/src/confirmation-bus/types.ts](https://github.com/google-gemini/gemini-cli/blob/d5b3e3accb26000d273abf16e0f1dd83aa5428a9/packages/core/src/confirmation-bus/types.ts) [packages/core/src/policy/policy-engine.ts](https://github.com/google-gemini/gemini-cli/blob/d5b3e3accb26000d273abf16e0f1dd83aa5428a9/packages/core/src/policy/policy-engine.ts)
- Safe edit boundaries: new tools go in packages/core/src/tools/ + registration in config.ts createToolRegistry; new slash commands in packages/cli/src/ui/commands/ + BuiltinCommandLoader; new settings keys in settingsSchema.ts (docs regenerated via npm run docs:settings, which CI verifies with --check). — [packages/core/src/config/config.ts#L3966-4087](https://github.com/google-gemini/gemini-cli/blob/d5b3e3accb26000d273abf16e0f1dd83aa5428a9/packages/core/src/config/config.ts#L3966-L4087) [packages/cli/src/services/BuiltinCommandLoader.ts#L123-240](https://github.com/google-gemini/gemini-cli/blob/d5b3e3accb26000d273abf16e0f1dd83aa5428a9/packages/cli/src/services/BuiltinCommandLoader.ts#L123-L240) [packages/cli/src/config/settingsSchema.ts](https://github.com/google-gemini/gemini-cli/blob/d5b3e3accb26000d273abf16e0f1dd83aa5428a9/packages/cli/src/config/settingsSchema.ts) [package.json#L32-34](https://github.com/google-gemini/gemini-cli/blob/d5b3e3accb26000d273abf16e0f1dd83aa5428a9/package.json#L32-L34) [.github/workflows/ci.yml#L116-119](https://github.com/google-gemini/gemini-cli/blob/d5b3e3accb26000d273abf16e0f1dd83aa5428a9/.github/workflows/ci.yml#L116-L119)
- Debugging trap: the CLI double-forks — the visible process is a thin parent; to debug or test the real logic run with GEMINI_CLI_NO_RELAUNCH=1 (or `npm run debug` which uses --inspect-brk), otherwise breakpoints attach to the wrong process and stdin/stdio patching differs. — [packages/cli/index.ts#L54-56](https://github.com/google-gemini/gemini-cli/blob/d5b3e3accb26000d273abf16e0f1dd83aa5428a9/packages/cli/index.ts#L54-L56) [packages/cli/src/gemini.tsx#L138-140](https://github.com/google-gemini/gemini-cli/blob/d5b3e3accb26000d273abf16e0f1dd83aa5428a9/packages/cli/src/gemini.tsx#L138-L140) [package.json#L23](https://github.com/google-gemini/gemini-cli/blob/d5b3e3accb26000d273abf16e0f1dd83aa5428a9/package.json#L23)
- Trap: `npm test` at the root runs a build afterwards (posttest → npm run build) and the prepare script runs `husky && npm run bundle`, so npm install/test are not side-effect-free; the package-lock is guarded by check:lockfile in CI. — [package.json#L52](https://github.com/google-gemini/gemini-cli/blob/d5b3e3accb26000d273abf16e0f1dd83aa5428a9/package.json#L52) [package.json#L73](https://github.com/google-gemini/gemini-cli/blob/d5b3e3accb26000d273abf16e0f1dd83aa5428a9/package.json#L73) [package.json#L77](https://github.com/google-gemini/gemini-cli/blob/d5b3e3accb26000d273abf16e0f1dd83aa5428a9/package.json#L77) [.github/workflows/ci.yml#L89](https://github.com/google-gemini/gemini-cli/blob/d5b3e3accb26000d273abf16e0f1dd83aa5428a9/.github/workflows/ci.yml#L89)
- Layering rule: packages/cli depends on @google/gemini-cli-core (file:../core) and everything cross-layer is exported through packages/core/src/index.ts; a2a-server and sdk also consume core only through that barrel — new core APIs must be re-exported there to be usable. — [packages/cli/package.json#L34](https://github.com/google-gemini/gemini-cli/blob/d5b3e3accb26000d273abf16e0f1dd83aa5428a9/packages/cli/package.json#L34) [packages/core/src/index.ts](https://github.com/google-gemini/gemini-cli/blob/d5b3e3accb26000d273abf16e0f1dd83aa5428a9/packages/core/src/index.ts) [packages/a2a-server/src/http/app.ts#L29-35](https://github.com/google-gemini/gemini-cli/blob/d5b3e3accb26000d273abf16e0f1dd83aa5428a9/packages/a2a-server/src/http/app.ts#L29-L35) [packages/sdk/package.json](https://github.com/google-gemini/gemini-cli/blob/d5b3e3accb26000d273abf16e0f1dd83aa5428a9/packages/sdk/package.json)
- Ink is pinned to a fork (@jrichman/ink@6.6.9) via npm overrides with wrap-ansi/cliui pinned too — do not upgrade ink casually; TUI tests rely on the fork's behavior (react-devtools-core in devDeps). — [package.json#L81-86](https://github.com/google-gemini/gemini-cli/blob/d5b3e3accb26000d273abf16e0f1dd83aa5428a9/package.json#L81-L86) [package.json#L143](https://github.com/google-gemini/gemini-cli/blob/d5b3e3accb26000d273abf16e0f1dd83aa5428a9/package.json#L143)
- Session transcript writes must remain append-only JSONL with proper record shapes (MessageRecord/$set/$rewindTo/$partial metadata guards in chatRecordingService); --resume and rewind depend on parsing these exact line types. — [packages/core/src/services/chatRecordingService.ts#L76-98](https://github.com/google-gemini/gemini-cli/blob/d5b3e3accb26000d273abf16e0f1dd83aa5428a9/packages/core/src/services/chatRecordingService.ts#L76-L98) [packages/cli/src/gemini.tsx#L336-407](https://github.com/google-gemini/gemini-cli/blob/d5b3e3accb26000d273abf16e0f1dd83aa5428a9/packages/cli/src/gemini.tsx#L336-L407)
- Enterprise/admin settings arrive via parent→child IPC and CCPA fetch in refreshAuth; features must consult admin flags (e.g. getAdminBlockedMcpServersMessage, adminSkillsEnabled, applyAdminAllowlist) rather than only user settings, or enterprise controls are bypassed. — [packages/cli/src/gemini.tsx#L669-679](https://github.com/google-gemini/gemini-cli/blob/d5b3e3accb26000d273abf16e0f1dd83aa5428a9/packages/cli/src/gemini.tsx#L669-L679) [packages/cli/src/config/extension-manager.ts#L55-56](https://github.com/google-gemini/gemini-cli/blob/d5b3e3accb26000d273abf16e0f1dd83aa5428a9/packages/cli/src/config/extension-manager.ts#L55-L56) [packages/core/src/config/config.ts#L1534-1550](https://github.com/google-gemini/gemini-cli/blob/d5b3e3accb26000d273abf16e0f1dd83aa5428a9/packages/core/src/config/config.ts#L1534-L1550) [docs/admin/enterprise-controls.md](https://github.com/google-gemini/gemini-cli/blob/d5b3e3accb26000d273abf16e0f1dd83aa5428a9/docs/admin/enterprise-controls.md)

Every claim links to its cited files at the pinned commit. Citations identify source evidence; they do not establish runtime correctness. Independent CodeVetter scan — not reviewed by upstream maintainers.

## Public product links

- [CodeVetter](https://codevetter.com/)
- [Download](https://codevetter.com/download)
- [Documentation](https://codevetter.com/docs/)
- [Source](https://github.com/Codevetter/codevetter)
