跳转到内容
本页面的翻译由 LLM 生成。如果你发现翻译有误,请在 GitHub 上提交 issue 告诉我们。

插件

Preview docs describe unreleased preview builds. Stable docs remain at /docs/.

Nagi 插件是可分享、可执行的工作流包。清单 v2 插件是由 Nagi 托管的 WebAssembly 组件。旧版插件可以是 Bash 脚本、JavaScript 应用、Lua 脚本、Rust 二进制,或你机器上能运行的任何 argv 命令。Nagi 负责宿主侧: 安装、清单校验、按键绑定、终端窗格、事件、调用上下文和 socket 访问。插件负责自己的实现语言、依赖、文件和持久状态。

插件的存在是为了让 Nagi 保持精简。核心继续专注于终端工作区、窗格、 智能体和稳定的 CLI/socket API。插件把这套已有的扩展面变成可复用的 工作流,让大家可以构建、安装和分享,而不必把每种工作流都塞进 Nagi 本体。

插件不是 SDK 集成。它是一个带 nagi-plugin.toml 清单和 Nagi 可启动 命令的目录。Nagi 校验清单、注入运行时上下文、启动声明的命令并记录日志。 命令在需要做更多工作时,通过 CLI 或 socket 回调 Nagi。

对于旧版原生插件,没有单独的插件 SDK,也没有受限的命令集。整个 Nagi CLI 就是插件 API: CLI 参考中的每条命令插件都能用,你自己能以 nagi ... 运行的任何东西,插件也能运行。大多数插件应通过指向运行中 Nagi 二进制的 NAGI_BIN_PATH 调用 Nagi,这样插件在 Unix socket 和 Windows 命名管道之间保持可移植。想自己发送原始 JSON 请求时,使用 socket API

运行时动作注册和非终端的原生插件 UI 不在插件 v1 范围内。动作、事件钩子、 窗格和链接处理器都在清单中声明。

清单 v2 组件通过 WASI Component Model 在 Wasmtime 中运行。Nagi 会限制组件 大小、线性内存、表、实例、输出、fuel 和执行时间,不继承宿主环境、文件系统预打开 路径或网络访问。请求 capability 的组件必须先运行 nagi plugin approve <id> 才能启用。授权绑定到插件版本、清单校验和与包校验和。内容变化后必须重新审核。 nagi plugin revoke <id> 会撤销授权并禁用插件。

授权不会自动生成尚未实现的宿主 API。没有 broker 绑定的 capability 仍不可用, 因此新权限默认保持关闭。

原生插件是运行在你机器上的普通代码。安装或链接一个插件时,它的构建和运行时 命令以你的用户身份、在你的环境中执行,并且可以调用完整的 Nagi CLI — 和你给编辑器、shell 或编程智能体添加的任何扩展一样。这种开放性正是设计 初衷,加上一点判断力就能保持安全。

从你信任的作者和仓库安装插件,并先大致看看新插件做什么: nagi-plugin.toml 清单,以及它运行的脚本或二进制。nagi plugin install 会展示来源、修订版本、 构建命令和无限制访问警告。非交互安装必须同时传入 --yes--trust-native。 本地链接使用 nagi plugin link <path> --trust-native。想固定某个特定版本时用 --ref

Nagi 校验清单,要求明确的信任门槛,清理继承环境,并把每个插件的配置和状态放在 各自的目录中。原生插件本身不在沙箱中运行。旧注册表条目会迁移为禁用且未受信任。

manifest_version = 2
id = "example.review"
name = "Review current mission"
version = "1.0.0"
min_nagi_version = "0.7.4"
runtime = "wasi-component"
entrypoint = "plugin.wasm"
capabilities = []
[[contributions.commands]]
id = "review"
title = "Review current mission"
contexts = ["mission"]

无 capability 的组件可直接用 nagi plugin link ./example-review 链接。 若清单请求 capability,请先审查源码和声明,然后运行:

