Development
Requires Node.js 24 and Git. Tauri also needs a Rust toolchain (and libwebkit2gtk-4.1-dev on Linux); Deno Desktop comes from npm. The terminal’s node-pty ships prebuilt for Windows and macOS; on Linux npm install compiles it, which needs Python, make and a C++ compiler.
Run from source
Section titled “Run from source”npm installnpm startnpm start runs the client with hot reload and the Electron app. Restart it after changing anything outside src/client/. Open this folder in Genbeya: its wiki is this documentation and its task board is the real backlog.
The web demo
Section titled “The web demo”npm run start:demo serves the Demo at http://127.0.0.1:5173/ with the managers running in the page; it rebuilds on every change. To see the static build as genbeya.fyi serves it:
npm run build:demonode scripts/serve-demo.mjs 4200Then open http://127.0.0.1:4200/try/. Reloading the page starts the demo over.
Scripts
Section titled “Scripts”| Command | What it does |
|---|---|
npm start | Client with hot reload plus the Electron app. Restart it after changing the backend or the shell |
npm run start:demo | The web demo with rebuilds on change, in your browser |
npm run check | Type-check backend, shells and client |
npm run lint | ESLint, including the layer rules of the Architecture |
npm run format | Prettier |
npm test | Backend and client unit tests |
npm run e2e | Build, then end-to-end tests against the Electron app |
npm run e2e:demo | Build the web demo, then its end-to-end tests in Chromium |
npm run build | Production client and Electron shell |
npm run build:demo | The web demo as static files, in dist/demo/browser |
npm run icons | App icons of all three shells and the favicon, rendered from the logo in branding/ |
npm run package | Electron installer for the current OS, in release/ |
npm run package:tauri | Tauri installers, in src/shells/tauri/src-tauri/target/release/bundle/ |
npm run package:deno | Deno Desktop installers (.msi, .dmg, or .AppImage and .deb), in release-deno/ |
Code is written test first. Specs sit next to the code they test.
- Backend (
npm run test:backend, Vitest): engines with plain data; resource access and managers against disposable repositories in.test-work/, including a content branch synced through a bare remote with some areas on it and the others in the checkout, and a WSL repository when theUbuntudistribution exists.backend.spec.tsdrives the managers through the RPC envelope, as a shell does. Both platforms pass the same machine contract (src/testing/machine-contract.ts); on Node it includes pseudo-terminals with the user’s real shell. Managers that start terminals get fake ones (src/testing/terminals.ts). - Client (
npm run test:client, Vitest throughng test): components with a fake platform (src/client/app/testing/fake-platform.ts), engines of the client such as fuzzy search and the commit graph, and the Markdown pipeline. - End to end (
npm run e2e, Playwright): the packaged Electron app with a fresh profile and a fresh repository per test, opened through the--openlaunch argument. Covers wiki, tasks, version control, sharing, the shell, the terminal and the onboarding, and browsing WSL folders when theUbuntudistribution exists. A test can launch the app again on the same profile (launch), e.g. with agenbeya://link. Unpackaged builds do not register forgenbeya://links, so development never takes them over from the installed app. Profiles start as a user who has seen the tour and this version’s news, so neither gets in the way;test.use({ preferences: null })starts like a first start, and other values set what the profile’sstate.jsonholds. - Web demo (
npm run e2e:demo, Playwright in Chromium,playwright.demo.config.ts): the built demo served under/try/byscripts/serve-demo.mjs, a fresh page per test; every test also fails when the page requests anything from another origin. Install the browser once withnpx playwright install chromium. The demo’s managers have unit tests of their own insrc/managers/demo/andsrc/access/memory/.
Continuous integration
Section titled “Continuous integration”.github/workflows/build.yml runs on every push and pull request to main and on pushes to experiment/** branches. On Windows, macOS and Linux it runs lint, unit and end-to-end tests (.github/actions/verify) and the Tauri shell’s Rust tests, then packages Electron, Tauri and Deno Desktop. On Linux it also builds the web demo, tests it in Chromium and uploads it as genbeya-web-demo.zip.
- The version is
package.json’s, and the same in its lockfile,tauri.conf.json,Cargo.tomlandCargo.lock:node scripts/version.mjs bump patch(orminor,major) orset 1.0.0changes all of them, and CI fails when they disagree (node scripts/version.mjs check). Bump the patch for fixes, the minor version for new features. Installers replace an installed older version, so every release needs a higher version. - Deno Desktop’s MSIs take their version from a generated
dist/deno/deno.json;scripts/msi-major-upgrade.ps1adds the upgrade rules they lack, and refuses to install over a newer version. Installing an MSI of the same version again repairs it instead of upgrading. scripts/collect-installers.mjscopies every installer intoout/installers/, renamed toGenbeya-<version>-<variant>-<os>-<arch>[-setup].<ext>(for exampleGenbeya-0.1.0-tauri-windows-x64-setup.exe), so the variants never clash. Run it locally after packaging;--dry-runonly prints the names.scripts/report-sizes.mjslists their sizes in the job summary.- Each run uploads one artifact per variant and platform, such as
Genbeya-tauri-macOS. - A push to
mainwhose version has no release yet publishes all installers andgenbeya-web-demo.zipas one GitHub release taggedv<version>, with the text of.github/release-notes.mdabove the generated notes; pushes whose version is released already are built and tested only. To release: bump the version, commit, push. A release is marked latest only when no publishedv*release is newer.
macOS builds Electron for Apple silicon and Intel; Tauri and Deno Desktop only for the runner’s Apple silicon.
What’s new and the tour
Section titled “What’s new and the tour”The app’s version comes from package.json at build time (src/client/app/core/app-version.ts). When the version is newer than the one the user saw last, Genbeya shows the news of every release line in between, once. First-time users get the tour instead.
To announce a change, add an item to the entry of its release line in src/client/app/features/onboarding/changelog.ts, newest release first:
{ version: "0.1", items: [ { title: "Stash", body: "Set changes aside and bring them back later, from **Changes**.", // Optional: "Show me" in the dialog points at the element, after going to the route. target: '[data-tour="commit-box"]', route: "/changes", }, ],},Entries are keyed by major.minor, since every build bumps the patch: a new entry only shows once package.json (and tauri.conf.json and Cargo.toml for Tauri) carries that minor version, and only to users updating from an older one. The changelog starts empty, in release line 0.0; while it has no entry, nobody sees What’s new, and Show what’s new says there is nothing yet. Keep items to a sentence or two of Markdown.
The tour’s steps are in src/client/app/features/onboarding/tour-steps.ts. A step names its element by selector, usually a data-tour attribute on it, and optionally the route it is on; steps whose element is missing are skipped. The tour itself (src/client/app/ui/tour/) knows nothing about the app.
Conventions
Section titled “Conventions”- Calls only go down the layers; ESLint enforces it. Managers do not call each other; engines do no I/O.
- Every manager method validates its own input.
- Client state lives in signals. The repository is in
core/session.ts, navigation in the router; views own everything else. - Operations go through
session.run, which reports errors and refreshes the snapshot afterwards. Apply a save’s result before the refresh, so the editor is clean when the snapshot arrives. - Styles use the tokens in
src/client/styles/tokens.css. - Line endings are LF (
.gitattributes);npm run formatbefore committing.
Documentation
Section titled “Documentation”docs/ is Genbeya’s own wiki, and Open the documentation (in Settings → Help, the command palette and on the start screen) opens it on GitHub, so it has to make sense to people who never cloned the repository. Write it as the rest of the wiki: short, concrete, second person, present tense, with the labels the app shows in bold.
- Prefer live examples:
[[GENBEYA-12]]next to its source shows readers what a reference does. Point them at tasks, pages and files that exist, so nothing renders as missing by accident. - Screenshots live in
docs/images/: the Electron app at its end-to-end window size (1000 × 680), light theme, the sample project as subject, reduced to 256 colours so each stays well under 150 KB. Link them relatively (../images/search.png). - Announce user-facing changes in What’s new as well (see above).
License
Section titled “License”Genbeya is licensed under the Functional Source License (FSL-1.1-ALv2): anyone may use, change and share it, but not offer it, or something substantially similar built from it, as a competing commercial product or service; each version becomes Apache 2.0 two years after its release. The license fields of package.json and Cargo.toml say so too.
What Genbeya writes into users’ repositories — the agent files, the sample project, new settings files and task templates — is under the MIT No Attribution License (MIT-0), and so is that text in the source files it comes from. Those files start with a comment saying so, and LICENSE-MIT-0.md lists them. When you add a file that writes text into users’ repositories, or move such text to another file, give it the same comment and update the list.