背景
HAPI 目前已经覆盖 CLI、Hub、Web、Runner、通知、语音、实时同步、远程控制、权限审批等多个模块。随着使用场景增长,越来越多需求呈现出相同模式:
- 只服务部分用户或特定环境;
- 与某个外部平台、某个 Agent、某种系统环境强绑定;
- 合入 core 会增加配置项、依赖、测试矩阵和长期维护成本;
- 不合入 core 时,用户只能维护 fork 或重复提交类似 PR;
- 多个功能需求本身并不改变 HAPI 的核心协作模型,更适合作为可选能力存在。
因此建议为 HAPI 引入一个轻量、本地优先、可审计的插件系统,用于承接通知渠道、Agent adapter、语音 provider、Web power-user UI、环境 workaround 等可选能力。
目标
插件系统的目标不是把 HAPI 改造成大型平台生态,而是提供一个明确边界:
- core 保持小而稳定;
- 可选集成不再持续进入主线;
- 用户可以按需启用本地插件;
- 插件通过 manifest 声明能力、配置、权限与运行位置;
- 插件失败不影响核心会话、权限、安全和数据一致性;
- Web 扩展优先使用声明式 descriptor,不执行任意第三方 JS。
需求依据
基于截至 2026-05-19 的公开 issue/PR 快照,本地整理出 71 个高信号候选项。候选项主要集中在以下方向:
| 类别 |
数量 |
结论 |
| notification-channel |
8 |
最高优先级;Feishu、Bark、WeCom、QQ 等需求重复出现,边界清晰。 |
| voice-provider |
5 |
需要 provider 抽象;已有 pluggable backend 相关 PR。 |
| agent-adapter |
6 |
新 coding CLI 不应继续写死进 core enum。 |
| agent-capability |
12 |
Codex/profile/history/usage/skill 等 provider-specific 能力需要能力接口。 |
| web-ui-extension |
12 |
power-user UI 和 renderer 需求较多,应声明式扩展,避免任意前端 JS。 |
| policy-settings |
7 |
用户偏好、模型、权限模式等会持续增长。 |
| environment-workaround |
8 |
Windows、WSL、proxy、tmux 等适合局部插件或策略扩展。 |
| deployment-pack |
3 |
部署方案更适合作为 recipe/distribution pack。 |
| integration-protocol |
2 |
MCP/A2A 等协议集成需要 core extension point 后再插件化。 |
| core-not-plugin |
8 |
权限、安全、数据丢失、核心传输 bug 不应插件化。 |
适合插件化的功能类型
1. 通知渠道
Feishu、Bark、WeCom、QQ 等通知渠道需求重复出现。它们通常需要:
- 平台 webhook;
- token/secret;
- callback route;
- permission approve/deny;
- 平台专属消息格式;
- 平台专属错误处理。
这类功能对部分用户非常重要,但不适合全部进入 core。插件系统可以让通知渠道以独立包存在,core 只维护统一的 notification extension point。
2. Agent adapter
PI、Kilo、CodeBuddy、Copilot CLI、OpenClaw 等新 Agent 需求说明,Agent 类型不应长期依赖固定 enum。
更合理的方式是由插件提供 AgentDescriptor:
- agent id;
- display name;
- supported modes;
- model/permission/profile capabilities;
- session discovery 能力;
- runner command adapter;
- Web new-session fields。
Hub/Web/CLI/Runner 通过 descriptor 识别能力,而不是为每个 Agent 修改多处 hard-code。
3. Voice provider
Gemini Live、Qwen Realtime、MiniMax Speech、dictation modes 等需求适合 provider 模式。
Voice provider 插件可以提供:
- token provider;
- realtime bridge;
- provider-specific config;
- Web voice mode descriptor;
- tool schema;
- lifecycle hooks。
4. Web power-user UI
多会话 grid、pinned sessions、inline image renderer、file autocomplete、batch actions 等需求对高级用户价值高,但默认合入主 UI 会增加复杂度。
Web 插件建议采用 declarative descriptor:
- session actions;
- session badges;
- safe tool result renderer;
- settings panels;
- new-session fields;
- composer suggestions。
Web 端只映射到 core 内置组件,不执行插件 JS。
5. 环境与本地工作流
Windows path resolver、WSL identity、proxy bypass、tmux runner、agent storage scanner 等需求与本机环境强相关。
这些能力适合作为 CLI/Runner 插件:
- command resolver;
- runner spawn strategy;
- environment detector;
- machine metadata provider;
- agent storage scanner;
- terminal attach provider。
不适合插件化的核心边界
以下内容应继续由 core 负责:
- auth / JWT / token / namespace 隔离;
- permission flow correctness;
- SQLite schema / migrations;
- Socket.IO / RPC / SSE 基础传输;
- session cache consistency;
- message ordering / loss recovery;
- runner trust boundary;
- terminal/file access 基础权限;
- core error propagation;
- 数据丢失与权限审批问题的根因修复。
插件可以扩展 provider、显示和策略,但不应绕过 core 的安全与一致性路径。
设计原则
Manifest-first
插件必须提供静态 manifest。core 应能在不执行插件代码的前提下读取:
- id;
- name;
- version;
- pluginApiVersion;
- compatibility;
- runtime entrypoints;
- static contributions;
- permissions;
- network allowlist;
- secrets;
- config schema。
插件列表、风险提示、设置页、新建会话 Agent 列表等,应尽量来自 manifest 或 descriptor。
Registry-first
引入中心 PluginRegistry,统一管理:
- discovered;
- validated;
- enabled;
- active;
- degraded;
- failed;
- disabled;
- diagnostics;
- contributions;
- registered extension points;
- disposables。
插件不应直接修改 core global singleton。
明确运行位置
插件应显式声明运行位置:
- hub;
- cli;
- runner;
- web-descriptor;
- external-process。
Hub、CLI、Runner、Web 的 extension point 不应混用一个不透明入口。
Typed small extension points
优先提供小而稳定的接口,而不是一个万能 PluginAPI:
- hub.notificationChannel;
- hub.callbackRoute;
- permission.action;
- cli.agentAdapter;
- cli.commandResolver;
- cli.runnerSpawnStrategy;
- web.sessionAction;
- web.toolResultRenderer;
- web.settingsPanel;
- agent.modelProvider;
- agent.sessionDiscovery;
- plugin.storage。
权限与能力分离
Capability 描述插件能贡献什么;Permission 描述插件需要访问什么。
示例:
notification.send
session.readSummary
permission.approve
permission.deny
machine.spawn
file.read
process.spawn
network:<pattern>
secret:<name>
新增高风险权限时,应要求用户重新确认。
Web declarative-only
Web 端默认不执行任意插件 JS。插件只提供 JSON descriptor,Web 将其映射到内置安全组件。
如果未来支持任意前端 bundle,应要求:
- signature;
- CSP;
- sandbox iframe;
- postMessage schema;
- 用户高风险确认。
Scoped services only
插件 context 只应暴露 scoped service:
- logger;
- config;
- declared secrets;
- notifications;
- callbacks;
- permissions;
- scoped storage;
- limited RPC/action bridge。
不暴露 raw Store、SyncEngine、SQLite、Socket.IO、SSE、RPC gateway。
本地候选项表
点击展开候选项表
| 类别 |
类型 |
编号 |
状态 |
标题 |
插件适配度 |
需要的扩展点 |
备注 |
| notification-channel |
PR |
#24 |
closed / unmerged |
feat: Add Lark (Feishu) Integration Support |
high |
hub.notificationChannel; hub.callbackRoute; config.secrets; permissionAction |
大型平台集成,适合作为插件边界。 |
| notification-channel |
PR |
#312 |
open |
增加飞书支持 |
high |
hub.notificationChannel; hub.callbackRoute; config.secrets |
Feishu 需求重复出现。 |
| notification-channel |
PR |
#320 |
open |
Refactor/feishu debug logging |
high |
hub.notificationChannel; diagnostics.logging |
Feishu 后续调试与日志需求。 |
| notification-channel |
PR |
#325 |
open |
Feishu support |
high |
hub.notificationChannel; config.secrets |
第三个 Feishu 实现,需求信号强。 |
| notification-channel |
PR |
#355 |
closed / unmerged |
feat(hub): add Bark notification channel |
high |
hub.notificationChannel; config.secrets |
单向通知渠道,适合作为最小样板。 |
| notification-channel |
PR |
#553 |
open |
feat(hub): add WeCom bot push notification channel |
high |
hub.notificationChannel; hub.callbackRoute; permissionAction; config.secrets |
交互式审批渠道,可验证 callback/action API。 |
| notification-channel |
Issue |
#263 |
open |
考虑接入QQ机器人吗?电报还是不太方便~ |
high |
hub.notificationChannel; hub.callbackRoute |
又一个聊天平台集成需求。 |
| notification-channel |
Issue |
#600 |
open |
WeCom push channel support |
high |
hub.notificationChannel; permissionAction |
明确的 WeCom 审批通知需求。 |
| voice-provider |
PR |
#401 |
open |
feat(voice): pluggable voice backend with Gemini Live & Qwen Realtime |
high |
hub.voiceProvider; web.voiceProvider; realtimeToolBridge; config.secrets |
已直接提出 pluggable backend。 |
| voice-provider |
PR |
#463 |
open |
feat(voice): add realtime dictation modes |
high |
web.composerAction; web.settingsPanel; hub.voiceTokenProvider |
Dictation mode 属于可选 UX/provider 能力。 |
| voice-provider |
PR |
#464 |
open |
fix(voice): create ElevenLabs tools before agent setup |
medium |
hub.voiceProvider.lifecycle |
provider-specific lifecycle 逻辑适合 provider 内聚。 |
| voice-provider |
Issue |
#190 |
closed |
Feature Request: Add MiniMax Speech as an alternative voice provider |
high |
hub.voiceProvider; config.secrets |
说明存在替代语音 provider 需求。 |
| voice-provider |
Issue |
#462 |
open |
Add selectable realtime dictation modes |
high |
web.settingsPanel; web.composerAction |
需要 provider-driven mode selector。 |
| agent-adapter |
PR |
#375 |
closed / unmerged |
feat(cli): add PI coding agent integration |
high |
cli.agentAdapter; cli.command; hub.spawnAgent; web.agentPicker; modelCapabilities |
新 Agent 接入,插件化可避免 core 膨胀。 |
| agent-adapter |
PR |
#441 |
closed / unmerged |
openclaw support |
high |
hub.integrationService; cli.command; config.secrets |
大型服务集成,更适合作为可选插件。 |
| agent-adapter |
Issue |
#182 |
open |
Kilo cli support |
high |
cli.agentAdapter; web.agentPicker |
新 coding CLI 需求。 |
| agent-adapter |
Issue |
#329 |
open |
是否考虑支持其他的coding CLI?例如CodeBuddy Code CLI。 |
high |
cli.agentAdapter; web.agentPicker |
说明 Agent 列表不能长期硬编码。 |
| agent-adapter |
Issue |
#335 |
open |
consider adding support for pi-mono? |
high |
cli.agentAdapter; web.agentPicker |
与 PI 系需求一致。 |
| agent-adapter |
Issue |
#362 |
open |
Add support for Copilot CLI |
high |
cli.agentAdapter; web.agentPicker |
另一个 provider-specific adapter。 |
| agent-capability |
PR |
#393 |
open |
feat(codex): Add support for codex /fast mode |
medium |
agent.capabilityFlag; web.newSessionField; runner.argBuilder |
Codex-specific mode,需要 agent capability API。 |
| agent-capability |
PR |
#418 |
closed / unmerged |
Codex startup profiles |
medium |
agent.profileProvider; web.newSessionField; cli.rpcHandler |
可选 Codex profile UX。 |
| agent-capability |
PR |
#447 |
open |
Support precise Codex session forking |
low-core-first |
sessionForkingCore; agent.historyProvider; web.sessionAction |
先需要 core extension point。 |
| agent-capability |
PR |
#535 |
open |
[codex] add Codex session selection support |
medium |
agent.sessionDiscovery; web.newSessionField; hub.machineRpc |
Provider-specific discovery。 |
| agent-capability |
PR |
#536 |
open |
[codex] restore Codex session history |
medium |
agent.historyImporter; messageNormalizer |
Provider-specific history import。 |
| agent-capability |
PR |
#537 |
open |
[codex] add Codex usage indicator |
medium |
agent.usageProvider; web.statusWidget; metadataSchemaExtension |
Provider-specific metadata。 |
| agent-capability |
PR |
#581 |
open |
feat: add Codex skill picker |
medium |
agent.skillProvider; web.composerAction |
可泛化为 skill provider。 |
| agent-capability |
PR |
#636 |
open |
Add Codex steer for queued messages |
low-core-first |
messageQueueCore; agent.steerActiveTurn; web.messageAction |
先需要 core message queue action API。 |
| agent-capability |
Issue |
#366 |
open |
支持codex的多profile模式 |
medium |
agent.profileProvider; web.newSessionField |
Codex profile 需求。 |
| agent-capability |
Issue |
#426 |
open |
hapi 获取不到 codex 桌面应用的对话记录session |
medium |
agent.sessionDiscovery; agent.historyImporter |
Provider-specific local storage scanner。 |
| agent-capability |
Issue |
#435 |
open |
什么时候可以建议加一个 复用本地的session啊 |
medium |
agent.sessionDiscovery; resumePolicy |
通用 session import/reuse 需求。 |
| agent-capability |
Issue |
#572 |
open |
Resume existing session (started outside of hapi) |
medium |
agent.sessionDiscovery; resumePolicy |
Cursor-specific,但可泛化。 |
| web-ui-extension |
PR |
#437 |
open |
feat(web): add auto-spawn session from URL params |
high |
web.startupHook; hub.spawnAction |
高级用户 workflow,可选插件。 |
| web-ui-extension |
PR |
#484 |
open |
feat(web): multi-session grid view, composer status bar, in-chat keyboard shortcuts |
high |
web.route; web.sessionAction; web.composerAddon; web.hotkey |
大型 power-user UI,不适合默认 core。 |
| web-ui-extension |
PR |
#509 |
open |
feat(web): inline image rendering in tool results with lightbox preview |
medium |
web.toolResultRenderer; web.attachmentRenderer |
可作为安全 renderer 插件,也可能进入 core UX。 |
| web-ui-extension |
PR |
#511 |
open |
feat(web): show image thumbnails in composer attachment chips |
medium |
web.attachmentRenderer; web.composerAddon |
可选 renderer/composer 扩展。 |
| web-ui-extension |
Issue |
#134 |
open |
Feature Request: Batch delete multiple conversations |
medium |
web.bulkAction; hub.sessionAction |
可选 power-user action。 |
| web-ui-extension |
Issue |
#270 |
open |
Add read/unread indicators for session activity |
medium |
web.sessionListBadge; sessionActivityProvider |
个人效率 UX。 |
| web-ui-extension |
Issue |
#477 |
open |
feat(web): improve session sidebar with pinning, sorting, and unread indicators |
high |
web.sessionListSection; web.sessionAction; pluginState |
session organization 插件候选。 |
| web-ui-extension |
Issue |
#508 |
open |
[Enhancement] Render images inline in tool results and attachments with lightbox preview |
medium |
web.toolResultRenderer; web.attachmentRenderer |
#509 对应 issue。 |
| web-ui-extension |
Issue |
#510 |
open |
[Enhancement] Show image thumbnails in composer attachment chips |
medium |
web.attachmentRenderer |
#511 对应 issue。 |
| web-ui-extension |
Issue |
#532 |
open |
feat(web): support pinned or starred sessions |
high |
web.sessionAction; pluginState; web.sessionListSection |
小型 session-list 插件候选。 |
| web-ui-extension |
Issue |
#533 |
open |
feat(web): quick start a new session from a directory |
high |
web.directoryAction; hub.spawnAction |
适合 schema-driven UI action。 |
| web-ui-extension |
Issue |
#550 |
open |
feat: Support auto-completion for file names |
medium |
web.composerSuggestionProvider; hub.fileSearchRpc |
composer provider 扩展。 |
| policy-settings |
PR |
#504 |
open |
feat(cli): add global option to disable automatic session title changes |
high |
cli.sessionPolicy; settings.schema; mcpToolGate |
用户策略,避免 core setting 膨胀。 |
| policy-settings |
PR |
#527 |
open |
feat: support custom Claude model |
high |
agent.modelProvider; web.modelSelector; runner.argBuilder |
模型策略会持续变化。 |
| policy-settings |
PR |
#529 |
open |
feat: replace YoloToggle with PermissionModeSelector for Claude sessions |
medium |
web.newSessionField; permissionModeProvider |
需要 agent-specific permission mode。 |
| policy-settings |
PR |
#603 |
closed / unmerged |
feat(cli): add /model slash command to show or set Claude model |
medium |
cli.slashCommand; agent.modelProvider |
slash command extension point。 |
| policy-settings |
Issue |
#271 |
open |
Add an option to disable automatic session title changes |
high |
cli.sessionPolicy; settings.schema |
#504 对应 issue。 |
| policy-settings |
Issue |
#281 |
open |
Preserve previous permission mode when resuming an archived session |
low-core |
core.sessionResumePolicy |
更偏 core resume correctness。 |
| policy-settings |
Issue |
#512 |
open |
hapi codex Web UI fails to inherit writable_roots from config.toml due to missing custom permission mode |
medium |
agent.permissionModeProvider |
Provider-specific permission semantics。 |
| environment-workaround |
PR |
#563 |
open |
fix(cli): bypass HTTP_PROXY for runner webhook via raw socket |
high |
cli.runnerTransport; environmentDetector |
环境特定 workaround。 |
| environment-workaround |
PR |
#617 |
closed / unmerged |
fix(opencode): Windows path case mismatch in SQLite scanner |
medium |
agent.storageScanner; environmentDetector |
Provider + OS-specific scanner fix。 |
| environment-workaround |
Issue |
#292 |
open |
[Bug] --worktree flag hangs on Windows - Git probe miss, no SessionStart hook |
medium |
runner.spawnHook; environmentDetector |
OS-specific runner policy。 |
| environment-workaround |
Issue |
#425 |
open |
Windows上claude即使配置HAPI_CLAUDE_PATH仍然无法被hapi访问 |
medium |
cli.commandResolver; settings.schema |
本地路径 resolver。 |
| environment-workaround |
Issue |
#491 |
open |
feat(web): distinguish WSL from Windows host |
medium |
machineMetadataProvider; web.machineBadge |
环境 metadata provider。 |
| environment-workaround |
Issue |
#596 |
open |
Support claudeCodePath in ~/.hapi/settings.json |
medium |
cli.commandResolver; settings.schema |
本地 agent path resolver/config。 |
| environment-workaround |
Issue |
#606 |
open |
BUG: Windows hapi codex fails when npm Codex CLI shim is first on PATH |
medium |
cli.commandResolver; environmentDetector |
Windows shim workaround。 |
| environment-workaround |
Issue |
#612 |
open |
feat: 支持通过 tmux 启动远程 session,以便本地终端可以 attach |
high |
runner.spawnStrategy; terminalAttachProvider |
本地 workflow-specific,插件边界清晰。 |
| deployment-pack |
PR |
#217 |
closed / unmerged |
docs: add Zeabur one-click deployment guide |
medium |
plugin.distributionPack; docsExtension |
部署 recipe,不属于 core runtime。 |
| deployment-pack |
PR |
#247 |
closed / unmerged |
feat(docker): 支持 CI 构建 docker 镜像 |
medium |
plugin.distributionPack; releaseWorkflow |
部署包/发布流程能力。 |
| deployment-pack |
PR |
#256 |
closed / unmerged |
fix(docker): 加固镜像构建与 Compose 配置安全性 |
medium |
plugin.distributionPack; releaseWorkflow |
Docker/Compose hardening pack。 |
| integration-protocol |
Issue |
#360 |
open |
Feature Request: Hub 提供 MCP Server 接入方式,支持 Agent-to-Agent 协作 |
high |
hub.mcpServer; auth.capability; rpcGateway |
协议集成,需先定义 core extension point。 |
| integration-protocol |
PR |
#381 |
open |
fix(codex): Handle mcpServer/elicitation/request |
low-core-first |
permissionRequestCore; hub.route; agent.mcpElicitation |
correctness 先 core,之后再扩展。 |
| core-not-plugin |
PR |
#483 |
open |
fix(codex): surface remote auth and app-server errors |
low |
core.errorPropagation |
应作为 core error propagation。 |
| core-not-plugin |
PR |
#516 |
open |
fix(hub): raise Socket.IO maxHttpBufferSize for file downloads |
low |
core.config |
core transport/config,不是插件候选。 |
| core-not-plugin |
PR |
#638 |
closed / unmerged |
Fix Codex MCP startup under Bun stdin |
low |
core.codexMcpBridge |
根因 bug fix。 |
| core-not-plugin |
PR |
#639 |
closed / unmerged |
Fix runner remote terminal disconnecting from web/mobile UI |
low |
core.terminalPty |
根因 bug fix。 |
| core-not-plugin |
Issue |
#444 |
open |
Web UI: exit-plan-mode approval lacks permission mode and implementation mode options |
low |
core.permissionFlow |
权限正确性应留在 core。 |
| core-not-plugin |
Issue |
#530 |
open |
claudecode的plan模式申请权限时无法授权 |
low |
core.permissionFlow |
权限正确性应留在 core。 |
| core-not-plugin |
Issue |
#587 |
open |
[BUG] Permission request fails to show for sub-agent runs in Claude Code |
low |
core.permissionFlow |
权限正确性应留在 core。 |
| core-not-plugin |
Issue |
#645 |
open |
[web] 已用context量在remote模式下疑似不显示 |
low-core-first |
agent.usageProvider later |
先修数据/展示根因,之后可考虑 usage provider。 |
English version
Background
HAPI currently spans CLI, Hub, Web, Runner, notifications, voice, realtime sync, remote control, and permission approval. As usage grows, more requests are showing the same pattern:
- they serve only a subset of users or a specific environment;
- they are tightly coupled to a particular external platform, Agent, or system setup;
- merging them into core increases configuration, dependencies, test matrix, and long-term maintenance cost;
- when they are not merged into core, users must maintain forks or repeatedly submit similar PRs;
- many of these features do not change HAPI's core collaboration model and are better suited as optional capabilities.
This issue proposes adding a lightweight, local-first, auditable plugin system to HAPI, covering optional capabilities such as notification channels, Agent adapters, voice providers, Web power-user UI, and environment workarounds.
Goals
The goal is not to turn HAPI into a large platform ecosystem. The goal is to define a clear extension boundary:
- keep core small and stable;
- stop optional integrations from continuously expanding the main codebase;
- allow users to enable local plugins on demand;
- require plugins to declare capabilities, config, permissions, and runtime placement through a manifest;
- ensure plugin failures do not affect core sessions, permissions, security, or data consistency;
- prefer declarative descriptors for Web extensions instead of executing arbitrary third-party JS.
Demand signals
Based on a public issue/PR snapshot as of 2026-05-19, 71 high-signal candidate items were grouped locally. They mainly fall into these categories:
| Category |
Count |
Conclusion |
| notification-channel |
8 |
Highest priority; Feishu, Bark, WeCom, QQ requests repeatedly appear, with clear boundaries. |
| voice-provider |
5 |
Needs a provider abstraction; there are already PRs around pluggable backends. |
| agent-adapter |
6 |
New coding CLIs should not keep being hard-coded into core enums. |
| agent-capability |
12 |
Codex/profile/history/usage/skill and other provider-specific capabilities need capability interfaces. |
| web-ui-extension |
12 |
Many power-user UI and renderer requests; should be declarative and avoid arbitrary frontend JS. |
| policy-settings |
7 |
User preferences, models, and permission modes will keep growing. |
| environment-workaround |
8 |
Windows, WSL, proxy, tmux, etc. are better as local plugins or policy extensions. |
| deployment-pack |
3 |
Deployment options are better modeled as recipes/distribution packs. |
| integration-protocol |
2 |
MCP/A2A and similar protocol integrations should be pluginized only after core extension points exist. |
| core-not-plugin |
8 |
Permission, security, data-loss, and core transport bugs should not be pluginized. |
Feature types suitable for plugins
1. Notification channels
Feishu, Bark, WeCom, QQ, and similar notification channel requests keep recurring. They usually require:
- platform webhooks;
- tokens/secrets;
- callback routes;
- permission approve/deny actions;
- platform-specific message formatting;
- platform-specific error handling.
These features are important for some users, but do not all belong in core. A plugin system would allow notification channels to live as separate packages while core maintains a unified notification extension point.
2. Agent adapters
Requests for PI, Kilo, CodeBuddy, Copilot CLI, OpenClaw, and other Agents show that Agent types should not depend on a fixed enum in the long run.
A better approach is for plugins to provide an AgentDescriptor:
- agent id;
- display name;
- supported modes;
- model/permission/profile capabilities;
- session discovery support;
- runner command adapter;
- Web new-session fields.
Hub/Web/CLI/Runner can then recognize capabilities through descriptors instead of requiring multi-package hard-coded changes for each Agent.
3. Voice providers
Gemini Live, Qwen Realtime, MiniMax Speech, dictation modes, and similar requests fit a provider model.
A voice provider plugin could provide:
- token provider;
- realtime bridge;
- provider-specific config;
- Web voice mode descriptor;
- tool schema;
- lifecycle hooks.
4. Web power-user UI
Multi-session grid, pinned sessions, inline image renderers, file autocomplete, batch actions, and similar features are valuable to advanced users, but merging all of them into the default UI would increase complexity.
Web plugins should use declarative descriptors:
- session actions;
- session badges;
- safe tool result renderers;
- settings panels;
- new-session fields;
- composer suggestions.
The Web app should map descriptors to built-in core components and should not execute plugin JS.
5. Environment and local workflow
Windows path resolution, WSL identity, proxy bypass, tmux runner, agent storage scanners, and similar needs are highly local-environment-specific.
These capabilities fit CLI/Runner plugins:
- command resolver;
- runner spawn strategy;
- environment detector;
- machine metadata provider;
- agent storage scanner;
- terminal attach provider.
Core boundaries that should not be pluginized
The following responsibilities should remain core-owned:
- auth / JWT / token / namespace isolation;
- permission flow correctness;
- SQLite schema / migrations;
- Socket.IO / RPC / SSE base transport;
- session cache consistency;
- message ordering / loss recovery;
- runner trust boundary;
- terminal/file access base permissions;
- core error propagation;
- root-cause fixes for data loss and permission approval issues.
Plugins may extend providers, presentation, and policies, but should not bypass core security and consistency paths.
Design principles
Manifest-first
Plugins must provide a static manifest. Core should be able to read the following without executing plugin code:
- id;
- name;
- version;
- pluginApiVersion;
- compatibility;
- runtime entrypoints;
- static contributions;
- permissions;
- network allowlist;
- secrets;
- config schema.
Plugin lists, risk prompts, settings pages, and new-session Agent lists should come from manifests or descriptors wherever possible.
Registry-first
Introduce a central PluginRegistry to manage:
- discovered;
- validated;
- enabled;
- active;
- degraded;
- failed;
- disabled;
- diagnostics;
- contributions;
- registered extension points;
- disposables.
Plugins should not directly mutate core global singletons.
Explicit runtime placement
Plugins should explicitly declare runtime placement:
- hub;
- cli;
- runner;
- web-descriptor;
- external-process.
Hub, CLI, Runner, and Web extension points should not be mixed behind one opaque entrypoint.
Typed small extension points
Prefer small, stable interfaces instead of one universal PluginAPI:
- hub.notificationChannel;
- hub.callbackRoute;
- permission.action;
- cli.agentAdapter;
- cli.commandResolver;
- cli.runnerSpawnStrategy;
- web.sessionAction;
- web.toolResultRenderer;
- web.settingsPanel;
- agent.modelProvider;
- agent.sessionDiscovery;
- plugin.storage.
Separate permissions from capabilities
Capabilities describe what a plugin contributes. Permissions describe what a plugin needs to access.
Examples:
notification.send
session.readSummary
permission.approve
permission.deny
machine.spawn
file.read
process.spawn
network:<pattern>
secret:<name>
New high-risk permissions should require user reconfirmation.
Web declarative-only
The Web side should not execute arbitrary plugin JS by default. Plugins should only provide JSON descriptors, and the Web app should map them to built-in safe components.
If arbitrary frontend bundles are supported in the future, they should require:
- signature;
- CSP;
- sandboxed iframe;
- postMessage schema;
- explicit high-risk user confirmation.
Scoped services only
Plugin contexts should expose only scoped services:
- logger;
- config;
- declared secrets;
- notifications;
- callbacks;
- permissions;
- scoped storage;
- limited RPC/action bridge.
They should not expose raw Store, SyncEngine, SQLite, Socket.IO, SSE, or RPC gateway instances.
Local candidate table
Expand candidate table
| Category |
Type |
Number |
State |
Title |
Plugin fit |
Required extension points |
Notes |
| notification-channel |
PR |
#24 |
closed / unmerged |
feat: Add Lark (Feishu) Integration Support |
high |
hub.notificationChannel; hub.callbackRoute; config.secrets; permissionAction |
Large platform integration; suitable plugin boundary. |
| notification-channel |
PR |
#312 |
open |
Add Feishu support |
high |
hub.notificationChannel; hub.callbackRoute; config.secrets |
Recurring Feishu demand. |
| notification-channel |
PR |
#320 |
open |
Refactor/feishu debug logging |
high |
hub.notificationChannel; diagnostics.logging |
Follow-up debugging/logging need for Feishu. |
| notification-channel |
PR |
#325 |
open |
Feishu support |
high |
hub.notificationChannel; config.secrets |
Third Feishu implementation; strong demand signal. |
| notification-channel |
PR |
#355 |
closed / unmerged |
feat(hub): add Bark notification channel |
high |
hub.notificationChannel; config.secrets |
One-way notification channel; suitable minimum sample. |
| notification-channel |
PR |
#553 |
open |
feat(hub): add WeCom bot push notification channel |
high |
hub.notificationChannel; hub.callbackRoute; permissionAction; config.secrets |
Interactive approval channel; validates callback/action API. |
| notification-channel |
Issue |
#263 |
open |
Consider adding QQ bot integration? Telegram is not always convenient |
high |
hub.notificationChannel; hub.callbackRoute |
Another chat-platform integration request. |
| notification-channel |
Issue |
#600 |
open |
WeCom push channel support |
high |
hub.notificationChannel; permissionAction |
Explicit WeCom approval notification demand. |
| voice-provider |
PR |
#401 |
open |
feat(voice): pluggable voice backend with Gemini Live & Qwen Realtime |
high |
hub.voiceProvider; web.voiceProvider; realtimeToolBridge; config.secrets |
Directly proposes a pluggable backend. |
| voice-provider |
PR |
#463 |
open |
feat(voice): add realtime dictation modes |
high |
web.composerAction; web.settingsPanel; hub.voiceTokenProvider |
Dictation mode is optional UX/provider capability. |
| voice-provider |
PR |
#464 |
open |
fix(voice): create ElevenLabs tools before agent setup |
medium |
hub.voiceProvider.lifecycle |
Provider-specific lifecycle logic should be kept inside provider. |
| voice-provider |
Issue |
#190 |
closed |
Feature Request: Add MiniMax Speech as an alternative voice provider |
high |
hub.voiceProvider; config.secrets |
Shows demand for alternative voice providers. |
| voice-provider |
Issue |
#462 |
open |
Add selectable realtime dictation modes |
high |
web.settingsPanel; web.composerAction |
Needs provider-driven mode selector. |
| agent-adapter |
PR |
#375 |
closed / unmerged |
feat(cli): add PI coding agent integration |
high |
cli.agentAdapter; cli.command; hub.spawnAgent; web.agentPicker; modelCapabilities |
New Agent integration; pluginization prevents core bloat. |
| agent-adapter |
PR |
#441 |
closed / unmerged |
openclaw support |
high |
hub.integrationService; cli.command; config.secrets |
Large service integration; better as optional plugin. |
| agent-adapter |
Issue |
#182 |
open |
Kilo cli support |
high |
cli.agentAdapter; web.agentPicker |
New coding CLI request. |
| agent-adapter |
Issue |
#329 |
open |
Consider supporting other coding CLIs, such as CodeBuddy Code CLI? |
high |
cli.agentAdapter; web.agentPicker |
Shows Agent list should not stay hard-coded. |
| agent-adapter |
Issue |
#335 |
open |
consider adding support for pi-mono? |
high |
cli.agentAdapter; web.agentPicker |
Same PI-related demand family. |
| agent-adapter |
Issue |
#362 |
open |
Add support for Copilot CLI |
high |
cli.agentAdapter; web.agentPicker |
Another provider-specific adapter. |
| agent-capability |
PR |
#393 |
open |
feat(codex): Add support for codex /fast mode |
medium |
agent.capabilityFlag; web.newSessionField; runner.argBuilder |
Codex-specific mode; needs agent capability API. |
| agent-capability |
PR |
#418 |
closed / unmerged |
Codex startup profiles |
medium |
agent.profileProvider; web.newSessionField; cli.rpcHandler |
Optional Codex profile UX. |
| agent-capability |
PR |
#447 |
open |
Support precise Codex session forking |
low-core-first |
sessionForkingCore; agent.historyProvider; web.sessionAction |
Needs core extension point first. |
| agent-capability |
PR |
#535 |
open |
[codex] add Codex session selection support |
medium |
agent.sessionDiscovery; web.newSessionField; hub.machineRpc |
Provider-specific discovery. |
| agent-capability |
PR |
#536 |
open |
[codex] restore Codex session history |
medium |
agent.historyImporter; messageNormalizer |
Provider-specific history import. |
| agent-capability |
PR |
#537 |
open |
[codex] add Codex usage indicator |
medium |
agent.usageProvider; web.statusWidget; metadataSchemaExtension |
Provider-specific metadata. |
| agent-capability |
PR |
#581 |
open |
feat: add Codex skill picker |
medium |
agent.skillProvider; web.composerAction |
Can be generalized as a skill provider. |
| agent-capability |
PR |
#636 |
open |
Add Codex steer for queued messages |
low-core-first |
messageQueueCore; agent.steerActiveTurn; web.messageAction |
Needs core message queue action API first. |
| agent-capability |
Issue |
#366 |
open |
Support multi-profile mode for Codex |
medium |
agent.profileProvider; web.newSessionField |
Codex profile demand. |
| agent-capability |
Issue |
#426 |
open |
HAPI cannot find conversation history sessions from Codex desktop app |
medium |
agent.sessionDiscovery; agent.historyImporter |
Provider-specific local storage scanner. |
| agent-capability |
Issue |
#435 |
open |
Can HAPI reuse local existing sessions? |
medium |
agent.sessionDiscovery; resumePolicy |
General session import/reuse need. |
| agent-capability |
Issue |
#572 |
open |
Resume existing session (started outside of hapi) |
medium |
agent.sessionDiscovery; resumePolicy |
Cursor-specific but generalizable. |
| web-ui-extension |
PR |
#437 |
open |
feat(web): add auto-spawn session from URL params |
high |
web.startupHook; hub.spawnAction |
Power-user workflow; optional plugin. |
| web-ui-extension |
PR |
#484 |
open |
feat(web): multi-session grid view, composer status bar, in-chat keyboard shortcuts |
high |
web.route; web.sessionAction; web.composerAddon; web.hotkey |
Large power-user UI; not ideal as default core. |
| web-ui-extension |
PR |
#509 |
open |
feat(web): inline image rendering in tool results with lightbox preview |
medium |
web.toolResultRenderer; web.attachmentRenderer |
Could be safe renderer plugin; might also become core UX. |
| web-ui-extension |
PR |
#511 |
open |
feat(web): show image thumbnails in composer attachment chips |
medium |
web.attachmentRenderer; web.composerAddon |
Optional renderer/composer extension. |
| web-ui-extension |
Issue |
#134 |
open |
Feature Request: Batch delete multiple conversations |
medium |
web.bulkAction; hub.sessionAction |
Optional power-user action. |
| web-ui-extension |
Issue |
#270 |
open |
Add read/unread indicators for session activity |
medium |
web.sessionListBadge; sessionActivityProvider |
Personal productivity UX. |
| web-ui-extension |
Issue |
#477 |
open |
feat(web): improve session sidebar with pinning, sorting, and unread indicators |
high |
web.sessionListSection; web.sessionAction; pluginState |
Session organization plugin candidate. |
| web-ui-extension |
Issue |
#508 |
open |
[Enhancement] Render images inline in tool results and attachments with lightbox preview |
medium |
web.toolResultRenderer; web.attachmentRenderer |
Counterpart to #509. |
| web-ui-extension |
Issue |
#510 |
open |
[Enhancement] Show image thumbnails in composer attachment chips |
medium |
web.attachmentRenderer |
Counterpart to #511. |
| web-ui-extension |
Issue |
#532 |
open |
feat(web): support pinned or starred sessions |
high |
web.sessionAction; pluginState; web.sessionListSection |
Small session-list plugin candidate. |
| web-ui-extension |
Issue |
#533 |
open |
feat(web): quick start a new session from a directory |
high |
web.directoryAction; hub.spawnAction |
Suitable for schema-driven UI action. |
| web-ui-extension |
Issue |
#550 |
open |
feat: Support auto-completion for file names |
medium |
web.composerSuggestionProvider; hub.fileSearchRpc |
Composer provider extension. |
| policy-settings |
PR |
#504 |
open |
feat(cli): add global option to disable automatic session title changes |
high |
cli.sessionPolicy; settings.schema; mcpToolGate |
User policy; avoids core setting bloat. |
| policy-settings |
PR |
#527 |
open |
feat: support custom Claude model |
high |
agent.modelProvider; web.modelSelector; runner.argBuilder |
Model policy will keep changing. |
| policy-settings |
PR |
#529 |
open |
feat: replace YoloToggle with PermissionModeSelector for Claude sessions |
medium |
web.newSessionField; permissionModeProvider |
Needs agent-specific permission mode. |
| policy-settings |
PR |
#603 |
closed / unmerged |
feat(cli): add /model slash command to show or set Claude model |
medium |
cli.slashCommand; agent.modelProvider |
Slash command extension point. |
| policy-settings |
Issue |
#271 |
open |
Add an option to disable automatic session title changes |
high |
cli.sessionPolicy; settings.schema |
Counterpart to #504. |
| policy-settings |
Issue |
#281 |
open |
Preserve previous permission mode when resuming an archived session |
low-core |
core.sessionResumePolicy |
More like core resume correctness. |
| policy-settings |
Issue |
#512 |
open |
HAPI Codex Web UI fails to inherit writable_roots from config.toml due to missing custom permission mode |
medium |
agent.permissionModeProvider |
Provider-specific permission semantics. |
| environment-workaround |
PR |
#563 |
open |
fix(cli): bypass HTTP_PROXY for runner webhook via raw socket |
high |
cli.runnerTransport; environmentDetector |
Environment-specific workaround. |
| environment-workaround |
PR |
#617 |
closed / unmerged |
fix(opencode): Windows path case mismatch in SQLite scanner |
medium |
agent.storageScanner; environmentDetector |
Provider + OS-specific scanner fix. |
| environment-workaround |
Issue |
#292 |
open |
[Bug] --worktree flag hangs on Windows - Git probe miss, no SessionStart hook |
medium |
runner.spawnHook; environmentDetector |
OS-specific runner policy. |
| environment-workaround |
Issue |
#425 |
open |
Claude cannot be accessed on Windows even when HAPI_CLAUDE_PATH is configured |
medium |
cli.commandResolver; settings.schema |
Local path resolver. |
| environment-workaround |
Issue |
#491 |
open |
feat(web): distinguish WSL from Windows host |
medium |
machineMetadataProvider; web.machineBadge |
Environment metadata provider. |
| environment-workaround |
Issue |
#596 |
open |
Support claudeCodePath in ~/.hapi/settings.json |
medium |
cli.commandResolver; settings.schema |
Local agent path resolver/config. |
| environment-workaround |
Issue |
#606 |
open |
BUG: Windows hapi codex fails when npm Codex CLI shim is first on PATH |
medium |
cli.commandResolver; environmentDetector |
Windows shim workaround. |
| environment-workaround |
Issue |
#612 |
open |
Support starting remote sessions through tmux so local terminal can attach |
high |
runner.spawnStrategy; terminalAttachProvider |
Local workflow-specific; clear plugin boundary. |
| deployment-pack |
PR |
#217 |
closed / unmerged |
docs: add Zeabur one-click deployment guide |
medium |
plugin.distributionPack; docsExtension |
Deployment recipe, not core runtime. |
| deployment-pack |
PR |
#247 |
closed / unmerged |
feat(docker): support CI-built Docker images |
medium |
plugin.distributionPack; releaseWorkflow |
Deployment pack/release workflow capability. |
| deployment-pack |
PR |
#256 |
closed / unmerged |
fix(docker): harden image build and Compose configuration security |
medium |
plugin.distributionPack; releaseWorkflow |
Docker/Compose hardening pack. |
| integration-protocol |
Issue |
#360 |
open |
Feature Request: Provide Hub as MCP Server for Agent-to-Agent collaboration |
high |
hub.mcpServer; auth.capability; rpcGateway |
Protocol integration; needs core extension point first. |
| integration-protocol |
PR |
#381 |
open |
fix(codex): Handle mcpServer/elicitation/request |
low-core-first |
permissionRequestCore; hub.route; agent.mcpElicitation |
Correctness first in core, extension later. |
| core-not-plugin |
PR |
#483 |
open |
fix(codex): surface remote auth and app-server errors |
low |
core.errorPropagation |
Should be core error propagation. |
| core-not-plugin |
PR |
#516 |
open |
fix(hub): raise Socket.IO maxHttpBufferSize for file downloads |
low |
core.config |
Core transport/config, not a plugin candidate. |
| core-not-plugin |
PR |
#638 |
closed / unmerged |
Fix Codex MCP startup under Bun stdin |
low |
core.codexMcpBridge |
Root-cause bug fix. |
| core-not-plugin |
PR |
#639 |
closed / unmerged |
Fix runner remote terminal disconnecting from web/mobile UI |
low |
core.terminalPty |
Root-cause bug fix. |
| core-not-plugin |
Issue |
#444 |
open |
Web UI: exit-plan-mode approval lacks permission mode and implementation mode options |
low |
core.permissionFlow |
Permission correctness should remain in core. |
| core-not-plugin |
Issue |
#530 |
open |
Claude Code plan mode permission request cannot be approved |
low |
core.permissionFlow |
Permission correctness should remain in core. |
| core-not-plugin |
Issue |
#587 |
open |
[BUG] Permission request fails to show for sub-agent runs in Claude Code |
low |
core.permissionFlow |
Permission correctness should remain in core. |
| core-not-plugin |
Issue |
#645 |
open |
[web] Context usage seems not displayed in remote mode |
low-core-first |
agent.usageProvider later |
Fix data/display root cause first; usage provider can be considered later. |
背景
HAPI 目前已经覆盖 CLI、Hub、Web、Runner、通知、语音、实时同步、远程控制、权限审批等多个模块。随着使用场景增长,越来越多需求呈现出相同模式:
因此建议为 HAPI 引入一个轻量、本地优先、可审计的插件系统,用于承接通知渠道、Agent adapter、语音 provider、Web power-user UI、环境 workaround 等可选能力。
目标
插件系统的目标不是把 HAPI 改造成大型平台生态,而是提供一个明确边界:
需求依据
基于截至 2026-05-19 的公开 issue/PR 快照,本地整理出 71 个高信号候选项。候选项主要集中在以下方向:
适合插件化的功能类型
1. 通知渠道
Feishu、Bark、WeCom、QQ 等通知渠道需求重复出现。它们通常需要:
这类功能对部分用户非常重要,但不适合全部进入 core。插件系统可以让通知渠道以独立包存在,core 只维护统一的 notification extension point。
2. Agent adapter
PI、Kilo、CodeBuddy、Copilot CLI、OpenClaw 等新 Agent 需求说明,Agent 类型不应长期依赖固定 enum。
更合理的方式是由插件提供 AgentDescriptor:
Hub/Web/CLI/Runner 通过 descriptor 识别能力,而不是为每个 Agent 修改多处 hard-code。
3. Voice provider
Gemini Live、Qwen Realtime、MiniMax Speech、dictation modes 等需求适合 provider 模式。
Voice provider 插件可以提供:
4. Web power-user UI
多会话 grid、pinned sessions、inline image renderer、file autocomplete、batch actions 等需求对高级用户价值高,但默认合入主 UI 会增加复杂度。
Web 插件建议采用 declarative descriptor:
Web 端只映射到 core 内置组件,不执行插件 JS。
5. 环境与本地工作流
Windows path resolver、WSL identity、proxy bypass、tmux runner、agent storage scanner 等需求与本机环境强相关。
这些能力适合作为 CLI/Runner 插件:
不适合插件化的核心边界
以下内容应继续由 core 负责:
插件可以扩展 provider、显示和策略,但不应绕过 core 的安全与一致性路径。
设计原则
Manifest-first
插件必须提供静态 manifest。core 应能在不执行插件代码的前提下读取:
插件列表、风险提示、设置页、新建会话 Agent 列表等,应尽量来自 manifest 或 descriptor。
Registry-first
引入中心 PluginRegistry,统一管理:
插件不应直接修改 core global singleton。
明确运行位置
插件应显式声明运行位置:
Hub、CLI、Runner、Web 的 extension point 不应混用一个不透明入口。
Typed small extension points
优先提供小而稳定的接口,而不是一个万能 PluginAPI:
权限与能力分离
Capability 描述插件能贡献什么;Permission 描述插件需要访问什么。
示例:
notification.sendsession.readSummarypermission.approvepermission.denymachine.spawnfile.readprocess.spawnnetwork:<pattern>secret:<name>新增高风险权限时,应要求用户重新确认。
Web declarative-only
Web 端默认不执行任意插件 JS。插件只提供 JSON descriptor,Web 将其映射到内置安全组件。
如果未来支持任意前端 bundle,应要求:
Scoped services only
插件 context 只应暴露 scoped service:
不暴露 raw Store、SyncEngine、SQLite、Socket.IO、SSE、RPC gateway。
本地候选项表
点击展开候选项表
English version
Background
HAPI currently spans CLI, Hub, Web, Runner, notifications, voice, realtime sync, remote control, and permission approval. As usage grows, more requests are showing the same pattern:
This issue proposes adding a lightweight, local-first, auditable plugin system to HAPI, covering optional capabilities such as notification channels, Agent adapters, voice providers, Web power-user UI, and environment workarounds.
Goals
The goal is not to turn HAPI into a large platform ecosystem. The goal is to define a clear extension boundary:
Demand signals
Based on a public issue/PR snapshot as of 2026-05-19, 71 high-signal candidate items were grouped locally. They mainly fall into these categories:
Feature types suitable for plugins
1. Notification channels
Feishu, Bark, WeCom, QQ, and similar notification channel requests keep recurring. They usually require:
These features are important for some users, but do not all belong in core. A plugin system would allow notification channels to live as separate packages while core maintains a unified notification extension point.
2. Agent adapters
Requests for PI, Kilo, CodeBuddy, Copilot CLI, OpenClaw, and other Agents show that Agent types should not depend on a fixed enum in the long run.
A better approach is for plugins to provide an AgentDescriptor:
Hub/Web/CLI/Runner can then recognize capabilities through descriptors instead of requiring multi-package hard-coded changes for each Agent.
3. Voice providers
Gemini Live, Qwen Realtime, MiniMax Speech, dictation modes, and similar requests fit a provider model.
A voice provider plugin could provide:
4. Web power-user UI
Multi-session grid, pinned sessions, inline image renderers, file autocomplete, batch actions, and similar features are valuable to advanced users, but merging all of them into the default UI would increase complexity.
Web plugins should use declarative descriptors:
The Web app should map descriptors to built-in core components and should not execute plugin JS.
5. Environment and local workflow
Windows path resolution, WSL identity, proxy bypass, tmux runner, agent storage scanners, and similar needs are highly local-environment-specific.
These capabilities fit CLI/Runner plugins:
Core boundaries that should not be pluginized
The following responsibilities should remain core-owned:
Plugins may extend providers, presentation, and policies, but should not bypass core security and consistency paths.
Design principles
Manifest-first
Plugins must provide a static manifest. Core should be able to read the following without executing plugin code:
Plugin lists, risk prompts, settings pages, and new-session Agent lists should come from manifests or descriptors wherever possible.
Registry-first
Introduce a central PluginRegistry to manage:
Plugins should not directly mutate core global singletons.
Explicit runtime placement
Plugins should explicitly declare runtime placement:
Hub, CLI, Runner, and Web extension points should not be mixed behind one opaque entrypoint.
Typed small extension points
Prefer small, stable interfaces instead of one universal PluginAPI:
Separate permissions from capabilities
Capabilities describe what a plugin contributes. Permissions describe what a plugin needs to access.
Examples:
notification.sendsession.readSummarypermission.approvepermission.denymachine.spawnfile.readprocess.spawnnetwork:<pattern>secret:<name>New high-risk permissions should require user reconfirmation.
Web declarative-only
The Web side should not execute arbitrary plugin JS by default. Plugins should only provide JSON descriptors, and the Web app should map them to built-in safe components.
If arbitrary frontend bundles are supported in the future, they should require:
Scoped services only
Plugin contexts should expose only scoped services:
They should not expose raw Store, SyncEngine, SQLite, Socket.IO, SSE, or RPC gateway instances.
Local candidate table
Expand candidate table