Verifying tsgo LSP server launch environment

/home/jm/.config/nvim · 22 messages · 86 parts · · 5,550 tokens
Created Feb 24, 06:51:54 PM · Updated Feb 24, 08:34:29 PM · 51 syncs
userFeb 24, 06:51:54 PM

How can I verify that the tsgo lsp will launch the correct tsgo lsp server, that should be in the current projects environment (either bun, npm, pnpm..)

assistantFeb 24, 06:51:54 PM
claude-opus-4-6 · anthropic

Good question. Let me look at how the tsgo LSP is currently configured in your Neovim setup to understand the current behavior, then I can advise on verification.

batchcompleted
Batch execution (1/2 successful)
Output
Executed 1/2 tools successfully. 1 failed.
grepcompleted
tsgo
Output
Found 5 matches
/home/jm/.config/nvim/lsp/tsgo.lua:
  Line 7: --- `tsgo` can be installed via npm `npm install @typescript/native-preview`.
  Line 11: --- `tsgo` supports monorepos by default. It will automatically find the `tsconfig.json` or `jsconfig.json` corresponding to the package you are working on.
  Line 12: --- This works without the need of spawning multiple instances of `tsgo`, saving memory.
  Line 20:     local cmd = 'tsgo'
  Line 21:     local local_cmd = (config or {}).root_dir and config.root_dir .. '/node_modules/.bin/tsgo'
readerror
File not found: /home/jm/.config/nvim/lua/config/lsp.lua Did you mean one of these? /home/jm/.config/nvim/lua/config/lsp
2in / 166out
assistantFeb 24, 06:52:00 PM
claude-opus-4-6 · anthropic
batchcompleted
Batch execution (2/2 successful)
Output
All 2 tools executed successfully.

