关于 paseo-plugin
paseo-plugin 是用于构建和管理 Paseo 插件的技能,可扩展应用与守护进程。它指导开发者添加界面、RPC 处理程序和生命周期钩子,并遵循兼容性要求。
主要功能
- 01添加屏幕、面板和命令
- 02注册时间线与附件功能
- 03实现守护进程端插件 RPC
- 04接入 Agent 和工作区生命周期
- 05搭建并检查插件结构
适用场景
- 01构建工作区面板或自定义屏幕
- 02添加斜杠命令或时间线渲染器
- 03连接应用界面与插件专属守护进程行为
- 04通过生命周期钩子配置 Agent 启动
MCP 相关
该技能介绍如何通过创建与启动钩子配置 MCP 服务。它并未将 paseo-plugin 本身描述为 MCP 服务。
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ getpaseo/ paseo --skill paseo-plugin安装后在 Claude Code 中输入/paseo-plugin确认已加载。
详细介绍
Paseo 插件
直接构建或管理所需的插件。使用当前公开文档检查契约变更;如果网络不可用,则继续依据此技能操作。
用户的请求: $ARGUMENTS
检查当前文档
首先获取 https://paseo.sh/llms.txt。在修改插件前,从该索引中选择并获取当前的插件 Markdown 页面:
如果已部署的文档与此技能不一致,请以已部署的文档为准。不要让用户自行阅读文档,而要直接完成工作。
在 Paseo 仓库中,使用 public-docs/plugins/reference.md 查阅此检出版本的 API,包括尚未发布的变更。使用 docs/plugins.md 查阅维护者指南。完整契约应放在公开文档中;此技能用于索引参考资料和示例。
插件可以提供的功能
选择与请求相符的功能。每一行都列出注册项、适用场景,以及完整契约所在的位置。大多数插件会组合多种功能:例如,调用 RPC 的斜杠命令会追加一条时间线记录,再由渲染器绘制出来。
| 贡献内容 | 注册方式 | 适用场景 | 参考 |
|---|---|---|---|
| 屏幕和侧边栏项 | addScreen + addSidebarHeaderItem/addSidebarFooterItem | 插件 UI 的完整屏幕,或可打开屏幕或弹出层的侧边栏页眉或页脚行 | reference.md → 屏幕和侧边栏项 |
| 工作区面板 | addWorkspacePanel | 位于 Agent、终端、文件和差异旁边标签页中的 UI;在 Explorer 中使用 locations: ["explorer"] | reference.md → 工作区面板 |
| 文件面板 | addFilePanel | 通过文件句柄在文件标签页中查看或编辑匹配的文件 | reference.md → 文件面板;plugin-examples/pdf-panel、plugin-examples/markdown-panel |
| Command Center 项 | addCommandCenterItem | 可通过 ⌘K 访问的全局、工作区或 Agent 操作 | reference.md → Command Center 项 |
| 客户端斜杠命令 | addSlashCommand | 在编辑器中输入 /command args,运行插件代码而非向 Agent 提示 | reference.md → 斜杠命令 |
| 编辑器胶囊 | addComposerPill | 编辑器轨道栏中 Tasks 和 Subagents 旁边的每个 Agent 专属按钮 | reference.md → 编辑器胶囊 |
| 时间线转换器 | addTimelineTransformer + addTimelineRenderer | 替换、展开或隐藏内置时间线项,包括其流式传输期间 | reference.md → 时间线项;plugin-examples/timeline-items、plugin-examples/inline-thinking |
| 时间线行 | paseo.agents.ref(id).timeline.append(...) | 从服务端处理程序将插件拥有的行推送到 Agent 时间线,并在之后更新 | reference.md → 从守护进程追加时间线行 |
| 附件来源 | client.addAttachmentSource + server.handle | 让用户将可搜索的外部资源(例如问题)附加到提示词 | reference.md → 添加编辑器附件来源;plugin-examples/linear |
| 主题 | addTheme | Settings → Appearance 下的浅色或深色调色板 | reference.md → 提供主题;plugin-examples/catppuccin |
| 插件 RPC | defineRpc + server.handle + useRpc | 非常规 Paseo 操作的守护进程端任务:供应商 API、凭据、本地文件 | reference.md → 添加插件专属后端行为 |
| 生命周期事件 | server.on | 观察 Agent/工作区生命周期、检查已结束的轮次并响应权限请求 | 生命周期钩子 |
| 创建和启动钩子 | server.before | 在操作前更改 Agent 配置、提供方选项、MCP 服务、环境或工作区隔离 | Before 钩子 |
| Paseo SDK | usePaseo() / handler { paseo } | 常规 Paseo 操作:工作区、Agent、提供方、配置 | reference.md → 使用 Paseo SDK |
| 生命周期任务 | 示例 | ||
| ------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------ | ||
| 记录全部 11 个钩子 | lifecycle-logger | ||
| 后续操作、权限、环境、提供方切换、工作树 | lifecycle-actions | ||
| 注入 MCP 服务并更改 Codex 沙盒/审批选项 | agent-configuration |
创建项目
请使用守护进程所在机器上的绝对路径。init 会写入文件,但不会安装软件包。
paseo plugin init /absolute/path/to/my-plugin
cd /absolute/path/to/my-plugin
npm install
生成的项目包含:
my-plugin/
paseo-plugin.json
OVERVIEW.md
package.json
tsconfig.json
index.client.tsx
index.server.ts
client/greeting.tsx
server/greeting.ts
shared/greeting.ts
清单提供默认安装 ID 和支持的 Paseo 版本:
{ "id": "my-plugin", "requirements": { "paseo": ">=0.8.0" } }
创建或编辑插件时,请确保 requirements.paseo 正确无误。init 使用 >=,后跟 CLI 版本。采用较新的 API 时,请提高最低版本要求;若后续 Paseo 版本不兼容,请添加上限。使用 npm semver 范围,并在面向 beta 版本时明确包含 beta 版本。缺少 requirements 表示 <0.8.0;添加 >=0.8.0 之前,请先完成 0.8 条目迁移。请使用守护进程和运行客户端贡献的应用验证兼容性。
参见requirements。
每个运行时都有各自可选的入口。插件必须至少有一个入口。两个入口都接受
.ts 或 .tsx;入口导入组件时请使用 .tsx。
| 路径 | 运行时 |
|---|---|
index.client.tsx 和 client/ | 应用 |
index.server.ts 和 server/ | 守护进程子进程 |
shared/ | 两者 |
不要在插件根目录中放置其他代码模块。
客户端导入 server/、服务端导入 client/,以及客户端代码可触达的所有 node: 导入,都会导致编译错误。相对导入插件根目录中的其他代码文件也会导致编译错误;请将其移至 client/、server/ 或 shared/。共享模块包含 Zod 契约和纯值;它们不会导入 Node 或 React Native 运行时 API。
在每个入口中默认导出一个贡献函数,并返回清理函数:
// index.client.tsx
import type { PluginClientContext } from "@getpaseo/plugin/client";
export default function contribute(client: PluginClientContext) {
// Register components and client callbacks here.
return () => {};
}
// index.server.ts
import type { PluginServerContext } from "@getpaseo/plugin/server";
export default function contribute(server: PluginServerContext) {
// Register daemon-side RPC handlers here.
return () => {};
}
清理操作可以是异步的。请用它清理插件代码创建的计时器、监视器、套接字、订阅及其他资源。每个客户端 add* 方法都会返回一个幂等移除函数。插件停止时,Paseo 会先调用入口清理函数,移除仍然存在的注册项,拒绝待处理的 RPC,关闭插件会话,并停止子进程。
添加工作区面板
工作区面板与 Agent、终端、文件和差异视图并列。插件可在桌面端和移动端运行,Paseo 也支持多种主题。每个 Text 都必须从 theme.colors 获取颜色。请使用 layout.compact 控制内边距和堆叠方式。未设置样式的文本为黑色,在深色主题下会显示异常。
import {
type PluginClientContext,
type PluginWorkspacePanelProps,
useWorkspace,
} from "@getpaseo/plugin/client";
import { useMemo } from "react";
import { Text, View } from "react-native";
function Overview({ theme, layout, workspaceId }: PluginWorkspacePanelProps) {
const name = useWorkspace(workspaceId, (workspace) => workspace.name);
const styles = useMemo(
() => ({
screen: {
flex: 1,
padding: layout.compact ? 16 : 24,
gap: layout.compact ? 8 : 12,
backgroundColor: theme.colors.surface0,
},
title: { color: theme.colors.foreground, fontSize: layout.compact ? 20 : 24 },
}),
[theme, layout.compact],
);
return (
<View style={styles.screen}>
<Text style={styles.title}>{name}</Text>
</View>
);
}
export default function contribute(client: PluginClientContext) {
client.addWorkspacePanel({
id: "overview",
title: "Workspace overview",
icon: "PanelsTopLeft",
context: "workspace",
Component: Overview,
});
client.addCommandCenterItem({
id: "open-overview",
title: "Open workspace overview",
icon: "PanelsTopLeft",
context: "workspace",
onSelect({ openPanel }) {
openPanel("overview");
},
});
return () => {};
}
请使用 useWorkspace(id, selector) 和 useAgent(id, selector)。必须提供选择器,
其结果使用浅比较。切勿选择整个快照,也不要添加 RPC 来发现当前工作区或 Agent。
命令回调会接收所选宿主的 paseo、类型化的 rpc(contract, input)、openScreen({ screenId, params? }) 和上下文相关的 openPanel(id) 能力。
添加屏幕和侧边栏项
插件屏幕使用 React Native 基本组件,可在桌面端、浏览器、iOS 和 Android 上运行。侧边栏项位于页眉或页脚,是一个组件:从 @getpaseo/plugin/client/ui 渲染一个或多个 SidebarRow,并在各组之间插入 SidebarSeparator,然后从中调用 openScreen 或 openPopover。屏幕的 title 是字符串或一个根据其 params 生成字符串的函数;屏幕组件会收到打开屏幕时传入的 params。使用 theme.colors 设置文字颜色,使用 layout.compact 设置内边距。
import type {
PluginClientContext,
PluginScreenProps,
PluginSidebarItemProps,
} from "@getpaseo/plugin/client";
import { SidebarRow } from "@getpaseo/plugin/client/ui";
import { useMemo, useState } from "react";
import { Pressable, Text, View } from "react-native";
function Counter({ theme, layout }: PluginScreenProps) {
const [count, setCount] = useState(0);
const styles = useMemo(
() => ({
screen: {
flex: 1,
padding: layout.compact ? 16 : 24,
gap: 16,
backgroundColor: theme.colors.surface0,
},
count: { color: theme.colors.foreground, fontSize: layout.compact ? 36 : 48 },
button: { padding: 14, borderRadius: 10, backgroundColor: theme.colors.accent },
buttonText: { color: theme.colors.accentForeground, textAlign: "center" as const },
}),
[theme, layout.compact],
);
return (
<View style={styles.screen}>
<Text style={styles.count}>{count}</Text>
<Pressable
accessibilityRole="button"
accessibilityLabel={`Increment counter, currently ${count}`}
onPress={() => setCount((value) => value + 1)}
style={styles.button}
>
<Text style={styles.buttonText}>Count me in</Text>
</Pressable>
</View>
);
}
function CounterItem({ currentScreen, openScreen }: PluginSidebarItemProps) {
return (
<SidebarRow
icon="ListPlus"
active={currentScreen?.screenId === "main"}
onPress={() => openScreen({ screenId: "main" })}
/>
);
}
export default function contribute(client: PluginClientContext) {
client.addScreen({ id: "main", title: "Counter", Component: Counter });
client.addSidebarHeaderItem({ id: "main", title: "Counter", Component: CounterItem });
return () => {};
}
图标可以是 Lucide 图标名称、内联 SVG({ svg })或组件;请参阅图标。每个屏幕和面板上的 theme 都是类型化的 PluginTheme。主要文字使用 theme.colors.foreground;标签使用 theme.colors.foregroundMuted;根视图使用 theme.colors.surface0。在移动设备和窄窗口中,layout.compact 为 true。Paseo 负责路由、页眉、主机选择器、关闭操作、错误边界,以及每个安装实例各自的查询客户端。
编写导入语句前,先将每个模块归类为 shared、client 或 server。遵循
SDK 导入边界,包括传递依赖和类型依赖。根目录仅允许 shared 模块;钩子和客户端上下文属于 @getpaseo/plugin/client,服务端上下文属于 /server,主机 UI 属于 /client/ui。
在本地安装依赖以进行类型检查;Paseo 会提供主机运行时模块。JSX 使用自动运行时。不要在插件代码中导入 /client/host。
支持移动设备
报告插件已完成前:
- 仅使用 React Native 基本组件:
View、Text、Pressable、ScrollView和TextInput。 - 不要使用 HTML 元素、
className、CSS 字符串或onClick。 - 不要在
tsconfig.json中加入"DOM",也不要使用/// <reference lib="dom" />。仅在client/web.ts中使用 DOM 全局变量,并且只声明该模块实际使用的变量;每个导出都必须以Platform.OS === "web"为条件,并提供原生替代实现或空操作。 - 从
theme.colors获取颜色。 - 检查紧凑布局。
在 client/ 上运行此检查:
rg -n "document\.|window\.|localStorage|navigator\.|<[a-z]+[ >]|className=|onClick=" client/
在 client/web.ts 之外发现匹配项即为错误。
选择正确的 API
常规 Paseo 操作使用现有的 Paseo SDK。仅在处理插件专属的后端行为时使用插件 RPC。
在界面中调用 Paseo
usePaseo() 会借用当前选定主机的连接。不要在界面中创建另一个客户端。它是插件在每个界面中唯一的客户端:在清理时释放订阅;其余部分会在插件拆卸时结束。
import { usePaseo } from "@getpaseo/plugin/client";
function PullRequestAction() {
const paseo = usePaseo();
async function createReviewWorkspace() {
const workspace = await paseo.workspaces.create({
title: "Review PR 42",
source: {
kind: "worktree",
cwd: "/absolute/path/to/repository",
action: "checkout",
checkoutSource: { kind: "change_request", forge: "github", number: 42 },
},
});
await workspace.agents.create({
config: { provider: "codex/gpt-5.5" },
prompt: "Review PR #42.",
});
}
// Wire createReviewWorkspace to a Pressable.
return null;
}
该 API 涵盖工作区、Agent、提供商和守护进程配置。由于连接由 Paseo 管理,因此不包含连接生命周期相关功能。方法详情请参阅最新的 SDK 参考。
添加守护进程端行为
在 shared/ 中定义一个 Zod 契约,在 index.server.ts 中注册其子进程处理程序,
并在客户端代码中使用 useRpc() 调用它:
// shared/greeting.ts
import { defineRpc } from "@getpaseo/plugin";
import { z } from "zod";
const greeting = defineRpc({
name: "greeting.create",
input: z.object({ name: z.string() }),
output: z.object({ message: z.string() }),
});
// server/greeting.ts
import type { RpcInput } from "@getpaseo/plugin";
import { greeting } from "../shared/greeting";
export async function createGreeting({ name }: RpcInput<typeof greeting>) {
return { message: `Hello, ${name}!` };
}
// index.server.ts
import type { PluginServerContext } from "@getpaseo/plugin/server";
import { createGreeting } from "./server/greeting";
import { greeting } from "./shared/greeting";
export default function contribute(server: PluginServerContext) {
server.handle(greeting, createGreeting);
return () => {};
}
// client/greeting.tsx
import { useRpc } from "@getpaseo/plugin/client";
import { greeting } from "../shared/greeting";
function Greeting() {
const createGreeting = useRpc(greeting);
// Use createGreeting({ name: "Ada" }) in a query, mutation, or event.
return null;
}
输入和输出都会在两端进行验证。后端处理程序会收到同一个 PaseoApi,形式为 { paseo };其基于 IPC 的守护进程会话与子进程的生命周期完全相同。后端代码可以使用 Node API 和已安装的依赖项。凭据、文件系统访问、shell 命令和供应商 API 调用应放在处理程序中,而不是客户端界面中。
使用 TanStack Query 管理异步请求状态、缓存和变更。
调试守护进程端的行为
后端贡献可以使用常规的 Node 日志记录。console.log() 会写入插件的 stdout;
console.error() 会写入 stderr。Paseo 会捕获这两个流,且不会干扰插件 IPC。
安装、重新加载、RPC 失败或子进程崩溃后,查看近期输出:
paseo plugin logs my-plugin
paseo plugin logs my-plugin --json
paseo plugin logs my-plugin --host <url>
也可以在 Settings → Plugins → Logs 中查看相同的日志尾部。内容包括初始化、处理程序、 清理和最终崩溃输出。重新加载、禁用和进程失败时会保留日志尾部。移除插件会清除日志;重启守护进程会清除内存中的日志尾部。结构化副本也会写入守护进程日志。切勿记录凭据或其他机密信息。
添加撰写器附件来源
在 shared/ 中定义搜索 RPC 和声明式来源,在服务端处理,并在客户端注册:
// shared/issues.ts
import { defineAttachmentSource, defineRpc } from "@getpaseo/plugin";
import { z } from "zod";
const searchIssues = defineRpc({
name: "issues.search",
input: z.object({ query: z.string() }),
output: z.object({
items: z.array(
z.object({
id: z.string(),
identifier: z.string(),
title: z.string(),
subtitle: z.string().optional(),
url: z.string().url(),
text: z.string(),
resourceType: z.string(),
}),
),
}),
});
const issues = defineAttachmentSource({
id: "issues",
title: "Acme issue",
icon: "CircleDot",
pickerTitle: "Attach Acme issue",
searchPlaceholder: "Search by identifier or title",
search: searchIssues,
});
// index.server.ts
import type { PluginServerContext } from "@getpaseo/plugin/server";
import { searchIssues } from "./shared/issues";
export default function contribute(server: PluginServerContext) {
server.handle(searchIssues, ({ query }) => searchAcmeIssues(query));
return () => {};
}
// index.client.tsx
import type { PluginClientContext } from "@getpaseo/plugin/client";
import { issues } from "./shared/issues";
export default function contribute(client: PluginClientContext) {
client.addAttachmentSource(issues);
return () => {};
}
返回完整的文本快照。撰写器菜单、选择器、标签、草稿和提交均由 Paseo 管理。凭据和供应商调用留在守护进程处理程序中。
添加客户端斜杠命令
用户提交 /name args 时,斜杠命令会在应用中运行插件代码。不会向 Agent 发送任何内容。args 是命令名称之后经过修剪的原始文本;请在插件中解析。
client.addSlashCommand({
name: "review",
description: "Run the review bot",
argumentHint: "[scope]",
context: "agent", // or "workspace" so drafts get it too
async onSubmit({ args, agent, rpc, openPanel }) {
await rpc(startReview, { agentId: agent.id, scope: args });
openPanel("review");
},
});
回调接收的上下文与匹配的 Command Center 项目相同,另加 args。自动补全行、清空输入和错误提示均由 Paseo 管理;请将待处理的界面放在标签或面板中。优先级依次为内置客户端命令、插件命令、供应商命令;低优先级的冲突命令会被丢弃。撰写器含有附件时不会运行命令。服务端不存在斜杠命令。
添加撰写器标签
标签是撰写器轨道栏中每个 Agent 各自的按钮,位于 Tasks 和 Subagents 旁边。通过客户端入口的生命周期添加和移除标签。PluginClientContext 上提供了 addComposerPill。
import type { PluginButtonRegistration, PluginClientContext } from "@getpaseo/plugin/client";
export function contributeClient(client: PluginClientContext) {
const pills = new Map<string, PluginButtonRegistration>();
const lifetime = new AbortController();
const register = (agent: { id: string; workspaceId?: string | null }) => {
if (lifetime.signal.aborted || !agent.workspaceId) return;
const agentId = agent.id;
const workspaceId = agent.workspaceId;
pills.get(agentId)?.remove();
pills.set(
agentId,
client.addComposerPill({
id: "review",
workspaceId,
agentId,
button: {
title: "Open review",
icon: "Scan",
label: "Review",
behavior: {
kind: "action",
onPress() {
client.openPanel("review", { workspaceId, agentId });
},
},
},
}),
);
};
const removeAll = () => {
for (const pill of pills.values()) pill.remove();
pills.clear();
};
// An owned list subscription delivers existing agents, then updates, and a fresh snapshot after a reconnect.
void client.paseo.agents
.list({ subscribe: {}, signal: lifetime.signal })
.then(({ subscription }) => {
subscription.subscribe({
snapshot: ({ entries }) => {
removeAll();
for (const { agent } of entries) register(agent);
},
update: (message) => {
if (message.type !== "agent_update") return;
const update = message.payload;
if (update.kind === "upsert") return register(update.agent);
pills.get(update.agentId)?.remove();
pills.delete(update.agentId);
},
});
return undefined;
})
.catch((error) => {
if (!lifetime.signal.aborted) console.error("Agent observation failed", error);
});
return () => {
lifetime.abort();
removeAll();
};
}
从 index.client.tsx 调用 contributeClient(client),或将其主体移入该入口。button 描述符用于设置图标、标签和行为;可按下的按钮、外观、待处理状态、错误报告和位置均由 Paseo 管理。addComposerPill 会返回一个包含 update() 和 remove() 的注册对象。remove() 可重复调用;插件、客户端入口或主机连接关闭时,Paseo 会移除所有标签。
转换和渲染时间线项目
时间线转换器和渲染器是客户端贡献。转换器选择一个内置的 AgentTimelineItem.type,检查该项目,并返回零个或多个带版本的插件项目。undefined 会保留源项目,items 会替换源项目,[] 会移除源项目。渲染器在使用其 Zod 架构验证 data 后,绘制一个 kind 和 version。
client.addTimelineTransformer({
id: "inline-thinking",
query: { itemType: "reasoning" },
transform: ({ item, phase }) => ({
items: [
{ type: "plugin", kind: "inline-thinking", version: 1, data: { text: item.text, phase } },
],
}),
});
client.addTimelineRenderer({
kind: "inline-thinking",
version: 1,
schema: z.object({ text: z.string(), phase: z.enum(["streaming", "complete"]) }),
Component: InlineThinking,
});
构建渲染模型时会运行转换器,包括获取历史记录时和每次实时更新时,因此对于正在加载的思考内容或正在运行的工具调用,phase 为 "streaming"。身份来自源项目,因此流式项目会保留其已挂载的组件;如果一个源项目拆分为多个项目,请设置输出 id。转换器必须同步且具确定性,data 必须是 JSON;抛出异常的转换器会被记录并跳过。对于节奏化显示的助手文本,请从 @getpaseo/plugin/client/ui 渲染 <StreamedText text={text} phase={phase} />;使用其 style 属性自定义文本外观。plugin-examples/inline-thinking 会将思考行替换为行内文本;plugin-examples/timeline-items 会将待办工具调用替换为任务卡片。
从守护进程追加时间线行
服务器处理程序可以将插件拥有的行推送到任意 Agent 时间线中。同一渲染器注册项会负责绘制它。
server.handle(publishReview, async ({ agentId, verdict }, { paseo }) => {
await paseo.agents.ref(agentId).timeline.append({
type: "plugin",
id: "review",
kind: "review-result",
version: 1,
data: { verdict },
});
return {};
});
守护进程会根据插件会话为 pluginId 添加标记,因此只有插件代码可以调用此功能。使用相同的 id 再次追加时,会实时替换之前的行,也会在重新获取时替换,这是插件更新行的方式。序列化后的 data 上限为 64 KiB,超过此限制会被拒绝。行保存在守护进程的内存时间线中,在滚动、重新获取和重新连接后仍会保留,但守护进程重启后不会保留。缺少对应插件的行会显示为不可用占位内容。主机通过 server_info.features.pluginTimelineItems 声明支持此功能。
贡献主题
addTheme 接受小型浅色或深色调色板;Paseo 会将其扩展为完整的令牌集。所有颜色都必须是十六进制字符串。
client.addTheme({
id: "mocha",
name: "Catppuccin Mocha",
appearance: "dark",
colors: {
background: "#1e1e2e",
foreground: "#cdd6f4",
raised: "#313244",
control: "#45475a",
border: "#45475a",
accent: "#cba6f7",
mutedForeground: "#a6adc8",
ring: "#6c7086",
},
});
主题会显示在 Settings → Appearance 中。不支持 addTheme 的旧版客户端无法处理该条目,并会报告 client.addTheme is not a function;请更新客户端。参见 plugin-examples/catppuccin。
主机与信任
插件按守护进程安装,属于受信任的非沙箱代码。后端代码可以访问守护进程所在机器上的文件、进程、凭据和网络服务。客户端贡献代码在 Paseo 应用内运行。请勿安装用户未授权的插件,也不要安装未经检查源代码的插件。
安装前检查全局开关
确定目标守护进程,并检查其 config.json 中的根级 pluginsEnabled 值。对于本地守护进程,paseo daemon status --json 会报告其 home;配置文件路径为 <home>/config.json。如果字段缺失,则视为 false。不要根据插件的 disabled 状态推断全局值,因为单个插件也可以单独禁用。
如果 pluginsEnabled 已经是 true,则继续操作,无需询问用户是否启用。
如果该值为 false 或字段缺失,请停止操作,并在编辑或启用任何内容前征得用户明确许可。请求中须包含以下警告:
插件是受信任的非沙箱代码。后端插件代码可以访问你的守护进程所在机器,包括文件、进程、凭据和网络服务。客户端插件代码在 Paseo 应用内运行。我可以在此守护进程上启用插件吗?
用户同意后,执行以下操作:
- 保留
config.json的其余内容,并将根级pluginsEnabled字段设为true。 - 针对该守护进程运行
paseo reload --json。 - 确认
appliedPaths中包含pluginsEnabled;若appliedPaths为空,只有在重新读取文件并确认实时插件目录已启用后才可接受。 - 运行
paseo plugin ls,并确认安装后目标插件状态变为running。
如果用户要求关闭全局开关,请将 pluginsEnabled 设为 false,运行 paseo reload --json,并确认已配置的插件状态显示为 disabled。
如果目标是远程守护进程,请勿编辑本地配置。请在守护进程所在机器上进行编辑,或让用户使用 Settings → Plugins → Enable plugins。paseo reload --host <url> 会重新加载远程守护进程自己的配置文件,但不会编辑该文件。
当多个已连接主机上存在相同的屏幕或侧边栏项目时,Paseo 只显示一次。屏幕标题栏中有主机选择器;侧边栏项目使用当前显示屏幕所属的主机,否则使用该插件某个屏幕中上次选定的主机。选定的主机负责提供资源包、SDK 调用、RPC 和查询缓存。选定主机离线时,不会切换到其他主机。附件来源始终限定在编写器所属的主机范围内。
发布列表条目
在 paseo-plugin.json 旁边编写 OVERVIEW.md,用于展示 Paseo 中的插件页面。
它能帮助用户决定是否安装插件;该页面顶部已经提供安装命令。README 面向 GitHub 用户,
包含安装说明、技术细节和徽章。篇幅过长的 AI 生成 README 会让用户不得不先读完这些内容,
才能了解插件的用途。
要在注册表中列出插件,必须提供 OVERVIEW.md。在固定的提交版本中,将它与
paseo-plugin.json 一起提交到源代码仓库。注册表会相对于清单文件解析其位置;对于单体仓库,
则在 pluginPath 下解析。还要将它包含在已发布的 npm 包中;脚手架的 files 列表已包含此文件。
发布前,请将脚手架中的指导性注释替换为有用的信息。
仓库中的概述优先于注册表中的临时替代文件。如果固定的提交中没有 OVERVIEW.md,在线验证就会失败;
唯一例外是未更改的导入记录,且注册表仓库中已包含 plugins/<owner>/<slug>.md。每次提升版本号都必须提供
仓库概述,并在同一个 PR 中移除临时替代文件。未提供仓库概述的版本更新会导致验证失败。README 不能替代概述。
作者编写的概述和注册表临时替代文件遵循相同的内容要求,并按以下顺序组织。 仅在有帮助时使用标题;篇幅根据复杂程度而定。主题只需一段文字。
- 首先用通俗的语言说明插件是什么以及它的用途。
- 仅在工作原理不明显时,说明它如何工作。
- 必要时说明设置方法:设置项、账户、令牌、提供商、外部工具或其他 插件。注明适用的守护进程版本和操作系统要求。可以提供设置指南,但不能提供安装说明。
- 说明值得了解的功能和设置、各选项的作用、插件读取或发送哪些内容以及发送到哪里、权限和已知限制。
使用句首字母大写的标题格式和客观直白的语言,不要使用 em dash。省略安装命令、 徽章、更新日志、贡献或许可章节、营销内容和未经支持的声明。 避免加入没有意义的实现细节,例如空的清理函数、主题令牌字段目录, 或不存在的功能列表。只保留有助于用户选择插件的内容。
如果你的插件是未更改的导入记录,可以提议用作者编写的概述替换注册表临时替代文件。
不要在自己的 OVERVIEW.md 中添加导入致谢。
参见你的列表页面。
类型检查与管理
编辑插件时,在安装或重新加载前对其源代码进行类型检查:
npm run typecheck
paseo plugin install /absolute/path/to/plugin
paseo plugin install /absolute/path/to/plugin --id another-runtime-id
paseo plugin install npm:@acme/paseo-review
paseo plugin install npm:@acme/[email protected]
paseo plugin install github:owner/repository
paseo plugin install github:owner/repository --ref main
paseo plugin update my-plugin
paseo plugin ls
paseo plugin reload my-plugin
paseo plugin logs my-plugin
paseo plugin disable my-plugin
paseo plugin enable my-plugin
paseo plugin remove my-plugin
对于 npm,请确保 npm 位于守护进程的 PATH 中;使用该主机的注册表配置和凭据。安装选择器只会选择一次内容;
不会固定更新版本。install 和 add 是别名。请遵循
Paseo 发布指南,了解 Paseo 的软件包内容和
准备要求;标准 npm 发布命令仍然适用。
管理非 CLI 默认目标的守护进程时,请使用 --host <url>。必须安装或生成内容的 Git 源代码,应在
paseo-plugin.json 中将 build 声明为 argv 数组列表;Paseo 会在安装和更新时不经 shell 直接运行这些命令,
如果有任何命令失败,就会保留旧版本。修改插件源代码后,必须运行 paseo plugin reload;更改全局开关的配置后,
必须运行 paseo reload。插件重新加载失败后会保持失败状态;查看 paseo plugin ls 获取加载错误,
查看 paseo plugin logs <id> 获取子进程输出,然后修复源代码、进行类型检查并再次重新加载。remove 会保留本地源代码目录,并删除由 Paseo 管理的 Git/npm 安装。
不要为了加载源代码更改而重启守护进程。重启可能会终止正在执行工作的 Agent。
对于旧式混合条目,请按独立运行时条目迁移指南逐步操作。
验证结果
完成更改后:
- 运行
npm run typecheck。 - 安装或重新加载确切的运行时 ID。
- 运行
paseo plugin ls,确认状态为running且没有错误。 - 在目标宿主中确认贡献内容。按 ⌘K(macOS)或 Ctrl+K(Windows/Linux)打开命令中心。在编辑器中输入
/可查看斜杠命令。对于时间线相关工作,运行一个会生成源条目的 Agent 轮次,并在其流式输出期间观察,而不只是等它完成。对于 UI 相关工作,检查宽屏桌面窗口和紧凑型/移动客户端,并切换主题,确认文本仍使用foreground/foregroundMuted。 - 测试更改后的操作或 RPC,包括其错误状态。
常见故障:
- 侧边栏条目缺失:宿主错误、插件状态不是
running、该条目在“设置”>“侧边栏”中被隐藏,或其组件抛出异常(使用未知 Lucide 名称或不安全 SVG 的SidebarRow会抛出异常)。 - 客户端模块不可用:客户端捆绑包只能使用上文列出的宿主提供模块。
- RPC 被拒绝:输入或输出未通过 Zod 架构验证,或处理程序抛出异常。查看
paseo plugin logs <id>获取处理程序输出。 - 插件退出或重新加载失败:查看
paseo plugin ls获取状态,并查看paseo plugin logs <id>获取初始化、清理或崩溃输出。 - UI 未更新:编辑了源文件,但没有运行
paseo plugin reload <id>。 - 时间线条目显示“Plugin timeline item unavailable”:未为该
kind和version注册渲染器、渲染器架构拒绝了data,或插件未在该宿主上运行。 - 转换器不起作用:
query.itemType与源类型不匹配、转换返回了undefined,或转换抛出异常并被跳过;检查应用控制台中的[Plugins] Timeline transformer failed。 - 未提供斜杠命令:名称与内置命令或其他插件的命令冲突、草稿的上下文为
agent,或编辑器中有附件。 - 追加被拒绝:调用方不是插件会话、
data超过 64 KiB,或宿主版本早于features.pluginTimelineItems。