MCPInstall

hermes-control-interface-dashboard

Self-hosted web dashboard for managing Hermes AI agent stacks with terminals, file explorer, multi-agent gateway, and RBAC

Installs
189
Last 24h
—
Trending rank
—
Security
Not audited

Install

Works with every agent the skills CLI supports.

npx skills add https://github.com/reason-machines/hermes-skills --skill hermes-control-interface-dashboard
  1. 01

    Install

    Run the command in your project. The CLI asks which agents to install for.

  2. 02

    Describe the task

    Ask your agent for something this skill covers. It loads hermes-control-interface-dashboard automatically when relevant.

  3. 03

    Review the result

    The agent follows the SKILL.md steps, scripts and references bundled with the skill.

SKILL.md

The instructions your agent reads when the skill is triggered.

Hermes Control Interface Dashboard

Skill by 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

# 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)

# 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:

# 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

# Build frontend
npm run build

# Start server
npm start

# Development mode (auto-reload)
npm run dev

Production Deployment (Systemd)

# 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):

// 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

// 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

// 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

// 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:

// 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:

// 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:

// 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:

// 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:

// 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:

// 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:

// 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:

// 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:

// POST /api/cron
fetch('/api/cron', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
    'Authorization': `Bearer ${sessionToken}`,
    'X-CSRF-Token': csrfToken
  },
  body: JSON.stringify({
    profile: 'default',
    schedule: '0 */6 * * *',  // Every 6 hours
    command: 'hermes chat "Check system health"',
    enabled: true
  })
});

Run Job Immediately:

// POST /api/cron/:jobId/run
fetch('/api/cron/job1/run', {
  method: 'POST',
  headers: {
    'Authorization': `Bearer ${sessionToken}`,
    'X-CSRF-Token': csrfToken
  },
  body: JSON.stringify({ profile: 'default' })
});

File Explorer

List Directory:

// GET /api/files?path=~/.hermes
fetch('/api/files?path=~/.hermes', {
  headers: { 'Authorization': `Bearer ${sessionToken}` }
})
.then(res => res.json())
.then(data => {
  console.log('Files:', data.files);
  // files: [{ name: 'config.yaml', type: 'file', size: 1024 }, { name: 'sessions', type: 'directory' }]
});

Read File:

// GET /api/files/read?path=~/.hermes/config.yaml
fetch('/api/files/read?path=~/.hermes/config.yaml', {
  headers: { 'Authorization': `Bearer ${sessionToken}` }
})
.then(res => res.json())
.then(data => {
  console.log('Content:', data.content);
});

Write File:

// POST /api/files/write
fetch('/api/files/write', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
    'Authorization': `Bearer ${sessionToken}`,
    'X-CSRF-Token': csrfToken
  },
  body: JSON.stringify({
    path: '~/.hermes/custom-prompt.txt',
    content: 'You are a helpful assistant specializing in DevOps.'
  })
});

Security Note: All paths are validated and scoped to HERMES_CONTROL_ROOTS (default: ~/.hermes). Path traversal attacks are prevented.

Terminal (WebSocket)

Connect to Terminal:

const ws = new WebSocket(`ws://${location.host}/terminal`);

ws.onopen = () => {
  console.log('Terminal connected');
  ws.send(JSON.stringify({ 
    type: 'auth', 
    token: sessionToken 
  }));
};

ws.onmessage = (event) => {
  const data = JSON.parse(event.data);
  
  if (data.type === 'output') {
    console.log('Output:', data.data);
  } else if (data.type === 'error') {
    console.error('Error:', data.message);
  }
};

// Send command
ws.send(JSON.stringify({
  type: 'input',
  data: 'hermes doctor\n'
}));

// Resize PTY
ws.send(JSON.stringify({
  type: 'resize',
  cols: 80,
  rows: 24
}));

Rate Limiting: 30 commands per minute per IP.

System Maintenance

Run Doctor (Diagnostics):

// POST /api/maintenance/doctor
fetch('/api/maintenance/doctor', {
  method: 'POST',
  headers: {
    'Authorization': `Bearer ${sessionToken}`,
    'X-CSRF-Token': csrfToken
  }
})
.then(res => res.json())
.then(data => {
  console.log('Issues found:', data.issues);
  console.log('Fixes applied:', data.fixes);
});

Generate Debug Dump:

