Helix + LanguageServer.jl + JuliaFormatter.jl

I’m trying to move from vscode to helix to save my RAM for Julia.

I’m on helix 25.07.01, julia 1.12.1. I haven’t configured anything except

$ cat ~/.config/helix/config.toml 
theme = "autumn_night"

$ cat ~/.config/helix/languages.toml 
[[language]]
name = "julia"
auto-format = true

If I open a julia file in helix I can see the language server is running

$ pgrep -laf julia
4072615 /usr/bin/julia --startup-file=no --history-file=no --quiet -e using LanguageServer; runserver()

and it’s doing its job: it knows about Julia keywords and types

But it’s unreliable around formatting.

It’s slow to format on the first save. It takes long enough that I can easily cancel it by changing the text. And it seems that if I am making lots of small changes and saving quickly, it never gets a chance to fully compile so it never formats my code.

The = button gives an error the first time I try to use it.

No configured language server supports range formatting

I have to wait, and then on the second time it works. This error is really confusing to me because it says “no support” but then a second later clearly there is support

If I press = multiple times in a row while it’s trying to figure itself out I’m able to lock the session up hard

Am I doing something wrong? neovim people, do you ever have these kinds of problems?


I’ve read the sysimage advice (repeated here and here). I tried

$ time julia --startup-file=no --project=@helix-lsp -e 'import Pkg; Pkg.add(["LanguageServer", "PackageCompiler", "JuliaFormatter"]); Pkg.update();using PackageCompiler; create_sysimage([:LanguageServer, :JuliaFormatter], sysimage_path=dirname(Pkg.Types.Context().env.project_file) * "/languageserver.so")'

I added this to language.toml:

[language-server.julia]
timeout = 60
command = "julia"
args = [
  "--project=@helix-lsp",
  "--startup-file=no",
  "--history-file=no",
  "--quiet",
  "-J/home/kousu/.julia/environments/helix-lsp/languageserver.so",
  "--sysimage-native-code=yes",
  "-e",
  """"
  import Pkg
project_path = let
    dirname(something(
        Base.load_path_expand((
            p = get(ENV, "JULIA_PROJECT", nothing);
            isnothing(p) ? nothing : isempty(p) ? nothing : p
        )),
        Base.current_project(pwd()),
        Pkg.Types.Context().env.project_file,
        Base.active_project(),
    ))
    end
ls_install_path = joinpath(get(DEPOT_PATH, 1, joinpath(homedir(), ".julia")), "environments", "helix-lsp");
pushfirst!(LOAD_PATH, ls_install_path);
using LanguageServer;
popfirst!(LOAD_PATH);
depot_path = get(ENV, "JULIA_DEPOT_PATH", "")
symbol_server_path = joinpath(homedir(), ".cache", "helix", "julia_lsp_symbol_server")
mkpath(symbol_server_path)
server = LanguageServer.LanguageServerIn`stance(stdin, stdout, project_path, depot_path, nothing, symbol_server_path, true)
server.runlinter = true
run(server)
"""
]

And I can see this is the version running now

$ pgrep -laf julia
23425 /usr/bin/julia --project=@helix-lsp --startup-file=no --history-file=no --quiet -J/home/kousu/.julia/environments/helix-lsp/languageserver.so --sysimage-native-code=yes -e "   import Pkg project_path = let     dirname(something(         Base.load_path_expand((             p = get(ENV, "JULIA_PROJECT", nothing);             isnothing(p) ? nothing : isempty(p) ? nothing : p         )),         Base.current_project(pwd()),         Pkg.Types.Context().env.project_file,         Base.active_project(),     ))     end ls_install_path = joinpath(get(DEPOT_PATH, 1, joinpath(homedir(), ".julia")), "environments", "helix-lsp"); pushfirst!(LOAD_PATH, ls_install_path); using LanguageServer; popfirst!(LOAD_PATH); depot_path = get(ENV, "JULIA_DEPOT_PATH", "") symbol_server_path = joinpath(homedir(), ".cache", "helix", "julia_lsp_symbol_server") mkpath(symbol_server_path) server = LanguageServer.LanguageServerInstance(stdin, stdout, project_path, depot_path, nothing, symbol_server_path, true) server.runlinter = true run(server) 

But it’s still slow.

What am I doing wrong? How do I debug this (can I see a log of what the language server is loading?). How do I make it faster?


I just tried to see if vscode has the same first-load problem and it does. It won’t format my code until after it finished with this:

Screenshot From 2025-11-09 00-37-14

and then gives me this error about it crashing:

Once it gives that error, though, formatting is fast.

2 Likes

I used the experimental juliac to build a statically linked formatter:

$ cat jlfmt.jl 
using JuliaFormatter
function @main(ARGS::Vector{String})::Cint
    try
        for f in ARGS
            if f == "-"
                print(format_text(read(stdin, String)))
            else
                format_file(f)
            end
        end
        return 0
    catch e
        @error "err:" e
        return 1
    end
end

