Core plugins

On this page

Core plugins ship with lattice. They are the batteries-included set — prebuilt WebAssembly components that live beside the editor (not compiled into the binary), discovered at boot, and enabled by default. You don't install them, you don't build them, and they work offline with no toolchain. You can turn any of them off.

This is distinct from user plugins, which you declare from a git repo or a local directory and which the editor builds on first boot — see plugins for that (the use-package model).

The list

PluginDefault modeEnable optionWhat it does
auto-pairauto-pair-modeauto-pair.enabled (default true)Auto-closes brackets/quotes; a manual style closes the nearest unmatched opener on one key. Run :help auto-pair.
treesitter-contexttreesitter-context-modetreesitter-context.enabled (default true)Pins the enclosing impl / fn / if above the text once their headers scroll away. Run :help treesitter-context.
projectproject-modeproject.enabled (default true)Choose the project first, then the verb — <leader>pp (or <C-x>pp) picks a project and offers find-file, grep, a shell or Magit in it. Every other project-aware surface roots itself at the buffer you are standing in; this is for the one you are not. Run :help project.

| comment | comment-mode | comment.enabled (default true) | gc toggles line comments — an operator, so gcc does the line, gcap the paragraph, gci{ a block, and gc works over a Visual selection. Run :help comment. |

More core plugins land over time (a git-gutter, a file-tree, …); each appears here with its mode, its <id>.enabled option, and its own options.

How a core plugin loads

  1. Ships prebuilt. A release stages each core plugin's .wasm + plugin.toml into lattice's runtime root — a directory beside the binary, found via a search path ($LATTICE_RUNTIME → the install prefix's share/lattice → next to the executable → the dev workspace's runtime/).
  2. Discovered at boot. The editor scans <runtime>/plugins/ and loads each at the bundled trust tier (pre-granted — no capability prompt).
  3. Enabled by a config gate. A core plugin's manifest names the minor mode it enables by default; the editor auto-registers a bool option <id>.enabled (default true) that turns that mode on. So the plugin is active out of the box, and the mode never forces itself on — you own the switch.

Where core plugins live — and pointing lattice elsewhere

The runtime root is resolved by a search path; the first existing location wins (except $LATTICE_RUNTIME, which always wins if set):

PriorityLocationFor
1$LATTICE_RUNTIME/plugins/An explicit override — you set this.
2<install-prefix>/share/lattice/plugins/Packaged installs (the prefix is baked in at build time via LATTICE_INSTALL_PREFIX).
3<exe-dir>/../share/lattice/plugins/Relocatable tarballs / macOS .app bundles.
4<workspace>/runtime/plugins/Running from a source checkout (cargo run).

To point lattice at a different runtime root, set $LATTICE_RUNTIME:

LATTICE_RUNTIME=/opt/my-lattice-runtime cargo run -p lattice-cli
# core plugins are then discovered under /opt/my-lattice-runtime/plugins/

Why an environment variable, not a config option? Core plugins are discovered and loaded at boot before lattice.toml and init.rs are read — so the location has to be known without loading config first. $LATTICE_RUNTIME (and the build-time LATTICE_INSTALL_PREFIX) are available that early; a config option would be a chicken-and-egg. (The user plugins root is different — it's always ~/.config/lattice/plugins/, honoring $XDG_CONFIG_HOME.)

Turning a core plugin off

Every core plugin has an <id>.enabled option. Turn it off any of three ways:

  • Live, this session: :set auto-pair.enabled=false (toggles the mode off immediately; back on with =true).

  • Statically, in lattice.toml:

    auto-pair.enabled = false
    
  • Programmatically, in init.rs:

    config::set_option("auto-pair.enabled", "false");
    

Disabling the mode leaves the plugin loaded — it just deactivates its mode, so re-enabling is instant. (You cannot un-ship a core plugin from config; if you truly never want it, a future core-plugins.exclude list will cover that.)

Per-buffer toggle. Independently of the enabled gate, the plugin's mode has an auto-generated :auto-pair-mode command — every registered mode gets a :<mode-name> toggle — that flips it on the active buffer only. Use auto-pair.enabled for the editor-wide default; :auto-pair-mode for a one-off buffer.

Each plugin's own manual

A core plugin's detailed documentation — its options, its keys, how to test it — ships inside the plugin, not in this page and not in lattice's binary. Each registers its own :help topic through the help seam, so:

:help auto-pair
:help treesitter-context

That is deliberate, and it is the same rule that applies to any plugin you install yourself: docs travel with the artefact that owns them, so removing a plugin removes its manual and a plugin that failed to load leaves none behind. See plugins for how the seam works if you are writing one.

These are typed, not linked, because a help: link in this page would be a dead link for anyone who removed the plugin — and this page has to stay truthful in that case, since it is the page that explains how to remove them.

For contributors — building core plugins from source

Running from a source checkout, stage the core plugins into the dev runtime root once (and after changing one):

cargo xtask build-core-plugins   # builds plugins/<name>/ → runtime/plugins/<name>/

Then cargo run -p lattice-cli (or --features gui -- --gui) discovers them. The runtime/ directory is git-ignored — it's regenerated build output. A released build stages the same artifacts into the packaged runtime root, so end users never run this step.

See the design fragment plugin-manager.md for the two-roots model, the runtime search path, and how user plugins (git/local, build-on-boot) differ from core plugins.