Hermes#
1 Projects#
Hermes Projects are named workspaces that can include folders or repositories. Project data is per profile. In this desktop version, use the built-in terminal for project and folder commands (Ctrl + ` opens it). Quote paths containing spaces.
# Create a project
hermes project create "Project Name" --primary "/absolute/path/to/folder" --use# Use a project
hermes project use dockdash# Add a folder
hermes project add-folder PROJECT "/absolute/path/to/folder"# Add a PRIMARY folder
hermes project add-folder PROJECT "/absolute/path/to/folder" --primary# Remove a folder
hermes project remove-folder PROJECT "/absolute/path/to/folder"# List projects
hermes project list# Show a project's configured folders
hermes project show PROJECT# Use a project in CLI
hermes project use dockdash2 Project Management#
Create projects and add folders
hermes project create "Homelab" --primary "$HOME/Obsidian/Homelab" --use
hermes project add-folder homelab "/Users/marc/Xcode/"
hermes project create "DockDash" --primary "$HOME/Xcode/DockDash" --use
hermes project add-folder dockdash "/Users/marc/Xcode/"
hermes project add-folder dockdash "/Users/marc/Obsidian/"
hermes project create "DashApps" --primary "$HOME/Obsidian/DashApps" --use
hermes project add-folder dashapps "/Users/marc/Xcode/"
hermes project add-folder dashapps "/Users/marc/Obsidian/"
hermes project create "GenDash" --primary "$HOME/Xcode/GenDash" --use
hermes project add-folder gendash "/Users/marc/Xcode/"
hermes project add-folder gendash "/Users/marc/Obsidian/"
hermes project create "GPSDash" --primary "$HOME/Obsidian/GPSApps" --use
hermes project add-folder gpsdash "/Users/marc/Xcode/"
hermes project add-folder gpsdash "/Users/marc/Obsidian/"
hermes project create "SoundDash" --primary "$HOME/Xcode/SoundDash" --use
hermes project add-folder sounddash "/Users/marc/Xcode/"
hermes project add-folder sounddash "/Users/marc/Obsidian/"3 Telegram#
Connect Telegram from Hermes Desktop:
- In Hermes Desktop, open Messaging from the sidebar, then open Telegram. If you have only ever used one Hermes setup, stay on the one that is already open; there is no need to change profiles.
- Click Create with QR.
- Scan the QR code with your phone, or click Open Telegram if that option appears.
- In the Telegram chat that opens, tap Create bot. Follow the prompts to choose a bot name and username.
- When Telegram offers Connect this bot, tap it.
- Return to Hermes and wait for it to finish connecting. Open the new bot in Telegram and send it a message to test it.
- Message the bot to verify the connection.
Restrict access to your own Telegram user ID; do not allow everyone to use a bot with access to Hermes tools. Keep the bot token secret. For ordinary group-message access, disable the bot’s group privacy in @BotFather → /mybots → Bot Settings → Group Privacy, then remove and re-add the bot to the group.
4 Dashboard#
The Hermes dashboard is a web server. To have it available after you sign in to your Mac, install a per-user macOS LaunchAgent. It starts the dashboard at login and restarts it if the process exits; it does not open a browser window. This is independent of Hermes Desktop, so the dashboard will already be running when you open the app. This configuration binds the dashboard to 10.1.2.4, so other devices that can reach that address may connect. Hermes requires authentication for a non-loopback address; use a strong password and keep access limited to a trusted LAN or VPN. Do not expose this dashboard directly to the public internet.
4.1 Install the LaunchAgent#
Before installing the LaunchAgent, run the dashboard once in Terminal with the required host and port:
hermes dashboard --host 10.1.2.4 --port 9119 --no-openIf Hermes asks how to authenticate, choose Username & password and follow the prompts. Hermes saves the authentication configuration to config.yaml under dashboard.basic_auth; the LaunchAgent then uses that configuration. Do not put the username or password in the plist. Once the dashboard prints HERMES_DASHBOARD_READY port=9119 and shows http://10.1.2.4:9119, stop this foreground test with Ctrl+C before loading the LaunchAgent.
- Open Terminal and find the Hermes command’s full path:
command -v hermesKeep the path it prints; it will be needed in the LaunchAgent file. If no path is printed, do not continue until Hermes is available in Terminal.
- Create the LaunchAgents folder if needed, then open a new plist file in a text editor:
mkdir -p ~/Library/LaunchAgents
nano ~/Library/LaunchAgents/com.hermes.dashboard.plist- Paste this content into the editor. Replace
/absolute/path/to/hermeswith the exact path from step 1. The example uses the default port,9119:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>Label</key>
<string>com.hermes.dashboard</string>
<key>ProgramArguments</key>
<array>
<string>/absolute/path/to/hermes</string>
<string>dashboard</string>
<string>--host</string>
<string>10.1.2.4</string>
<string>--port</string>
<string>9119</string>
<string>--no-open</string>
</array>
<key>RunAtLoad</key>
<true/>
<key>KeepAlive</key>
<true/>
<key>StandardOutPath</key>
<string>/Users/marc/Library/Logs/hermes-dashboard.log</string>
<key>StandardErrorPath</key>
<string>/Users/marc/Library/Logs/hermes-dashboard-error.log</string>
</dict>
</plist>In nano, save with Ctrl+O, press Return, then exit with Ctrl+X.
- Check that the plist is valid, then load it for your logged-in Mac user:
plutil -lint ~/Library/LaunchAgents/com.hermes.dashboard.plist
launchctl bootstrap gui/$(id -u) "$HOME/Library/LaunchAgents/com.hermes.dashboard.plist"- Open
http://10.1.2.4:9119in a browser. To confirm that LaunchAgent is loaded, run:
launchctl print gui/$(id -u)/com.hermes.dashboard4.2 Change the port#
The example uses port 9119. To use another available port, edit the plist and change the value after <string>--port</string>. Also use the new port in the one-time test command and in the URL. For example, with port 9120, use --port 9120 and open http://10.1.2.4:9120. Save the plist, then reload the LaunchAgent:
launchctl bootout gui/$(id -u) "$HOME/Library/LaunchAgents/com.hermes.dashboard.plist"
plutil -lint ~/Library/LaunchAgents/com.hermes.dashboard.plist
launchctl bootstrap gui/$(id -u) "$HOME/Library/LaunchAgents/com.hermes.dashboard.plist"4.3 Stop or remove automatic startup#
To stop the dashboard and disable its automatic startup, unload the LaunchAgent:
launchctl bootout gui/$(id -u) "$HOME/Library/LaunchAgents/com.hermes.dashboard.plist"To remove the automatic-start configuration too, delete the plist after unloading it:
rm ~/Library/LaunchAgents/com.hermes.dashboard.plistThe dashboard binds to 10.1.2.4, so it can be reached by devices with network access to that address; authentication is required. The equivalent one-time foreground command is hermes dashboard --host 10.1.2.4 --port 9119 --no-open.
4.4 Access through Pangolin#
The Pangolin resource https://hermes.mmmo.app targets the dashboard at http://10.1.2.4:9119. Pangolin forwards requests with the public hostname, so Hermes must allow that exact hostname. Set the dashboard’s public URL in Hermes:
hermes config set dashboard.public_url https://hermes.mmmo.app
hermes config get dashboard.public_urlRestart the dashboard LaunchAgent so it reads the new setting:
launchctl bootout gui/$(id -u) "$HOME/Library/LaunchAgents/com.hermes.dashboard.plist"
launchctl bootstrap gui/$(id -u) "$HOME/Library/LaunchAgents/com.hermes.dashboard.plist"Open https://hermes.mmmo.app. A redirect to the Hermes /login page confirms the host is accepted; sign in with the Hermes dashboard credentials. In Pangolin, leave Custom Host Header unset so the public hostname is forwarded. If it is explicitly set, it must be hermes.mmmo.app.
Connect Hermes Conduit on iPhone#
- In Pangolin, open the Hermes Dashboard resource → Authentication. Enable Basic Header Auth, set its username and password, and save the resource settings. Keep Hermes dashboard authentication enabled as a separate layer.
- On the Mac, generate the HTTP Basic header value. Replace
marcif a different Pangolin Basic Header Auth username was configured. Enter the Pangolin password only at the hidden prompt:
python3 -c 'import base64, getpass; p=getpass.getpass("Pangolin password: "); print("Basic " + base64.b64encode(("marc:" + p).encode()).decode())'The command prints Basic <base64(username:password)>. Base64 is encoding, not encryption. Do not put the generated value or password in notes or chat; use HTTPS and keep the value private.
- In Conduit, add a dashboard with address
hermes.mmmo.app:443(Conduit uses HTTPS for this domain). Expand Advanced → Extra headers and add:- Header name:
Authorization - Value: the complete output from the command, beginning with
Basic
- Header name:
- Save the extra header and continue. When prompted, sign in with the Hermes dashboard username and password; these are separate from the Pangolin Basic Header Auth credentials.
Conduit sends the extra header with requests to this dashboard and stores its value in the iPhone Keychain. To revoke access, disable or change Basic Header Auth for the Pangolin resource, then update Conduit if needed.
Keep both Pangolin’s Protected access and Hermes dashboard authentication enabled. If login does not retain its session behind HTTPS, configure dashboard.trusted_proxies with the exact IP address from which Pangolin’s proxy reaches Hermes; do not use a wildcard or guess the address.
4.5 Change the Hermes dashboard password securely#
The Hermes dashboard sign-in (dashboard.basic_auth) is separate from Pangolin Basic Header Auth. Hermes currently uses one shared username/password for the dashboard; it does not provide individual local user accounts. Changing the Hermes password does not change the Pangolin Authorization header unless the Pangolin Basic Header Auth password is also changed.
Store a scrypt password hash in config.yaml, not the plaintext password. The following uses only Python’s standard library (so it does not depend on Hermes modules such as httpx). Enter it in Terminal:
PASSWORD_HASH=$(python3 -c 'import base64, getpass, hashlib, secrets; p=getpass.getpass("New dashboard password: "); salt=secrets.token_bytes(16); digest=hashlib.scrypt(p.encode("utf-8"), salt=salt, n=2**14, r=8, p=1, dklen=32, maxmem=0); print(f"scrypt$16384$8$1${base64.b64encode(salt).decode()}${base64.b64encode(digest).decode()}")') &&
hermes config set dashboard.basic_auth.password_hash "$PASSWORD_HASH" >/dev/null &&
unset PASSWORD_HASHRestart the dashboard LaunchAgent to load the new password, then sign out and back in to Hermes and Conduit with the updated Hermes dashboard credentials:
launchctl bootout gui/$(id -u) "$HOME/Library/LaunchAgents/com.hermes.dashboard.plist"
launchctl bootstrap gui/$(id -u) "$HOME/Library/LaunchAgents/com.hermes.dashboard.plist"Keep the commands joined with &&: if hash generation fails, Hermes will not be given an empty hash. Type the new password only at the hidden prompt; it will not appear on screen or in shell history. The generated hash is stored in Hermes config. If dashboard.basic_auth.password is already set as plaintext, remove that setting after successfully setting the hash:
hermes config unset dashboard.basic_auth.passwordIf HERMES_DASHBOARD_BASIC_AUTH_PASSWORD is configured as an environment override, it takes precedence over the config hash and must also be changed or removed securely.
Memory#
# check memory status
hermes memory status# inspect memory
hermes memory status# check memory status
cat ~/.hermes/memories/USER.md
cat ~/.hermes/memories/MEMORY.md