Thanks for your interest in contributing!
Note: SproutGit is an early prototype under active development. This is a great time to shape the direction of the project.
- Node.js ≥ 22
- pnpm v11 (
npm install -g pnpm) - Git ≥ 2.36 (worktree support required)
# 1. Fork and clone
git clone https://github.com/your-fork/sproutgit.git
cd sproutgit
# 2. Install dependencies (all packages in the monorepo)
pnpm install
# 3. Start the app in dev mode with hot-reload
pnpm devpnpm dev # Start Electron app with hot-reload (electron-vite)
pnpm build # Production build → app/dist-electron/
pnpm typecheck # TypeScript typecheck across all packages
pnpm lint # oxlint
pnpm test # Unit tests (Vitest)
pnpm test:e2e # WebdriverIO E2E tests (requires a production build first)app/ ← Electron app (main process + renderer + preload)
packages/
types/ ← Shared TypeScript types + all IPC channel constants
git/ ← simple-git wrapper — all Git operations live here
database/ ← Drizzle ORM + node:sqlite — config DB and workspace DB
terminal/ ← node-pty wrapper
ui/ ← Shared React components
providers/github/ ← GitHub provider integration (OAuth, repo listing)
e2e/ ← WebdriverIO end-to-end tests
website/ ← Astro marketing site
old/ ← Legacy Tauri/SvelteKit source — do NOT modify
- React 19 with hooks. No class components.
- TanStack Router v1 with
createHashHistory()— useuseNavigate()and<Link>, never manipulatewindow.locationdirectly from React components. - Zustand v5 for cross-component state. TanStack Query for all server/IPC-fetched data.
- Tailwind CSS v4 — utility classes only, no config file. Use
--sg-*CSS variables fromapp/src/renderer/tailwind.cssfor all colors and spacing tokens. Never hardcode color values. - Icons —
lucide-reactonly. Do not add new icon libraries or use emoji as icons. - Use
cn()(re-exported from@sproutgit/ui) for conditional class names.
All IPC channel names live in packages/types/src/ipc.ts. Never use bare strings.
- Add
IPC.DOMAIN_ACTION: 'domain:action'topackages/types/src/ipc.tsand its entry toIpcMap. pnpm --filter @sproutgit/types build- Add the handler in
app/src/main/ipc/<domain>.ts. - Expose it via
window.apiinapp/src/preload/index.ts. - Call
window.api.myNewCall()from the renderer — never importipcRendererin renderer code.
The database package has two schemas: config (global user settings) and workspace (per-repo state). Both use Drizzle ORM with node:sqlite.
Always generate migrations with drizzle-kit — never write migration SQL by hand.
Config schema changes:
cd packages/database
pnpm drizzle-kit generate --config=drizzle.config.config.tsWorkspace schema changes:
cd packages/database
pnpm drizzle-kit generate --config=drizzle.workspace.config.tsThen rebuild the package:
pnpm --filter @sproutgit/database buildAll Git work goes through @sproutgit/git. Do not call simple-git directly from the main process or use child_process/exec for Git commands.
nodeIntegration: falseandcontextIsolation: true— never change these.- All Node.js access goes through the context bridge (
window.api). - Validate paths received over IPC before passing to filesystem APIs.
- Use
simple-gitAPIs for Git operations — never pass user input to shell commands.
- Types — Add shared types to
packages/types/src/and rebuild:pnpm --filter @sproutgit/types build - IPC — Follow the IPC steps above if the feature needs main ↔ renderer communication
- Main process — Implement in
app/src/main/ipc/<domain>.ts, delegating to the appropriate package - Renderer — Build UI using existing design tokens and component patterns
- Tests — Add unit tests for business logic; add E2E selectors (
data-testid) for any new interactive elements - Verify —
pnpm typecheck && pnpm lint && pnpm test
- Create a branch from
main - Make focused commits — one feature or fix per PR
- Run
pnpm typecheck && pnpm lint && pnpm testbefore pushing - Open a pull request against
mainwith a clear description of what changed and why
- Use GitHub Issues
- Include your OS, Node version, Git version, and steps to reproduce
- Attach relevant error messages or screenshots from
~/Library/Logs/SproutGit/main.log(macOS) /%APPDATA%\SproutGit\logs\main.log(Windows)