Elixir LSP в Claude Code: настройка для контейнеров
Суть проблемы
Claude Code имеет встроенный LSP tool, но он несовместим с Lexical (новый официальный LS) из-за client/registerCapability. Совместим только ElixirLS (старый, сторонний).
Архитектура решения
Claude Code (LSP tool)
│
│ JSON-RPC / stdio
▼
elixir-lsp плагин
│ запускает
▼
/opt/elixir-ls/language_server.sh ← ElixirLS бинарник
│
│ анализирует
▼
Elixir проект (mix.exs)
.elixir_ls/ ← кэш индекса (персистентный)
Что нужно установить
1. ElixirLS бинарник
# В Dockerfile или setup скрипте
RUN mkdir -p /opt/elixir-ls && \
cd /opt/elixir-ls && \
curl -L https://github.com/elixir-lsp/elixir-ls/releases/download/v0.30.0/elixir-ls-v0.30.0.zip \
-o elixir-ls.zip && \
unzip elixir-ls.zip && \
rm elixir-ls.zip && \
chmod +x language_server.sh
# Добавить в PATH
ENV PATH="/opt/elixir-ls:$PATH"
Версию проверить на: https://github.com/elixir-lsp/elixir-ls/releases
2. Плагин elixir-lsp в Claude Code
# Установить плагин (внутри контейнера, один раз)
claude plugin install elixir-lsp
После установки плагин регистрирует ElixirLS как LSP-сервер для .ex, .exs, .heex, .eex, .leex.
Что происходит при старте сессии
claude запускается
│
├─ читает плагины → находит elixir-lsp
│
├─ спавнит: /opt/elixir-ls/language_server.sh
│ (отдельный OS-процесс)
│
└─ ElixirLS инициализируется:
1. Читает mix.exs
2. Компилирует зависимости (первый раз ~2-5 мин)
3. Строит индекс символов
4. Пишет кэш → .elixir_ls/
5. Готов (~9000+ символов для PhoenixKit)
Важно: Первый запуск в новом контейнере медленный. Последующие — быстрые (кэш из .elixir_ls/).
Проверка работоспособности
После старта сессии Claude Code — попросить выполнить проверку:
Use the LSP tool to run documentSymbol on lib/.ex
Ожидаемый результат:
- Список функций файла → LSP активен
- Ошибка “No LSP server” → ElixirLS не найден или не запустился
Для полной проверки — workspaceSymbol (возвращает тысячи символов после индексации):
Use the LSP tool: workspaceSymbol on any project file
Типичные проблемы
| Симптом | Причина | Решение |
|---|---|---|
| “No LSP server available” | ElixirLS не найден в PATH |
Проверить /opt/elixir-ls/language_server.sh, добавить в PATH |
“requires restart” после /reload-plugins |
Нормально — LSP стартует при следующем запуске claude | Перезапустить claude (не TMUX) |
workspaceSymbol → 0 результатов |
Индексация ещё не завершена | Подождать 1-2 мин, повторить |
| LSP зависает навсегда | Попытка использовать Lexical вместо ElixirLS | Lexical несовместим, использовать только ElixirLS |
| Медленная индексация |
Первый запуск, нет .elixir_ls/ кэша |
Нормально, ждать 2-5 мин |
Персистентность кэша между сессиями
Контейнер
├── /opt/elixir-ls/ ← монтировать или билдить в image
│ └── language_server.sh
│
└── /app/ ← проект
└── .elixir_ls/ ← МОНТИРОВАТЬ как volume
├── build/ (скомпилированные .beam)
└── dialyzer/ (PLT файлы, большие)
Если .elixir_ls/ не персистентный — каждое пересоздание контейнера = полная переиндексация.
# docker-compose.yml
volumes:
- ./:/app
- elixir_ls_cache:/app/.elixir_ls # ← важно
volumes:
elixir_ls_cache:
Минимальный чеклист
-
[ ] ElixirLS установлен в
/opt/elixir-ls/(или любой PATH-доступный путь) -
[ ] Плагин elixir-lsp установлен:
claude plugin install elixir-lsp -
[ ]
.elixir_ls/персистентный (volume или не в gitignore если нужен кэш) - [ ] Первый запуск — подождать индексацию (1-5 мин)
- [ ] Lexical НЕ использовать с LSP tool — несовместим