From 390ba2ef61a776acd8828dddceb2de274b1670eb Mon Sep 17 00:00:00 2001 From: Thierry Pouplier Date: Thu, 30 Apr 2026 14:31:38 +0000 Subject: [PATCH 1/8] feat: Add Hermes Agent vterm integration with SPC z h keybinding --- doom/.config/doom/config.el | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/doom/.config/doom/config.el b/doom/.config/doom/config.el index ee75e4d..040345e 100644 --- a/doom/.config/doom/config.el +++ b/doom/.config/doom/config.el @@ -18,7 +18,9 @@ (map! :leader (:prefix ("w" . "window") - :desc "Minimize window" "O" #'minimize-window)) + :desc "Minimize window" "O" #'minimize-window) + (:prefix ("z" . "Personal") + :desc "Hermes Agent" "h" #'gortium/hermes-vterm)) (use-package! ultra-scroll :init @@ -941,7 +943,19 @@ Handles org-clock and context link capture for tasks." (after! vterm (add-hook 'vterm-mode-hook (lambda () - (evil-local-set-key 'insert (kbd "C-j") #'vterm--self-insert)))) + (evil-local-set-key 'insert (kbd "C-j") #'vterm--self-insert))) + ;; Quick launch Hermes Agent on lazyworkhorse server + (defun gortium/hermes-vterm () + "Launch Hermes Agent in a vterm buffer via SSH to lazyworkhorse." + (interactive) + (let ((buf (get-buffer-create "*hermes*"))) + (switch-to-buffer buf) + (unless (get-buffer-process buf) + (vterm buf) + (sleep-for 0.5) + ;; SSH to server, then exec into docker and run hermes from venv + (vterm-send-string "ssh lazyworkhorse 'docker exec -it hermes /opt/hermes/.venv/bin/hermes chat'") + (vterm-send-return))))) ;; GPTel AI chat for emacs (use-package! gptel -- 2.49.1 From aa06568852fe2121673be48d53d8dba96a272a9c Mon Sep 17 00:00:00 2001 From: Thierry Pouplier Date: Fri, 1 May 2026 14:35:48 +0000 Subject: [PATCH 2/8] refactor: replace sleep-for vterm hack with process-send-string for Hermes launch - Replaced sleep-for 0.5 + vterm-send-string timing hack with direct process-send-string (no timing race) - Removed TUI chat command, SSH uses -t PTY for clean CLI mode - Lines 947-957 in config.el --- doom/.config/doom/config.el | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/doom/.config/doom/config.el b/doom/.config/doom/config.el index 040345e..0d1a372 100644 --- a/doom/.config/doom/config.el +++ b/doom/.config/doom/config.el @@ -946,16 +946,15 @@ Handles org-clock and context link capture for tasks." (evil-local-set-key 'insert (kbd "C-j") #'vterm--self-insert))) ;; Quick launch Hermes Agent on lazyworkhorse server (defun gortium/hermes-vterm () - "Launch Hermes Agent in a vterm buffer via SSH to lazyworkhorse." + "Launch Hermes Agent in vterm via SSH to lazyworkhorse (CLI mode)." (interactive) (let ((buf (get-buffer-create "*hermes*"))) (switch-to-buffer buf) (unless (get-buffer-process buf) (vterm buf) - (sleep-for 0.5) - ;; SSH to server, then exec into docker and run hermes from venv - (vterm-send-string "ssh lazyworkhorse 'docker exec -it hermes /opt/hermes/.venv/bin/hermes chat'") - (vterm-send-return))))) + (let ((proc (get-buffer-process buf))) + (when proc + (process-send-string proc "ssh -t lazyworkhorse hermes\n"))))))) ;; GPTel AI chat for emacs (use-package! gptel -- 2.49.1 From a2a3baf7daea13f15edaaa61f4494973fa70a537 Mon Sep 17 00:00:00 2001 From: Thierry Pouplier Date: Fri, 1 May 2026 14:40:02 +0000 Subject: [PATCH 3/8] feat: add hermes zsh alias (hermes) and Hyprland binding ( + C) - zsh: alias hermes=emacsclient -n -c -e '(gortium/hermes-vterm)' - hyprland: bind = , C to same command - C for CLI/Chat, unused key in current layout --- hypr/.config/hypr/hyprland.conf | 1 + zsh/.zshrc | 3 +++ 2 files changed, 4 insertions(+) diff --git a/hypr/.config/hypr/hyprland.conf b/hypr/.config/hypr/hyprland.conf index 8a57593..ffa46da 100644 --- a/hypr/.config/hypr/hyprland.conf +++ b/hypr/.config/hypr/hyprland.conf @@ -227,6 +227,7 @@ bind = $mainMod, X, swapwindow bind = $mainMod, B, exec, python /home/tpouplier/ExoKortex/4-Automata/recordntrans/record_transcribe.py # bind = $mainMod, G, exec, nerd-dictation end bind = $mainMod, A, exec, $music +bind = $mainMod, C, exec, emacsclient -n -c -e '(gortium/hermes-vterm)' # Full screen bind = SUPER, F, fullscreen diff --git a/zsh/.zshrc b/zsh/.zshrc index 742eaeb..7cd3b74 100644 --- a/zsh/.zshrc +++ b/zsh/.zshrc @@ -19,6 +19,9 @@ alias emacs="emacsclient -c -a emacs" # Opencode alias oc="opencode" +# Hermes Agent in Emacs vterm +alias hermes="emacsclient -n -c -e '(gortium/hermes-vterm)'" + # Yazi alias y="yazi" function yy() { -- 2.49.1 From d73ed29733205c8c7c4964f7c3a8a866c3b73e17 Mon Sep 17 00:00:00 2001 From: Thierry Pouplier Date: Fri, 1 May 2026 14:50:36 +0000 Subject: [PATCH 4/8] fix: move hermes config from config.el to README.org org-babel source - Revert config.el changes (file is generated from README.org via tangle) - Add dedicated ** +Hermes Agent+ section under * AI in README.org - Add SPC z h keybinding to existing map! block in Minimize window section - config.el should NEVER be edited directly --- doom/.config/doom/README.org | 21 ++++++++++++++++++++- doom/.config/doom/config.el | 17 ++--------------- 2 files changed, 22 insertions(+), 16 deletions(-) diff --git a/doom/.config/doom/README.org b/doom/.config/doom/README.org index 584784a..a54ebbb 100644 --- a/doom/.config/doom/README.org +++ b/doom/.config/doom/README.org @@ -112,7 +112,9 @@ My current workflow consist in having the 3-5 files I work on open in vertical s #+begin_src emacs-lisp (map! :leader (:prefix ("w" . "window") - :desc "Minimize window" "O" #'minimize-window)) + :desc "Minimize window" "O" #'minimize-window) + (:prefix ("z" . "Personal") + :desc "Hermes Agent" "h" #'gortium/hermes-vterm)) #+end_src ** Ultra-scroll @@ -1830,6 +1832,23 @@ Org-AI (org-ai-install-yasnippets)) ; if you are using yasnippet and want `ai` snippets #+end_src +** +Hermes Agent+ +Hermes Agent runs on lazyworkhorse server. Launched via SSH in a vterm buffer. + +#+begin_src emacs-lisp +(after! vterm + (defun gortium/hermes-vterm () + "Launch Hermes Agent in vterm via SSH to lazyworkhorse (CLI mode)." + (interactive) + (let ((buf (get-buffer-create "*hermes*"))) + (switch-to-buffer buf) + (unless (get-buffer-process buf) + (vterm buf) + (let ((proc (get-buffer-process buf))) + (when proc + (process-send-string proc "ssh -t lazyworkhorse hermes\n"))))))) +#+end_src + * Tramp Remote connection to server inside emacs (with all my config) <3 diff --git a/doom/.config/doom/config.el b/doom/.config/doom/config.el index 0d1a372..ee75e4d 100644 --- a/doom/.config/doom/config.el +++ b/doom/.config/doom/config.el @@ -18,9 +18,7 @@ (map! :leader (:prefix ("w" . "window") - :desc "Minimize window" "O" #'minimize-window) - (:prefix ("z" . "Personal") - :desc "Hermes Agent" "h" #'gortium/hermes-vterm)) + :desc "Minimize window" "O" #'minimize-window)) (use-package! ultra-scroll :init @@ -943,18 +941,7 @@ Handles org-clock and context link capture for tasks." (after! vterm (add-hook 'vterm-mode-hook (lambda () - (evil-local-set-key 'insert (kbd "C-j") #'vterm--self-insert))) - ;; Quick launch Hermes Agent on lazyworkhorse server - (defun gortium/hermes-vterm () - "Launch Hermes Agent in vterm via SSH to lazyworkhorse (CLI mode)." - (interactive) - (let ((buf (get-buffer-create "*hermes*"))) - (switch-to-buffer buf) - (unless (get-buffer-process buf) - (vterm buf) - (let ((proc (get-buffer-process buf))) - (when proc - (process-send-string proc "ssh -t lazyworkhorse hermes\n"))))))) + (evil-local-set-key 'insert (kbd "C-j") #'vterm--self-insert)))) ;; GPTel AI chat for emacs (use-package! gptel -- 2.49.1 From a09a7c03ef948be21feacec72c136ddf7e8cb1b4 Mon Sep 17 00:00:00 2001 From: Thierry Pouplier Date: Fri, 1 May 2026 15:02:19 +0000 Subject: [PATCH 5/8] fix: update zsh alias to direct SSH, fix Emacs function with delete-other-windows and correct docker exec path - Zsh alias now runs ssh + docker exec directly (no emacsclient) - Emacs function uses delete-other-windows for clean single-window vterm - SSH command uses correct docker exec path: /opt/hermes/.venv/bin/hermes - config.el not included - user will tangle from README.org --- doom/.config/doom/README.org | 4 +++- zsh/.zshrc | 4 ++-- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/doom/.config/doom/README.org b/doom/.config/doom/README.org index a54ebbb..d3088ff 100644 --- a/doom/.config/doom/README.org +++ b/doom/.config/doom/README.org @@ -1841,12 +1841,14 @@ Hermes Agent runs on lazyworkhorse server. Launched via SSH in a vterm buffer. "Launch Hermes Agent in vterm via SSH to lazyworkhorse (CLI mode)." (interactive) (let ((buf (get-buffer-create "*hermes*"))) + (delete-other-windows) (switch-to-buffer buf) (unless (get-buffer-process buf) (vterm buf) (let ((proc (get-buffer-process buf))) (when proc - (process-send-string proc "ssh -t lazyworkhorse hermes\n"))))))) + (process-send-string + proc "ssh -t lazyworkhorse 'docker exec -it hermes /opt/hermes/.venv/bin/hermes'\n"))))))) #+end_src * Tramp diff --git a/zsh/.zshrc b/zsh/.zshrc index 7cd3b74..072f6ee 100644 --- a/zsh/.zshrc +++ b/zsh/.zshrc @@ -19,8 +19,8 @@ alias emacs="emacsclient -c -a emacs" # Opencode alias oc="opencode" -# Hermes Agent in Emacs vterm -alias hermes="emacsclient -n -c -e '(gortium/hermes-vterm)'" +# Hermes Agent - SSH directly to remote server +alias hermes="ssh lazyworkhorse 'docker exec -it hermes /opt/hermes/.venv/bin/hermes'" # Yazi alias y="yazi" -- 2.49.1 From 386d1a3bf83ebf55f9325e80b25e78b79e8a78f3 Mon Sep 17 00:00:00 2001 From: Thierry Pouplier Date: Fri, 1 May 2026 15:06:05 +0000 Subject: [PATCH 6/8] fix: add ssh -t to zsh alias, use vterm-mode instead of vterm in Emacs function - zsh alias: added -t to SSH (docker exec -it needs a TTY) - Emacs function: vterm-mode instead of vterm (vterm splits windows, vterm-mode is just a major mode, keeps current window layout) - The SSH command in both cases is now consistent: ssh -t lazyworkhorse 'docker exec -it hermes /opt/hermes/.venv/bin/hermes' --- doom/.config/doom/README.org | 6 +++--- zsh/.zshrc | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/doom/.config/doom/README.org b/doom/.config/doom/README.org index d3088ff..bc5f6be 100644 --- a/doom/.config/doom/README.org +++ b/doom/.config/doom/README.org @@ -1841,10 +1841,10 @@ Hermes Agent runs on lazyworkhorse server. Launched via SSH in a vterm buffer. "Launch Hermes Agent in vterm via SSH to lazyworkhorse (CLI mode)." (interactive) (let ((buf (get-buffer-create "*hermes*"))) - (delete-other-windows) (switch-to-buffer buf) - (unless (get-buffer-process buf) - (vterm buf) + (unless (and (eq major-mode 'vterm-mode) + (get-buffer-process buf)) + (vterm-mode) (let ((proc (get-buffer-process buf))) (when proc (process-send-string diff --git a/zsh/.zshrc b/zsh/.zshrc index 072f6ee..0afbe72 100644 --- a/zsh/.zshrc +++ b/zsh/.zshrc @@ -20,7 +20,7 @@ alias emacs="emacsclient -c -a emacs" alias oc="opencode" # Hermes Agent - SSH directly to remote server -alias hermes="ssh lazyworkhorse 'docker exec -it hermes /opt/hermes/.venv/bin/hermes'" +alias hermes="ssh -t lazyworkhorse 'docker exec -it hermes /opt/hermes/.venv/bin/hermes'" # Yazi alias y="yazi" -- 2.49.1 From 311a2eae576fb3646ff771d8e054e66853d0f49d Mon Sep 17 00:00:00 2001 From: Thierry Pouplier Date: Thu, 14 May 2026 17:11:08 -0400 Subject: [PATCH 7/8] Emacs config with the hermes shortcut --- doom/.config/doom/config.el | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/doom/.config/doom/config.el b/doom/.config/doom/config.el index ee75e4d..64b3639 100644 --- a/doom/.config/doom/config.el +++ b/doom/.config/doom/config.el @@ -18,7 +18,9 @@ (map! :leader (:prefix ("w" . "window") - :desc "Minimize window" "O" #'minimize-window)) + :desc "Minimize window" "O" #'minimize-window) + (:prefix ("z" . "Personal") + :desc "Hermes Agent" "h" #'gortium/hermes-vterm)) (use-package! ultra-scroll :init @@ -1053,6 +1055,20 @@ DIFF: :desc "GPT generate commit" "g" #'gortium/magit-gptel-generate-commit) +(after! vterm + (defun gortium/hermes-vterm () + "Launch Hermes Agent in vterm via SSH to lazyworkhorse (CLI mode)." + (interactive) + (let ((buf (get-buffer-create "*hermes*"))) + (switch-to-buffer buf) + (unless (and (eq major-mode 'vterm-mode) + (get-buffer-process buf)) + (vterm-mode) + (let ((proc (get-buffer-process buf))) + (when proc + (process-send-string + proc "ssh -t lazyworkhorse 'docker exec -it hermes /opt/hermes/.venv/bin/hermes'\n"))))))) + ;; set `tramp-direct-async-process' locally in all ssh connections (connection-local-set-profile-variables 'remote-direct-async-process -- 2.49.1 From 4982831883875e64751b0b5ebc2483a7a47c8984 Mon Sep 17 00:00:00 2001 From: Thierry Pouplier Date: Thu, 14 May 2026 17:12:10 -0400 Subject: [PATCH 8/8] Command to send stuff to hermes --- zsh/.zshrc | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/zsh/.zshrc b/zsh/.zshrc index 0afbe72..23bd7c6 100644 --- a/zsh/.zshrc +++ b/zsh/.zshrc @@ -22,6 +22,30 @@ alias oc="opencode" # Hermes Agent - SSH directly to remote server alias hermes="ssh -t lazyworkhorse 'docker exec -it hermes /opt/hermes/.venv/bin/hermes'" +hermes-cp() { + if [ $# -eq 0 ]; then + echo "Usage: hermes-cp [...]" + echo "" + echo "Copies files/directories from your Arch laptop into the Hermes" + echo "agent container at /opt/data/home/ preserving directory structure." + echo "" + echo "Examples:" + echo " hermes-cp document.pdf # single file" + echo " hermes-cp *.pdf # multiple files (glob)" + echo " hermes-cp manuals/ # whole directory" + echo " hermes-cp manuals/ keyence-docs/ # multiple items" + echo "" + echo "To copy to a different destination inside the container:" + echo " tar -czf - . | ssh gortium@lazyworkhorse \\" + echo " \"docker exec -i hermes sh -c 'cd /opt/data/projects && tar -xzf -'\"" + return 1 + fi + # tar everything into a single SSH pipe, extract inside container + # Supports: single files, directories, glob patterns, mixed args + tar -czf - "$@" | ssh gortium@lazyworkhorse \ + "docker exec -i hermes sh -c 'cd /opt/data/home && tar -xzf -'" +} + # Yazi alias y="yazi" function yy() { -- 2.49.1