Windows (Native) Guide - Early Beta
native Windows support는 early beta입니다. 설치와 실행은 가능하고 Windows footgun lint도 통과하지만, Linux/macOS/WSL2 경로만큼 넓게 실전 검증되지는 않았습니다. 특히 subprocess handling, path quirks, non-ASCII console output 주변에 rough edge가 있을 수 있습니다. 재현 가능한 문제가 있으면 issues에 repro steps를 남겨 주세요. 지금 가장 검증된 Windows 환경이 필요하다면 WSL2 기반 Linux/macOS installer 경로를 사용하세요.
Hermes는 Windows 10과 Windows 11에서 native로 실행됩니다. WSL, Cygwin, Docker가 필요 없습니다. 이 문서는 deep dive입니다. native에서 무엇이 동작하는지, 무엇이 WSL 전용인지, installer가 실제로 무엇을 하는지, Windows 전용으로 만져야 할 knob은 무엇인지 설명합니다.
설치만 하고 싶다면 landing page 또는 Installation page의 one-liner면 충분합니다. 예상과 다른 동작을 만났을 때 이 문서로 돌아오세요.
dashboard embedded terminal, fork semantics, Linux-style file watchers 같은 POSIX 환경이 필요하다면 **Windows (WSL2) Guide**를 참고하세요. 둘은 함께 설치해도 충돌하지 않습니다. native data는 %LOCALAPPDATA%\hermes, WSL data는 ~/.hermes에 저장됩니다.
Quick install
PowerShell 또는 Windows Terminal을 열고 실행합니다.
irm https://raw.githubusercontent.com/NousResearch/hermes-agent/main/scripts/install.ps1 | iex
admin 권한은 필요 없습니다. installer는 %LOCALAPPDATA%\hermes\에 설치하고 hermes를 User PATH에 추가합니다. 설치가 끝나면 새 terminal을 여세요.
Installer options(parameter 전달에는 scriptblock form이 필요):
& ([scriptblock]::Create((irm https://raw.githubusercontent.com/NousResearch/hermes-agent/main/scripts/install.ps1))) -NoVenv -SkipSetup -Branch main
| Parameter | Default | Purpose |
|---|---|---|
-Branch | main | 특정 branch clone. PR 테스트에 유용 |
-NoVenv | off | venv 생성을 건너뜀. advanced: Python을 직접 관리 |
-SkipSetup | off | post-install hermes setup wizard 생략 |
-HermesHome | %LOCALAPPDATA%\hermes | data directory override |
-InstallDir | %LOCALAPPDATA%\hermes\hermes-agent | code location override |
Installer가 실제로 하는 일
순서대로 다음을 수행합니다.
uvbootstrap - Astral의 빠른 Python manager입니다.%USERPROFILE%\.local\bin에 설치됩니다.- Python 3.11 설치 -
uv를 통해 설치합니다. 기존 Python은 필요 없습니다. - Node.js 22 설치 - winget이 있으면 winget, 없으면 portable Node tarball을
%LOCALAPPDATA%\hermes\node아래에 풀어 설치합니다. browser tool과 WhatsApp bridge에 사용됩니다. - Portable Git 설치 -
git이 PATH에 있으면 그것을 사용합니다. 없으면 공식git-for-windowsrelease에서 trimmed self-contained PortableGit(약 45 MB)을%LOCALAPPDATA%\hermes\git에 받습니다. admin 권한이나 Windows installer registry가 필요 없고, 기존 설치에 간섭하지 않습니다. - repo clone -
%LOCALAPPDATA%\hermes\hermes-agent에 clone하고 그 안에 virtualenv를 만듭니다. - tiered
uv pip install- 먼저.[all]을 시도하고, GitHub rate limit 등으로git+httpsdependency가 흔들리면 점진적으로 작은 extras(.[messaging,dashboard,ext]->.[messaging]->.)로 fallback합니다. "dependency 하나가 흔들려 bare install로 떨어지는" 실패를 막습니다. - messaging SDK 자동 설치 -
.env에TELEGRAM_BOT_TOKEN,DISCORD_BOT_TOKEN,SLACK_BOT_TOKEN,SLACK_APP_TOKEN,WHATSAPP_ENABLED가 있으면python -m ensurepip --upgrade와 targetedpip install을 실행해 각 platform SDK가 실제로 import 가능하게 합니다. HERMES_GIT_BASH_PATH설정 - 해석된bash.exe경로를 설정해 fresh shell에서도 Hermes가 deterministic하게 찾도록 합니다.%LOCALAPPDATA%\hermes\bin을 User PATH에 추가 - 새 terminal을 열면hermescommand를 사용할 수 있습니다.hermes setup실행 - model, provider, toolsets를 설정하는 일반 first-run wizard입니다.-SkipSetup으로 생략할 수 있습니다.
Feature matrix
dashboard의 embedded terminal pane을 제외한 대부분의 기능은 native Windows에서 실행됩니다.
| Feature | Native Windows | WSL2 |
|---|---|---|
CLI(hermes chat, hermes setup, hermes gateway 등) | 지원 | 지원 |
Interactive TUI(hermes --tui) | 지원 | 지원 |
| Messaging gateway(Telegram, Discord, Slack, WhatsApp, 15+ platforms) | 지원 | 지원 |
| Cron scheduler | 지원 | 지원 |
| Browser tool(Chromium via Node) | 지원 | 지원 |
| MCP servers(stdio and HTTP) | 지원 | 지원 |
| Local Ollama / LM Studio / llama-server | 지원 | 지원(WSL networking 필요) |
| Web dashboard(sessions, jobs, metrics, config) | 지원 | 지원 |
Dashboard /chat embedded terminal pane | 미지원(POSIX PTY 필요) | 지원 |
| Auto-start at login | 지원(schtasks) | 지원(systemd) |
dashboard의 /chat tab은 POSIX PTY(ptyprocess)를 통해 실제 terminal을 embed합니다. native Windows에는 같은 primitive가 없습니다. Python의 pywinpty / Windows ConPTY로 구현할 수는 있지만 별도 implementation이므로 future work로 봅니다. dashboard의 나머지 기능은 native로 동작하며, 이 tab만 "use WSL2 for this" banner를 보여줍니다.
Windows에서 shell command 실행 방식
Hermes의 terminal tool은 Git Bash를 통해 command를 실행합니다. Claude Code가 쓰는 전략과 같습니다. 모든 tool을 rewrite하지 않고 POSIX-vs-Windows gap을 우회합니다.
bash.exe resolution order:
HERMES_GIT_BASH_PATHenvironment variable이 있으면 우선 사용.%LOCALAPPDATA%\hermes\git\usr\bin\bash.exe(installer-managed PortableGit).%LOCALAPPDATA%\hermes\git\bin\bash.exe(older Git-for-Windows layout).- system Git-for-Windows install(
%ProgramFiles%\Git\bin\bash.exe등). - 마지막 fallback으로 PATH에 있는 MSYS2, Cygwin, 기타
bash.exe.
installer는 HERMES_GIT_BASH_PATH를 명시적으로 설정해 fresh PowerShell session이 다시 탐색하지 않아도 되게 합니다. 특정 bash를 쓰고 싶다면 override하세요. 예: system Git Bash 또는 symlink를 통한 WSL-hosted bash.
Pitfall: MinGit layout은 full Git-for-Windows installer와 다릅니다. bash가 bin\bash.exe가 아니라 usr\bin\bash.exe 아래에 있습니다. Hermes는 둘 다 확인합니다. MinGit zip을 직접 푼다면 non-busybox variant(MinGit-*-64-bit.zip)를 고르세요. busybox build는 bash 대신 ash를 제공하고 coreutils가 많이 빠져 있습니다.
Windows UTF-8 console
Windows에서 Python의 기본 stdio는 active code page를 사용합니다. 대개 cp1252 또는 cp437입니다. Hermes banner, slash-command list, tool feed, Rich panels, skill descriptions에는 Unicode가 들어갑니다. 아무 처리도 없으면 UnicodeEncodeError: 'charmap' codec can't encode character로 crash할 수 있습니다.
수정은 hermes_cli/stdio.py::configure_windows_stdio()에 있으며, 모든 entry point(cli.py::main, hermes_cli/main.py::main, gateway/run.py::main) 초기에 호출됩니다.
이 함수가 하는 일:
kernel32.SetConsoleCP/SetConsoleOutputCP로 console code page를 CP_UTF8(65001)로 전환.sys.stdout/sys.stderr/sys.stdin을 UTF-8,errors='replace'로 reconfigure.- child Python subprocess도 UTF-8을 상속하도록
PYTHONIOENCODING=utf-8,PYTHONUTF8=1설정.setdefault를 사용하므로 사용자 override가 우선합니다. EDITOR와VISUAL이 모두 없으면EDITOR=notepad설정. 아래 Editor section 참고.
idempotent하며 non-Windows에서는 no-op입니다.
Opt out: 환경변수 HERMES_DISABLE_WINDOWS_UTF8=1을 설정하면 legacy cp1252 stdio path로 돌아갑니다. encoding bug를 bisect할 때 유용할 수 있지만, 일반적으로 올바른 설정은 아닙니다.
Editor(Ctrl-X Ctrl-E, /edit)
이전에는 Windows에서 Ctrl-X Ctrl-E를 누르거나 /edit를 입력해도 조용히 아무 일도 일어나지 않았습니다. prompt_toolkit의 fallback editor list는 POSIX absolute paths(/usr/bin/nano, /usr/bin/pico, /usr/bin/vi 등)에 고정되어 있어 Windows에서는 full Git for Windows가 설치되어 있어도 resolve되지 않았습니다.
Hermes의 Windows stdio shim은 이제 기본값으로 EDITOR=notepad를 설정합니다. Notepad는 모든 Windows 설치에 포함되어 있고 blocking editor로 동작합니다. subprocess.call(["notepad", file])은 window가 닫힐 때까지 block합니다.
User override가 우선합니다. setdefault 전에 확인됩니다.
| Editor | PowerShell command |
|---|---|
| VS Code | $env:EDITOR = "code --wait" |
| Notepad++ | $env:EDITOR = "'C:\Program Files\Notepad++\notepad++.exe' -multiInst -nosession" |
| Neovim | $env:EDITOR = "nvim" |
| Helix | $env:EDITOR = "hx" |
VS Code에서는 --wait flag가 중요합니다. 없으면 editor가 즉시 return하고 Hermes는 빈 buffer를 받습니다.
영구 설정하려면 PowerShell profile에 넣으세요.
# In $PROFILE
$env:EDITOR = "code --wait"
또는 System Settings의 User environment variable로 설정하면 새 shell 전체에 적용됩니다.
CLI에서 Ctrl+Enter로 newline 입력
Windows Terminal은 Ctrl+Enter를 dedicated key sequence로 전달합니다. Hermes는 이를 "insert newline"으로 bind합니다. 따라서 CLI에서 multi-line prompt를 작성할 때 Esc 후 Enter에 의존하지 않아도 됩니다. Windows Terminal, VS Code integrated terminal, VT escape sequences를 지원하는 modern Windows console host에서 동작합니다.
legacy cmd.exe console에서는 Ctrl+Enter가 plain Enter로 collapse됩니다. 이 경우 Esc Enter를 사용하거나 Windows Terminal로 전환하세요. Windows 11에는 기본 설치되어 있고 무료입니다.
Windows login 시 gateway 실행
Windows에서 hermes gateway install은 Scheduled Tasks를 사용하고, 실패 시 Startup folder fallback을 사용합니다. admin 권한은 필요 없습니다.
Install
hermes gateway install
내부 동작:
schtasks /Create /SC ONLOGON /RL LIMITED /TN HermesGateway- 사용자 login 때 standard(non-elevated) permission으로 실행되는 task 등록. UAC prompt 없음.- group policy로 schtasks가 차단되면
%APPDATA%\Microsoft\Windows\Start Menu\Programs\Startup에start /min cmd.exe /d /c <wrapper>shortcut을 작성합니다. 효과는 같지만 조금 더 투박합니다. - gateway를
python.exe가 아니라 **pythonw.exe**로 detached spawn합니다.pythonw.exe는 console이 붙지 않으므로 같은 process group의 sibling process에서 Ctrl+C를 눌렀을 때 발생하는CTRL_C_EVENTbroadcast에 영향을 받지 않습니다.
spawn flags: DETACHED_PROCESS | CREATE_NEW_PROCESS_GROUP | CREATE_NO_WINDOW | CREATE_BREAKAWAY_FROM_JOB
Manage
hermes gateway status # schtasks + Startup folder + running PID merged view
hermes gateway start # scheduled task를 지금 시작
hermes gateway stop # graceful SIGTERM equivalent(psutil을 통한 TerminateProcess)
hermes gateway restart
hermes gateway uninstall # schtasks entry, Startup shortcut, pid file 제거
hermes gateway status는 idempotent입니다. 여러 번 호출해도 gateway를 실수로 죽이지 않습니다. 이전 구현에서는 os.kill(pid, 0)이 Windows에서 CTRL_C_EVENT와 충돌해 status 확인이 gateway를 죽이는 문제가 있었습니다. 자세한 내용은 아래 process management internals를 참고하세요.
왜 Windows Service가 아닌가?
service 설치에는 admin 권한이 필요하고 lifecycle이 user login이 아니라 machine boot에 묶입니다. 일반적인 Hermes 사용자가 원하는 것은 "로그인하면 gateway 사용 가능, 로그아웃하면 gateway 종료"입니다. Scheduled Tasks는 elevation 없이 정확히 그 동작을 제공합니다. 정말 service가 필요하다면 nssm 또는 sc create를 직접 사용할 수 있지만, 보통은 필요 없습니다.
Data layout
| Path | Contents |
|---|---|
%LOCALAPPDATA%\hermes\hermes-agent\ | Git checkout + venv. 삭제 후 재설치해도 됩니다. |
%LOCALAPPDATA%\hermes\git\ | PortableGit. installer가 provision한 경우만 존재 |
%LOCALAPPDATA%\hermes\node\ | Portable Node.js. installer가 provision한 경우만 존재 |
%LOCALAPPDATA%\hermes\bin\ | hermes.cmd shim. User PATH에 추가됨 |
%USERPROFILE%\.hermes\ | 사용자 config, auth, skills, sessions, logs. 재설치 후에도 유지 |
이 분리는 의도적입니다. %LOCALAPPDATA%\hermes는 disposable infrastructure입니다. 지워도 one-liner가 복구합니다. %USERPROFILE%\.hermes는 사용자 data입니다. config, memory, skills, session history가 들어 있으며 Linux install과 같은 모양입니다. 이 directory를 machine 간 mirror하면 Hermes 상태도 함께 옮겨집니다.
HERMES_HOME override: environment variable을 다른 data directory로 지정할 수 있습니다. Linux와 같은 방식으로 동작합니다.
Browser tool
browser tool은 Node helper인 agent-browser로 Chromium을 제어합니다. Windows에서는:
- installer가 npm을 통해
agent-browser를 PATH에 둡니다. shutil.which("agent-browser", path=...)가.cmdshim을 자동으로 찾습니다.CreateProcessW는 extensionless shebang을 실행할 수 없으므로 Hermes는 항상.CMDwrapper로 resolve합니다. shebang script를 직접 호출하지 말고.cmd를 거치세요.- Playwright Chromium은 첫 실행 시 자동 설치됩니다(
npx playwright install chromium). 설치가 실패하면hermes doctor가 fix-it hint와 함께 보여줍니다.
Windows에서 Hermes 실행 시 practical notes
설치 후 PATH
installer는 %LOCALAPPDATA%\hermes\bin을 [Environment]::SetEnvironmentVariable로 User PATH에 추가합니다. 이미 열려 있는 terminal은 이 변경을 받지 않습니다. 설치 후 새 PowerShell window 또는 Windows Terminal tab을 여세요. 잘 모르면 수동으로 $env:PATH += ...를 붙이지 마세요.
확인:
Get-Command hermes # C:\Users\<you>\AppData\Local\hermes\bin\hermes.cmd 출력
hermes --version
Environment variables
Hermes는 $env:X(process-scope)와 User environment variables(permanent, System Properties -> Environment Variables)를 모두 존중합니다. API keys는 %USERPROFILE%\.hermes\.env에 넣는 것이 일반적이며 Linux와 같습니다.
OPENROUTER_API_KEY=sk-or-...
TELEGRAM_BOT_TOKEN=...
특별히 모든 Windows process가 secret을 보게 만들고 싶은 경우가 아니라면 User environment variables에 secret을 넣지 마세요.
Windows-specific env vars
native Windows install에만 영향을 주는 변수입니다.
| Variable | Effect |
|---|---|
HERMES_GIT_BASH_PATH | bash.exe discovery override. full Git-for-Windows, symlink를 통한 WSL bash, MSYS2, Cygwin 등 어느 bash든 지정 가능. installer가 자동 설정합니다. |
HERMES_DISABLE_WINDOWS_UTF8 | 1이면 UTF-8 stdio shim을 끄고 locale code page로 fallback. encoding bug bisect용 |
EDITOR / VISUAL | /edit와 Ctrl-X Ctrl-E에 사용할 editor. 둘 다 없으면 Hermes가 notepad로 default 설정 |
Uninstall
PowerShell에서:
hermes uninstall
clean path입니다. schtasks entry, Startup folder shortcut, hermes.cmd shim을 제거하고 %LOCALAPPDATA%\hermes\hermes-agent\를 삭제하며 User PATH를 정리합니다. 재설치를 고려해 %USERPROFILE%\.hermes\(config, auth, skills, sessions, logs)는 그대로 둡니다.
정말 전부 지우려면:
hermes uninstall
Remove-Item -Recurse -Force "$env:USERPROFILE\.hermes"
Remove-Item -Recurse -Force "$env:LOCALAPPDATA\hermes"
hermes uninstall CLI subcommand는 schtasks entry가 older install에서 다른 task name으로 등록된 경우도 처리합니다. hardcoded task name이 아니라 install path로 검색합니다.
Process management internals
이 section은 background material입니다. "왜 자꾸 스스로 죽지?" 같은 문제를 debug할 때만 보세요.
Linux와 macOS에서 POSIX idiom인 os.kill(pid, 0)은 no-op permission check입니다. "이 PID가 살아 있고 signal을 보낼 수 있는가?"를 확인합니다. Windows에서 Python의 os.kill은 sig=0을 CTRL_C_EVENT에 map합니다. 둘 다 integer value 0이라 충돌하고, GenerateConsoleCtrlEvent(0, pid)를 통해 target PID가 속한 전체 console process group에 Ctrl+C를 broadcast합니다. 이는 bpo-14484이며 2012년부터 열려 있습니다. 현재 동작에 의존하는 script를 깨뜨릴 수 있어 수정되지 않을 가능성이 큽니다.
결과적으로 Windows에서 os.kill(pid, 0)으로 "PID가 살아 있는지 확인"하던 codepath는 target을 조용히 죽일 수 있었습니다. Hermes는 이런 모든 위치(11 files의 14 call sites)를 gateway.status._pid_exists()로 옮겼습니다. 이 함수는 psutil.pid_exists()를 사용하고, Windows에서는 OpenProcess + GetExitCodeProcess로 확인하므로 signal을 보내지 않습니다. plugin이나 patch를 작성한다면 psutil.pid_exists() 또는 gateway.status._pid_exists()를 사용하세요. os.kill(pid, 0)은 쓰지 마세요.
scripts/check-windows-footguns.py는 이를 CI에서 강제합니다. 새 os.kill(pid, 0) call이 들어오면, 해당 line에 # windows-footgun: ok - <reason> marker가 없는 한 Windows footguns (blocking) check가 실패합니다.
Common pitfalls
설치 직후 hermes: command not found가 납니다.
새 PowerShell window를 여세요. installer가 %LOCALAPPDATA%\hermes\bin을 User PATH에 추가했지만 기존 shell은 갱신되지 않습니다. 당장 실행하려면 & "$env:LOCALAPPDATA\hermes\bin\hermes.cmd"를 사용할 수 있습니다.
tool 실행 중 WinError 193: %1 is not a valid Win32 application이 납니다.
.cmd shim을 거치지 않고 shebang script를 직접 호출한 경우입니다. Hermes는 shutil.which(cmd, path=local_bin)로 command를 resolve해 PATHEXT가 .CMD를 잡게 합니다. hardcoded path로 tool을 호출하고 있다면 .cmd variant로 바꾸세요. 예: npx가 아니라 npx.cmd.
[scriptblock]::Create(...)가 The assignment expression is not valid로 실패합니다.
받아 온 install.ps1에 UTF-8 BOM이 붙은 경우입니다. irm | iex form은 BOM을 자동으로 제거하지만 [scriptblock]::Create((irm ...))는 그렇지 않습니다. simple irm | iex form으로 다시 실행하거나, script를 수동으로 내려받아 BOM 없이 저장하세요: [IO.File]::WriteAllText($path, $text, (New-Object Text.UTF8Encoding $false)).
restart 후 gateway가 계속 살아 있지 않습니다.
hermes gateway status를 확인하세요. 이 명령은 schtasks entry, Startup-folder shortcut, live PID를 merge해 보여줍니다. schtasks가 등록되어 있는데 실행되지 않는다면 group policy가 ONLOGON trigger를 막고 있을 수 있습니다. schtasks /Query /TN HermesGateway /V /FO LIST로 failure reason을 확인하거나, uninstall 후 HERMES_GATEWAY_FORCE_STARTUP=1로 reinstall해 Startup-folder path로 fallback하세요.
$env:EDITOR를 설정했는데도 /edit가 아무 일도 하지 않습니다.
현재 process에만 설정했을 수 있습니다. shell을 닫았다가 다시 열거나, System Properties -> Environment Variables에서 User scope로 설정하세요. 새 PowerShell window에서 echo $env:EDITOR로 확인합니다.
Browser tool은 launch되지만 tools가 timeout됩니다.
Chromium은 첫 실행 시 자동 설치됩니다. rate-limited GitHub나 Playwright CDN 이슈로 설치가 실패했다면 hermes doctor가 missing Chromium과 정확한 npx playwright install chromium fix command를 표시합니다.
agent-browser가 이상한 Node version error로 실패합니다.
installer는 Node 22를 %LOCALAPPDATA%\hermes\node에 provision하지만, PATH에서 오래된 system Node 18이 먼저 잡힐 수 있습니다. Hermes의 node directory를 PATH 앞쪽으로 옮기거나, 다른 곳에서 쓰지 않는 system Node install을 제거하세요.
중국어/일본어/아랍어 문자가 CLI에서 ?로 보입니다.
UTF-8 stdio shim이 활성화되지 않은 것입니다. HERMES_DISABLE_WINDOWS_UTF8가 설정되어 있지 않은지 확인하세요: Get-ChildItem env:HERMES_DISABLE_WINDOWS_UTF8. 비어 있는데도 ?가 보이면 매우 오래된 console host가 UTF-8을 제대로 지원하지 않을 수 있습니다. Windows Terminal로 전환하세요.
Gateway가 Telegram photos를 보낼 때 BadRequest: payload contains invalid characters가 납니다.
Windows 자체 문제는 아니지만 Windows에서 먼저 보일 수 있습니다. 보통 JSON body에 backslash가 escape되지 않은 raw Windows path가 들어간 경우입니다. Telegram에는 Hermes가 normalize한 path가 전달되어야 합니다. custom plugin 안에서 본다면 사용자 input에서 만든 str(Path(...))가 아니라 Hermes-provided path를 넘기고 있는지 확인하세요.
다른 machine에서는 되는데 git pull 후 encoding이 이상합니다.
Windows에서 non-UTF-8 editor(구버전 Notepad, 일부 Chinese IME 등)로 Hermes config나 skill을 수정하면 BOM이 붙을 수 있습니다. Hermes는 대부분의 config read에서 utf-8-sig를 tolerate하지만, folded YAML scalar(description: >) 내부 BOM은 YAML parsing을 조용히 깨뜨릴 수 있습니다. file을 plain UTF-8 without BOM으로 다시 저장하세요.
다음으로 볼 문서
- Installation - Linux/macOS/WSL2/Termux를 포함한 전체 install page.
- Windows (WSL2) Guide - POSIX semantics 또는 dashboard terminal pane이 필요할 때.
- CLI Reference - 모든
hermessubcommand. - FAQ - Windows 외 common questions.
- Messaging Gateway - Windows에서 Telegram/Discord/Slack 실행.