- name
- hermes-control-interface-dashboard
- description
- Self-hosted web dashboard for managing Hermes AI agent stacks with terminals, file explorer, multi-agent gateway, and RBAC
- triggers
- ["set up hermes control interface dashboard","manage hermes agents through web ui","configure hermes control interface","deploy hermes dashboard with rbac","use hermes control interface api","troubleshoot hermes control interface","create users in hermes control","manage hermes gateway profiles"]
# Hermes Control Interface Dashboard
> Skill by [ara.so](https://ara.so) — Hermes Skills collection.
A self-hosted web dashboard for managing the Hermes AI agent stack. Provides browser-based terminal, file explorer, session management, cron jobs, multi-agent gateway control, token analytics, and RBAC — all behind password authentication.
**Stack:** Vanilla JS + Vite, Node.js, Express, WebSocket, xterm.js
**Port:** 10272 (default)
**Version:** 3.5.0
## Installation
### Prerequisites
```bash
# Required: Node.js 18+, build tools for node-pty
sudo apt-get install -y python3 make g++ # Ubuntu/Debian
# OR
brew install python3 # macOS
```
### Manual Installation (Recommended)
```bash
# Clone repository
git clone https://github.com/xaspx/hermes-control-interface.git
cd hermes-control-interface
# Install dependencies
npm install
# Configure environment
cp .env.example .env
# Generate secure secret
openssl rand -hex 32 # Copy output for HERMES_CONTROL_SECRET
# Edit .env with your settings
nano .env
```
### Environment Configuration
**Minimal `.env`:**
```bash
# Required
HERMES_CONTROL_PASSWORD=your-secure-password-here
HERMES_CONTROL_SECRET=<output-from-openssl-rand-hex-32>
# Optional
PORT=10272
NODE_ENV=production
HERMES_CONTROL_ROOTS=~/.hermes,~/Documents # File explorer roots
```
### Build and Run
```bash
# Build frontend
npm run build
# Start server
npm start
# Development mode (auto-reload)
npm run dev
```
### Production Deployment (Systemd)
```bash
# Create systemd service
sudo tee /etc/systemd/system/hermes-control.service > /dev/null <<EOF
[Unit]
Description=Hermes Control Interface
After=network.target
[Service]
Type=simple
User=root
WorkingDirectory=$(pwd)
ExecStart=/usr/bin/node server.js
Restart=always
Environment=NODE_ENV=production
[Install]
WantedBy=multi-user.target
EOF
# Enable and start
sudo systemctl enable hermes-control
sudo systemctl start hermes-control
sudo systemctl status hermes-control
```
## Core Features
### Authentication & RBAC
HCI supports multi-user authentication with role-based access control:
**Roles:**
- `admin` — Full access (all 20 permissions)
- `viewer` — Read-only access
- `custom` — Granular permission selection
**Key Permissions:**
- `agents:read`, `agents:write`, `agents:delete`
- `chat:read`, `chat:write`
- `sessions:read`, `sessions:write`, `sessions:delete`
- `config:read`, `config:write`
- `gateway:control`, `gateway:logs`
- `files:read`, `files:write`
- `terminal:exec`
- `users:manage`
- `system:maintain`
- `cron:manage`
**Creating Users (via Maintenance → Users):**
```javascript
// API endpoint: POST /api/users
{
"username": "alice",
"password": "secure-password",
"role": "viewer"
}
```
### Multi-Agent Gateway Management
**Profile Structure:**
```
~/.hermes/
├── profiles/
│ ├── default/
│ │ └── config.yaml
│ ├── production/
│ │ └── config.yaml
│ └── testing/
│ └── config.yaml
```
**API: List Profiles**
```javascript
// GET /api/agents/profiles
fetch('/api/agents/profiles', {
headers: {
'Authorization': `Bearer ${sessionToken}`,
'X-CSRF-Token': csrfToken
}
})
.then(res => res.json())
.then(data => {
// data.profiles = [{ name: 'default', isDefault: true, status: 'running', model: 'hermes-3' }]
});
```
**API: Start/Stop Gateway**
```javascript
// POST /api/agents/gateway/start
fetch('/api/agents/gateway/start', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': `Bearer ${sessionToken}`,
'X-CSRF-Token': csrfToken
},
body: JSON.stringify({ profile: 'production' })
})
.then(res => res.json())
.then(data => console.log(data.message)); // "Gateway started for production"
```
**API: Create Profile**
```javascript
// POST /api/agents/profiles
fetch('/api/agents/profiles', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': `Bearer ${sessionToken}`,
'X-CSRF-Token': csrfToken
},
body: JSON.stringify({
name: 'staging',
cloneFrom: 'default' // Optional: clone existing config
})
});
```
### Chat Interface
**Session Management:**
```javascript
// POST /api/chat/send
const sendMessage = async (message, sessionId = null) => {
const args = sessionId
? ['--continue', sessionId, message]
: ['--continue', '', message]; // Empty string creates new session
const response = await fetch('/api/chat/send', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': `Bearer ${sessionToken}`,
'X-CSRF-Token': csrfToken
},
body: JSON.stringify({
profile: 'default',
args: args,
suppressBanner: true // Use -Q flag for clean output
})
});
const reader = response.body.getReader();
const decoder = new TextDecoder();
while (true) {
const { done, value } = await reader.read();
if (done) break;
const chunk = decoder.decode(value);
const lines = chunk.split('\n');
for (const line of lines) {
if (line.startsWith('data: ')) {
const data = JSON.parse(line.slice(6));
if (data.type === 'session_id') {
console.log('Session ID:', data.sessionId);
} else if (data.type === 'tool_call') {
console.log('Tool:', data.tool, 'Status:', data.status);
} else if (data.type === 'output') {
console.log('Output:', data.text);
}
}
}
}
};
// Usage
await sendMessage('What is the weather?'); // New session
await sendMessage('And tomorrow?', 'abc123'); // Continue session
```
**List Sessions:**
```javascript
// GET /api/chat/sessions?profile=default
fetch('/api/chat/sessions?profile=default', {
headers: { 'Authorization': `Bearer ${sessionToken}` }
})
.then(res => res.json())
.then(data => {
// data.sessions = [{ id: 'abc123', title: 'Weather discussion', timestamp: '2026-05-17...' }]
});
```
**Rename Session:**
```javascript
// PUT /api/chat/sessions/:sessionId
fetch('/api/chat/sessions/abc123', {
method: 'PUT',
headers: {
'Content-Type': 'application/json',
'Authorization': `Bearer ${sessionToken}`,
'X-CSRF-Token': csrfToken
},
body: JSON.stringify({ title: 'Weather Research' })
});
```
### Token Analytics
**Get Usage Stats:**
```javascript
// GET /api/usage/stats?range=7d&profile=default
fetch('/api/usage/stats?range=7d&profile=default', {
headers: { 'Authorization': `Bearer ${sessionToken}` }
})
.then(res => res.json())
.then(data => {
console.log('Sessions:', data.totalSessions);
console.log('Tokens:', data.totalTokens);
console.log('Cost:', data.estimatedCost);
console.log('Models:', data.modelBreakdown);
// modelBreakdown: [{ model: 'hermes-3', sessions: 42, tokens: 150000, avgTokens: 3571 }]
console.log('Platforms:', data.platformBreakdown);
// platformBreakdown: [{ platform: 'CLI', count: 30 }, { platform: 'Telegram', count: 12 }]
console.log('Top Tools:', data.topTools);
// topTools: [{ tool: 'web_search', calls: 15, success_rate: 0.93 }]
});
```
**Query Ranges:** `today`, `7d`, `30d`, `90d`
### Configuration Management
**Get Config:**
```javascript
// GET /api/agents/config?profile=default
fetch('/api/agents/config?profile=default', {
headers: { 'Authorization': `Bearer ${sessionToken}` }
})
.then(res => res.json())
.then(data => {
console.log('Config YAML:', data.config);
console.log('Categories:', data.categories);
// categories: ['llm', 'platforms', 'memory', 'tools', 'prompts', ...]
});
```
**Update Config:**
```javascript
// PUT /api/agents/config
fetch('/api/agents/config', {
method: 'PUT',
headers: {
'Content-Type': 'application/json',
'Authorization': `Bearer ${sessionToken}`,
'X-CSRF-Token': csrfToken
},
body: JSON.stringify({
profile: 'default',
config: `
llm:
model: hermes-3
provider: openrouter
temperature: 0.7
platforms:
telegram:
enabled: true
token: \${TELEGRAM_BOT_TOKEN}
memory:
provider: honcho
honcho_url: http://localhost:8000
`
})
});
```
**Reset Category to Defaults:**
```javascript
// POST /api/agents/config/reset
fetch('/api/agents/config/reset', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': `Bearer ${sessionToken}`,
'X-CSRF-Token': csrfToken
},
body: JSON.stringify({
profile: 'default',
category: 'llm'
})
});
```
### Cron Job Management
**List Cron Jobs:**
```javascript
// GET /api/cron?profile=default
fetch('/api/cron?profile=default', {
headers: { 'Authorization': `Bearer ${sessionToken}` }
})
.then(res => res.json())
.then(data => {
// data.jobs = [{ id: 'job1', schedule: '0 9 * * *', command: 'hermes chat "Daily summary"', enabled: true, nextRun: '...' }]
});
```
**Create Cron Job:**
```javascript
// POST /api/cron
fetch('/api/cron', {
Voir sur GitHub