Terminal window
nagi plugin approve example.review
nagi plugin enable example.review

清单是 Nagi 和插件之间的契约。它声明包元数据、支持的平台、可选的构建 命令,以及 Nagi 可以运行的入口点。

id = "example.layout"
name = "Layout"
version = "0.1.0"
min_nagi_version = "0.7.0"
description = "Apply project layouts"
platforms = ["linux", "macos", "windows"]
[[build]]
command = ["npm", "ci"]
[[build]]
command = ["npm", "run", "build"]
platforms = ["linux", "macos"]
[[actions]]
id = "apply"
title = "Apply layout"
contexts = ["workspace"]
command = ["node", "dist/apply.js"]
[[events]]
on = "worktree.created"
command = ["nagi", "workspace", "list"]
[[panes]]
id = "board"
title = "Project board"
placement = "overlay"
command = ["nagi-board"]
[[link_handlers]]
id = "github-issue"
title = "Open GitHub issue"
pattern = "^https://github\\.com/[^/]+/[^/]+/(issues|pull)/[0-9]+$"
action = "apply"

顶层的 idnameversionmin_nagi_version 是必填项。 把 min_nagi_version 设为支持你插件所用的插件 API、事件名和清单字段的 最老 Nagi 版本。当插件的最低版本比当前二进制更新时,Nagi 会拒绝链接 或安装。description 可选。插件 id 可以使用 ASCII 字母、数字、点、 冒号、下划线和连字符。

动作 id、窗格 id 和链接处理器 id 是插件内部的本地 id。它们可以使用 ASCII 字母、数字、冒号、下划线和连字符,但不能用点。每种 id 在插件内 必须唯一。当需要全局唯一名称时,Nagi 会把动作 id 限定为 plugin.id.action 的形式。

platforms = ["linux", "macos", "windows"] 声明插件可以运行的平台。 构建命令、动作、事件钩子、窗格和链接处理器也可以声明自己的 platforms; 条目级的 platforms 覆盖顶层列表。没有顶层 platforms 的本地插件在链接 时会给出警告。

command 的值是 argv 数组。Nagi 不会通过 shell 运行它们,所以除非你的 命令自己启动 shell,否则没有 shell 展开。语言相关的行为放到你的脚本或 二进制里。

从一个包含 nagi-plugin.toml 和一个可执行脚本或程序的目录开始:

my-plugin/
nagi-plugin.toml
index.js
id = "example.workspace-tools"
name = "Workspace Tools"
version = "0.1.0"
min_nagi_version = "0.7.0"
description = "Small workspace helpers"
platforms = ["linux", "macos", "windows"]
[[actions]]
id = "list-workspaces"
title = "List workspaces"
contexts = ["workspace"]
command = ["node", "index.js"]

在命令内部通过 NAGI_BIN_PATH 回调 Nagi:

const { spawnSync } = require("node:child_process");
const nagi = process.env.NAGI_BIN_PATH ?? "nagi";
const result = spawnSync(nagi, ["workspace", "list"], {
encoding: "utf8",
stdio: ["ignore", "pipe", "pipe"],
});
process.stdout.write(result.stdout);
process.stderr.write(result.stderr);
process.exit(result.status ?? 1);

这个示例用了 Node,但插件本身完全不要求 Node。清单可以启动 Bash、 PowerShell、Python、Rust、Go、Lua、Bun 或用户机器上可用的任何其他命令。

安装一个示例插件:

Terminal window
nagi plugin install owner/nagi-plugin/agent-telegram-notify
nagi plugin config-dir examples.agent-telegram-notify
nagi plugin list
nagi plugin action list --plugin examples.agent-telegram-notify

在本地编写插件时,改为链接工作目录:

Terminal window
nagi plugin link /path/to/plugin
nagi plugin config-dir example.layout
nagi plugin action list --plugin example.layout
nagi plugin action invoke example.layout.apply
nagi plugin pane open --plugin example.layout --entrypoint board
nagi plugin log list --plugin example.layout