// GET /api/maintenance/dump
fetch('/api/maintenance/dump', {
  headers: { 'Authorization': `Bearer ${sessionToken}` }
})
.then(res => res.json())
.then(data => {
  console.log('System info:', data.system);
  console.log('Config:', data.config);
  console.log('Logs:', data.logs);
});

Backup System:

// GET /api/maintenance/backup
// Returns a zip file download
window.location.href = '/api/maintenance/backup?token=' + sessionToken;

Restart HCI Server:

// POST /api/maintenance/restart-hci
fetch('/api/maintenance/restart-hci', {
  method: 'POST',
  headers: {
    'Authorization': `Bearer ${sessionToken}`,
    'X-CSRF-Token': csrfToken
  }
});
// Server will restart in 2 seconds

Common Patterns

Programmatic Profile Switching

class HermesProfileManager {
  constructor(baseUrl, token, csrfToken) {
    this.baseUrl = baseUrl;
    this.token = token;
    this.csrfToken = csrfToken;
  }

  async switchProfile(from, to) {
    // Stop current profile gateway
    await fetch(`${this.baseUrl}/api/agents/gateway/stop`, {
      method: 'POST',
      headers: {
        'Content-Type': 'application/json',
        'Authorization': `Bearer ${this.token}`,
        'X-CSRF-Token': this.csrfToken
      },
      body: JSON.stringify({ profile: from })
    });

    // Start new profile gateway
    await fetch(`${this.baseUrl}/api/agents/gateway/start`, {
      method: 'POST',
      headers: {
        'Content-Type': 'application/json',
        'Authorization': `Bearer ${this.token}`,
        'X-CSRF-Token': this.csrfToken
      },
      body: JSON.stringify({ profile: to })
    });

    console.log(`Switched from ${from} to ${to}`);
  }

  async createTestProfile(name, baseProfile = 'default') {
    // Clone base profile
    await fetch(`${this.baseUrl}/api/agents/profiles`, {
      method: 'POST',
      headers: {
        'Content-Type': 'application/json',
        'Authorization': `Bearer ${this.token}`,
        'X-CSRF-Token': this.csrfToken
      },
      body: JSON.stringify({ name, cloneFrom: baseProfile })
    });

    // Update config for testing (lower temperature, etc.)
    const config = await fetch(`${this.baseUrl}/api/agents/config?profile=${name}`, {
      headers: { 'Authorization': `Bearer ${this.token}` }
    }).then(res => res.json());

    const modifiedConfig = config.config.replace(/temperature: \d\.\d+/, 'temperature: 0.3');

    await fetch(`${this.baseUrl}/api/agents/config`, {
      method: 'PUT',
      headers: {
        'Content-Type': 'application/json',
        'Authorization': `Bearer ${this.token}`,
        'X-CSRF-Token': this.csrfToken
      },
      body: JSON.stringify({ profile: name, config: modifiedConfig })
    });

    console.log(`Test profile ${name} created`);
  }
}

// Usage
const manager = new HermesProfileManager('http://localhost:10272', sessionToken, csrfToken);
await manager.createTestProfile('experiment-1');
await manager.switchProfile('default', 'experiment-1');

Bulk Session Export

async function exportAllSessions(profile) {
  const sessions = await fetch(`/api/chat/sessions?profile=${profile}`, {
    headers: { 'Authorization': `Bearer ${sessionToken}` }
  }).then(res => res.json());

  const exports = [];
  
  for (const session of sessions.sessions) {
    const data = await fetch(`/api/chat/sessions/${session.id}/export?profile=${profile}`, {
      headers: { 'Authorization': `Bearer ${sessionToken}` }
    }).then(res => res.json());
    
    exports.push({
      id: session.id,
      title: session.title,
      messages: data.messages
    });
  }

  // Save to file
  const blob = new Blob([JSON.stringify(exports, null, 2)], { type: 'application/json' });
  const url = URL.createObjectURL(blob);
  const a = document.createElement('a');
  a.href = url;
  a.download = `hermes-sessions-${profile}-${Date.now()}.json`;
  a.click();
}

// Usage
await exportAllSessions('production');

Custom Token Usage Reporter

class TokenUsageReporter {
  constructor(baseUrl, token) {
    this.baseUrl = baseUrl;
    this.token = token;
  }

