AI開発(AIエージェントとの協働)に最適化したノート・タスク管理デスクトップアプリ hanamask を公開しました。v1.0.0 です。
コンセプトは一言でいうと 「本文はエージェントが書き、人間が読む」 です。
↑ エージェントが書いたノート。Markdownの表もMermaid図もそのまま描画されます。
どんな課題を解決するのか
Claude Code などのAIエージェントと日常的に開発していると、こんなことが起きます。
- エージェントに調べさせた結果が チャットログの奥に埋もれて二度と見つからない
- 「さっき決めた方針」がセッションを跨ぐと消える。同じ調査を二度やる
- 作業中に見つけたバグや TODO を口頭で伝えたきり、どこにも積まれていない
チャットは揮発します。かといって、エージェントの出力を毎回自分でコピペしてノートアプリに貼るのは続きません。
なら、エージェント自身にノートとタスクを書かせればいい——というのが hanamask の出発点です。
hanamask とは
ローカル完結のノート・タスク管理 Electron アプリで、MCPサーバーを内蔵しています。アプリを起動すると http://127.0.0.1:39217/mcp(Streamable HTTP)で待ち受けが始まり、普段使っているAIエージェントがそこにつないで、ノート・タスクを直接読み書きします。
-
主要な操作経路はエージェント。
create_note/create_task/search_notesなど約20のMCPツールを公開 - データは全部ローカル。 SQLite + ローカルファイル。クラウド同期はありません
- AIモデルは内蔵しない。 利用者自身が管理するエージェント(BYO Agent)をつなぐ設計
- Apache License 2.0 のOSSです
構成はこうなっています。エージェントは外にいて、hanamask はあくまで「エージェントが読み書きする記録置き場 + 人間が読む画面」です。
クラウドはどこにも登場しません。通信は localhost で閉じています。
対象環境
アプリ本体は現在 Windows 向けで、インストーラー(hanamask-Setup-*.exe)を配布しています。つなぐ側のエージェントは、Streamable HTTP トランスポートの MCP クライアントなら何でも構いません(Claude Code で動作確認しています)。
よくある構成は次の2つです。
| 構成 | 追加設定 |
|---|---|
| Windows 上のエージェント → Windows 上の hanamask | 不要。127.0.0.1 でそのままつながる |
| WSL2 上のエージェント → Windows 上の hanamask | WSL のミラーモードが必要(下記) |
WSL2 から使う場合はミラーモードを設定する
hanamask の MCP サーバーは 127.0.0.1 にのみ待ち受けます。WSL2 は既定で Windows とは別のネットワークを持つため、WSL 側から見た 127.0.0.1 は WSL 自身であり、Windows 側のアプリには届きません(Windows→WSL 方向の転送はありますが、逆方向はありません)。
待ち受けを 0.0.0.0 に広げれば届きますが、MCP サーバーには認証が無く、接続できた相手はノート・タスクの全読み書き(削除を含む)ができるため、ローカルネットワークへ露出させる選択は取りませんでした。代わりに WSL のミラーモードを使います。WSL が Windows のネットワークを写し取り、両者で localhost が同じものを指すようになる仕組みで、アプリ側は 127.0.0.1 のまま変更不要、ネットワークへの露出も増えません。
C:\Users\<ユーザー名>\.wslconfig に次を書き、Windows 側から wsl --shutdown で再起動するだけです。
[wsl2]
networkingMode=mirrored
前提は Windows 11 22H2 以降 + WSL 2.0.0 以降です。到達確認は WSL から:
curl -s -m 5 http://127.0.0.1:39217/mcp -o /dev/null -w '%{http_code}\n'
詳細な手順・切り戻し・既知の副作用は docs/WSL.md にまとめてあります。
⚠️ ミラーモードは WSL のネットワーク挙動を全体的に変えます。他プロジェクトでポート転送やコンテナのネットワークに依存している場合は、影響を確認してから切り替えてください。
セットアップは2ステップ
Node.js もソースコードも不要です(Electron アプリなので実行に必要なものは同梱)。
1. インストールして起動する
Releases から hanamask-Setup-*.exe をダウンロードして実行し、起動したままにしておきます(MCPサーバーはアプリの中で動いているため、アプリを閉じるとエージェントからも見えなくなります)。
インストーラーには署名を付けていないため、実行時に「WindowsによってPCが保護されました」という画面が出ます。**「詳細情報」→「実行」**と進めてください。署名しない判断の経緯は docs/SIGNING.md にまとめてあります。
データは %APPDATA%\hanamask\ に保存され、アンインストールや新しい版の上書きインストールでは消えません。
なお自動更新の仕組みはまだありません。新しい版が出ていないか Releases をたまに見て、あれば同じ手順で入れ直してください(上書きしてもデータは消えません)。
2. エージェントをつなぐ
Claude Code なら1コマンドです。
claude mcp add --transport http hanamask http://127.0.0.1:39217/mcp
あるいは、エージェントにこう頼むだけでも設定してくれます。
hanamask というローカルアプリの MCP サーバーにつないでください。
エンドポイントは http://127.0.0.1:39217/mcp、トランスポートは Streamable HTTP です。
あとは普段どおり話しかけるだけです。
今日調べたことをノートにまとめて
さっきのバグ、タスクに積んでおいて
このノートに「プロジェクトA」のタグを付けて
裏で起きていることはこうです。利用者がやるのは最初の一言だけで、ツールの選択も本文の整形もエージェント側が済ませます。
こだわったところ
1. エージェントの書き込みが「見える」
エージェントが書いた内容は、開いている画面へ手動リロードなしで現れます。書き換えられた直後のノートはピンクで示し、「たった今 · エージェントが更新」と文字でも表示します(色だけに意味を持たせない)。
画面を見ていないときは OSの通知 で知らせます。通知が出るのはウィンドウにフォーカスが無いときだけなので、自分のUI操作で鳴ることはありません。短時間に続いた変更は1通にまとめます。
自分が編集している最中に外から更新が来た場合は、編集内容を消さずに通知だけを出して利用者に選ばせます。
2. タグで「どの案件の記録か」が分かる
エージェントは記録を増やし続けるので、放っておくと案件Aと案件Bの話が同じ一覧に混ざります。ノート・タスクにはタグを付けられ、一覧のカード上で開かずに判別でき、絞り込み・タグごとのグループ表示もできます。
↑ 「プロジェクトA」で絞り込んだ状態。選んだタグ以外は消さずに薄く残すので、「この記録は別の案件にも関わっている」ことが同時に分かります。
タグを付けるのもエージェントです。ここで問題になるのがエージェントは過去に自分が何と名付けたかを覚えていないこと。同じ案件に「プロジェクトA」「project-a」と別名が付くとグループとして機能しなくなるため、使われているタグと件数を返す list_tags ツールを用意し、既存タグを再利用させています。
3. エージェントに壊されないためのガードレール
エージェントに書き込み権限を渡す以上、事故への備えが要ります。
-
削除はすべてソフトデリート。 物理削除はせず、
delete_note/delete_taskはconfirm: trueを必須に。ゴミ箱から30日間は復元できます
-
編集履歴を自動保存。 ノート更新前のスナップショットが残り、
restore_note_versionで戻せます。復元操作自体も履歴に積まれるので、復元もやり直せます - 取り込み前の自動退避。 バックアップzipの取り込みは既存データを置き換えますが、実行前の状態が自動でzipに退避されます
4. データを人質に取らない
設定画面から、ノート・タスク・リンク・編集履歴・画像を zip 1つに書き出せます。別のPCへの移行、OSの入れ直し、破損時の備えに使えます。中身はSQLiteとふつうのファイルなので、アプリを気に入らなくなってもデータは読めます。
セキュリティモデル
エージェントに全権を渡すアプリなので、どこで線を引いているかを書いておきます。
接続の境界は「localhost に閉じる」こと。 MCPサーバーは 127.0.0.1 にのみ待ち受け、認証や Origin 検証は持ちません。つまり接続できた相手はノート・タスクの全読み書き(削除を含む)ができる、という割り切りです。だからこそ待ち受けは絶対に広げません——WSL2 対応でも 0.0.0.0 に開く方法を採らず、ミラーモード(前述)で localhost のまま届くようにしたのはこのためです。データもすべてローカルに閉じており、外部へ送信される経路がそもそもありません。
本文は「信頼できない入力」として扱う。 本文は Markdown(GFMの表・タスクリスト対応)+ HTML直接埋め込み + Mermaid図に対応していて、装飾を凝りたいエージェントは <div style="..."> をそのまま書けます。ただし書くのはAIエージェントなので、<script> / <iframe> / javascript: リンク / イベントハンドラ属性は描画時に取り除きます。style 属性は使えますが <style> タグは描画しません(タグ内のCSSはアプリ全体に効いてしまうため)。
詳細は SECURITY.md にまとめてあります。
実装済みのMCPツール(抜粋)
| 分類 | ツール |
|---|---|
| ノート |
create_note / get_note / search_notes / update_note / delete_note / restore_note / list_note_versions / restore_note_version / attach_image
|
| タスク |
create_task / update_task / list_tasks / delete_task / restore_task
|
| タグ | list_tags |
| リンク |
link_entities / unlink_entities / list_links
|
| UI連携 |
open_app / open_note / open_task / open_search
|
UI連携ツールが地味に便利で、エージェントに「そのノート開いて」と言うとデスクトップアプリの該当画面が前面に出ます。
技術スタック
- アプリ本体: Electron
- UI: React + Vite / Tailwind CSS v4 / motion / Mermaid
-
MCPサーバー:
@modelcontextprotocol/sdkを main プロセスに内蔵、localhost 向け Streamable HTTP で待ち受け -
データ保存: SQLite(
better-sqlite3)+ ローカルファイルシステム(画像) -
テスト: Vitest + Playwright の
_electronAPI(E2E)
おわりに
「エージェントに話すだけで記録が残り、人間はきれいに描画された画面で読む」という体験は、一度慣れると手動のノート管理に戻れなくなります。
フィードバック・Issue・PR、お待ちしています

