用 AI 做 Obsidian 插件:从零到上架社区市场(2026)
如果你用 Obsidian 记笔记,多半有过这种念头:「差一个小功能,市场上的插件都不趁手,要是能自己写一个就好了。」在 AI 编程工具普及之后,这件事的门槛已经低到超出很多人的想象——Obsidian 插件开发是目前最适合拿 AI 练手的方向之一:技术栈只有 TypeScript,官方 API 面积不大且多年稳定,代码改完不用部署、不用等审核,在本地重载一下就能看到效果。这篇文章带你从零跑通第一个插件,讲清 AI 最容易写错的几处官方规范,以及 2026 年 5 月改版之后全新的上架流程。
为什么 Obsidian 插件特别适合用 AI 写
很多人用 AI 做东西之所以卡住,不是 AI 不会写代码,而是项目本身的「环境复杂度」太高:要配数据库、要部署、要过应用商店审核,AI 帮你写完第一版之后你依然动不了。Obsidian 插件几乎没有这些负担:
- 技术栈极窄——TypeScript + 一个 esbuild 配置,官方模板已经配好,你只改业务逻辑那一个文件。
- 反馈闭环极短——
npm run dev起着监听编译,改完代码在 Obsidian 里重载插件就生效,AI 写错了你三十秒内就知道。 - API 面积小且稳定——常用的就是 Plugin、Notice、Modal、PluginSettingTab、Vault、Workspace 这几个类,模型对它们的了解普遍不差。
- 不上架也能用——插件本质是往 vault 的
.obsidian/plugins/塞三个文件,自己用、发给朋友用完全不需要经过官方市场。 - 需求来自你自己——你是这个插件的第一个用户,需求描述得比任何外部项目都清楚,而「需求说得清」正是 AI 写对代码的前提。
先想清楚要做什么
动手前先用一句话写下插件要解决的问题,例如「统计当前笔记的中文字数并显示在状态栏」。需求越具体,AI 一次写对的概率越高;「做个好用的笔记增强插件」这种描述,任何模型都只会还给你一堆没用的样板代码。
五分钟跑通官方模板
Obsidian 官方维护了一个插件模板仓库 obsidian-sample-plugin,构建配置和最佳实践都已经就位,一切从它开始,别让 AI 从空目录给你「凭空发明」工程结构。建议直接把它克隆进你的 vault 插件目录,这样改代码和看效果是同一份文件,省掉来回拷贝:
# 1. 确认 Node 版本(官方模板要求 v18 以上)
node --version
# 2. 克隆官方模板到你的 vault 插件目录
# 正式做自己的插件时,建议先在 GitHub 上点 "Use this template" 生成自己的仓库再克隆
cd /path/to/YourVault/.obsidian/plugins
git clone https://github.com/obsidianmd/obsidian-sample-plugin.git my-first-plugin
cd my-first-plugin
# 3. 安装依赖 + 起监听编译(改 TS 源码会自动重编成 main.js)
npm i
npm run dev然后打开 Obsidian → 设置 → 第三方插件(社区插件)→ 关闭「安全模式」/开启社区插件 → 在已安装列表里刷新,就能看到你刚克隆的插件,打开开关即启用。之后每次改完代码,用命令面板执行 Reload app without saving,或者在插件列表里关一次再开一次,新代码就生效了。
拿一个练手 vault 来开发
别在存着你全部真实笔记的主 vault 里做开发。插件代码有权限读写整个 vault 的文件,AI 写出的文件操作逻辑万一有 bug(比如写错路径、批量覆盖),损失是不可逆的。新建一个空 vault,塞几篇测试笔记,改稳了再装到主 vault。
manifest.json:插件的身份证
manifest.json 决定 Obsidian 怎么识别你的插件,也是上架时自动审核第一个检查的文件。官方模板里的内容长这样:
{
"id": "sample-plugin",
"name": "Sample Plugin",
"version": "1.0.0",
"minAppVersion": "1.0.0",
"description": "Demonstrates some of the capabilities of the Obsidian API.",
"author": "Obsidian",
"authorUrl": "https://obsidian.md",
"fundingUrl": "https://obsidian.md/pricing",
"isDesktopOnly": false
}| 字段 | 作用 | 填写要点 |
|---|---|---|
| id | 插件唯一标识,也是插件安装目录名 | 全市场唯一,且**不能包含 obsidian 字样**;用 kebab-case |
| name | 用户在插件市场看到的名字 | 别叫 Sample Plugin;不要在名字里塞 Obsidian 或 Plugin |
| version | 插件版本号 | 必须是 `x.y.z` 三段式,**不能带 v 前缀**,且要和 GitHub Release 的 tag 完全一致 |
| minAppVersion | 最低支持的 Obsidian 版本 | 你用了新 API 就往上调,否则老版本用户装上会直接报错 |
| description | 一句话说明插件干什么 | 用户唯一会读的介绍,写清楚解决什么问题 |
| author / authorUrl | 作者与主页 | authorUrl 可留空,别填成插件仓库地址 |
| fundingUrl | 赞助链接 | 可选;不需要赞助就整个删掉这一行 |
| isDesktopOnly | 是否仅桌面端可用 | 只要用了 Node API(fs、child_process 等)就必须设 `true`,否则手机端会崩 |
第一个真正有用的插件:统计中文字数
Obsidian 自带的字数统计对中文不友好,这是个经典的「自己动手」场景。把模板 main.ts 里的示例类换成下面这段,就有了一个能用的插件——左侧栏一个图标、命令面板一条命令,点一下弹出当前笔记的中文字符数:
import { Plugin, Notice } from 'obsidian';
export default class ChineseWordCountPlugin extends Plugin {
async onload() {
// 左侧功能区图标(第一个参数是 Lucide 图标名)
this.addRibbonIcon('file-text', '统计当前笔记中文字数', () => {
void this.countWords();
});
// 注册命令,用户按 Ctrl/Cmd+P 就能搜到
this.addCommand({
id: 'count-chinese-words',
name: 'Count Chinese characters in current note',
callback: () => void this.countWords(),
});
}
private async countWords() {
const file = this.app.workspace.getActiveFile();
if (!file) {
new Notice('当前没有打开的笔记');
return;
}
// cachedRead 适合只读场景,比 read 更省 IO
const text = await this.app.vault.cachedRead(file);
const chinese = (text.match(/[\u4e00-\u9fa5]/g) ?? []).length;
new Notice(`中文字符 ${chinese} 个 / 全文 ${text.length} 字符`);
}
}这段代码把插件开发最核心的几件事都涵盖了:onload() 是插件生命周期入口,addRibbonIcon / addCommand 是两种主要的功能入口,this.app.workspace 拿当前界面状态,this.app.vault 读写文件,Notice 弹提示。想往下加功能,基本就是在这几个点上延伸——加设置面板用 addSettingTab(new XxxSettingTab(this.app, this)),弹窗用 Modal,监听文件变化用 this.registerEvent(this.app.vault.on('modify', ...))。
怎么让 AI 一次写对:把规范喂给它
直接说「帮我写个 Obsidian 插件」,模型大概率会给你一份能跑但违反官方规范、上架必被打回的代码——它记忆里混杂着大量早期社区插件的老写法。有效做法是把「事实」和「规矩」都摆到它面前:
- 1给它真实的类型定义:项目里
node_modules/obsidian/obsidian.d.ts就是完整 API 定义。让 AI 编程工具先读这个文件,而不是凭记忆猜方法名——这一步能消掉大部分「查无此 API」的幻觉。 - 2给它模板作参照:让它先读
main.ts原始示例,照着现有工程结构改,而不是另起一套。 - 3把官方规范写成项目规则文件:在仓库根目录放一份
AGENTS.md(或CLAUDE.md),把下面这些硬性约束写进去,AI 每次都会带着这些约束干活。 - 4让它自己跑检查:模板预置了 ESLint,让 AI 改完后跑
npm run lint和npm run build,报错自己修完再给你看。
# Obsidian 插件开发约束(写给 AI)
- 只用 `obsidian` 包导出的 API;除非 manifest 里已设 isDesktopOnly,禁止引入 fs / path / child_process。
- 禁止 `innerHTML` / `outerHTML` / `insertAdjacentHTML`,一律用 `createEl()` / `createDiv()` / `createSpan()` 构建 DOM。
- 用 `this.app`,禁止使用全局 `app` 或 `window.app`。
- 事件监听用 `this.registerEvent(...)`,定时器用 `this.registerInterval(...)`,确保插件卸载时自动清理。
- 变量用 `const` / `let`,不用 `var`;异步用 `async` / `await`,不写 Promise 链。
- 样式写进 styles.css 并优先复用 Obsidian CSS 变量,禁止在 TS 里硬编码颜色、字号、间距。
- 界面文案(命令名、设置项、按钮)用 sentence case,只首字母和专有名词大写。
- 不要保留模板的 MyPlugin / MyPluginSettings / SampleSettingTab 等占位类名。
- 正则不要用 lookbehind,移动端不支持。官方规范里 AI 最容易踩的几条
Obsidian 的开发者规范(Plugin guidelines)不长,但每一条都对应过真实的社区事故。这张表是 AI 生成代码里出现频率最高的几处违规,也是上架自动审核和人工复查会盯的地方:
| AI 常见写法 | 正确写法 | 为什么 |
|---|---|---|
| `el.innerHTML = userInput` | `el.createEl('span', { text: userInput })` | 用笔记内容拼 HTML 等于把 XSS 注入自己的 vault,这是官方明确点名的安全风险 |
| `app.vault.read(...)`(全局 app) | `this.app.vault.read(...)` | 全局 app 是内部实现细节,官方要求用插件实例上的引用 |
| `document.addEventListener(...)` 裸注册 | `this.registerDomEvent(...)` / `this.registerEvent(...)` | 插件卸载时不清理,监听器会残留、内存泄漏,重载后一次操作触发多次 |
| `setInterval(...)` | `this.registerInterval(setInterval(...))` | 同上,定时器必须随插件卸载一起销毁 |
| 在 TS 里写 `el.style.color = '#7c3aed'` | 在 styles.css 里加 class,用 CSS 变量 | 硬编码样式在深色/浅色主题下必然有一种是难看的,用户也无法覆盖 |
| 命令名写成 `Count Chinese Words In Note` | `Count Chinese characters in current note` | 官方 UI 文案统一 sentence case |
| 插件 id 起成 `obsidian-word-count` | `chinese-word-count` | id 全市场唯一且不允许包含 obsidian 字样,否则自动审核直接不通过 |
发布与上架:2026 年 5 月起流程已经变了
这一步是网上中文教程最容易把你带错路的地方。过去几年的教程都会告诉你「往 obsidian-releases 仓库提 PR,然后排队等人工审核,通常要等半个月以上」。2026 年 5 月 12 日,官方上线了全新的社区平台 community.obsidian.md,把提交入口和审核方式整个换掉了:现在是登录官网、关联 GitHub、在开发者面板里选仓库提交,自动化审核通常几分钟内出结果;只有热门插件、精选插件和被举报的项目才会走人工复查。之前积压的 2300 多个待审提交,就是靠这套自动审核清空的。
提交之前,你的仓库和 Release 需要满足这些硬性条件(自动审核会逐条检查):
- 仓库根目录有
README.md(说明插件用途和用法)、LICENSE(选好开源协议)、manifest.json。 - GitHub Release 的 tag 是纯
x.y.z格式,不带 v 前缀,且与 manifest.json 里的 version 完全一致。 - Release 里以附件形式上传了
main.js、manifest.json,用到样式的话再加styles.css(注意是作为 Release assets 单独上传,不是只打包源码)。 id全市场唯一且不含 obsidian 字样;name不叫 Sample Plugin。- 代码里没有 innerHTML 这类被点名的写法,没有混淆代码,没有未经用户同意的数据上报。
# 模板内置了版本号同步脚本:一条命令同时更新
# package.json / manifest.json / versions.json
npm version patch # 1.0.0 -> 1.0.1,功能不变的修 bug
# npm version minor # 1.0.0 -> 1.1.0,加了新功能
# 产出用于发布的 main.js(生产构建,含类型检查)
npm run build
# 推代码和 tag,然后到 GitHub 上按这个 tag 创建 Release,
# 把 main.js / manifest.json / styles.css 作为附件上传
git push && git push --tags不想上架也完全可以
上架的唯一好处是别人能在插件市场里搜到你。只给自己或几个朋友用,把 main.js、manifest.json、styles.css 三个文件拷进对方 vault 的 `.obsidian/plugins/你的插件id/` 目录即可;想让对方能自动更新,就让他们装 BRAT 插件,在里面填你的 `用户名/仓库名`,BRAT 会自动跟踪你的 GitHub Release 并更新。这也是插件正式上架前做 beta 测试的标准做法。
从「能跑」到「敢给别人用」
AI 让写出第一版插件变得很快,但插件是要跑在别人真实笔记库上的程序,有几件事必须你自己把关,而不是交给模型:
- 任何写文件的操作都要额外小心——修改笔记优先用
vault.process()这类原子接口,避免「读出来—改—整篇覆盖」的写法在用户同时编辑时丢内容。批量操作先在测试 vault 上跑,并且给用户留确认步骤。 - 移动端要么支持,要么老实声明——用了 Node API 就把
isDesktopOnly设成true。谎报的后果是手机端用户一装就崩。 - 报错要给用户看得懂的提示——
Notice里写「无法解析这篇笔记的日期格式」,而不是把异常堆栈原样弹出来。 - 性能别在大 vault 上翻车——几千篇笔记的库里做全量遍历,主线程一卡整个应用就假死;能用元数据缓存(
metadataCache)就别自己读文件。 - 不要偷偷联网——插件要往外发任何数据,都必须在 README 和设置里明确告知,这是官方政策的红线,也是社区最敏感的点。
写 Obsidian 插件的价值不只是多一个顺手的小工具——它是一个几乎没有环境噪音的练习场:需求是你自己的,反馈是即时的,规范是明确的,你能非常清楚地看到「把要求讲清楚、把规则喂给 AI、让它自己跑检查」这套方法到底能把交付质量提升多少。这套从需求拆解到规范约束、再到验证发布的完整方法论,也正是 IMAI 体系化课程一直在讲的东西:让 AI 帮你交付真正能给别人用的产品,而不是停在「能跑就行」的第一版。
想系统学会用 AI 编程,从入门到做出真实产品?
查看系统课程