Tai Groot cd2571d3f2 feat: bug fixes, lazy.nvim-style controls, auto-update checking, repo polish
Phase 1 - Bug fixes:
- Fix extmark rendering in text.lua (table vs string hl handling)
- Fix timer leak: WinClosed autocmd now triggers view.close()
- Add GOBIN/GOPATH/~/go/bin awareness to is_installed() and new bin_path()
- Reject update_all() while tasks running (race condition fix)
- Implement _toggle_details with full binary info expansion

Phase 2 - Lazy.nvim-style controls:
- U = Update all, u = update cursor binary
- I = Install all missing, i = install cursor binary
- x = Abort, CR = toggle details, q/Esc = close
- Line-to-binary mapping for cursor-aware actions

Phase 3 - Auto-update checking:
- New checker module with go list/go version -m integration
- auto_check config option (daily/weekly/custom frequency)
- Persistent state in stdpath('data')/glaze/state.json
- :GlazeCheck command for manual checks
- Update indicators in UI (version info + arrows)

Phase 4 - Repo polish:
- MIT LICENSE file
- Doughnut-themed README with badges and Why Glaze? section
- Updated help docs with all new features/keybinds/API
2026-02-19 00:47:19 +00:00

🍩 glaze.nvim

Go + Lazy = Glaze β€” A Mason/Lazy-style manager for Go binaries in Neovim. Charmbracelet-inspired aesthetic. Zero duplication. One source of truth.

Like a fresh doughnut glaze β€” smooth, sweet, and holds everything together.

Lua Neovim Go Required License: MIT

πŸ€” Why Glaze?

Every Go-based Neovim plugin reinvents the wheel: each one ships its own go install wrapper, its own update command, its own version checking.

Glaze stops the madness. Register your binaries once, manage them all from one beautiful UI. Plugin authors get a two-line integration. Users get a single :Glaze command.

✨ Features

  • Centralized binary management β€” Register binaries from any plugin, update them all at once
  • Lazy.nvim-style UI β€” Floating window with progress bars, spinners, and status indicators
  • Cursor-aware keybinds β€” u updates the binary under your cursor, U updates all
  • Parallel installations β€” Configurable concurrency for fast updates
  • Auto-update checking β€” Daily/weekly checks with non-intrusive notifications
  • GOBIN/GOPATH awareness β€” Finds binaries even if not in PATH
  • Detail expansion β€” Press <CR> to see URL, install path, version info
  • Charmbracelet aesthetic β€” Pink/magenta color scheme that matches the Charm toolchain
  • Zero config for dependents β€” Just register and go
  • Callback support β€” Get notified when your binary is updated

πŸ“¦ Installation

Using lazy.nvim:

{
  "taigrr/glaze.nvim",
  config = function()
    require("glaze").setup({})
  end,
}

πŸš€ Quick Start

local glaze = require("glaze")

-- Setup (usually in your plugin config)
glaze.setup({})

-- Register binaries
glaze.register("freeze", "github.com/charmbracelet/freeze")
glaze.register("glow", "github.com/charmbracelet/glow")
glaze.register("mods", "github.com/charmbracelet/mods")

πŸ“– Usage

Commands

Command Description
:Glaze Open the Glaze UI
:GlazeUpdate [name] Update all or specific binary
:GlazeInstall [name] Install missing or specific binary
:GlazeCheck Manually check for available updates

Keybinds (in Glaze UI)

Key Action
U Update ALL binaries
u Update binary under cursor
I Install all missing binaries
i Install binary under cursor
x Abort running tasks
<CR> Toggle details (URL, path, version)
q / <Esc> Close window

πŸ”Œ For Plugin Authors

Register your plugin's binaries as a dependency β€” two lines is all it takes:

-- In your plugin's setup or init:
local ok, glaze = pcall(require, "glaze")
if ok then
  glaze.register("mytool", "github.com/me/mytool", {
    plugin = "myplugin.nvim",
    callback = function(success)
      if success then
        vim.notify("mytool updated!")
      end
    end,
  })
end

Providing Update Commands

You can still expose plugin-specific commands that delegate to Glaze:

vim.api.nvim_create_user_command("MyPluginUpdate", function()
  require("glaze.runner").update({ "mytool" })
end, {})

βš™οΈ Configuration

require("glaze").setup({
  ui = {
    border = "rounded",  -- "none", "single", "double", "rounded", "solid", "shadow"
    size = { width = 0.7, height = 0.8 },  -- Percentage of screen
    icons = {
      pending = "β—‹",
      running = "◐",
      done = "●",
      error = "βœ—",
      binary = "󰆍",
    },
  },
  concurrency = 4,  -- Max parallel installations
  go_cmd = { "go" },  -- Auto-detects goenv if available
  auto_check = {
    enabled = true,      -- Auto-check for updates
    frequency = "daily", -- "daily", "weekly", or hours as number
  },
})

🎨 Highlight Groups

Glaze defines these highlight groups (all prefixed with Glaze):

Group Description
GlazeH1 Main title (pink)
GlazeH2 Section headers
GlazeBinary Binary names
GlazeUrl Module URLs
GlazePlugin Plugin names
GlazeDone Success status
GlazeError Error status
GlazeRunning In-progress status
GlazeProgressDone Progress bar (filled)
GlazeProgressTodo Progress bar (empty)

πŸ“‹ API

local glaze = require("glaze")

-- Registration
glaze.register(name, url, opts?)  -- Register a binary
glaze.unregister(name)            -- Remove a binary
glaze.binaries()                  -- Get all registered binaries

-- Status
glaze.is_installed(name)          -- Check if binary exists (PATH + GOBIN + GOPATH)
glaze.bin_path(name)              -- Get full path to binary
glaze.status(name)                -- "installed", "missing", or "unknown"

-- Runner (for programmatic control)
local runner = require("glaze.runner")
runner.update({ "freeze", "glow" })  -- Update specific binaries
runner.update_all()                  -- Update all
runner.install({ "freeze" })         -- Install specific
runner.install_missing()             -- Install all missing
runner.abort()                       -- Stop all tasks
runner.is_running()                  -- Check if tasks are running
runner.tasks()                       -- Get current task list
runner.stats()                       -- Get { total, done, error, running, pending }

-- Update checker
local checker = require("glaze.checker")
checker.check()                      -- Check for updates (with notifications)
checker.auto_check()                 -- Check only if enough time has passed
checker.get_update_info()            -- Get cached update info

πŸ“„ License

MIT Β© Tai Groot

Languages
Lua 99.5%
Makefile 0.5%