Ventoy Menu Class and Menu Alias Plugins: Customizing Boot Entries Without Rebuilding ISOs

Ventoy's menu class and menu alias plugins let you categorize ISO files and rename menu entries dynamically by parsing JSON rules at boot time, eliminating the need to rebuild the USB image.

The ventoy/Ventoy repository provides a lightweight plugin system that reads ventoy.json from the boot partition to customize the GRUB-based menu. These two plugins attach CSS-style classification tags and human-readable display names to files or directories, enabling conditional theming and clearer navigation without touching the ISO files themselves.

Architecture of the Menu Class and Menu Alias System

Ventoy implements these features as linked-list structures populated during plugin loading and queried while enumerating ISO files. The implementation resides entirely within the GRUB2 module source under GRUB2/MOD_SRC/grub-2.04/grub-core/ventoy/.

Data Structures in ventoy_def.h

The core definitions live in ventoy_def.h.

menu_class struct (lines 993–1002): Stores a type field (file or directory), a pattern string supporting wildcards, a parent flag indicating whether to match the parent directory path, and the class string itself that will be attached to matching entries.

menu_alias struct (lines 66–74): Stores a type (image or directory), the exact isopath of the entry, and the alias string that replaces the displayed name in the boot menu.

Plugin Initialization Functions

When Ventoy loads ventoy.json, specialized parsers build linked lists in memory.

ventoy_plugin_menuclass_entry() (lines 1833–1909 in ventoy_plugin.c): Parses the menu_class JSON array, constructs menu_class nodes, and rebuilds the g_menu_class_head linked list, freeing any previous configuration.

ventoy_plugin_menualias_entry() (lines 1449–1506 in ventoy_plugin.c): Performs the same operation for the menu_alias array, populating g_menu_alias_head with menu_alias objects.

Runtime Lookup Functions

During menu construction, Ventoy queries these lists to retrieve metadata for each file.

ventoy_plugin_get_menu_class() (lines 2666–2675 in ventoy_plugin.c): Accepts a file type, filename, and full path, returning the matching class string or NULL.

ventoy_plugin_get_menu_alias() (lines 2820–2839 in ventoy_plugin.c): Accepts a type and exact path, returning the alias string if defined.

Data Flow During Boot

  1. Plugin Load: ventoy_cmd_load_plugin reads /ventoy/ventoy.json from the boot partition.
  2. List Construction: The JSON parser invokes ventoy_plugin_menuclass_entry and ventoy_plugin_menualias_entry to populate static globals g_menu_class_head and g_menu_alias_head.
  3. Enumeration: As GRUB discovers ISO files, ventoy_cmd.c calls the lookup functions to determine img->class and img->alias.
  4. Rendering: The bootloader exports these values as environment variables for themes and scripts.

Configuring Menu Classes and Aliases in ventoy.json

You define these plugins in the root of your Ventoy partition inside the ventoy.json file. No recompilation or ISO rebuilding is required.

Defining CSS-Style Classes for Theming

Use the menu_class array to attach classification tags based on filename patterns or directory location:

{
  "menu_class": [
    { "key": ".iso", "class": "iso" },
    { "parent": "/linux", "class": "linux_dir" },
    { "dir": "windows", "class": "win_dir" }
  ]
}
  • key: Matches a substring or suffix in the filename (e.g., ".iso").
  • parent: Matches the parent directory path; applies the class to all entries within.
  • dir: Matches an exact directory name.
  • class: An arbitrary string consumed by themes (e.g., "ubuntu", "red", "custom").

Creating Human-Readable Display Names

Use the menu_alias array to override display names with readable labels:

{
  "menu_alias": [
    { "image": "/ubuntu-20.04.iso", "alias": "Ubuntu 20.04 LTS" },
    { "dir": "/tools", "alias": "Utility Tools" }
  ]
}
  • image: Absolute path to a specific ISO or IMG file (must start with /).
  • dir: Absolute path to a directory.
  • alias: The string displayed in the boot menu instead of the raw filename.