This didn’t work unfortunately, there were too many functions that can’t be trimmed yet I guess

julia /usr/share/julia/juliac/juliac.jl --experimental --output-exe ./jlfmt --trim ./jlfmt.jl 

This did

julia /usr/share/julia/juliac/juliac.jl --output-exe ./jlfmt ./jlfmt.jl 

It unfortunately took minutes and made a very large binary

$ ls -lh jlfmt
-rwxr-xr-x 1 kousu kousu 264M Nov  9 01:27 jlfmt

but it worked in the end.

Here’s my config now:

$ cat ~/.config/helix/config.toml 
theme = "autumn_night"

$ cat ~/.config/helix/languages.toml 
[[language]]
name = "julia"
auto-format = true
formatter = { command = "/home/kousu/src/jlfmt", args = ["-"] }

With this, formatting on save or with = works instantly.

This doesn’t seem like a good solution. The language server is supposed to handle formatting. I wish to get it to a point where it does, out of the box.

Unfortunately, format-on-save swallows errors silently; if I mangle the code enough it can’t be formatted then = shows an error (but only the first line of the error, and quickly) and format-on-save doesn’t at all.

1 Like

My go-to configuration would be similar to the one outlined here: GitHub - milanglacier/Helix-Zellij-AI-REPL-Workflow: workflow integration for Helix, Zellij, AI Code Completion, AI CLIs, and REPLs built around two minimal shell scripts with nearly zero dependencies.
I’d like to slightly modify it by using Gemini models with Crush by Charm instead of Claude and Aider and in general making it as simple as possible with a Julia focus. This is a new setup for me, so I don’t have much code to share. I was also wondering whether MuxDisplay.jl by @goerz might work with it, or if it could be adapted to fit such a configuration. I don’t have much experience with serious coding in modal editors, however, I’d like to transition to such a workflow.

Not sure about the --quiet flag, however, you should be able to see the logs in Helix with :log-open.

@kousu and @goerz Guys, you don’t like it, if I may ask? I mean the workflow outlined in the repo I linked above. I guess, the lack of support for pane names or floating window names by Zellij is a major blocker? Are you recommending tmux? I have to admit that I also took a look at GitHub - Gaurav-Gosain/tuios: Terminal UI OS (Terminal Multiplexer) , however, I got a feeling that it is still in the early stage of a development cycle.

Ah! Thanks, this tip helps a lot!

Here’s a log from where I jammed it by pressing = too fast.

