See status of ci/cd pipeline runs directly in neovim. Currently supports GitHub Actions and GitLab CI.
Lua
184
193 commits
updated Jul 22, 2026
The pipeline.nvim plugin for Neovim allows developers to easily manage and dispatch their CI/CD Pipelines, like GitHub Actions or Gitlab CI, directly from within the editor.
workflow_dispatchorigin + upstream)Either have the cli yq installed or:
Using lazy.nvim
{
'topaxi/pipeline.nvim',
keys = {
{ '<leader>ci', '<cmd>Pipeline<cr>', desc = 'Open pipeline.nvim' },
},
-- optional, you can also install and use `yq` instead.
build = 'make',
---@type pipeline.Config
opts = {},
},
Define a GITHUB_TOKEN variable in your environment.
Alternatively, if the gh cli is installed and authenticated via gh auth login, the token will be sourced from it automatically.
Define a GITLAB_TOKEN variable in your environment.
Alternatively, if the glab cli is installed and authenticated via glab auth login, the token will be sourced from it automatically.
:Pipeline or :Pipeline toggle toggles the pipeline.nvim split:Pipeline open opens the pipeline.nvim split:Pipeline close closes the pipeline.nvim split:Pipeline remote opens a picker to switch the active remoteThe following keybindings are provided by the plugin:
q - closes the pipeline.nvim the splitgp - open the pipeline below the cursor on GitHubgr - open the run below the cursor on GitHubgj - open the job of the workflow run below the cursor on GitHubgR - switch the active remoted - dispatch a new run for the workflow below the cursor on GitHubThe default options (as defined in lua/config.lua)
{
--- The browser executable path to open workflow runs/jobs in
browser = nil,
--- Interval to refresh in seconds
refresh_interval = 10,
--- How much workflow runs and jobs should be indented
indent = 2,
providers = {
github = {
default_host = 'github.com',
--- Mapping of names that should be renamed to resolvable hostnames
--- names are something that you've used as a repository url,
--- that can't be resolved by this plugin, like aliases from ssh config
--- for example to resolve "gh" to "github.com"
--- ```lua
--- resolve_host = function(host)
--- if host == "gh" then
--- return "github.com"
--- end
--- end
--- ```
--- Return nil to fallback to the default_host
---@param host string
---@return string|nil
resolve_host = function(host)
return host
end,
},
gitlab = {
default_host = 'gitlab.com',
--- Mapping of names that should be renamed to resolvable hostnames
--- names are something that you've used as a repository url,
--- that can't be resolved by this plugin, like aliases from ssh config
--- for example to resolve "gl" to "gitlab.com"
--- ```lua
--- resolve_host = function(host)
--- if host == "gl" then
--- return "gitlab.com"
--- end
--- end
--- ```
--- Return nil to fallback to the default_host
---@param host string
---@return string|nil
resolve_host = function(host)
return host
end,
},
},
--- Allowed hosts to fetch data from, github.com is always allowed
allowed_hosts = {},
--- Configure which branch to use to dispatch workflow
--- set to "default" to use the repository default branch
--- set to "current" to use the branch you're currently checked out
--- set to any valid branch name to use that branch
--- @type string
dispatch_branch = "default",
icons = {
workflow_dispatch = '⚡️',
conclusion = {
success = '✓',
failure = 'X',
startup_failure = 'X',
cancelled = '⊘',
skipped = '◌',
},
status = {
unknown = '?',
pending = '○',
queued = '○',
requested = '○',
waiting = '○',
in_progress = '●',
},
},
highlights = {
PipelineError = { link = 'DiagnosticError' },
PipelineRunIconSuccess = { link = 'DiagnosticOk' },
PipelineRunIconFailure = { link = 'DiagnosticError' },
PipelineRunIconStartup_failure = { link = 'DiagnosticError' },
PipelineRunIconPending = { link = 'DiagnosticWarn' },
PipelineRunIconRequested = { link = 'DiagnosticWarn' },
PipelineRunIconWaiting = { link = 'DiagnosticWarn' },
PipelineRunIconIn_progress = { link = 'DiagnosticWarn' },
PipelineRunIconCancelled = { link = 'Comment' },
PipelineRunIconSkipped = { link = 'Comment' },
PipelineRunCancelled = { link = 'Comment' },
PipelineRunSkipped = { link = 'Comment' },
PipelineJobCancelled = { link = 'Comment' },
PipelineJobSkipped = { link = 'Comment' },
PipelineStepCancelled = { link = 'Comment' },
PipelineStepSkipped = { link = 'Comment' },
},
split = {
relative = 'editor',
position = 'right',
size = 60,
win_options = {
wrap = false,
number = false,
foldlevel = nil,
foldcolumn = '0',
cursorcolumn = false,
signcolumn = 'no',
},
},
}
require('lualine').setup({
sections = {
lualine_a = {
{ 'pipeline' },
},
}
})
or with options:
require('lualine').setup({
sections = {
lualine_a = {
-- with default options
{ 'pipeline', icon = '' },
},
}
})
Lua
98.1%
Makefile
1.2%
See status of ci/cd pipeline runs directly in neovim. Currently supports GitHub Actions and GitLab CI.
Lua
184
193 commits
updated Jul 22, 2026
The pipeline.nvim plugin for Neovim allows developers to easily manage and dispatch their CI/CD Pipelines, like GitHub Actions or Gitlab CI, directly from within the editor.
workflow_dispatchorigin + upstream)Either have the cli yq installed or:
Using lazy.nvim
{
'topaxi/pipeline.nvim',
keys = {
{ '<leader>ci', '<cmd>Pipeline<cr>', desc = 'Open pipeline.nvim' },
},
-- optional, you can also install and use `yq` instead.
build = 'make',
---@type pipeline.Config
opts = {},
},
Define a GITHUB_TOKEN variable in your environment.
Alternatively, if the gh cli is installed and authenticated via gh auth login, the token will be sourced from it automatically.
Define a GITLAB_TOKEN variable in your environment.
Alternatively, if the glab cli is installed and authenticated via glab auth login, the token will be sourced from it automatically.
:Pipeline or :Pipeline toggle toggles the pipeline.nvim split:Pipeline open opens the pipeline.nvim split:Pipeline close closes the pipeline.nvim split:Pipeline remote opens a picker to switch the active remoteThe following keybindings are provided by the plugin:
q - closes the pipeline.nvim the splitgp - open the pipeline below the cursor on GitHubgr - open the run below the cursor on GitHubgj - open the job of the workflow run below the cursor on GitHubgR - switch the active remoted - dispatch a new run for the workflow below the cursor on GitHubThe default options (as defined in lua/config.lua)
{
--- The browser executable path to open workflow runs/jobs in
browser = nil,
--- Interval to refresh in seconds
refresh_interval = 10,
--- How much workflow runs and jobs should be indented
indent = 2,
providers = {
github = {
default_host = 'github.com',
--- Mapping of names that should be renamed to resolvable hostnames
--- names are something that you've used as a repository url,
--- that can't be resolved by this plugin, like aliases from ssh config
--- for example to resolve "gh" to "github.com"
--- ```lua
--- resolve_host = function(host)
--- if host == "gh" then
--- return "github.com"
--- end
--- end
--- ```
--- Return nil to fallback to the default_host
---@param host string
---@return string|nil
resolve_host = function(host)
return host
end,
},
gitlab = {
default_host = 'gitlab.com',
--- Mapping of names that should be renamed to resolvable hostnames
--- names are something that you've used as a repository url,
--- that can't be resolved by this plugin, like aliases from ssh config
--- for example to resolve "gl" to "gitlab.com"
--- ```lua
--- resolve_host = function(host)
--- if host == "gl" then
--- return "gitlab.com"
--- end
--- end
--- ```
--- Return nil to fallback to the default_host
---@param host string
---@return string|nil
resolve_host = function(host)
return host
end,
},
},
--- Allowed hosts to fetch data from, github.com is always allowed
allowed_hosts = {},
--- Configure which branch to use to dispatch workflow
--- set to "default" to use the repository default branch
--- set to "current" to use the branch you're currently checked out
--- set to any valid branch name to use that branch
--- @type string
dispatch_branch = "default",
icons = {
workflow_dispatch = '⚡️',
conclusion = {
success = '✓',
failure = 'X',
startup_failure = 'X',
cancelled = '⊘',
skipped = '◌',
},
status = {
unknown = '?',
pending = '○',
queued = '○',
requested = '○',
waiting = '○',
in_progress = '●',
},
},
highlights = {
PipelineError = { link = 'DiagnosticError' },
PipelineRunIconSuccess = { link = 'DiagnosticOk' },
PipelineRunIconFailure = { link = 'DiagnosticError' },
PipelineRunIconStartup_failure = { link = 'DiagnosticError' },
PipelineRunIconPending = { link = 'DiagnosticWarn' },
PipelineRunIconRequested = { link = 'DiagnosticWarn' },
PipelineRunIconWaiting = { link = 'DiagnosticWarn' },
PipelineRunIconIn_progress = { link = 'DiagnosticWarn' },
PipelineRunIconCancelled = { link = 'Comment' },
PipelineRunIconSkipped = { link = 'Comment' },
PipelineRunCancelled = { link = 'Comment' },
PipelineRunSkipped = { link = 'Comment' },
PipelineJobCancelled = { link = 'Comment' },
PipelineJobSkipped = { link = 'Comment' },
PipelineStepCancelled = { link = 'Comment' },
PipelineStepSkipped = { link = 'Comment' },
},
split = {
relative = 'editor',
position = 'right',
size = 60,
win_options = {
wrap = false,
number = false,
foldlevel = nil,
foldcolumn = '0',
cursorcolumn = false,
signcolumn = 'no',
},
},
}
require('lualine').setup({
sections = {
lualine_a = {
{ 'pipeline' },
},
}
})
or with options:
require('lualine').setup({
sections = {
lualine_a = {
-- with default options
{ 'pipeline', icon = '' },
},
}
})
Lua
98.1%
Makefile
1.2%