Keep using the batch tool for optimal performance in your next response!
readcompleted
lsp/tsgo.lua
Output
<path>/home/jm/.config/nvim/lsp/tsgo.lua</path>
<type>file</type>
<content>1: ---@brief
2: ---
3: --- https://github.com/microsoft/typescript-go
4: ---
5: --- `typescript-go` is experimental port of the TypeScript compiler (tsc) and language server (tsserver) to the Go programming language.
6: ---
7: --- `tsgo` can be installed via npm `npm install @typescript/native-preview`.
8: ---
9: --- ### Monorepo support
10: ---
11: --- `tsgo` supports monorepos by default. It will automatically find the `tsconfig.json` or `jsconfig.json` corresponding to the package you are working on.
12: --- This works without the need of spawning multiple instances of `tsgo`, saving memory.
13: ---
14: --- It is recommended to use the same version of TypeScript in all packages, and therefore have it available in your workspace root. The location of the TypeScript binary will be determined automatically, but only once.
15: ---
16: 
17: ---@type vim.lsp.Config
18: return {
19:   cmd = function(dispatchers, config)
20:     local cmd = 'tsgo'
21:     local local_cmd = (config or {}).root_dir and config.root_dir .. '/node_modules/.bin/tsgo'
22:     if local_cmd and vim.fn.executable(local_cmd) == 1 then
23:       cmd = local_cmd
24:     end
25:     return vim.lsp.rpc.start({ cmd, '--lsp', '--stdio' }, dispatchers)
26:   end,
27:   filetypes = {
28:     'javascript',
29:     'javascriptreact',
30:     'typescript',
31:     'typescriptreact',
32:   },
33: 
34:   root_dir = function(bufnr, on_dir)
35:     -- The project root is where the LSP can be started from
36:     -- As stated in the documentation above, this LSP supports monorepos and simple projects.
37:     -- We select then from the project root, which is identified by the presence of a package
38:     -- manager lock file.
39:     local root_markers =
40:       { 'package-lock.json', 'yarn.lock', 'pnpm-lock.yaml', 'bun.lockb', 'bun.lock' }
41:     -- Give the root markers equal priority by wrapping them in a table
42:     root_markers =...
readcompleted
lua/config/lsp
Output
<path>/home/jm/.config/nvim/lua/config/lsp</path>
<type>directory</type>
<entries>
completion_prioritizer.lua
workspace_enhancer.lua

(2 entries)
</entries>
1in / 122out
assistantFeb 24, 06:52:02 PM
claude-opus-4-6 · anthropic

Here's what your current lsp/tsgo.lua does and how you can verify it:

Current behavior (lines 19-25)

The cmd function resolves the binary in this order:

  1. Local project binary: <root_dir>/node_modules/.bin/tsgo — used if it exists and is executable.
  2. Global fallback: bare tsgo from $PATH.

How to verify which binary launches

There are several approaches, from quick to thorough:

1. Check from within Neovim (quickest)

Open a TypeScript file in your project, then run:

:lua print(vim.inspect(vim.lsp.get_clients({ name = 'tsgo' })[1].config.cmd))

However, since cmd is a function (not a table), the config won't show the resolved path directly. Instead, check the running process:

:!ps aux | grep tsgo

This will show the exact binary path that was spawned.

2. Check the LSP log

:lua vim.cmd('edit ' .. vim.lsp.get_log_path())

Search for tsgo — the log should show the command that was started.

3. Pre-flight check in a project directory

From a terminal inside your project root, verify what node_modules/.bin/tsgo resolves to:

# Does the local binary exist?
ls -la node_modules/.bin/tsgo

# What version is it?
node_modules/.bin/tsgo --version

# What would the bare command resolve to?
which tsgo

The limitation you should be aware of

Your current config only checks node_modules/.bin/tsgo — this works for npm and pnpm (which both create node_modules/.bin/ shims). However:

  • Bun also uses node_modules/.bin/, so it should work.
  • pnpm with shamefully-hoist=false or strict mode may not always have the binary there if it's a transitive dependency.

The config does not use the package manager's own exec command (e.g., npx tsgo, bunx tsgo, pnpm exec tsgo). It relies purely on the node_modules/.bin/ shim existing at the root. For most setups this is fine, but if you want to be more robust, you could detect the package manager and use its exec wrapper instead.

Would you like me to plan an enhancement that detects the active package manager and uses the appropriate exec command, or is the current node_modules/.bin/ check sufficient for your workflow?

1in / 639out
userFeb 24, 06:59:46 PM

So in tsgo's lsp.ClientConfig, cmd is a function that takes in a clientConfig to use its root_dir, but root_dir could also be a function, as in this case.

What would the lua do in the case that root_dir is an unresolved function? Why does the type inference of lua also just assume it will be a string, when it could be that OR a function

assistantFeb 24, 06:59:46 PM
claude-opus-4-6 · anthropic

Great observation. Let me look at exactly how the cmd function receives its config argument and what root_dir would be at that point.

codesearchcompleted
Code search: neovim vim.lsp.Config cmd function signature dispatchers config parameter
Output
## News - Neovim docs
https://neovim.io/doc/user/news.html

exrc".
### EXPERIMENTS
todo
### LSP vim.lsp.buf.selection\_range() now accepts an integer which specifies its direction, rather than a string `'outer'` or `'inner'`.
### OPTIONS `'completefuzzycollect'` and `'isexpand'` have been removed.
### TREESITTER
todo
### UI ... was implemented as an internal C routine).
 'statusline' includes vim.diagnostic.status() Project-local configuration ( 'exrc' ) is also loaded from parent directories. Unset 'exrc' to stop further search.
Mappings: grt in Normal mode maps to vim.lsp.buf.type\_definition() 'shada' default now excludes "/tmp/" and "/private/" paths to reduce clutter in :oldfiles . ... hl-PmenuBorder hl-PmenuShadow hl-PmenuShadowThrough see 'pumborder' . ### LSP
 :lsp can be used to interactively manage LSP clients. vim.lsp.ClientConfig gained `workspace\_required`. You can control the priority of vim.lsp.Config `root\_markers`. Support for `textDocument/documentColor`: lsp-document\_color ... The `textDocument/diagnostic` request now includes the previous id in its
parameters. vim.lsp.enable() start/stops clients as necessary and detaches
non-applicable LSP clients. vim.lsp.is\_enabled() checks if a LSP config is enabled (without
"resolving" it). Support for `workspace/diagnostic`: vim.lsp.buf.workspace\_diagnostics() ... Incremental selection is now supported via `textDocument/selectionRange`. `an` selects outwards and `in` selects inwards.
Support for multiline semantic tokens. Support for the `disabled` field on code actions. The function form of `cmd` in a vim.lsp.Config or vim.lsp.ClientConfig receives the resolved config as the second arg: `cmd(dispatchers, config)`.
Support for annotated text edits. `:checkhealth vim.lsp` is now available to check which buffers the active LSP features are attached to. LSP `DiagnosticRelatedInformation` is now shown in vim.diagnostic.open\_float() . It is read from the LSP diagnostic object
stored in the `user\_data` fie...
grepcompleted
vim\.lsp\.Config
Output
Found 11 matches
/home/jm/.config/nvim/lsp/tsgo.lua:
  Line 17: ---@type vim.lsp.Config

/home/jm/.config/nvim/lsp/ocamllsp.lua:
  Line 32: ---@type vim.lsp.Config

/home/jm/.config/nvim/lsp/bashls.lua:
  Line 2: ---@type vim.lsp.Config

/home/jm/.config/nvim/lsp/clangd.lua:
  Line 66: ---@type vim.lsp.Config

/home/jm/.config/nvim/lsp/ts_ls.lua:
  Line 112: ---@type vim.lsp.Config

/home/jm/.config/nvim/lsp/copilot.lua:
  Line 75: ---@type vim.lsp.Config

/home/jm/.config/nvim/lsp/biome.lua:
  Line 39: ---@type vim.lsp.Config

/home/jm/.config/nvim/lsp/astro.lua:
  Line 16: ---@type vim.lsp.Config

/home/jm/.config/nvim/lua/lsp/resolver.lua:
  Line 119: -- --- Create a cmd resolver function for vim.lsp.Config
  Line 120: -- --- This function is passed directly to the `cmd` field of vim.lsp.Config

/home/jm/.config/nvim/lsp/rust_analyzer.lua:
  Line 55: ---@type vim.lsp.Config
2in / 195out
assistantFeb 24, 06:59:52 PM
claude-opus-4-6 · anthropic

Now let me look at the Neovim source to understand exactly what the cmd function receives as its second argument — specifically whether root_dir is already resolved to a string by the time cmd is called.

batchcompleted
Batch execution (2/2 successful)
Output
All 2 tools executed successfully.

Keep using the batch tool for optimal performance in your next response!
readcompleted
lua/lsp/resolver.lua
Output
<path>/home/jm/.config/nvim/lua/lsp/resolver.lua</path>
<type>file</type>
<content>1: --- Binary Resolution System for LSP Servers
2: --- Provides flexible binary discovery with conditional fallback mechanisms
3: -- local M = {}
4: --
5: -- --- Mapping of LSP names to Mason package names
6: -- --- @type table<string, string>
7: -- local mason_name_map = {
8: --   ts_ls = "typescript-language-server",
9: --   eslint = "eslint-language-server",
10: --   lua_ls = "lua-language-server",
11: --   ocamllsp = "ocaml-lsp",
12: --   jsonls = "vscode-json-language-server",
13: --   html = "vscode-html-language-server",
14: --   cssls = "vscode-css-language-server",
15: --   marksman = "marksman",
16: --   tailwindcss = "tailwindcss-language-server",
17: --   emmet_ls = "emmet-ls",
18: --   bashls = "bash-language-server",
19: --   yamlls = "yaml-language-server",
20: -- }
21: --
22: -- local function get_mason_package(lsp_name)
23: --   return mason_name_map[lsp_name] or lsp_name
24: -- end
25: --
26: -- --- Check if a command array is executable
27: -- --- @param cmd string[]
28: -- --- @return boolean
29: -- local function is_executable(cmd)
30: --   if #cmd == 0 then
31: --     return false
32: --   end
33: --   return vim.fn.executable(cmd[1]) == 1
34: -- end
35: --
36: -- --- Try Mason installation path
37: -- --- @param mason_package string
38: -- --- @return string[]|nil cmd The Mason command array, or nil if not found
39: -- local function try_mason(mason_package)
40: --   local mason_bin = vim.fn.stdpath("data") .. "/mason/bin/" .. mason_package
41: --   if vim.fn.executable(mason_bin) == 1 then
42: --     return { mason_bin }
43: --   end
44: --   return nil
45: -- end
46: --
47: -- --- Try PATH for binary
48: -- --- @param binary_name string
49: -- --- @return string[]|nil cmd The PATH command array, or nil if not found
50: -- local function try_path(binary_name)
51: --   if vim.fn.executable(binary_name) == 1 then
52: --     return { binary_name }
53: --   end
54:...
codesearchcompleted
Code search: neovim vim.lsp.Client.lua cmd function dispatchers resolved config root_dir
Output
## on_new_config for vim.lsp.config · Issue #32287 - GitHub
https://github.com/neovim/neovim/issues/32287?timeline_page=1

LSP: on\_new\_config for vim.lsp.config ·Issue #32287 ·neovim/neovim ·GitHub
 Skip to content ## Navigation Menu
Toggle navigation
 
 Sign in 
Appearance settings
Search or jump to... # Search code, repositories, users, issues, pull requests...
 
Search
Clear
 Search syntax tips # Provide feedback
 
We read every piece of feedback, and take your input very seriously. ... Sign up 
Appearance settings
Resetting focus You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to ... {{ message }}
 neovim /** neovim **Public
* ### Uh oh! ... * Notifications You must be signed in to change notification settings
* Fork6.5k * Star95.6k 
# LSP: on\_new\_config for vim.lsp.config#32287
 New issue 
Copy link New issue 
Copy link
Open
 Enhancement 
Open LSP: on\_new\_config for vim.lsp.config #32287
Enhancement
Copy link
Labels
 lsp 
Milestone
 
0.12 
 @justinmk 
## Description
 @justinmk justinmk 
opened onFeb 1, 2025 
Issue body actions
### Problem nvim-lspconfig has a`on\_new\_config`feature which is apparently not addressed by vim.lsp.config. The documentation for`on\_new\_config`is: > > Function executed after a root directory is detected. Used to modify the server configuration (including `> cmd `> itself).
> ### Expected behavior
ref neovim/nvim-lspconfig#3597 (comment) > > This could be another application for an autocmd that triggers just before the client starts. Or maybe could just be done in RTP. > Edit: maybe`root\_dir()`is already flexible enough?
## Metadata
## Metadata
### Assignees
No one assigned
### Labels lsp 
### Type
 Enhancement 
### Projects
No projects
### Milestone
* 
0.12
 ###

## Lsp - Neovim docs
https://neovim.io/doc/user/lsp.html

/doc/user/lsp/

## neovim/runtime/lua/vim/lsp.lua at mast...
1in / 185out
assistantFeb 24, 07:00:00 PM
claude-opus-4-6 · anthropic

Now let me look at the actual Neovim runtime source to see exactly how cmd is called and what the config argument contains — specifically whether root_dir is resolved before being passed:

taskcompleted
Explore Neovim LSP Client.lua
Output
task_id: ses_36efa0554ffe1VO5wOAVuxkGFE (for resuming to continue this task if needed)

<task_result>
Now I have all the source code needed. Let me compile the complete analysis.

---

## Complete Analysis: How Neovim LSP Calls `cmd` as a Function and the State of `root_dir`

### 1. The Exact Code Where `cmd` Function Is Called

In **`client.lua`** (`runtime/lua/vim/lsp/client.lua`), inside `Client.create()`:

```lua
  -- Start the RPC client.
  local config_cmd = config.cmd
  if type(config_cmd) == 'function' then
    self.rpc = config_cmd(dispatchers, config)
  else
    self.rpc = lsp.rpc.start(config_cmd, dispatchers, {
      cwd = config.cmd_cwd,
      env = config.cmd_env,
      detached = config.detached,
    })
  end
```

The signature is exactly `cmd(dispatchers, config)` where `config` is the **entire `vim.lsp.ClientConfig`** object that was passed to `Client.create()`.

### 2. The Code That Resolves `root_dir` from Function to String

In **`lsp.lua`** (`runtime/lua/vim/lsp.lua`), inside `lsp_enable_callback()`:

```lua
  for name in vim.spairs(lsp._enabled_configs) do
    local config = lsp.config[name]
    if config and can_start(bufnr, config, true) then
      -- Deepcopy config so changes done in the client
      -- do not propagate back to the enabled configs.
      config = vim.deepcopy(config)

      if type(config.root_dir) == 'function' then
        ---@param root_dir string
        config.root_dir(bufnr, function(root_dir)
          config.root_dir = root_dir        -- <-- RESOLVES HERE: replaces function with string
          vim.schedule(function()
            start_config(bufnr, config)
          end)
        end)
      else
        start_config(bufnr, config)
      end
    end
  end
```

When `root_dir` is a function, the code:
1. Calls `config.root_dir(bufnr, on_dir_callback)`
2. Inside the callback, **overwrites** `config.root_dir` with the string value
3. Then calls `start_config()` via `vim.schedule()`

### 3. The Full Pipeline: `vim.lsp.e...
1in / 583out
assistantFeb 24, 07:02:11 PM
claude-opus-4-6 · anthropic

This is a thorough answer. Here's the summary:

root_dir is always resolved to a string before cmd() is called

The two types tell the story:

Type root_dir type
vim.lsp.Config (user-facing) string | fun(bufnr, on_dir)
vim.lsp.ClientConfig (internal) string? — never a function

The cmd function signature is:

fun(dispatchers: vim.lsp.rpc.Dispatchers, config: vim.lsp.ClientConfig): vim.lsp.rpc.PublicClient

Note the second argument is vim.lsp.ClientConfig, not vim.lsp.Config. By the time cmd() receives it, the config has already been narrowed.

How Neovim resolves it

In runtime/lua/vim/lsp.lua, inside lsp_enable_callback():

if type(config.root_dir) == 'function' then
  config.root_dir(bufnr, function(root_dir)
    config.root_dir = root_dir  -- overwrites function with the string result
    vim.schedule(function()
      start_config(bufnr, config)  -- only proceeds AFTER resolution
    end)
  end)
else
  start_config(bufnr, config)
end

The pipeline is:

  1. vim.lsp.enable() triggers lsp_enable_callback() on FileType
  2. If root_dir is a function, it's called with (bufnr, on_dir_callback)
  3. The callback overwrites config.root_dir with the string
  4. Only then → start_config()vim.lsp.start()Client.create()cmd(dispatchers, config)

So your tsgo config is correct — by the time cmd(dispatchers, config) runs, config.root_dir is guaranteed to be a resolved string (or nil if on_dir was never called / called with nil).

Why the Lua type annotation doesn't complain

The cmd function's config parameter is typed as vim.lsp.ClientConfig where root_dir is string?. Lua's type system (via LuaLS annotations) trusts this contract. It doesn't track the runtime narrowing that happens in lsp_enable_callback() — it simply knows that by the time ClientConfig is constructed, the function form has already been eliminated. So the type inference is correct, not just an assumption.

To verify at runtime in your actual project

You could add a temporary assertion in your cmd function:

cmd = function(dispatchers, config)
    assert(type(config.root_dir) == 'string', 'root_dir was not resolved: ' .. type(config.root_dir))
    -- rest of your logic...
end

Or check the running process with :!ps aux | grep tsgo after opening a TS file.

1in / 757out
userFeb 24, 07:15:43 PM

q[ERROR][2026-02-24 14:14:44] /home/jm/.local/share/nvim/runtime/lua/vim/lsp/log.lua:151 "rpc" "/home/jm/data/code/opencode-trees/ChyTQ/node_modules/.bin/tsgo" "stderr" "context canceled\n"
[ERROR][2026-02-24 14:14:44] /home/jm/.local/share/nvim/runtime/lua/vim/lsp/log.lua:151 "error handling method 'exit': EOF"
[WARN][2026-02-24 14:14:44] /home/jm/.local/share/nvim/runtime/lua/vim/lsp/log.lua:151 "The language server tsgo triggers a registerCapa
bility handler for workspace/didChangeConfiguration despite dynamicRegistration set to false. Report upstream, this warning is harmless"

assistantFeb 24, 07:15:43 PM
claude-opus-4-6 · anthropic

The LSP log confirms the local binary is being resolved correctly — it's launching /home/jm/data/code/opencode-trees/ChyTQ/node_modules/.bin/tsgo.

The errors you're seeing are:

  1. "context canceled\n" on stderr — This is the tsgo process writing to stderr as it shuts down. This typically happens when Neovim closes the LSP client (e.g., you closed the buffer/window, or the client was stopped). The Go runtime's context cancellation propagates and gets logged. This is normal shutdown behavior, not a startup failure.

  2. "error handling method 'exit': EOF" — Neovim tried to handle the exit notification but the pipe was already closed. This is a race condition during shutdown — also harmless.

  3. registerCapability handler for workspace/didChangeConfiguration despite dynamicRegistration set to false — This is a known upstream tsgo issue. The server sends a capability registration that Neovim's client didn't advertise support for. The warning itself says it's harmless.

None of these indicate a problem with binary resolution. The correct project-local tsgo binary at node_modules/.bin/tsgo was found and launched.

Is there a specific problem you're experiencing with tsgo (crashes, missing features, not starting), or were you just verifying the binary resolution works?

2in / 326out
userFeb 24, 08:33:02 PM
  • tsgo (id: 9)
    • Version: 7.0.0-dev.20260224.1
    • Root directory: ~/data/code/opencode-trees/ChyTQ
    • Command: <function @/home/jm/.config/nvim/lsp/tsgo.lua:22>
    • Settings: {}
    • Attached buffers: 15, 109

Can you configure it so that the server has some settings configured that are available and of use, in tsgo version

It looks like there is just a tsgo.js in the installed package, how can I ensure bun

assistantFeb 24, 08:33:02 PM
claude-opus-4-6 · anthropic

Two separate questions here. Let me research both.

batchcompleted
Batch execution (2/2 successful)
Output
All 2 tools executed successfully.

Keep using the batch tool for optimal performance in your next response!
codesearchcompleted
Code search: tsgo typescript-go LSP server settings configuration options 2025 2026
Output
## How to Install and Configure TypeScript-Go (tsgo) as an LSP in Neovim | stephansama blog
https://blog.stephansama.info/articles/how-to-install-and-configure-typescript-go-as-an-lsp-in-neovim/

How to Install and Configure TypeScript-Go (tsgo) as an LSP in Neovim
 Banner Created:4/27/2025Updated:10/25/2025
2 min read -313 words
Tags: lsp typescript go neovim If you’re interested in using the blazing-fast TypeScript-Go (tsgo)** project as your TypeScript/JavaScript LSP inside Neovim, here’s a full guide to get you up and running. This guide assumes you’re using**Neovim 0.11+**which supports the new`lsp/`folder structure for lightweight LSP ... ## Step 3: Create a Neovim LSP Configuration for tsgo ** Next, create a new configuration file for`tsgo`under your Neovim config directory, using the new LSP structure:
``` `\~/.config/nvim/lsp/tsgo.lua`
```
(Adjust the path based on your Neovim setup.) ## Step 4: Add the tsgo LSP Setup Code ** 
Paste the following Lua code into your`lsp/tsgo.lua`file:
``` ... https://gist.github.com/kr-alt/24aaf4bad50d603c3c6a270502e57209localroot\_files={"tsconfig.base.json","tsconfig.json"," jsconfig.json","package.json",".git"}localpaths=vim.fs.find(root\_files, ... foundifroot\_dir==nilthenreturnend---@typevim.lsp.ConfiglocalM={}M.cmd={vim.env.HOME.."/Code/typescript-go/built/local/ tsgo","lsp","--stdio"}M.filetypes={"javascript","javascriptreact","typescript","typescriptreact"}M.root\_dir=root\_dirre ... ```
## Step 5: Enable the tsgo LSP in Your Neovim Config ** Wherever you load or configure your LSP servers (for example inside the`nvim-lspconfig`setup), you can now enable the tsgo LSP: ```
`vim.lsp.enable({"tsgo",-- other language servers})`
``` Or, if you’re using a plugin like`neovim/nvim-lspconfig`, you might hook it into your existing LSP setup logic. 
# Wrapping Up ** You should now have**TypeScript-Go**running inside Neovim, providing fast and efficient TypeScript and JavaScript ... * https://gist.github.com/kr-alt/24aaf4bad50d...
bashcompleted
Inspect tsgo bin shim content
Output
cat: /home/jm/data/code/opencode-trees/ChyTQ/node_modules/.bin/tsgo: No such file or directory
2in / 170out
assistantFeb 24, 08:33:10 PM
claude-opus-4-6 · anthropic
batchcompleted
Batch execution (4/4 successful)
Output
All 4 tools executed successfully.

Keep using the batch tool for optimal performance in your next response!
bashcompleted
Check tsgo binary and package structure
Output
NOT FOUND
native-preview NOT FOUND
bashcompleted
Check package.json for tsgo dep
bashcompleted
Check which lockfile exists
Output
ls: cannot access '/home/jm/data/code/opencode-trees/ChyTQ/bun.lockb': No such file or directory
ls: cannot access '/home/jm/data/code/opencode-trees/ChyTQ/bun.lock': No such file or directory
ls: cannot access '/home/jm/data/code/opencode-trees/ChyTQ/package-lock.json': No such file or directory
websearchcompleted
Web search: typescript-go tsgo LSP settings configuration workspace/configuration 2026
Output
MCP error -32602: Input validation error: Invalid arguments for tool web_search_exa: [
  {
    "received": "deep",
    "code": "invalid_enum_value",
    "options": [
      "auto",
      "fast"
    ],
    "path": [
      "type"
    ],
    "message": "Invalid enum value. Expected 'auto' | 'fast', received 'deep'"
  }
]
1in / 418out
assistantFeb 24, 08:33:17 PM
claude-opus-4-6 · anthropic

Interesting — that project directory seems to have been cleaned up since the earlier LSP log. Let me check the actual state and look into tsgo settings.

batchcompleted
Batch execution (3/3 successful)
Output
All 3 tools executed successfully.

Keep using the batch tool for optimal performance in your next response!
bashcompleted
List project directory contents
websearchcompleted
Web search: microsoft typescript-go tsgo LSP server settings configuration workspace didChangeConfiguration 2026
Output
Title: Installing Native Preview broke TS Imports · Issue #2555
Author: tikki100
Published Date: 2026-01-21T00:00:00.000Z
URL: https://github.com/microsoft/typescript-go/issues/2555
Text: # Issue: microsoft/typescript-go #2555

- Repository: microsoft/typescript-go | Staging repo for development of native port of TypeScript | 24K stars | Go

## Installing Native Preview broke TS Imports

- Author: [@tikki100] 
- State: open
- Labels: Domain: Editor
- Reactions: 👍 2
- Created: 2026-01-21T12:35:07Z
- Updated: 2026-02-03T07:25:59Z

### Extension Version

0.20260120.1

### VS Code Version

1.108.1 (Universal)

### Operating system Version

macOS tahoe 26.2

### Steps to reproduce

EDIT: I managed to get imports working with the old version of TypeScript again while testing below solutions. I'm not certain what changed, but the imports are still not working at all using Native.

---

1. I had a working environment with auto-imports and saw the hype around the Native Preview. I went to the Extensions store to install it (probably 1 month ago).

1. I enabled the Native Typescript extension in VS Code

1. I noticed that auto-imports were flaky- sometimes working and sometimes not.

1. I tried disabling the `tsgo` extension by using the

Title: Search code, repositories, users, issues, pull requests...
Author: lokeshrj
Published Date: 2025-12-03T00:00:00.000Z
URL: https://github.com/microsoft/typescript-go/issues/2205
Text: # Issue: microsoft/typescript-go #2205

- Repository: microsoft/typescript-go | Staging repo for development of native port of TypeScript | 24K stars | Go

## TSGO doesnt read vscode settings json

- Author: [@lokeshrj] 
- State: open
- Labels: Domain: Editor
- Created: 2025-12-03T22:41:25Z
- Updated: 2025-12-04T04:37:35Z

Type: Bug 

I have 
"typescript.preferences.importModuleSpecifier": "non-relative",
"typescript.updateImportsOnFileMove.enabled": "always",
in my vscode settings.json but it doesn't follow these.

Extension version: 0.20251203.1
VS Cod...
websearchcompleted
Web search: github microsoft typescript-go LSP settings initialization options tsgo server configuration
Output
Title: typescript-language-server/docs/configuration.md at master
URL: https://github.com/typescript-language-server/typescript-language-server/blob/master/docs/configuration.md
Text: typescript-language-server/docs/configuration.md at master ·typescript-language-server/typescript-language-server ·GitHub
[Skip to content] 
## Navigation Menu
Toggle navigation
[] 
[Sign in] 
Appearance settings
Search or jump to...
# Search code, repositories, users, issues, pull requests...
 
Search
Clear
[Search syntax tips] 
# Provide feedback
 
We read every piece of feedback, and take your input very seriously.
Include my email address so I can be contacted
CancelSubmit feedback
# Saved searches
## Use saved searches to filter your results more quickly
 
Name
Query
To see all available qualifiers, see our[documentation].
CancelCreate saved search
[Sign in] 
[Sign up] 
Appearance settings
Resetting focus
You signed in with another tab or window.[Reload] to refresh your session.You signed out in another tab or window.[Reload] to refresh your session.You switched accounts on another tab or window.[Reload] to refresh your session.Dismiss alert
{{ message }}
[typescript-language-server] /**[typescript-language-server] **Public
* [Notifications] Y

Title: typescript-go/internal/lsp/server.go at main
Published Date: 2026-01-31T00:00:00.000Z
URL: https://github.com/microsoft/typescript-go/blob/main/internal/lsp/server.go
Text: # File: microsoft/typescript-go/internal/lsp/server.go

- Repository: microsoft/typescript-go | Staging repo for development of native port of TypeScript | 24K stars | Go
- Branch: main

```go
package lsp

import (
	"context"
	"errors"
	"fmt"
	"io"
	"iter"
	"math/rand/v2"
	"runtime/debug"
	"slices"
	"strings"
	"sync"
	"sync/atomic"
	"time"

	"github.com/microsoft/typescript-go/internal/api"
	"github.com/microsoft/typescript-go/internal/collections"
	"github.com/microsoft/typescript-go/internal/core"
	"github.com/microsoft/typescript-go/internal/json"
	"github.com/...
1in / 221out
assistantFeb 24, 08:33:32 PM
claude-opus-4-6 · anthropic

Let me look at the actual tsgo LSP source to understand what settings it supports:

batchcompleted
Batch execution (2/2 successful)
Output
All 2 tools executed successfully.

Keep using the batch tool for optimal performance in your next response!
webfetchcompleted
https://github.com/microsoft/typescript-go/blob/main/internal/lsp/server.go (text/html; charset=utf-8)
Output
typescript-go/internal/lsp/server.go at main · microsoft/typescript-go · GitHub



  
  
  
  

    
  


  


    


  
  

  
  

    







  

  




    

  

    

    

      

      

    
    
    

      
  
  




      



        


  
  
  
  

  

      

    

  

  



    

    
  


  

  

  
  

  
  
  





  

  

  
    
      
      

    
      Skip to content

      
    
      
      
      


  
  






      

          

              

  Navigation Menu

  
    Toggle navigation
  

  
    
      
          
    
            
            
  

      

      
        
    

      

      
          
            Sign in
          
              
    
        
    

Appearance settings

      
        



  
  



      
    
  

      
    


    
      
            



  
  PlatformAI CODE CREATIONGitHub CopilotWrite better code with AIGitHub SparkBuild and deploy intelligent appsGitHub ModelsManage and compare promptsMCP RegistryNewIntegrate external toolsDEVELOPER WORKFLOWSActionsAutomate any workflowCodespacesInstant dev environmentsIssuesPlan and track workCode ReviewManage code changesAPPLICATION SECURITYGitHub Advanced SecurityFind and fix vulnerabilitiesCode securitySecure your code as you buildSecret protectionStop leaks before they startEXPLOREWhy GitHubDocumentationBlogChangelogMarketplaceView all featuresSolutionsBY COMPANY SIZEEnterprisesSmall and medium teamsStartupsNonprofitsBY USE CASEApp ModernizationDevSecOpsDevOpsCI/CDView all use casesBY INDUSTRYHealthcareFinancial servicesManufacturingGovernmentView all industriesView all solutionsResourcesEXPLORE BY TOPICAISoftware DevelopmentDevOpsSecurityView all topicsEXPLORE BY TYPECustomer storiesEvents &amp; webinarsEbooks &amp; reportsBusiness insightsGitHub SkillsSUPPORT &amp; SERVICESDocumentationCustomer supportCommunity forumTrust centerPartnersView all resourcesOpen SourceCOMMUNITYGitHub SponsorsFund open source developersPROGRAMSSecurity LabMaintainer CommunityAccele...
websearchcompleted
Web search: site:github.com/microsoft/typescript-go "workspace/didChangeConfiguration" OR "initializationOptions" OR "settings" internal lsp
Output
Title: Pyrefly LSP Does Not Apply Any Configuration From LSP Client ...
Author: Sandyeee0094
Published Date: 2025-11-20T00:00:00.000Z
URL: https://github.com/facebook/pyrefly/issues/1633
Text: # Issue: facebook/pyrefly #1633

- Repository: facebook/pyrefly | A fast type checker and language server for Python | 5K stars | Rust

## Pyrefly LSP Does Not Apply Any Configuration From LSP Client (settings/ initializationOptions)

- Author: [@Sandyeee0094] 
- State: closed (completed)
- Labels: language-server
- Assignees: [@kinto0] 
- Reactions: 👍 2
- Created: 2025-11-20T13:03:55Z
- Updated: 2025-11-26T17:02:36Z
- Closed: 2025-11-22T01:47:35Z
- Closed by: [@meta-codesync[bot]] 

### Describe the Bug

Pyrefly’s LSP server currently **ignores all configuration sent from the LSP client**, including:

- `settings`
- `initializationOptions`
- `workspace/didChangeConfiguration`

This means users cannot configure Pyrefly globally via Neovim, VSCode, or any other LSP client.
The only configuration source that actually affects behavior is **`[tool.pyrefly]` inside `pyproject.toml`**.

This prevents enabling diagnostics, strict mode, analyzer mode, or any other options globally.
Everything must be repeated inside every project.

---

# **Envir

Title: Send LSP `workspace/didChangeConfiguration` notification when reconfiguring `vim.lsp.config` · Issue #36673 · neovim/neovim
Author: saecki
Published Date: 2025-11-23T00:00:00.000Z
URL: https://github.com/neovim/neovim/issues/36673
Text: # Issue: neovim/neovim #36673

- Repository: neovim/neovim | Vim-fork focused on extensibility and usability | 97K stars | Vim Script

## Send LSP `workspace/didChangeConfiguration` notification when reconfiguring `vim.lsp.config`

- Author: [@saecki] 
- Association: CONTRIBUTOR
- State: open
- Labels: lsp
- Created: 2025-11-23T22:12:09Z
- Updated: 2025-11-28T08:50:58Z

### Problem

I'm not aware of a simple way to update the settings of an already running LSP server.

### Expected behavior

Sending a...
1in / 177out
assistantFeb 24, 08:33:38 PM
claude-opus-4-6 · anthropic
webfetchcompleted
https://raw.githubusercontent.com/microsoft/typescript-go/main/internal/lsp/server.go (text/plain; charset=utf-8)
Output
package lsp

import (
	"context"
	"errors"
	"fmt"
	"io"
	"iter"
	"math/rand/v2"
	"runtime/debug"
	"slices"
	"strings"
	"sync"
	"sync/atomic"
	"time"

	"github.com/microsoft/typescript-go/internal/api"
	"github.com/microsoft/typescript-go/internal/collections"
	"github.com/microsoft/typescript-go/internal/core"
	"github.com/microsoft/typescript-go/internal/json"
	"github.com/microsoft/typescript-go/internal/jsonrpc"
	"github.com/microsoft/typescript-go/internal/locale"
	"github.com/microsoft/typescript-go/internal/ls"
	"github.com/microsoft/typescript-go/internal/ls/lsconv"
	"github.com/microsoft/typescript-go/internal/ls/lsutil"
	"github.com/microsoft/typescript-go/internal/lsp/lsproto"
	"github.com/microsoft/typescript-go/internal/pprof"
	"github.com/microsoft/typescript-go/internal/project"
	"github.com/microsoft/typescript-go/internal/project/ata"
	"github.com/microsoft/typescript-go/internal/tspath"
	"github.com/microsoft/typescript-go/internal/vfs"
	"golang.org/x/sync/errgroup"
)

type ServerOptions struct {
	In  Reader
	Out Writer
	Err io.Writer

	Cwd                string
	FS                 vfs.FS
	DefaultLibraryPath string
	TypingsLocation    string
	ParseCache         *project.ParseCache
	NpmInstall         func(cwd string, args []string) ([]byte, error)
}

func NewServer(opts *ServerOptions) *Server {
	if opts.Cwd == "" {
		panic("Cwd is required")
	}

	s := &Server{
		r:                     opts.In,
		w:                     opts.Out,
		stderr:                opts.Err,
		requestQueue:          make(chan *lsproto.RequestMessage, 100),
		outgoingQueue:         make(chan *lsproto.Message, 100),
		pendingClientRequests: make(map[jsonrpc.ID]pendingClientRequest),
		pendingServerRequests: make(map[jsonrpc.ID]chan *lsproto.ResponseMessage),
		cwd:                   opts.Cwd,
		fs:                    opts.FS,
		defaultLibraryPath:    opts.DefaultLibraryPath,
		typingsLocation:       opts.TypingsLocation,
		parseCache:            opts.ParseCache,
		npmInstall:    ...
1in / 96out
assistantFeb 24, 08:33:42 PM
claude-opus-4-6 · anthropic

Now let me look at what configuration options tsgo actually accepts:

webfetcherror
Error: Request failed with status code: 404
1in / 114out
assistantFeb 24, 08:33:46 PM
claude-opus-4-6 · anthropic
batchcompleted
Batch execution (2/2 successful)
Output
All 2 tools executed successfully.

Keep using the batch tool for optimal performance in your next response!
websearchcompleted
Web search: site:github.com/microsoft/typescript-go "internal/ls/lsutil" userconfig OR user_config OR UserPreferences
Output
Title: Differences/issues with Code Lens references · Issue #2177 ...
Author: eamodio
URL: https://github.com/microsoft/typescript-go/issues/2177
Text: # Issue: microsoft/typescript-go #2177

- Repository: microsoft/typescript-go | Staging repo for development of native port of TypeScript | 24K stars | Go

## Differences/issues with Code Lens references

- Author: [@eamodio] 
- State: closed (completed)
- Labels: Domain: Editor
- Assignees: [@Copilot] 
- Reactions: 👀 1
- Created: 2025-12-02T16:57:06Z
- Updated: 2025-12-08T23:02:15Z
- Closed: 2025-12-08T23:02:15Z
- Closed by: [@sheetalkamat] 

### Extension Version

0.20251202.1

### VS Code Version

1.107.0-insider

### Operating system Version

Windows_NT x64 10.0.26220

### Steps to reproduce

1. Open https://github.com/gitkraken/vscode-gitlens/blob/cdf7cd3fc2f9246c10081b0b038b68328981d413/src/webviews/apps/home/home.ts#L61
2. And see that there are 70 references using TS, but 31 using TSGO

### Issue

Related to #2145
Seeing differences in the references between TS and TSGO

(Loving that this feature is back tho!)

---

### Timeline

**eamodio** added label `Domain: Editor` · Dec 2, 2025 at 4:57pm

**@DanielRosenwasser** commented · Dec 4, 2025 at 12:40am

> One reason this 

Title: typescript-go/internal/lsp/server.go at main · microsoft/typescript-go ...
URL: https://github.com/microsoft/typescript-go/blob/main/internal/lsp/server.go
Text: # File: microsoft/typescript-go/internal/lsp/server.go

- Repository: microsoft/typescript-go | Staging repo for development of native port of TypeScript | 24K stars | Go
- Branch: main

```go
package lsp

import (
	"context"
	"errors"
	"fmt"
	"io"
	"iter"
	"math/rand/v2"
	"runtime/debug"
	"slices"
	"strings"
	"sync"
	"sync/atomic"
	"time"

	"github.com/microsoft/typescript-go/internal/api"
	"github.com/microsoft/typescript-go/internal/collections"
	"github.com/microsoft/typescript-go/internal/core"
	"github.com/microsoft/typescript-go/internal/json"
	"github.com/microsoft/t...
webfetchcompleted
https://github.com/microsoft/typescript-go/tree/main/internal/ls/lsutil (text/html; charset=utf-8)
Output
typescript-go/internal/ls/lsutil at main · microsoft/typescript-go · GitHub



  
  
  
  

    
  


  


    


  
  

  
  

    







  

  




    

  

    

    

      

      

    
    
    

      
  
  




      



        


  
  
  
  

  

      

    

  

  



    

    
  


  

  

  
  

  
  
  





  

  

  
    
      
      

    
      Skip to content

      
    
      
      
      


  
  






      

          

              

  Navigation Menu

  
    Toggle navigation
  

  
    
      
          
    
            
            
  

      

      
        
    

      

      
          
            Sign in
          
              
    
        
    

Appearance settings

      
        



  
  



      
    
  

      
    


    
      
            



  
  PlatformAI CODE CREATIONGitHub CopilotWrite better code with AIGitHub SparkBuild and deploy intelligent appsGitHub ModelsManage and compare promptsMCP RegistryNewIntegrate external toolsDEVELOPER WORKFLOWSActionsAutomate any workflowCodespacesInstant dev environmentsIssuesPlan and track workCode ReviewManage code changesAPPLICATION SECURITYGitHub Advanced SecurityFind and fix vulnerabilitiesCode securitySecure your code as you buildSecret protectionStop leaks before they startEXPLOREWhy GitHubDocumentationBlogChangelogMarketplaceView all featuresSolutionsBY COMPANY SIZEEnterprisesSmall and medium teamsStartupsNonprofitsBY USE CASEApp ModernizationDevSecOpsDevOpsCI/CDView all use casesBY INDUSTRYHealthcareFinancial servicesManufacturingGovernmentView all industriesView all solutionsResourcesEXPLORE BY TOPICAISoftware DevelopmentDevOpsSecurityView all topicsEXPLORE BY TYPECustomer storiesEvents &amp; webinarsEbooks &amp; reportsBusiness insightsGitHub SkillsSUPPORT &amp; SERVICESDocumentationCustomer supportCommunity forumTrust centerPartnersView all resourcesOpen SourceCOMMUNITYGitHub SponsorsFund open source developersPROGRAMSSecurity LabMaintainer CommunityAccelerato...
1in / 155out
assistantFeb 24, 08:33:53 PM
claude-opus-4-6 · anthropic
webfetcherror
Error: Request failed with status code: 404
1in / 101out
assistantFeb 24, 08:33:56 PM
claude-opus-4-6 · anthropic
websearchcompleted
Web search: github.com/microsoft/typescript-go internal/ls/lsutil user_config.go OR userconfig.go UserPreferences ParseNewUserConfig
Output
Title: Auto-imports broken in JS files when user preferences are used #2598
Author: DanielRosenwasser
Published Date: 2026-01-27T00:00:00.000Z
URL: https://github.com/microsoft/typescript-go/issues/2598
Text: # Issue: microsoft/typescript-go #2598

- Repository: microsoft/typescript-go | Staging repo for development of native port of TypeScript | 24K stars | Go

## Auto-imports broken in JS files when user preferences are used

- Author: [@DanielRosenwasser] 
- Association: MEMBER
- State: closed (completed)
- Labels: Crash
- Assignees: [@iisaduan] 
- Reactions: 👍 1
- Created: 2026-01-28T01:55:56Z
- Updated: 2026-01-30T21:47:33Z
- Closed: 2026-01-30T21:47:33Z
- Closed by: [@iisaduan] 

I built tsgo with

```
hereby build --race
```

I ran the crawler with the race detector on VS Code and I got the following crash.

```
panic handling request completionItem/resolve: completion list needs auto imports
goroutine 2396 [running]:
runtime/debug.Stack()
        /usr/local/go/src/runtime/debug/stack.go:26 +0x68
github.com/microsoft/typescript-go/internal/lsp.(*Server).recover(0xc000269c08, {0xc0168f35d7?, 0xc0168f3628?}, 0xc013149e30)
        /workspaces/typescript-go/internal/lsp/server.go:776 +0x5d
panic({0x11f2040?, 0x1e995f0?})
   

Title: Search code, repositories, users, issues, pull requests...
Author: microsoft
Published Date: 2024-09-19T00:00:00.000Z
URL: https://github.com/microsoft/typescript-go/blob/main/cmd/tsgo/main.go
Text: # File: microsoft/typescript-go/cmd/tsgo/main.go

- Repository: microsoft/typescript-go | Staging repo for development of native port of TypeScript | 24K stars | Go
- Branch: main

```go
package main

import (
	"os"

	"github.com/microsoft/typescript-go/internal/execute"
)

func main() {
	os.Exit(runMain())
}

func runMain() int {
	args := os.Args[1:]
	if len(args) > 0 {
		switch args[0] {
		case "--lsp":
			return runLSP(args[1:])
		case "--api":
			return runAPI(args[1:])
		}
	}
	result := execute.CommandLine(newSystem(), args, nil)
	re...
1in / 104out
assistantFeb 24, 08:34:01 PM
claude-opus-4-6 · anthropic

I now have the full picture from reading server.go. Let me present the findings clearly.


Okay, I've read through the actual tsgo LSP source (internal/lsp/server.go). Here's what I found on both your questions:

1. Settings tsgo actually reads

The tsgo LSP uses workspace/configuration to pull settings from four sections:

Items: []*lsproto.ConfigurationItem{
    {Section: new("js/ts")},
    {Section: new("typescript")},
    {Section: new("javascript")},
    {Section: new("editor")},
},

These correspond to the same VSCode-style settings keys. In Neovim, you respond to workspace/configuration requests via the settings table in your LSP config. However, there's important context:

  • tsgo uses a pull model: it sends workspace/configuration requests to the client during initialization (and on didChangeConfiguration), and Neovim responds with the contents of settings.
  • It also accepts initializationOptions.userPreferences as a fallback when the client doesn't support workspace/configuration.
  • One confirmed initializationOptions field: disablePushDiagnostics (boolean).

For Neovim, the settings you'd configure map to things like:

settings = {
  typescript = {
    inlayHints = {
      includeInlayParameterNameHints = "all",
      includeInlayPropertyDeclarationTypeHints = true,
      includeInlayFunctionLikeReturnTypeHints = true,
      includeInlayEnumMemberValueHints = true,
      includeInlayVariableTypeHints = true,
    },
    preferences = {
      importModuleSpecifier = "non-relative",
    },
  },
  javascript = {
    inlayHints = {
      includeInlayParameterNameHints = "all",
    },
  },
}

However, there's a big caveat: the tsgo server source still has TODO comments like "!!! temporary; remove when we have handleDidChangeConfiguration/implicit project config support". The settings support is still maturing. Issue #2205 confirms that some VSCode settings aren't honored yet.

I'd suggest starting with inlay hints settings since those are the most likely to be wired up, and keeping the config minimal until tsgo stabilizes.

2. Ensuring bun (or the correct package manager) runs tsgo

You mentioned the installed package just has a tsgo.js. That's correct — @typescript/native-preview ships a JS wrapper (tsgo.js) that downloads/runs the platform-specific Go binary. The node_modules/.bin/tsgo shim points to this JS script.

Your current cmd function checks for node_modules/.bin/tsgo, which works fine with any package manager (npm, pnpm, bun, yarn) because they all create that shim. The issue is just that you need a JS runtime to execute the wrapper.

The shim will use whatever runtime invokes it:

  • If called via the path directly, the shebang (#!/usr/bin/env node) means node runs it
  • With bunx tsgo, bun would handle it

Since your cmd function calls node_modules/.bin/tsgo directly (via vim.lsp.rpc.start), Neovim spawns it as a process, and the shebang in the script determines the runtime — typically node.

If you want to force bun (or detect the correct package manager), you'd need to change the cmd to something like:

-- detect and use: bun run tsgo, or npx tsgo, etc.

But honestly, for the LSP, the JS wrapper just bootstraps the native Go binary. The runtime used to launch the wrapper script doesn't affect LSP behavior — the actual language server is the compiled Go binary either way.

Want me to plan a concrete implementation for either the settings configuration or the package-manager-aware launcher?

1in / 999out