unkin-agent 3190b30e97 Abort clean when a plugin spec fails to parse
An unparseable entry dropped out of the wanted set, so clean deleted the
directory and lock entry of a plugin the user still has configured.

Add tests/init_spec.lua covering setup, sync, clean and list.
2026-09-08 23:32:04 +10:00
2026-09-08 23:22:15 +10:00
2026-09-08 23:22:15 +10:00

arti-pack

A Neovim plugin manager that installs plugins from an artifact store instead of git. It downloads tagged upstream source archives through artifactapi and unpacks them into Neovim's native package path — see :h packages.

No git, no submodules, no network access to GitHub from the editor: every plugin arrives as a cached, immutable, tagged artifact from the same proxy that serves RPMs, containers and Terraform providers.

Requirements

  • Neovim 0.10+
  • curl, and unzip (or tar when using ext = 'tar.gz')

Install

arti-pack manages itself least awkwardly as a plain clone into the package path:

git clone https://git.unkin.net/unkin/arti-pack \
  "${XDG_DATA_HOME:-$HOME/.local/share}/nvim/site/pack/arti-pack/start/arti-pack"

Usage

require('arti-pack').setup({
  registry = 'https://artifactapi.k8s.syd1.au.unkin.net/api/v1/remote/github',
  plugins = {
    { 'nvim-lua/plenary.nvim', tag = 'v0.1.4' },
    { 'folke/which-key.nvim',  tag = 'v3.13.3', opt = true },
    { 'folke/tokyonight.nvim', tag = 'v4.10.0', as = 'tokyonight' },
    { 'tpope/vim-fugitive',    tag = 'v3.7',    ext = 'tar.gz' },
  },
})

Every plugin needs an explicit tag — that is the point. Plugins install to stdpath('data')/site/pack/arti-pack/start/<name>, or .../opt/<name> when opt = true.

Spec fields

Field Default Meaning
[1] required owner/repo
tag required Upstream tag, used verbatim in the archive path
opt false Install under opt/ for :packadd instead of start/
as repo name Directory name to install as
ext 'zip' zip or tar.gz
url — Full archive URL, bypassing the registry

Options

Option Default Meaning
registry the estate artifactapi github remote Proxy prefix placed in front of owner/repo
auto_sync true Sync missing and changed plugins on startup
concurrency 4 Plugins downloaded in parallel
timeout 120 Per-download timeout in seconds

Commands

Command Effect
:ArtiPackSync Install missing plugins and update ones whose tag changed
:ArtiPackSync! Reinstall everything, ignoring recorded state
:ArtiPackClean Remove installed plugins no longer in the spec
:ArtiPackList Show every configured plugin and its state

How it resolves an archive

<registry>/<owner>/<repo>/archive/refs/tags/<tag>.<ext>

which for the defaults is

https://artifactapi.k8s.syd1.au.unkin.net/api/v1/remote/github/nvim-lua/plenary.nvim/archive/refs/tags/v0.1.4.zip

Archives are cached under stdpath('cache')/arti-pack, checked for a real zip or gzip magic header before being trusted, and unpacked into a staging directory. Tag archives wrap their contents in a single <repo>-<version> directory, which is stripped on the way in. Installed tags are recorded in stdpath('data')/arti-pack/lock.json, so a sync with nothing to do costs nothing. Helptags are regenerated per plugin after install.

A failed plugin is reported and skipped; the rest of the run continues.

Tests

make test
S
Description
Neovim plugin manager that installs plugins from tagged archives in an HTTP artifact repository into nvim's native package path
Readme 256 KiB
Languages
Lua 97.7%
Makefile 2.3%