An offline desktop companion for OpenClaw β elegant, oceanic, and built for non-technical users.
OpenClaw Harbor is an offline desktop companion app that gives non-technical users a friendly, polished way to install, configure, launch, monitor, and use OpenClaw agents locally.
It wraps and orchestrates your existing OpenClaw install rather than replacing it, presenting everything through a merman-themed command interface: you issue orders, your emissary Azurel is dispatched into the depths, and the results surface back to shore.
Tip: You can rename the emissary in Deep Config β but his default name is Azurel.
| Layer | Technology |
|---|---|
| Desktop shell | Electron 41 |
| Build system | electron-vite 5 |
| UI | React 18 + TypeScript |
| Bundler | Vite 6 |
| Packaging | electron-builder 26 |
| Linting | ESLint 9 + @typescript-eslint |
| Formatting | Prettier 3 |
| Persistence | File-system JSON (via app.getPath('userData')) |
- Node.js 18 or later
- npm 8 or later
- A local OpenClaw install (optional β the app will guide you through setup)
git clone https://github.com/potemkin666/merman.git
cd merman
npm install # install all dependencies
npm run rebuild # compile native modules (node-pty) for Electron
npm run dev # launch the app in dev modeWhy
npm run rebuild? The app usesnode-pty(a native C++ addon) for the built-in terminal. Native addons must be compiled specifically for Electron's version of Node.js. Without this step the terminal may not work (the rest of the app still functions thanks to a built-in fallback).
When you git pull new changes, node_modules/ is not updated automatically β it
is listed in .gitignore and never stored in git. If dependencies changed you need to
re-install:
git pull
npm install # picks up any new/changed dependencies
npm run rebuild # recompile native modules against Electron
npm run devTip: The one-click launchers (
start.sh/start.bat) handle this for you automatically β they detect whenpackage.jsonis newer thannode_modulesand re-run install + rebuild before launching.
After cloning, you can use the included launcher shortcuts instead of the terminal:
- Windows: Double-click
start.bat - macOS / Linux: Double-click
start.sh(or run./start.shin terminal)
These scripts automatically:
- Check that Node.js is installed
- Install dependencies if missing or if
package.jsonhas changed since the last install - Rebuild native modules for Electron
- Launch the app
npm run buildThe compiled output lands in out/.
# Package for current platform
npm run dist
# Platform-specific
npm run dist:mac # .dmg + .zip
npm run dist:win # .exe installer + portable
npm run dist:linux # .AppImage + .debPackaged output goes to release/.
The project uses ESLint with @typescript-eslint and Prettier so that every
contributor formats code the same way.
npm run lint # check for lint errors/warnings
npm run lint:fix # auto-fix what ESLint can
npm run format # reformat all source files with Prettier
npm run format:check # check formatting without writing (CI-friendly)Configuration lives in:
eslint.config.jsβ ESLint 9 flat config (TypeScript, React, React Hooks, Prettier compat).prettierrcβ Prettier options (no semicolons, single quotes, 120-char lines)
Tip for editors: Install the ESLint and Prettier extensions for your editor and enable "format on save" for the smoothest experience.
- Open Deep Config and set the path to your local OpenClaw folder.
- Open Setup to run
npm installinside that folder and verify prerequisites. - Return to The Harbor and press Summon to start the OpenClaw service (
node index.js). - Use Dispatch to send tasks/prompts directly to the running agent.
- Open The Fishtank to watch Azurel work β he'll swim, think, examine scrolls, and share his thoughts while he's at it.
The app spawns OpenClaw as a child process, captures its stdout/stderr, translates output into readable log entries in Tide Log, and surfaces errors with plain-English explanations.
| Screen | Purpose |
|---|---|
| The Harbor | Main dashboard: status, quick actions, environment health, recent dispatches |
| Setup Wizard | Guided onboarding: check prerequisites, locate install, run setup |
| Dispatch | Send a task to the emissary; select a mode/preset; view results |
| The Fishtank | Peer into the depths β watch Azurel's idle animations and hear his thoughts |
| Tide Log | Filterable log panel with simplified and raw views |
| Deep Config | Form-based settings: paths, model, provider, API key, emissary name, presets |
Click "Fishtank" in the sidebar to peer into Azurel's underwater world. You'll see:
- Idle animations that cycle automatically β floating, swimming, thinking, examining scrolls, waving, stretching, gazing into the abyss
- Status-aware sayings β Azurel says different things depending on whether he's idle, working, done, or encountering errors
- Ambient effects β bubbles rise, caustic light drifts, coral decorates the seabed
- Live status β a bottom bar shows what the emissary is currently doing
When a task is running, Azurel's animations shift to focused work behavior and his sayings reflect progress.
- Electron + React + Vite + TypeScript scaffold
- Dark underwater theme (CSS custom properties)
- Sidebar navigation
- Harbor dashboard with status card, environment health, and recent dispatches
- Setup Wizard with real environment checks (Node, npm, git, OpenClaw dir, config files)
- Start / stop / restart OpenClaw service with real process tracking
- Dispatch screen with prompt entry, mode selection, output panel
- Fishtank with animated emissary, cycling idle behaviors, and status-aware sayings
- Customizable emissary name (default: Azurel) β set in Deep Config, used throughout the UI
- Tide Log with severity filters and raw/simplified toggle
- Deep Config with path fields, model settings, preset management
- Error translation with plain-English explanations and retry buttons
- Saved presets (Quick Chat, Starter Mode, Coding Helper, Local Researcher, Advanced Custom)
- IPC layer between main and renderer
- Persistent config stored in
userData/config.json - Local task history in browser localStorage
- Packaging via electron-builder (macOS, Windows, Linux)
- ESLint + Prettier configured for consistent code style
- The app does not rebuild or replace OpenClaw internals
- No cloud features, sync, or multi-user support
- Log parsing is basic β more patterns can be added
- Visual theme uses emoji icons; SVG/custom art is a future improvement
- Custom merman character art (replace emoji with illustrated sprites)
- More emissary animations and reactions tied to specific task events
- Richer log parsing and pattern matching
- Task templates and prompt library
- Optional "advanced mode" for technical users
- Health diagnostics panel
- Auto-update support
src/
βββ main/ # Electron main process
β βββ index.ts # Window creation + IPC handlers
β βββ preload.ts # contextBridge exposure
β βββ services/
β βββ envChecker.ts # Detect Node, npm, git, OpenClaw
β βββ processRunner.ts # Spawn child processes, stream output
β βββ configService.ts # Read/write JSON config
β βββ logService.ts # In-memory log buffer + persistence
βββ renderer/ # React UI
β βββ index.html
β βββ src/
β βββ App.tsx
β βββ components/ # StatusCard, NavSidebar, LogPanel, Modal
β βββ screens/ # Harbor, SetupWizard, Dispatch, Fishtank, TideLog, DeepConfig
β βββ hooks/ # useAppState, useIpc
β βββ theme/ # Design tokens reference
βββ shared/
βββ types.ts # Shared TypeScript interfaces
βββ ipc.ts # IPC channel name constants
This means native modules were not compiled for Electron. Run:
npm run rebuildIf that fails, delete node_modules and start fresh:
rm -rf node_modules # macOS/Linux
rmdir /s /q node_modules # Windows
npm install
npm run rebuild
npm run devgit pull only updates source files β it does not touch node_modules/. If
dependencies changed in the pull, run:
npm install
npm run rebuildOr just use the one-click launcher (start.sh / start.bat) which detects this
automatically.
Make it executable:
chmod +x start.sh
./start.shThis is non-fatal. The app falls back to a basic child_process shell. To get full
PTY support, run npm run rebuild to compile node-pty for Electron.
MIT
