Contributing to Gemini Desktop

April 27, 2026 · View on GitHub

First off, thank you for considering contributing to Gemini Desktop! 🎉 This guide walks you through setup, testing, code style, and the contribution workflow.

Quick summary: Use Node.js 20+, install dependencies with npm install, run the app with npm run electron:dev, and run the relevant tests before opening a PR.

Table of Contents


Welcome

We follow a simple code of conduct: be kind, be respectful, be helpful. If you’re unsure where to start, feel free to open an issue or a discussion.

Development Setup

Prerequisites

  • Node.js 20+ (CI uses Node 20)
  • npm 9+
  • Git

Getting Started

# Fork the repository on GitHub, then clone your fork
git clone https://github.com/<your-username>/gemini-desktop.git
cd gemini-desktop

# Install dependencies
npm install

# Start development mode
npm run electron:dev

Project Structure (high level)

src/main/      # Electron main process
src/renderer/  # React UI
src/preload/   # Secure preload bridge
src/shared/    # Shared types and constants
tests/         # Unit, coordinated, integration, and E2E tests

For a deeper architecture overview, see docs/ARCHITECTURE.md.

Available Scripts

All scripts below come from package.json and are the source of truth for contributing and CI workflows.

CategoryScriptDescription
Developmentnpm run devStart Vite dev server
Developmentnpm run previewPreview the Vite build
Developmentnpm run electron:devBuild Electron + run Vite + launch app
Buildnpm run buildType-check and build renderer (TypeScript + Vite)
Buildnpm run build:electronBuild Electron main/preload output
Buildnpm run electron:buildFull production build via electron-builder
Buildnpm run cleanRemove build artifacts
Releasenpm run dist:mac-x64Build macOS x64 release artifact
Releasenpm run dist:mac-arm64Build macOS ARM64 release artifact
Releasenpm run dist:winBuild Windows x64 release artifact
Releasenpm run dist:win-x64Build Windows x64 release artifact
Releasenpm run dist:win-arm64Build Windows ARM64 release artifact
Releasenpm run dist:linuxBuild Linux release artifact
Lint/Formatnpm run lintRun ESLint across the repo
Lint/Formatnpm run formatFormat files with Prettier
Docsnpm run docsGenerate TypeDoc docs
Testnpm run testRun unit tests (Vitest)
Testnpm run test:watchRun unit tests in watch mode
Testnpm run test:coverageRun unit tests with coverage
Testnpm run test:electronRun Electron unit tests
Testnpm run test:electron:coverageRun Electron unit tests with coverage
Testnpm run test:coordinatedRun coordinated multi-window tests
Testnpm run test:integrationRun integration tests (WDIO)
Testnpm run test:integration:watchRun integration tests in watch mode
Testnpm run test:e2eRun E2E tests sequentially
Testnpm run test:e2e:specRun a single E2E spec (WDIO)
Testnpm run test:e2e:group:startupRun E2E startup group
Testnpm run test:e2e:group:windowRun E2E window group
Testnpm run test:e2e:group:menuRun E2E menu group
Testnpm run test:e2e:group:hotkeysRun E2E hotkeys group
Testnpm run test:e2e:group:quickchatRun E2E quickchat group
Testnpm run test:e2e:group:optionsRun E2E options group
Testnpm run test:e2e:group:themeRun E2E theme group
Testnpm run test:e2e:group:authRun E2E auth group
Testnpm run test:e2e:group:trayRun E2E tray group
Testnpm run test:e2e:group:updateRun E2E update group
Testnpm run test:e2e:group:stabilityRun E2E stability group
Testnpm run test:e2e:group:toastRun E2E toast group
Testnpm run test:e2e:group:macosRun E2E macOS group
Testnpm run test:e2e:lifecycleRun E2E lifecycle tests
Testnpm run test:e2e:releaseRun E2E release tests
Testnpm run test:e2e:allRun all E2E tests (sequential + lifecycle)
Testnpm run test:allRun the full test suite
Metanpm run prepareInstall Husky hooks