helix.log
2025-11-09T17:10:50.888 helix_lsp::transport [ERROR] julia err <- "[ Info: Downloading cache files...\n"
2025-11-09T17:10:50.998 helix_lsp::transport [ERROR] julia err <- "[ Info: Downloading cache files...\n"
2025-11-09T17:10:50.998 helix_lsp::transport [ERROR] julia err <- "[ Info: Downloading cache files...\n"
2025-11-09T17:10:50.998 helix_lsp::transport [ERROR] julia err <- "[ Info: Downloading cache files...\n"
2025-11-09T17:10:53.165 helix_lsp::transport [ERROR] julia err <- "[ Info: Downloading cache files...\n"
2025-11-09T17:10:53.165 helix_lsp::transport [ERROR] julia err <- "[ Info: Downloading cache files...\n"
2025-11-09T17:10:53.165 helix_lsp::transport [ERROR] julia err <- "[ Info: Downloading cache files...\n"
2025-11-09T17:10:53.168 helix_lsp::transport [ERROR] julia err <- "[ Info: Downloading cache files...\n"
2025-11-09T17:10:53.169 helix_lsp::transport [ERROR] julia err <- "[ Info: Downloading cache files...\n"
2025-11-09T17:10:53.171 helix_lsp::transport [ERROR] julia err <- "[ Info: Downloading cache files...\n"
2025-11-09T17:10:53.171 helix_lsp::transport [ERROR] julia err <- "[ Info: Downloading cache files...\n"
2025-11-09T17:10:53.172 helix_lsp::transport [ERROR] julia err <- "[ Info: Downloading cache files...\n"
2025-11-09T17:10:53.173 helix_lsp::transport [ERROR] julia err <- "[ Info: Downloading cache files...\n"
2025-11-09T17:10:53.176 helix_lsp::transport [ERROR] julia err <- "[ Info: Downloading cache files...\n"
2025-11-09T17:10:53.176 helix_lsp::transport [ERROR] julia err <- "[ Info: Downloading cache files...\n"
2025-11-09T17:10:53.177 helix_lsp::transport [ERROR] julia err <- "[ Info: Downloading cache files...\n"
2025-11-09T17:10:53.182 helix_lsp::transport [ERROR] julia err <- "[ Info: Downloading cache files...\n"
2025-11-09T17:10:53.184 helix_lsp::transport [ERROR] julia err <- "[ Info: Downloading cache files...\n"
2025-11-09T17:10:53.188 helix_lsp::transport [ERROR] julia err <- "[ Info: Downloading cache files...\n"
2025-11-09T17:10:53.188 helix_lsp::transport [ERROR] julia err <- "[ Info: Downloading cache files...\n"
2025-11-09T17:10:53.189 helix_lsp::transport [ERROR] julia err <- "[ Info: Downloading cache files...\n"
2025-11-09T17:10:53.196 helix_lsp::transport [ERROR] julia err <- "[ Info: Downloading cache files...\n"
2025-11-09T17:10:53.196 helix_lsp::transport [ERROR] julia err <- "[ Info: Downloading cache files...\n"
2025-11-09T17:10:53.196 helix_lsp::transport [ERROR] julia err <- "[ Info: Downloading cache files...\n"
2025-11-09T17:10:53.199 helix_lsp::transport [ERROR] julia err <- "[ Info: Downloading cache files...\n"
2025-11-09T17:10:53.199 helix_lsp::transport [ERROR] julia err <- "[ Info: Downloading cache files...\n"
2025-11-09T17:10:53.200 helix_lsp::transport [ERROR] julia err <- "[ Info: Downloading cache files...\n"
2025-11-09T17:10:53.201 helix_lsp::transport [ERROR] julia err <- "[ Info: Downloading cache files...\n"
2025-11-09T17:10:53.202 helix_lsp::transport [ERROR] julia err <- "[ Info: Downloading cache files...\n"
2025-11-09T17:10:53.202 helix_lsp::transport [ERROR] julia err <- "[ Info: Downloading cache files...\n"
2025-11-09T17:10:53.204 helix_lsp::transport [ERROR] julia err <- "[ Info: Downloading cache files...\n"
2025-11-09T17:10:53.207 helix_lsp::transport [ERROR] julia err <- "[ Info: Downloading cache files...\n"
2025-11-09T17:10:53.209 helix_lsp::transport [ERROR] julia err <- "[ Info: Downloading cache files...\n"
2025-11-09T17:10:53.210 helix_lsp::transport [ERROR] julia err <- "[ Info: Downloading cache files...\n"
2025-11-09T17:10:53.210 helix_lsp::transport [ERROR] julia err <- "[ Info: Downloading cache files...\n"
2025-11-09T17:10:53.212 helix_lsp::transport [ERROR] julia err <- "[ Info: Downloading cache files...\n"
2025-11-09T17:10:53.212 helix_lsp::transport [ERROR] julia err <- "[ Info: Downloading cache files...\n"
2025-11-09T17:10:53.212 helix_lsp::transport [ERROR] julia err <- "[ Info: Downloading cache files...\n"
2025-11-09T17:10:53.219 helix_lsp::transport [ERROR] julia err <- "[ Info: Downloading cache files...\n"
2025-11-09T17:10:53.221 helix_lsp::transport [ERROR] julia err <- "[ Info: Downloading cache files...\n"
2025-11-09T17:10:53.221 helix_lsp::transport [ERROR] julia err <- "[ Info: Downloading cache files...\n"
2025-11-09T17:10:53.224 helix_lsp::transport [ERROR] julia err <- "[ Info: Downloading cache files...\n"
2025-11-09T17:10:53.225 helix_lsp::transport [ERROR] julia err <- "[ Info: Downloading cache files...\n"
2025-11-09T17:10:53.225 helix_lsp::transport [ERROR] julia err <- "[ Info: Downloading cache files...\n"
2025-11-09T17:10:53.226 helix_lsp::transport [ERROR] julia err <- "[ Info: Downloading cache files...\n"
2025-11-09T17:10:53.226 helix_lsp::transport [ERROR] julia err <- "[ Info: Downloading cache files...\n"
2025-11-09T17:10:53.227 helix_lsp::transport [ERROR] julia err <- "[ Info: Downloading cache files...\n"
2025-11-09T17:10:53.229 helix_lsp::transport [ERROR] julia err <- "[ Info: Downloading cache files...\n"
2025-11-09T17:10:53.232 helix_lsp::transport [ERROR] julia err <- "[ Info: Downloading cache files...\n"
2025-11-09T17:10:53.233 helix_lsp::transport [ERROR] julia err <- "[ Info: Downloading cache files...\n"
2025-11-09T17:10:53.234 helix_lsp::transport [ERROR] julia err <- "[ Info: Downloading cache files...\n"
2025-11-09T17:10:53.237 helix_lsp::transport [ERROR] julia err <- "[ Info: Downloading cache files...\n"
2025-11-09T17:10:53.239 helix_lsp::transport [ERROR] julia err <- "[ Info: Downloading cache files...\n"
2025-11-09T17:10:53.239 helix_lsp::transport [ERROR] julia err <- "[ Info: Downloading cache files...\n"
2025-11-09T17:10:53.241 helix_lsp::transport [ERROR] julia err <- "[ Info: Downloading cache files...\n"
2025-11-09T17:10:53.241 helix_lsp::transport [ERROR] julia err <- "[ Info: Downloading cache files...\n"
2025-11-09T17:10:53.242 helix_lsp::transport [ERROR] julia err <- "[ Info: Downloading cache files...\n"
2025-11-09T17:10:53.243 helix_lsp::transport [ERROR] julia err <- "[ Info: Downloading cache files...\n"
2025-11-09T17:10:53.246 helix_lsp::transport [ERROR] julia err <- "[ Info: Downloading cache files...\n"
2025-11-09T17:10:53.247 helix_lsp::transport [ERROR] julia err <- "[ Info: Downloading cache files...\n"
2025-11-09T17:10:53.248 helix_lsp::transport [ERROR] julia err <- "[ Info: Downloading cache files...\n"
2025-11-09T17:10:53.249 helix_lsp::transport [ERROR] julia err <- "[ Info: Downloading cache files...\n"
2025-11-09T17:10:53.251 helix_lsp::transport [ERROR] julia err <- "[ Info: Downloading cache files...\n"
2025-11-09T17:10:53.252 helix_lsp::transport [ERROR] julia err <- "[ Info: Downloading cache files...\n"
2025-11-09T17:10:53.253 helix_lsp::transport [ERROR] julia err <- "[ Info: Downloading cache files...\n"
2025-11-09T17:10:53.256 helix_lsp::transport [ERROR] julia err <- "[ Info: Downloading cache files...\n"
2025-11-09T17:10:53.257 helix_lsp::transport [ERROR] julia err <- "[ Info: Downloading cache files...\n"
2025-11-09T17:10:53.257 helix_lsp::transport [ERROR] julia err <- "[ Info: Downloading cache files...\n"
2025-11-09T17:10:53.259 helix_lsp::transport [ERROR] julia err <- "[ Info: Downloading cache files...\n"
2025-11-09T17:10:53.261 helix_lsp::transport [ERROR] julia err <- "[ Info: Downloading cache files...\n"
2025-11-09T17:10:53.261 helix_lsp::transport [ERROR] julia err <- "[ Info: Downloading cache files...\n"
2025-11-09T17:10:53.261 helix_lsp::transport [ERROR] julia err <- "[ Info: Downloading cache files...\n"
2025-11-09T17:10:53.262 helix_lsp::transport [ERROR] julia err <- "[ Info: Downloading cache files...\n"
2025-11-09T17:10:53.264 helix_lsp::transport [ERROR] julia err <- "[ Info: Downloading cache files...\n"
2025-11-09T17:10:53.266 helix_lsp::transport [ERROR] julia err <- "[ Info: Downloading cache files...\n"
2025-11-09T17:10:53.268 helix_lsp::transport [ERROR] julia err <- "[ Info: Downloading cache files...\n"
2025-11-09T17:10:53.269 helix_lsp::transport [ERROR] julia err <- "[ Info: Downloading cache files...\n"
2025-11-09T17:10:53.271 helix_lsp::transport [ERROR] julia err <- "[ Info: Downloading cache files...\n"
2025-11-09T17:10:53.272 helix_lsp::transport [ERROR] julia err <- "[ Info: Downloading cache files...\n"
2025-11-09T17:10:53.272 helix_lsp::transport [ERROR] julia err <- "[ Info: Downloading cache files...\n"
2025-11-09T17:10:53.274 helix_lsp::transport [ERROR] julia err <- "[ Info: Downloading cache files...\n"
2025-11-09T17:10:53.274 helix_lsp::transport [ERROR] julia err <- "[ Info: Downloading cache files...\n"
2025-11-09T17:10:53.278 helix_lsp::transport [ERROR] julia err <- "[ Info: Downloading cache files...\n"
2025-11-09T17:10:53.279 helix_lsp::transport [ERROR] julia err <- "[ Info: Downloading cache files...\n"
2025-11-09T17:10:53.279 helix_lsp::transport [ERROR] julia err <- "[ Info: Downloading cache files...\n"
2025-11-09T17:10:53.280 helix_lsp::transport [ERROR] julia err <- "[ Info: Downloading cache files...\n"
2025-11-09T17:10:53.280 helix_lsp::transport [ERROR] julia err <- "[ Info: Downloading cache files...\n"
2025-11-09T17:10:53.281 helix_lsp::transport [ERROR] julia err <- "[ Info: Downloading cache files...\n"
2025-11-09T17:10:53.283 helix_lsp::transport [ERROR] julia err <- "[ Info: Downloading cache files...\n"
2025-11-09T17:10:53.283 helix_lsp::transport [ERROR] julia err <- "[ Info: Downloading cache files...\n"
2025-11-09T17:10:53.284 helix_lsp::transport [ERROR] julia err <- "[ Info: Downloading cache files...\n"
2025-11-09T17:10:53.284 helix_lsp::transport [ERROR] julia err <- "[ Info: Downloading cache files...\n"
2025-11-09T17:10:53.285 helix_lsp::transport [ERROR] julia err <- "[ Info: Downloading cache files...\n"
2025-11-09T17:10:53.286 helix_lsp::transport [ERROR] julia err <- "[ Info: Downloading cache files...\n"
2025-11-09T17:10:53.286 helix_lsp::transport [ERROR] julia err <- "[ Info: Downloading cache files...\n"
2025-11-09T17:10:53.289 helix_lsp::transport [ERROR] julia err <- "[ Info: Downloading cache files...\n"
2025-11-09T17:10:53.290 helix_lsp::transport [ERROR] julia err <- "[ Info: Downloading cache files...\n"
2025-11-09T17:10:53.291 helix_lsp::transport [ERROR] julia err <- "[ Info: Downloading cache files...\n"
2025-11-09T17:10:53.292 helix_lsp::transport [ERROR] julia err <- "[ Info: Downloading cache files...\n"
2025-11-09T17:10:53.292 helix_lsp::transport [ERROR] julia err <- "[ Info: Downloading cache files...\n"
2025-11-09T17:10:53.293 helix_lsp::transport [ERROR] julia err <- "[ Info: Downloading cache files...\n"
2025-11-09T17:10:55.331 helix_lsp::transport [ERROR] julia err <- "[ Info: Downloading cache files...\n"
2025-11-09T17:10:55.334 helix_lsp::transport [ERROR] julia err <- "[ Info: Downloading cache files...\n"
2025-11-09T17:10:55.335 helix_lsp::transport [ERROR] julia err <- "[ Info: Downloading cache files...\n"
2025-11-09T17:10:55.336 helix_lsp::transport [ERROR] julia err <- "[ Info: Downloading cache files...\n"
2025-11-09T17:10:55.336 helix_lsp::transport [ERROR] julia err <- "[ Info: Downloading cache files...\n"
2025-11-09T17:10:55.336 helix_lsp::transport [ERROR] julia err <- "[ Info: Downloading cache files...\n"
2025-11-09T17:10:55.340 helix_lsp::transport [ERROR] julia err <- "[ Info: Downloading cache files...\n"
2025-11-09T17:10:55.344 helix_lsp::transport [ERROR] julia err <- "[ Info: Downloading cache files...\n"
2025-11-09T17:10:55.344 helix_lsp::transport [ERROR] julia err <- "[ Info: Downloading cache files...\n"
2025-11-09T17:10:55.344 helix_lsp::transport [ERROR] julia err <- "[ Info: All cache files downloaded (took 4.5s).\n"
2025-11-09T17:10:59.430 helix_lsp::transport [ERROR] julia err <- "[ Info: Will cache package Distributions (31c24e10-a181-5473-b8eb-7969acd0382f)\n"
2025-11-09T17:10:59.451 helix_lsp::transport [ERROR] julia err <- "[ Info: Will cache package StatsPlots (f3b207a7-027a-5e70-b257-86293d7955fd)\n"
2025-11-09T17:10:59.451 helix_lsp::transport [ERROR] julia err <- "[ Info: Will cache package ProfileSVG (132c30aa-f267-4189-9183-c8a63c7e05e6)\n"
2025-11-09T17:10:59.451 helix_lsp::transport [ERROR] julia err <- "[ Info: Will cache package LanguageServer (2b0e0bc5-e4fd-59b4-8912-456d1b03d8d7)\n"
2025-11-09T17:10:59.452 helix_lsp::transport [ERROR] julia err <- "[ Info: Will cache package FlameGraphs (08572546-2f56-4bcf-ba4e-bab62c3a3f89)\n"
2025-11-09T17:10:59.452 helix_lsp::transport [ERROR] julia err <- "[ Info: Will cache package JuliaFormatter (98e50ef6-434e-11e9-1051-2b60c6c9e899)\n"
2025-11-09T17:10:59.452 helix_lsp::transport [ERROR] julia err <- "[ Info: Will cache package ImageIO (82e4d734-157c-48bb-816b-45c225c6df19)\n"
2025-11-09T17:10:59.452 helix_lsp::transport [ERROR] julia err <- "[ Info: Will cache package Plots (91a5bcdd-55d7-5caf-9e0b-520d859cae80)\n"
2025-11-09T17:10:59.452 helix_lsp::transport [ERROR] julia err <- "[ Info: Will cache package FileIO (5789e2e9-d7fb-5bc7-8068-2c6fae9b9549)\n"
2025-11-09T17:10:59.452 helix_lsp::transport [ERROR] julia err <- "[ Info: Will cache package ProfileView (c46f51b8-102a-5cf2-8d2c-8597cb0e0da7)\n"
2025-11-09T17:10:59.452 helix_lsp::transport [ERROR] julia err <- "[ Info: Will cache package SpecialFunctions (276daf66-3868-5448-9aa4-cd146d93841b)\n"
2025-11-09T17:10:59.633 helix_lsp::transport [ERROR] julia err <- "[ Info: Indexing Distributions...\n"
2025-11-09T17:11:00.388 helix_lsp::transport [ERROR] julia err <- "WARNING: Detected access to binding `LoadingBay.Distributions` in a world prior to its definition world.\n"
2025-11-09T17:11:00.388 helix_lsp::transport [ERROR] julia err <- "  Julia 1.12 has introduced more strict world age semantics for global bindings.\n"
2025-11-09T17:11:00.388 helix_lsp::transport [ERROR] julia err <- "  !!! This code may malfunction under Revise.\n"
2025-11-09T17:11:00.388 helix_lsp::transport [ERROR] julia err <- "  !!! This code will error in future versions of Julia.\n"
2025-11-09T17:11:00.388 helix_lsp::transport [ERROR] julia err <- "Hint: Add an appropriate `invokelatest` around the access to this binding.\n"
2025-11-09T17:11:00.388 helix_lsp::transport [ERROR] julia err <- "To make this warning an error, and hence obtain a stack trace, use `julia --depwarn=error`.\n"
2025-11-09T17:11:00.388 helix_lsp::transport [ERROR] julia err <- "[ Info: Indexing StatsPlots...\n"
2025-11-09T17:11:02.637 helix_lsp::transport [ERROR] julia err <- "WARNING: Detected access to binding `LoadingBay.StatsPlots` in a world prior to its definition world.\n"
2025-11-09T17:11:02.637 helix_lsp::transport [ERROR] julia err <- "  Julia 1.12 has introduced more strict world age semantics for global bindings.\n"
2025-11-09T17:11:02.637 helix_lsp::transport [ERROR] julia err <- "  !!! This code may malfunction under Revise.\n"
2025-11-09T17:11:02.637 helix_lsp::transport [ERROR] julia err <- "  !!! This code will error in future versions of Julia.\n"
2025-11-09T17:11:02.637 helix_lsp::transport [ERROR] julia err <- "Hint: Add an appropriate `invokelatest` around the access to this binding.\n"
2025-11-09T17:11:02.637 helix_lsp::transport [ERROR] julia err <- "To make this warning an error, and hence obtain a stack trace, use `julia --depwarn=error`.\n"
2025-11-09T17:11:02.637 helix_lsp::transport [ERROR] julia err <- "[ Info: Indexing ProfileSVG...\n"
2025-11-09T17:11:02.716 helix_lsp::transport [ERROR] julia err <- "WARNING: Detected access to binding `LoadingBay.ProfileSVG` in a world prior to its definition world.\n"
2025-11-09T17:11:02.716 helix_lsp::transport [ERROR] julia err <- "  Julia 1.12 has introduced more strict world age semantics for global bindings.\n"
2025-11-09T17:11:02.716 helix_lsp::transport [ERROR] julia err <- "  !!! This code may malfunction under Revise.\n"
2025-11-09T17:11:02.716 helix_lsp::transport [ERROR] julia err <- "  !!! This code will error in future versions of Julia.\n"
2025-11-09T17:11:02.716 helix_lsp::transport [ERROR] julia err <- "Hint: Add an appropriate `invokelatest` around the access to this binding.\n"
2025-11-09T17:11:02.716 helix_lsp::transport [ERROR] julia err <- "To make this warning an error, and hence obtain a stack trace, use `julia --depwarn=error`.\n"
2025-11-09T17:11:02.717 helix_lsp::transport [ERROR] julia err <- "[ Info: Indexing LanguageServer...\n"
2025-11-09T17:11:03.317 helix_lsp::transport [ERROR] julia err <- "WARNING: Detected access to binding `LoadingBay.LanguageServer` in a world prior to its definition world.\n"
2025-11-09T17:11:03.317 helix_lsp::transport [ERROR] julia err <- "  Julia 1.12 has introduced more strict world age semantics for global bindings.\n"
2025-11-09T17:11:03.317 helix_lsp::transport [ERROR] julia err <- "  !!! This code may malfunction under Revise.\n"
2025-11-09T17:11:03.317 helix_lsp::transport [ERROR] julia err <- "  !!! This code will error in future versions of Julia.\n"
2025-11-09T17:11:03.317 helix_lsp::transport [ERROR] julia err <- "Hint: Add an appropriate `invokelatest` around the access to this binding.\n"
2025-11-09T17:11:03.317 helix_lsp::transport [ERROR] julia err <- "To make this warning an error, and hence obtain a stack trace, use `julia --depwarn=error`.\n"
2025-11-09T17:11:03.317 helix_lsp::transport [ERROR] julia err <- "[ Info: Processing FlameGraphs...\n"
2025-11-09T17:11:06.817 helix_lsp::transport [ERROR] julia err <- "ERROR: LoadError: UndefVarError: `FlameGraphs` not defined in `Main.SymbolServer.LoadingBay`\n"
2025-11-09T17:11:06.818 helix_lsp::transport [ERROR] julia err <- "The binding may be too new: running in world age 39213, while current world is 39423.\n"
2025-11-09T17:11:06.882 helix_lsp::transport [ERROR] julia err <- "Hint: FlameGraphs is loaded but not imported in the active module Main.\n"
2025-11-09T17:11:06.882 helix_lsp::transport [ERROR] julia err <- "Stacktrace:\n"
2025-11-09T17:11:06.882 helix_lsp::transport [ERROR] julia err <- " [1] load_package(c::Pkg.Types.Context, uuid::Base.UUID, conn::Base.PipeEndpoint, loadingbay::Module, percentage::Int64)\n"
2025-11-09T17:11:06.882 helix_lsp::transport [ERROR] julia err <- "   @ Main.SymbolServer ~/.julia/packages/SymbolServer/2jiVV/src/utils.jl:631\n"
2025-11-09T17:11:06.882 helix_lsp::transport [ERROR] julia err <- " [2] top-level scope\n"
2025-11-09T17:11:06.882 helix_lsp::transport [ERROR] julia err <- "   @ ~/.julia/packages/SymbolServer/2jiVV/src/server.jl:100\n"
2025-11-09T17:11:06.882 helix_lsp::transport [ERROR] julia err <- "in expression starting at /home/kousu/.julia/packages/SymbolServer/2jiVV/src/server.jl:1\n"
2025-11-09T17:11:46.289 helix_term::handlers::signature_help [ERROR] signature help request failed: request 1 timed out

I’m not sure though. Ive tried this a lot of times and the results are inconsistent. It says “downloading cache files” every time I start up helix, and interrupting it there seems to upset it, so that’s one obvious target for improvement, but I’ve also seen it jam before it ever prints that.

Your reply was very helpful I just didn’t have any solid results and I didn’t want to waste your time with guesses. I need to keep at it.

So far the separately compiled formatted is the most reliable. But that’s hard to deploy.

I’m not familiar Helix or Zellij. Personally, I’ve been very happy with (neo-)vim and tmux, which I’ve used for probably 15 years. I have no reason to look for other solutions.

I think I did look briefly at Zellij in the context of MuxDisplay, and got to the conclusion that “this doesn’t look very suitable” (but I don’t remember the details). Of course, if someone managed to get MuxDisplay to work with Zellij, or a future version of Zellij with more features, I’d be perfectly happy to accept PRs that document that workflow.

I see you are rather quite advanced! I managed to send the code between two panes today, but the cursor doesn’t automatically return to the editor! I’ll try to find a solution tomorrow! Moreover, I was hoping that with Helix I’d be able to operate almost entirely without a configuration file. However, I noticed today that there’s no built-in file manager, so I’m planning to integrate Yazi!

Thank you for the information. I’ll take another look at tmux. My hope was that with Zellij or TuiOS, this setup could be made more approachable. I was also considering extending it with Sway and nwg-drawer so that it runs inside WSL2, with the idea of eventually creating a Fedora Julia focused “Lab Edition” or “Spin”, however, all this is about details and is not so easy.

