Skip to content

extension_api: Add custom debug actions for extensions#51873

Open
paulocagol wants to merge 7 commits into
zed-industries:mainfrom
paulocagol:custom-debug-actions
Open

extension_api: Add custom debug actions for extensions#51873
paulocagol wants to merge 7 commits into
zed-industries:mainfrom
paulocagol:custom-debug-actions

Conversation

@paulocagol

@paulocagol paulocagol commented Mar 18, 2026

Copy link
Copy Markdown

Summary

  • Add get_dap_custom_actions to the Extension API, allowing extensions to declare
    custom debug adapter actions (toolbar buttons and/or on-save triggers)
  • Add request_raw() to DebugAdapterClient for sending dynamic DAP commands
  • Render extension-declared custom actions as buttons in the debugger toolbar
  • Automatically trigger on-save actions when a buffer is saved during an active debug session

This is a generic mechanism — any debug adapter extension can declare custom actions.
The immediate use case is Flutter hot reload/restart via the dart extension.

Addresses feedback from #45467: instead of hardcoding Flutter-specific actions in the core,
the extension API now supports this declaratively.

Screenshots

image image image

Overview: Editor + Flutter app + Debug panel with Console output

Console showing "Reloaded 1 of 748 libraries" confirming hot reload on-save

Toolbar close-up with 🔥 (Hot Reload) and 🔄 (Hot Restart) icons

Companion PR: zed-extensions/dart#72 uses this API to add Flutter hot reload/restart.

Test plan

  • Install a debug adapter extension that implements get_dap_custom_actions
    (e.g., the dart extension with hot reload support)
  • Start a debug session — custom action buttons should appear in the toolbar
  • Click a toolbar button — the corresponding DAP command should be sent
  • Save a file during debug — on-save actions should trigger automatically
  • Verify actions with trigger: Toolbar only show as buttons (no on-save)
  • Verify actions with trigger: OnSave only trigger on save (no button)
  • Verify actions with trigger: Both show button AND trigger on save
  • Start a debug session with an adapter that doesn't declare custom actions —
    no extra buttons should appear

Release Notes:

  • Added custom debug actions support to the Extension API, allowing debug adapter
    extensions to add toolbar buttons and on-save triggers for adapter-specific commands

paulocagol and others added 6 commits March 18, 2026 17:21
Add a `request_raw()` method to `DebugAdapterClient` that sends custom
DAP requests with a dynamic command name and JSON arguments. This enables
extension-declared custom actions (e.g. "hotReload") to communicate
directly with the debug adapter.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Introduce DapCustomAction, DapCustomActionTrigger, and DapCustomActionIcon
types that allow debug adapters to declare custom toolbar actions. Add a
default `custom_actions()` method to the DebugAdapter trait that returns
an empty list.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Define WIT records for dap-custom-action, dap-custom-action-trigger, and
dap-custom-action-icon. Export the get-dap-custom-actions function in the
extension world. Add the corresponding trait method and Guest implementation
in the Rust extension API, with a default that returns an empty list.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Implement the WASM host side of get_dap_custom_actions: dispatch to v0.8.0
extensions (older versions return empty), convert WIT types to Rust types
via From impls, and delegate from ExtensionDapAdapter to the extension.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Add custom_actions field to Session with getter/setter and a
send_custom_request method. Fetch custom actions from the adapter during
boot_session and store them. Render extension-declared actions as icon
buttons in the debugger toolbar with a divider, filtering to Toolbar/Both
trigger types.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Hook BufferEvent::Saved in project.rs to call dap_store.on_buffer_saved(),
which iterates active debug sessions and triggers any custom actions with
OnSave or Both trigger types.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@cla-bot

cla-bot Bot commented Mar 18, 2026

Copy link
Copy Markdown

We require contributors to sign our Contributor License Agreement, and we don't have @paulocagol on file. You can sign our CLA at https://zed.dev/cla. Once you've signed, post a comment here that says '@cla-bot check'.

