Load plugin hooks without other plugin capabilities (#26272)

## Summary

`hooks/list` only consumes plugin hook declarations, but previously
loaded every enabled plugin's skills, MCP configuration, apps, and
capability summary before discarding them.

In a local benchmark, this reduced `hooks/list` latency by over 100ms
(e.g., from 594 to 467ms on startup, and 168 to 16ms when making a
`hooks/list` call later in the same TUI session). This is on the
critical path to rendering the TUI, so every 10s of ms should be eyed
skeptically (IMO).

This change adds a hook-specific plugin loading path that preserves
plugin enablement, remote/local conflict resolution, deterministic
ordering, manifest resolution, and hook-loading warnings while skipping
unrelated capabilities. (I think there's room for a more general design
here that allows you to project the capabilities you need at load-time,
but that seems unnecessary right now.)
This commit is contained in:
Charlie Marsh authored and GitHub committed 2026-06-04 11:21:40 -04:00
1 parent d81fcdf8ef
commit 4ae7930f58
7 files changed
+330 -53

No files matched your search

@@ -645,20 +645,20 @@ impl CatalogRequestProcessor {
.await;
let plugins_enabled =
config.features.enabled(Feature::Plugins) && workspace_codex_plugins_enabled;
let plugin_outcome = if plugins_enabled {
let plugin_hooks = if plugins_enabled {
let plugins_input = config.plugins_config_input();
plugins_manager
.plugins_for_layer_stack(&config.config_layer_stack, &plugins_input)
.plugin_hooks_for_layer_stack(&config.config_layer_stack, &plugins_input)
.await
} else {
PluginLoadOutcome::default()
codex_core_plugins::PluginHookLoadOutcome::default()
};
let hooks = codex_hooks::list_hooks(codex_hooks::HooksConfig {
feature_enabled: config.features.enabled(Feature::CodexHooks),
bypass_hook_trust: config.bypass_hook_trust,
config_layer_stack: Some(config.config_layer_stack),
plugin_hook_sources: plugin_outcome.effective_plugin_hook_sources(),
plugin_hook_load_warnings: plugin_outcome.effective_plugin_hook_warnings(),
plugin_hook_sources: plugin_hooks.hook_sources,
plugin_hook_load_warnings: plugin_hooks.hook_load_warnings,
..Default::default()
});
data.push(codex_app_server_protocol::HooksListEntry {