  async generateReport(profile, range = '30d') {
    const stats = await fetch(
      `${this.baseUrl}/api/usage/stats?range=${range}&profile=${profile}`,
      { headers: { 'Authorization': `Bearer ${this.token}` } }
    ).then(res => res.json());

    const report = {
      period: range,
      profile: profile,
      summary: {
        totalSessions: stats.totalSessions,
        totalMessages: stats.totalMessages,
        totalTokens: stats.totalTokens,
        estimatedCost: stats.estimatedCost,
        avgTokensPerSession: Math.round(stats.totalTokens / stats.totalSessions)
      },
      topModels: stats.modelBreakdown.slice(0, 5),
      topTools: stats.topTools.slice(0, 10),
      platformDistribution: stats.platformBreakdown
    };

    console.table(report.topModels);
    console.table(report.topTools);
    
    return report;
  }

  async compareProfiles(profileA, profileB, range = '7d') {
    const [statsA, statsB] = await Promise.all([
      fetch(`${this.baseUrl}/api/usage/stats?range=${range}&profile=${profileA}`,
        { headers: { 'Authorization': `Bearer ${this.token}` } }).then(res => res.json()),
      fetch(`${this.baseUrl}/api/usage/stats?range=${range}&profile=${profileB}`,
        { headers: { 'Authorization': `Bearer ${this.token}` } }).then(res => res.json())
    ]);

    return {
      profileA: { name: profileA, cost: statsA.estimatedCost, tokens: statsA.totalTokens },
      profileB: { name: profileB, cost: statsB.estimatedCost, tokens: statsB.totalTokens },
      costDiff: statsA.estimatedCost - statsB.estimatedCost,
      tokenDiff: statsA.totalTokens - statsB.totalTokens
    };
  }
}

// Usage
const reporter = new TokenUsageReporter('http://localhost:10272', sessionToken);
const report = await reporter.generateReport('production', '30d');
console.log('Monthly cost:', report.summary.estimatedCost);

const comparison = await reporter.compareProfiles('production', 'staging', '7d');
console.log('Cost difference:', comparison.costDiff);

Configuration Examples

Multi-Platform Setup

~/.hermes/profiles/production/config.yaml:

llm:
  model: hermes-3
  provider: openrouter
  api_key: ${OPENROUTER_API_KEY}
  temperature: 0.7
  max_tokens: 4000

platforms:
  telegram:
    enabled: true
    token: ${TELEGRAM_BOT_TOKEN}
  
  whatsapp:
    enabled: true
    account_sid: ${TWILIO_ACCOUNT_SID}
    auth_token: ${TWILIO_AUTH_TOKEN}
    from_number: ${TWILIO_PHONE_NUMBER}
  
  slack:
    enabled: true
    bot_token: ${SLACK_BOT_TOKEN}
    app_token: ${SLACK_APP_TOKEN}

memory:
  provider: honcho
  honcho_url: http://localhost:8000
  honcho_app_name: hermes-prod

tools:
  web_search:
    enabled: true
    provider: tavily
    api_key: ${TAVILY_API_KEY}
  
  code_execution:
    enabled: true
    sandbox: docker
    timeout: 30

prompts:
  system: |
    You are Hermes, a production AI assistant for the DevOps team.
    Focus on accuracy and provide detailed technical responses.

Custom RBAC Setup

Create a "Analyst" role (read-only + chat):

// Via Maintenance → Users UI or API
const analystPermissions = [
  'agents:read',
  'chat:read',
  'chat:write',
  'sessions:read',
  'config:read',
  'gateway:logs'
];

await fetch('/api/users', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
    'Authorization': `Bearer ${adminToken}`,
    'X-CSRF-Token': csrfToken
  },
  body: JSON.stringify({
    username: 'analyst1',
    password: 'secure-password',
    role: 'custom',
    permissions: analystPermissions
  })
});

Scheduled Maintenance Cron

// Daily health check at 3 AM
await fetch('/api/cron', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
    'Authorization': `Bearer ${sessionToken}`,
    'X-CSRF-Token': csrfToken
  },
  body: JSON.stringify({
    profile: 'default',
    schedule: '0 3 * * *',
    command: 'hermes doctor --auto-fix && hermes chat "Daily system report"',
    enabled: true
  })
});

