--- title: Plugin reference description: Local plugin files, client and server runtimes, platform limits, contributions, RPCs, lifecycle, hosts, and CLI commands. nav: Reference order: 48 category: Plugins --- # Plugin reference Start with the [plugin quickstart](/docs/plugins) to create your first plugin. Migrating an existing plugin? Follow the standalone [runtime-entry migration guide](/docs/plugins/migration). Local plugins are directory sources installed into one Paseo daemon. A plugin can contribute: - React Native screens and sidebar header and footer items to Paseo clients; - workspace and agent panels opened as workspace tabs; - global, workspace, and agent actions in the Command Center; - slash commands in the message composer; - transformed and daemon-pushed agent timeline rows; - light and dark themes in Settings → Appearance; - schema-validated RPC handlers running beside the daemon; - normal Paseo operations through the TypeScript SDK; - searchable external resources in the message composer. Plugin code is trusted and unsandboxed. Client surfaces run in the Paseo app. Backend contributions run in a subprocess with access to the daemon machine, including its files, processes, credentials, and network. ## Project files `paseo plugin init /absolute/path/to/my-plugin` creates: ```text my-plugin/ paseo-plugin.json index.client.tsx index.server.ts client/greeting.tsx server/greeting.ts shared/greeting.ts package.json tsconfig.json ``` The required root manifest is `paseo-plugin.json`: ```json { "id": "my-plugin", "description": "Reviews changes before merge", "requirements": { "paseo": ">=0.8.0" } } ``` | Field | Required | Behavior | | -------------- | -------- | ---------------------------------------------------------------------- | | `id` | Yes | Default installation ID. | | `description` | No | Non-empty summary shown below the plugin ID in **Settings → Plugins**. | | `requirements` | No | Supported Paseo versions, described below. | | `build` | No | Preparation commands, described in the CLI reference. | ### Requirements `requirements` is an optional object. Its currently supported key, `paseo`, accepts an npm semver range. An omitted `requirements.paseo` means `<0.8.0`: the plugin predates the first breaking plugin release. Paseo 0.8 and later reject it with a link to the [migration guide](migration). Empty strings, invalid ranges, and unknown manifest requirement keys are rejected. | Range | Compatible releases | | ---------------- | ---------------------------------------------------------------------------- | | `>=0.8.0` | 0.8.0 and later releases, including prereleases and future breaking releases | | `^0.8.0` | 0.8.x releases, including prereleases | | `>=0.8.3 <0.9.0` | 0.8.3 through the last 0.8 patch, including prereleases | Prerelease Paseo versions also satisfy a range their stable core (`major.minor.patch`) satisfies, so `0.8.0-beta.1` satisfies `>=0.8.0` but not `<0.8.0`. `paseo plugin init` writes `>=` followed by the current CLI version and pins the matching SDK for typechecking. Raise the minimum when adopting a newer API. Add an upper bound when a later release is incompatible; a minimum alone does not promise protection from future breaking changes. The daemon checks its version before installing, running preparation commands, or loading a plugin, and checks again on startup, enable, and reload. A rejected update keeps the installed revision. Each connected app checks its own version before evaluating client code and shows incompatibility in Settings → Plugins. A compatible daemon does not make an older app compatible. A plugin with no client entry does not require the connected app to match. For example: `Plugin "review" requires Paseo >=0.8.0. Your daemon is 0.7.2.` Use a compatible plugin revision or update the named runtime. Releases before 0.8 do not understand this manifest field and cannot show this new diagnostic. ### Runtime entries | Entry | Runtime | Receives | Required | | ------------------ | --------------------- | --------------------- | ------------------------------------------------------------------------------- | | `index.client.tsx` | Paseo app, per client | `PluginClientContext` | When the plugin has any UI, callback, theme, or attachment source | | `index.server.ts` | Daemon subprocess | `PluginServerContext` | When the plugin contributes handlers, hooks, settings persistence, or providers | At least one entry is required; both accept `.ts` or `.tsx`. A directory that still has only the old `index.ts` fails to load and points at the [migration guide](/docs/plugins/migration). Plugin, screen, sidebar-item, workspace-panel, Command Center item, attachment-source, and slash-command IDs start with a lowercase letter and contain lowercase letters, numbers, or hyphens. The generated `package.json` installs `@getpaseo/plugin` and the other host modules as development dependencies for local typechecking and tests. Paseo supplies their runtime instances. Consumers do not install them when adding the plugin. Every other module lives in one of three directories. Nesting inside them is fine; a module at the plugin root is a compile error. | Directory | Compiled into | Use it for | | --------- | ------------------ | -------------------------------------------------------------------- | | `client/` | App bundle only | React, React Native, hooks, styles, surfaces, panels, and callbacks. | | `server/` | Daemon bundle only | Node APIs, local resources, credentials, and RPC handlers. | | `shared/` | Both | Zod RPC contracts and plain values imported by both runtimes. | ## Runtime modules Paseo builds each bundle from its matching entry. An import from `client/` into the daemon bundle, from `server/` into the app bundle, or of a Node module anywhere in the app bundle is a compile error. Server imports of React, React Native, or client SDK entries also fail. Shared code imports only shared code: no Node, React, runtime-specific SDK entries, or runtime-specific types. The SDK root (`@getpaseo/plugin`) contains shared data, schemas, and runtime-neutral helpers only. Import client contexts and hooks from `/client`, server contexts and lifecycle contracts from `/server`, and UI from `/client/react-native` or `/client/ui`. These rules include type imports and transitive dependencies. `/client/host` is private to the app host; plugins cannot import it. ### Client runtime Paseo provides these modules to client code: | Module | Use it for | | -------------------------------------- | ------------------------------------------------------------------------------------------------- | | `@getpaseo/plugin` | Shared data, `defineRpc`, `defineSettings`, `defineAttachmentSource`, `RpcInput`, and `RpcOutput` | | `@getpaseo/plugin/client/ui` | Named, composable settings components | | `@getpaseo/plugin/client/react-native` | Paseo UI components and UI hooks | | `@getpaseo/plugin/client` | Client contribution contexts, `usePaseo`, `useRpc`, `useSettings`, and data hooks | | `@tanstack/react-query` | Request state and caching | | `react` | Components and hooks | | `react/jsx-runtime` | Compiled JSX | | `react-native` | Cross-platform UI | | `zod` | Shared schemas | The host owns its paired React and renderer versions. The SDK's React peer range permits patch versions for tooling and Node consumers; it does not change the app's pinned React version or guarantee compatibility with another host's renderer. These exact module specifiers use the host's runtime instances. A client bundle that requests another host module fails with `Module "" is not available in plugin client code`. Do not import `lucide-react-native`, `react-native-svg`, or DOM libraries. Set contribution `icon` fields to a [Lucide icon name](https://lucide.dev/icons/); Paseo validates the name and renders the icon. ### Cross-platform rules Client code runs on iOS, Android, and in browsers through React Native Web. A component that works in your browser and crashes on a phone is the most common plugin bug. The rules: | Do | Do not | | -------------------------------------------------------------------------- | --------------------------------------------------------------------------- | | `View`, `Text`, `Pressable`, `ScrollView`, `TextInput` from `react-native` | `
`, ``, `