Latest commit

History

23 Commits

Folders and files

NameName
Last commit message
Last commit date

Repository files navigation

NimbleAPI logo
API route explorer and navigator for Neovim

Browse routes. Jump to handlers. Navigate your API.


A Neovim plugin for exploring, navigating, and testing API applications. Browse routes in a sidebar explorer, jump to handlers via fuzzy picker, and see CodeLens annotations linking test client calls to their route definitions. Works across multiple web frameworks with a pluggable provider system.

Supported Frameworks

FrameworkLanguageStatus
FastAPI🐍 Python💚 Supported
Spring / Spring Boot☕ Java💚 Supported
Gin / Echo / Chi / http/net🐹 Go💚 Supported
Express.jsJavaScript / TypeScript💚 Supported
Axum🦀 Rust🐢🐢🐢 Planned
Ruby on Rails💎 Ruby🐢🐢🐢 Planned

Features

  • Route Explorer -- sidebar listing all HTTP routes grouped by source file, with jump-to-definition
  • Fuzzy Picker -- searchable route list via Telescope, Snacks.nvim, or vim.ui.select
  • CodeLens Annotations -- virtual text on test client calls linking them to their route handler
  • Auto-Refresh -- debounced file watcher refreshes routes on save
  • Smart Discovery -- auto-detects framework and app entry point from project files
  • Provider System -- pluggable architecture makes adding new frameworks straightforward

Picker

picker

Explorer

explorer

Requirements

Installation

{
"mrpbennett/nimbleapi.nvim",
cmd="NimbleAPI",
dependencies= {
"nvim-treesitter/nvim-treesitter",
-- Optional: HTTP client for testing routes-- "mistweaverco/kulala.nvim",
},
opts= {},
}

Configuration

All options below are shown with their defaults. Pass only what you want to change:

require("nimbleapi").setup({
provider=nil, -- auto-detect; override: "fastapi", "spring"explorer= {
position="right", -- "left" or "right"width=40,
icons=true, -- requires a Nerd Font
},
picker= {
provider=nil, -- "telescope", "snacks", or "builtin" (nil = auto-detect)
},
keymaps= {
toggle="<leader>Nt", -- toggle explorer sidebarpick="<leader>Np", -- open route pickerrefresh="<leader>Nr", -- refresh route cachecodelens="<leader>Nc", -- toggle codelenstest="<leader>Ne", -- test route under cursor-- Kulala keymaps (buffer-local on .http files, requires kulala.nvim)http_run="<leader>Ns", -- send requesthttp_replay="<leader>NR", -- replay last requesthttp_inspect="<leader>Ni", -- inspect current requesthttp_env="<leader>NE", -- set environment
},
codelens= {
enabled=true,
test_patterns= { "test_*.py", "*_test.py", "tests/**/*.py" },
},
watch= {
enabled=true,
debounce_ms=200,
},
})

Usage

Commands

All commands are available under the :NimbleAPI prefix:

CommandDescription
:NimbleAPI toggleToggle the explorer sidebar
:NimbleAPI pickOpen the route picker
:NimbleAPI refreshRefresh the route cache
:NimbleAPI codelensToggle CodeLens annotations
:NimbleAPI testOpen HTTP test buffer for route under cursor
:NimbleAPI infoShow provider status and diagnostics

Default Keymaps

All keymaps are configurable. Set any keymap to false to disable it.

KeymapActionScope
<leader>NtToggle explorerGlobal
<leader>NpOpen pickerGlobal
<leader>NrRefresh routesGlobal
<leader>NcToggle CodeLensGlobal
<leader>NeTest route under cursorGlobal

Kulala HTTP Keymaps

When kulala.nvim is installed, these keymaps are automatically bound buffer-locally in .http files. They are only active in HTTP buffers and won't pollute your normal keymap space.

KeymapAction
<leader>NsSend request
<leader>NRReplay last request
<leader>NiInspect current request
<leader>NESet environment

All keymaps can be disabled individually by setting them to false in your config.

Explorer Sidebar

The explorer groups routes by source file. The main app file appears first, followed by router files alphabetically. When your active buffer contains routes, the explorer automatically highlights that context.

 NimbleAPI (main.py)
──────────────────────────────────────
main.py
GET / -> root()
GET /health -> health_check()
routers/items.py
GET /items -> get_all_items()
POST /items -> create_item()
GET /items/{id} -> get_item()
PUT /items/{id} -> update_item()
DELETE /items/{id} -> delete_item()

Pressing <CR> or o on a file header jumps to that file. Pressing it on a route line jumps to the handler definition.

Explorer Buffer Keymaps

KeyAction
<CR> / oJump to route or file
sOpen in horizontal split
vOpen in vertical split
rRefresh routes
qClose the sidebar

CodeLens Annotations

When CodeLens is enabled and you open a test file matching one of the configured patterns, virtual text annotations appear on test client calls showing the matched handler:

client.get("/users/123") -> get_user() app/routers/users.py:15

Press gd on an annotated line to jump directly to the route definition.

App Discovery

FastAPI (Python)

The plugin locates your FastAPI application in this order:

  1. pyproject.toml -- reads the [tool.fastapi] section for an app key
  2. Heuristic scan -- searches Python files for FastAPI() constructor calls, preferring shallower paths

Spring / Spring Boot (Java)

  1. Dependency detection -- looks for spring-boot-starter-web, spring-boot-starter-webflux, spring-webmvc, or spring-web in pom.xml or build.gradle
  2. Controller scan -- falls back to scanning for @RestController or @Controller annotations
  3. Entry point -- resolves from @SpringBootApplication class, or the first controller found

Highlight Groups

All highlights ship with sensible defaults and can be overridden in your colorscheme:

GroupDefault
NimbleApiMethodGETGreen, bold
NimbleApiMethodPOSTBlue, bold
NimbleApiMethodPUTYellow, bold
NimbleApiMethodPATCHOrange, bold
NimbleApiMethodDELETERed, bold
NimbleApiMethodOPTIONSPurple, bold
NimbleApiMethodHEADCyan, bold
NimbleApiMethodTRACEGray, bold
NimbleApiMethodWEBSOCKETTeal, bold
NimbleApiTitleOrange, bold
NimbleApiRouterPurple, italic
NimbleApiPathLight gray
NimbleApiFuncCyan

Diagnostics

Run :NimbleAPI info to see a summary of provider status, detection results, and any issues. This is the first place to look when the plugin does not detect your project or a framework is not recognized.

Contributing

Contributions are welcome. The plugin uses a provider pattern that makes adding new framework support straightforward. Each provider lives in its own file under lua/nimbleapi/providers/ and implements a standard interface for detection, route extraction, and app discovery. Corresponding Tree-sitter queries go in queries/<language>/.

See CLAUDE.md at the project root for full architecture documentation, the provider interface spec, and a checklist of files to touch when adding a new framework.

License

MIT

About

Inspired by the FastAPI plugin for VSC, API route explorer and tester for neovim

Topics

Resources

Stars

2 stars

Watchers

0 watching

Forks

