Current experimental target
- T3 Code
https://siva.otter-hawksbill.ts.net:7446/- Repository
https://github.com/pingdotgg/t3code.git- Branch
experiment/hermes-provider- Plugin source
integrations/hermes-t3-gateway- Network
- Tailnet only
Use the exact siva.otter-hawksbill.ts.net hostname. Do not substitute siva.davis7.space for this HTTPS port; that alias does not currently have a valid certificate for port 7446. Hermes opens an outbound WebSocket, so the Hermes machine needs no public listener or inbound firewall rule.
1. Preflight
Run these checks on the machine that already owns the Hermes Agent:
command -v git
command -v hermes
hermes --version
tailscale status
hermes gateway list
curl -fsSI --max-time 10 https://siva.otter-hawksbill.ts.net:7446/ | head
The HTTP check must return 200. Stop on a timeout, DNS error, TLS error, or non-200 response and ask the operator to restore the experimental T3 environment. Do not silently use the production T3 instance.
The Hermes installation must support hermes plugins enable, hermes gateway, Python 3.11–3.13, and Hermes' normal websockets dependency.
Select exactly one Hermes profile
For the default profile:
HERMES_HOME_DIR="${HERMES_HOME:-$HOME/.hermes}"
hermes_cmd() { hermes "$@"; }
For a named profile, replace PROFILE_NAME with the profile reported by hermes gateway list:
HERMES_PROFILE="PROFILE_NAME"
HERMES_HOME_DIR="$HOME/.hermes/profiles/$HERMES_PROFILE"
hermes_cmd() { hermes -p "$HERMES_PROFILE" "$@"; }
Keep this shell open. Use hermes_cmd for every remaining Hermes command so installation, enrollment, and the running gateway all target the same profile.
2. Clone the experimental branch
Use a fresh path. Stop rather than overwrite an existing checkout.
T3CODE_DIR="$HOME/Developer/t3code-hermes-provider"
if [ -e "$T3CODE_DIR" ]; then
echo "STOP: $T3CODE_DIR already exists; inspect it or choose a new path." >&2
exit 1
fi
mkdir -p "$(dirname "$T3CODE_DIR")"
git clone --branch experiment/hermes-provider --single-branch \
https://github.com/pingdotgg/t3code.git \
"$T3CODE_DIR"
git -C "$T3CODE_DIR" status --short --branch
git -C "$T3CODE_DIR" log -1 --oneline --decorate
The checked-out branch must be experiment/hermes-provider. Record the current commit hash in the final report.
3. Install and enable the plugin
PLUGIN_SOURCE="$(cd "$T3CODE_DIR/integrations/hermes-t3-gateway" && pwd -P)"
PLUGIN_LINK="$HERMES_HOME_DIR/plugins/hermes-t3-gateway"
mkdir -p "$HERMES_HOME_DIR/plugins"
if [ -L "$PLUGIN_LINK" ]; then
ls -ld "$PLUGIN_LINK"
echo "STOP if this does not point to $PLUGIN_SOURCE"
elif [ -e "$PLUGIN_LINK" ]; then
echo "STOP: $PLUGIN_LINK exists and is not a symlink." >&2
exit 1
else
ln -s "$PLUGIN_SOURCE" "$PLUGIN_LINK"
fi
hermes_cmd plugins enable hermes-t3-gateway
hermes_cmd plugins list --user --plain | grep hermes-t3-gateway
hermes_cmd t3 status
Before pairing, hermes_cmd t3 status should say T3 Code: not enrolled. “Unknown command” means the plugin was enabled in the wrong profile or Hermes lacks the required plugin CLI surface.
Optional source smoke test:
python3 -m unittest discover \
"$T3CODE_DIR/integrations/hermes-t3-gateway/tests" \
-p 'test_*.py'
4. Create and consume a fresh enrollment
The operator performs these steps in T3 Code:
- Open
https://siva.otter-hawksbill.ts.net:7446/. - Go to Settings → Providers → Add provider → Hermes.
- Choose a unique name such as
hermes-researchorhermes-nexus. - Keep the connector URL at the browser origin unless another reachable T3 origin is intentional.
- Create enrollment and deliver the complete one-time command directly to the setup agent.
The generated command has this shape. Do not run this placeholder:
hermes t3 connect \
--url https://siva.otter-hawksbill.ts.net:7446 \
--token '<fresh-one-time-token>'
Run the exact generated command through the selected profile:
hermes_cmd t3 connect \
--url https://siva.otter-hawksbill.ts.net:7446 \
--token '<paste-the-fresh-token-here>'
hermes_cmd t3 status
The token expires after 10 minutes, is single-use, and is invalidated when a newer token is created for that instance. The long-lived credential is delivered over the WebSocket and stored through Hermes' profile-aware configuration helper; it is never printed.
5. Restart the correct Hermes gateway
hermes_cmd gateway status --deep --full
If a gateway service already owns this profile:
hermes_cmd gateway restart
If no service exists on a normal Linux or macOS host:
hermes_cmd gateway install --start-now --start-on-login
For WSL without systemd or an intentionally foreground-managed deployment, use exactly one supervisor, for example one tmux session:
hermes_cmd gateway run -v
Do not launch a foreground gateway when a service already owns the profile. Docker, s6, and existing system-level installations should keep their current process manager and restart that owner.
6. End-to-end verification
- In T3 Settings, refresh the Hermes instance and confirm Connected.
- Confirm plugin version, Hermes version, protocol version, and last-connected time are populated.
- Start a new T3 thread and select the named Hermes instance in the normal provider selector.
- Send
Reply exactly HERMES_GATEWAY_OKand confirm text streams live. - Send another message in the same T3 thread and confirm it continues the same Hermes session.
- Optionally send during an active turn and confirm it steers the running Hermes turn.
- Confirm mapped tool activity appears in T3's activity UI.
hermes_cmd t3 status
hermes_cmd gateway status --deep --full
A final report may include the machine/profile, branch and commit, plugin symlink and source, enabled state, redacted hermes t3 status, gateway service state, T3 provider state, and streaming result. Never include a token, credential, environment-file contents, or copied pairing command.
Update later
git -C "$T3CODE_DIR" status --short --branch
git -C "$T3CODE_DIR" fetch origin experiment/hermes-provider
git -C "$T3CODE_DIR" switch experiment/hermes-provider
git -C "$T3CODE_DIR" pull --ff-only origin experiment/hermes-provider
hermes_cmd gateway restart
Stop if the checkout has local changes. The symlink updates the source in place, but the long-running gateway must restart to load new Python code.
Troubleshooting
Enrollment is invalid, expired, or already used
Ask the operator for a fresh command and run it exactly once. A newer command invalidates the older token.
T3 remains Offline
hermes t3 connect saves credentials; it does not reload a running gateway. Verify the selected profile, restart its owning service, and confirm only one gateway process uses that profile.
The connection alternates between machines
The same credential is active in more than one Hermes process. Stop the duplicate. Each Hermes agent needs its own T3 provider instance and enrollment.
The instance was revoked or removed
Revocation permanently invalidates that credential. Remove the dead instance in T3, add a fresh instance, enroll it, and restart Hermes. Historical T3 threads remain readable and bound to the unavailable old identity; they are never reassigned.
Upgrade required
Fast-forward the experimental branch and restart Hermes. If the warning remains, report the T3 commit and hermes --version; do not bypass protocol validation.
Generic activity or no attachments
This is expected in V1. Activity that does not map cleanly uses a meaningful generic payload. Attachments intentionally remain unsupported until the gateway is stable.