An MCP plugin that brings Hermes Agent into Codex as an embedded chat app. Connect to local or remote Hermes instances, work with their profiles and conversations, and inspect scheduled jobs without leaving Codex.
The interface follows Codex's chat and sidebar conventions and inherits the host's light/dark theme. Hermes runs the agent, tools, memory and scheduler; the surrounding Codex conversation remains separate.
- Streams replies, renders Markdown and code, shows tool activity, and supports Stop, approvals and clarification questions.
- Groups conversations under expandable profile sections with Hermes avatars. Drafts stay with their owning instance and profile.
- Uses each profile's real model catalogue and defaults, with a model selector and Power control for reasoning effort.
- Shows scheduled jobs and recorded runs for one profile or all profiles. Schedule, execution and delivery status are shown separately.
- Archives conversations through Hermes, with a brief Undo action. Archiving retains the stored messages.
Upstream credentials stay in the local bridge process. The embedded interface receives connection labels and chat data, rather than tokens or provider credentials.
- Node.js 22 or later, available to Codex as node. A source build also needs npm.
- A Codex desktop version that supports local plugins and MCP Apps. The installer registers a local marketplace entry; public Plugins Directory publication is a separate process.
- An installed, configured Hermes backend with the desktop JSON-RPC/WebSocket API and REST management routes. See connection configuration.
- For SSH connections, a local sshclient, an accepted host key and non-interactive authentication through your SSH configuration or agent. Managed SSH also needs a POSIX remote host,python3on its PATH and a Hermes installation with its server dependencies.
This package provides a local stdio MCP server. It does not provide a hosted MCP endpoint for ChatGPT cloud access.
Download hermes-chatgpt-extension-VERSION.zip from the latest GitHub release. Extract it and open a terminal in the extracted directory containing plugin.json.
node scripts/verify-plugin.mjsThe ZIP includes the compiled server and self-contained UI. It needs Node.js, without an npm install or build. Each release also provides a -source.zip and SHA256SUMS for checking both ZIPs. GitHub's automatically generated Source code downloads require a source build. Continue with Configure and register the plugin below.
Extract the source ZIP and open its directory containing package.json. Alternatively, with access to the Git repository:
git clone https://github.com/intellectronica/hermes-chatgpt-extension.git
cd hermes-chatgpt-extensionBuild the source:
npm ci
npm run build
node scripts/verify-plugin.mjsContinue with the same configuration and installation steps. A raw Git checkout needs this build before Codex can load the plugin.
Keep your connection configuration outside the plugin directory so updates preserve it. Start with the example for your connection mode:
mkdir -p "$HOME/.config/hermes-chatgpt-extension"
cp examples/config.ssh.json "$HOME/.config/hermes-chatgpt-extension/hermes.config.json"Edit that file for your Hermes host and installation paths. For other modes, use the examples in connection configuration. Preview the installation, then apply it:
node scripts/install-plugin.mjs --config "$HOME/.config/hermes-chatgpt-extension/hermes.config.json" --dry-run
node scripts/install-plugin.mjs --config "$HOME/.config/hermes-chatgpt-extension/hermes.config.json" --applyThe installer copies the plugin into ~/.codex/plugins/hermes-chatgpt-extension and adds its entry to ~/.agents/plugins/marketplace.json. It preserves an existing marketplace name and unrelated entries. It records the configuration file's absolute path; it does not copy its contents.
Open the plugin detail link printed by the installer and choose Install or Enable in Codex. If your local source is not yet listed, restart the desktop app, open the Plugins Directory and select the marketplace named by the installer. A new marketplace is called Personal plugins; an existing one keeps its name. The script does not enable the plugin or restart Codex itself. These local-marketplace steps follow OpenAI's plugin packaging guidance.
Build the new source checkout or extract the new ZIP, then run:
node scripts/install-plugin.mjs --replace --dry-run
node scripts/install-plugin.mjs --replace --applyReplacement retains backups and preserves the previous configuration reference. To change that reference, add --config /absolute/path/to/hermes.config.json. Refresh the installed plugin in Codex or restart the desktop app so its MCP connection and cached UI load the new files.
A configuration contains a connections array. Each entry needs a unique id, a display label and its connection settings. Add several entries to connect multiple Hermes instances; the footer selector switches between them. Profiles are discovered from Hermes rather than enumerated in this file.
Configuration is loaded in this order:
- The --configargument, if supplied.
- HERMES_EXTENSION_CONFIG, if set.
- hermes.config.jsonin the bridge's working directory.
- $XDG_CONFIG_HOME/hermes-chatgpt-extension/hermes.config.jsonwhen- XDG_CONFIG_HOMEis an absolute path; otherwise- ~/.config/hermes-chatgpt-extension/hermes.config.json.
An explicitly selected missing file, or any selected invalid file, is an error; discovery does not skip invalid configuration. With no configuration file, the app opens with no connections. Relative configuration paths are resolved from the working directory; relative tokenFile paths are resolved from the configuration file's directory. Local paths can use ~/.
Use this mode when Hermes is installed remotely and the extension should start its own temporary backend:
{
"connections": [
{
"id": "remote",
"label": "Remote Hermes",
"kind": "ssh",
"ssh": {
"host": "hermes-host",
"mode": "managed"
}
}
]
}host can be an SSH-config alias or hostname. Optional user and port select the SSH account and port. Defaults are ~/.hermes for hermesHome and <hermesHome>/hermes-agent for repoPath; the bridge looks for venv/bin/python, then .venv/bin/python, in that repository. Set pythonPath for another existing runtime. These remote paths must be absolute or start with ~/, relative to the SSH user. Managed SSH example.
The bridge starts a token-protected loopback backend on a dynamically allocated port and owns that process and its SSH tunnel. It stops its backend when the bridge closes. It uses the existing Hermes installation and does not install software, edit profiles or restart services. Its temporary backend does not start the desktop cron scheduler; Scheduled reads the jobs and run records maintained by Hermes.
Check SSH access before using the plugin:
ssh -o BatchMode=yes hermes-host trueManaged mode generates its own credential. Do not specify tokenEnv, tokenFile, remoteHost or remotePort for it.
Use this mode to connect to an already-running, compatible Hermes desktop backend bound to remote loopback:
{
"connections": [
{
"id": "attached",
"label": "Existing Hermes",
"kind": "ssh",
"tokenFile": "./hermes.token",
"ssh": {
"host": "hermes-host",
"mode": "attach",
"remotePort": 9119
}
}
]
}remotePort must be the backend's actual port. remoteHost defaults to 127.0.0.1 and must remain a loopback address. The bridge forwards it through SSH and leaves the existing backend running when it closes. tokenFile is a local file containing that backend's credential, not a remote path. Attach mode cannot include the managed-only hermesHome, repoPath or pythonPath settings. SSH attach example.
Use a compatible Hermes desktop gateway directly:
{
"connections": [
{
"id": "gateway",
"label": "Hermes gateway",
"kind": "http",
"baseUrl": "https://hermes.example.com/hermes",
"tokenEnv": "HERMES_GATEWAY_TOKEN"
}
]
}Use a compatible hermes serve desktop backend. It must expose JSON-RPC over /api/ws and the corresponding REST routes for profiles, sessions and cron data. Hermes's messaging gateway, an OpenAI-compatible /v1 endpoint or a generic HTTP chat API alone is insufficient. A reverse proxy must forward WebSocket upgrades and preserve the configured path prefix. See Hermes's programmatic integration guide for the separate protocols.
baseUrl is the gateway root, optionally with a path prefix, without /api/ws, embedded credentials, a query or a fragment. Remote URLs require HTTPS. Plain HTTP is accepted only for loopback hosts such as http://127.0.0.1:9119. HTTPS example, local HTTP example.
HTTP and SSH attach require exactly one credential source:
- tokenEnv: the name of an environment variable available to the bridge process.
- tokenFile: a small local text file containing the credential, with surrounding whitespace ignored. On POSIX systems, it must belong to the current user and have owner-only permissions, for example- chmod 600 /path/to/hermes.token.
A desktop app may not inherit variables exported in an interactive shell. A private tokenFile is useful when the plugin is launched by Codex. Use the credential accepted by the Hermes desktop backend. A public dashboard needs a session access token from its configured authentication provider, accepted for both REST and WebSocket access. Provider API keys are configured in Hermes, not in this plugin. Keep token files and your populated configuration outside the distributable package and source control.
Combine any supported modes in one connections array. Each instance has its own connection and credential; use distinct IDs even when labels are similar. See multiple-instance example.
An optional connection-level cwd sets the working directory for new Hermes conversations. It is a path on the Hermes host, so use a remote path for SSH connections. To show Hermes-tagged automated conversations, add "sidebar": { "showAutomatedChats": true } alongside connections; they are hidden by default. Hermes's own subagent visibility setting still applies.
After installation and enabling:
- Sidebar app: open Explore → Hermes. Hover its entry and choose Pin to sidebar to keep it available. Some desktop versions expose pinning under Explore → Customize.
- Tab in a Codex chat: choose New tab (+) → More tools… → Plugins and MCPs → Hermes.
- Inline app: ask Codex to open Hermes, then expand the returned app panel.
Opening the app does not send a Hermes prompt. Choose an instance in the sidebar footer; the connection indicator appears beneath its name. Expand a profile section to see its chats, select a conversation, or use the profile's New chat control. Switching profiles preserves their drafts and does not change Hermes's machine-wide default profile.
Type in the Hermes composer. Enter sends; Shift+Enter adds a newline. Stop interrupts an active Hermes turn. Answer any displayed approval or clarification card to let Hermes continue. Tool activity can be expanded to inspect the available input and output.
The composer control beside Send shows the model and reasoning effort. Open it to adjust Power, or click the selected model row to choose from Hermes's available models. Left/Right adjusts effort and Enter closes the picker. New chats inherit profile defaults; explicit choices affect the selected conversation. Reset to default applies the current profile defaults to that conversation. Required Hermes model confirmations must be accepted before a guarded change takes effect. Supported reasoning options depend on the model, and Hermes maps effort to the provider's capabilities.
Select Scheduled to view jobs for the selected profile or all profiles, their schedules and recorded runs. Timestamps use your browser's local timezone, while each job retains its schedule timezone. Missing execution, delivery or scheduler evidence is shown as unknown. This view cannot create, edit or run jobs.
Hover a chat row, or focus it with the keyboard, to reveal Archive chat. The row disappears after Hermes confirms the archive. Undo restores the same conversation and its history. Archiving is unavailable while that conversation is busy, has an unanswered question, awaits a model confirmation or has an uncertain operation. There is no archived-chat browser in this version; later restoration can use Hermes's own interface.
The same app can run in a browser for development or use outside the embedded panel:
node dist/server.cjs --http --config /absolute/path/to/hermes.config.jsonOpen the loopback URL printed by the server, normally http://127.0.0.1:4318. Use --port 4320 to choose another port. The preview uses a same-origin HttpOnly cookie and validates Host/Origin; upstream credentials remain in the bridge. It is a local interface, not a public web deployment.
- Codex hosts the app through MCP Apps; the plugin does not replace Codex's native agent runtime. Host versions and account policies can affect discovery and available panel routes.
- Hermes's desktop APIs are the compatibility boundary. There is no universal Hermes version guarantee or adapter for arbitrary chat gateways.
- Standard chat, tools, approvals and clarification are supported. Desktop-only file, browser, secret, sudo and vault peer operations are not implemented.
- Reconnecting to the same live backend differs from restarting it. Stored history can be reloaded safely, but in-flight work and conversation-only model settings are not guaranteed to survive a backend restart.
- History, conversation lists, tool output and job records are bounded. The sidebar is a recent-conversation view, not an exhaustive export.
- The embedded app controls are intended for a trusted local MCP host. UI-only MCP metadata and tool visibility keep transcript data out of ordinary model-facing results; they are not a separate authentication boundary.
npm run check
npm test
npm run build
npm run plugin:verify -- --probeBuild shareable archives and verify their fresh-user installation:
npm run release:package
npm run release:verifyThis creates a prebuilt plugin ZIP, a source ZIP and SHA256SUMS under release/. Both ZIPs contain only allowlisted files and an integrity manifest; they exclude Git history, private configuration, tokens, logs and local development outputs. Use the source ZIP to initialise a new repository with clean history when needed.
The Release extension workflow runs when a vMAJOR.MINOR.PATCH tag is pushed. The tag must match package.json, plugin.json and both root version fields in package-lock.json. Prerelease tags such as v0.4.0-rc.1 are supported and produce prereleases.
To release a new version:
-
Update the package version with npm version VERSION --no-git-tag-version, then set the same version inplugin.json. Commit and push the version change, and wait for CI to pass.
-
Tag that commit and push the tag: git tag -a vVERSION -m "Hermes vVERSION" git push origin vVERSION
-
Wait for Release extension in GitHub Actions. It checks types, runs tests, builds, audits production dependencies and verifies both packages on Node.js 22 and 24. The Node.js 22 build supplies the release assets.
The workflow creates a draft, uploads the installable ZIP, source ZIP and SHA256SUMS, downloads and verifies their bytes, then publishes the release. It uses GitHub's built-in token; no custom secrets are needed. Only the publishing job has repository write permission. The workflow uses the current repository, so forks can release their own builds.
Publishing a release through GitHub's UI or CLI also starts the workflow to attach its packages. Use the tag-push process when immutable releases are enabled: an already published immutable release cannot accept missing assets. Releases created by this workflow already include their packages before publication.
Failed runs can be rerun from GitHub Actions. Retries verify existing assets and upload missing files; conflicting or incomplete assets fail without being overwritten. A moved tag is rejected. Publish a new version for changed files. Releases retain the repository's access settings; users need repository access to download private releases.
The verifier checks packaging and can probe MCP initialization, entrypoints and UI resources without sending a Hermes prompt. Live Hermes integration tests are opt-in. Frontend code lives in src/web, the MCP/local HTTP bridge in src/bridge, and the Hermes protocol adapter in src/hermes.
This extension is released under the MIT licence. Its repository is maintained by intellectronica. A local installation or shared ZIP does not imply publication or approval in OpenAI's public Plugins Directory.
Hermes brand assets and other bundled components retain their upstream licences. See third-party notices and the generated dist/THIRD_PARTY_LICENSES.txt included with the built package. This project is an independent integration and is not an OpenAI or Nous Research product.