I corrected the code so the cursor returns to the editor. Yazi now works in sync with Helix, as does the AI completion, however I’m not sure how usable it is. I’m still not fully convinced about Zellij, but it seems much more approachable than tmux. I have no additional comments on MuxDisplay.jl at the moment. Like your reports, I can’t get LanguageServer.jl to work reliably with Helix, it sometimes works and sometimes doesn’t. I’ll be looking forward to a potential solution - hopefully one you can provide. In case of your interest in a similar setup to the one I outlined above, please let me know. :- )

:sweat_smile: I hope so too.

I guess you must be on Arch, btw. What scheduler are you using, if I may ask? Also, I’m wondering, how’s your Arch congestion control algorithm stack performing today? Are you experiencing similar issues as with the language server? Anyway, as I mentioned, I’ve also been running into problems with LanguageServer when using Helix and Crush. I’m currently on the latest stable Julia v1.12.1 and using LanguageServer v4.5.1 along with Runic v1.5.1. My setup looks like below. I decided to go with separate environments since I figured it would be easier to maintain. As for the other topics I mentioned in my previous posts, I have no updates. Happy to keep in touch.

cat languages.toml

# LanguageServer.jl [Install: julia --project=@languageserver --startup-file=no -e 'using Pkg; Pkg.add("LanguageServer")']
[[language]]
name = "julia"
language-servers = ["julia"]
scope = "source.julia"
injection-regex = "julia"
file-types = ["jl"]
roots = ["Project.toml", "Manifest.toml", "JuliaProject.toml"]
comment-token = "#"
indent = { tab-width = 4, unit = "    " }

[language-server.julia]
command = "julia"
args = [ "--project=@languageserver", "--startup-file=no", "--history-file=no", "-e", "using LanguageServer; runserver();"]
timeout = 60



# Runic.jl [Install: julia --project=@runic --startup-file=no -e 'using Pkg; Pkg.add("Runic")'
auto-format = false
formatter = { command = "julia" , args = ["--project=@runic", "--startup-file=no", "-e", "using Runic; exit(Runic.main(ARGS))"] }

I am :stuck_out_tongue:. I’m just using linux so uh, I don’t think I have a choice of scheduler. It’s fine most of the time. It’s really only if I hit 90% RAM usage that things start to lock up (though that’s easy to hit with Julia and VSCode and Zoom all going at once).

I upgraded to v4.5.1 yesterday and things are better now. I don’t know why but I was stuck on 4.1.0 and pkg> up wasn’t upgrading. Ahh, if this was all just because I had the wrong version I’m going to be sad.

My config is now back to basics:

$ cat ~/.config/helix/config.toml 
theme = "autumn_night"

[editor]
trim-final-newlines = true
trim-trailing-whitespace = true

$ cat ~/.config/helix/languages.toml 
[[language]]
# julia's formatter is expensive so disabled by default
name = "julia"
auto-format = true

$ julia --startup-file=no --quiet
(@v1.12) pkg> st
Status `~/.julia/environments/v1.12/Project.toml`
  [5903a43b] Infiltrator v1.9.4
  [2b0e0bc5] LanguageServer v4.5.1
  [efd6af41] ProfileCanvas v0.1.7

