Core Plugins
HUME ships a some plugins under the core: namespace — a plugin and grammar manager, language server support, live git diff, and a few keymap alternatives. None of them load automatically. Nothing runs until you ask for it in your init.scm, so a default HUME is exactly what you see.
There are two ways to bring a plugin in:
(declare-plugin "core:plum") ; lazy — loads the first time you use it
(load-plugin "core:plum") ; eager — loads at startupA plugin's key bindings only exist once its body has run, so a lazily declared plugin needs some other trigger — a command, an event, a language — to fire before you'd press one of its keys. The plugins marked below have no such trigger, so they're loaded eagerly instead. See Plugins for the difference in detail.
core:stdlib
A toolkit of small helpers that other plugins build on, rather than something you use directly. core:git-diff, core:pickers, core:vim-keybind, and core:lsp all depend on it, so declare or load it before them:
(declare-plugin "core:stdlib")Always declare it bare
Don't pass #:commands/#:events/#:languages to core:stdlib's own declare-plugin call — leave it exactly as above. Every plugin that depends on core:stdlib relies on its default activation list; a custom one can leave out a helper a dependent plugin needs, and that dependent plugin will then misbehave instead of failing with a clear error.
If you're writing a plugin yourself, see Plugin API → Standard Library for every command it offers.
core:plum
PLUM — the HUME PLUgin Manager — installs and updates third-party plugins and themes from GitHub, and installs the tree-sitter grammars that power syntax highlighting. Its install and cleanup commands depend on core:stdlib.
(declare-plugin "core:stdlib")
(declare-plugin "core:plum")PLUM never installs anything on its own: the commands below do the work when you run them.
| Command | Effect |
|---|---|
:plum-install-plugins | Install all declared plugins not yet on disk |
:plum-cleanup-plugins | Remove on-disk plugins no longer declared |
:plum-update-plugins | Pull the latest version of every installed third-party plugin |
:plum-list-plugins | Show declared / installed / orphan / missing plugins |
:plum-install-grammar <lang> | Install and compile one grammar |
:plum-list-grammars | Show the grammar catalog and what's installed |
:plum-cleanup-grammars | Remove compiled grammars you no longer need |
:plum-install-theme <user/repo> | Install (or reinstall) a theme repo's themes |
:plum-update-themes | Pull the latest version of every installed theme repo |
:plum-list-themes | Show installed theme repos and the themes each provides |
:plum-remove-theme <user/repo> | Remove an installed theme repo |
plum-ensure-grammars — install a list of grammars not yet compiled — is for init.scm, not the command mode prompt; it takes a list argument.
(call! "plum-ensure-grammars" '("rust" "toml"))Leaving PLUM out only removes these commands. Already-installed plugins, grammars, and themes keep working without it — PLUM is only needed to install new ones. See Syntax Highlighting for the grammar workflow and Configuration for the theme workflow.
core:lsp
Language server support: hover, go-to-definition, references, diagnostics, rename, formatting, code actions, signature help, completions, and inlay hints. It also downloads and manages the servers themselves (:lsp-install, :lsp-uninstall, :lsp-servers), and the running processes (:lsp-status, :lsp-stop, :lsp-restart).
(declare-plugin "core:stdlib")
(declare-plugin "core:lsp")Requires core:stdlib declared or loaded first. core:lsp itself is still declared lazily here — it wakes up on the first buffer with a detected language, or the first :lsp-* command you type, and its key bindings go live at that same moment, before there's a buffer they'd need to act on.
See Language Servers for setup, the full command and key tables, and settings.
core:steel-server
Registers a language server for Scheme buffers (.ss/.scm/.sld) — which includes your own init.scm and plugin files, so you get hover, diagnostics, and completion while editing your HUME config. Requires core:lsp, which provides the editor-side features that make a registered server useful.
(declare-plugin "core:stdlib")
(declare-plugin "core:lsp")
(declare-plugin "core:steel-server")Declared lazily like this, it activates on the first Scheme buffer or the first time you run :steel-server-install. It's registered so HUME's own commands and configuration functions are recognized while you edit init.scm or a plugin file — you won't see unknown-identifier warnings for anything HUME itself provides.
This is a temporary plugin. The underlying server isn't in HUME's regular server catalog yet, so it can't be installed through :lsp-install like other servers. Once it lands upstream, HUME's catalog will pick it up automatically and this plugin will be retired.
| Command | Effect |
|---|---|
:steel-server-install | Install the Scheme language server and register it for Scheme buffers |
Installing requires cargo — install Rust from rustup.rs first. See Language Servers for the general LSP workflow.
core:pickers
Fuzzy file, buffer, and modified-file finders: z f opens a file picker (git-index-backed inside a repo, fd-backed otherwise), z b opens a buffer switcher, z m opens a picker over files with staged or unstaged git changes.
(declare-plugin "core:stdlib")
(load-plugin "core:pickers")Must be loaded eagerly (core:stdlib only needs to be declared or loaded before it) — its keys are the only way to reach its commands, so declared lazily it would have no trigger to ever wake it up. By default the modified-files picker includes untracked files; turn them off with #:config:
(declare-plugin "core:stdlib")
(load-plugin "core:pickers" #:config (hash "untracked" #f))See Fuzzy Finder for the file-source chain, keys, buffer display, and modified-files details.
core:git-diff
Live, VSCode-style inline git diff. As you type, compares the buffer against a git ref (default HEAD) and renders gutter +/-/~ signs, deleted lines as virtual rows, added/changed lines with a background tint, and word-level highlights inside changed lines.
(declare-plugin "core:stdlib")
(declare-plugin "core:git-diff")Requires core:stdlib declared or loaded before it. Declared lazily like this, it wakes on the first buffer opened (signs default on) or the first :toggle-git-signs/:toggle-inline-diff you type.
| Command | Effect |
|---|---|
:toggle-git-signs [ref] | Toggle gutter signs for the current buffer |
:toggle-inline-diff [ref] | Toggle inline rendering (virtual deleted lines, word highlights, background tint) for the current buffer |
Both take an optional git ref, e.g. :toggle-inline-diff HEAD~2. Giving a ref always turns that rendering on and points it at that ref; it's sticky across a later bare toggle off/on. The ref is shared between the two commands. A file git doesn't know about yet (untracked, brand-new, or outside a repo) shows no diff.
Also keeps a "steel:git-branch" statusline element fresh for the focused buffer, e.g. (main) — no config needed, just add it to your own configure-statusline! call (see Statusline → Custom elements). Updates when you switch to a buffer and when you save it; empty for a buffer outside any repo.
No default key bindings — bind them yourself, e.g. (bind-key! 'normal "g Shift-d" "toggle-inline-diff").
Configure with #:config:
(declare-plugin "core:stdlib")
(declare-plugin "core:git-diff"
#:config (hash "signs" #t "inline" #f "ref" "HEAD"))| Key | Type | Default | Effect |
|---|---|---|---|
"signs" | bool | #t | Whether gutter signs start on for a newly opened buffer |
"inline" | bool | #f | Whether inline rendering starts on for a newly opened buffer |
"ref" | string | "HEAD" | The default git ref a buffer diffs against, until overridden per-buffer via the toggle commands |
Inline rendering's background tint and word highlights depend on your theme defining colors for them; HUME's bundled themes do.
core:vim-keybind
Vim muscle memory: $, ^, 0, C and D (change/delete to end of line), Ctrl+6 (alternate buffer, kitty only), and o in Extend mode to swap the selection's ends. It does not bind G — that key is HUME's own prefix (G L/G U/G C, plus G R with core:lsp), and g e already goes to the last line.
(declare-plugin "core:stdlib")
(load-plugin "core:vim-keybind")Must be loaded eagerly (core:stdlib only needs to be declared or loaded before it) — it replaces keys HUME already binds, and most of what it rebinds (goto-line-start, goto-line-end, and the rest) are built-in commands, not plugin commands, so there's no first dispatch to trigger loading. Declared lazily, $/^/0 would keep doing HUME's default thing until something unrelated woke the plugin up.
By default ('smart), C is context-sensitive: on a bare cursor with no count it changes to end of line as in vim, but with a real selection, or any count prefix (e.g. 3C), it runs HUME's own copy-selection-on-next-line, so that command stays fully reachable. Change this with #:config:
(load-plugin "core:vim-keybind" #:config (hash "change-to-eol" 'on))'on always changes to end of line; 'off leaves C alone. core:stdlib is required for every mode, not just 'smart — config validation itself goes through it.
core:helix-surround
Helix-style surround keys: m s wraps the selection, m d deletes a surrounding pair, m r replaces one.
(load-plugin "core:helix-surround")Must be loaded eagerly: it takes over m s — which by default selects a surrounding pair — and removes m w outright, so wrapping lives on m s alone once it's loaded. Declared lazily, m s would silently keep selecting instead of wrapping until something else triggered the plugin.
core:classic-paste
GUI-style paste, if you'd rather not have p choose a source for you: p / P paste the kill ring, Ctrl+V / Ctrl+Shift+V paste the system clipboard (Ctrl+Shift+V needs the kitty protocol).
(load-plugin "core:classic-paste")Must be loaded eagerly — it replaces p/P/Ctrl+V/Ctrl+Shift+V's default behavior, so until it loads p keeps pasting the default way instead of erroring or doing nothing.