Skip to content

feat: IPC Introspection#15326

Draft
oscartbeaumont wants to merge 7 commits into
tauri-apps:devfrom
oscartbeaumont:ipc-introspection
Draft

feat: IPC Introspection#15326
oscartbeaumont wants to merge 7 commits into
tauri-apps:devfrom
oscartbeaumont:ipc-introspection

Conversation

@oscartbeaumont
Copy link
Copy Markdown
Member

@oscartbeaumont oscartbeaumont commented May 3, 2026

Summary

Adds command introspection metadata for #[tauri::command] handlers.

  • Introduces tauri::ipc::CommandMetadata and CommandMetadataDeprecated for describing registered commands.
  • Extends the command macro wrapper with a @metadata arm that exposes command name, docs, deprecation metadata, and argument names (as a tauri::ipc::CommandMetadata)

Why?

Frameworks and tooling built on top of Tauri could benefit from a reliable way to discover command metadata without re-parsing Rust source or duplicating macro behavior.

This enables integrations such as Tauri Specta to drop the #[specta::specta] macro from each command while still generate end to end typeafe bindings for other langauges but I think this feature can go much furthur than just IPC typesafety.

For example a tool like CrabNebula DevTools could use this to provide a playground for invoking commands kinda like you would get from an OpenAPI spec.

This could also be used to generate command documentation, or even determining which command exist for automatic mocking, etc. The possibilities would be endless.

More into Specta's rational

Of course the DX of removing #[specta::specta] on each command is a massive motivation.

Other than that I have come to dislike specta::function::* + the specta::specta macro and am likely going to deprecate it soon. The idea behind stablising it in Specta's core (as we moved it from Tauri Specta where it was originally) was for other frameworks to be able to reuse it. This came true as now TauRPC is also using it but the issue with is that at the end of the day it is it's too opinionated for Specta's core.

For example Tauri has rename_all which we have never supported (specta-rs/specta#453). If we did it would need to be used like:

#[specta::specta(rename_all = ...)]
#[tauri::command(rename_all = ...)]

which is super error prone.

It also means any framework-specific parameters need to be implemented via the macro in Specta's core which is rough for keeping Specta's core stable and clean. For example Specta's core actually stays quite agnostic of Serde while rename_all here is more of a Serde convention.

This PR is paired with specta-rs/tauri-specta#218 which is a prototype of implementing this PR into Tauri Specta to confirm it works.

Design

This feature explicitly only exposes metadata about the command which the user would need their own macro on each command to expose. It's expected that trait inference on Fn(*) -> *-style traits is used for everything that is possible. These function traits lack the information for:

  • Rustdoc comments
  • Rust #[deprecated] attribute
  • command argument names (Fn(*) only has the types and positions)
  • command name (including the automatically applied plugin prefix if defined in a Tauri plugin)

It can be used by calling __cmd__{function}!(@metadata); which returns a tauri::ipc::CommandMetadata which contains the introspected information.

This PR doesn't expose any helpers for accessing the command metadata via the tauri::Builder as I don't think we could make that possible without a breaking change on invoke_handler. This could be considered for v3 but I am also not sure it's really required.

I have not exposed anything for collecting command metadata, that would be up to the downstream framework right now. This aligns with how Tauri Specta already works where it defines it's own collect_commands! macro to wrap the tauri::generate_handler! macro. One major downside of this approach is that multiple frameworks can't compose well, that being said I don't think this is a blocker as solving this would require stablising APIs on top of the primitive this PR exposes.

This is definitely a more significant thing to stablise so I am opening this for feedback. I am not bound to the current implementation but I do think having a feature in this realm would be really nice for improving the DX of people building applications with Tauri.

I also don't know why the changeset is causing issues given I added it through the GitHub link in the GH Actions comment.

@github-project-automation github-project-automation Bot moved this to 📬Proposal in Roadmap May 3, 2026
@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented May 3, 2026

Package Changes Through 0807a9c

There are 4 changes which include tauri-macros with minor, tauri with minor, tauri-driver with patch, tauri-utils with patch

Planned Package Versions

The following package releases are the planned based on the context of changes in this pull request.

package current next
tauri-utils 2.9.0 2.9.1
tauri-bundler 2.9.0 2.9.1
tauri-runtime 2.11.0 2.11.1
tauri-runtime-wry 2.11.0 2.11.1
tauri-codegen 2.6.0 2.6.1
tauri-macros 2.6.0 2.7.0
tauri-plugin 2.6.0 2.6.1
tauri-build 2.6.0 2.6.1
tauri 2.11.0 2.12.0
@tauri-apps/cli 2.11.0 2.11.1
tauri-cli 2.11.0 2.11.1
tauri-driver 2.0.5 2.0.6

Add another change file through the GitHub UI by following this link.


Read about change files or the docs at github.com/jbolda/covector

@amrbashir
Copy link
Copy Markdown
Member

amrbashir commented May 5, 2026

I honestly don't want add this in tauri, the current macro system is a bit complex to my taste, and as I suggested before I would like to move a way from it, into a trait-based system.

Landing this PR would make it harder and harder to ever ditch the macro system.

This is just my opinion, not the whole team

@oscartbeaumont
Copy link
Copy Markdown
Member Author

Very fair but I am also not sure this does impact the removal of the macro system, imo. I am personally for removing the command macro, my work on rspc shows what I think this sort of system should look like, so I wouldn't want to compromise that.

Tauri Specta has had the goal from day zero to be Tauri + Specta. It's designed to try and be unopinionated and small. If Tauri were to remove the command macro, we would also follow suite, removing the need for any introduced introspection API.

If Tauri moved to a trait-inference system (as all the discussions I can see point to) then this introspection API would also become obsolete as it could just be implemented in userspace using the Fn() class of traits. From that perspective I don't think it would block the removal of #[tauri::command], if anything it's another argument for moving away from #[tauri::command].

On the PR linked with this one (specta-rs/tauri-specta#2180) we actually rely on runtime type inference using the Fn traits for for figuring out the command arguments and return type, we only need the argument name, doc comments and deprecated to come from this introspection API as Rust provides no way to introspect that. If Tauri did move to a runtime command system based on Fn() traits, Tauri's internal IPC would have to live without this same information avaiable to Tauri Specta which would put us both on a even playing field and would ensure no special APIs need to remain.

Also from what I can tell #[tauri::command] being removed is very uncertain at the moment as some people aren't happy about the fact that function arguments will need to become a tuple, so from my stance it seems unclear if this will land anytime soon, as much as I am a supporter of it.

I am planning to bring this issue up in the working group channel when I get a chance, I definitely expected pushback on this. Really appricate you taking the time to look at it!

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

Labels

None yet

Projects

Status: 📬Proposal

Development

Successfully merging this pull request may close these issues.

2 participants