// Weekly backup every Sunday at 2 AM
await fetch('/api/cron', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
    'Authorization': `Bearer ${sessionToken}`,
    'X-CSRF-Token': csrfToken
  },
  body: JSON.stringify({
    profile: 'default',
    schedule: '0 2 * * 0',
    command: 'cd ~/.hermes && tar -czf backup-$(date +%Y%m%d).tar.gz .',
    enabled: true
  })
});

Troubleshooting

Gateway Won't Start

Symptom: "Failed to start gateway" error

Solutions:

# 1. Check if port is already in use
sudo lsof -i :8000  # Default gateway port

# 2. View gateway logs
journalctl -u hermes-gateway-default -n 50

# 3. Check systemd service status
systemctl status hermes-gateway-default

# 4. Manually test gateway
hermes gateway start --profile default --debug

# 5. Check config.yaml syntax
hermes config validate --profile default

WebSocket Connection Fails

Symptom: Terminal or chat streaming doesn't work

Solutions:

// 1. Check WebSocket origin in server.js
// Ensure your domain is allowed in WebSocket verification

// 2. If behind reverse proxy, configure headers:
// Nginx example:
/*
location /terminal {
    proxy_pass http://localhost:10272;
    proxy_http_version 1.1;
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection "upgrade";
    proxy_set_header Host $host;
}
*/

// 3. Check browser console for CORS errors
// Update .env if needed:
// HERMES_CONTROL_CORS_ORIGIN=https://yourdomain.com

Session Not Resuming

Symptom: --continue <session-id> creates new session instead

Solutions:

# 1. Verify session exists
ls -la ~/.hermes/sessions/

# 2. Check session ID format
# New format: abc123
# Legacy format: Session_abc123

# 3. Test CLI directly
hermes chat --continue abc123 "test message"

# 4. Check session file permissions
chmod 644 ~/.hermes/sessions/abc123.json

# 5. Review chat logs in HCI
# Navigate to Agents → [Profile] → Sessions tab

Token Analytics Not Showing

Symptom: Usage page shows zero data

Solutions:

# 1. Verify session log files exist
ls -la ~/.hermes/sessions/*.json

# 2. Check token tracking is enabled in config
cat ~/.hermes/profiles/default/config.yaml | grep -A5 analytics

# 3. Manually trigger analytics rebuild
hermes analytics rebuild

# 4. Check for parsing errors in logs
tail -f ~/.hermes/hci.log | grep analytics

Permission Denied Errors

Symptom: "Permission denied" when accessing files/terminals

Solutions:

# 1. Check user permissions on ~/.hermes
ls -ld ~/.hermes
chmod 755 ~/.hermes

# 2. If running as non-root, ensure RBAC role allows action
# Check Maintenance → Users → [Your User] → Permissions

# 3. For terminal: verify user has shell access
echo $SHELL

# 4. For files: check HERMES_CONTROL_ROOTS in .env
# Default: ~/.hermes (user must have read/write access)

High Memory Usage

Symptom: HCI process consuming excessive RAM

Solutions:

# 1. Check active WebSocket connections
# Navigate to browser DevTools → Network → WS tab

# 2. Restart HCI to clear stale connections
systemctl restart hermes-control
# OR via UI: Maintenance → HCI Restart

# 3. Limit concurrent sessions
# Edit server.js to add connection limits if needed

# 4. Check for memory leaks in logs
node --expose-gc server.js

CSRF Token Mismatch

Symptom: "Invalid CSRF token" on form submissions

Solutions:

// 1. Ensure CSRF token is included in request headers
const csrfToken = document.querySelector('meta[name="csrf-token"]').content;

fetch('/api/agents/profiles', {
  method: 'POST',
  headers: {
    'X-CSRF-Token': csrfToken,
    'Content-Type': 'application/json'
  },
  body: JSON.stringify({ name: 'test' })
});

// 2. Check session hasn't expired
// Default: 24 hour session timeout

// 3. Clear cookies and re-login
document.cookie.split(";").forEach(c => {
  document.cookie = c.replace(/^ +/, "").replace(/=.*/, "=;expires=" + new Date().toUTCString() + ";path=/");
});

Gateway Logs Not Streaming

Symptom: Gateway log viewer shows "Connecting..." indefinitely

Solutions:

# 1. Verify gateway is actually running
systemctl status hermes-gateway-default

# 2. Check systemd journal accessibility
sudo journalctl -u hermes-gateway-default --no-pager -n 10

