Editors
Emacs
Eglot and lsp-mode both give JavaScript buffers typescript-language-server by
default, and it reads a Flow file as TypeScript. uf.el makes uf
the server for a uf project's buffers and leaves every other project with the
server it would have had.
What you will be able to do: edit a uf project in Emacs with uf's diagnostics, hover, definitions, completion, code actions and formatting.
What you need first: uf installed, a project with a
uf.config.js, and Emacs 29 or later (Eglot is built in), or lsp-mode.
1. Load uf.el
uf editor install emacs writes uf.el to ~/.local/share/uf/editors/emacs
and prints the load-path line. uf.el is also in a uf checkout:
(add-to-list 'load-path "/path/to/uf/editors/emacs")
(require 'uf)
(setq uf-format-on-save t) ; optional
(add-hook 'js-mode-hook #'uf-eglot-ensure) ; Eglot: start it in uf projects
(add-hook 'js-ts-mode-hook #'uf-eglot-ensure)
uf.el makes a
directory with uf.config.js a project.el project. That project root is where
Eglot starts the server, and the command names it again with --cwd.
2. How the TypeScript server stays off
- Eglot.
uf.elputs its entry first ineglot-server-programs. Its contact function answersuf lspin a uf project. Anywhere else it answers with whatever the rest ofeglot-server-programsgives the buffer's mode: typescript-language-server on Emacs 30, and on Emacs 31 therass tsalternative it tries first. A TypeScript project therefore keeps its server. - lsp-mode.
uf.elregisters a client,uf, at priority 1, whose activation function accepts a buffer only in a uf project. lsp-mode starts the highest-priority client that accepts a buffer, andts-lsis -2, so a uf project gets uf and every other project is unchanged.
To say it per project for lsp-mode as well, commit a .dir-locals.el
(uf editor setup emacs writes it when the project has none).
lsp-disabled-clients is marked safe as a directory-local variable, so Emacs
applies it without asking:
((js-mode . ((lsp-disabled-clients . (ts-ls jsts-ls tsgo deno-ls))))
(js-ts-mode . ((lsp-disabled-clients . (ts-ls jsts-ls tsgo deno-ls)))))
Setting eglot-server-programs from .dir-locals.el also works, but it is not
marked safe, so Emacs asks every time. uf.el's contact function makes that
unnecessary.
Check that it worked
M-x eglot-events-buffer (or M-x lsp-describe-session) shows uf for a
Flow buffer. M-x flymake-show-buffer-diagnostics lists uf and flow
entries. M-x eglot-format-buffer, then uf fmt --check in a terminal: they
agree when the server read the project's uf.config.js. After editing
uf.config.js, M-x eglot-reconnect (or M-x lsp-workspace-restart).
Checked against
Eglot's defaults and lsp-mode's client ids, priorities and
lsp-disabled-clients were read from eglot.el (emacs-30 and master) and
lsp-mode's source in September 2026. The Editors workflow byte-compiles
uf.el with warnings as errors and runs its ERT tests in batch Emacs. Those
tests cover the project root, the command, the fallback to another server
outside a uf project, and lsp-mode's activation. Eglot and lsp-mode themselves
are not started by the tests.
Edit this pagedocs/app/guide/editors/emacs/$page.mdx