A Neovim plugin for interacting with Buildkite CI/CD pipelines directly from your editor.
- 🚀 View build status for current git branch
- 🔧 Configure multiple Buildkite organizations with easy switching
- 📊 List recent builds for any branch
- 🌐 Open builds in browser
- 🔄 Rebuild failed builds with instant status updates
- ⚙️ Per-project pipeline configuration
- 🎯 Auto-detect pipeline based on git repository
- 📱 Statusline integration (lualine, etc.)
- ⌨️ Customizable keymaps
- 🔍 Built-in debugging tools
- Neovim >= 0.7.0
- plenary.nvim
- Buildkite API token(s)
Basic Setup:
{
"mcncl/buildkite.nvim",
dependencies = { "nvim-lua/plenary.nvim" },
config = function()
require("buildkite").setup()
end,
}
Version Pinning:
{
"mcncl/buildkite.nvim",
version = "*", -- Use latest release (recommended for stability)
-- version = "v0.1.0", -- Pin to specific version
dependencies = { "nvim-lua/plenary.nvim" },
config = function()
require("buildkite").setup()
end,
}
Note on Versions:
- No
version
specified = latest commit on main branch (bleeding edge)version = "*"
= latest stable release (recommended)version = "v0.1.0"
= specific version (maximum stability)
Advanced Setup with Lazy Loading and Custom Keys:
{
"mcncl/buildkite.nvim",
version = "*", -- Use latest release (recommended)
dependencies = { "nvim-lua/plenary.nvim" },
cmd = { "Buildkite" }, -- Load only when :Buildkite command is used
keys = { -- Load when these keys are pressed
{ "<leader>bc", function() require("buildkite.commands").show_current_build() end, desc = "Current build" },
{ "<leader>bl", function() require("buildkite.commands").show_builds() end, desc = "List builds" },
{ "<leader>bo", function() require("buildkite.commands").open_build_url() end, desc = "Open build" },
{ "<leader>br", function() require("buildkite.commands").rebuild_current_build() end, desc = "Rebuild build" },
{ "<leader>bp", function() require("buildkite.commands").set_pipeline() end, desc = "Set pipeline" },
{ "<leader>bs", function() require("buildkite.commands").switch_organization() end, desc = "Switch org" },
{ "<leader>bbs", function() require("buildkite.commands").set_branch() end, desc = "Set branch" },
{ "<leader>bbu", function() require("buildkite.commands").unset_branch() end, desc = "Unset branch" },
{ "<leader>bbi", function() require("buildkite.commands").show_branch_info() end, desc = "Branch info" },
},
config = function()
require("buildkite").setup({
organizations = {
["my-company"] = {
token = vim.env.BUILDKITE_TOKEN,
},
["client-company"] = {
token = vim.env.BUILDKITE_TOKEN_CLIENT,
repositories = {"client-app", "client-api"},
},
},
current_organization = "my-company",
keymaps = { enabled = false }, -- Using custom keys above
auto_setup = { enabled = true, suggest_pipeline = true },
})
end,
}
Note: Lazy loading improves startup time by only loading the plugin when needed. The statusline integration will still work automatically once loaded.
use {
"mcncl/buildkite.nvim",
requires = { "nvim-lua/plenary.nvim" },
tag = "*", -- Use latest release (recommended)
-- tag = "v0.1.0", -- Pin to specific version
config = function()
require("buildkite").setup()
end,
}
Plug 'nvim-lua/plenary.nvim'
Plug 'mcncl/buildkite.nvim', { 'tag': '*' } " Latest release
" Plug 'mcncl/buildkite.nvim', { 'tag': 'v0.1.0' } " Specific version
- Go to Buildkite Personal Access Tokens
- Click "New API Access Token"
- Give it a name (e.g., "Neovim Plugin")
- Select the following scopes:
read_builds
read_pipelines
read_organizations
write_builds
(optional, for rebuilding)
- Click "Create Token"
- Copy the token for use in configuration
💡 Version Tip: For stability, pin to a release version in your plugin manager:
version = "*"
(latest release) orversion = "v0.1.0"
(specific version).
-
Add your first organization:
:Buildkite org add
Enter your organization name and API token. This will be set as your current organization.
-
Set up a pipeline for your project:
:Buildkite pipeline set
The plugin will fetch your pipelines and try to auto-detect the right one based on your git repository.
-
Check your current build:
:Buildkite build current
That's it! The plugin will remember your organization and pipeline settings per project.
The plugin can be configured during setup or will use sensible defaults.
require("buildkite").setup({
organizations = {
["my-company"] = {
token = "bkua_your_token_here",
},
},
current_organization = "my-company",
})
require("buildkite").setup({
organizations = {
["my-company"] = {
token = vim.env.BUILDKITE_TOKEN, -- Use environment variable
repositories = {}, -- Optional: filter to specific repos
},
["client-org"] = {
token = vim.env.BUILDKITE_TOKEN_CLIENT,
repositories = {"client-app", "client-api"},
},
},
current_organization = "my-org",
api = {
endpoint = "https://api.buildkite.com/v2",
timeout = 10000,
},
ui = {
icons = {
passed = "✓",
failed = "✗",
running = "●",
scheduled = "○",
canceled = "◎",
skipped = "◌",
blocked = "⏸",
},
},
keymaps = {
enabled = true,
prefix = "<leader>bk",
mappings = {
current_build = "c",
current_pipeline = "cp",
list_builds = "l",
open_build = "o",
rebuild_build = "r",
set_pipeline = "p",
org_list = "ol",
org_switch = "os",
branch_set = "bs",
branch_unset = "bu",
branch_info = "bi",
}
},
auto_setup = {
enabled = true,
suggest_pipeline = true,
},
cache = {
build_duration = 60000, -- Cache build status for 60 seconds (in milliseconds)
}
})
:Buildkite org add " Add a new organization
:Buildkite org remove [name] " Remove an organization
:Buildkite org list " List all organizations
:Buildkite org switch [name] " Switch current organization
:Buildkite org current " Show current organization
:Buildkite pipeline set [name] " Set pipeline for current project
:Buildkite pipeline unset " Remove pipeline for current project
:Buildkite pipeline info " Show current project's pipeline
:Buildkite branch set [name] " Set manual branch override
:Buildkite branch unset " Remove manual branch override
:Buildkite branch info " Show current branch information
:Buildkite build current " Show current branch build status
:Buildkite build list [branch] [n] " List recent builds (default: 10)
:Buildkite build open " Open current build in browser
:Buildkite build refresh " Refresh current build status (clears cache)
:Buildkite build rebuild " Rebuild the most recent build (updates status instantly)
:Buildkite debug config " Show configuration
:Buildkite debug reset " Reset all configuration
With the default keymap prefix <leader>bk
:
<leader>bkc
- Show current build<leader>bkcp
- Show current pipeline<leader>bkl
- List builds<leader>bko
- Open build in browser<leader>bkr
- Rebuild current build<leader>bkp
- Set pipeline<leader>bkol
- List organizations<leader>bkos
- Switch organization<leader>bkbs
- Set branch<leader>bkbu
- Unset branch<leader>bkbi
- Show branch info
You can disable the default keymaps and define your own:
require("buildkite").setup({
keymaps = { enabled = false },
-- ... other config
})
-- Then define your own keymaps
vim.keymap.set('n', '<leader>bc', function() require("buildkite.commands").show_current_build() end, { desc = "Buildkite: Current build" })
vim.keymap.set('n', '<leader>bl', function() require("buildkite.commands").show_builds() end, { desc = "Buildkite: List builds" })
vim.keymap.set('n', '<leader>bs', function() require("buildkite.commands").set_branch() end, { desc = "Buildkite: Set branch" })
vim.keymap.set('n', '<leader>bu', function() require("buildkite.commands").unset_branch() end, { desc = "Buildkite: Unset branch" })
vim.keymap.set('n', '<leader>bi', function() require("buildkite.commands").show_branch_info() end, { desc = "Buildkite: Branch info" })
-- ... add more as needed
Or use them directly in your plugin manager's keys
configuration (see lazy.nvim advanced setup example above).
Since each API token only works with one Buildkite organization, the plugin supports multiple organizations with easy switching:
organizations = {
["work-org"] = {
token = "bkua_work_token_here",
},
["personal-org"] = {
token = "bkua_personal_token_here",
repositories = {"my-project"},
},
},
current_organization = "work-org",
Use :Buildkite org switch
to change between them. All pipeline and build operations use the currently active organization.
The plugin caches build status to avoid excessive API calls that could slow down your editor. By default:
- Build status is cached for 60 seconds
- Cache is per-branch and per-pipeline
- Lualine integration uses cached data (no performance impact)
You can configure the cache duration:
require("buildkite").setup({
cache = {
build_duration = 30000, -- Cache for 30 seconds
},
})
To manually refresh the build status:
:Buildkite build refresh
This clears the cache and fetches fresh data from the Buildkite API.
Add this component to your lualine configuration. The integration is performant thanks to built-in caching:
require('lualine').setup {
sections = {
lualine_c = {
-- ... other components
{
function()
local buildkite = require("buildkite")
local build, err = buildkite.get_current_build()
if build and not err then
local config = buildkite.get_config()
local icon = config.ui.icons[build.state] or "?"
return icon .. " " .. build.state .. " #" .. build.number
elseif err == "Loading..." then
return "⏳ Loading..."
end
return ""
end,
cond = function()
return require("buildkite.git").is_git_repo()
end,
color = function()
local buildkite = require("buildkite")
local build, err = buildkite.get_current_build()
if build and not err then
if build.state == "passed" then
return { fg = "#50fa7b" } -- green
elseif build.state == "failed" then
return { fg = "#ff5555" } -- red
elseif build.state == "running" then
return { fg = "#f1fa8c" } -- yellow
elseif build.state == "scheduled" then
return { fg = "#8be9fd" } -- cyan
elseif build.state == "blocked" then
return { fg = "#ffb86c" } -- orange
elseif build.state == "canceled" then
return { fg = "#6272a4" } -- gray
end
end
return { fg = "#6272a4" } -- gray
end,
},
},
},
}
For other statusline plugins, use the core function (cached automatically):
local buildkite = require("buildkite")
local build, err = buildkite.get_current_build()
if build and not err then
local config = buildkite.get_config()
local icon = config.ui.icons[build.state] or "?"
-- Add icon .. " " .. build.state .. " #" .. build.number to your statusline
end
Note: The get_current_build()
function uses intelligent caching, so it's safe to call frequently in statuslines without performance concerns.
The plugin automatically saves configurations per project in your Neovim data directory:
- Global config:
~/.local/share/nvim/buildkite.nvim/config.json
- Project configs:
~/.local/share/nvim/buildkite.nvim/projects/
Each project gets its own configuration based on the working directory path, including:
- Pipeline configuration (organization and pipeline slug)
- Manual branch override (if set)
By default, the plugin uses your Git branch to determine which Buildkite builds to show. However, you can override this behavior:
Use Cases:
- Working in a non-Git directory but wanting to monitor builds
- Local branch name differs from the Buildkite branch name
- Monitoring a different branch while working on another
- Working in detached HEAD state
Commands:
:Buildkite branch set main " Monitor 'main' branch builds
:Buildkite branch info " Show current effective branch
:Buildkite branch unset " Remove override, use Git branch
The manual branch override is saved per-project, so different projects can have different branch settings.
It's recommended to use environment variables for your API tokens:
export BUILDKITE_TOKEN="bkua_your_token_here"
export BUILDKITE_TOKEN_CLIENT="bkua_client_token_here"
Then in your config:
organizations = {
["my-company"] = {
token = vim.env.BUILDKITE_TOKEN,
},
["client-company"] = {
token = vim.env.BUILDKITE_TOKEN_CLIENT,
},
},
Check if everything is configured correctly:
:checkhealth buildkite
-
"No organizations configured"
- Run
:Buildkite org add
to add your first organization
- Run
-
"No pipeline configured"
- Run
:Buildkite pipeline set
in your project directory
- Run
-
"API request failed"
- Check your API token has the correct scopes
- Verify the organization name is correct
- Check your internet connection and API endpoint availability
-
"Could not determine current git branch"
- Make sure you're in a git repository
- Check that git is available in your PATH
- Use
:Buildkite branch set <branch_name>
to manually specify a branch
Use the debug commands for troubleshooting:
:Buildkite debug config " Show current configuration
Check the Releases page for:
- New features and improvements
- Bug fixes
- Breaking changes
- Migration guides
Contributions are welcome! Please feel free to submit a Pull Request.
MIT License - see LICENSE file for details.