Hermes Control Interface: port, version, and a missing install.sh
A self-hosted web dashboard for the Hermes AI agent stack. Provides a browser-based terminal, file explorer, session overview, cron management, system metrics, and an agent status panel — all behind a single password gate.
At a glance
- What is it?
- A self-hosted web dashboard for the Hermes AI agent stack, sitting behind one bcrypt password gate. Its page list is broad; its own files disagree with each other in places you can check before installing, starting with the port number and a setup script the checkout does not contain.
- Who is it for?
- Weigh this project by how its files agree with each other rather than by how many pages it has. One person running a single Hermes agent on their own machine gets a working dashboard from the Quick Start, as long as they read the port their build actually binds and start the server themselves.
- Can I use it commercially?
- Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository last received commits 98 days ago.
- What is it written in?
- Mainly JavaScript, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on October 2, 2026, and from our analysis. They are not legal advice.
Editorial analysis
The Quick Start says port 10274 and the env template says 10272
The Quick Start sends you to http://localhost:10274, and the Configuration table gives `PORT` a default of `10274`. The environment template that the same Quick Start tells you to copy says something else, twice: `# Port to listen on. Default: 10272` and, below it, `# PORT=10272`. Those two numbers cannot both be what a fresh install binds. The architecture diagram labels the transport `HTTPS :10274`, so the disagreement sits between the file you are told to copy and the two places that agree with each other. That template also repeats a block: the optional HTTPS notes, the self-signed certificate command, the two HCI_SSL variable paths, and a port line appear once, get interrupted by a bare port comment, and then start over from the top. An interrupted copy like that is what a chunk of documentation pasted into the middle of the optional section leaves behind. Nothing in the required part of the template sets a port, so `PORT` stays unset on a plain copy and whatever server.js falls back to decides where the dashboard appears. The dependable check is the value your own build binds, not either number in the repository.
npm run setup targets install.sh, which the root does not list
The package manifest wires the setup script to a shell file: `"setup": "bash install.sh"`. No such file sits at the top level of the repository. What is listed there is `.env.example`, `.github/`, `.gitignore`, `CODE_OF_CONDUCT.md`, `CONTRIBUTING.md`, `LICENSE`, `README.md`, `RELEASE_v3.6.0.md`, `SECURITY_AUDIT.md`, `auth.js`, `dist/`, `docs/`, `hci.config.yaml.example`, `lib/`, `package-lock.json`, `package.json`, `playwright.config.js`, `scripts/`, `server.js`, `src/`, `test/`, `tests/`, and `vite.config.js`. So the one command that sounds like a guided installer resolves to a path this checkout does not have, and the Quick Start never mentions setup at all. It hands you a build and a direct server start instead:
git clone https://github.com/xaspx/hermes-control-interface.git
cd hermes-control-interface
cp .env.example .env # set HERMES_CONTROL_PASSWORD + HERMES_CONTROL_SECRET
npm install && npm run build
node server.js # → http://localhost:10274Two test directories and two names for one script sit in the same manifest. The test entry point is `node --test test/*.test.js`, a glob over one directory, while `test/` and `tests/` both appear at the root, so whatever is under the second directory is not collected by that glob. The end-to-end entry point is `npx playwright test`, which uses `playwright.config.js`. And `start` and `serve` are two spellings of `node server.js`, which the Quick Start then runs directly, so the documented first command and the defined scripts say the same thing three times over.
The update recipe pulls from a remote the clone never creates
The Updating block tells you to fetch from a remote named upstream:
git pull upstream main
npm install
npm run build
# Restart your HCI service (adjust service name):
systemctl restart hci-stagingThe Quick Start clone points at the repository over HTTPS and creates `origin`, and nothing else. A checkout made by the documented steps has no `upstream` to pull from, so the update recipe works only for someone who cloned a fork and kept the original around, which is a step the docs never describe. After the pull, the same block restarts a unit named `hci-staging` and asks you to adjust the service name, which makes that staging label the only glimpse of a systemd unit anywhere outside docs/INSTALL.md. The version line has not kept up either. The stack header reads `Version: 3.6.1` while the manifest reads `3.6.2`, and the newest tag, v3.6.2, carries the title Profile-Based Access Control & Windows Compatibility and was published on 2026-06-28, the same day as the last push on record. The Profile-Based Access Control section describes exactly that work, so the section was written for 3.6.2 while the number above it stayed on the previous release, 3.6.1, which shipped on 2026-06-16 with the Workspace page.
config.yaml feeds the health grid and appears in no configuration table
The architecture diagram puts `config.yaml` on the filesystem side next to logs and skills, and the Office panel builds its health grid from `config.yaml + kanban.db`. Neither file has a documented schema. The Configuration section is entirely environment variables: `HERMES_CONTROL_PASSWORD`, `HERMES_CONTROL_SECRET`, `PORT`, `HERMES_CONTROL_HOME` defaulting to `~/.hermes`, and `HERMES_PROJECTS_ROOT` defaulting to the parent of the repo. The root also carries `hci.config.yaml.example`, a YAML template for a surface that table never mentions, and the dependency list loads two YAML parsers at once, `js-yaml` at ^4.1.1 and `yaml` at ^2.9.0, which is the shape a parser migration takes while it is still in progress. Three configuration surfaces are in play then, and only the env file has one documented. The env template is also where the two roots get their explanation, and one of those sentences stops mid-clause: `# Root directory for the projects explorer panel.` is followed by a line beginning `Default: parent directory of` and nothing after it, where the table states the same value in three words. The home root, by contrast, is spelled out as the top-level .hermes directory and not a profile subdirectory, which matters once a single install can hold several agent profiles.
One password from the environment, twenty permissions behind it
The login gate is a single environment variable, `HERMES_CONTROL_PASSWORD`, described as the login password and bcrypt hashed, with `HERMES_CONTROL_SECRET` signing auth tokens and verifying internal requests. Both ship empty in the template, each with an `openssl rand -hex 32` line above it. Behind that one gate the project advertises 20 permissions across three roles, and profile-based access isolation, which is the headline of the newest release. The sample code for it creates accounts with their own passwords:
// User creation with profile restriction
createUser('cx-team', 'password', 'custom', ['jorah']); // only sees Jorah
createUser('influencer-team', 'password', 'custom', ['varys']); // only sees Varys
createUser('admin', 'password', 'admin', ['*']); // sees all agentsThe `allowed_profiles` field on each user does the narrowing, with `["*"]` meaning everything and a list of agent names meaning those agents. It filters `/api/profiles`, `/api/office/agent-states`, and every `:profile` endpoint, and a `requireProfileAccess` middleware guards the gateway, config, and keys routes. The role model still shows at the edges. Nav tabs are hidden by permission, with Files and Maintenance reserved for admins, and in the API table `GET /api/office/events` is marked Admin while the other six office routes in the same table need only a login. That endpoint is the live feed behind the swarm monitor, so a viewer restricted to one profile can read the agent health grid and the kanban board but not the feed above them. Passwords are managed from outside the app, since `npm run reset-password` runs `node scripts/reset-password.js`.
The 100ms figure has no timing script in the manifest
The Office panel claims zero-subprocess agent states at about 100ms against 3000ms, presented as the reason the panel feels fast. Nothing in the scripts block measures it. The defined tasks are `test`, which runs the node test glob, and `test:e2e`, which runs Playwright. There is no bench task and no timing harness, so the comparison reads as a note about not spawning a process per agent rather than a measurement this repository lets you reproduce. The panel also pulls 50 events out of gateway logs with an agent filter and a keyword search, and `GET /api/office/summary` returns board stats with recommendations, which is the endpoint that would want a number behind it. Counting drifts the same way. The Overview table lists twelve pages, from Home through Maintenance, while the architecture diagram labels the browser side `11 pages, SPA`. Build output deserves its own check before trusting an update: `dist/` sits at the root of the checkout, so compiled assets are committed, and the service worker is set to auto-update on a new version, which leaves a client holding new assets while the server behind them is between restarts.
postinstall rebuilds one of the three compiled dependencies
Installing this project runs a postinstall hook, `npm rebuild better-sqlite3`, and the dependency list holds three packages that compile against the host machine: `bcrypt` at ^6.0.0, `better-sqlite3` at ^12.9.0, and `node-pty` at ^1.1.0, the last one backing the browser terminal. The hook names only better-sqlite3, leaving bcrypt and node-pty to whatever prebuilt binary the installer finds for the platform, so on a machine without a toolchain the install stops on those two instead. Node 20 or newer is the floor, stated both in the requirements list and in the `engines` field, so the version is enforced at install time. The rest is ordinary Express work: `express` at ^4.18.2, `ws` for the gateway stream, `helmet`, `express-rate-limit`, `multer`, `dotenv`, `chart.js` behind the Usage page, and the xterm pair with its fit addon. Cost projections on that page come from a third-party price table, `@pydantic/genai-prices` at ^0.0.56, pinned to a package still on a 0.0.x version, so the money figures the dashboard shows are only as current as that dependency. Authentication and roles live in `auth.js` at the root beside `server.js`, and the architecture diagram calls that server monolithic at roughly six thousand lines.
Editorial conclusion
Weigh this project by how its files agree with each other rather than by how many pages it has. One person running a single Hermes agent on their own machine gets a working dashboard from the Quick Start, as long as they read the port their build actually binds and start the server themselves. Teams sharing one Hermes install across several agents should read the access control section closely, because per-profile isolation, a single bootstrap password, and an admin-only event feed only behave as intended behind the proxy and TLS setup in docs/INSTALL.md. Before trusting it, confirm install.sh exists in your own checkout before running the setup script, add the update remote by hand, and expect to rebuild the compiled dependencies yourself.
Frequently asked questions
What does Hermes Control Interface need installed before the dashboard will start?
Node.js 20 or newer, the Hermes Agent installed on the same machine, and the hermes CLI available on PATH. Two env values must also be filled in from the template: HERMES_CONTROL_PASSWORD and HERMES_CONTROL_SECRET, each generated with openssl rand -hex 32.
How do I reach the Hermes Control Interface dashboard from another machine?
The Quick Start only binds locally, and the two documented port numbers disagree, 10274 in the architecture diagram and 10272 in the env template. Remote access is the job of docs/INSTALL.md, which covers nginx, systemd, and Cloudflare, and the optional HCI_SSL_CERT_FILE and HCI_SSL_KEY_FILE variables are how HTTPS gets turned on.
Can Hermes Control Interface restrict a user to a single agent?
Yes, through the allowed_profiles field on each user, where a wildcard list means every agent and a list of names means only those. It filters /api/profiles, /api/office/agent-states, and every :profile endpoint, with requireProfileAccess middleware on the gateway, config, and keys routes.
Does Hermes Control Interface give the Hermes Agent a graphical interface?
It is a web interface for that stack, a single page app behind one password gate. The Overview table lists twelve pages including chat with streaming and tool call cards, a workspace file editor, the Office swarm monitor, MCP server control, and token usage, and a service worker makes it installable to the homescreen.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/xaspx-hermes-control-interface)