A Neovim plugin for managing Bitbucket PRs and Jira issues without leaving your editor.
Caution
Still in early development, will have breaking changes!
Using lazy.nvim
{
"emrearmagan/atlas.nvim",
dependencies = {
"MeanderingProgrammer/render-markdown.nvim", -- optional but recommended (Jira)
"sindrets/diffview.nvim", -- optional (Bitbucket PR diff)
"esmuellert/codediff.nvim", -- optional (Bitbucket PR diff alternative)
},
config = function()
require("atlas").setup({
bitbucket = { }, -- See configuration below
jira = { }, -- See configuration below
})
end,
}Using packer.nvim
use {
"emrearmagan/atlas.nvim",
config = function()
require("atlas").setup({
bitbucket = { }, -- See configuration below
jira = { }, -- See configuration below
})
end
}Tip
It's a good idea to run :checkhealth atlas to see if everything is set up correctly.
- Neovim:
0.10+ - Jira: Jira Cloud REST API v3 (
*.atlassian.net) - Bitbucket: Bitbucket Cloud REST API 2.0 (
api.bitbucket.org)
Note
I have only tested this with my personal and work accounts. If you encounter any issues, please feel free to open an issue. See: https://support.atlassian.com/atlassian-account/docs/manage-api-tokens-for-your-atlassian-account/
:AtlasJira- Open Jira issue picker:AtlasJqlSearch {query}- Search Jira issues with JQL:AtlasBitbucket- Open Bitbucket PR picker:AtlasClearCache- Clear Atlas disk and memory cache:AtlasLogs- Toggle Atlas logs
- Create and Edit issues
- View and edit issues as markdown -> ADF conversion for issue descriptions (experimental)
- Issue panel tabs: overview, comments, history
- Jira actions: transition, change assignee, change reporter, edit title
- Comment workflows (create, reply, edit, delete)
- Search issues
- JQL support and completion
- Support for custom fields
- Create and edit issue templates
- Save JQL queries as custom views
- Save and filter issues
Important
The markdown editor for issue descriptions and comments is still experimental and may not work perfectly in all cases. You can toggle between markdown and ADF view in the overview tab to see the raw ADF content and how it translates to markdown. If you encounter any issues with the markdown editor, please open an issue with details.
return {
"emrearmagan/atlas.nvim",
config = function()
require("atlas").setup({
---@type JiraConfig
jira = {
base_url = "https://your-site.atlassian.net",
email = "you@example.com",
--- See: https://support.atlassian.com/atlassian-account/docs/manage-api-tokens-for-your-atlassian-account/
token = "your_jira_api_token",
cache_ttl = 300,
max_result = 100,
resolve_parent_issues = true,
project_config = {
KAN = {
customfield_10003 = {
name = "Approvers",
format = function(value)
if type(value) ~= "table" or #value == 0 then
return nil -- nil hides the field
end
return table.concat(value, ", ")
end,
hl_group = "AtlasChipActive",
display = "chip", -- "chip" (default) or "table"
},
},
},
---@type JiraViewConfig[]
views = {
{
name = "My Board",
key = "M",
jql = "project = KAN AND assignee = currentUser() ORDER BY updated DESC",
},
{
name = "Team Board",
key = "T",
jql = "project = KAN ORDER BY updated DESC",
},
},
},
})
end,
}Use :AtlasJqlSearch to run JQL directly from command mode. It also supports command-line completion while typing the query.
Examples:
:AtlasJqlSearch project = KAN AND assignee = currentUser() ORDER BY updated DESC
:AtlasJqlSearch summary ~ "login bug"- Multiple Bitbucket views
- PR tabs: overview, activity, comments, commits, files
- PR actions: merge, approve, request changes
- Comment workflows (create, reply, edit, delete)
- Add custom actions to PRs
- Resolve and checkout PR branches locally
- Open PR diff in given command
- View Repository details like branches, tags, commits
- Pagination for API results (PRs, comments, commits, files, activity)
- Switch between open, merged and superseded PRs
- Bulk actions: approve/request changes on multiple PRs at once
- Shows pull request checks
- Support for Bitbucket Server
- Save and filter pull requests
return {
"emrearmagan/atlas.nvim",
config = function()
require("atlas").setup({
---@type BitbucketConfig
bitbucket = {
user = os.getenv("BITBUCKET_USER") or "",
token = os.getenv("BITBUCKET_TOKEN") or "",
cache_ttl = 300,
diff = {
-- Command must support range input: origin/<destination>...origin/<source>
open_cmd = "DiffviewOpen", -- e.g. "DiffviewOpen" or "CodeDiff", defaults to nil.
},
repo_config = {
-- Maps `workspace/repo` to local paths. Used for checkout and custom actions.
paths = {
["your-workspace/*"] = "~/code/repos/*",
["your-workspace/atlas"] = "~/code/atlas",
},
settings = {
["your-workspace/atlas"] = {
readme = "README.md", -- optional, defaults to README.md
},
},
},
custom_actions = {}, -- See Custom Actions below.
---@type BitbucketViewConfig[]
views = {
{
name = "Me",
key = "M",
layout = "compact", -- "compact" or "plain"
repos = {
{ workspace = "your-workspace", repo = "atlas" },
},
---@param pr BitbucketPR
---@param ctx table
filter = function(pr, ctx)
local user = ctx.user or {}
return pr.author and pr.author.account_id == user.account_id
end,
},
{
name = "Team",
key = "O",
layout = "plain", -- "compact" or "plain"
repos = {
{ workspace = "your-workspace", repo = "atlas" },
{ workspace = "your-workspace", repo = "other-repo" },
},
},
},
},
})
end,
}You can add custom PR actions under bitbucket.custom_actions.
Context type:
---@class BitbucketCustomActionContext
---@field repo_path string|nil
---@field pr BitbucketPRExample:
bitbucket = {
repo_config = {
paths = {
["your-workspace/*"] = "~/code/repos/*",
},
settings = {},
},
custom_actions = {
{
id = "open_tmux_window",
label = "Open repo in tmux window",
confirmation = true, -- present a confirmation prompt before running the action
---@param pr BitbucketPR
---@param ctx BitbucketCustomActionContext
---@param done fun(ok: boolean|nil, message: string|nil)
run = function(_, ctx, done)
if not ctx.repo_path then
done(false, "No repo path")
return
end
vim.system({ "tmux", "new-window", "-c", ctx.repo_path }, { text = true }, function(res)
vim.schedule(function()
if res.code ~= 0 then
done(false, "Failed to open tmux window")
return
end
done(true, "Opened tmux window")
end)
end)
end,
},
},
}Set an action to false to disable it, or set it to a list to add aliases.
require("atlas").setup({
keymaps = {
ui = {
toggle_panel = false,
next_panel_tab = { "]", "<Tab>", "gn" },
previous_panel_tab = { "[", "<S-Tab>", "gp" },
},
jira = {
create_issue = "i",
manage_templates = "gT",
},
bitbucket = {
open_diffview = { "go", "gd" },
},
},
})| Context | Key | Action |
|---|---|---|
| Atlas | q |
Close Atlas |
| Atlas | ? |
Toggle help popup |
| Atlas | p |
Toggle detail pane |
| Atlas | <S-Tab> |
Previous panel tab |
| Atlas | <Tab> |
Next panel tab |
| Atlas | K |
Show issue/pr details |
| Atlas | R |
Refresh current view |
| Atlas | r |
Refresh selected issue/pr |
| Atlas | a/i / c / e / d |
Add / reply / edit / delete comment |
| Context | Key | Action |
|---|---|---|
| Jira | A |
Open Jira actions |
| Jira | / |
Search issues |
| Jira | ge |
Edit Issue |
| Jira | gs |
Transition Issue |
| Jira | ga / gr |
Change Assignee and reporter |
| Jira | gt |
Change issue type |
| Jira | gT |
Open template editor |
| Jira | gx |
Open issue/comment in browser |
| Jira | c |
Create issue |
| Jira | y / Y |
Copy issue key / URL |
| Jira | m |
Toggle ADF / markdown view |
| Context | Key | Action |
|---|---|---|
| Bitbucket | A |
Open PR actions |
| Bitbucket | / |
Search repositories |
| Bitbucket | o |
Toggle repository panel |
| Bitbucket | T |
Create new tasks on PR |
| Bitbucket | gc |
Checkout selected PR |
| Bitbucket | gd |
Open selected PR diff |
| Bitbucket | gx |
Open pr/build/comment in browser |
| Bitbucket | y / Y |
Copy PR id / URL |
| Bitbucket (File changes) | za |
Toggle hunk fold |
| Bitbucket (File changes) | ]h / [h |
Next / previous hunk |
Thanks go to these wonderful people (emoji key):
Riza Khan 💻 |
MIT License - see LICENSE for details.