# CLAUDE.md — Hermes Web UI Development Guide
## Project Overview
Hermes Web UI is a web dashboard for [Hermes Agent](https://github.com/EKKOLearnAI/hermes-web-ui), a multi-platform AI chat system. It provides session management, scheduled jobs, usage analytics, model configuration, channel management (Telegram, Discord, Slack, WhatsApp, etc.), an integrated terminal, and a streaming chat interface.
The project is designed for **multi-agent extensibility** — Hermes is the first agent integration. All agent-specific code is namespaced under `hermes/` directories, so future agents can be added alongside without conflicts.
**Tech stack:**
- **Frontend:** Vue 3 (Composition API, `
{{ t('common.save') }}
```
Key patterns:
- Import Naive UI components directly from `naive-ui`
- Use `useMessage()` for toast notifications
- Use `useI18n()` for translations, access via `t('key.path')`
- Scoped SCSS with `@use '@/styles/variables' as *`
### Vue Composables
Shared composables live in `packages/client/src/composables/`:
- `useKeyboard.ts` — keyboard shortcut handling
- `useTheme.ts` — theme management (dark/light mode)
### Pinia Stores
Use setup store syntax (function passed to `defineStore`):
```ts
import { defineStore } from 'pinia'
import { ref } from 'vue'
export const useMyStore = defineStore('myStore', () => {
const items = ref- ([])
const loading = ref(false)
async function fetchItems() {
loading.value = true
try {
items.value = await apiCall()
} finally {
loading.value = false
}
}
return { items, loading, fetchItems }
})
```
Existing stores in `packages/client/src/stores/hermes/`: `app`, `chat`, `jobs`, `models`, `settings`, `usage`, `gateways`, `profiles`.
### API Layer
Agent-specific API modules live in `api/{agent}/`. The shared base `api/client.ts` provides:
- `request(path, options)` — typed fetch wrapper with automatic `Authorization: Bearer` header and global 401 handling (clears token, redirects to login)
- `getApiKey()` / `setApiKey()` / `clearApiKey()` — token management via `localStorage`
- `getBaseUrlValue()` — configurable server URL from `localStorage`
```ts
// packages/client/src/api/hermes/sessions.ts
import { request } from '../client'
export async function fetchSessions(source?: string, limit?: number): Promise {
const params = new URLSearchParams()
if (source) params.set('source', source)
if (limit) params.set('limit', String(limit))
const query = params.toString()
const res = await request<{ sessions: SessionSummary[] }>(`/api/hermes/sessions${query ? `?${query}` : ''}`)
return res.sessions
}
```
**API path rules:**
- Local BFF endpoints: `/api/hermes/{resource}` — handled by Koa routes, call Hermes CLI directly
- Gateway proxy endpoints: `/api/hermes/v1/*`, `/api/hermes/jobs/*` — forwarded to upstream Hermes gateway
- Shared endpoints: `/health`, `/upload`, `/webhook` — no agent prefix
### i18n
Eight locales in `packages/client/src/i18n/locales/`: `en`, `zh`, `de`, `es`, `fr`, `ja`, `ko`, `pt`. Flat nested object structure organized by feature section:
```ts
// en.ts
export default {
chat: {
emptyState: 'Start a conversation with Hermes Agent',
inputPlaceholder: 'Type a message...',
sessions: 'Sessions',
// ...
},
common: {
save: 'Save',
cancel: 'Cancel',
delete: 'Delete',
// ...
},
}
```
When adding new strings, add to all locale files.
### SCSS Styling
- Global variables in `packages/client/src/styles/variables.scss` — import with `@use '@/styles/variables' as *`
- Naive UI theme overrides in `packages/client/src/styles/theme.ts`
- Code block styling in `packages/client/src/styles/code-block.scss`
- Theme: "Pure Ink" (monochrome black/white/gray), no color accent
- Mobile breakpoint: `$breakpoint-mobile: 768px`
- Global resets and shared classes in `packages/client/src/styles/global.scss`
- Component styles are always `