@zed-community-bot zed-community-bot Bot added the first contribution the author's first pull request to Zed. NOTE: the label application is automated via github actions label Mar 18, 2026
paulocagol added a commit to paulocagol/dart that referenced this pull request Mar 18, 2026
Implement `get_dap_custom_actions` to expose Flutter hot reload and hot
restart as custom debug actions. Hot reload triggers both on toolbar click
and on file save; hot restart is toolbar-only.

Also fix device selection by passing `-d <device_id>` via `toolArgs` in
the launch configuration.

Depends on zed-industries/zed#51873 (custom debug actions Extension API).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@paulocagol

Copy link
Copy Markdown
Author

@cla-bot check

@cla-bot

cla-bot Bot commented Mar 18, 2026

Copy link
Copy Markdown

We require contributors to sign our Contributor License Agreement, and we don't have @paulocagol on file. You can sign our CLA at https://zed.dev/cla. Once you've signed, post a comment here that says '@cla-bot check'.

@cla-bot

cla-bot Bot commented Mar 18, 2026

Copy link
Copy Markdown

The cla-bot has been summoned, and re-checked this pull request!

@paulocagol

Copy link
Copy Markdown
Author

@cla-bot check

@cla-bot cla-bot Bot added the cla-signed The user has signed the Contributor License Agreement label Mar 18, 2026
@cla-bot

cla-bot Bot commented Mar 18, 2026

Copy link
Copy Markdown

The cla-bot has been summoned, and re-checked this pull request!

@rubenvde

Copy link
Copy Markdown

Can someone please review this PR, how is this open for a month? @MrSubidubi do you have time to look at it?

@ShirishAryal

This comment was marked as spam.

@knotbin

knotbin commented May 18, 2026

Copy link
Copy Markdown

@MrSubidubi it would be really great if this could get a review. It's a really essential feature for many debug extensions, especially Dart.

@josevargasweb

Copy link
Copy Markdown

plz we need this extension

@josevargasweb

Copy link
Copy Markdown

@paulocagol plz resolve conflicts :)

@paulocagol

Copy link
Copy Markdown
Author

@paulocagol plz resolve conflicts :)

Why would I resolve a conflict if they're not going to do the merge? lol

@knotbin

knotbin commented Jun 10, 2026

Copy link
Copy Markdown

@paulocagol yeah it's a self-fulfilling prophecy/cycle.
they can't expect you to continue to maintain the PR if they don't make efforts towards merging but they won't make efforts towards merging if the PR isn't maintained.

this is a very important change and i really hate to see it stuck in this limbo that will just lead to it being closed as stale in a few months.
I really urge @maxdeviant or @MrSubidubi to get the ball rolling by giving this a review, or just adding any comment about where this stands.

@cla-bot

cla-bot Bot commented Jun 10, 2026

Copy link
Copy Markdown

We require contributors to sign our Contributor License Agreement, and we don't have @TESTPERSONAL on file. You can sign our CLA at https://zed.dev/cla. Once you've signed, post a comment here that says '@cla-bot check'.

@cla-bot cla-bot Bot removed the cla-signed The user has signed the Contributor License Agreement label Jun 10, 2026
@paulocagol
paulocagol force-pushed the custom-debug-actions branch from e76f1fa to 6dbbc2c Compare June 10, 2026 16:53
@cla-bot cla-bot Bot added the cla-signed The user has signed the Contributor License Agreement label Jun 10, 2026
# Conflicts:
#	crates/debugger_ui/src/debugger_panel.rs
#	crates/project/src/debugger/session.rs
@paulocagol
paulocagol force-pushed the custom-debug-actions branch from 6dbbc2c to f0c6cfd Compare June 10, 2026 16:54
@paulocagol

Copy link
Copy Markdown
Author

My part is done — conflicts resolved and the branch is up to date with main again.

A bit of context: I tend to move around between tools rather than staying in one place, and while I was using Zed I figured I'd give back and contribute this. I'm not actively on it at the moment, so I don't plan to keep pushing this PR forward myself from here on.

I'm leaving it in good shape in case it's useful — there's clear community interest, and I genuinely hope it lands and gives folks (and maybe future me) a reason to come back. For what it's worth, Zed is a great editor: fast, well-built, and it served me well while I used it.

