# Architecture hermes-ui is a TypeScript project that ships a browser dashboard and a Koa backend around Hermes Agent. It runs on Node.js and talks to Hermes over an Agent Bridge (see "Hermes Integration" below). ## Package Boundaries | Area | Path | Responsibility | | --- | --- | --- | | Client | `packages/client/src` | Vue UI, routing, Pinia stores, API wrappers, i18n, browser-visible state. | | Server | `packages/server/src` | HTTP API, auth, Socket.IO, SQLite stores, file access, Hermes runtime integration. | | Skills | `packages/skills` | Built-in skills injected into the Hermes skills directory. | | Legacy agent | `packages/ekko-agent` | In-house agent runtime. Slated for removal in Phase 003; do not extend it. | | Tests | `tests` | Vitest unit/integration tests and Playwright browser tests. | | CI | `.github/workflows` | Build, e2e, lockfile, Docker, and release automation. | This is not an npm workspaces monorepo. `packages/client` and `packages/server` have no `package.json`; their dependencies are declared in the root `package.json`. ## Request Flow 1. The browser loads the Vite-built client from the Koa server. 2. Client modules call API helpers from `packages/client/src/api`. 3. Server routes in `packages/server/src/routes` wire HTTP paths to controllers. 4. Controllers validate request concerns and delegate reusable behavior to services. 5. Services own side effects: files, SQLite, Hermes profiles, subprocesses, bridges, and credentials. 6. Long-running chat and group-chat flows use Socket.IO namespaces managed by server services. Keep each layer narrow. Routes should not grow business logic, and client code should not duplicate server persistence rules. ## State And Data Ownership - Web UI state defaults to `~/.hermes-web-ui` through `config.appHome`. - `HERMES_WEB_UI_HOME` and `HERMES_WEBUI_STATE_DIR` override Web UI state location. These identifiers are intentionally kept from the 0.6.x line: renaming them would break existing deployment scripts and orphan existing data directories. - Hermes Agent state lives under Hermes profile directories and must stay distinct from Web UI state. Profile isolation is done by injecting `HERMES_HOME` into child processes, never by copying directories. - Hermes `state.db` is read-only and owned by the Hermes Agent. Node-side code must never open it; read session history through the bridge's `getHistory`/`getOutput`. - The project's own SQLite store under `packages/server/src/db` is the only writable store for sessions, messages, and usage. There is no startup import sync from Hermes state. - Uploads default to `config.uploadDir`, which is derived from the Web UI home unless `UPLOAD_DIR` is set. - Runtime data directories must also live under the Web UI home, not beside built `dist` assets. - Profile-scoped Hermes data should use existing profile helpers instead of manually joining paths. ## Server Structure - `routes/` registers HTTP and WebSocket entry points. - `controllers/` handles request-level behavior. - `services/` owns reusable IO, domain behavior, external process calls, and integration logic. - `db/` owns SQLite schemas and stores. - `middleware/` owns request middleware such as user auth. - `shared/` contains cross-server constants and helpers. Architecture rules: - Register local API routes before proxy catch-all routes. - Keep auth behavior centralized in `packages/server/src/services/auth.ts`. - Prefer `execFile` or `spawn` with argument arrays over shell command strings. - All Hermes CLI calls go through `execHermesWithBin`/`spawnHermesWithBin` in `services/hermes/hermes-process.ts`. - Use structured file and YAML/JSON parsers when editing structured data. ## Hermes Integration Chat runs through the Agent Bridge, which is the only supported path: ``` browser --Socket.IO--> Koa/Node server --JSON over Unix socket--> Python child └- hermes-agent run_agent.AIAgent ``` - `services/hermes/agent-bridge/python/` is vendored, read-only code. The only exception is the `HERMES_DESKTOP` checks in `bridge_runtime.py`, which hide the Windows console window for git subprocesses and must stay. - `services/hermes/group-chat/`, `lib/context-compressor/`, and `services/hermes/context-engine/` form the chat chain. Changes there require a `docs/chat-chain-changes/-.md` fragment. - The Hermes CLI is user-installed. Point `HERMES_BIN` at the executable, or let the server resolve `hermes` from `PATH`. ## Client Structure - `views/` contains route-level screens. - `components/` contains reusable UI. - `stores/` contains Pinia state. - `api/` contains HTTP clients and should use `packages/client/src/api/client.ts`. - `i18n/` contains locale messages for user-facing strings. Only `zh` and `en` are supported. - `styles/` contains global styling and theme primitives. Frontend rules: - Use Vue 3 Composition API with `