# AGENTS.md This file provides guidance to AI coding agents when working with code in this repository. ## Project Overview Lepton is a lean code snippet manager powered by GitHub Gist, built with Electron, React, and Redux. It provides a desktop application for managing and organizing code snippets with features like unlimited public/secret snippets, tagging, markdown/Jupyter notebook support, and GitHub Enterprise integration. ## Tech Stack - **Framework**: Electron (desktop app) - **Frontend**: React 19 + Redux (with Redux Thunk for async actions) - **Build System**: Webpack + Babel (ES6 transpilation) - **Styling**: Sass/SCSS - **Code Editor**: CodeMirror (via react-codemirror) - **Testing/Linting**: Vitest, Electron smoke tests, ESLint with Standard config - **Dependencies**: Uses npm package manager ## Key Commands ### Runtime Use Node.js 24 LTS for local development, preferably the version in `.nvmrc`: ```bash nvm install nvm use ``` The project uses npm 11.x. This is the host runtime for dependency installation and webpack builds; Electron's bundled app runtime is controlled separately by the Electron version in `package.json`. On Apple Silicon, use the native arm64 Node.js runtime: ```bash npm ci npm run build npm start ``` ### Development ```bash # Install dependencies npm ci # Development build and run npm run build && npm start # Watch mode for development npm run webpack-watch # Production build npm run webpack-prod ``` ### Building & Distribution ```bash # Create installer for current platform npm run dist # Platform-specific builds npm run dist -- -m # macOS npm run dist -- -w # Windows npm run dist -- -l # Linux (requires Docker for snap) npm run dist -- -wml # All platforms ``` ### Code Quality ```bash # Lint code npm run lint # Normal local check: Vitest unit tests plus webpack development build npm test # Unit tests only npm run test:unit # Unit tests in watch mode npm run test:unit:watch # Webpack build verification only npm run test:build # Check for outdated dependencies npm run check-outdated # Pre-version checks (runs lint + test + outdated check) npm run preversion ``` ### Testing The `npm test` command runs Vitest unit tests and webpack development build verification. Use it for normal local validation before committing code changes. Electron smoke checks are available for UI/runtime-sensitive changes: ```bash # Renderer smoke: login screens plus fixture-backed authenticated surfaces npm run test:smoke # Packaged app smoke: builds an unpacked app and verifies packaged login render npm run test:packaged-smoke ``` `npm run test:smoke` uses isolated config/user-data directories. It verifies the login UI and render fixtures such as active layout, edit/new modals, about/settings, dashboard, search, delete confirmation, raw modal, pinned tags, and immersive view. Fixture smoke verifies initial rendering, preload bridge availability, renderer isolation, visible dimensions, screenshots, and absence of renderer warnings/errors/crashes. Fixture smoke does not validate GitHub OAuth, Gist CRUD, sync behavior, real API responses, OS shortcut delivery, or full interaction flows. Use manual verification for those. ### Rendering Verification For any Electron, React, layout, CSS, webpack, or dependency change that could affect the UI, always verify actual rendering before considering the work complete: ```bash npm run build npm start ``` Confirm more than process startup. The app must visibly render the Lepton UI, not just log `updateUserSession ACTIVE`. Always capture a screenshot of the running app and show that screenshot in the chat when reporting rendering verification. If the window is blank or suspicious, inspect the renderer with Electron DevTools or a remote debugging port and verify DOM layout, visible text, and the renderer screenshot. Before relaunching, check for and stop duplicate Lepton/Electron instances so stale blank windows do not mask the current result. For render-only confidence on authenticated surfaces, use the fixture smoke path when appropriate: ```bash npm run build LEPTON_RENDER_FIXTURE=active npm start ``` Supported fixture names are `active`, `edit`, `new`, `about`, `dashboard`, `search`, `delete`, `raw`, `pinned-tags`, and `immersive`. Fixture rendering is acceptable for checking React/Electron render regressions without login. It is not enough for changes touching GitHub authentication, backend sync, request construction, shortcut delivery, or save/delete flows; those require manual logged-in verification against GitHub/Gist behavior. Document rendering verification in PR descriptions, including whether the app was launched locally and what was observed. ## Architecture ### Application Structure - `/app` - Main React application source - `/containers` - React container components (connected to Redux) - `/reducers` - Redux reducers for state management - `/actions` - Redux action creators - `/utilities` - Shared utilities (GitHub API, parser, search, etc.) - `/configs` - Configuration files including GitHub OAuth credentials - `/main.js` - Electron main process entry point - `/bundle` - Webpack build output directory ### Key Components - **GitHub API Integration**: `/app/utilities/githubApi/` - handles Gist CRUD operations - **Theme Management**: `/app/utilities/themeManager/` - light/dark theme switching - **Code Rendering**: Uses CodeMirror for syntax highlighting and editing - **Search**: `/app/utilities/search/` - snippet metadata and downloaded-content search functionality - **Configuration**: Uses nconf for config management, stored in `~/.leptonrc` - **Preload Bridge**: `/preload.js` exposes the limited renderer API as `window.lepton` ### Search Development Notes Search records are built through `/app/utilities/search/records.js`. Use the shared builder when sync, create, edit, fixture rendering, or lazy single-gist fetches need to refresh indexed gist data. Search currently performs exact, case-insensitive token matching across metadata and any downloaded file content; do not reintroduce fuzzy matching without updating tests and UI expectations. Complete global content search depends on `snippet.downloadAll` being enabled before sync so every snippet's details and file contents are downloaded. When `downloadAll` is disabled, content search can only cover snippets whose details have already been loaded locally. ### GitHub OAuth Setup The app requires GitHub OAuth credentials in `/configs/account.js`: ```js module.exports = { client_id: '', client_secret: '' } ``` Register your application at https://github.com/settings/applications/new ## Development Notes - **Electron Version**: Uses Electron 42.x. Renderer windows are sandboxed and context-isolated. - **Renderer Bridge**: Renderer code must use the `window.lepton` preload API. Do not access Node globals directly from renderer code. - **React Version**: Uses React 19 with `createRoot`; do not use legacy React root APIs. - **Node Version**: Use Node.js 24 LTS for local development. - **ES6 Support**: Babel transpiles application source for the Electron renderer. - **Hot Reloading**: Use `npm run webpack-watch` for auto-rebuilding during development - **Styling**: Uses Sass with component-level SCSS files - **State Management**: Redux store handles application state, actions use Redux Thunk for async operations - **Shortcuts**: Customizable keyboard shortcuts defined in config, registered via electron-localshortcut - **Packaged Runtime Files**: `electron-builder.js` allowlists the main-process runtime files shipped in packaged apps. When `main.js`, `preload.js`, or another packaged runtime file starts requiring a new local helper, add that helper path to `mainRuntimeAppFiles` in `electron-builder.js` and update `tests/configs/electronBuilder.test.js`. - **Locales/i18n**: Adding a UI locale is not just a renderer code change. Update the locale catalog and package configuration together so packaged Electron builds keep the right Chromium locale resources. ### Adding A Locale When adding a new interface locale: 1. Add `app/utilities/i18n/locales/.js`, using `en.js` as the source-of-truth key shape. 2. Update `app/utilities/i18n/index.js` to import the catalog, add it to `catalogs`, and add the display label to `supportedLocales`. 3. Update `tests/utilities/i18n.test.js` so the new catalog is included in shape/translation coverage and, when useful, has a focused behavior assertion. 4. Update user-facing supported-locale lists in `README.md` and `wiki/configuration.md`. 5. Update `configs/electronLanguages.js` if the new Lepton locale needs a different Electron/Chromium resource name in packaged apps. `electron-builder.js` derives the packaged locale list from `getSupportedLocales()`, so do not add a separate hard-coded list to `package.json`. 6. Validate with `npm run test:unit` and `npm run test:packaged-smoke`. For packaged-smoke, confirm the packaged app contains every supported Electron locale and no intentionally unsupported locales. On macOS, inspect both: - `dist/mac-arm64/Lepton.app/Contents/Frameworks/Electron Framework.framework/Versions/A/Resources/*.lproj` - `dist/mac-arm64/Lepton.app/Contents/Resources/*.lproj` ## Configuration The app uses a hierarchical configuration system: 1. Default config in `/configs/defaultConfig.js` 2. User config in `~/.leptonrc` (JSON format) 3. Environment variables and command line args Key configuration areas include theme, shortcuts, proxy settings, editor preferences, and GitHub Enterprise support. ## Important Guidelines When working with this codebase: - **NEVER modify `node_modules/`** - this directory contains installed dependencies and should not be edited - **DO NOT commit `package-lock.json` churn** unless specifically updating dependencies - this file locks dependency versions - **DO NOT change LICENSE files** unless told - **DO NOT commit `license.json` path-only churn** - `npm run build` regenerates local absolute paths - Focus code changes on the `/app` directory, `/configs`, `main.js`, and configuration files - Avoid searching or reading files in `node_modules/`, `/bundle`, `/build`, `/dist` directories unless absolutely necessary - Avoid bypassing the global logger for auth-related values; logger methods automatically redact known token and secret patterns - When adding new files used by the Electron main process at packaged-app startup, update `electron-builder.js` so packaged builds include them; otherwise `npm run test:packaged-smoke` can fail even when dev builds work. - Do not reintroduce `@electron/remote`, `nodeIntegration`, renderer `require`, or renderer `process` access. Add preload bridge methods instead. - Do not reintroduce Redux Form or other React 19-incompatible form patterns. - Do not use `ReactDOM.render`; use the existing React 19 root setup.