Architecture
The apps and packages, and the boundary between Electron main and the renderer.
Vimputer has two halves. The editor is where you build layers, bindings, and variables. The runtime receives Karabiner events and shows the HUD.
Apps and packages
| Path | Owns |
|---|---|
apps/desktop |
Electron main, preload, renderer, plugin runtime, HUD |
apps/browser-extension |
Chrome extension for tab and web-app commands |
apps/macos-accessibility-helper |
Swift helper: menus, displays, windows, Accessibility permission |
apps/docs |
This site |
packages/schemas |
Zod contracts for config, actions, plugins, HUD, and RPC |
packages/config |
Config store, defaults, and Karabiner import |
packages/karabiner |
Generation into Karabiner profile JSON |
packages/plugin-sdk |
The plugin authoring API |
packages/integrations |
Node-safe discovery and parsing of local command sources |
packages/shortcuts |
Re-exports the OpenKeymap SDK for semantic commands |
packages/api |
The external automation API contract |
packages/cli |
The vimputer command-line tool |
packages/ui |
Shared renderer primitives |
Code that speaks the product’s language stays in apps/desktop. A reusable
primitive, contract, parser, or compiler step goes in a package.
Main and renderer
Electron main owns everything privileged: the filesystem, shell, Karabiner writes, the runtime socket, plugin execution, and the Accessibility helper. The renderer stays platform-agnostic and calls main over typed oRPC through preload and a message port.
| State | Lives in |
|---|---|
| Data from main | TanStack Query |
| The working copy of the config | The renderer store, autosaved |
Shareable view state (?view=, ?binding=) |
TanStack Router search params |
| Everything transient | Component state |
App hotkeys go through @tanstack/react-hotkeys. Keep preload thin and main’s
procedures narrow.