plugin install 只接受 GitHub 简写,比如 owner/repo/subdir。它用 git 克隆,在交互式终端展示预览,运行受支持的构建命令,然后把检出保存到 Nagi 管理的插件数据下并注册。非交互式安装用 --yes。重新安装 GitHub 管理的插件会替换该托管检出。不允许覆盖安装到本地链接的插件之上;请先 unlink 或 uninstall 本地插件。plugin installplugin link 会创建 插件的配置和状态目录,plugin config-dir <id> 打印配置目录,方便安装 文档和 shell 脚本使用。

plugin uninstall <id-or-source> 注销插件。对 GitHub 管理的安装,它还会 删除托管检出,并且既接受插件 id,也接受与 install 相同的 owner/repo[/subdir...] 简写。plugin unlink <id> 只注销插件、不动文件, 对本地开发很有用。v1 没有单独的 plugin update;要刷新托管插件,请从 GitHub 重新安装。

示例菜谱仓库是 owner/nagi-plugin。它在子目录中包含 多个独立示例插件,包括 agent-telegram-notifygithub-link-previewdev-layout-bootstrap。这些是供复制的示例,不是持续维护的官方插件。

构建命令在 GitHub plugin install 过程中运行,时机在确认之后、Nagi 注册插件之前。如果构建命令失败,安装中止,插件不会被注册。plugin link 不运行构建命令;本地作者自己构建工作树。构建命令可以生成文件,但在 安装预览之后修改 nagi-plugin.toml 会导致安装中止。构建失败时会显示 插件 id、构建序号、工作目录、命令、退出状态或 spawn 错误,以及截断后的 stdout/stderr,不会解读工具输出。

构建命令同样是普通的 argv 命令,但它们不会收到运行时插件上下文或 Nagi socket 环境变量。插件作者应在文档中说明所需的系统工具,比如 cargonpmbunlua;Nagi 报告构建失败,但不会安装缺失的 工具链。

运行时命令以插件目录为工作目录执行。Nagi 注入 NAGI_SOCKET_PATHNAGI_BIN_PATHNAGI_ENV=1NAGI_PLUGIN_IDNAGI_PLUGIN_ROOTNAGI_PLUGIN_CONFIG_DIRNAGI_PLUGIN_STATE_DIRNAGI_PLUGIN_CONTEXT_JSON,以及可用时的 NAGI_WORKSPACE_IDNAGI_TAB_IDNAGI_PANE_ID。动作命令还会收到 NAGI_PLUGIN_ACTION_ID;事件钩子收到 NAGI_PLUGIN_EVENTNAGI_PLUGIN_EVENT_JSON;窗格命令收到 NAGI_PLUGIN_ENTRYPOINT_ID

NAGI_PLUGIN_ROOT 是已安装或已链接的插件目录。不要把用户凭据或持久 状态放在那里,因为 GitHub 安装的插件根目录是托管的源码检出。把 .env 这类用户可编辑的配置放在 NAGI_PLUGIN_CONFIG_DIR 下,把本地运行时 状态放在 NAGI_PLUGIN_STATE_DIR 下。Nagi 会创建这些目录,并在旧版 插件配置位置存在时把内容初始化到 NAGI_PLUGIN_CONFIG_DIR,但不会校验、 同步或删除其中的内容。文件格式和生命周期归插件所有。

NAGI_PLUGIN_CONTEXT_JSON 在本次调用可用时,可以包含工作区、标签页、 聚焦窗格、worktree、智能体、选中文本、点击的 URL 和链接处理器字段。 shell 插件可以从各个环境变量读取常用 id,或解析上下文 JSON 获取完整结构。