No hard feelings at all — thanks to everyone who chimed in and supported the feature. If a maintainer wants to pick it up or adopt the branch, please feel free. ✌️

psc. @maxdeviant, @MrSubidubi, @knotbin, @josevargasweb

@zelenenka zelenenka added area:extensions/infrastructure Feedback for extensions APIs, creation, management, etc area:debugger Feedback for Zed's debugger labels Jun 16, 2026
@TateWalker

Copy link
Copy Markdown

Interested in seeing this merged as well. I've got a separate PR in zed-extensions/dart that fixes remote support. Together with @paulocagol 's other PR, we'd have much-needed support for VSCode-equivalent Flutter debugging

@MrSubidubi

Copy link
Copy Markdown
Member

To finally give this a long overdue reply, sorry for the delay:

We are, generally speaking, not the biggest fans of changes to our extension API without prior discussion for these, primarily due to the following reasons:

  • Whatever API we add, we will almost definitely keep supporting for a very long time - this adds a lot of maintenance cost and we will need to work around what we added in the future, which e.g. currently bites us in the context of language servers.
  • API additions without prior context/discussion make it hard for us to make an appropriate judgement and it is not always clear what this adds in the context of not only this, but especially other languages
  • Opening a PR for a change without prior discussion very much dictates the way this will be wired through, which might lead to a bad approach from the start. This again puts us at the risk of maintenance burden if we go with the fundamentally wrong approach for something (e.g. with the icon approach here, we would almost need to keep the API-available icons around for forever, which, well, might not work).

In the context of this PR, the second point is definitely the biggest: While I see that this adds a lot for dart given by the time you guys put into this, the idea here for this should also add benefit to other consumers of this API and, especially, MUST be equally well suited for them. I currently cannot know whether this is the case, since I am unaware of any other cases where an API like this might benefit a debugger and only have the (obvious) Dart-demand at hand here. Similarly, we have not once looked at how VSCode handles this. While we must not adopt their approach, it would definitely benefit to know how they solved it perhaps so we can make a better judgement here.

Hope that adds some context here finally, in any case, sorry for the time to reply.

@blaqshyd

Copy link
Copy Markdown

To finally give this a long overdue reply, sorry for the delay:

We are, generally speaking, not the biggest fans of changes to our extension API without prior discussion for these, primarily due to the following reasons:

  • Whatever API we add, we will almost definitely keep supporting for a very long time - this adds a lot of maintenance cost and we will need to work around what we added in the future, which e.g. currently bites us in the context of language servers.
  • API additions without prior context/discussion make it hard for us to make an appropriate judgement and it is not always clear what this adds in the context of not only this, but especially other languages
  • Opening a PR for a change without prior discussion very much dictates the way this will be wired through, which might lead to a bad approach from the start. This again puts us at the risk of maintenance burden if we go with the fundamentally wrong approach for something (e.g. with the icon approach here, we would almost need to keep the API-available icons around for forever, which, well, might not work).

In the context of this PR, the second point is definitely the biggest: While I see that this adds a lot for dart given by the time you guys put into this, the idea here for this should also add benefit to other consumers of this API and, especially, MUST be equally well suited for them. I currently cannot know whether this is the case, since I am unaware of any other cases where an API like this might benefit a debugger and only have the (obvious) Dart-demand at hand here. Similarly, we have not once looked at how VSCode handles this. While we must not adopt their approach, it would definitely benefit to know how they solved it perhaps so we can make a better judgement here.

Hope that adds some context here finally, in any case, sorry for the time to reply.

I guess these are all valid reasons for not wanting to commit to this but one question, is there a way the team would recommend/suggest we go about this? A RFC or alternative ways to do this because there are a couple of PRs that are on hold because the core API doesn't provide support for it out of the box in the dart extension (have to come and as you suggested I think it might be worth checking out how vscode handles this just to come up with a solution that works.

@MrSubidubi

Copy link
Copy Markdown
Member

is there a way the team would recommend/suggest we go about this

Since I have not closed the PR yet, I am open for options. The best way currently from my perspective would be some context gathering here so that we can make an educated decision - frankly, I do not have any time to dig into this right now and would appreciate if someone here could pick this up, I am happy to look at whatever is collected here. My main questions as outlined above would be

  • what other debuggers could/would benefit from this
  • how is it handled/exposed in VSCode (both in their core/dart extension) as well as visually

then re-evaluate the approach chosen here and continue from there

@blaqshyd

Copy link
Copy Markdown

is there a way the team would recommend/suggest we go about this

Since I have not closed the PR yet, I am open for options. The best way currently from my perspective would be some context gathering here so that we can make an educated decision - frankly, I do not have any time to dig into this right now and would appreciate if someone here could pick this up, I am happy to look at whatever is collected here. My main questions as outlined above would be

  • what other debuggers could/would benefit from this
  • how is it handled/exposed in VSCode (both in their core/dart extension) as well as visually

then re-evaluate the approach chosen here and continue from there

Alright, thank you for the response and the things to take note of. I actually did some research on how things were handled in vscode specifically for this issue: Code completion is not invoked by typing a dot.

I'm going to go over this PR and test it locally and update the discussion here based on my findings of how it was approached in vscode and also how it could benefit not just the dart debugger.

The author said they don't plan to maintain this anymore, so I'm going to take a stab at it.

@knotbin

knotbin commented Jun 24, 2026

Copy link
Copy Markdown

Hi @MrSubidubi, thanks so much for the very detailed response. I understand you're not able to dig into this issue specifically so I won't ask about specific details but I do have one more abstract question regarding how the extensions API is being thought of internally.

We are, generally speaking, not the biggest fans of changes to our extension API without prior discussion for these...

I don't remember exactly where I heard it but I am pretty confident that I heard someone on the Zed team (on some podcast or show or the like) say something along the lines of "we are keeping the extension API limited for the moment because we want to build out a solid core experience that doesn't rely so heavily on extensions for core functionality" (he was also drawing a contrast to VS Code's extension-heavy philosophy iirc).

Generally I don't think it's controversial to say that the Zed Extension API is very limited compared to VS Code, and I assumed, based on hearing that, that was an intentional choice for the time being and that eventually there would be a big push to make extensions as powerful as they are in VS Code.
But the comment you left seems to imply (and I could be reading this totally wrong) that internally the extensions API is thought of as mostly a stable, semi-complete API that isn't intended to have large additions added onto it in any near future. Again, this could be a completely wrong assumption and you might just be talking about outside contributions.

But it does make me want to get clarification on that main question regarding Extension APIs. So the question is:

Are there plans to, at some point in the future, have some large effort (similar to recent efforts/pushes to make Git integration much better) to make the Extensions API much more powerful, and to bring it more in line with the extensiveness of VS Code's extensions API? Or is the internal philosophy that extensions being limited is a long-term purposeful choice that sets Zed apart from VS Code?
(Or is that just still being determined or not decided on yet or just not very important internally?)

Sorry for the long big question and I understand if it's not something you can answer at the moment, but if you can it would be greatly appreciated.

@MrSubidubi

Copy link
Copy Markdown
Member

Hey @knotbin !

But the comment you left seems to imply (and I could be reading this totally wrong)

The latter is very much the case - we do not consider the API as neither complete nor stable, however, additions to it just come with a maintenance cost that is not to be neglected.

We do have plans to have some large effort on it in the future to substantially improve it and very much want to to this. This is not an "if" but "when" question. What I wanted to note with this is that speaking from experience, API additions without prior discussions have had a low chance to be merged since they almost all neglected big parts of the "mostly stable" part in the sense that we'd would have needed to change those substantially in the future again.

Hope that made some sense, but I think that should answer your core question. Appreciate you raising this, sorry for the message being ambiguous in that sense!

@quinn-dougherty

Copy link
Copy Markdown

I'd love for this to get merged in! working on a cool custom PL project that would greatly benefit from it

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area:debugger Feedback for Zed's debugger area:extensions/infrastructure Feedback for extensions APIs, creation, management, etc cla-signed The user has signed the Contributor License Agreement first contribution the author's first pull request to Zed. NOTE: the label application is automated via github actions

Projects

None yet

Development

Successfully merging this pull request may close these issues.