✅ Introduction
Hydra menus are a powerful keyboard-driven menu system inspired by Emacs hydra and transient packages. They provide quick access to Scimax commands through persistent, modal menus that remain open until you explicitly close them or execute an exit command.
✅ Key Features
Fast keyboard-driven navigation with single-key selection
Organized command groups with descriptive labels and icons
Persistent menus that stay open for repeated actions (red heads)
Exit-after-action commands (blue heads)
Submenu navigation for hierarchical organization
Toggle indicators showing on/off state
Conditional visibility based on context
Customizable through VS Code settings
Full integration with all Scimax features
✅ Philosophy
The hydra system is designed around the principle of discoverability and efficiency. Instead of memorizing dozens of keyboard shortcuts, you can press `C-c m' to open the main menu and see all available commands with their shortcuts. Once you learn commonly-used shortcuts, you can invoke them directly without opening the menu.
✅ Getting Started
✅ Understanding Exit Behaviors
Each menu item has one of three exit behaviors, indicated by icons in the interface.
Note: The terms "Blue Head" and "Red Head" come from Emacs Hydra, which uses colored text. VS Code's QuickPick API doesn't support per-item colors, so we use icons instead.
✅ Exit (Blue Head) - $(sign-out)
The menu closes after executing the command. Most commands use this behavior. These items are marked with a $(sign-out) icon (exit door).
[t] Today $(sign-out) → Opens today's journal and closes menu [s] Search $(sign-out) → Starts search and closes menu
✅ Stay (Red Head) - $(sync)
The menu remains open after executing the command, allowing you to execute it multiple times or try different commands. These items are marked with a $(sync) icon (circular arrows).
[r] Refresh $(sync) → Refreshes data and keeps menu open [i] Index File $(sync) → Indexes file and keeps menu open
✅ Available Hydras
Scimax comes with eight pre-built hydra menus covering all major features:
✅ Commands and Keybindings
✅ Global Keybindings
| Keybinding | Command | Description |
|---|---|---|
| C-c m | scimax.hydra.main | Open main menu |
| C-c C-m | scimax.hydra.contextMenu | Open context-aware menu |
C-c m opens the main hydra menu, while C-c C-m opens a menu tailored to the current file type.
✅ Available Commands
All hydra commands can be invoked through the command palette (Cmd/C-S-P):
✅ scimax.hydra.show
Show a specific hydra menu by ID. If no ID is provided, shows a picker to select from available menus.
// Show main menu
await vscode.commands.executeCommand('scimax.hydra.show', 'scimax.main');
// Show menu picker
await vscode.commands.executeCommand('scimax.hydra.show');
✅ scimax.hydra.hide
Hide the currently visible hydra menu.
✅ scimax.hydra.back
Navigate back to the parent menu. If there's no parent, closes the menu.
✅ scimax.hydra.main
Open the main Scimax menu (scimax.main).
✅ scimax.hydra.toggle
Toggle visibility of a specific menu.
await vscode.commands.executeCommand('scimax.hydra.toggle', 'scimax.journal');
✅ Configuration
✅ Settings
Configure hydra behavior through VS Code settings (File > Preferences > Settings or Cmd/C-,):
✅ scimax.hydra.showKeyHints
Show keyboard shortcuts inline with menu items.
Type: boolean
Default: true
When enabled, shows shortcuts like [t] before each menu item:
[t] Today - With key hints Today - Without key hints
{
"scimax.hydra.showKeyHints": true
}
✅ scimax.hydra.singleKeySelection
Select menu items with a single keypress (no Enter needed).
Type: boolean
Default: true
When enabled, pressing a key immediately executes the command. When disabled, you must press Enter after selecting.
{
"scimax.hydra.singleKeySelection": true
}
✅ scimax.hydra.dimNonMatching
Dim menu items that don't match the current filter.
Type: boolean
Default: true
When typing to filter, non-matching items are dimmed rather than hidden.
{
"scimax.hydra.dimNonMatching": true
}
✅ scimax.hydra.sortByKey
Sort menu items by their keyboard shortcut instead of definition order.
Type: boolean
Default: false
When enabled, items are alphabetically sorted by key (a, b, c...) rather than their logical grouping.
{
"scimax.hydra.sortByKey": false
}
✅ Example Configuration
A complete hydra configuration might look like:
{
"scimax.hydra.showKeyHints": true,
"scimax.hydra.singleKeySelection": true,
"scimax.hydra.dimNonMatching": true,
"scimax.hydra.sortByKey": false
}
✅ Creating Custom Hydras
You can create custom hydra menus programmatically in extension code or through configuration.
✅ Using the Fluent Builder API
The easiest way to create a custom menu is with the fluent builder:
import { HydraManager } from './hydra';
// Get the hydra manager instance
const hydraManager = getHydraManager();
// Build a custom menu
const menu = hydraManager.createMenuBuilder('my.custom.menu')
.title('My Custom Menu')
.hint('Press a key to select an action')
.command('a', 'Action A', 'my.command.a')
.persistentCommand('r', 'Refresh', 'my.command.refresh')
.submenu('s', 'Settings', 'my.settings.menu')
.parent('scimax.main')
.build();
// Register the menu
hydraManager.registerMenu(menu);
✅ Advanced Features
✅ Conditional Visibility
Show items only when certain conditions are met:
{
key: 'x',
label: 'Advanced Feature',
exit: 'exit',
action: 'my.advanced.command',
when: () => {
const config = vscode.workspace.getConfiguration('myext');
return config.get('enableAdvanced', false);
}
}
✅ Toggle Items
Display on/off state for toggle commands:
{
key: 't',
label: 'Auto Save',
exit: 'stay',
action: 'my.toggle.autosave',
isToggle: true,
getToggleState: async () => {
const config = vscode.workspace.getConfiguration('myext');
return config.get('autoSave', false);
}
}
Toggle items display \((check) when on and \)(circle-outline) when off.
✅ Lifecycle Hooks
Execute code when menus are shown or hidden:
const menu: HydraMenuDefinition = {
id: 'my.menu',
title: 'My Menu',
groups: [],
onShow: async () => {
console.log('Menu opened');
await refreshData();
},
onHide: async () => {
console.log('Menu closed');
await cleanup();
}
};
✅ Practical Examples
✅ Example 1: Opening Today's Journal
The quickest way to open today's journal entry:
Press C-c m → opens main menu
Press j → opens journal submenu
Press t → opens today's entry and closes menu
Or, if you remember the keybinding, press C-S-J directly.
✅ Example 2: Inserting a Citation
To insert a citation in your document:
Position cursor where you want the citation
Press C-c m → opens main menu
Press r → opens references submenu
Press c → starts citation insertion
Type to search for your reference
Select the reference to insert it
✅ Example 4: Searching TODO Items
To find all TODO items in your org files:
Press C-c m → opens main menu
Press s → opens search submenu
Press t → searches for TODO items
View results in quick pick
Select an item to navigate to it
✅ Differences from Emacs Hydra
While inspired by Emacs hydra, the VS Code implementation has some differences due to platform constraints and design choices:
✅ Similarities
Keyboard-driven navigation with single-key selection
Persistent menus that stay open for repeated actions
Exit vs. stay behavior (blue vs. red heads)
Hierarchical menu organization
Visual indicators and hints
✅ Differences
✅ Quick Pick vs. Minibuffer
VS Code uses the native quick pick interface instead of Emacs's minibuffer. This provides:
Native VS Code look and feel
Fuzzy filtering built-in
Mouse support (if desired)
Icon support
Better accessibility
✅ No Dedicated Hydra Mode
VS Code doesn't have a dedicated "hydra mode" like Emacs. Hydras appear as quick picks that temporarily take focus but don't create a new modal mode.
✅ Async Command Execution
Commands execute asynchronously and can return Promises, supporting VS Code's async command pattern.
Icon-Based Indicators Instead of Colors
Unlike Emacs hydra which uses colored text (blue for exit, red for stay), VS Code's QuickPick API doesn't support per-item color customization. Instead, we use codicons to indicate behavior:
| Behavior | Icon | Meaning |
|---|---|---|
| Exit | $(sign-out) | Menu closes after command executes |
| Stay | $(sync) | Menu stays open after command |
| Submenu | $(chevron-right) | Navigates to a child menu |
| Toggle On | $(check) | Toggle is currently enabled |
| Toggle Off | $(circle-outline) | Toggle is currently disabled |
The overall color theme follows VS Code's active color theme.
✅ Configuration Through Settings
Configuration uses VS Code's settings system (JSON) rather than Emacs Lisp variables.
✅ No Posframe Support
Menus don't appear at specific screen positions like Emacs posframe. They always appear in the standard quick pick location (top center).
✅ Migration Tips
If you're coming from Emacs hydra:
Keybindings: Map C-c m (or your preferred binding) to scimax.hydra.main
Menu Definition: Use the fluent builder API for a declarative style similar to Emacs
Exit Behavior: exit blue head, stay red head
Submenus: Use the submenu exit behavior instead of (exit) with another hydra call
Hooks: Use onShow and onHide instead of :before-exit and :after-exit
✅ Tips and Best Practices
✅ Discoverability
Keep menus organized in logical groups
Use descriptive labels and helpful descriptions
Add icons to make items visually distinct
Use consistent key assignments (e.g., s for search, n for new)
✅ Performance
Use conditional visibility (when) to hide irrelevant items
Don't create too many nested submenus (2-3 levels max)
Keep async actions fast to avoid blocking the UI
Use persistent commands (stay) for repeated actions
✅ Keyboard Shortcuts
Assign memorable single-letter keys
Use uppercase for destructive or advanced operations
Group related commands under similar keys across menus
Reserve common keys (q for quit, ? for help, b for back)
✅ User Experience
Provide clear hints in menu titles
Show toggle state for boolean options
Use submenus to reduce cognitive load
Test both keyboard and mouse interaction
Ensure menus work in all relevant contexts
✅ Debugging
To debug custom menus:
Open the Developer Console (Help > Toggle Developer Tools)
Set breakpoints in menu actions
Use console.log in onShow and onHide hooks
Check for errors in command execution
Verify menu registration with hydraManager.getMenuIds()
✅ Troubleshooting
✅ Commands Not Executing
Verify the command is registered in VS Code
Check command arguments are correct
Look for errors in the Developer Console
Test the command directly from command palette
✅ Items Not Showing
Check the when condition if present
Verify group visibility conditions
Ensure items are not filtered by current search
Check that sortByKey setting isn't hiding items
✅ Single-Key Selection Not Working
Verify scimax.hydra.singleKeySelection is true
Check for key conflicts with other extensions
Ensure the hydra menu has focus
Try pressing keys slowly (avoid double-press)
✅ Frequently Asked Questions
✅ Can I create hydras for non-Scimax commands?
Yes! You can create hydras that execute any VS Code command, including those from other extensions.
✅ How do I add a hydra to the command palette?
Hydra commands like scimax.hydra.show are automatically available in the command palette. To show a specific menu, register it first, then call:
await vscode.commands.executeCommand('scimax.hydra.show', 'your.menu.id');
✅ Can I bind a hydra to a custom keybinding?
Yes! Add a keybinding in keybindings.json:
{
"key": "ctrl+alt+h",
"command": "scimax.hydra.show",
"args": "my.custom.menu"
}
✅ Can hydras work with multiple workspaces?
Yes! Hydras are global to the VS Code window and work across all workspace folders.
✅ How do I disable hydras?
Unmap the keybindings in your keybindings.json:
{
"key": "ctrl+c m",
"command": "-scimax.hydra.main"
}
The hydras remain available through the command palette.
✅ Additional Resources
✅ Source Code
The hydra framework source is located in srchydra:
src/hydra/types.ts - Type definitions
src/hydra/hydraManager.ts - Core manager implementation
src/hydra/commands.ts - Command registrations
src/hydramenus - Pre-built menu definitions
✅ External References
Emacs Hydra Package - Original inspiration
Emacs Transient Package - Alternative approach
VS Code QuickPick API - Underlying implementation
✅ Conclusion
Hydra menus provide a powerful and discoverable way to access Scimax features. Whether you're a new user exploring available commands or an experienced user building custom workflows, hydras help you work efficiently without memorizing dozens of keyboard shortcuts.
Start with C-c m to open the main menu and explore. Over time, you'll develop muscle memory for frequently-used commands and can invoke them directly or through submenus.
Happy hydra-ing!