Contributing
This guide covers what you need to get started contributing to Kangentic. For detailed architecture documentation, see the Architecture page or the repo docs.
Getting set up
Section titled “Getting set up”What to install, how to start the app, and how the tree is laid out.
Prerequisites
Section titled “Prerequisites”- Node.js 22.14+ or 24+, Download from nodejs.org. better-sqlite3 13 needs Node-API 10, and an older Node 22 crashes on the first database open instead of reporting it. CI runs the test tiers on Node 24
- Git 2.26+, worktree support required
- Claude Code CLI installed and on
PATH; it is what the end-to-end tier drives. The app itself runs any of the fifteen supported agents, and all fifteen are first-class: add features or adapters for any of them.
Platform build tools
Section titled “Platform build tools”| Platform | Required |
|---|---|
| Windows | Nothing since v0.44.0: every native module ships a prebuilt Windows binary |
| macOS | Xcode Command Line Tools, which a macOS package build needs for node-pty’s spawn-helper |
| Linux | build-essential, python3, because node-pty ships no Linux binary and compiles on install |
Quick start
Section titled “Quick start”git clone https://github.com/kangentic/kangentic.gitcd kangenticnpm installnpm startnpm start does four things in order. It starts Vite in-process for renderer hot reload. It builds the main process, the preload script, and the three utility-process workers (embedding, line-count, dictation) once with esbuild. It copies the bridge and plugin scripts next to the bundle. Then it launches Electron. Renderer edits hot-reload; a main-process or preload edit needs npm start run again, since esbuild does not watch.
A dev build names itself Kangentic (dev) in the title-bar wordmark and in the OS window title, so a dogfooding npm start window is tellable from an installed build in the taskbar without clicking into it. Production builds drop both strings.
Project structure
Section titled “Project structure”src/ main/ # Electron main process (Node.js) activity-engine/ # Activity-state engine behind the board's status dots agent/ # Agent adapters (per-agent subfolders) with detection, command building, hooks, trust analytics/ # Opt-out usage analytics automations/ # Column automation runner, registry, and the per-type adapters boards/ # External board adapters (Asana auth, import sources) browser/ # Embedded Browser pane host + automation gating config/ # Three-tier config: global > project > effective db/ # SQLite database layer + migrations dev-ports/ # Dev-server port ledger + bind probe diagnostics/ # Log mirroring, crash capture, IPC recording fs/ # Filesystem helpers git/ # Worktree creation and cleanup ipc/ # IPC handler registration + handlers/ mobile-bridge/ # Mobile companion pairing + relay monitor/ # Cross-project Agent Monitor aggregation notifications/ # Desktop alerts and the announcements feed pop-out/ # Detachable-surface window engine pr/ # Branch-to-PR resolution + refresh scheduling pty/ # Terminal session management + queue retrieval/ # Conversation Memory index + search search/ # Quick Find query backend shared/ # Helpers shared across main-process subsystems task-detail/ # Cross-window task-detail ownership registry transcription/ # Local voice dictation runtime transition-engine/ # Transition engine, session recovery usage-stats/ # Usage dashboard aggregation utility-process/ # Shared plumbing for the utilityProcess workers (paths, restart policy, stderr tail) preload/ # Context bridge (window.electronAPI) renderer/ # React UI components/ # Board, dialogs, layout, terminal hooks/ # React hooks (useTerminal, etc.) pop-out/ # Renderer side of the detachable surfaces: roots, registry, frame stores/ # Zustand state management window-manager/ # In-app window layer: floating/tiled/snapped panes over the board and monitor shared/ # Shared types, IPC channels, path utilities devtools/ # Dev-build-only tooling, excluded from production bundlespackages/ # npm workspaces launcher/ # The `kangentic` npm package behind `npx kangentic` protocol/ # @kangentic/protocol - a shared wire-schema package, published to npm on its own version linetests/ unit/ # Vitest - pure logic, no browser integration/ # Vitest - opt-in, hits real CLIs/network (excluded from test:unit) ui/ # Playwright + Chromium - mock electronAPI e2e/ # Playwright + real Electron captures/ # Playwright - on-demand screenshots/recordings, not a test tier demo/ # Playwright - smoke test of the static web demo build (npm run test:demo) fixtures/ # Shared fixtures: mock agent CLIs, real session transcriptsBuild system
Section titled “Build system”| Mode | Command | What Runs |
|---|---|---|
| Development | npm start or npm run dev | Vite dev server + esbuild watch + Electron |
| Production | npm run build | tsc --noEmit > Vite build > esbuild (minified) |
| Package | npm run package | Build + unpacked app directory (electron-builder --dir, no installer) |
| Make | npm run make | Build + create platform installers |
| Publish | npm run publish | Build + upload to GitHub Releases |
In development, native modules (better-sqlite3, node-pty, sherpa-onnx-node, sqlite-vec, @huggingface/transformers, and font-list) are marked external in esbuild and loaded at runtime from node_modules (as is electron itself).
Packaging
Section titled “Packaging”Kangentic builds its installers with electron-builder, configured in electron-builder.yml at the project root. Packaging and releases covers the platform targets, how the native modules ship, what is unpacked from the ASAR archive, the Electron security fuses, code signing, and the release workflow.
Contributing changes
Section titled “Contributing changes”From the CLA to the merged pull request.
Contributor license agreement
Section titled “Contributor license agreement”First-time contributors must sign a Contributor License Agreement (CLA) before their pull request can be merged. When you open your first PR, the CLA Assistant bot will post a comment - you sign by adding a comment to the PR. It takes about 30 seconds and only needs to be done once.
Kangentic is dual-licensed: the public version uses AGPLv3, and commercial licenses are available for organizations that need proprietary modifications. The CLA (modeled after the Apache ICLA) grants VORPAHL LLC a non-exclusive license to distribute your contribution under any license, while you retain full copyright to your work.
To inquire about a commercial license, email licensing@kangentic.com.
Key conventions
Section titled “Key conventions”- Text formatting - no em-dashes (U+2014) and no
--used as punctuation in anything you author (code, comments, tests, docs, commit messages). Use a single dash or restructure with a period. Enforced by a CI unit test plus review - TypeScript strict mode -
noImplicitAnyenabled, noanytypes (use the types insrc/shared/types.ts,unknownwith a type guard, or generics), and full descriptive names:currentIndexnotcurIdx - UI conventions - use the shared primitives (
Selectrather than a raw<select>,CountBadge,ConfirmDialog) and Lucide React icons, never inline SVGs. Respect the font floor:text-xsby default and never belowtext-[11px]. Avoid hover-only controls, use theme-adaptive semantic tokens rather than hardcoded colors so the UI re-colors across every theme, prefer visual subtraction over addition, and adddata-testidattributes on interactive elements for test selectors - No personal info - the repo is public, so never hardcode usernames, emails, or home-directory paths. Use generic placeholders like
C:\Users\devin tests and examples - Reuse before reimplement - search for an existing utility before adding a new one, and extract duplicated logic into a shared module instead of copying it
- Bounded IPC payloads - cap large captured buffers, such as child-process stdout and stderr, before they cross IPC. An Error must never carry tens of megabytes
- IPC channels -
src/shared/ipc-channels.tsis the single source of truth - Cross-platform parity - code and tests must behave identically on Windows, macOS, and Linux. No hardcoded OS paths, pass
{ force: true }tofs.rmSync/fs.rmfor Windows file locking, write test files only underos.tmpdir(), and avoid pixel-exact or bare-timeout assertions. Enforced by a CI unit test and the Linux CI run - Docs stay in sync - changing an anchor source file (union types, IPC channels, DB migrations, adapter capabilities, or settings) means updating the matching doc under
docs/. Enforced by an automated doc-anchor check when the PR is opened and merged - Commit messages - Conventional Commits format (
type(scope): subject), enforced by commitlint. Allowed types:feat,fix,docs,style,refactor,perf,test,build,ci,chore,revert. The scope is optional and unchecked, so reuse an existing one rather than coining a new spelling of it (agentnotagents,dbnotdatabase); CONTRIBUTING.md lists the scopes in active use
These are the conventions that most often need a maintainer follow-up when missed; the full set lives in the repo’s .claude/rules/ directory.
Adding an IPC channel
Section titled “Adding an IPC channel”Most features that cross from the UI into the main process start with a new IPC channel, and every channel touches the same six files. Add them in this order:
- The channel constant in
src/shared/ipc-channels.ts, the single source of truth for channel names - The handler in the matching
src/main/ipc/handlers/*.tsmodule, registered withipcMain.handleon that constant - The method on the
ElectronAPIinterface insrc/shared/types.ts - The bridge method in
src/preload/preload.ts, which callsipcRenderer.invokewith the constant behindcontextBridge - The call from the renderer, through
window.electronAPI.domain.method() - The stand-in in
tests/ui/mock-electron-api.js, when UI tests exercise the call
Submitting a pull request
Section titled “Submitting a pull request”-
Fork the repo and create a branch from
main. Use a descriptive branch name likefix/session-resume-crash,feature/multi-agent-support, ordocs/update-architecture. -
Make your changes and add or update tests for them.
-
Run the quick local pass before opening the PR:
Terminal window npm run lintnpm run typechecknpm run test:unitnpx playwright test --project=ui -
Sign the CLA when the bot prompts you on your first PR (see Contributor License Agreement above).
-
Open the PR. The template prompts you for What / Why / How / Tests and a short checklist. Link any related issues.
Small, focused PRs are easier to review and merge faster. For the full three-tier testing strategy, see Testing.
What to expect
Section titled “What to expect”Your PR must be green on every CI check before it can merge:
| Check | What it runs |
|---|---|
| Lint, Typecheck, Build | One job with three independently reported steps: ESLint with --max-warnings 0 (so any warning fails it), tsc, and the production bundle plus the @kangentic/protocol package build. A failing lint step never hides a type error, because every step runs regardless |
| Unit tests (Vitest) | Three shards behind one gate |
| UI tests (Playwright) | Eleven shards of headless Chromium behind one gate |
| E2E tests (Electron) | Five shards under xvfb behind one gate |
| cla | The CLA assistant, which asks you to sign on your first PR |
A sixth job, Web demo (build + smoke), builds the static web demo and boots it through the demo Playwright project on every run.
CodeQL scanning is deliberately not on that list. It runs after a merge to main and again weekly rather than on the PR, because the gate already fills the account’s concurrent-job budget and two more jobs per PR would make every run slower. main is PR-gated either way, so nothing reaches the scan unreviewed. Dependabot is scoped to GitHub Actions only and opens one grouped PR a week; npm bumps stay manual, because several dependencies are pinned to exact versions after a floating range broke a release.
If a check fails, push a fix and CI re-runs automatically. Contributors cannot re-run checks directly (that requires write access), so to re-trigger a run for a failure unrelated to your change - a flaky test, say - push a new commit (an empty git commit --allow-empty is fine), close and reopen the PR, or ask a maintainer to re-run it.
- A maintainer may push follow-up commits to your branch for design polish or hardening before merging. This is normal and keeps the bar consistent, not a reflection on your work.
- UI changes get a maintainer design review against the UI conventions. Including a screenshot or short clip in the PR makes that review much faster.
- A maintainer merges your PR once it is approved and green. You do not need write access to the repository; repeat contributors may be granted it over time, at which point you merge your own PRs once approved.
Where to start
Section titled “Where to start”Good first areas, and where to take a problem that should not be public.
Agent-specific contributions
Section titled “Agent-specific contributions”Kangentic drives fourteen coding-agent CLIs, and the maintainers do not hold a subscription to all of them. Anything that needs a live, authenticated CLI is measured where that is possible and recorded honestly where it is not, so the gaps are written down rather than papered over. If you use one of these agents every day, you are better placed to close them than we are.
The clearest example is column message delivery. Kangentic confirms that a message it typed at the agent actually became a user turn, and an agent only earns the last-resort recovery of restarting the session once two separate things have been proven for it. The per-adapter status, what each agent is still missing, and a step-by-step recipe live in docs/command-injection.md. Partial results are welcome: measuring one agent and reporting the numbers is a useful pull request on its own, as is committing a sanitized capture, and neither requires touching an adapter.
Bug reports in this area are most useful with the agent name, the task’s auto_command_state, and whether the session was local or remote.
Finding work
Section titled “Finding work”Look for issues labeled good first issue for approachable tasks. If you want to take on something larger, open an issue first to discuss the approach. Questions are welcome in GitHub Discussions.
Code of conduct and security reports
Section titled “Code of conduct and security reports”The project follows the Contributor Covenant. Report unacceptable behavior to support@kangentic.com.
A security problem is the one thing that should not go in a public issue. Use GitHub’s private vulnerability reporting, or email security@kangentic.com if you would rather not go through GitHub, so a fix can ship before the details are public.
See also
Section titled “See also”- Testing - Three-tier testing strategy
- Architecture - Process model, data flow, IPC channels
- Configuration reference - All settings keys and types
- Repo docs - Deep dives on database schema, transition engine, session lifecycle, and more
Kangentic is free and open source. A star helps other people find it.
Star on GitHub