# 3. Grant user access to systemd journal (if non-root)
sudo user

FAQ

What does the hermes-control-interface-dashboard skill do?

Self-hosted web dashboard for managing Hermes AI agent stacks with terminals, file explorer, multi-agent gateway, and RBAC

How do I install hermes-control-interface-dashboard?

Run npx skills add https://github.com/reason-machines/hermes-skills --skill hermes-control-interface-dashboard in your project. The skills CLI detects the agents you use and copies the skill into the right folder. For Claude Code you can also place the skill folder at ~/.claude/skills/hermes-control-interface-dashboard/ (personal) or .claude/skills/hermes-control-interface-dashboard/ (project).

Which AI agents can use hermes-control-interface-dashboard?

Any agent that supports the open Agent Skills format (a folder with a SKILL.md file), including Claude Code, Codex, Cursor, GitHub Copilot, Gemini CLI, Windsurf, Cline, OpenCode and more.

Is hermes-control-interface-dashboard safe to install?

No partner security audit is available yet. Skills can run commands and scripts, so read the SKILL.md and any bundled files before installing.

Who maintains hermes-control-interface-dashboard?

It is published by reason-machines in reason-machines/hermes-skills. It has 189 recorded installs.

More from reason-machines/hermes-skills

View all →

hermes-agent-self-evolution

reason-machines/hermes-skills

Evolutionary self-improvement for Hermes Agent using DSPy + GEPA to optimize skills, prompts, and code

AI & Agents323 installs

hermes-webui-agent

reason-machines/hermes-skills

Open the skill to read its SKILL.md instructions.

262 installs

awesome-hermes-agent-ecosystem

reason-machines/hermes-skills

Open the skill to read its SKILL.md instructions.

232 installs

hermes-agent-framework

reason-machines/hermes-skills

Open the skill to read its SKILL.md instructions.

219 installs

hermes-workspace-ai-agent-ui

reason-machines/hermes-skills

Open the skill to read its SKILL.md instructions.

Frontend & Design213 installs

hermes-desktop-companion

reason-machines/hermes-skills

Open the skill to read its SKILL.md instructions.

206 installs

Popular data & databases skills

View category →

Postgres best practices maintained by Supabase, for Postgres running anywhere. Load this skill BEFORE writing or changing anything that lives in a Postgres database: creating or altering tables and columns (including choosing column types), schema design, migrations and declarative schema files, RLS policies and the tests that verify them, indexes, triggers, database functions, queues and scheduled jobs (pgcron, pgmq), vector/semantic search (pgvector), and restoring dumps (pgrestore) or importing data. Also load it when diagnosing slow queries, high CPU, timeouts, EXPLAIN plans, connection exhaustion, locking, bloat, or rows visible to the wrong user or tenant. This is not just a performance guide — schema, migration, security, and SQL authoring tasks need these rules too, even for a one-column change or a single query.

OfficialData & Databases462.2K installs

prisma-client-api

prisma/skills

Prisma Client API reference covering model queries, filters, operators, and client methods. Use when writing database queries, using CRUD operations, filtering data, or configuring Prisma Client. Triggers on "prisma query", "findMany", "create", "update", "delete", "$transaction".

OfficialData & Databases393.5K installs

Deprecated compatibility name for prisma-orm-setup. Use only when a user or existing integration explicitly invokes prisma-database-setup; otherwise select prisma-orm-setup.

OfficialData & Databases392.3K installs

prisma-cli

prisma/skills

Prisma ORM 7 CLI reference for existing Prisma 7 applications or explicitly selected Prisma 7 workflows. Covers prisma init, generate, migrate, db, dev, studio, and mcp. For setup, connection repair, or Prisma 8, use prisma-orm-setup; not the Prisma Platform CLI.

OfficialData & Databases390.8K installs

prisma-postgres

prisma/skills

Deprecated compatibility name for prisma-postgres-setup. Use only when a user or existing integration explicitly invokes prisma-postgres; otherwise select prisma-postgres-setup.

OfficialData & Databases384.4K installs

Required reference for Prisma ORM 7 SQL driver adapter work. Use when implementing or modifying adapters, adding database drivers, or touching SqlDriverAdapter, Transaction, savepoint, result mapping, or DriverAdapterError behavior. Covers current transaction lifecycle, optional savepoint hooks, original database-error preservation, and verification.

OfficialData & Databases378.9K installs