$ helix --version
helix 25.07.1

and here’s an example showing that the formatter kicks in all by itself. The compiled jlfmt isn’t needed. There is a lag at boot, but it’s about 15s, which you can see as the screen hangs in the middle after the first time I try to save, which is longer than jlfmt, but it’s tolerable.

fwiw, here’s

helix.log
2025-11-12T19:32:14.847 helix_lsp::transport [ERROR] julia err <- "[ Info: Package LanguageServer (2b0e0bc5-e4fd-59b4-8912-456d1b03d8d7) is cached.\n"
2025-11-12T19:32:14.866 helix_lsp::transport [ERROR] julia err <- "[ Info: Package ProfileCanvas (efd6af41-a80b-495e-886c-e51b0c7d77a3) is cached.\n"
2025-11-12T19:32:14.866 helix_lsp::transport [ERROR] julia err <- "[ Info: Package Infiltrator (5903a43b-9cc3-4c30-8d17-598619ec4e9b) is cached.\n"

‘=’ works too – again, with a hang at the first use, but it’s not nearly as bad as before

I tried = on a bigger project. There the lag is much worse: up to a minute still. I discovered that LS is pretty slow about indexing imports. I think that was probably making things worse for me, because I was constantly killing julia before LanguageServer could fully index and write its index to disk (I still don’t know where its cache is but it’s working so it is somewhere). I’ve made it better for myself by creating Project.toml one import at a time, and running Helix until I see the symbol index working and saved. It took ~25 minutes to go through all my deps and have it cache everything. The 1 minute it takes to reload all that cache is still kind of high but it’s at least usable, and when working on a real project where I have helix open for a day or more at a time, probably not that big a deal. Probably.


