Thanks for your interest in contributing! We favor small, focused PRs and clear intent over big bangs. This guide explains how to get set up, the workflow we use, and a few project‑specific conventions.
Prerequisites
- Node.js 20.0.0+ (recommended: 22.20.0) and Git
- Optional (recommended for end‑to‑end):
- Codex CLI (
npm install -g @openai/codexorbrew install codex; then runcodexto authenticate) - GitHub CLI (
brew install gh; thengh auth login)
- Codex CLI (
Setup
# Fork this repo, then clone your fork
git clone https://github.com/<you>/emdash.git
cd emdash
# Use the correct Node.js version (if using nvm)
nvm use
# Quick start: install dependencies and run dev server
npm run d
# Or run separately:
npm install
npm run dev
# Type checking, lint, build
npm run type-check
npm run lint
npm run buildTip: During development, the renderer hot‑reloads. Changes to the Electron main process (files in src/main) require a restart of the dev app.
src/main/– Electron main process, IPC handlers, services (Git, worktrees, Codex process manager, DB, etc.)src/renderer/– React UI (Vite), hooks, components- Local database – SQLite file created under the OS userData folder (see “Local DB” below)
- Worktrees – Git worktrees are created outside your repo root in a sibling
worktrees/folder - Logs – Agent stream logs are written to the OS userData folder (not inside repos)
- Create a feature branch
git checkout -b feat/<short-slug>
- Make changes and keep PRs small and focused
- Prefer a series of small PRs over one large one.
- Include UI screenshots/GIFs when modifying the interface.
- Update docs (README or inline help) when behavior changes.
- Run checks locally
npm run type-check
npm run lint
npm run build
- Commit using Conventional Commits
feat:– new user‑facing capabilityfix:– bug fixchore:,refactor:,docs:,perf:,test:etc.
Examples
fix(chat): preserve stream state across workspace switches
feat(ci): add type-check + build workflow for PRs
- Open a Pull Request
- Describe the change, rationale, and testing steps.
- Link related Issues.
- Keep the PR title in Conventional Commit format if possible.
TypeScript + ESLint
- Keep code type‑safe. Run
npm run type-checkbefore pushing. - Run
npm run lintand address warnings where reasonable.
Electron main (Node side)
- Prefer
execFileoverexecto avoid shell quoting issues. - Never write logs into Git worktrees. Stream logs belong in the Electron
userDatafolder. - Be conservative with console logging; noisy logs reduce signal. Use clear prefixes.
Git and worktrees
- The app creates worktrees in a sibling
../worktrees/folder. - Do not delete worktree folders from Finder/Explorer; if you need cleanup, use:
git worktree prune(from the main repo)- or the in‑app workspace removal
- The file
codex-stream.logis intentionally excluded from Git status and auto‑ignored in new worktrees.
Renderer (React)
- Components live under
src/renderer/components; hooks undersrc/renderer/hooks. - Streaming UI conventions:
- “Reasoning” content renders inside a collapsible.
- Response content is shown only after a
codexmarker. - While waiting for the first marker, show the minimal “loading/working” indicator.
- Use existing UI primitives and Tailwind utility classes for consistency.
- Aim for accessible elements (labels,
aria-*where appropriate).
Local DB (SQLite)
- Location (Electron
app.getPath('userData')):- macOS:
~/Library/Application Support/emdash/emdash.db - Linux:
~/.config/emdash/emdash.db - Windows:
%APPDATA%\emdash\emdash.db
- macOS:
- Reset: quit the app, delete the file, relaunch (the schema is recreated).
- Use GitHub Issues. Include:
- OS, Node version
- Steps to reproduce
- Relevant logs (renderer console, terminal output)
- Screenshots/GIFs for UI issues
Use npm's built-in versioning to ensure consistency:
# For bug fixes (0.2.9 → 0.2.10)
npm version patch
# For new features (0.2.9 → 0.3.0)
npm version minor
# For breaking changes (0.2.9 → 1.0.0)
npm version majorThis automatically:
- Updates
package.jsonandpackage-lock.json - Creates a git commit with the version number (e.g.,
"0.2.10") - Creates a git tag (e.g.,
v0.2.10)
Then push to trigger the CI/CD pipeline.
The GitHub Actions workflow (.github/workflows/release.yml) automatically:
- Triggers when it detects the
v*tag - Builds the TypeScript and Vite bundles
- Signs the app with Apple Developer ID
- Notarizes via Apple's notary service
- Creates a GitHub Release with the DMG artifacts
- Uploads signed DMGs for both arm64 and x64 architectures