Testing Guide

We use a five-tier testing strategy. Please run the relevant tier(s) before opening a PR.

Test Tiers

  1. Unit tests (Vitest)
  2. Electron unit tests (Vitest with Electron config)
  3. Coordinated tests (Vitest multi-window)
  4. Integration tests (WebdriverIO)
  5. End-to-end (E2E) tests (WebdriverIO)

How to Run Tests

# Unit tests
npm run test

# Electron unit tests
npm run test:electron

# Coordinated tests
npm run test:coordinated

# Integration tests
npm run test:integration

# E2E tests (sequential)
npm run test:e2e

# Full test suite
npm run test:all

Run a Single Test File

# Vitest single test file
npm run test -- tests/unit/shared/hotkeys.test.ts

# WDIO E2E single spec
npm run test:e2e:spec -- --spec=tests/e2e/auth.spec.ts

# WDIO integration single spec
npm run test:integration -- --spec=tests/integration/your-test.integration.test.ts

E2E References

ARM Linux / Headless Notes

If you’re running tests on headless ARM Linux, follow the runbook in docs/ARM_LINUX_TESTING.md.

Code Style & Linting

Prettier

Prettier is the formatter for this repository. Key settings (from .prettierrc):

  • tabWidth: 4
  • singleQuote: true
  • printWidth: 120
  • trailingComma: es5
  • semi: true

Run formatting across the repo:

npm run format

ESLint

ESLint is configured with @eslint/js, typescript-eslint, eslint-plugin-react, eslint-plugin-react-hooks, and eslint-plugin-react-refresh.

Notable rules:

  • @typescript-eslint/no-explicit-any is warn in source and off in tests.
  • @typescript-eslint/no-unused-vars is error (underscore-prefixed names are ignored).
  • react-hooks/exhaustive-deps is warn.
  • react-refresh/only-export-components is warn.

Run linting:

npm run lint

Import Order Convention

When writing TypeScript/React code, follow this order:

  1. React and third-party libraries
  2. Local components, contexts, and hooks
  3. Types and constants
  4. CSS/Styles

Pre-commit Hooks

We use Husky + lint-staged. On commit, Husky runs:

npx lint-staged

lint-staged runs this on staged files:

prettier --write --ignore-unknown

If the hook modifies files, re-stage them and commit again.

Commit Message Format

Use conventional commits so the history stays clean and readable:

feat: add zen mode toggle
fix: resolve tray icon not showing on Linux
docs: update installation instructions
test: add e2e tests for quick chat
refactor: simplify ipc handler wiring
chore: bump electron-builder

Common prefixes: feat:, fix:, docs:, test:, refactor:, chore:.

Contributing Workflow

  1. Fork the repo and create your branch from main.
  2. Install dependencies: npm install.
  3. Make your changes.
  4. Run relevant tests (see Testing Guide).
  5. Commit using the conventional format above.
  6. Push your branch and open a Pull Request targeting main.

PR Checklist (include in your description)

  • Tests pass for the areas you touched
  • npm run lint and npm run format are clean
  • Conventional commit message(s)
  • Clear description of what changed and why

Reporting Bugs

Open a new issue here: https://github.com/bwendell/gemini-desktop/issues/new

Please include:

  • OS + version (Windows/macOS/Linux distro)
  • Desktop environment + display server (Wayland/X11) when relevant
  • App version and package format (AppImage/RPM/DMG/EXE)
  • Steps to reproduce (numbered)
  • Expected behavior vs actual behavior
  • Console logs (View → Toggle DevTools → Console)
  • Terminal output if the app crashes on launch
  • Workarounds you already tried

Example of a great report: Issue #158.

Requesting Features

Open a new issue here: https://github.com/bwendell/gemini-desktop/issues/new

Please describe:

  • The problem you’re trying to solve
  • Why it matters for your workflow
  • Any alternatives you’ve considered

Additional Resources

Closing

Thanks again for contributing! If you get stuck, open a discussion or issue and we’ll help you out.

Return to the main project overview: README.md