tl;dr:

  • Make sure you’re using the latest LanguageServer (v4.5.1 right now)
  • You shouldn’t have to configure ~/.config/helix/languages.toml, the defaults work
  • Make a toy script with no imports and no Project.toml; open it in Helix, mangle it a bit, and test :format and =. Expect them to lag out as Julia warms up, but be instant once the first formatting runs.
  • (Optionally) Make a toy project with a SINGLE import listed in a Project.toml with a SINGLE dependency.
    • Open this in Helix, make sure space+k can load the docs.

      Again, this will lag out as Julia warms up. actually first it give an error in the status bar, then it will lag out if you try again. But be patient and tail your logs (tail -f ~/.cache/helix/helix.log) and it should work.

      • Once space+k is able to load docs, your symbols should be cached, which means the LanguageServer shouldn’t take so long to start up.
      • Close Helix and reopen the file. Mangle it and try :format or =. It should lag while it reloads the symbol cache, but not as long as the first time.
      • Close and reopen and retest just to confirm it’s still quick to get it working.
      • Add another import. Close and reopen. See if formatting lags again – it probably will.
      • Continue adding imports you want to use one by one until you have their caches all built up.

I would like to try to make a sysimage again like the wiki suggested now that I know where to look for logs. Hopefully I can get that minute of startup time down to a few seconds. And I might like to use a separate LanguageServer env like you did, @j_u to protect my tools from me experimenting. Though after seeing how touchy this all is I might stick with disabling the language server and defining formatter explicitly because that seems less fragile, and honestly I’m way more interested in formatting than code suggestions.


And yes, very happy to stay in touch about making workflows better!

I asked because I noticed that CachyOS, which is based on Arch, offers this kind of choice ( sched-ext Tutorial | CachyOS ). I was curious about how those schedulers might impact Julia’s performance, if at all, hence the question.

As for Helix (by the way, I’m on v25.07.1 a05c151b):

I once had a pretty neat NeoVim setup. However, I realized that I mostly preferred using Vim and VS Code, the former for its speed, and the latter for its usability. Recently, due to some other activities, I took a closer look at Helix again. I think that while it shares a lot of similarities with Vim, it’s also quite different in ways that matter, most notably, it has a much lower entry barrier.

I haven’t fully made up my mind yet. Testing different configurations takes a lot of time, especially when things are new. For me, the Language Server experience feels quite different compared to VS Code. I’ve also encountered some issues with the system clipboard when running Helix inside a Zellij pane. I’m still unsure about AI completions as well. However, overall, I think I’ll stick with Helix for now.

1 Like