언어 서버 프로토콜 (LSP)
Hermes는 pyright, gopls, rust-analyzer, typescript-language-server, clangd 등 20개 이상의 language server를 background subprocess로 실행하고, write_file 및 patch 이후의 post-write lint check에 semantic diagnostic을 제공합니다. agent가 file을 편집하면 단순 syntax error뿐 아니라 type error, undefined name, missing import, project-wide semantic issue처럼 language server가 감지한 문제도 정확히 볼 수 있습니다.
이는 상위 coding agent가 사용하는 것과 같은 architecture입니다. Hermes가 자체적으로 관리하므로 editor host, plugin install, 별도 daemon 관리가 필요 없습니다.
LSP 실행
LSP는 git workspace detection으로 gate됩니다. agent의 directory(또는 편집된 file)가 git repository 안에 있으면 LSP가 해당 workspace에 대해 실행됩니다. git repo 밖에서는 LSP가 dormant 상태로 남습니다. 이는 cwd가 사용자 home directory이고 진단할 project가 없는 messaging gateway에서 유용합니다.
검사는 계층적으로 수행됩니다. 먼저 in-process syntax check를 실행하고(마이크로초 단위), syntax가 깨끗할 때만 LSP 진단을 실행합니다. language server가 flaky하거나 없더라도 write가 막히지 않도록, 모든 LSP 실패 경로는 syntax-only 결과로 fallback합니다.
구체적으로, 모든 성공적인 write_file 또는 patch에:
- Hermes가 해당 file의 현재 diagnostic baseline을 capture합니다.
- write를 수행합니다.
- language server를 다시 query하고, 이미 있던 diagnostic을 걸러 새 항목만 표시합니다.
agent는 다음과 같은 output을 봅니다.
{
"bytes_written": 42,
"dirs_created": false,
"lint": {"status": "ok", "output": ""},
"lsp_diagnostics": "LSP diagnostics introduced by this edit:\n<diagnostics file=\"/path/to/foo.py\">\nERROR [42:5] Cannot find name 'foo' [reportUndefinedVariable](Pyright)\nERROR [50:1] Argument of type \"str\" is not assignable to \"int\" [reportArgumentType](Pyright)\n</diagnostics>"
}
lint field는 ast.parse, json.loads 같은 in-process parse를 통해 얻은 syntax check 결과를 나타냅니다(마이크로초 단위). lsp_diagnostics field는 실제 language server가 반환한 semantic diagnostic을 담습니다. 두 channel은 독립적인 signal입니다. syntax 문제는 없지만 semantic 문제가 있는 file이라면 agent는 lint: ok와 함께 채워진 lsp_diagnostics를 보게 됩니다.
지원 언어
| 언어 | 서버 | 자동 설치 |
|---|---|---|
| Python | pyright-langserver | npm |
| TypeScript / JavaScript / JSX / TSX | typescript-language-server | npm |
| Vue | @vue/language-server | npm |
| Svelte | svelte-language-server | npm |
| Astro | @astrojs/language-server | npm |
| Go | gopls | go install |
| Rust | rust-analyzer | 수동 (rustup) |
| C / C++ | clangd | 수동 (LLVM) |
| Bash / Zsh | bash-language-server | npm |
| YAML | yaml-language-server | npm |
| Lua | lua-language-server | 수동 (GitHub releases) |
| PHP | intelephense | npm |
| OCaml | ocaml-lsp | 수동 (opam) |
| Dockerfile | dockerfile-language-server-nodejs | npm |
| Terraform | terraform-ls | 수동 |
| Dart | dart language-server | 수동 (dart sdk) |
| Haskell | haskell-language-server | 수동 (ghcup) |
| Julia | julia + LanguageServer.jl | 수동 |
| Clojure | clojure-lsp | 수동 |
| Nix | nixd | 수동 |
| Zig | zls | 수동 |
| Gleam | gleam lsp | 수동 (gleam 설치) |
| Elixir | elixir-ls | 수동 |
| Prisma | prisma language-server | 수동 |
| Kotlin | kotlin-language-server | 수동 |
| Java | jdtls | 수동 |
manual 항목은 해당 언어의 툴체인 관리자(rustup, ghcup, opam, brew 등)로 서버를 설치하세요. Hermes는 PATH 또는 <HERMES_HOME>/lsp/bin/에서 바이너리를 자동 감지합니다.
일부 서버는 npm이 자동으로 끌어오지 않는 peer dependency와 함께 설치됩니다. 현재 대표 사례는 typescript-language-server이며, 같은 node_modules 트리에서 import 가능한 typescript SDK가 필요합니다. hermes lsp install typescript를 실행하거나 첫 사용 시 auto-install이 동작하면 Hermes가 두 패키지를 함께 설치합니다.
CLI
hermes lsp status # service state + per-server install status
hermes lsp list # registry, optionally --installed-only
hermes lsp install <id> # eagerly install one server
hermes lsp install-all # try every server with a known recipe
hermes lsp restart # tear down running clients
hermes lsp which <id> # print resolved binary path
hermes lsp status는 가장 좋은 출발점입니다. 현재 semantic diagnostics를 받을 수 있는 언어와 별도 바이너리 설치가 필요한 언어를 보여줍니다.
구성
일반적인 설정에서는 기본값으로 충분합니다. 필요한 바이너리가 PATH에 있다면 따로 설정할 것은 없습니다.
# config.yaml
lsp:
# Master toggle. Disabling skips the entire subsystem — no servers
# spawn, no background event loop runs.
enabled: true
# How long to wait for diagnostics after each write.
wait_mode: document # "document" or "full"
wait_timeout: 5.0
# How to handle missing server binaries.
# auto — install via npm/pip/go install into <HERMES_HOME>/lsp/bin
# manual — only use binaries already on PATH
install_strategy: auto
# Per-server overrides (all optional).
servers:
pyright:
disabled: false
command: ["/abs/path/to/pyright-langserver", "--stdio"]
env: { PYRIGHT_LOG_LEVEL: "info" }
initialization_options:
python:
analysis:
typeCheckingMode: "strict"
typescript:
disabled: true # skip TS even when its extensions match
서버 키
disabled: true- file extension이 맞아도 이 server를 완전히 건너뜁니다.command: [bin,...args]- custom binary path를 고정합니다. 자동 설치보다 우선합니다.env: {KEY: value}- spawned process에 전달할 추가 env var입니다.initialization_options: {...}- LSPinitialize요청에 전송되는initializationOptionspayload에 병합됩니다. 값은 server별로 다르므로 language server 문서를 참고하세요.
설치 위치
install_strategy: auto이면 Hermes는 binary를 <HERMES_HOME>/lsp/bin/에 설치합니다. NPM package는 <HERMES_HOME>/lsp/node_modules/에 설치되고, bin symlink는 한 단계 위에 만들어집니다. Go 기반 server는 이 staging directory를 GOBIN으로 사용합니다.
/usr/local/, ~/.local/ 같은 공유 위치에는 설치하지 않습니다. staging directory는 완전히 Hermes가 소유하며 profile을 reset할 때 제거됩니다.
성능 특성
LSP server는 첫 사용 시 lazy-spawn됩니다. .py 파일을 편집한 적이 없는 project에서는 pyright traffic이 발생하지 않습니다. 대부분의 server는 spawn에 1-3초가 걸리고, cold project의 rust-analyzer는 10초 이상 걸릴 수 있습니다. 같은 workspace에서 이어지는 edit은 이미 실행 중인 server를 재사용합니다.
diagnostic이 나오지 않는 깨끗한 write에서는 LSP layer가 몇 밀리초 정도만 추가합니다. diagnostic이 나오는 경우 대기 예산은 wait_timeout초입니다. 일반적으로 pyright/tsserver는 수십 밀리초 안에 응답하고, rust-analyzer는 indexing 중일 때 몇 초가 걸릴 수 있습니다.
server는 Hermes process가 살아 있는 동안 유지됩니다. 아직 idle-timeout reaper는 없습니다. 매 write마다 server index를 다시 시작하는 비용이 daemon을 유지하는 비용보다 훨씬 크기 때문입니다.
비활성화
전체 subsystem을 비활성화하려면 config.yaml에서 lsp.enabled: false를 설정하세요. post-write check는 이전 버전과 동일하게 in-process syntax check(Python의 ast.parse, JSON의 json.loads 등)로 돌아갑니다.
전체 레이어를 비활성화하지 않고 단일 언어를 비활성화하려면:
lsp:
servers:
rust-analyzer:
disabled: true
문제 해결
**hermes lsp status는 "missing"으로 서버를 보여줍니다. * 이름
이진은 PATH가 아니며 <HERMES_HOME>/lsp/bin/에 없습니다. 지원하다
hermes lsp install <server_id> 자동 설치를 시도하거나
언어의 정상적인 툴체인을 통해 이진을 수동으로 설치합니다.
Backend warnings 섹션에서 hermes lsp status
일부 서버는 외부 CLI 주변의 얇은 래퍼로 배송됩니다
진단 - 그들은 깨끗하게 말하고 요청을 수락하지만 결코 방출하지
sidecar 바이너리가 누락 될 때 오류. 가장 일반적인 케이스는
bash-language-server, shellcheck에 진단을 위임합니다.
hermes lsp status가 Backend warnings 섹션을 표시하면 설치됩니다
OS 패키지 관리자를 통해 지정된 도구:
apt install shellcheck # Debian / Ubuntu
brew install shellcheck # macOS
scoop install shellcheck # Windows
동일한 경고는 서버에서 한 번에 기록됩니다
~/.hermes/logs/agent.log입니다.
** 서버는 시작하지만 진단을 반환하지 않습니다 * * 이름
~/.hermes/logs/agent.log를 [agent.lsp.client] 항목에 체크하세요
언어 서버 및 프로토콜 오류 땅에서 모두 stderr
있습니다. 일부 서버(rust-analyzer 특히)는 완료해야 합니다
프로젝트 전체 색인은 per-file 진단을 방출하기 전에; 첫번째
서버 시작 후에 편집은 아무 진단도 없이, 완료할지도 모릅니다
그(것)들을 데려오기 후에 편집합니다.
*서버 충돌 * 이름
추락된 서버가 파손된 상태로 추가되며, 다시 시도할 수 없습니다
세션의 나머지. hermes lsp restart 을 실행하여 설정을 취소합니다;
다음 편집 re-spawns.
어떤 git repo 이외의 파일을 편집
디자인에 의해, LSP는 단지 git 저장소 안쪽에 실행합니다. 프로젝트가 없다면
그러나 초기화, 실행 git init LSP 진단을 가능하게. 그렇지 않으면
in-process syntax-only fallback 적용.