当插件需要从 Node、PowerShell、Bash 或其他运行时可移植地调用 Nagi 时, 使用 NAGI_BIN_PATHNAGI_SOCKET_PATH 背后的原始 socket 传输是 操作系统相关的: Unix 客户端连接 Unix socket 路径,Windows 客户端连接 命名管道。通过 NAGI_BIN_PATH 的 CLI 调用可以避开这种传输差异。可用 命令见 CLI 参考,原始请求结构见 socket API

清单中窗格的 placement 默认为 overlay,它在活动窗格上方打开一个 临时的缩放覆盖层,关闭时恢复之前的焦点和缩放。plugin.pane.open 请求 可以用 overlaypopupsplittabzoomed 覆盖清单的 placement。

placement = "popup" 会打开一个会话级模态终端弹窗,而不改变平铺布局。 可以在清单或 open 请求中指定可选的 widthheight;省略时默认为终端大小的一半,数字表示外层终端单元格数,"80%" 这样的字符串表示终端区域的百分比。 弹窗会接收包括 Escape 在内的所有终端输入,并在命令退出或发送 popup.close 请求时关闭。 小于弹窗最小尺寸的值会限制为最小值。

如果某个插件窗格应始终是临时的,可直接在入口点上声明 placement:

[[panes]]
id = "picker"
title = "Picker"
platforms = ["linux", "macos"]
placement = "popup"
width = "80%"
height = 20
command = ["sh", "picker.sh"]

split、tab、zoomed 和 overlay 插件窗格打开后就是普通的 Nagi 窗格。插件可以通过 socket 或 CLI 调用 pane.movepane.swappane.resizepane.zoom 等标准窗格 API; 窗格跨标签页或工作区移动时,Nagi 会让插件窗格的所有权跟随底层窗格。 弹窗不是 Nagi 窗格,而是会话级单例资源:它没有窗格 id,不会改变插件焦点上下文,不会发出窗格生命周期事件,也不参与 pane、layout、持久化或智能体 API。 其进程不会收到 NAGI_PANE_ID;底层平铺窗格仍可通过 NAGI_PLUGIN_CONTEXT_JSON 获取。 在 Settings、复制模式或其他 Nagi 模态界面打开时尝试打开弹窗会返回 ui_busy;启动成功后,plugin.pane.open 返回 ok

在 Windows 上,构建命令、动作命令和事件命令会在裸命令位于 PATH 上时 解析常见的 PATHEXT shim,比如 npm.cmdbun.cmdpnpm.cmd。 窗格命令使用 Nagi 常规的 Windows 窗格启动器,仍然必须是有效的 Windows argv 命令。

把某个键绑定到已安装的插件动作:

[[keys.command]]
key = "prefix+l"
type = "plugin_action"
command = "example.layout.apply"
description = "apply layout"

[[link_handlers]] 把对匹配终端 URL 的修饰键点击路由到插件动作, 而不是在浏览器中打开 URL。修饰键点击的修饰键在所有平台上都是 Control, 包括 macOS,因为被捕获的终端鼠标上报无法把 Command/Super 和普通点击 区分开。pattern 是对被点击 URL 匹配的 Rust 正则表达式,action 必须 指向同一插件声明的动作。链接处理器动作在 NAGI_PLUGIN_CONTEXT_JSON 中收到 invocation_source = "link_click"clicked_urllink_handler_id;shell 插件也可以读取 NAGI_PLUGIN_CLICKED_URLNAGI_PLUGIN_LINK_HANDLER_ID。每个插件内的处理器按清单顺序检查。

v1 没有 Nagi 管理的插件存储 API。需要持久状态的插件应自己管理文件或 数据库。

公开注册表仍在规划中,目前不会列出插件。GitHub 直接安装和本地链接已经可用, 所以作者可以发布带有 nagi-plugin.toml 的仓库,并分享 nagi plugin install owner/repo[/subdir]

现在添加 nagi-plugin 主题标签不会创建条目。当前边界和上线准备见 插件市场