Releases

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Add copy buttons to all
 blocks\n(function() {\n function addCopyButtons() {\n document.querySelectorAll('pre code').forEach(function(codeBlock) {\n if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;\n codeBlock.parentElement.setAttribute('data-copy-added', 'true');\n \n var btn = document.createElement('button');\n btn.textContent = 'Copy';\n btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';\n btn.onmouseover = function() { this.style.opacity = '1'; };\n btn.onmouseout = function() { this.style.opacity = '0.7'; };\n btn.onclick = function() {\n navigator.clipboard.writeText(codeBlock.textContent).then(function() {\n btn.textContent = 'Copied!';\n setTimeout(function() { btn.textContent = 'Copy'; }, 1500);\n });\n };\n codeBlock.parentElement.style.position = 'relative';\n codeBlock.parentElement.appendChild(btn);\n });\n }\n \n addCopyButtons();\n \n // Re-run on dynamic content\n var observer = new MutationObserver(addCopyButtons);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Add Copy Buttons to Code Blocks");
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
Skip to content

Latest commit

History

23 Commits

Folders and files

NameName
Last commit message
Last commit date

Repository files navigation

NimbleAPI logo
API route explorer and navigator for Neovim

Browse routes. Jump to handlers. Navigate your API.


A Neovim plugin for exploring, navigating, and testing API applications. Browse routes in a sidebar explorer, jump to handlers via fuzzy picker, and see CodeLens annotations linking test client calls to their route definitions. Works across multiple web frameworks with a pluggable provider system.

Supported Frameworks

FrameworkLanguageStatus
FastAPI🐍 Python💚 Supported
Spring / Spring Boot☕ Java💚 Supported
Gin / Echo / Chi / http/net🐹 Go💚 Supported
Express.jsJavaScript / TypeScript💚 Supported
Axum🦀 Rust🐢🐢🐢 Planned
Ruby on Rails💎 Ruby🐢🐢🐢 Planned

Features

  • Route Explorer -- sidebar listing all HTTP routes grouped by source file, with jump-to-definition
  • Fuzzy Picker -- searchable route list via Telescope, Snacks.nvim, or vim.ui.select
  • CodeLens Annotations -- virtual text on test client calls linking them to their route handler
  • Auto-Refresh -- debounced file watcher refreshes routes on save
  • Smart Discovery -- auto-detects framework and app entry point from project files
  • Provider System -- pluggable architecture makes adding new frameworks straightforward

Picker

picker

Explorer

explorer

Requirements

Installation

{
"mrpbennett/nimbleapi.nvim",
cmd="NimbleAPI",
dependencies= {
"nvim-treesitter/nvim-treesitter",
-- Optional: HTTP client for testing routes-- "mistweaverco/kulala.nvim",
},
opts= {},
}

Configuration

All options below are shown with their defaults. Pass only what you want to change:

require("nimbleapi").setup({
provider=nil, -- auto-detect; override: "fastapi", "spring"explorer= {
position="right", -- "left" or "right"width=40,
icons=true, -- requires a Nerd Font
},
picker= {
provider=nil, -- "telescope", "snacks", or "builtin" (nil = auto-detect)
},
keymaps= {
toggle="<leader>Nt", -- toggle explorer sidebarpick="<leader>Np", -- open route pickerrefresh="<leader>Nr", -- refresh route cachecodelens="<leader>Nc", -- toggle codelenstest="<leader>Ne", -- test route under cursor-- Kulala keymaps (buffer-local on .http files, requires kulala.nvim)http_run="<leader>Ns", -- send requesthttp_replay="<leader>NR", -- replay last requesthttp_inspect="<leader>Ni", -- inspect current requesthttp_env="<leader>NE", -- set environment
},
codelens= {
enabled=true,
test_patterns= { "test_*.py", "*_test.py", "tests/**/*.py" },
},
watch= {
enabled=true,
debounce_ms=200,
},
})

Usage

Commands

All commands are available under the :NimbleAPI prefix:

CommandDescription
:NimbleAPI toggleToggle the explorer sidebar
:NimbleAPI pickOpen the route picker
:NimbleAPI refreshRefresh the route cache
:NimbleAPI codelensToggle CodeLens annotations
:NimbleAPI testOpen HTTP test buffer for route under cursor
:NimbleAPI infoShow provider status and diagnostics

Default Keymaps

All keymaps are configurable. Set any keymap to false to disable it.

KeymapActionScope
<leader>NtToggle explorerGlobal
<leader>NpOpen pickerGlobal
<leader>NrRefresh routesGlobal
<leader>NcToggle CodeLensGlobal
<leader>NeTest route under cursorGlobal

Kulala HTTP Keymaps

When kulala.nvim is installed, these keymaps are automatically bound buffer-locally in .http files. They are only active in HTTP buffers and won't pollute your normal keymap space.

KeymapAction
<leader>NsSend request
<leader>NRReplay last request
<leader>NiInspect current request
<leader>NESet environment

All keymaps can be disabled individually by setting them to false in your config.

Explorer Sidebar

The explorer groups routes by source file. The main app file appears first, followed by router files alphabetically. When your active buffer contains routes, the explorer automatically highlights that context.

 NimbleAPI (main.py)
──────────────────────────────────────
main.py
GET / -> root()
GET /health -> health_check()
routers/items.py
GET /items -> get_all_items()
POST /items -> create_item()
GET /items/{id} -> get_item()
PUT /items/{id} -> update_item()
DELETE /items/{id} -> delete_item()

Pressing <CR> or o on a file header jumps to that file. Pressing it on a route line jumps to the handler definition.

Explorer Buffer Keymaps

KeyAction
<CR> / oJump to route or file
sOpen in horizontal split
vOpen in vertical split
rRefresh routes
qClose the sidebar

CodeLens Annotations

When CodeLens is enabled and you open a test file matching one of the configured patterns, virtual text annotations appear on test client calls showing the matched handler:

client.get("/users/123") -> get_user() app/routers/users.py:15

Press gd on an annotated line to jump directly to the route definition.

App Discovery

FastAPI (Python)

The plugin locates your FastAPI application in this order:

  1. pyproject.toml -- reads the [tool.fastapi] section for an app key
  2. Heuristic scan -- searches Python files for FastAPI() constructor calls, preferring shallower paths

Spring / Spring Boot (Java)

  1. Dependency detection -- looks for spring-boot-starter-web, spring-boot-starter-webflux, spring-webmvc, or spring-web in pom.xml or build.gradle
  2. Controller scan -- falls back to scanning for @RestController or @Controller annotations
  3. Entry point -- resolves from @SpringBootApplication class, or the first controller found

Highlight Groups

All highlights ship with sensible defaults and can be overridden in your colorscheme:

GroupDefault
NimbleApiMethodGETGreen, bold
NimbleApiMethodPOSTBlue, bold
NimbleApiMethodPUTYellow, bold
NimbleApiMethodPATCHOrange, bold
NimbleApiMethodDELETERed, bold
NimbleApiMethodOPTIONSPurple, bold
NimbleApiMethodHEADCyan, bold
NimbleApiMethodTRACEGray, bold
NimbleApiMethodWEBSOCKETTeal, bold
NimbleApiTitleOrange, bold
NimbleApiRouterPurple, italic
NimbleApiPathLight gray
NimbleApiFuncCyan

Diagnostics

Run :NimbleAPI info to see a summary of provider status, detection results, and any issues. This is the first place to look when the plugin does not detect your project or a framework is not recognized.

Contributing

Contributions are welcome. The plugin uses a provider pattern that makes adding new framework support straightforward. Each provider lives in its own file under lua/nimbleapi/providers/ and implements a standard interface for detection, route extraction, and app discovery. Corresponding Tree-sitter queries go in queries/<language>/.

See CLAUDE.md at the project root for full architecture documentation, the provider interface spec, and a checklist of files to touch when adding a new framework.

License

MIT

About

Inspired by the FastAPI plugin for VSC, API route explorer and tester for neovim

Topics

Resources

Stars

2 stars

Watchers

0 watching

Forks

Releases

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Force GitHub README to respect dark mode\n(function() {\n var style = document.createElement('style');\n style.textContent = '\n .markdown-body {\n color-scheme: dark light;\n }\n .markdown-body pre { background: #161b22 !important; }\n .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; }\n .markdown-body table th, .markdown-body table td { border-color: #30363d !important; }\n .markdown-body img { background: #0d1117; }\n .markdown-body blockquote { border-left-color: #8b949e; }\n .markdown-body hr { border-color: #30363d; }\n ';\n document.head.appendChild(style);\n})();", "GitHub Dark Mode README Fix"); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Latest commit

History

23 Commits

Folders and files

NameName
Last commit message
Last commit date

Repository files navigation

NimbleAPI logo
API route explorer and navigator for Neovim

Browse routes. Jump to handlers. Navigate your API.


A Neovim plugin for exploring, navigating, and testing API applications. Browse routes in a sidebar explorer, jump to handlers via fuzzy picker, and see CodeLens annotations linking test client calls to their route definitions. Works across multiple web frameworks with a pluggable provider system.

Supported Frameworks

FrameworkLanguageStatus
FastAPI🐍 Python💚 Supported
Spring / Spring Boot☕ Java💚 Supported
Gin / Echo / Chi / http/net🐹 Go💚 Supported
Express.jsJavaScript / TypeScript💚 Supported
Axum🦀 Rust🐢🐢🐢 Planned
Ruby on Rails💎 Ruby🐢🐢🐢 Planned

Features

  • Route Explorer -- sidebar listing all HTTP routes grouped by source file, with jump-to-definition
  • Fuzzy Picker -- searchable route list via Telescope, Snacks.nvim, or vim.ui.select
  • CodeLens Annotations -- virtual text on test client calls linking them to their route handler
  • Auto-Refresh -- debounced file watcher refreshes routes on save
  • Smart Discovery -- auto-detects framework and app entry point from project files
  • Provider System -- pluggable architecture makes adding new frameworks straightforward

Picker

picker

Explorer

explorer

Requirements

Installation

{
"mrpbennett/nimbleapi.nvim",
cmd="NimbleAPI",
dependencies= {
"nvim-treesitter/nvim-treesitter",
-- Optional: HTTP client for testing routes-- "mistweaverco/kulala.nvim",
},
opts= {},
}

Configuration

All options below are shown with their defaults. Pass only what you want to change:

require("nimbleapi").setup({
provider=nil, -- auto-detect; override: "fastapi", "spring"explorer= {
position="right", -- "left" or "right"width=40,
icons=true, -- requires a Nerd Font
},
picker= {
provider=nil, -- "telescope", "snacks", or "builtin" (nil = auto-detect)
},
keymaps= {
toggle="<leader>Nt", -- toggle explorer sidebarpick="<leader>Np", -- open route pickerrefresh="<leader>Nr", -- refresh route cachecodelens="<leader>Nc", -- toggle codelenstest="<leader>Ne", -- test route under cursor-- Kulala keymaps (buffer-local on .http files, requires kulala.nvim)http_run="<leader>Ns", -- send requesthttp_replay="<leader>NR", -- replay last requesthttp_inspect="<leader>Ni", -- inspect current requesthttp_env="<leader>NE", -- set environment
},
codelens= {
enabled=true,
test_patterns= { "test_*.py", "*_test.py", "tests/**/*.py" },
},
watch= {
enabled=true,
debounce_ms=200,
},
})

Usage

Commands

All commands are available under the :NimbleAPI prefix:

CommandDescription
:NimbleAPI toggleToggle the explorer sidebar
:NimbleAPI pickOpen the route picker
:NimbleAPI refreshRefresh the route cache
:NimbleAPI codelensToggle CodeLens annotations
:NimbleAPI testOpen HTTP test buffer for route under cursor
:NimbleAPI infoShow provider status and diagnostics

Default Keymaps

All keymaps are configurable. Set any keymap to false to disable it.

KeymapActionScope
<leader>NtToggle explorerGlobal
<leader>NpOpen pickerGlobal
<leader>NrRefresh routesGlobal
<leader>NcToggle CodeLensGlobal
<leader>NeTest route under cursorGlobal

Kulala HTTP Keymaps

When kulala.nvim is installed, these keymaps are automatically bound buffer-locally in .http files. They are only active in HTTP buffers and won't pollute your normal keymap space.

KeymapAction
<leader>NsSend request
<leader>NRReplay last request
<leader>NiInspect current request
<leader>NESet environment

All keymaps can be disabled individually by setting them to false in your config.

Explorer Sidebar

The explorer groups routes by source file. The main app file appears first, followed by router files alphabetically. When your active buffer contains routes, the explorer automatically highlights that context.

 NimbleAPI (main.py)
──────────────────────────────────────
main.py
GET / -> root()
GET /health -> health_check()
routers/items.py
GET /items -> get_all_items()
POST /items -> create_item()
GET /items/{id} -> get_item()
PUT /items/{id} -> update_item()
DELETE /items/{id} -> delete_item()

Pressing <CR> or o on a file header jumps to that file. Pressing it on a route line jumps to the handler definition.

Explorer Buffer Keymaps

KeyAction
<CR> / oJump to route or file
sOpen in horizontal split
vOpen in vertical split
rRefresh routes
qClose the sidebar

CodeLens Annotations

When CodeLens is enabled and you open a test file matching one of the configured patterns, virtual text annotations appear on test client calls showing the matched handler:

client.get("/users/123") -> get_user() app/routers/users.py:15

Press gd on an annotated line to jump directly to the route definition.

App Discovery

FastAPI (Python)

The plugin locates your FastAPI application in this order:

  1. pyproject.toml -- reads the [tool.fastapi] section for an app key
  2. Heuristic scan -- searches Python files for FastAPI() constructor calls, preferring shallower paths

Spring / Spring Boot (Java)

  1. Dependency detection -- looks for spring-boot-starter-web, spring-boot-starter-webflux, spring-webmvc, or spring-web in pom.xml or build.gradle
  2. Controller scan -- falls back to scanning for @RestController or @Controller annotations
  3. Entry point -- resolves from @SpringBootApplication class, or the first controller found

Highlight Groups

All highlights ship with sensible defaults and can be overridden in your colorscheme:

GroupDefault
NimbleApiMethodGETGreen, bold
NimbleApiMethodPOSTBlue, bold
NimbleApiMethodPUTYellow, bold
NimbleApiMethodPATCHOrange, bold
NimbleApiMethodDELETERed, bold
NimbleApiMethodOPTIONSPurple, bold
NimbleApiMethodHEADCyan, bold
NimbleApiMethodTRACEGray, bold
NimbleApiMethodWEBSOCKETTeal, bold
NimbleApiTitleOrange, bold
NimbleApiRouterPurple, italic
NimbleApiPathLight gray
NimbleApiFuncCyan

Diagnostics

Run :NimbleAPI info to see a summary of provider status, detection results, and any issues. This is the first place to look when the plugin does not detect your project or a framework is not recognized.

Contributing

Contributions are welcome. The plugin uses a provider pattern that makes adding new framework support straightforward. Each provider lives in its own file under lua/nimbleapi/providers/ and implements a standard interface for detection, route extraction, and app discovery. Corresponding Tree-sitter queries go in queries/<language>/.

See CLAUDE.md at the project root for full architecture documentation, the provider interface spec, and a checklist of files to touch when adding a new framework.

License

MIT

About

Inspired by the FastAPI plugin for VSC, API route explorer and tester for neovim

Topics

Resources

Stars

2 stars

Watchers

0 watching

Forks

Releases

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Highlight search terms from Google/DuckDuckGo/Bing referrer\n(function() {\n var ref = document.referrer;\n var terms = [];\n \n if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) {\n var url = new URL(ref);\n var q = url.searchParams.get('q') || url.searchParams.get('p');\n if (q) {\n terms = q.split(/\\s+/).filter(function(t) { return t.length > 2; });\n }\n }\n \n if (terms.length === 0) return;\n \n var style = document.createElement('style');\n style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }';\n document.head.appendChild(style);\n \n function highlight(node) {\n if (node.nodeType === 3) { // text node\n var text = node.textContent;\n var found = false;\n terms.forEach(function(term) {\n var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\') + ')', 'gi');\n if (regex.test(text)) {\n found = true;\n var frag = document.createDocumentFragment();\n var parts = text.split(regex);\n parts.forEach(function(part, i) {\n if (i % 2 === 0) {\n frag.appendChild(document.createTextNode(part));\n } else {\n var span = document.createElement('span');\n span.className = 'userscript-highlight';\n span.textContent = part;\n frag.appendChild(span);\n }\n });\n node.parentNode.replaceChild(frag, node);\n }\n });\n } else if (node.nodeType === 1 && node.childNodes) { // element\n var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT'];\n if (!skipTags.includes(node.tagName)) {\n Array.from(node.childNodes).forEach(highlight);\n }\n }\n }\n \n highlight(document.body);\n \n // Re-highlight on dynamic content\n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1 || node.nodeType === 3) highlight(node);\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Highlight Search Terms"); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Latest commit

History

23 Commits

Folders and files

NameName
Last commit message
Last commit date

Repository files navigation

NimbleAPI logo
API route explorer and navigator for Neovim

Browse routes. Jump to handlers. Navigate your API.


A Neovim plugin for exploring, navigating, and testing API applications. Browse routes in a sidebar explorer, jump to handlers via fuzzy picker, and see CodeLens annotations linking test client calls to their route definitions. Works across multiple web frameworks with a pluggable provider system.

Supported Frameworks

FrameworkLanguageStatus
FastAPI🐍 Python💚 Supported
Spring / Spring Boot☕ Java💚 Supported
Gin / Echo / Chi / http/net🐹 Go💚 Supported
Express.jsJavaScript / TypeScript💚 Supported
Axum🦀 Rust🐢🐢🐢 Planned
Ruby on Rails💎 Ruby🐢🐢🐢 Planned

Features

  • Route Explorer -- sidebar listing all HTTP routes grouped by source file, with jump-to-definition
  • Fuzzy Picker -- searchable route list via Telescope, Snacks.nvim, or vim.ui.select
  • CodeLens Annotations -- virtual text on test client calls linking them to their route handler
  • Auto-Refresh -- debounced file watcher refreshes routes on save
  • Smart Discovery -- auto-detects framework and app entry point from project files
  • Provider System -- pluggable architecture makes adding new frameworks straightforward

Picker

picker

Explorer

explorer

Requirements

Installation

{
"mrpbennett/nimbleapi.nvim",
cmd="NimbleAPI",
dependencies= {
"nvim-treesitter/nvim-treesitter",
-- Optional: HTTP client for testing routes-- "mistweaverco/kulala.nvim",
},
opts= {},
}

Configuration

All options below are shown with their defaults. Pass only what you want to change:

require("nimbleapi").setup({
provider=nil, -- auto-detect; override: "fastapi", "spring"explorer= {
position="right", -- "left" or "right"width=40,
icons=true, -- requires a Nerd Font
},
picker= {
provider=nil, -- "telescope", "snacks", or "builtin" (nil = auto-detect)
},
keymaps= {
toggle="<leader>Nt", -- toggle explorer sidebarpick="<leader>Np", -- open route pickerrefresh="<leader>Nr", -- refresh route cachecodelens="<leader>Nc", -- toggle codelenstest="<leader>Ne", -- test route under cursor-- Kulala keymaps (buffer-local on .http files, requires kulala.nvim)http_run="<leader>Ns", -- send requesthttp_replay="<leader>NR", -- replay last requesthttp_inspect="<leader>Ni", -- inspect current requesthttp_env="<leader>NE", -- set environment
},
codelens= {
enabled=true,
test_patterns= { "test_*.py", "*_test.py", "tests/**/*.py" },
},
watch= {
enabled=true,
debounce_ms=200,
},
})

Usage

Commands

All commands are available under the :NimbleAPI prefix:

CommandDescription
:NimbleAPI toggleToggle the explorer sidebar
:NimbleAPI pickOpen the route picker
:NimbleAPI refreshRefresh the route cache
:NimbleAPI codelensToggle CodeLens annotations
:NimbleAPI testOpen HTTP test buffer for route under cursor
:NimbleAPI infoShow provider status and diagnostics

Default Keymaps

All keymaps are configurable. Set any keymap to false to disable it.

KeymapActionScope
<leader>NtToggle explorerGlobal
<leader>NpOpen pickerGlobal
<leader>NrRefresh routesGlobal
<leader>NcToggle CodeLensGlobal
<leader>NeTest route under cursorGlobal

Kulala HTTP Keymaps

When kulala.nvim is installed, these keymaps are automatically bound buffer-locally in .http files. They are only active in HTTP buffers and won't pollute your normal keymap space.

KeymapAction
<leader>NsSend request
<leader>NRReplay last request
<leader>NiInspect current request
<leader>NESet environment

All keymaps can be disabled individually by setting them to false in your config.

Explorer Sidebar

The explorer groups routes by source file. The main app file appears first, followed by router files alphabetically. When your active buffer contains routes, the explorer automatically highlights that context.

 NimbleAPI (main.py)
──────────────────────────────────────
main.py
GET / -> root()
GET /health -> health_check()
routers/items.py
GET /items -> get_all_items()
POST /items -> create_item()
GET /items/{id} -> get_item()
PUT /items/{id} -> update_item()
DELETE /items/{id} -> delete_item()

Pressing <CR> or o on a file header jumps to that file. Pressing it on a route line jumps to the handler definition.

Explorer Buffer Keymaps

KeyAction
<CR> / oJump to route or file
sOpen in horizontal split
vOpen in vertical split
rRefresh routes
qClose the sidebar

CodeLens Annotations

When CodeLens is enabled and you open a test file matching one of the configured patterns, virtual text annotations appear on test client calls showing the matched handler:

client.get("/users/123") -> get_user() app/routers/users.py:15

Press gd on an annotated line to jump directly to the route definition.

App Discovery

FastAPI (Python)

The plugin locates your FastAPI application in this order:

  1. pyproject.toml -- reads the [tool.fastapi] section for an app key
  2. Heuristic scan -- searches Python files for FastAPI() constructor calls, preferring shallower paths

Spring / Spring Boot (Java)

  1. Dependency detection -- looks for spring-boot-starter-web, spring-boot-starter-webflux, spring-webmvc, or spring-web in pom.xml or build.gradle
  2. Controller scan -- falls back to scanning for @RestController or @Controller annotations
  3. Entry point -- resolves from @SpringBootApplication class, or the first controller found

Highlight Groups

All highlights ship with sensible defaults and can be overridden in your colorscheme:

GroupDefault
NimbleApiMethodGETGreen, bold
NimbleApiMethodPOSTBlue, bold
NimbleApiMethodPUTYellow, bold
NimbleApiMethodPATCHOrange, bold
NimbleApiMethodDELETERed, bold
NimbleApiMethodOPTIONSPurple, bold
NimbleApiMethodHEADCyan, bold
NimbleApiMethodTRACEGray, bold
NimbleApiMethodWEBSOCKETTeal, bold
NimbleApiTitleOrange, bold
NimbleApiRouterPurple, italic
NimbleApiPathLight gray
NimbleApiFuncCyan

Diagnostics

Run :NimbleAPI info to see a summary of provider status, detection results, and any issues. This is the first place to look when the plugin does not detect your project or a framework is not recognized.

Contributing

Contributions are welcome. The plugin uses a provider pattern that makes adding new framework support straightforward. Each provider lives in its own file under lua/nimbleapi/providers/ and implements a standard interface for detection, route extraction, and app discovery. Corresponding Tree-sitter queries go in queries/<language>/.

See CLAUDE.md at the project root for full architecture documentation, the provider interface spec, and a checklist of files to touch when adding a new framework.

License

MIT

About

Inspired by the FastAPI plugin for VSC, API route explorer and tester for neovim

Topics

Resources

Stars

2 stars

Watchers

0 watching

Forks

Releases

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Strip utm_, fbclid, gclid, etc. from all links on page\n(function() {\n var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content',\n 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid',\n 'ref', 'ref_src', 'source', 'medium', 'campaign'];\n \n function cleanUrl(url) {\n try {\n var u = new URL(url, window.location.origin);\n var changed = false;\n trackingParams.forEach(function(p) {\n if (u.searchParams.has(p)) {\n u.searchParams.delete(p);\n changed = true;\n }\n });\n return changed ? u.toString() : url;\n } catch (e) {\n return url;\n }\n }\n \n function cleanLinks() {\n document.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n \n cleanLinks();\n \n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1) {\n if (node.tagName === 'A') cleanLinks();\n node.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Remove Tracking Parameters from Links"); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + '
Skip to content

Latest commit

History

23 Commits

Folders and files

NameName
Last commit message
Last commit date

Repository files navigation

NimbleAPI logo
API route explorer and navigator for Neovim

Browse routes. Jump to handlers. Navigate your API.


A Neovim plugin for exploring, navigating, and testing API applications. Browse routes in a sidebar explorer, jump to handlers via fuzzy picker, and see CodeLens annotations linking test client calls to their route definitions. Works across multiple web frameworks with a pluggable provider system.

Supported Frameworks

FrameworkLanguageStatus
FastAPI🐍 Python💚 Supported
Spring / Spring Boot☕ Java💚 Supported
Gin / Echo / Chi / http/net🐹 Go💚 Supported
Express.jsJavaScript / TypeScript💚 Supported
Axum🦀 Rust🐢🐢🐢 Planned
Ruby on Rails💎 Ruby🐢🐢🐢 Planned

Features

  • Route Explorer -- sidebar listing all HTTP routes grouped by source file, with jump-to-definition
  • Fuzzy Picker -- searchable route list via Telescope, Snacks.nvim, or vim.ui.select
  • CodeLens Annotations -- virtual text on test client calls linking them to their route handler
  • Auto-Refresh -- debounced file watcher refreshes routes on save
  • Smart Discovery -- auto-detects framework and app entry point from project files
  • Provider System -- pluggable architecture makes adding new frameworks straightforward

Picker

picker

Explorer

explorer

Requirements

Installation

{
"mrpbennett/nimbleapi.nvim",
cmd="NimbleAPI",
dependencies= {
"nvim-treesitter/nvim-treesitter",
-- Optional: HTTP client for testing routes-- "mistweaverco/kulala.nvim",
},
opts= {},
}

Configuration

All options below are shown with their defaults. Pass only what you want to change:

require("nimbleapi").setup({
provider=nil, -- auto-detect; override: "fastapi", "spring"explorer= {
position="right", -- "left" or "right"width=40,
icons=true, -- requires a Nerd Font
},
picker= {
provider=nil, -- "telescope", "snacks", or "builtin" (nil = auto-detect)
},
keymaps= {
toggle="<leader>Nt", -- toggle explorer sidebarpick="<leader>Np", -- open route pickerrefresh="<leader>Nr", -- refresh route cachecodelens="<leader>Nc", -- toggle codelenstest="<leader>Ne", -- test route under cursor-- Kulala keymaps (buffer-local on .http files, requires kulala.nvim)http_run="<leader>Ns", -- send requesthttp_replay="<leader>NR", -- replay last requesthttp_inspect="<leader>Ni", -- inspect current requesthttp_env="<leader>NE", -- set environment
},
codelens= {
enabled=true,
test_patterns= { "test_*.py", "*_test.py", "tests/**/*.py" },
},
watch= {
enabled=true,
debounce_ms=200,
},
})

Usage

Commands

All commands are available under the :NimbleAPI prefix:

CommandDescription
:NimbleAPI toggleToggle the explorer sidebar
:NimbleAPI pickOpen the route picker
:NimbleAPI refreshRefresh the route cache
:NimbleAPI codelensToggle CodeLens annotations
:NimbleAPI testOpen HTTP test buffer for route under cursor
:NimbleAPI infoShow provider status and diagnostics

Default Keymaps

All keymaps are configurable. Set any keymap to false to disable it.

KeymapActionScope
<leader>NtToggle explorerGlobal
<leader>NpOpen pickerGlobal
<leader>NrRefresh routesGlobal
<leader>NcToggle CodeLensGlobal
<leader>NeTest route under cursorGlobal

Kulala HTTP Keymaps

When kulala.nvim is installed, these keymaps are automatically bound buffer-locally in .http files. They are only active in HTTP buffers and won't pollute your normal keymap space.

KeymapAction
<leader>NsSend request
<leader>NRReplay last request
<leader>NiInspect current request
<leader>NESet environment

All keymaps can be disabled individually by setting them to false in your config.

Explorer Sidebar

The explorer groups routes by source file. The main app file appears first, followed by router files alphabetically. When your active buffer contains routes, the explorer automatically highlights that context.

 NimbleAPI (main.py)
──────────────────────────────────────
main.py
GET / -> root()
GET /health -> health_check()
routers/items.py
GET /items -> get_all_items()
POST /items -> create_item()
GET /items/{id} -> get_item()
PUT /items/{id} -> update_item()
DELETE /items/{id} -> delete_item()

Pressing <CR> or o on a file header jumps to that file. Pressing it on a route line jumps to the handler definition.

Explorer Buffer Keymaps

KeyAction
<CR> / oJump to route or file
sOpen in horizontal split
vOpen in vertical split
rRefresh routes
qClose the sidebar

CodeLens Annotations

When CodeLens is enabled and you open a test file matching one of the configured patterns, virtual text annotations appear on test client calls showing the matched handler:

client.get("/users/123") -> get_user() app/routers/users.py:15

Press gd on an annotated line to jump directly to the route definition.

App Discovery

FastAPI (Python)

The plugin locates your FastAPI application in this order:

  1. pyproject.toml -- reads the [tool.fastapi] section for an app key
  2. Heuristic scan -- searches Python files for FastAPI() constructor calls, preferring shallower paths

Spring / Spring Boot (Java)

  1. Dependency detection -- looks for spring-boot-starter-web, spring-boot-starter-webflux, spring-webmvc, or spring-web in pom.xml or build.gradle
  2. Controller scan -- falls back to scanning for @RestController or @Controller annotations
  3. Entry point -- resolves from @SpringBootApplication class, or the first controller found

Highlight Groups

All highlights ship with sensible defaults and can be overridden in your colorscheme:

GroupDefault
NimbleApiMethodGETGreen, bold
NimbleApiMethodPOSTBlue, bold
NimbleApiMethodPUTYellow, bold
NimbleApiMethodPATCHOrange, bold
NimbleApiMethodDELETERed, bold
NimbleApiMethodOPTIONSPurple, bold
NimbleApiMethodHEADCyan, bold
NimbleApiMethodTRACEGray, bold
NimbleApiMethodWEBSOCKETTeal, bold
NimbleApiTitleOrange, bold
NimbleApiRouterPurple, italic
NimbleApiPathLight gray
NimbleApiFuncCyan

Diagnostics

Run :NimbleAPI info to see a summary of provider status, detection results, and any issues. This is the first place to look when the plugin does not detect your project or a framework is not recognized.

Contributing

Contributions are welcome. The plugin uses a provider pattern that makes adding new framework support straightforward. Each provider lives in its own file under lua/nimbleapi/providers/ and implements a standard interface for detection, route extraction, and app discovery. Corresponding Tree-sitter queries go in queries/<language>/.

See CLAUDE.md at the project root for full architecture documentation, the provider interface spec, and a checklist of files to touch when adding a new framework.

License

MIT

About

Inspired by the FastAPI plugin for VSC, API route explorer and tester for neovim

Topics

Resources

Stars

2 stars

Watchers

0 watching

Forks

Releases

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Auto-enable theater mode on YouTube\n(function() {\n function tryTheater() {\n var btn = document.querySelector('button[aria-label=\"Theater mode\"], ytd-player #player button[title=\"Theater mode\"]');\n if (btn && !btn.classList.contains('activated')) {\n btn.click();\n }\n }\n \n // Try immediately\n tryTheater();\n \n // Try after navigation (SPA)\n var lastUrl = location.href;\n setInterval(function() {\n if (location.href !== lastUrl) {\n lastUrl = location.href;\n setTimeout(tryTheater, 500);\n }\n }, 1000);\n \n // Also try on player load\n var observer = new MutationObserver(tryTheater);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "YouTube Theater Mode Default"); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Latest commit

History

23 Commits

Folders and files

NameName
Last commit message
Last commit date

Repository files navigation

NimbleAPI logo
API route explorer and navigator for Neovim

Browse routes. Jump to handlers. Navigate your API.


A Neovim plugin for exploring, navigating, and testing API applications. Browse routes in a sidebar explorer, jump to handlers via fuzzy picker, and see CodeLens annotations linking test client calls to their route definitions. Works across multiple web frameworks with a pluggable provider system.

Supported Frameworks

FrameworkLanguageStatus
FastAPI🐍 Python💚 Supported
Spring / Spring Boot☕ Java💚 Supported
Gin / Echo / Chi / http/net🐹 Go💚 Supported
Express.jsJavaScript / TypeScript💚 Supported
Axum🦀 Rust🐢🐢🐢 Planned
Ruby on Rails💎 Ruby🐢🐢🐢 Planned

Features

  • Route Explorer -- sidebar listing all HTTP routes grouped by source file, with jump-to-definition
  • Fuzzy Picker -- searchable route list via Telescope, Snacks.nvim, or vim.ui.select
  • CodeLens Annotations -- virtual text on test client calls linking them to their route handler
  • Auto-Refresh -- debounced file watcher refreshes routes on save
  • Smart Discovery -- auto-detects framework and app entry point from project files
  • Provider System -- pluggable architecture makes adding new frameworks straightforward

Picker

picker

Explorer

explorer

Requirements

Installation

{
"mrpbennett/nimbleapi.nvim",
cmd="NimbleAPI",
dependencies= {
"nvim-treesitter/nvim-treesitter",
-- Optional: HTTP client for testing routes-- "mistweaverco/kulala.nvim",
},
opts= {},
}

Configuration

All options below are shown with their defaults. Pass only what you want to change:

require("nimbleapi").setup({
provider=nil, -- auto-detect; override: "fastapi", "spring"explorer= {
position="right", -- "left" or "right"width=40,
icons=true, -- requires a Nerd Font
},
picker= {
provider=nil, -- "telescope", "snacks", or "builtin" (nil = auto-detect)
},
keymaps= {
toggle="<leader>Nt", -- toggle explorer sidebarpick="<leader>Np", -- open route pickerrefresh="<leader>Nr", -- refresh route cachecodelens="<leader>Nc", -- toggle codelenstest="<leader>Ne", -- test route under cursor-- Kulala keymaps (buffer-local on .http files, requires kulala.nvim)http_run="<leader>Ns", -- send requesthttp_replay="<leader>NR", -- replay last requesthttp_inspect="<leader>Ni", -- inspect current requesthttp_env="<leader>NE", -- set environment
},
codelens= {
enabled=true,
test_patterns= { "test_*.py", "*_test.py", "tests/**/*.py" },
},
watch= {
enabled=true,
debounce_ms=200,
},
})

Usage

Commands

All commands are available under the :NimbleAPI prefix:

CommandDescription
:NimbleAPI toggleToggle the explorer sidebar
:NimbleAPI pickOpen the route picker
:NimbleAPI refreshRefresh the route cache
:NimbleAPI codelensToggle CodeLens annotations
:NimbleAPI testOpen HTTP test buffer for route under cursor
:NimbleAPI infoShow provider status and diagnostics

Default Keymaps

All keymaps are configurable. Set any keymap to false to disable it.

KeymapActionScope
<leader>NtToggle explorerGlobal
<leader>NpOpen pickerGlobal
<leader>NrRefresh routesGlobal
<leader>NcToggle CodeLensGlobal
<leader>NeTest route under cursorGlobal

Kulala HTTP Keymaps

When kulala.nvim is installed, these keymaps are automatically bound buffer-locally in .http files. They are only active in HTTP buffers and won't pollute your normal keymap space.

KeymapAction
<leader>NsSend request
<leader>NRReplay last request
<leader>NiInspect current request
<leader>NESet environment

All keymaps can be disabled individually by setting them to false in your config.

Explorer Sidebar

The explorer groups routes by source file. The main app file appears first, followed by router files alphabetically. When your active buffer contains routes, the explorer automatically highlights that context.

 NimbleAPI (main.py)
──────────────────────────────────────
main.py
GET / -> root()
GET /health -> health_check()
routers/items.py
GET /items -> get_all_items()
POST /items -> create_item()
GET /items/{id} -> get_item()
PUT /items/{id} -> update_item()
DELETE /items/{id} -> delete_item()

Pressing <CR> or o on a file header jumps to that file. Pressing it on a route line jumps to the handler definition.

Explorer Buffer Keymaps

KeyAction
<CR> / oJump to route or file
sOpen in horizontal split
vOpen in vertical split
rRefresh routes
qClose the sidebar

CodeLens Annotations

When CodeLens is enabled and you open a test file matching one of the configured patterns, virtual text annotations appear on test client calls showing the matched handler:

client.get("/users/123") -> get_user() app/routers/users.py:15

Press gd on an annotated line to jump directly to the route definition.

App Discovery

FastAPI (Python)

The plugin locates your FastAPI application in this order:

  1. pyproject.toml -- reads the [tool.fastapi] section for an app key
  2. Heuristic scan -- searches Python files for FastAPI() constructor calls, preferring shallower paths

Spring / Spring Boot (Java)

  1. Dependency detection -- looks for spring-boot-starter-web, spring-boot-starter-webflux, spring-webmvc, or spring-web in pom.xml or build.gradle
  2. Controller scan -- falls back to scanning for @RestController or @Controller annotations
  3. Entry point -- resolves from @SpringBootApplication class, or the first controller found

Highlight Groups

All highlights ship with sensible defaults and can be overridden in your colorscheme:

GroupDefault
NimbleApiMethodGETGreen, bold
NimbleApiMethodPOSTBlue, bold
NimbleApiMethodPUTYellow, bold
NimbleApiMethodPATCHOrange, bold
NimbleApiMethodDELETERed, bold
NimbleApiMethodOPTIONSPurple, bold
NimbleApiMethodHEADCyan, bold
NimbleApiMethodTRACEGray, bold
NimbleApiMethodWEBSOCKETTeal, bold
NimbleApiTitleOrange, bold
NimbleApiRouterPurple, italic
NimbleApiPathLight gray
NimbleApiFuncCyan

Diagnostics

Run :NimbleAPI info to see a summary of provider status, detection results, and any issues. This is the first place to look when the plugin does not detect your project or a framework is not recognized.

Contributing

Contributions are welcome. The plugin uses a provider pattern that makes adding new framework support straightforward. Each provider lives in its own file under lua/nimbleapi/providers/ and implements a standard interface for detection, route extraction, and app discovery. Corresponding Tree-sitter queries go in queries/<language>/.

See CLAUDE.md at the project root for full architecture documentation, the provider interface spec, and a checklist of files to touch when adding a new framework.

License

MIT

About

Inspired by the FastAPI plugin for VSC, API route explorer and tester for neovim

Topics

Resources

Stars

2 stars

Watchers

0 watching

Forks

Releases

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Remove or un-stick sticky/fixed headers that block content\n(function() {\n function unstick() {\n document.querySelectorAll('header, nav, [role=\"banner\"], .header, .navbar, .sticky, .fixed-top, [style*=\"position: fixed\"], [style*=\"position:sticky\"]').forEach(function(el) {\n if (el.style.position === 'fixed' || el.style.position === 'sticky' || \n getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') {\n el.style.position = 'static';\n el.style.top = 'auto';\n el.style.zIndex = 'auto';\n }\n });\n }\n \n unstick();\n \n var observer = new MutationObserver(unstick);\n observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] });\n})();", "Kill Sticky Headers"); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Latest commit

History

23 Commits

Folders and files

NameName
Last commit message
Last commit date

Repository files navigation

NimbleAPI logo
API route explorer and navigator for Neovim

Browse routes. Jump to handlers. Navigate your API.


A Neovim plugin for exploring, navigating, and testing API applications. Browse routes in a sidebar explorer, jump to handlers via fuzzy picker, and see CodeLens annotations linking test client calls to their route definitions. Works across multiple web frameworks with a pluggable provider system.

Supported Frameworks

FrameworkLanguageStatus
FastAPI🐍 Python💚 Supported
Spring / Spring Boot☕ Java💚 Supported
Gin / Echo / Chi / http/net🐹 Go💚 Supported
Express.jsJavaScript / TypeScript💚 Supported
Axum🦀 Rust🐢🐢🐢 Planned
Ruby on Rails💎 Ruby🐢🐢🐢 Planned

Features

  • Route Explorer -- sidebar listing all HTTP routes grouped by source file, with jump-to-definition
  • Fuzzy Picker -- searchable route list via Telescope, Snacks.nvim, or vim.ui.select
  • CodeLens Annotations -- virtual text on test client calls linking them to their route handler
  • Auto-Refresh -- debounced file watcher refreshes routes on save
  • Smart Discovery -- auto-detects framework and app entry point from project files
  • Provider System -- pluggable architecture makes adding new frameworks straightforward

Picker

picker

Explorer

explorer

Requirements

Installation

{
"mrpbennett/nimbleapi.nvim",
cmd="NimbleAPI",
dependencies= {
"nvim-treesitter/nvim-treesitter",
-- Optional: HTTP client for testing routes-- "mistweaverco/kulala.nvim",
},
opts= {},
}

Configuration

All options below are shown with their defaults. Pass only what you want to change:

require("nimbleapi").setup({
provider=nil, -- auto-detect; override: "fastapi", "spring"explorer= {
position="right", -- "left" or "right"width=40,
icons=true, -- requires a Nerd Font
},
picker= {
provider=nil, -- "telescope", "snacks", or "builtin" (nil = auto-detect)
},
keymaps= {
toggle="<leader>Nt", -- toggle explorer sidebarpick="<leader>Np", -- open route pickerrefresh="<leader>Nr", -- refresh route cachecodelens="<leader>Nc", -- toggle codelenstest="<leader>Ne", -- test route under cursor-- Kulala keymaps (buffer-local on .http files, requires kulala.nvim)http_run="<leader>Ns", -- send requesthttp_replay="<leader>NR", -- replay last requesthttp_inspect="<leader>Ni", -- inspect current requesthttp_env="<leader>NE", -- set environment
},
codelens= {
enabled=true,
test_patterns= { "test_*.py", "*_test.py", "tests/**/*.py" },
},
watch= {
enabled=true,
debounce_ms=200,
},
})

Usage

Commands

All commands are available under the :NimbleAPI prefix:

CommandDescription
:NimbleAPI toggleToggle the explorer sidebar
:NimbleAPI pickOpen the route picker
:NimbleAPI refreshRefresh the route cache
:NimbleAPI codelensToggle CodeLens annotations
:NimbleAPI testOpen HTTP test buffer for route under cursor
:NimbleAPI infoShow provider status and diagnostics

Default Keymaps

All keymaps are configurable. Set any keymap to false to disable it.

KeymapActionScope
<leader>NtToggle explorerGlobal
<leader>NpOpen pickerGlobal
<leader>NrRefresh routesGlobal
<leader>NcToggle CodeLensGlobal
<leader>NeTest route under cursorGlobal

Kulala HTTP Keymaps

When kulala.nvim is installed, these keymaps are automatically bound buffer-locally in .http files. They are only active in HTTP buffers and won't pollute your normal keymap space.

KeymapAction
<leader>NsSend request
<leader>NRReplay last request
<leader>NiInspect current request
<leader>NESet environment

All keymaps can be disabled individually by setting them to false in your config.

Explorer Sidebar

The explorer groups routes by source file. The main app file appears first, followed by router files alphabetically. When your active buffer contains routes, the explorer automatically highlights that context.

 NimbleAPI (main.py)
──────────────────────────────────────
main.py
GET / -> root()
GET /health -> health_check()
routers/items.py
GET /items -> get_all_items()
POST /items -> create_item()
GET /items/{id} -> get_item()
PUT /items/{id} -> update_item()
DELETE /items/{id} -> delete_item()

Pressing <CR> or o on a file header jumps to that file. Pressing it on a route line jumps to the handler definition.

Explorer Buffer Keymaps

KeyAction
<CR> / oJump to route or file
sOpen in horizontal split
vOpen in vertical split
rRefresh routes
qClose the sidebar

CodeLens Annotations

When CodeLens is enabled and you open a test file matching one of the configured patterns, virtual text annotations appear on test client calls showing the matched handler:

client.get("/users/123") -> get_user() app/routers/users.py:15

Press gd on an annotated line to jump directly to the route definition.

App Discovery

FastAPI (Python)

The plugin locates your FastAPI application in this order:

  1. pyproject.toml -- reads the [tool.fastapi] section for an app key
  2. Heuristic scan -- searches Python files for FastAPI() constructor calls, preferring shallower paths

Spring / Spring Boot (Java)

  1. Dependency detection -- looks for spring-boot-starter-web, spring-boot-starter-webflux, spring-webmvc, or spring-web in pom.xml or build.gradle
  2. Controller scan -- falls back to scanning for @RestController or @Controller annotations
  3. Entry point -- resolves from @SpringBootApplication class, or the first controller found

Highlight Groups

All highlights ship with sensible defaults and can be overridden in your colorscheme:

GroupDefault
NimbleApiMethodGETGreen, bold
NimbleApiMethodPOSTBlue, bold
NimbleApiMethodPUTYellow, bold
NimbleApiMethodPATCHOrange, bold
NimbleApiMethodDELETERed, bold
NimbleApiMethodOPTIONSPurple, bold
NimbleApiMethodHEADCyan, bold
NimbleApiMethodTRACEGray, bold
NimbleApiMethodWEBSOCKETTeal, bold
NimbleApiTitleOrange, bold
NimbleApiRouterPurple, italic
NimbleApiPathLight gray
NimbleApiFuncCyan

Diagnostics

Run :NimbleAPI info to see a summary of provider status, detection results, and any issues. This is the first place to look when the plugin does not detect your project or a framework is not recognized.

Contributing

Contributions are welcome. The plugin uses a provider pattern that makes adding new framework support straightforward. Each provider lives in its own file under lua/nimbleapi/providers/ and implements a standard interface for detection, route extraction, and app discovery. Corresponding Tree-sitter queries go in queries/<language>/.

See CLAUDE.md at the project root for full architecture documentation, the provider interface spec, and a checklist of files to touch when adding a new framework.

License

MIT

About

Inspired by the FastAPI plugin for VSC, API route explorer and tester for neovim

Topics

Resources

Stars

2 stars

Watchers

0 watching

Forks

Releases

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Universal Dark Mode - works on any site\n(function() {\n var enabled = true;\n \n function applyDarkMode() {\n if (!enabled) return;\n \n // Create style element if it doesn't exist\n var style = document.getElementById('universal-dark-mode-style');\n if (!style) {\n style = document.createElement('style');\n style.id = 'universal-dark-mode-style';\n document.head.appendChild(style);\n }\n \n // Dark mode CSS - inverts colors but preserves images/video\n style.textContent = '\n /* Invert everything except media */\n html {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #1a1a2e !important;\n }\n \n /* Restore images, videos, iframes, canvas */\n img, video, iframe, canvas, svg, picture, [style*=\"background-image\"] {\n filter: invert(1) hue-rotate(180deg) !important;\n }\n \n /* Preserve specific elements that should not be inverted */\n .no-dark-mode, .no-dark-mode *,\n [data-theme=\"light\"], [data-theme=\"light\"],\n .ace_editor, .ace_editor *,\n .CodeMirror, .CodeMirror *,\n .monaco-editor, .monaco-editor *,\n .markdown-body pre, .markdown-body pre *,\n .highlight, .highlight *,\n pre code, pre code * {\n filter: none !important;\n }\n \n /* Fix common UI elements */\n .modal, .popup, .dropdown-menu, .tooltip, .popover {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #2d2d44 !important;\n border-color: #444 !important;\n }\n \n /* Scrollbars */\n ::-webkit-scrollbar { background: #1a1a2e !important; }\n ::-webkit-scrollbar-thumb { background: #444 !important; }\n ::-webkit-scrollbar-thumb:hover { background: #555 !important; }\n \n /* Selection */\n ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ';\n }\n \n function removeDarkMode() {\n var style = document.getElementById('universal-dark-mode-style');\n if (style) style.remove();\n }\n \n // Toggle with Alt+Shift+D\n document.addEventListener('keydown', function(e) {\n if (e.altKey && e.shiftKey && e.key === 'D') {\n e.preventDefault();\n enabled = !enabled;\n if (enabled) {\n applyDarkMode();\n console.log('[Universal Dark Mode] Enabled');\n } else {\n removeDarkMode();\n console.log('[Universal Dark Mode] Disabled');\n }\n }\n });\n \n // Apply on load\n applyDarkMode();\n \n // Re-apply on dynamic content\n var observer = new MutationObserver(function(mutations) {\n if (enabled && !document.getElementById('universal-dark-mode-style')) {\n applyDarkMode();\n }\n });\n observer.observe(document.head, { childList: true });\n \n console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle');\n})();", "Universal Dark Mode"); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })();
Skip to content

Latest commit

History

23 Commits

Folders and files

NameName
Last commit message
Last commit date

Repository files navigation

NimbleAPI logo
API route explorer and navigator for Neovim

Browse routes. Jump to handlers. Navigate your API.


A Neovim plugin for exploring, navigating, and testing API applications. Browse routes in a sidebar explorer, jump to handlers via fuzzy picker, and see CodeLens annotations linking test client calls to their route definitions. Works across multiple web frameworks with a pluggable provider system.

Supported Frameworks

FrameworkLanguageStatus
FastAPI🐍 Python💚 Supported
Spring / Spring Boot☕ Java💚 Supported
Gin / Echo / Chi / http/net🐹 Go💚 Supported
Express.jsJavaScript / TypeScript💚 Supported
Axum🦀 Rust🐢🐢🐢 Planned
Ruby on Rails💎 Ruby🐢🐢🐢 Planned

Features

  • Route Explorer -- sidebar listing all HTTP routes grouped by source file, with jump-to-definition
  • Fuzzy Picker -- searchable route list via Telescope, Snacks.nvim, or vim.ui.select
  • CodeLens Annotations -- virtual text on test client calls linking them to their route handler
  • Auto-Refresh -- debounced file watcher refreshes routes on save
  • Smart Discovery -- auto-detects framework and app entry point from project files
  • Provider System -- pluggable architecture makes adding new frameworks straightforward

Picker

picker

Explorer

explorer

Requirements

Installation

{
"mrpbennett/nimbleapi.nvim",
cmd="NimbleAPI",
dependencies= {
"nvim-treesitter/nvim-treesitter",
-- Optional: HTTP client for testing routes-- "mistweaverco/kulala.nvim",
},
opts= {},
}

Configuration

All options below are shown with their defaults. Pass only what you want to change:

require("nimbleapi").setup({
provider=nil, -- auto-detect; override: "fastapi", "spring"explorer= {
position="right", -- "left" or "right"width=40,
icons=true, -- requires a Nerd Font
},
picker= {
provider=nil, -- "telescope", "snacks", or "builtin" (nil = auto-detect)
},
keymaps= {
toggle="<leader>Nt", -- toggle explorer sidebarpick="<leader>Np", -- open route pickerrefresh="<leader>Nr", -- refresh route cachecodelens="<leader>Nc", -- toggle codelenstest="<leader>Ne", -- test route under cursor-- Kulala keymaps (buffer-local on .http files, requires kulala.nvim)http_run="<leader>Ns", -- send requesthttp_replay="<leader>NR", -- replay last requesthttp_inspect="<leader>Ni", -- inspect current requesthttp_env="<leader>NE", -- set environment
},
codelens= {
enabled=true,
test_patterns= { "test_*.py", "*_test.py", "tests/**/*.py" },
},
watch= {
enabled=true,
debounce_ms=200,
},
})

Usage

Commands

All commands are available under the :NimbleAPI prefix:

CommandDescription
:NimbleAPI toggleToggle the explorer sidebar
:NimbleAPI pickOpen the route picker
:NimbleAPI refreshRefresh the route cache
:NimbleAPI codelensToggle CodeLens annotations
:NimbleAPI testOpen HTTP test buffer for route under cursor
:NimbleAPI infoShow provider status and diagnostics

Default Keymaps

All keymaps are configurable. Set any keymap to false to disable it.

KeymapActionScope
<leader>NtToggle explorerGlobal
<leader>NpOpen pickerGlobal
<leader>NrRefresh routesGlobal
<leader>NcToggle CodeLensGlobal
<leader>NeTest route under cursorGlobal

Kulala HTTP Keymaps

When kulala.nvim is installed, these keymaps are automatically bound buffer-locally in .http files. They are only active in HTTP buffers and won't pollute your normal keymap space.

KeymapAction
<leader>NsSend request
<leader>NRReplay last request
<leader>NiInspect current request
<leader>NESet environment

All keymaps can be disabled individually by setting them to false in your config.

Explorer Sidebar

The explorer groups routes by source file. The main app file appears first, followed by router files alphabetically. When your active buffer contains routes, the explorer automatically highlights that context.

 NimbleAPI (main.py)
──────────────────────────────────────
main.py
GET / -> root()
GET /health -> health_check()
routers/items.py
GET /items -> get_all_items()
POST /items -> create_item()
GET /items/{id} -> get_item()
PUT /items/{id} -> update_item()
DELETE /items/{id} -> delete_item()

Pressing <CR> or o on a file header jumps to that file. Pressing it on a route line jumps to the handler definition.

Explorer Buffer Keymaps

KeyAction
<CR> / oJump to route or file
sOpen in horizontal split
vOpen in vertical split
rRefresh routes
qClose the sidebar

CodeLens Annotations

When CodeLens is enabled and you open a test file matching one of the configured patterns, virtual text annotations appear on test client calls showing the matched handler:

client.get("/users/123") -> get_user() app/routers/users.py:15

Press gd on an annotated line to jump directly to the route definition.

App Discovery

FastAPI (Python)

The plugin locates your FastAPI application in this order:

  1. pyproject.toml -- reads the [tool.fastapi] section for an app key
  2. Heuristic scan -- searches Python files for FastAPI() constructor calls, preferring shallower paths

Spring / Spring Boot (Java)

  1. Dependency detection -- looks for spring-boot-starter-web, spring-boot-starter-webflux, spring-webmvc, or spring-web in pom.xml or build.gradle
  2. Controller scan -- falls back to scanning for @RestController or @Controller annotations
  3. Entry point -- resolves from @SpringBootApplication class, or the first controller found

Highlight Groups

All highlights ship with sensible defaults and can be overridden in your colorscheme:

GroupDefault
NimbleApiMethodGETGreen, bold
NimbleApiMethodPOSTBlue, bold
NimbleApiMethodPUTYellow, bold
NimbleApiMethodPATCHOrange, bold
NimbleApiMethodDELETERed, bold
NimbleApiMethodOPTIONSPurple, bold
NimbleApiMethodHEADCyan, bold
NimbleApiMethodTRACEGray, bold
NimbleApiMethodWEBSOCKETTeal, bold
NimbleApiTitleOrange, bold
NimbleApiRouterPurple, italic
NimbleApiPathLight gray
NimbleApiFuncCyan

Diagnostics

Run :NimbleAPI info to see a summary of provider status, detection results, and any issues. This is the first place to look when the plugin does not detect your project or a framework is not recognized.

Contributing

Contributions are welcome. The plugin uses a provider pattern that makes adding new framework support straightforward. Each provider lives in its own file under lua/nimbleapi/providers/ and implements a standard interface for detection, route extraction, and app discovery. Corresponding Tree-sitter queries go in queries/<language>/.

See CLAUDE.md at the project root for full architecture documentation, the provider interface spec, and a checklist of files to touch when adding a new framework.

License

MIT

About

Inspired by the FastAPI plugin for VSC, API route explorer and tester for neovim

Topics

Resources

Stars

2 stars

Watchers

0 watching

Forks

Releases

Contributors

Languages