vibemon-app

Features

Agent Support

VibeMon normalizes multiple agent ecosystems into one display model. The rendering layer is shared, but the integration path is not.

Agent Integration path Best signal source Observability quality Important limitation
Claude Code Native hooks Session, turn, and tool hooks High None significant for basic monitoring
Codex Native hooks and non-interactive JSON output Interactive lifecycle and local tool hooks, codex exec --json for automation High Hosted tools such as WebSearch do not pass through local tool hooks
Kiro Native hooks Prompt, tool, and stop hooks High Fewer lifecycle events than Claude Code
OpenClaw Plugin bridge Plugin SDK hooks Medium to high Internal hooks are not enough by themselves for full tool-loop visibility

Bridge Types

Agent-Specific Notes

Characters

Character Color Description Auto-selected for
vibemon Purple Robot with antenna, default character Any bridge without its own character
clawd Orange Four-legged friend Claude Code
codex Navy Cloud character with light eyes on a dark screen Codex CLI
kiro White Ghost character Kiro
claw Red Antenna character OpenClaw
daangni Peach/teal Round face, fluffy top Manual only (Character Lock)

In 2D (default) all characters use image-based rendering (128x128 PNG). Images load remote-first from static.vibemon.io, with copies bundled in src/assets/characters/ as the offline fallback. Character is auto-selected by bridge, not by the core display runtime. You can also force one with Character Lock.

Characters are defined in a single registry canonically hosted in vibemon-static (served at static.vibemon.io/data/characters.json, with src/shared/data/characters.json bundled as the fallback and kept in sync via npm run check:registry): display name, accent color (the eye/accent overlay drawn on the sprite — white for VibeMon, distinct from the “Color” appearance above), image file, eye/effect coordinates (in canvas pixels on the 128x128 sprite, adjustable at 1px), and the theme palette the 3D engine paints. The character window, tray icon (downscaled from the same PNG), menus, and validation all derive from it — adding a character is one PNG plus one registry entry in vibemon-static, no code change here.

Render Mode

Settings → Character → Render Mode switches the character window between the two engines; the choice persists and the open window reloads into it.

Both engines are vendored from vibemon-static (src/engine/); three.js ships locally in src/vendor/ because the renderer CSP forbids runtime CDN imports.

Character Lock

Forces the character window to always show one character, ignoring whatever character each project’s status reports.

States

The state drives the character’s eyes/effects on the sprite, the speech bubble’s background color, and the tray icon’s background color. States are defined in a single registry (src/shared/data/states.json): bubble color/text, focus and loading behavior, and eye/effect type all live in one entry per state.

State Color Eyes Bubble text Trigger
start Cyan ■ ■ + ✦ Hello! Session begins
idle Green ■ ■ Ready Waiting for input
thinking Purple ▀ ▀ + 💭 Thinking User submits prompt
planning Teal ▀ ▀ + 💭 Planning Plan mode active
working Blue 👓 (glasses) (tool-based) Tool executing
packing Gray ▀ ▀ + 💭 Packing Context compacting
notification Yellow ● ● + ? Input? User input needed
done Green > < Done! Tool completed
sleep Navy ─ ─ + Z Zzz… 5min inactivity
alert Red ■ ■ + ! Alert Critical error/failure

Working State Text

The working state’s speech bubble shows fixed text based on the active tool:

Tool Text
Bash Running
Read Reading
Edit Editing
Write Writing
Grep / WebSearch Searching
Glob Scanning
WebFetch Fetching
Task Tasking
Default Working

State Timeout

From State Timeout To State
start, done 1 minute idle
planning, thinking, working, packing, notification, alert 5 minutes idle
idle 5 minutes sleep

After 10 minutes in sleep state, the window automatically closes. It reappears on the next status update.

Animations

Character Window

The app shows exactly one character window plus its following speech bubble:

Desktop App Features

Always on Top Modes

Mode Description
all The window stays on top regardless of state - Default
active-only Only active states (thinking, planning, working, packing, notification, alert) stay on top
disabled The window never stays on top

When active-only is selected:

Change via system tray menu: Always on Top → Select mode

Click to Focus Terminal (macOS)

When running Claude Code in multiple terminal tabs, clicking the character window automatically switches to the corresponding terminal tab.

Supported Terminals:

Requirements:

Speech Bubble

A small, transparent, click-through window that displays selected info fields (status, project name, model, memory, 5h usage, weekly usage, model-scoped weekly usage — e.g. “Fable 12% · 4d11h”) next to the character. Each plan-usage row shows its own reset countdown when available. Positioned automatically so it never overlaps the character window and stays on-screen, with an animated slide when it needs to move.

Settings Window

A dedicated settings window (tray menu → Settings…) with four tabs in a sidebar:

Changes apply immediately through the same code paths as the tray menu, and the window re-syncs when refocused so tray-made changes are reflected.

The account token is never returned to the settings renderer after it is saved; the UI only receives whether a token is configured. WebSocket authentication sends the token both as a connection URL query parameter (required by the deployed relay, which authorizes at the HTTP upgrade) and in a protocol auth message after connecting.

System Tray Menu

Grouped to mirror the Settings window’s tab order (VibeMon / Collector / AI Tools / About):

Rendering Engine

The character is rendered by a bundled engine (src/engine/vibemon-engine.js): a 128x128 canvas drawing the character PNG, state-driven pixel-art eyes/effects, and the floating animation, over a fully transparent background. Character images load remote-first from static.vibemon.io, falling back to the bundled copies in src/assets/characters/ — rendering works fully offline.

Build

Hook installation verifies the downloaded installer against the installer SHA-256 published in the same origin’s manifest.json (fetched fresh at install time), so install.py updates ship with a vibemon-docs deploy alone — no app release needed. install.py then re-checks every file it downloads against that same manifest before writing it, so install.py and manifest.json have to go out in the same deploy. Custom installer deployments can pin a specific hash via VIBEMON_INSTALLER_SHA256 together with VIBEMON_DOCS_URL; the pin takes precedence over the manifest. VIBEMON_DOCS_URL only redirects where install.py itself is fetched from — the installer always pulls the files it installs, and the manifest it checks them against, from docs.vibemon.io.

Installs run unattended but not force-approved: the app passes a platform flag and never --yes. VibeMon’s own hook scripts are upgraded in place (so Reinstall still repairs drift), while settings you own — most visibly an existing Claude Code statusLine — are left as they are. Run install.py yourself with --yes to have those replaced too. When a run fails, the installer’s own reason (a failed integrity check, a file it couldn’t write) is shown with the exit code instead of the bare code.

Detection and hook paths honor CLAUDE_CONFIG_DIR, CODEX_HOME, and KIRO_HOME. Kiro is detected through either kiro or kiro-cli.

npm run build:mac     # macOS (DMG, ZIP)
npm run build:win     # Windows (NSIS, Portable)
npm run build:linux   # Linux (AppImage, DEB)
npm run build:all     # All platforms