Follow Discord
Sweep 22 Sep 2026 · 17:19Z Build v2.1.280 501 read Stable v2.1.267 Latest v2.1.280 Next v2.1.280 Feeds RSS JSON llms.txt Unofficial
Claude Code v2.1.269 ·

Plugin hooks.json surface field replaced by per-module surfaceModules

Plugin hooks.json no longer has a top-level surface field; each Client element now names its own module, and multiple surfaceModules can load at once

TierUnder the hoodhow much it should matter to you
Useful1my rating, 1 to 5
Signal1worth watching, 1 to 5
AreaPlugin UIwhat it touches
KindInternal Changesin v2.1.269,
Group of 2 Under the hood No documentation found

Plugin hooks.json no longer has a top-level surface field; each Client element now names its own module, and multiple surfaceModules can load at once

What

  • The hooks.json schema for plugins no longer accepts a top-level surface key. Instead, each Client element in the config must name its own module. Using the old surface field now produces a hard schema error.
  • The runtime error shown when a plugin has no drawable Client now checks surfaceModules from the hooks module's own exports, instead of looking for a surface entry in hooks.json.
  • The code that resolves a plugin's hooks module used to also resolve and validate a separate surface path (checking for path traversal and that the file exists) and store it as surfacePath; that check is now removed, and the code just sets modulePath.
  • Elsewhere, the surface-environment loader was changed from loading a single surface module to loading an array of surfaceModules, and its logging now lists all the loaded module names instead of just one.

Why

This lets a plugin provide multiple UI-drawing ('surface') modules instead of just one, with each Client referencing its own module directly rather than all of them sharing a single top-level surface path.

How sure we are
Something disagreesSomething we can check disagrees with this entry, or the writer said they could not settle it.
The writer flagged doubtThe finding does not say where the removed path-traversal check now happens or whether it is still enforced somewhere.

See this entry in the whole of v2.1.269 →

Feedback