https://github.com/y3owk1n/tool-resolver.nvim
Resolve project-local CLI tools in Neovim with monorepo-aware logic.
https://github.com/y3owk1n/tool-resolver.nvim
neovim neovim-plugin neovim-plugins node-js nodejs nvim nvim-plugin nvim-plugins
Last synced: 9 months ago
JSON representation
Resolve project-local CLI tools in Neovim with monorepo-aware logic.
- Host: GitHub
- URL: https://github.com/y3owk1n/tool-resolver.nvim
- Owner: y3owk1n
- License: mit
- Created: 2025-07-11T06:37:12.000Z (9 months ago)
- Default Branch: main
- Last Pushed: 2025-07-11T07:54:07.000Z (9 months ago)
- Last Synced: 2025-07-11T10:29:36.766Z (9 months ago)
- Topics: neovim, neovim-plugin, neovim-plugins, node-js, nodejs, nvim, nvim-plugin, nvim-plugins
- Language: Lua
- Homepage:
- Size: 20.5 KB
- Stars: 0
- Watchers: 0
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- Changelog: CHANGELOG.md
- License: LICENSE
Awesome Lists containing this project
README
# π§° tool-resolver.nvim
Resolve project-local CLI tools in Neovim with monorepo-aware logic. Say bye to version mismatches!
## π‘ Motivation
I ran into constant version mismatch issues when using tools like biome globally β especially in monorepos or older projects that donβt use the latest version. This often resulted in frustrating errors, even when everything seemed properly set up.
At that point, I had two choices:
- π§ Upgrade every project to use the latest tool versions (not always ideal or even possible)
- β
Resolve the tool binary per project, based on its local installation
So, I built this plugin to make the second option easy and seamless.
While tools like mason.nvim are great, they typically install the latest versions globally β which doesnβt help when you need project-specific versions. **tool-resolver.nvim** fills that gap with fast, reliable, and monorepo-aware resolution of `node_modules/.bin/` for each buffer.
## π Features
- Monorepo-friendly: climbs up directory tree to find local binaries
- Falls back to monorepo root if needed
- Global fallback to system binary if no local match
- Smart per-buffer resolution (works as you switch files)
- Lightweight, dependency-free
> [!NOTE]
> This plugin currently only supports node projects, feel free to contribute for more language resolvers if this plugin interests you.
## π§ How It Works
When resolving a tool (e.g. `biome`), this plugin:
1. Starts at the file's directory
2. Traverses upward to find the nearest executable based on configured type, for `node` it will be at `node_modules/.bin/biome`
3. If none is found, tries the same logic from `vim.fn.getcwd()` (monorepo root fallback)
4. If still not found, falls back to the fallbacks tool name specified in configuration or the global tool name (e.g. "biome")
## π Contents
- [Installation](#-installation)
- [Configuration](#%EF%B8%8F-configuration)
- [API](#-api)
- [Quick Start](#-quick-start)
- [Contributing](#-contributing)
## π¦ Installation
Using [lazy.nvim](https://github.com/folke/lazy.nvim):
```lua
-- tool-resolver.lua
return {
"y3owk1n/tool-resolver.nvim",
version = "*", -- remove this if you want to use the `main` branch
opts = {
-- your configuration comes here
-- or leave it empty to use the default settings
-- refer to the configuration section below
}
}
```
If you are using other package managers you need to call `setup`:
```lua
require("tool-resolver").setup({
-- your configuration
})
```
### Requirements
- Neovim 0.11+ with Lua support
## βοΈ Configuration
The default configurations are as below.
### Default Options
```lua
---@type ToolResolver.Config
{
tools = {},
}
```
### Type Definitions
```lua
---@class ToolResolver.Config
---@field tools table tools with type and fallback
---@class ToolResolver.Config.Tools
---@field type ToolResolver.ResolverType
---@field fallback? string fallback binary name, if not specified then use the key.
```
## π Quick Start
See the example below for how to configure **tool-resolver.nvim**.
```lua
{
"y3owk1n/tool-resolver.nvim",
cmd = {
"ToolResolverGetTool",
"ToolResolverGetTools",
},
---@type ToolResolver.Config
opts = {
-- register the tools that you want to use here
tools = {
biome = {
type = "node", -- type is required, and only "node" is supported for now
},
prettier = {
type = "node", -- type is required, and only "node" is supported for now
fallback = "prettierd", -- specify a fallback binary name will resolve to this, else will fallback to the key `prettier`
},
},
},
},
```
You can then use the following to resolve a tool anywhere. For example in my biome LSP config:
```lua
local tr = require("tool-resolver")
---@type vim.lsp.Config
return {
cmd = { tr.get_bin("biome"), "lsp-proxy" }, -- instead of just getting it from the global bin, use tool-resolver for it.
-- the rest of your lsp configurations
}
```
## π API
**tool-resolver.nvim** provides the following api functions that you can use for different things:
### Get the local or global tool bin
This is the most important function in **tool-resolver.nvim**. It will try to resolve the tool bin from the current buffer to the node modules available binary, and only fallback to the globally installed version.
```lua
---@class ToolResolver.GetBinOpts
---@field path? string start search path (default: current buffer)
---@param tool string
---@param opts? ToolResolver.GetBinOpts
---@return string
require("tool-resolver").get_bin(tool, opts)
```
## π€ Contributing
Read the documentation carefully before submitting any issue.
Feature and pull requests are welcome.