Review pull requests and manage issues across GitHub, GitLab, Bitbucket and Jira without leaving your editor.
251
stars
533
commits
Lua
primary language
Sep 6, 2026
updated
Review GitHub, Bitbucket, and GitLab pull requests and manage Jira, GitHub, and GitLab issues without leaving Neovim.
[!CAUTION] Still in early development, will have breaking changes!
---@module "atlas"
{
"emrearmagan/atlas.nvim",
dependencies = {
"nvim-tree/nvim-web-devicons", -- optional but recommended
"MeanderingProgrammer/render-markdown.nvim", -- optional but recommended
"esmuellert/codediff.nvim", -- optional (PullRequest diff)
"sindrets/diffview.nvim", -- optional; or "dlyongemallo/diffview-plus.nvim"
},
-- See Configuration below
---@type AtlasConfig
opts = {},
}
vim.pack.add({
"https://github.com/emrearmagan/atlas.nvim",
})
-- See Configuration below
require("atlas").setup({})
0.10+git and curl on $PATH*.atlassian.net) or Jira Server REST API v2api.bitbucket.org)gh) authenticated with gh auth logingitlab.com or self-hosted), Personal Access Token with api scope[!tip] It's a good idea to run
:checkhealth atlasto see if everything is set up correctly.
Run :Atlas review inside a Git repository to pick one of its open or draft pull requests, or pass a pull-request URL directly. Atlas opens the configured diff viewer.
Or press the configured pulls.open_diff key (gd by default) on a pull request to start a review.
[!NOTE] Alternative viewers: CodeDiff, Diffview, and Diffview-plus can display Atlas comment, task, and local-note overlays, but their integrations rely on plugin internals and may break after upstream changes.
Local notes let you leave something on a diff without posting it to the pull request. Each note is attached to a file and line and can be an ISSUE, SUGGESTION, NOTE, or PRAISE. Diff views mark notes as outdated when their saved line changes.
For scripts, use bin/atlas-notes. Notes added there appear in AtlasDiff, CodeDiff, Diffview, Diffview-plus, and :Atlas notes:
./bin/atlas-notes add \
--target https://github.com/owner/repository/pull/123 \
--file lua/review_queue.lua --line 19 \
--context "local item = queue[index]" \
--type suggestion --body "Should this be a bool?"
My dotfiles include a Pi extension that wraps this script so review agents can list and add notes.
View pipelines and their jobs, inspect their status, and read job logs directly in Atlas. Retry failed pipelines or jobs and cancel work that is still running.
Add project-specific actions to pull requests and issues. Custom actions receive the current item and provider context, making it possible to call local scripts, open repositories in tmux, copy branch names, or connect Atlas to your own tooling.
pulls = {
repo_config = {
paths = {
["your-workspace/*"] = "~/code/repos/*",
},
settings = {},
},
custom_actions = {
{
id = "show_repo_status",
label = "Show repository status",
confirmation = true,
---@param pr PullRequest
---@param ctx AtlasPullsCustomActionContext
---@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
local output = ctx.output("Repository status")
output:write("Checking " .. ctx.repo_path)
output:run({ "git", "status", "--short" }, function(code)
if code ~= 0 then
done(false, "Failed to read repository status")
return
end
done(true, "Repository status loaded")
end, {
cwd = ctx.repo_path,
})
end,
},
},
},
issues = {
custom_actions = {
{
id = "copy_branch_name",
label = "Copy branch name",
---@param issue Issue
---@param ctx AtlasIssuesCustomActionContext
---@param done fun(ok: boolean|nil, message: string|nil)
run = function(issue, ctx, done)
local branch = string.format("%s/%s", issue.key, issue.title:lower():gsub("%s+", "-"))
vim.fn.setreg("+", branch)
done(true, "Copied: " .. branch)
end,
},
},
},
Use ctx.output(title) to show output from a custom action:
output:write("Loading...")
output:run(cmd, on_exit, { cwd = "/repo" })
:Atlas create pr opens a form for the current branch using a configured template or a description generated from its commits. Edit the title and description, choose the target branch and reviewers, set the draft state, and preview the commits and diffstat before submitting.
:Atlas create issue opens a provider-specific form for GitHub, GitLab, or Jira with Markdown descriptions, saved templates, and fields such as labels, assignees, milestones, and Jira issue types.
Open GitHub and GitLab notifications inside Atlas, refresh them, open the related item, and mark notifications as read or done without leaving Neovim.
Turn frequently used GitHub and GitLab searches, Bitbucket repository/project views, or Jira JQL into named shortcuts. Use bookmarks for review queues, recurring project views, and the searches you return to throughout the day.
Bookmarks appear alongside your configured views, keeping important queries one action away.
Star a pull request or issue with * to keep it at the top of lists. Starred items are saved locally and appear in the first bookmark entry.
Atlas comes with its own statusline for key hints, loading progress, and notifications. Keeping it enabled is recommended because most interaction and feedback goes through it.
If you use lualine, disable its statusline for Atlas buffers so it does not replace the Atlas statusline:
require("lualine").setup({
options = {
disabled_filetypes = {
statusline = { "atlas" },
winbar = {},
},
},
})
At some point there will probably an extension for lualine.
{
ui = {
-- Global statusline for Atlas. See the Statusline section below.
statusline = true,
-- "auto", "default", "snacks", or "fzf-lua".
picker = "auto",
-- Make the main Atlas dashboard a listed buffer.
listed_buffer = false,
},
providers = {
---@type AtlasGitHubConfig
github = {
cache_ttl = 300, -- Set to 0 to disable caching.
},
---@type AtlasGitLabConfig
gitlab = {
base_url = "https://gitlab.com",
-- Personal Access Token with `api` scope:
-- https://docs.gitlab.com/ee/user/profile/personal_access_tokens.html
token = vim.env.GITLAB_TOKEN,
cache_ttl = 300, -- Set to 0 to disable caching.
},
---@type AtlasBitbucketConfig
bitbucket = {
user = vim.env.BITBUCKET_USER,
token = vim.env.BITBUCKET_TOKEN,
cache_ttl = 300, -- Set to 0 to disable caching.
},
---@type AtlasJiraConfig
jira = {
base_url = "https://your-site.atlassian.net",
email = "you@example.com", -- Required for basic authentication only.
--- See: https://support.atlassian.com/atlassian-account/docs/manage-api-tokens-for-your-atlassian-account/
token = "your_jira_api_token",
auth_method = "basic", -- "basic" or "bearer", defaults to "basic". If using bearer, set `token` to your API token.
api_type = "cloud", -- either "cloud" or "server", defaults to "cloud". Cloud API is v3, server API is v2
cache_ttl = 300, -- Set to 0 to disable caching.
},
},
-- See Pulls Configuration below.
pulls = { },
-- See Issue Configuration below.
issues = { },
}
:Atlas - Pick a command:Atlas pulls [provider] - Open a pull-request provider dashboard:Atlas issues [provider] - Open an issue provider dashboard:Atlas review [pull-request-url] - Review a pull request with the configured diff viewer:Atlas diff <base>...<head> - Open a Git range in native AtlasDiff:Atlas diff <pull-request-url> - Open a pull request in native AtlasDiff:Atlas create <pr|issue> - Create a pull request or issue:Atlas search [provider] - Search configured pull-request and issue providers:Atlas open <target|.> - Open a provider URL, Jira key, a PR/issue number in the current repository, or the current repository:Atlas notes [target] - Inspect local review notes:Atlas clear [cache|notes|stars] - Clear all Atlas data or only cached data and cloned repositories, local review notes, or starred items:Atlas logs - Toggle Atlas logs:AtlasDiff <base>...<head> - Open a Git range in native AtlasDiff directly:AtlasDiff <pull-request-url> - Open a pull request in native AtlasDiff directlyUse :Atlas pulls [provider] to browse and manage pull requests from GitHub, Bitbucket, and GitLab.
Shared authentication and endpoints are configured in the top-level providers table.
pulls = {
delete_notes = false, -- Delete local PR notes after approval or merge.
default_merge_method = "merge", -- "merge" or "squash".
default_delete_branch = false,
git_transport = "https", -- "https" or "ssh" for Atlas-managed Git remotes.
-- Replaces the built-in Conventional Comments templates.
comment_templates = {
insert_mode = true, -- Enter Insert mode after applying a template.
items = {
{ label = "Suggestion", text = "suggestion: " },
{ label = "Issue", text = "issue: " },
{ label = "Nitpick", text = "nitpick: " },
},
},
diff = {
-- Any command that accepts explicit <base>...<head> Git revisions.
open_cmd = "AtlasDiff", -- default; for example "DiffviewOpen" or "CodeDiff".
show_review_panel = false, -- Set true to show the review panel when a diff opens.
comment_display = "virtual_lines", -- "virtual_lines" or compact "virtual_text" hints.
review_panel = {
height = 10,
},
-- AtlasDiff options; external viewers use their own configuration.
layout = "inline", -- "inline" or "side-by-side".
compact = true, -- Start with only changed hunks and surrounding context visible.
compact_context_lines = 3, -- Context lines shown around hunks in compact mode.
explorer = {
grouped = true, -- Group changed files by directory.
hidden = false,
show_commits = false, -- Set true to show commits below changed files initially.
width = 40,
initial_focus = "explorer", -- "explorer" or "diff".
preview = false, -- Show a file as soon as the explorer cursor moves onto it.
ignore = { ".git/**", ".jj/**" },
},
},
repo_config = {
-- Maps `workspace/repo` to local paths. Used for checkout, diffs, 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
pr_template = ".github/pull_request_template.md", -- optional, defaults to .github/pull_request_template.md
},
},
},
custom_actions = {}, -- See Custom Actions below.
},
pulls = {
---@type AtlasGitHubPullsConfig
github = {
---@type AtlasGitHubViewConfig[]
views = {
{
name = "My PRs",
key = "1",
layout = "plain", -- "compact", "grouped", or "plain"
search = "author:@me sort:updated-desc",
},
{
name = "Team",
key = "2",
layout = "compact",
search = "org:your-org sort:updated-desc",
},
{
name = "Repo",
key = "3",
layout = "grouped",
search = "repo:your-org/your-repo",
},
},
bookmarks = {
key = "S", -- default
label = "Search", -- default
items = {
["Drafts"] = "is:pr is:draft author:@me",
["Recently merged"] = "is:pr is:merged author:@me sort:updated-desc",
["Review requested"] = "is:pr is:open review-requested:@me",
},
},
},
},
pulls = {
---@type AtlasBitbucketPullsConfig
bitbucket = {
---@type AtlasBitbucketViewConfig[]
views = {
{
name = "Me",
key = "M",
layout = "compact", -- "compact", "grouped", or "plain"
targets = {
{ workspace = "your-workspace", repo = "standalone-repo" },
{ workspace = "your-workspace", project = "CORE" },
},
---@param pr PullRequest
---@param ctx { user: PullsUser|nil }
filter = function(pr, ctx)
local user = ctx.user
return pr.author and user and pr.author.id == user.id
end,
},
{
name = "Team",
key = "1",
layout = "grouped",
targets = {
{ workspace = "your-workspace", project = "TEAM" },
},
},
},
bookmarks = {
key = "S", -- default
label = "Search", -- default
items = {
["Atlas"] = {
targets = {
{ workspace = "your-workspace", repo = "atlas" },
{ workspace = "your-workspace", project = "ATLAS" },
},
filter = function(pr)
return pr.state ~= "draft"
end,
},
},
},
},
},
Each Bitbucket target selects one repository with repo, or every repository in a project with its project key. Views and bookmarks can mix both target types and narrow the resulting PRs with filter.
pulls = {
---@type AtlasGitLabPullsConfig
gitlab = {
---@type AtlasGitLabPullsViewConfig[]
views = {
{
name = "Assigned",
key = "1",
layout = "grouped", -- "compact", "grouped", or "plain"
scope = "assigned_to_me",
},
{
name = "Reviewing",
key = "3",
scope = "all",
extra_params = { reviewer_id = "Me" },
},
-- Single project
{
name = "GitLab",
key = "G",
project = "gitlab-org/gitlab",
},
-- Whole group, all projects under it
{
name = "GitLab Org",
key = "O",
group = "gitlab-org",
},
},
bookmarks = {
key = "S", -- default
label = "Search", -- default
items = {
["Reviewing"] = { scope = "all", extra_params = { reviewer_id = "Me" } },
["Created by me"] = { scope = "all", author_username = "me" },
},
},
},
},
Use :Atlas issues [provider] to browse and manage Jira, GitHub, and GitLab issues.
Shared authentication and endpoints are configured in the top-level providers table.
issues = {
max_results = 100,
with_relationships = true, -- Fetch parent/subissue relationships for plain issue tree views.
custom_actions = {}, -- See Custom Actions below.
}
[!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.
issues = {
---@type AtlasJiraIssuesConfig
jira = {
---@type AtlasJiraViewConfig[]
views = {
{
name = "My Board",
key = "M",
layout = "plain",
jql = "project = KAN AND assignee = currentUser() ORDER BY updated DESC",
},
{
name = "Team Board",
key = "T",
layout = "compact",
jql = "project = KAN ORDER BY updated DESC",
},
},
bookmarks = {
key = "J", -- default
label = "JQL", -- default
items = {
["Backlog"] = "project = KAN AND statusCategory != Done AND (sprint IS EMPTY OR sprint NOT IN openSprints()) ORDER BY Rank ASC",
["Next sprint"] = "project = KAN AND sprint in futureSprints() ORDER BY Rank ASC",
["My open"] = "assignee = currentUser() AND statusCategory != Done ORDER BY updated DESC",
},
},
project_config = {
-- The Jira custom field ID used for story points. Defaults to "customfield_10016".
story_points_field = "customfield_10016",
issue_types = {
["Maintenance"] = { icon = "", hl_group = "AtlasTextWarning" },
["Infrastructure"] = { icon = "", hl_group = "AtlasLogInfo" },
},
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" or "table"
},
},
},
},
},
issues = {
---@type AtlasGitHubIssuesConfig
github = {
---@type AtlasGitHubIssuesViewConfig[]
views = {
{
name = "Assigned",
key = "1",
layout = "plain",
search = "assignee:@me is:open",
},
{
name = "Created",
key = "2",
layout = "compact",
search = "author:@me is:open",
},
{
name = "Mentions",
key = "3",
layout = "plain",
search = "mentions:@me is:open",
},
},
bookmarks = {
key = "S", -- default
label = "Search", -- default
items = {
["Bugs"] = "is:issue is:open label:bug",
["Recently closed"] = "is:issue is:closed author:@me sort:updated-desc",
},
},
},
},
issues = {
---@type AtlasGitLabIssuesConfig
gitlab = {
---@type AtlasGitLabIssuesViewConfig[]
views = {
{
name = "Assigned",
key = "1",
scope = "assigned_to_me",
state = "opened",
},
{
name = "Created",
key = "2",
scope = "created_by_me",
state = "opened",
},
{
name = "All open",
key = "3",
scope = "all",
state = "opened",
-- Anything not covered by the explicit fields below can be passed via `extra_params`.
extra_params = { ["not[labels]"] = "wontfix" },
},
},
bookmarks = {
key = "S", -- default
label = "Search", -- default
items = {
["No labels"] = { scope = "all", state = "opened",
extra_params = { ["not[labels]"] = "*" } },
["Closed"] = { scope = "created_by_me", state = "closed" },
},
},
},
},
Atlas emits these User events after the corresponding cleanup or setup has completed:
AtlasUIClosed for the main pulls/issues dashboard.AtlasDiffOpened and AtlasDiffClosed for the native AtlasDiff view.AtlasReviewAttached and AtlasReviewDetached for Atlas review overlays in AtlasDiff, CodeDiff, and Diffview.Set an action to false to disable it, or set it to a list to add aliases.
keymaps = {
ui = {
help = "g?", -- { "g?", "<leader>?" } would add aliases
close = "q", -- false would disable it
next_item = "j",
previous_item = "k",
first_item = "gg",
last_item = "G",
select = "<CR>",
submit = "<C-s>",
delete = "dd",
comments = {
add = { "a", "i" },
reply = "c",
edit = "e",
react = "gr",
},
toggle_panel = "p",
toggle_fold = "za",
toggle_all_folds = "zA",
previous_panel_tab = "<S-Tab>",
next_panel_tab = "<Tab>",
notifications = {
open = "N",
mark_read = "r",
mark_done = "d",
},
toggle_subscription = "gS",
toggle_star = "*",
refresh = "r",
refresh_view = "R",
open_actions = "A",
open_in_browser = "gx",
copy_id = "y",
copy_url = "Y",
show_details = "K",
search = "?",
},
picker = {
next_item = { "<Down>", "<C-n>", "<C-j>" },
previous_item = { "<Up>", "<C-p>", "<C-k>" },
select = { "<CR>", "<C-s>" },
toggle = "<Tab>",
close = { "q", "<Esc>" },
},
issues = {
transition_issue = "gs",
change_assignee = "ga",
change_reporter = "gr",
edit_issue = "ge",
create_issue = "c",
toggle_description_mode = "m",
},
pulls = {
open_diff = "gd",
checkout = "gc",
external_help = "gA", -- Atlas help in external diff viewers
toggle_repo_panel = "o",
toggle_repo_issue_state = "t",
edit_title = "T",
edit_description = "D",
review = {
focus_item = "gd",
approve = "ga",
request_changes = "gr",
submit_review = "gs",
add_task = "<leader>t",
comment_templates = "gT",
find_file = "<leader>ff",
explorer = {
find_file = { "f", "<leader>ff" },
next_file = { "]f", "<Tab>" },
previous_file = { "[f", "<S-Tab>" },
next_unreviewed_file = "]u",
previous_unreviewed_file = "[u",
toggle_grouping = "T",
toggle_file_reviewed = "-",
toggle_commits = "gC",
},
diff = {
toggle_layout = "t",
toggle_compact = "gc",
next_hunk = "]h",
previous_hunk = "[h",
toggle_review_panel = "gR",
toggle_detail_panel = "gD",
toggle_comments = "gH",
next_comment = "]c",
previous_comment = "[c",
next_note = "]n",
previous_note = "[n",
add_comment = "c",
submit_comment = "C",
add_suggestion = "s",
submit_suggestion = "S",
add_note = "<leader>n",
toggle_resolved = "x",
},
},
filters = {
open = "gpo",
merged = "gpm",
declined = "gpd",
},
},
},
Thank you to everyone who has contributed to Atlas! ❤️
Contributions are welcome! If you'd like to contribute, please open an issue or pull request on GitHub. See CONTRIBUTING.md.
MIT License - see LICENSE for details.
Lua
100.0%
Review pull requests and manage issues across GitHub, GitLab, Bitbucket and Jira without leaving your editor.
251
stars
533
commits
Lua
primary language
Sep 6, 2026
updated
Review GitHub, Bitbucket, and GitLab pull requests and manage Jira, GitHub, and GitLab issues without leaving Neovim.
[!CAUTION] Still in early development, will have breaking changes!
---@module "atlas"
{
"emrearmagan/atlas.nvim",
dependencies = {
"nvim-tree/nvim-web-devicons", -- optional but recommended
"MeanderingProgrammer/render-markdown.nvim", -- optional but recommended
"esmuellert/codediff.nvim", -- optional (PullRequest diff)
"sindrets/diffview.nvim", -- optional; or "dlyongemallo/diffview-plus.nvim"
},
-- See Configuration below
---@type AtlasConfig
opts = {},
}
vim.pack.add({
"https://github.com/emrearmagan/atlas.nvim",
})
-- See Configuration below
require("atlas").setup({})
0.10+git and curl on $PATH*.atlassian.net) or Jira Server REST API v2api.bitbucket.org)gh) authenticated with gh auth logingitlab.com or self-hosted), Personal Access Token with api scope[!tip] It's a good idea to run
:checkhealth atlasto see if everything is set up correctly.
Run :Atlas review inside a Git repository to pick one of its open or draft pull requests, or pass a pull-request URL directly. Atlas opens the configured diff viewer.
Or press the configured pulls.open_diff key (gd by default) on a pull request to start a review.
[!NOTE] Alternative viewers: CodeDiff, Diffview, and Diffview-plus can display Atlas comment, task, and local-note overlays, but their integrations rely on plugin internals and may break after upstream changes.
Local notes let you leave something on a diff without posting it to the pull request. Each note is attached to a file and line and can be an ISSUE, SUGGESTION, NOTE, or PRAISE. Diff views mark notes as outdated when their saved line changes.
For scripts, use bin/atlas-notes. Notes added there appear in AtlasDiff, CodeDiff, Diffview, Diffview-plus, and :Atlas notes:
./bin/atlas-notes add \
--target https://github.com/owner/repository/pull/123 \
--file lua/review_queue.lua --line 19 \
--context "local item = queue[index]" \
--type suggestion --body "Should this be a bool?"
My dotfiles include a Pi extension that wraps this script so review agents can list and add notes.
View pipelines and their jobs, inspect their status, and read job logs directly in Atlas. Retry failed pipelines or jobs and cancel work that is still running.
Add project-specific actions to pull requests and issues. Custom actions receive the current item and provider context, making it possible to call local scripts, open repositories in tmux, copy branch names, or connect Atlas to your own tooling.
pulls = {
repo_config = {
paths = {
["your-workspace/*"] = "~/code/repos/*",
},
settings = {},
},
custom_actions = {
{
id = "show_repo_status",
label = "Show repository status",
confirmation = true,
---@param pr PullRequest
---@param ctx AtlasPullsCustomActionContext
---@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
local output = ctx.output("Repository status")
output:write("Checking " .. ctx.repo_path)
output:run({ "git", "status", "--short" }, function(code)
if code ~= 0 then
done(false, "Failed to read repository status")
return
end
done(true, "Repository status loaded")
end, {
cwd = ctx.repo_path,
})
end,
},
},
},
issues = {
custom_actions = {
{
id = "copy_branch_name",
label = "Copy branch name",
---@param issue Issue
---@param ctx AtlasIssuesCustomActionContext
---@param done fun(ok: boolean|nil, message: string|nil)
run = function(issue, ctx, done)
local branch = string.format("%s/%s", issue.key, issue.title:lower():gsub("%s+", "-"))
vim.fn.setreg("+", branch)
done(true, "Copied: " .. branch)
end,
},
},
},
Use ctx.output(title) to show output from a custom action:
output:write("Loading...")
output:run(cmd, on_exit, { cwd = "/repo" })
:Atlas create pr opens a form for the current branch using a configured template or a description generated from its commits. Edit the title and description, choose the target branch and reviewers, set the draft state, and preview the commits and diffstat before submitting.
:Atlas create issue opens a provider-specific form for GitHub, GitLab, or Jira with Markdown descriptions, saved templates, and fields such as labels, assignees, milestones, and Jira issue types.
Open GitHub and GitLab notifications inside Atlas, refresh them, open the related item, and mark notifications as read or done without leaving Neovim.
Turn frequently used GitHub and GitLab searches, Bitbucket repository/project views, or Jira JQL into named shortcuts. Use bookmarks for review queues, recurring project views, and the searches you return to throughout the day.
Bookmarks appear alongside your configured views, keeping important queries one action away.
Star a pull request or issue with * to keep it at the top of lists. Starred items are saved locally and appear in the first bookmark entry.
Atlas comes with its own statusline for key hints, loading progress, and notifications. Keeping it enabled is recommended because most interaction and feedback goes through it.
If you use lualine, disable its statusline for Atlas buffers so it does not replace the Atlas statusline:
require("lualine").setup({
options = {
disabled_filetypes = {
statusline = { "atlas" },
winbar = {},
},
},
})
At some point there will probably an extension for lualine.
{
ui = {
-- Global statusline for Atlas. See the Statusline section below.
statusline = true,
-- "auto", "default", "snacks", or "fzf-lua".
picker = "auto",
-- Make the main Atlas dashboard a listed buffer.
listed_buffer = false,
},
providers = {
---@type AtlasGitHubConfig
github = {
cache_ttl = 300, -- Set to 0 to disable caching.
},
---@type AtlasGitLabConfig
gitlab = {
base_url = "https://gitlab.com",
-- Personal Access Token with `api` scope:
-- https://docs.gitlab.com/ee/user/profile/personal_access_tokens.html
token = vim.env.GITLAB_TOKEN,
cache_ttl = 300, -- Set to 0 to disable caching.
},
---@type AtlasBitbucketConfig
bitbucket = {
user = vim.env.BITBUCKET_USER,
token = vim.env.BITBUCKET_TOKEN,
cache_ttl = 300, -- Set to 0 to disable caching.
},
---@type AtlasJiraConfig
jira = {
base_url = "https://your-site.atlassian.net",
email = "you@example.com", -- Required for basic authentication only.
--- See: https://support.atlassian.com/atlassian-account/docs/manage-api-tokens-for-your-atlassian-account/
token = "your_jira_api_token",
auth_method = "basic", -- "basic" or "bearer", defaults to "basic". If using bearer, set `token` to your API token.
api_type = "cloud", -- either "cloud" or "server", defaults to "cloud". Cloud API is v3, server API is v2
cache_ttl = 300, -- Set to 0 to disable caching.
},
},
-- See Pulls Configuration below.
pulls = { },
-- See Issue Configuration below.
issues = { },
}
:Atlas - Pick a command:Atlas pulls [provider] - Open a pull-request provider dashboard:Atlas issues [provider] - Open an issue provider dashboard:Atlas review [pull-request-url] - Review a pull request with the configured diff viewer:Atlas diff <base>...<head> - Open a Git range in native AtlasDiff:Atlas diff <pull-request-url> - Open a pull request in native AtlasDiff:Atlas create <pr|issue> - Create a pull request or issue:Atlas search [provider] - Search configured pull-request and issue providers:Atlas open <target|.> - Open a provider URL, Jira key, a PR/issue number in the current repository, or the current repository:Atlas notes [target] - Inspect local review notes:Atlas clear [cache|notes|stars] - Clear all Atlas data or only cached data and cloned repositories, local review notes, or starred items:Atlas logs - Toggle Atlas logs:AtlasDiff <base>...<head> - Open a Git range in native AtlasDiff directly:AtlasDiff <pull-request-url> - Open a pull request in native AtlasDiff directlyUse :Atlas pulls [provider] to browse and manage pull requests from GitHub, Bitbucket, and GitLab.
Shared authentication and endpoints are configured in the top-level providers table.
pulls = {
delete_notes = false, -- Delete local PR notes after approval or merge.
default_merge_method = "merge", -- "merge" or "squash".
default_delete_branch = false,
git_transport = "https", -- "https" or "ssh" for Atlas-managed Git remotes.
-- Replaces the built-in Conventional Comments templates.
comment_templates = {
insert_mode = true, -- Enter Insert mode after applying a template.
items = {
{ label = "Suggestion", text = "suggestion: " },
{ label = "Issue", text = "issue: " },
{ label = "Nitpick", text = "nitpick: " },
},
},
diff = {
-- Any command that accepts explicit <base>...<head> Git revisions.
open_cmd = "AtlasDiff", -- default; for example "DiffviewOpen" or "CodeDiff".
show_review_panel = false, -- Set true to show the review panel when a diff opens.
comment_display = "virtual_lines", -- "virtual_lines" or compact "virtual_text" hints.
review_panel = {
height = 10,
},
-- AtlasDiff options; external viewers use their own configuration.
layout = "inline", -- "inline" or "side-by-side".
compact = true, -- Start with only changed hunks and surrounding context visible.
compact_context_lines = 3, -- Context lines shown around hunks in compact mode.
explorer = {
grouped = true, -- Group changed files by directory.
hidden = false,
show_commits = false, -- Set true to show commits below changed files initially.
width = 40,
initial_focus = "explorer", -- "explorer" or "diff".
preview = false, -- Show a file as soon as the explorer cursor moves onto it.
ignore = { ".git/**", ".jj/**" },
},
},
repo_config = {
-- Maps `workspace/repo` to local paths. Used for checkout, diffs, 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
pr_template = ".github/pull_request_template.md", -- optional, defaults to .github/pull_request_template.md
},
},
},
custom_actions = {}, -- See Custom Actions below.
},
pulls = {
---@type AtlasGitHubPullsConfig
github = {
---@type AtlasGitHubViewConfig[]
views = {
{
name = "My PRs",
key = "1",
layout = "plain", -- "compact", "grouped", or "plain"
search = "author:@me sort:updated-desc",
},
{
name = "Team",
key = "2",
layout = "compact",
search = "org:your-org sort:updated-desc",
},
{
name = "Repo",
key = "3",
layout = "grouped",
search = "repo:your-org/your-repo",
},
},
bookmarks = {
key = "S", -- default
label = "Search", -- default
items = {
["Drafts"] = "is:pr is:draft author:@me",
["Recently merged"] = "is:pr is:merged author:@me sort:updated-desc",
["Review requested"] = "is:pr is:open review-requested:@me",
},
},
},
},
pulls = {
---@type AtlasBitbucketPullsConfig
bitbucket = {
---@type AtlasBitbucketViewConfig[]
views = {
{
name = "Me",
key = "M",
layout = "compact", -- "compact", "grouped", or "plain"
targets = {
{ workspace = "your-workspace", repo = "standalone-repo" },
{ workspace = "your-workspace", project = "CORE" },
},
---@param pr PullRequest
---@param ctx { user: PullsUser|nil }
filter = function(pr, ctx)
local user = ctx.user
return pr.author and user and pr.author.id == user.id
end,
},
{
name = "Team",
key = "1",
layout = "grouped",
targets = {
{ workspace = "your-workspace", project = "TEAM" },
},
},
},
bookmarks = {
key = "S", -- default
label = "Search", -- default
items = {
["Atlas"] = {
targets = {
{ workspace = "your-workspace", repo = "atlas" },
{ workspace = "your-workspace", project = "ATLAS" },
},
filter = function(pr)
return pr.state ~= "draft"
end,
},
},
},
},
},
Each Bitbucket target selects one repository with repo, or every repository in a project with its project key. Views and bookmarks can mix both target types and narrow the resulting PRs with filter.
pulls = {
---@type AtlasGitLabPullsConfig
gitlab = {
---@type AtlasGitLabPullsViewConfig[]
views = {
{
name = "Assigned",
key = "1",
layout = "grouped", -- "compact", "grouped", or "plain"
scope = "assigned_to_me",
},
{
name = "Reviewing",
key = "3",
scope = "all",
extra_params = { reviewer_id = "Me" },
},
-- Single project
{
name = "GitLab",
key = "G",
project = "gitlab-org/gitlab",
},
-- Whole group, all projects under it
{
name = "GitLab Org",
key = "O",
group = "gitlab-org",
},
},
bookmarks = {
key = "S", -- default
label = "Search", -- default
items = {
["Reviewing"] = { scope = "all", extra_params = { reviewer_id = "Me" } },
["Created by me"] = { scope = "all", author_username = "me" },
},
},
},
},
Use :Atlas issues [provider] to browse and manage Jira, GitHub, and GitLab issues.
Shared authentication and endpoints are configured in the top-level providers table.
issues = {
max_results = 100,
with_relationships = true, -- Fetch parent/subissue relationships for plain issue tree views.
custom_actions = {}, -- See Custom Actions below.
}
[!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.
issues = {
---@type AtlasJiraIssuesConfig
jira = {
---@type AtlasJiraViewConfig[]
views = {
{
name = "My Board",
key = "M",
layout = "plain",
jql = "project = KAN AND assignee = currentUser() ORDER BY updated DESC",
},
{
name = "Team Board",
key = "T",
layout = "compact",
jql = "project = KAN ORDER BY updated DESC",
},
},
bookmarks = {
key = "J", -- default
label = "JQL", -- default
items = {
["Backlog"] = "project = KAN AND statusCategory != Done AND (sprint IS EMPTY OR sprint NOT IN openSprints()) ORDER BY Rank ASC",
["Next sprint"] = "project = KAN AND sprint in futureSprints() ORDER BY Rank ASC",
["My open"] = "assignee = currentUser() AND statusCategory != Done ORDER BY updated DESC",
},
},
project_config = {
-- The Jira custom field ID used for story points. Defaults to "customfield_10016".
story_points_field = "customfield_10016",
issue_types = {
["Maintenance"] = { icon = "", hl_group = "AtlasTextWarning" },
["Infrastructure"] = { icon = "", hl_group = "AtlasLogInfo" },
},
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" or "table"
},
},
},
},
},
issues = {
---@type AtlasGitHubIssuesConfig
github = {
---@type AtlasGitHubIssuesViewConfig[]
views = {
{
name = "Assigned",
key = "1",
layout = "plain",
search = "assignee:@me is:open",
},
{
name = "Created",
key = "2",
layout = "compact",
search = "author:@me is:open",
},
{
name = "Mentions",
key = "3",
layout = "plain",
search = "mentions:@me is:open",
},
},
bookmarks = {
key = "S", -- default
label = "Search", -- default
items = {
["Bugs"] = "is:issue is:open label:bug",
["Recently closed"] = "is:issue is:closed author:@me sort:updated-desc",
},
},
},
},
issues = {
---@type AtlasGitLabIssuesConfig
gitlab = {
---@type AtlasGitLabIssuesViewConfig[]
views = {
{
name = "Assigned",
key = "1",
scope = "assigned_to_me",
state = "opened",
},
{
name = "Created",
key = "2",
scope = "created_by_me",
state = "opened",
},
{
name = "All open",
key = "3",
scope = "all",
state = "opened",
-- Anything not covered by the explicit fields below can be passed via `extra_params`.
extra_params = { ["not[labels]"] = "wontfix" },
},
},
bookmarks = {
key = "S", -- default
label = "Search", -- default
items = {
["No labels"] = { scope = "all", state = "opened",
extra_params = { ["not[labels]"] = "*" } },
["Closed"] = { scope = "created_by_me", state = "closed" },
},
},
},
},
Atlas emits these User events after the corresponding cleanup or setup has completed:
AtlasUIClosed for the main pulls/issues dashboard.AtlasDiffOpened and AtlasDiffClosed for the native AtlasDiff view.AtlasReviewAttached and AtlasReviewDetached for Atlas review overlays in AtlasDiff, CodeDiff, and Diffview.Set an action to false to disable it, or set it to a list to add aliases.
keymaps = {
ui = {
help = "g?", -- { "g?", "<leader>?" } would add aliases
close = "q", -- false would disable it
next_item = "j",
previous_item = "k",
first_item = "gg",
last_item = "G",
select = "<CR>",
submit = "<C-s>",
delete = "dd",
comments = {
add = { "a", "i" },
reply = "c",
edit = "e",
react = "gr",
},
toggle_panel = "p",
toggle_fold = "za",
toggle_all_folds = "zA",
previous_panel_tab = "<S-Tab>",
next_panel_tab = "<Tab>",
notifications = {
open = "N",
mark_read = "r",
mark_done = "d",
},
toggle_subscription = "gS",
toggle_star = "*",
refresh = "r",
refresh_view = "R",
open_actions = "A",
open_in_browser = "gx",
copy_id = "y",
copy_url = "Y",
show_details = "K",
search = "?",
},
picker = {
next_item = { "<Down>", "<C-n>", "<C-j>" },
previous_item = { "<Up>", "<C-p>", "<C-k>" },
select = { "<CR>", "<C-s>" },
toggle = "<Tab>",
close = { "q", "<Esc>" },
},
issues = {
transition_issue = "gs",
change_assignee = "ga",
change_reporter = "gr",
edit_issue = "ge",
create_issue = "c",
toggle_description_mode = "m",
},
pulls = {
open_diff = "gd",
checkout = "gc",
external_help = "gA", -- Atlas help in external diff viewers
toggle_repo_panel = "o",
toggle_repo_issue_state = "t",
edit_title = "T",
edit_description = "D",
review = {
focus_item = "gd",
approve = "ga",
request_changes = "gr",
submit_review = "gs",
add_task = "<leader>t",
comment_templates = "gT",
find_file = "<leader>ff",
explorer = {
find_file = { "f", "<leader>ff" },
next_file = { "]f", "<Tab>" },
previous_file = { "[f", "<S-Tab>" },
next_unreviewed_file = "]u",
previous_unreviewed_file = "[u",
toggle_grouping = "T",
toggle_file_reviewed = "-",
toggle_commits = "gC",
},
diff = {
toggle_layout = "t",
toggle_compact = "gc",
next_hunk = "]h",
previous_hunk = "[h",
toggle_review_panel = "gR",
toggle_detail_panel = "gD",
toggle_comments = "gH",
next_comment = "]c",
previous_comment = "[c",
next_note = "]n",
previous_note = "[n",
add_comment = "c",
submit_comment = "C",
add_suggestion = "s",
submit_suggestion = "S",
add_note = "<leader>n",
toggle_resolved = "x",
},
},
filters = {
open = "gpo",
merged = "gpm",
declined = "gpd",
},
},
},
Thank you to everyone who has contributed to Atlas! ❤️
Contributions are welcome! If you'd like to contribute, please open an issue or pull request on GitHub. See CONTRIBUTING.md.
MIT License - see LICENSE for details.
Lua
100.0%