How to Contribute to the holaOS Project: A Complete Developer Guide

Contributing to holaOS requires setting up a Node 24.14.1 environment, choosing between Desktop (Electron), Runtime (Fastify API), or Harness (agent adapter) tracks, and running targeted validation scripts before submitting PRs with Conventional Commits.

holaOS is a monorepo housing three distinct subsystems that power an AI-native operating environment. Whether you are fixing UI bugs in the desktop shell, extending the HTTP API, or bridging agent actions to system calls, understanding the repository structure and validation workflows ensures your contributions merge smoothly.

Understanding the holaOS Monorepo Architecture

Before writing code, identify which subsystem your change affects. The repository is organized into three primary domains, each with strict contracts between them.

Subsystem Core Code Location Typical Entry Points Validation Commands
Desktop shell (Electron UI, preload bridge, main process) apps/desktop/ apps/desktop/electron/main.ts, apps/desktop/src/** npm run desktop:typecheck + npm run desktop:e2e
Runtime HTTP API (Fastify server, workers, state‑store) runtime/api-server/, runtime/state-store/ runtime/api-server/src/app.ts, runtime/state-store/src/store.ts npm run runtime:api-server:typecheck + npm run runtime:test
Agent harness (adapter, run projection) runtime/harness-host/, runtime/harnesses/ runtime/harness-host/src/**, runtime/harnesses/src/** npm run runtime:harness-host:test + npm run runtime:api-server:test

The Desktop runs on Electron and maintains strict IPC contracts between the main process and renderer. The Runtime exposes HTTP endpoints that agents consume, backed by a SQLite state store. The Harness translates agent intentions into runtime requests via adapter contracts.

Setting Up Your Development Environment

Start with the automated installer or manual steps documented in INSTALL.md. You will need Git and Node.js version 24.14.1 installed globally.

Run the one-line installer from the repository root:

./scripts/install.sh

If installing manually, execute these steps in order:

  1. Clone the repository and navigate to the root.
  2. Run npm run desktop:install to bootstrap dependencies.
  3. Copy the environment template file to .env and configure local variables.
  4. Prepare the local runtime bundle for testing.

Choosing Your Contribution Track

Select the track that matches the scope of your change. Each track has distinct entry points and validation requirements.

Desktop Track (Electron)

Work in this track when modifying UI components, window management, or inter-process communication (IPC) logic. Key files include apps/desktop/electron/main.ts for the main process and apps/desktop/electron/preload.ts for the preload bridge.

When adding or modifying IPC channels, you must update both the preload exposure and the main process handler.

Runtime Track (Fastify API)

Work here when adding HTTP endpoints, modifying business logic, or changing the SQLite-backed state persistence. Primary files are runtime/api-server/src/app.ts for route registration and runtime/state-store/src/store.ts for session and artifact storage.

Harness Track (Agent Integration)

Work here when adapting agent outputs to system actions or modifying the projection layer. Core files live in runtime/harness-host/src/adapter.ts and runtime/harnesses/src/**, defining how agent requests map to runtime commands.

The Contribution Workflow

Follow this seven-step workflow to ensure your PR passes CI and review.

  1. Identify the subsystem using the table above to determine which validation scripts to run later.

  2. Make atomic changes scoped to a single concern. Edit source files within the appropriate directory (e.g., apps/desktop/src/ for UI components or runtime/api-server/src/ for routes).

  3. Update contracts and types whenever you touch IPC channels, HTTP routes, or harness adapters. This includes TypeScript definitions in preload.ts, Fastify schemas in app.ts, or interface definitions in adapter.ts.

  4. Run narrow validation to catch type errors and regressions early:

    • For Desktop changes: npm run desktop:typecheck
    • For Runtime changes: npm run runtime:test
    • For Harness changes: npm run runtime:harness-host:test
  5. Run broad validation for mixed changes:

    npm run desktop:typecheck
    npm run runtime:test
    npm run docs:typecheck
    npm run docs:build
  6. Commit with Conventional Commits using prefixes like feat:, fix:, docs:, or chore:. Include a bulleted body explaining what changed and why. Keep commits focused on one cohesive change.

  7. Open a Pull Request describing user-visible impact, migration steps, new environment variables, and the validation commands you executed. Reviewers expect narrow scope, updated tests, and documentation.

Code Examples for Common Contributions

Adding a New Electron IPC Channel

When exposing new functionality from the main process to the renderer, update both the preload script and the main handler.

In apps/desktop/electron/preload.ts, expose the API:

import { contextBridge, ipcRenderer } from "electron";

contextBridge.exposeInMainWorld("myFeature", {
  getStatus: () => ipcRenderer.invoke("my-feature:get-status"),
});

In apps/desktop/electron/main.ts, register the handler:

ipcMain.handle("my-feature:get-status", async () => {
  // Implementation logic here
  return { ok: true, message: "All good" };
});

Validate your changes:

npm run desktop:typecheck
npm run desktop:e2e

Adding a New Fastify Route

Extend the HTTP API by registering new routes in runtime/api-server/src/app.ts.

import { FastifyInstance } from "fastify";

export async function registerMyRoute(app: FastifyInstance) {
  app.get("/api/v1/my-endpoint", async (req, reply) => {
    return { hello: "world" };
  });
}

Import and register the route in the server builder:

import { registerMyRoute } from "./my-endpoint";

export async function buildServer() {
  const app = fastify();
  await registerMyRoute(app);
  return app;
}

Run validation:

npm run runtime:api-server:typecheck
npm run runtime:test

Extending the Harness Adapter

Modify runtime/harness-host/src/adapter.ts to handle new agent request types:

export interface MyFeatureRequest {
  type: "my-feature";
  payload: { foo: string };
}

export async function handleMyFeature(req: MyFeatureRequest, ctx: HarnessContext) {
  return { result: `Processed ${req.payload.foo}` };
}

Register the handler in runtime/harness-host/src/dispatcher.ts:

import { handleMyFeature } from "./adapter";

dispatchMap.set("my-feature", handleMyFeature);

Validate with harness-specific tests:

npm run runtime:harness-host:test
npm run runtime:test

Key Files Every Contributor Should Know

File Subsystem Purpose
apps/desktop/electron/main.ts Desktop Main process entry; defines IPC handlers and window management
apps/desktop/electron/preload.ts Desktop Preload bridge exposing Node APIs to renderer
runtime/api-server/src/app.ts Runtime Fastify route registration and server bootstrap
runtime/state-store/src/store.ts Runtime SQLite-backed persistence for sessions and artifacts
runtime/harness-host/src/adapter.ts Harness Agent action-to-runtime translation layer
runtime/harness-host/src/dispatcher.ts Harness Handler routing map for harness requests
apps/docs/content/docs/contribute/index.mdx Docs Contribution guidelines and track selection
scripts/install.sh Setup One-line development environment installer

Summary

  • holaOS is organized into three subsystems: Desktop (Electron), Runtime (Fastify/SQLite), and Harness (agent adapters).
  • Use the narrowest validation script for your change (e.g., npm run desktop:typecheck for UI work) to maintain fast feedback loops.
  • Always update type contracts when modifying IPC channels, HTTP routes, or harness adapters.
  • Follow Conventional Commits with descriptive bodies and keep PRs narrowly scoped to simplify review.

Frequently Asked Questions

What Node.js version is required to contribute to holaOS?

You must use Node.js 24.14.1 as specified in INSTALL.md. The project relies on specific Node APIs and npm behaviors present in this version, and CI pipelines enforce this constraint strictly.

How do I know which validation scripts to run before submitting a PR?

Match your changed files to the subsystem table in the contribution docs. If you modified files under apps/desktop/, run npm run desktop:typecheck and npm run desktop:e2e if IPC logic changed. For runtime/api-server/ changes, run npm run runtime:api-server:typecheck and npm run runtime:test. Mixed changes require running all relevant suites.

Why do I need to update both preload.ts and main.ts when adding a desktop feature?

The Electron security model requires explicit context bridging between the Node.js main process and the Chromium renderer. The preload.ts script exposes a controlled API surface to the frontend, while main.ts implements the actual handler logic. Updating only one side breaks the IPC contract and causes runtime errors.

Where is the best place to start if I want to add new HTTP endpoints for agents?

Add your route definitions in runtime/api-server/src/app.ts and implement business logic in a new file under the same directory. Import and register your route in the buildServer() function. Ensure you run npm run runtime:api-server:typecheck to validate TypeScript definitions before submitting.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →