Claude CodeでObsidianプラグインを開発する手順
ObsidianのサンプルプラグインをClaude Codeで拡張し、manifest更新・ホットリロード・審査提出まで進める手順と、レビューガイドラインが定める落とし穴をまとめます。
Obsidianプラグイン開発でClaude Codeが担う役割
Claude CodeでObsidianプラグインを開発するときは、ビルドと読み込みをObsidianのツールチェーンに任せます。Claude Codeにはコードの生成とガイドライン準拠のレビューを任せます。ノートをClaudeから読み書きしたいだけなら、プラグインを作らずMCPサーバー経由でつなぐ方法もあります。
Obsidianプラグインとは、TypeScript製のPluginクラスを継承してObsidianに機能を追加するコードです。開発手順は通常のTypeScriptプロジェクトと同じで、Claude Code向けの特別な手順はチュートリアルにありません。
この記事では、サンプルプラグインをcloneしてからmanifestを更新し、審査に提出するところまでを、Claude Codeを使う場面ごとに区切って説明します。手順そのものはObsidianのチュートリアルと同じで、そこにClaude Codeの使いどころを足す構成です。
開発を始める前に、次の3つを用意します。
- Git
- ローカルのNode.js開発環境
- Claude Code(コードエディタとしてVS Code等を併用してもよい)
Step 1: サンプルプラグインを取得してビルドする
サンプルプラグインはobsidianmd/obsidian-sample-pluginとしてGitHubに公開されています。テンプレートリポジトリなので、自分のGitHubアカウント上に複製してから使うことも可能です。
開発用Vaultの.obsidian/pluginsディレクトリにcloneし、依存関係をインストールします。
cd path/to/vault/.obsidian/plugins
git clone https://github.com/obsidianmd/obsidian-sample-plugin.git
cd obsidian-sample-plugin
npm install
npm run devnpm run devはターミナルで動き続け、ソースコードを変更するたびにmain.jsを自動で再コンパイルします。ここまでは通常のTypeScript開発と同じで、Claude Codeを起動する必要はまだありません。
Obsidian側では「設定」→「コミュニティプラグイン」から「コミュニティプラグインを有効化」を選び、インストール済みプラグイン一覧でSample Pluginのトグルをオンにします。これでプラグインが読み込まれます。
cloneしたリポジトリのpackage.jsonには、後の工程で使うスクリプトが4つ定義されています。
| スクリプト | 実行内容 |
|---|---|
dev | 実行内容esbuildをウォッチモードで起動し、main.jsを再生成し続ける |
build | 実行内容tsc -noEmit -skipLibCheckで型検査してから、本番用にminifyして書き出す |
lint | 実行内容eslint .を実行する |
version | 実行内容version-bump.mjsを実行し、manifest.jsonとversions.jsonを更新してgit addする |
型検査が入っているのはbuildで、devには含まれません。ウォッチ中に型エラーがあってもmain.jsは再生成されます。Claude Codeに編集を任せるときは、buildかlintを別途走らせる運用にすると安全です。
Step 2: Claude CodeにObsidian APIの作法を教える
Obsidian APIには、レビューで頻出する指摘としてまとめられた作法があります。これをClaude Codeに知らせずに編集を任せると、サンプルプラグインのまま残りがちなアンチパターンを踏襲してしまいます。
サンプルプラグインのリポジトリには、最初からAGENTS.mdが入っています。ファイルの分け方、manifest.jsonの規則、リリース手順までを書いた指示ファイルで、ゼロから書く必要はありません。
指示ファイルに書く内容の分担
サンプル同梱のAGENTS.md
main.tsはライフサイクル(onload・onunload・addCommand)に絞る- 200〜300行を超えるファイルはモジュールに分ける
- すべてを
main.jsにバンドルする - タグはバージョン番号そのままにし、
vを付けない
CLAUDE.mdに足す
- グローバルな
appではなくthis.appを使う innerHTMLなどでユーザー入力からDOMを組み立てない- 自動解放されないリソースだけ
onunload()で解放する
CLAUDE.mdに足す3点はレビューガイドラインにある指摘です。理由は次のとおりです。
this.app: グローバルなappはデバッグ用途で、将来削除される可能性がある- DOM構築:
innerHTML・outerHTML・insertAdjacentHTMLは、ユーザー入力に<script>が含まれると任意のコードを実行されるリスクがある。代わりにcreateEl()・createDiv()・createSpan()を使う - 解放:
registerEvent()で登録したイベントやaddCommand()で登録したコマンドは、アンロード時に自動で解放される。手動で作ったリソースだけonunload()で解放する
既定では、CLAUDE.mdがあるとAGENTS.mdは読まれません。サンプル同梱のAGENTS.mdを生かしたままCLAUDE.mdを足すなら、CLAUDE.mdの先頭に@AGENTS.mdと書いて取り込みます。/configのProject instructionsをclaude-md-and-agents-mdにしても、両方を読ませられます。AGENTS.mdだけを直接読む動作は、v2.1.277以降の挙動です。複数のAIツールで設定を共有する場合は、AGENTS.mdとCLAUDE.mdで設定を統合する運用パターンのように一本化しておくと、Obsidian API向けの作法を二重管理せずに済みます。
CLAUDE.mdに書いた作法を編集のたびに確認させたい場合は、Claude CodeのPostToolUse hookで型検査を自動実行する構成も選べます。.claude/settings.jsonに次のように書くと、EditまたはWriteのたびにbuildスクリプトと同じ型検査が走ります。
{
"hooks": {
"PostToolUse": [
{
"matcher": "Edit|Write",
"hooks": [
{ "type": "command", "command": "npx tsc -noEmit -skipLibCheck" }
]
}
]
}
}このmatcherはEditとWriteだけに反応し、Bash経由のファイル書き換えは対象外です。詳しい設定手順はPostToolUse hookでツール実行後の後処理を自動化するにまとめています。
Step 3: manifest.jsonを更新してプラグインを識別可能にする
manifest.jsonはプラグインの識別情報を持つファイルです。リファレンスでは、プラグイン固有のプロパティとして次の3つが必須とされています。
| プロパティ | 必須 | 内容 |
|---|---|---|
id | 必須必須 | 内容小文字とハイフンのみ。末尾をpluginにできず、obsidianという文字列も含められない |
description | 必須必須 | 内容プラグインの説明文 |
isDesktopOnly | 必須必須 | 内容NodeJSやElectron APIを使うなどデスクトップ専用の場合はtrue |
共通プロパティとしてauthor・minAppVersion・name・version(x.y.z形式のセマンティックバージョニング)も必須です。authorUrlとfundingUrlは任意項目です。ローカル開発ではidをプラグインのフォルダ名と一致させておくと、onExternalSettingsChangeなどの一部メソッドが正しく呼び出されます。
サンプルが出荷時に持つ値は、idがsample-plugin、nameがSample Plugin、versionが1.0.0、minAppVersionが1.0.0、isDesktopOnlyがfalseです。descriptionにもサンプル用の文言が入っているので、これも書き換えの対象です。
nameにも制約があります。英数字(Basic Latin)を基本とし、ハイフン・プラス記号・括弧以外の記号や絵文字は使えません。「Live Preview」のようなObsidianのコア機能名は単体では使えず、「Obsidian」「Plugin」という単語やその変形も含められません。
Claude Codeにこの節を渡し、「manifest.jsonのidを一意な識別子に変更し、プラグインフォルダ名も揃える」ように指示すれば、チュートリアルのStep 4に相当する作業を任せられます。main.ts側のクラス名の改名も同時に頼むと手戻りが減ります。ガイドラインが、プレースホルダーのMyPlugin・MyPluginSettings・SampleSettingTabを自分のプラグイン名に合わせて改名するよう求めているためです。
AGENTS.mdには「リリース後にidを変えない。安定したAPIとして扱う」とあります。idの変更は最初の公開前に済ませる作業です。
Step 4: 開発ループを回す
コードを変更したら、プラグインを再読み込みしないと変更が反映されません。リロードには3つの方法があります。
- 手動リロード: コミュニティプラグイン一覧でトグルをオフ→オンにする
- コマンドパレット: 「Reload app without saving」を実行する(チュートリアルのStep 5で案内されている方法)
- 自動リロード: コミュニティプラグインHot-Reloadを導入し、ソースコードの変更を検知して自動的にリロードする
manifest.jsonを書き換えたときは別扱いで、チュートリアルは「manifest.jsonを変更するたびにObsidianを再起動する」ことを求めています。
npm run devはエディタ上のソースではなくmain.jsというビルド成果物を書き換えます。このmain.jsはClaude Codeが直接編集したファイルではなく、ビルドプロセスが生成した派生ファイルです。Claude Codeのセッション中にこの種の外部プロセスによる書き換えを把握しておきたい場合は、FileChanged hookでディスク上の変更を検知する構成が使えます。仕組みはFileChanged hookでディスク上のファイル変更を検知するで解説しています。
デバッグには開発者ツールのConsoleタブを使います。Windows/LinuxはCtrl+Shift+I、macOSはCmd-Option-Iで開けます。onload()とonunload()にconsole.logを仕込んでおくと、リロードのタイミングを目視で確認できます。
Claude Codeにレビューさせたいチェック項目
Obsidianのガイドラインには「レビューでよく出る指摘」が一覧になっています。サンプルプラグインを改造したコードをClaude Codeにレビューさせる際は、次の観点を明示的に伝えると効果的です。
| 観点 | 避けるべき実装 | 推奨される実装 |
|---|---|---|
| 開いているノートの編集 | 避けるべき実装Vault.modifyで書き換える(カーソル位置・選択範囲・折りたたみが失われる) | 推奨される実装Editorインターフェースを使う |
| 開いていないファイルの編集 | 避けるべき実装Vault.modifyで書き換える | 推奨される実装Vault.processで原子的に書き換える |
| フロントマター編集 | 避けるべき実装YAMLを自前でパースして書き戻す | 推奨される実装FileManager.processFrontMatterを使う |
| ファイル検索 | 避けるべき実装vault.getFiles().find()で全ファイルを走査する | 推奨される実装Vault.getFileByPath()で直接取得する |
| アクティブビュー取得 | 避けるべき実装workspace.activeLeafを直接参照する | 推奨される実装getActiveViewOfType()を使う |
| ファイル操作の層 | 避けるべき実装app.vault.adapterを直接呼ぶ | 推奨される実装app.vaultのVault APIを使う(キャッシュと直列処理の恩恵がある) |
| コマンド | 避けるべき実装デフォルトのホットキーを設定する | 推奨される実装ホットキーは未設定のままユーザーに委ねる |
| スタイリング | 避けるべき実装el.style.colorのようにインラインで指定する | 推奨される実装CSSクラスとObsidianのCSS variablesで指定する |
ユーザーが入力したパスを扱うコードには、normalizePath()を通す指摘もあります。スラッシュの重複や前後のスラッシュを除き、ノーブレークスペースを通常の空白に置き換える関数です。パスを組み立てる箇所をClaude Codeに洗わせるときの観点になります。
モバイル対応が必要な場合は追加の制約があります。Node.jsとElectronのAPIはモバイル版Obsidianで使えないため、isDesktopOnlyをtrueにしない限り、これらのAPIを呼ぶコードはモバイル環境でクラッシュの原因になります。正規表現の後読み(lookbehind)もiOS 16.4未満では未対応なので、Platform.isIosAppで分岐するか、ブラウザのバージョンを検出してフォールバックを用意します。
デスクトップ上でモバイルの挙動を試すには、開発者ツールのConsoleでthis.app.emulateMobile(true)を実行します。戻すときはfalseを渡します。実機のAndroidはUSBデバッグを有効にしてchrome://inspect/から、iOSは16.4以上とmacOSの組み合わせで確認できます。
公開までの流れ
開発が一段落したら、Obsidian Community directoryへの提出に進みます。提出前にリポジトリのルートへREADME.md(プラグインの説明と使い方)・LICENSE・manifest.jsonの3ファイルを揃えます。
リリースから審査対応まで
- 1
バージョンを上げる
manifest.jsonのminAppVersionを必要に応じて直したうえで、npm version patch・npm version minor・npm version majorのいずれかを実行します。versionスクリプトがmanifest.jsonとversions.jsonを更新します。 - 2
GitHub Releaseを作る
タグ名は
manifest.jsonのversionと完全に一致させます。main.js・manifest.json・任意でstyles.cssをバイナリ添付ファイルとしてアップロードします。 - 3
ディレクトリに登録する
community.obsidian.mdでObsidianアカウントにログインし、GitHubアカウントを連携してからプラグインを追加します。
- 4
指摘に対応する
自動レビューが走り、修正が必要な箇所は画面上に表示されます。対応したら、バージョンを上げた新しいGitHub Releaseを公開します。
npm versionを使うときは、サンプルに含まれる.npmrcが効きます。中身はtag-version-prefix=""の1行で、npmが作るGitタグから既定のvを外します。Obsidianはタグ名とmanifestのversionの一致を求めるため、v1.0.1ではなく1.0.1というタグが必要になるからです。リポジトリを新規に作り直す場合は、この.npmrcも一緒に持っていきます。
versions.jsonは「プラグインのバージョン→必要なObsidianの最小バージョン」の対応表です。version-bump.mjsは、同じバージョンのエントリが既にあれば上書きしません。サンプルのREADMEによると、この表があることで古いObsidianが互換のある旧版を入手できます。
提出方法については、サンプルのREADMEと公式ドキュメントで記述が異なります。READMEは、公開済みの初版を用意したうえでobsidianmd/obsidian-releasesにプルリクエストを出す流れを案内しています。一方、Submit your pluginのページはcommunity.obsidian.mdから登録する流れです。このページでは、初回のバージョンだけを提出すれば、以後の更新はGitHubのReleaseから利用者に届くと説明されています。
よくあるつまずき
idにobsidianという文字列を含めてしまう: 審査で弾かれる制約です。プラグイン名にもObsidianやその変形(Obsi-など)を含められませんmanifest.jsonを書き換えてもObsidianを再起動していない: チュートリアルは、manifest.jsonを変えたときはObsidianを再起動するよう求めています- 開発中の
onunload()でリーフをdetachしてしまう: ユーザーがプラグインを更新すると、開いていたリーフは、ユーザーが動かした位置に関係なく元の位置で再初期化されます - モバイル版でクラッシュする: Node.js/Electron APIを使うコードパスがデスクトップ専用のはずが、
isDesktopOnlyの設定漏れでモバイルにも配布されているケースです - リリースのタグに
vが付く:npm versionの既定ではタグがv1.0.1の形になります。.npmrcのtag-version-prefix=""を残しておけば避けられます
まとめ
サンプルプラグインのビルド工程は変わらず、Claude Codeに任せる範囲は、コードの生成とガイドライン準拠のレビューです。サンプル同梱のAGENTS.mdを土台に、this.app・DOM構築・リソース解放の3点を足しておけば、最初の指示で踏みやすい指摘を避けられます。Vaultを読み書きさせたいだけなら、プラグインを自作しない道もあります。ObsidianのMCPサーバーでClaudeにVaultを読み書きさせる方法です。
参照した一次ソース
この記事の記述は、次の一次ソースと照合しています。更新時に参照先が変わった場合は一覧も更新します。
- docs.obsidian.md/Plugins/Getting+started/Build+a+plugin
- docs.obsidian.md/Plugins/Getting+started/Anatomy+of+a+plugin
- docs.obsidian.md/Plugins/Getting+started/Development+workflow
- docs.obsidian.md/Plugins/Getting+started/Mobile+development
- docs.obsidian.md/Plugins/Releasing/Plugin+guidelines
- docs.obsidian.md/Plugins/Releasing/Submit+your+plugin
- docs.obsidian.md/Reference/Manifest
- github.com/obsidianmd/obsidian-sample-plugin
- code.claude.com/docs/en/memory
- code.claude.com/docs/en/hooks-guide