Google Drive 上の Markdown をAI と人間が安全に編集するためのエディタ coscribe
AI と一緒に文章を書く機会が増えた。書いてもらう機会が増えたというほうが妥当かもしれないが。
その分、読む機会・量が増えた。
自分の場合、Google Drive をMac に同期して Markdown ファイルを置いて、そこにメモや仕様、下書きを書いている。Typora のような WYSIWYG エディタで読み書きしたい。プレビューが別れるのはちょっと苦手な感じ。
一方で、Claude Code や Codex などの AI にも同じ .md ファイルを直接編集してもらいたい。
この運用はかなり便利なのだけれど、人間側のエディタが外部変更に気づかないまま保存すると、AI が書いた内容を上書きして消してしまう。その逆でAIに上書きされるほうが多いという感じもある。
Typora では発生するけど、CotEditor では発生しないので、なにか Google Drive で管理してるファイルとアプリ側の相性とかなんだろうと思われる。
これを避けるために、coscribe という macOS 向け Markdown エディタを作った(作ってもらった)。
作ったもの
coscribe は、Google Drive 上の Markdown ファイルを、人間と AI が安全に共同編集するためのエディタ。
機能は Typora の劣化版なかんじではあるがこんな感じ。
.md/.markdownファイルを WYSIWYG で編集する- Google Drive 上の外部変更を検知する
- ローカル編集と外部変更が衝突したら、上書きせず退避する
- GFM table や task list を扱う
##見出し単位でセクションをロックする- frontmatter や未対応 Markdown をなるべく壊さず保持する
- クラッシュ時の復旧 snapshot を残す
AI と人間が同じ Markdown ファイルを触っても、内容を消さないことを目指す。
既存アプリもいくつか試したけどマッチしなかった。
| アプリ | 良いと感じた点 | 自分の用途に合わなかった点 |
|---|---|---|
| CotEditor | Google Drive 互換性が良い | 表を WYSIWYG に扱う体験が弱い |
| Typora | WYSIWYG の体験が一番良い | Drive 上の外部変更を検知できず、上書き事故の原因に |
| MWeb / Bear / Inkdrop | それぞれ UI や同期が良い | 「Drive + AI 共同編集」の前提に合わなかった |
ちなみに Obsidian はデイリーノートで別途使っているので、それとは別にしたかったというのがある。
ということで以下、開発した Codex に記事を書いてもらった。
へー。
外部変更をどう検知するか
Google Drive 上のファイルでは、macOS の通常のファイル変更イベント(FSEvents)だけに頼るのが危うい。Drive の仮想ファイルシステムは FSEvents を期待通りに発火しないことがある。
そこで coscribe では、Rust 側で polling watcher を使っている。一定間隔でファイルの状態を確認し、外部変更があればフロントエンドに通知する。
ローカルに未保存変更がない場合は、そのままディスク上の最新版を読み込む。未保存変更がある場合は、前述の競合フローに乗せる。
この挙動があるだけで、AI と同じファイルを触るときの安心感がかなり変わる。
Markdown を壊さず保存する難しさ
作ってみて改めて感じたのは、Markdown エディタの難しさは「表示」よりも「保存」にあるということだ。
Markdown は単純なテキストに見えるが、実際にはいろいろな方言や拡張がある。frontmatter、GFM table、task list、HTML comment、wikilink、footnote、Obsidian callout など、すべてをきれいに WYSIWYG 化するのは簡単ではない。
しかも、AI と共同編集する用途では、勝手な整形も困る。
見た目は同じでも、保存した瞬間に Markdown の細部が変わると、差分が読みにくくなる。場合によっては、未対応構文が壊れる。
そのため coscribe では、対応できる構文と保護する構文を分けている。
たとえば frontmatter は、MVP では編集 UI を持たせず、raw slice として切り出して保存時にそのまま戻す。未対応 Markdown についても、無理に解釈して壊すより、なるべくそのまま保持する方針にしている。
完全な Markdown 互換エディタを作るのではなく、自分の運用で壊れてほしくない部分を明確に守る、という設計にした。
競合したらどうするか
外部変更があり、かつローカルにも未保存の編集がある場合は、競合モーダルを出す。
ここで coscribe は「Save Anyway」のような片方を消す挙動を基本にしない。ディスク版を採用する場合も、ローカル版は退避ファイルとして残す。逆にローカル版を採用する場合も、ディスク版を退避する。
退避ファイルは、元ファイルと同じディレクトリに次の名前で作られる。
filename.md.local-YYYYMMDD-HHmmss.md
filename.md.disk-YYYYMMDD-HHmmss.md
これなら、判断を間違えても内容自体は残る。「どちらを採用するか」よりも前に、「どちらも失わない」ことを優先している。
セクションロック
coscribe には、## 見出し単位でセクションをロックする機能も入れた。
これは、AI と共同編集するうえでかなり重要だと思っている。
たとえば、ひとつの Markdown ファイルの中に「自分のメモ」と「AI に整理してほしい部分」が混在していることがある。AI には後者だけ触ってほしいが、前者は勝手に書き換えてほしくない。
そこで、見出し単位で保護できるようにした。
内部的には Markdown 内にロック用の HTML comment を保持し、ProseMirror の transaction レベルで編集を拒否する。単に見た目を read-only 風にするのではなく、編集操作そのものを止める方針にしている。
これはまだ発展途上だが、将来的には「AI が編集してよい範囲 / 触ってはいけない範囲」を UI 上で管理できるようにしたい。
技術構成
技術構成は、Claude と Codex に相談しながら決めた。主な構成は次のとおり。
- Tauri 2
- React 18
- TypeScript
- Tiptap / ProseMirror
- markdown-it
- Rust
- Vite
- Vitest
- ESLint
フロントエンドは React + Tiptap、macOS アプリ化とファイル操作まわりは Tauri + Rust で構成している。Markdown の parse / serialize まわりは、既存ライブラリだけでは要件に合わない部分があったため、一部自前で実装した。
学び
一番の学びは、AI と共同編集する時代のエディタには、従来とは違う安全性が必要だということだ。
これまでのエディタは、基本的に「人間がそのアプリ内で編集する」ことを中心に考えている。しかし今は、AI や CLI ツールや別アプリが、同じファイルを外部から編集する。
その場合、エディタが古い内容を持ち続けること自体がリスクになる。
Markdown エディタとしての快適さも大事だが、それ以上に「このエディタで開いていても、AI の編集を消さない」と信頼できることが大事だった。
今後やりたいこと
今の coscribe は、まだ個人利用向けの MVP だ。今後はざっくり2階層で進めたい。
直近で着手したいこと
- フォルダツリー
- 最近開いたファイル
- 本文検索
- E2E テスト
- Markdown roundtrip テストの拡充
- Google Drive 上での長文ファイル検証
将来構想
- 設定画面の整理
- PDF / HTML 書き出し
- AI が編集してよい範囲を管理する UI
coscribe は、単なる Typora クローンではない。Google Drive や AI による外部編集を前提にした、壊れにくい Markdown エディタとして育てたい。
AI と人間が同じファイルを編集するのは、これからもっと普通になると思う。そのときに必要なのは、派手な AI 機能だけではなく、地味だけれど確実に内容を守る仕組みだ。
coscribe は、そのために作った。