Consuming Plugin Data in Custom GRUB Themes

Ventoy exposes the plugin data as environment variables that custom grub.cfg files or themes can reference.

Accessing VTOY_MENU_CLASS for Conditional Theming

Themes can switch layouts or icons based on the class assigned to the current entry. Ventoy sets VTOY_MENU_CLASS immediately before displaying each menu item (see ventoy_cmd.c lines 2137–2148).


# In grub.cfg

if [ "$VTOY_MENU_CLASS" = "linux_dir" ]; then
    set theme=/boot/theme-linux.cfg
elif [ "$VTOY_MENU_CLASS" = "win_dir" ]; then
    set theme=/boot/theme-windows.cfg
fi

Displaying VTOY_MENU_ALIAS Instead of File Names

Replace the default filename display with the friendly alias using the VTOY_MENU_ALIAS variable. If no alias exists, Ventoy automatically falls back to the original filename.


# theme.cfg

menuentry "${VTOY_MENU_ALIAS}" --class $VTOY_MENU_CLASS {
    chainloader /ventoy/ventoy.chain
}

Implementation Details from the Ventoy Source Code

The integration between JSON parsing and menu rendering occurs in three critical files.

The Linked List Implementation

Both plugins use global head pointers to store configuration in memory:

  • g_menu_class_head: Tracks active menu class rules.
  • g_menu_alias_head: Tracks active alias mappings.

These globals are defined and manipulated in ventoy_plugin.c, where the entry functions allocate nodes with grub_zalloc and insert them at the list head.

Integration Point in ventoy_cmd.c

The actual assignment of class and alias data happens in ventoy_cmd.c at lines 2137–2148. For each discovered image, the code executes:

img->class = ventoy_plugin_get_menu_class(vtoy_class_image_file, 
                                          img->name, 
                                          img->path);

img->alias = ventoy_plugin_get_menu_alias(vtoy_alias_image_file, 
                                          img->path);

These values are later exported to the GRUB environment before the menu entry is rendered.

Key Source Files for Reference

Summary

  • Menu class and menu alias plugins read rules from ventoy.json at boot time without requiring ISO rebuilds.
  • The system uses linked lists (g_menu_class_head, g_menu_alias_head) defined in ventoy_def.h and populated by ventoy_plugin_menuclass_entry and ventoy_plugin_menualias_entry.
  • Runtime lookups occur via ventoy_plugin_get_menu_class and ventoy_plugin_get_menu_alias, called from ventoy_cmd.c during menu enumeration.
  • Configuration supports pattern matching on filenames (key), parent directories (parent), and exact paths (dir or image).
  • Custom themes access this data through the VTOY_MENU_CLASS and VTOY_MENU_ALIAS environment variables.

Frequently Asked Questions

How do I apply a class to all files in a specific directory?

Use the parent key in your menu_class entry. Set the value to the absolute directory path (e.g., /linux), and Ventoy will attach the specified class to every entry within that directory according to the logic in ventoy_plugin_get_menu_class at lines 2666–2675.

Can I use wildcards in menu alias definitions?

No. The menu_alias plugin requires an exact isopath match as defined in the menu_alias struct at lines 66–74 of ventoy_def.h. Aliases use strict string comparison against the full path, unlike menu classes which support substring matching via the key field.

What happens if both a directory alias and individual image aliases exist for the same path?

Ventoy checks for aliases at the individual entry level. The lookup function ventoy_plugin_get_menu_alias (lines 2820–2839) searches the g_menu_alias_head list for an exact path match. If an image-specific alias exists, it takes precedence; otherwise, the directory alias applies if configured.

Do I need to restart Ventoy after editing ventoy.json?

Yes. The JSON file is parsed once during the initial plugin load phase when ventoy_cmd_load_plugin executes. Changes require a reboot to trigger re-parsing by ventoy_plugin_menuclass_entry and ventoy_plugin_menualias_entry, which rebuild the linked lists from scratch.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →