Create powerful custom plugins to extend oRPC handlers and links with interceptors.
Scanned 9/12/2026
Install to Claude Code
npx -y skills add ali-master/skills --skill orpc-building-custom-plugins --agent claude-codeInstalls into .claude/skills of the current project.
Are you the author of Orpc Building Custom Plugins?
Add the live security badge to your README — it updates automatically with every re-scan.
[](https://www.skillsdirectory.com/skills/ali-master-orpc-building-custom-plugins)More formats (shields.io, HTML) on the badges page.
---
name: oRPC Building Custom Plugins
description: Create powerful custom plugins to extend oRPC handlers and links with interceptors.
license: MIT
metadata:
author: Ali Torki
homepage: https://github.com/ali-master
version: "1.0.0"
---
# Building Custom Plugins
This guide explains how to create custom oRPC plugins for handlers and links.
## What is a Plugin?
In oRPC, a plugin is a collection of `interceptors` that can work together or independently.
```ts
export class ResponseHeadersPlugin<T extends ResponseHeadersPluginContext> implements StandardHandlerPlugin<T> {
init(options: StandardHandlerOptions<T>): void {
options.rootInterceptors ??= []
options.rootInterceptors.push(async (interceptorOptions) => {
const resHeaders = interceptorOptions.context.resHeaders ?? new Headers()
const result = await interceptorOptions.next({
...interceptorOptions,
context: { ...interceptorOptions.context, resHeaders },
})
if (!result.matched) return result
const responseHeaders = clone(result.response.headers)
for (const [key, value] of resHeaders) {
// merge headers
responseHeaders[key] = value
}
return { ...result, response: { ...result.response, headers: responseHeaders } }
})
}
}
```
### Handler Plugins
Extend server-side handlers (RPCHandler, OpenAPIHandler). Work with interceptors from the [Handler Lifecycle](/docs/rpc-handler#lifecycle).
### Link Plugins
Enhance client-side communication (RPCLink, OpenAPILink). Use interceptors from the [Link Lifecycle](/docs/client/rpc-link#lifecycle).
## Communication Between Interceptors
Use a unique symbol to inject context shared between interceptors. The [Strict Get Method Plugin](/docs/plugins/strict-get-method) demonstrates this — it uses `rootInterceptors` to collect HTTP methods and combines them with procedure info in `clientInterceptors`.
## Plugin Order
```ts
export class ExamplePlugin<T extends Context> implements StandardHandlerPlugin<T> {
order = 10
init(options: StandardHandlerOptions<T>): void {
options.rootInterceptors ??= []
options.clientInterceptors ??= []
options.rootInterceptors.push(async ({ next }) => next())
options.clientInterceptors.push(async ({ next }) => next())
}
}
```
`order` controls plugin loading order, not interceptor execution order. Higher order with `.unshift` to run earlier, or `.push` to run later.
> Avoid setting `order` unless necessary. Keep it below `1_000_000` to avoid conflicts with built-in plugins.
Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.
No comments yet. Be the first to comment!