跳转到内容

下载 Termii · v0.4.5

三分钟,装进你的 Dock

原生构建,包体仅数 MB。应用内自动更新,始终新鲜。

安装说明

macOS:若提示「无法打开」,在终端执行 xattr -dr com.apple.quarantine /Applications/Termii.app。Windows:首次运行可能触发 SmartScreen,选择「仍要运行」即可。

贡献点

插件通过 ctx.ui.register* 注册六类贡献点。每个注册都返回一个清理函数 (Disposer),插件被禁用 / 卸载时宿主统一回放,无需手动管理。

外部插件(包括官方插件,它们也是从磁盘加载的外部插件)注册的任何贡献点 id 必须以 <pluginId>. 开头(如 my-plugin.panel),否则注册被拒绝。 宿主对未加前缀的旧 bundle 会自动补全前缀(兼容早期插件),但显式书写 前缀仍是推荐做法。同贡献点同 id 冲突时,后注册的被拒绝。

内置插件(随宿主编译、使用核心命名空间)不受此限。

注册侧栏条目 + 主区 React 组件。注册后自动获得 ⌘1..9 快捷键与命令 面板入口(两者都从可见侧栏派生,无需额外注册):

interface ViewContribution {
id: string; // "my-plugin.panel"
icon: PluginIcon; // lucide 图标组件
labelKey: string; // i18n 文案键,默认在 "views" 命名空间解析
ns?: string; // i18n 命名空间,缺省 "views"
component: ComponentType; // React 组件
}
ctx.ui.registerView({
id: "my-plugin.panel",
icon: Package, // lucide 图标组件
labelKey: "panelTitle",
ns: "plugin-my-plugin", // 会被强制改写为 plugin-<id>
component: MyPanel, // 普通 React 组件,React 来自宿主共享运行时
});

⌘K 命令面板条目:

interface CommandContribution {
id: string; // "my-plugin.sayHi"
group: string; // 分组标题(已本地化的展示字符串)
title: string;
sub?: string;
icon: PluginIcon;
run: () => void | Promise<void>;
}
ctx.ui.registerCommand({
id: "my-plugin.sayHi",
group: "My Plugin",
title: "Say Hi",
icon: Zap,
run: () => ctx.ui.toast.info({ title: "Hi!" }),
});

渲染在「设置」页里的配置区块:

interface SettingsSectionContribution {
id: string; // "my-plugin.settings"
icon: PluginIcon;
labelKey: string; // 默认在 "settings" 命名空间解析
ns?: string; // 缺省 "settings"
component: ComponentType;
}

全局快捷键。combo 形如 "Mod+Shift+D":Mod = ⌘(macOS)/ Ctrl(其他), Cmd / Ctrl 是 Mod 的同义词;Shift / Alt 可选;最后一段为单字符键。 大小写不敏感。内置快捷键优先命中(⌘K / T / W / D、⌘0..9),未处理的 按键才会落到插件快捷键表:

ctx.ui.registerShortcut({
id: "my-plugin.jump",
combo: "Mod+Shift+D",
run: () => ctx.ui.navigate("my-plugin.panel"),
});

应用主题:注入 :root[data-theme="<id>"] { …vars },并出现在 「设置 → 外观」的主题卡片列表:

interface ThemeContribution {
id: string;
label: string; // 主题卡片上的显示名(纯文本,插件自行本地化)
dark: boolean; // 暗色主题标记(终端回放等需要跟随 app 明暗)
previewBg?: string; // 卡片预览色;缺省取 vars 里的 --bg / --fg
previewFg?: string;
vars: Record<string, string>;
}
  • vars 的键必须是 CSS 自定义属性(-- 开头)。常用 token: --bg、--fg、--accent、--green、--red、--fg-dim 等 (完整 token 表见宿主内置主题块)。
  • 键值会经消毒:键不允许 {} / ;,值不允许 {} / </style, 违规声明被静默丢弃(防止插件逃逸出规则块)。
  • 插件被禁用时,宿主把当前主题回落到内置 dark(若正使用该插件主题)。
ctx.ui.registerTheme({
id: "my-plugin.night",
label: "Night",
dark: true,
vars: { "--bg": "#101418", "--fg": "#d8dee9", "--accent": "#88c0d0" },
});

系统托盘右键菜单的固定区条目(「新建本地终端」与「SSH 主机」子菜单之后), 点击时经 tray://plugin-item 事件分发回注册表触发 run:

ctx.ui.registerTrayItem({
id: "my-plugin.quick",
label: "Quick Action", // 纯文本,插件自行本地化
run: () => {
// …
},
});

一个注册全部六类贡献点的最小插件:

import { definePlugin } from "@termii/plugin-sdk";
import React from "react";
import { Package, Zap, Settings, Sun, Cloud } from "lucide-react";
export default definePlugin({
manifest: {
id: "my-plugin",
name: "My Plugin",
version: "0.1.0",
apiVersion: 3,
contributes: {
views: [{ id: "my-plugin.panel", labelKey: "panelTitle" }],
commands: [{ id: "my-plugin.sayHi", title: "Say Hi" }],
settingsSections: [{ id: "my-plugin.settings", labelKey: "settingsTitle" }],
themes: [{ id: "my-plugin.night", label: "Night" }],
trayItems: [{ id: "my-plugin.quick", label: "Quick Action" }],
},
},
activate(ctx) {
ctx.i18n.addBundle("zh-CN", "ignored", {
panelTitle: "我的面板",
settingsTitle: "我的设置",
});
ctx.ui.registerView({
id: "my-plugin.panel",
icon: Package,
labelKey: "panelTitle",
component: () => <div className="view-body">面板内容</div>,
});
ctx.ui.registerCommand({
id: "my-plugin.sayHi",
group: "My Plugin",
title: "Say Hi",
icon: Zap,
run: () => ctx.ui.toast.success({ title: "Hi!" }),
});
ctx.ui.registerSettingsSection({
id: "my-plugin.settings",
icon: Settings,
labelKey: "settingsTitle",
component: () => <div>设置内容</div>,
});
ctx.ui.registerShortcut({
id: "my-plugin.jump",
combo: "Mod+Shift+D",
run: () => ctx.ui.navigate("my-plugin.panel"),
});
ctx.ui.registerTheme({
id: "my-plugin.night",
label: "Night",
dark: true,
vars: { "--bg": "#101418", "--fg": "#d8dee9", "--accent": "#88c0d0" },
});
ctx.ui.registerTrayItem({
id: "my-plugin.quick",
label: "Quick Action",
run: () => ctx.ui.toast.info({ title: "Quick Action" }),
});
},
});