⌘+click finally works in my Elixir projects in VS Code with ElixirLS
For years I coded Elixir in VS Code without go-to-definition. It was on my list, I never had the time. Today I sat down with the ElixirLS…
⌘+click finally works in my Elixir projects in VS Code with ElixirLS
For years I coded Elixir in VS Code without go-to-definition. It was on my list, I never had the time. Today I sat down with the ElixirLS output log and fixed it in an hour. Here’s everything, so you don’t spend the same hour.
Install
ElixirLS: Elixir support and debugger (JakeBecker.elixir-ls).
Shortcut on macOS is ⌘+click or F12. Ctrl+click is the context menu.
Where is your mix.exs?
This is the big one. ElixirLS looks for mix.exs in the root of the opened folder.
Case A — mix.exs in root
myapp_umbrella/
├── mix.exs
└── apps/
Opened with code myapp_umbrella. No config needed. Umbrellas work fine from their root.
Case B — mix.exs in a subdirectory
myapp-application-felipe/ <- opened folder
└── myapp_umbrella/
├── mix.exs
└── apps/
The server starts, indexes nothing, and says so:
[warning] No mixfile found in project. Looked for mixfile at ".../mix.exs"
[info] Compile took 0 milliseconds
[ElixirLS WorkspaceSymbols] 0 symbols added to index in 0ms
Fix in .vscode/settings.json (workspace, not user):
{ "elixirLS.projectDir": "myapp_umbrella" }
Relative to the opened folder. Reload the window after.
Your only diagnostic
View > Output → ElixirLS. One line matters:
[ElixirLS WorkspaceSymbols] N symbols added to index in Xms
N > 0 → navigation works. N = 0 → scroll up for the compile error.
Compile once from the terminal
Indexing needs a successful build. elixirLS.fetchDeps defaults to false, so the server won't fetch deps for you.
mix deps.get
MIX_ENV=test mix compile
MIX_ENV=test is what ElixirLS uses by default.
Version manager mismatch (mise / asdf)
ElixirLS activates mise from the opened folder, not from projectDir. In case B, if the project pins a version and the parent doesn't, you get two different Elixirs.
# Output panel
Running on elixir 1.18.4 (compiled with Erlang/OTP 27) on OTP 27
# terminal, inside the project
$ mise current
elixir 1.19.5-otp-28
Two Elixirs writing the same _build means endless recompilation and bogus errors.
Fix — mirror the pin in the opened folder:
mise use elixir@1.19.5-otp-28 erlang@28
Then clear the mixed artifacts once:
rm -rf _build .elixir_ls
Case A doesn’t have this problem.
rebar3
Any Erlang dependency needs rebar3:
Could not find "rebar3", which is needed to build dependency :otel_http
** (Mix.Error) httpc request failed with: ... builds.hex.pm ... tls_alert
Mix does not check your PATH. It looks inside MIX_HOME, and downloads a copy if missing — which fails behind a TLS-inspecting proxy or VPN.
With mise, MIX_HOME lives inside each Elixir install, so a registered rebar3 is per Elixir version. Switch versions, it's gone.
Per version:
brew install rebar3
mix local.rebar rebar3 "$(which rebar3)" --force
Global — [MIX_REBAR3](https://hexdocs.pm/mix/Mix.html) overrides the copy Mix installs and survives version switches. In ~/.zshrc:
export MIX_REBAR3=/opt/homebrew/bin/rebar3
And in VS Code user settings:
{
"elixirLS.envVariables": { "MIX_REBAR3": "/opt/homebrew/bin/rebar3" }
}
envVariables is an object — workspace settings replace it wholesale, no key merge.
If you hit the TLS error, something is intercepting your HTTPS:
curl -v https://builds.hex.pm 2>&1 | grep -i issuer
Standard library navigation
Elixir sources not found (checking in /home/build/elixir).
Code navigation to Elixir modules disabled.
That path is baked in at CI build time. Jumping into Enum needs Elixir source on disk:
{ "elixirLS.stdlibSrcDir": "/path/to/elixir/lib/elixir/lib" }
Precompiled installs often ship no .ex files there — clone elixir-lang/elixir at your version tag instead. Independent of everything above; your own code navigates without it.
Documented non-bugs
- No go-to-definition inside a Phoenix router
scopeblock. - Fails when the cursor is at the very end of a symbol.
- Requires an open workspace; single-file editing unsupported.
Restarting
Command Palette (⌘⇧P), cheapest first:
Command When ElixirLS: Restart language server Config change, or after fixing a build ElixirLS: Run mix clean Restart wasn't enough Quit, rm -rf .elixir_ls, reopen Last resort — full Dialyzer rebuild
Checklist
mix.exsin the opened folder — orprojectDirset- Output panel Elixir version == terminal Elixir version
mix deps.get && MIX_ENV=test mix compilepasses- rebar3 registered, or
MIX_REBAR3exported - Non-zero symbol count
References
메타데이터
- post_id
- 3d8faf8a35ee
- slug
- click-finally-works-in-my-elixir-projects-in-vs-code-with-elixirls-3d8faf8a35ee
- url
- https://medium.com/@felipelopezhamann/click-finally-works-in-my-elixir-projects-in-vs-code-with-elixirls-3d8faf8a35ee
- canonical_url
- https://medium.com/@felipelopezhamann/click-finally-works-in-my-elixir-projects-in-vs-code-with-elixirls-3d8faf8a35ee
- author_url
- https://medium.com/@felipelopezhamann
- status
- ok
- fetched_at
- 2026-08-17 00:58:49