Part 1 (Intro)
I am in the process of moving away from astronvim https://docs.astronvim.com/ to a more minimal neovim configuration. I needed something more native to replace Harpoon https://github.com/ThePrimeagen/harpoon, which is a sort of plugin-based buffer switcher, bookmarker.
I eventually came across this reddit thread that implemented something like what i was searching with native arglist: https://www.reddit.com/r/neovim/comments/1om84w2/persistent_harpoon_with_arglist/. The problem was, since arglist doesn't persist by itself when you close neovim, he implemented his own state management for it. He also considered marks-based replacement but it had other, bigger problems.
An idea came to my mind: doesn’t Neovim’s built-in session management already save and restore the arglist?
So I went digging, found the help page https://neovim.io/doc/user/usr_21.html#_sessions and apparently it does !
A Vim session contains all the information about what you are editing.
This includes things such as the file list, window layout, global variables,
options and other information
AstroNvim uses Resession.nvim https://github.com/stevearc/resession.nvim to manage sessions. I used them in my workflow but sparingly...Honestly, if not for the arglist, I probably would have chosen to not use them at all. Anyways, upon further reading I realized just how simple native session management really is and that I wouldn't need any other extra plugins for my use case.
Part 2 (Sessions)
So I came across this blog post: https://aymanbagabas.com/blog/2023/04/13/simple-vim-session-management.html It implements session management in a hands-off manner. Basically: If you open a directory with nvim, it checks if that directory is a project directory (looks for git file). If it is, it loads the session from ./.nvim/session.vim (if it's there), and on closing saves the session to the same place.
This was fine. I tried it, but soon realized I didn't need this amount of complexity. So I opted for a way simpler setup:
-- #Sessions
-- Save current session to .nvim/session.vim
vim.keymap.set("n", "<leader>ss", function()
vim.cmd("!mkdir -p .nvim")
vim.cmd("mksession! .nvim/session.vim")
print("Session saved!")
end, { desc = "Save current session " })
-- Load session from .nvim/session.vim
vim.keymap.set("n", "<leader>sl", function()
vim.cmd("source .nvim/session.vim")
print("Session loaded")
end, { desc = "Load session" })
-- Save session on exit
vim.api.nvim_create_autocmd("vimleave", {
callback = function(data)
-- only save session if there's a .nvim/session.nvim file
local sessionfile = ".nvim/session.vim"
if vim.fn.filereadable(sessionfile) then
vim.cmd("mksession! " .. sessionfile)
end
end,
})
1 keybinding to save session in ./.nvim/session.vim 1 to load it and 1 autocommand: when you exit Neovim, if a session.vim file already exists, it’s overwritten with the current session state.
Really simple setup that explicitly gives me control when to save my session and when not to. It's way better than what I had back in AstroNvim, where it would auto-save for every directory. And now they're stored in the same project directory, which I like.
Part 3(Arglist)
Now that I had sessions I just needed to add some keybindings to interact with the arglist. For that, this blog post explained everything really well and I based a lot of my keybindings off of it:
https://jkrl.me/vim/2025/05/28/nvim-arglist.html
This is what I ended up with :
-- Show the list
vim.keymap.set("n", "<leader>al", "<C-L><Cmd>args<CR>")
-- Navigate forward / backwards / first / last
vim.keymap.set("n", "[a", '<cmd>exe v:count1 .. "N"<bar>args<cr><esc>')
vim.keymap.set("n", "]a", '<cmd>exe v:count1 .. "n"<bar>args<cr><esc>')
vim.keymap.set("n", "[A", "<cmd>first<bar>args<cr><esc>")
vim.keymap.set("n", "]A", "<cmd>last<bar>args<cr><esc>")
-- Jump to arglist entry 1..6 with Alt+number (and show args)
for i = 1, 6 do
vim.keymap.set("n", ("<M-%d>"):format(i), ("<cmd>argument %d | args<cr><esc>"):format(i), {
desc = ("Arglist: go to %d"):format(i),
silent = true,
})
end
-- Add current buffer to list
vim.keymap.set("n", "<leader>aa", "<cmd>$arge %<bar>argded<bar>args<cr>")
-- Insert current buffer at x position, shift everything to the right
-- Prefix a number before shortcut that will be the x position in which to insert the current buffer
-- If you don't enter any number before the command, insert at position 0
vim.keymap.set("n", "<leader>ai", function()
local count = vim.v.count
vim.cmd(count .. "arge %")
vim.cmd("args")
end)
-- Delete current buffer from list
vim.keymap.set("n", "<leader>ad", "<cmd>argd %<bar>args<cr>")
-- Delete all
vim.keymap.set("n", "<leader>aD", "<cmd>%argd<cr><C-L>")
A lot of it is self-explanatory from the comments. I use alt + number to navigate through my arglist, don't really even need those navigate forward / backward keybindings but whatever.
And I added a simple autocmd from the Reddit post that jumps to your last cursor position when you open a buffer.
-- #go to last loc when opening a buffer
vim.api.nvim_create_autocmd("bufreadpost", {
desc = "go to last edit location when opening a new buffer",
group = vim.api.nvim_create_augroup("last_loc", { clear = true }),
callback = function(event)
local exclude = { "gitcommit" }
local buf = event.buf
if vim.tbl_contains(exclude, vim.bo[buf].filetype) or vim.b[buf].last_loc_flag then
return
end
vim.b[buf].last_loc_flag = true
local mark = vim.api.nvim_buf_get_mark(buf, '"')
local lcount = vim.api.nvim_buf_line_count(buf)
if mark[1] > 0 and mark[1] <= lcount then
pcall(vim.api.nvim_win_set_cursor, 0, mark)
end
end,
})
Really happy with the results. Everything was like 60 lines of code and using native neovim functionality. I replaced a session plugin and harpoon and it works IMO better than what I had previously.