Skip to content

Make oxc-vscode work with Vite+ environments #629

Closed

Description

@Boshen

oxc-vscode tries to discover oxlint|oxfmt binaries by looking in node_modules/.bin/.

In Vite+ projects, these binaries are internal dependencies of the vp CLI, so they don't appear in the user's node_modules/.bin/.
As a result, oxc-vscode cannot find them and LSP features (--lsp) don't work.

TODO

Create wrapper scripts in node_modules/.bin/oxlint|oxfmt after vp install.

  • The wrappers only allow --lsp mode
    • Other usage should show an error directing users to vp lint|fmt
  • Shim generation (sh/cmd/ps1) is handled in Rust, reusing the existing shim.rs
  • Binary paths are resolved via the existing JS lint/fmt resolver() callbacks

Concerns

  • Need to ensure shims are created across all install code paths?
    • explicit vp install, auto-install during vp run, global CLI install, etc
  • Cross-platform support?
    • need all of sh, cmd, and ps1 wrappers

Activity

  1. linear commented on Feb 25, 2026

    @linear
  2. changed the title [-]Oxc LSP support[/-] [+]Make oxc-vscode work with Vite+ environments[/+] on Feb 25, 2026
  3. leaysgur commented on Feb 25, 2026

    @leaysgur
  4. fengmk2 commented on Feb 25, 2026

    @fengmk2
  5. leaysgur commented on Feb 25, 2026

    @leaysgur
  6. leaysgur commented on Feb 26, 2026

    @leaysgur
  7. added a commit that references this issue on Feb 26, 2026
    52709db
  8. leaysgur commented on Mar 6, 2026

    @leaysgur
    Contributor

    Background

    First, the Vite+ configuration file is a single file named vite.config.ts located at the root. Within this file, the keys test, lint, and fmt are nested.

    vp lint and vp fmt generate temporary config files at runtime to integrate with oxlint/oxfmt. This is because oxapps doesn't know about vite.config.ts, so even if you specify it with --config, it cannot be interpreted.

    However, this approach does not work for editor integrations (e.g., VSCode) where the LSP server needs persistent config files.

    ⚠️ And we need to release this by this Thursday.

    Option A: JSON Config Files (Project Root)

    Serialize the vite.config content into .oxlintrc.json / .oxfmtrc.json and place them at the project root. No changes needed on the oxc side, but keeping them in sync with vite.config is a challenge.

    Option B: oxlint/oxfmt Recognize vite.config Directly

    oxlint/oxfmt natively read vite.config.ts and extract the .lint / .fmt fields as their config source. This requires Vite+ knowledge to oxc side.

    👉🏻 This was rejected, oxapps should not know Vite+ specific usage.

    Option C: Generic Config Field Extraction

    Instead of being vite.config-aware, oxlint/oxfmt support extracting a specific field from any TS config file. e.g., oxlint -c vite.config.ts --config-field lint. Not Vite+-specific, so more likely to be accepted by oxc. This also works with package.json (e.g., oxlint -c package.json --config-field oxlint), which is a well-established pattern used by tools like prettier and jest.

    Option D: Bridge Files (Project Root)

    Place oxlint.config.ts / oxfmt.config.ts at the project root that simply import vite.config and re-export the relevant field.

    Option E: Bridge Files (Hidden Location) + basePath

    Place bridge files in a hidden location (e.g., node_modules/.vite-plus/) and add a basePath option to oxlint/oxfmt so that relative paths are resolved from the project root instead of the file's actual location.

    Config Files oxlint oxfmt oxc-vscode vite+ VSCode UX Others UX Concerns
    A .oxlintrc.json, .oxfmtrc.json None None None File generation + sync OK OK 1, 2
    B vite.config.ts vite.config support vite.config support, TS config support None None OK OK 3
    C vite.config.ts configField support configField support, TS config support None None OK OK -
    D oxlint.config.ts, oxfmt.config.ts None TS config support Additional watch patterns File generation OK OK 2, 4
    E Under node_modules/.vite-plus/ basePath support TS config + basePath support Additional watch patterns File generation + editor config OK Not easy 4, 5
    1. Sync between vite.config and JSON files is an ongoing challenge (vp config sync command? file watcher? pre-commit hook?)
    2. Additional files appear in the project root (gitignore?)
    3. Vite+-specific logic would be introduced into oxc side
    4. Watch patterns must be manually configured by the user. There is no mechanism to automatically detect and track import dependencies of config files
    5. Editor-side configuration for configPath + watch is required. Editors which are using CLI directly also requires finding config, extracting field, etc
  9. fengmk2 commented on Mar 6, 2026

    @fengmk2
  10. leaysgur commented on Mar 6, 2026

    @leaysgur
  11. leaysgur commented on Mar 9, 2026

    @leaysgur
    Contributor

    Finally, Option C Option B: approved, TODOs are:

  12. leaysgur commented on Mar 11, 2026

    @leaysgur
    Contributor

    NOTE for the record:


    Currently, Oxlint has 2 concepts to configuration files:

    • root config
    • nested configs

    Nested configs are not used if -c or oxc.configPath is specified.

    And there are 2 types of uses for them:

    • CLI
    • LSP

    First, when the CLI is executed:

    • root config: Searches only the current working directory (cwd)
    • nested configs: Searches upwards from each file

    Regarding vite.config.ts, it used only as a root config and acts as a fallback if other .oxlintrc.json(c) or oxlint.config.ts are not found. (It is ignored when searching for nested configs).

    Next, in the case of LSP, the cwd is based on the workspace folder opened by the user.

    • Root config: Searches upwards from the workspace.
    • Nested configs: Searches downwards from the workspace.

    The key point is that it differs slightly from the CLI, but the handling of vite.config.ts is the same as the CLI; it is only considered as a root config.


    Oxfmt always uses a single configuration file and does not have the concept of nested configs.

    Both the CLI and LSP search upwards from the current working directory.

    vite.config.ts also acts as a fallback if no other .oxfmtrc.json(c) or oxfmt.config.ts is found.


    The current issue is that, for both Oxlint and Oxfmt, the LSP sometimes finds a nested vite.config.ts during the process of searching for the root config.

    monorepo/
    ├── vite.config.ts          # .lint is here
    ├── packages/
    │   └── child/              ← workspace root
    │       ├── vite.config.ts  # .lint not found!
    │       └── src/
    

    This is not an issue when .lint|fmt is intentionally written, but in most other cases, it results in a ".lint|fmt does not exist" error.
    It should work with valid .lint|fmt config one.

    But how...? Load js config and check key, then ignore if not exists...?

    Or, if we only need to support root configs, then perhaps we could allow specifying the root config somehow when calling the wrapper with --lsp...?

    👉🏻 This is fixed by just ignoring vite.config.ts w/o .lint|fmt, and defineConfig(fn) exports.


    To summarize, the remaining concerns we likely have at this point are:

    • The plan for Vite+ has always been for vite.config.ts to be nested, but it's unclear if we want users to nest .lint|fmt configurations
      • I heard that vp lint|fmt will always specify the root vite.config.ts using the -c flag
    • When running vp run fmt in a subdirectory, oxfmt searches for a higher-level configuration file, while oxlint does not
      • There might also be a difference in how oxlint searches for nested configurations (since vp lint uses -c, it doesn't search for nested configurations)
    • For LSP, both will search for a higher-level configuration file
      • However, if an oxfmtrc or similar file is found along that path, it will be used
      • In the first place, placing such files in a Vite+ project is probably not recommended
    • If vite.config.ts uses function style defineConfig(fn), oxapps cannot consume it
      • It seems limitation to interpret vite.config.ts

    These are issues that users may encounter for a while:

  13. jordan-boyer commented on Mar 13, 2026

    @jordan-boyer

    I did install vite+ as my node manager. But now on older project that does not use vite+ the lsp for oxc doesn't work.

    this is the output of the oxc plugin.
    2026-03-13 15:22:45.151 [info] Searching for oxlint binary. 2026-03-13 15:22:45.151 [info] Using server binary at: /Users/jordanboyer/Documents/home/project-medusa/node_modules/.pnpm/oxlint@1.55.0_oxlint-tsgolint@0.16.0/node_modules/oxlint/bin/oxlint 2026-03-13 15:22:45.151 [info] [Error - 3:22:45 PM] oxc client: couldn't create connection to server. 2026-03-13 15:22:45.151 [info] Launching server using command node failed. Error: spawn node ENOENT

    I don't understand how to fix this from this PR if someone have a answer ^^'

  14. nickbutsky commented on Jun 8, 2026

    @nickbutsky

    Unfortunately the issue is not resolved. I resorted to adding the following lines to .vscode/settings.json to make the extension recognize vite.config.ts

    "oxc.path.oxfmt": "node_modules/vite-plus/bin/oxfmt",
    "oxc.path.oxlint": "node_modules/vite-plus/bin/oxlint"
    
  15. shannonmoeller commented on Sep 8, 2026

    @shannonmoeller
    "oxc.configPath": "./vite.config.js",
    "oxc.fmt.configPath": "./vite.config.js",
    "oxc.path.oxfmt": "node_modules/vite-plus/bin/oxfmt",
    "oxc.path.oxlint": "node_modules/vite-plus/bin/oxlint"
    

    This should be part of the default recommended vscode config for vite-plus. https://viteplus.dev/guide/ide-integration#vs-code

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Labels

No labels
No labels

Type

No type

Fields

Priority

None yet

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions