はじめに
前の記事では、Windows のデスクトップアプリを AI に操作させる MCP サーバー winuse を使い、Claude Code に実機確認を強制する仕組みを紹介しました。
その記事を書き終えたところで、ふと思いました。「この記事の Qiita への投稿も、winuse でできるのでは?」
そこで Claude Code に頼んでみました。
winuse を使って Qiita の投稿も自動化してみて。
この記事は、その結果の記録です。結論から言うと、ログイン済みの Chrome で、タイトル・タグ・本文(約7,600字)を入れて下書き保存するところまで、ほぼ winuse だけでできました。そして、途中でつまずいた点がいちばんの学びでした。
公開ボタンは押させていません。外部への公開は取り消しにくい操作で、記事の内容も人が確認してから出すべきなので、「下書き保存まで」と範囲を決めてから始めました。
使ったもの
- Claude Code(winuse を MCP サーバーとして登録済み)
- winuse 0.2.1
- Google Chrome(Qiita にログイン済み)
ブラウザの自動操作といえば Playwright ですが、今回はあえて winuse を使いました。Windows の UI Automation(UIA)で Chrome を外から操作するので、普段使っているログイン済みのブラウザをそのまま使えます。API トークンを発行する必要もありません。
やったこと
1. 新規記事の画面を開く
まず list_windows で、Qiita を開いている Chrome のウィンドウを見つけます。アドレスバーには press_keys(ctrl+l)でフォーカスし、type_text で URL を入力しました。
list_windows {"process": "chrome"}
→ "title":"Qiita - Google Chrome" (win1)
window_activate {"ref": "win1"}
press_keys {"keys": "ctrl+l"}
type_text {"text": "https://qiita.com/drafts/new\n"}
2. 入力欄を UIA のツリーで見つける
get_ui_tree を実行すると、Web ページの中身も UIA の部品として見えます。
u33 Edit "タイトルを入力してください"
u35 Edit "タグを入力してください。スペース区切りで5つまで入力できます。"
u50 Edit "エンジニアに関わる知識をMarkdown記法で書いて共有しよう" ← 本文
u30 Button "下書き保存"
u31 Button "公開設定へ"
座標を探す必要はなく、部品の名前で入力欄を特定できます。
3. タイトルとタグは set_text で入れる
set_text {"ref": "u33", "text": "Claude Codeに「動作確認をお願いします」と言わせない ― ..."}
set_text {"ref": "u35", "text": "ClaudeCode MCP E2Eテスト Windows デスクトップアプリ "}
set_text は UIA の Value パターンで値を直接書き込みます。React で作られたページだと、値が見た目だけ変わってアプリの状態には届かないのでは、と心配していました。ところが、入力した直後に Qiita の自動保存が走り、URL も下書きの編集画面(/drafts/<id>/edit)に変わりました。タグもタグとして認識されています。ページの状態まで届いていることがわかります。
日本語も set_text なら IME を通らないので、文字化けしません(type_text は日本語 IME 下でまれに化けることがあります)。
4. 本文はクリップボード経由で貼り付ける
本文は約7,600字の Markdown です。Qiita の本文エディタは、自動インデントや括弧の自動補完がある高機能なエディタです。一文字ずつ打つと、それらの機能で中身が変わってしまう恐れがあります。
そこで、ここだけは PowerShell でクリップボードに入れ、winuse で貼り付けました。
Set-Clipboard -Value (Get-Content -Raw -Encoding UTF8 .\winuse-gate.md)
click {"ref": "u50"}
press_keys {"keys": "ctrl+a ctrl+v"}
5. 下書き保存して、assert で確かめる
最後に「下書き保存」を押します。下書き一覧の先頭に記事が出たことを、assert_text で確認しました。
assert_text {"ref": "u179", "expected": "Claude Codeに「動作確認をお願いします」と言わせない ― ..."}
→ {"passed": true, ...}
つまずいたところ
貼り付けが「効いていない」ように見えて、2回貼った
ctrl+a ctrl+v の直後にスクリーンショットを撮ると、本文欄は空のままでした。Claude は「貼り付けが効かなかった」と判断して、もう一度 ctrl+v を送りました。
結果、本文は 2回分(384行) になりました。元の Markdown は192行です。実際には1回目の貼り付けも効いていて、スクリーンショットを撮った時点では、まだ描画が追いついていなかっただけでした。
最終的には、全選択して1回だけ貼り直し、末尾の行番号が192であることを確かめて直しました。
画面を見て「効いていない」と判断するのは危ない、という教訓です。前の記事で「確認はスクリーンショットの感想ではなく assert で」と書きました。その理由を、自分たちで踏んで確かめる形になりました。描画の遅れがある画面では、待ってから値や件数を確かめるべきでした。
本文エディタの中身は、見えている範囲しか読めない
貼り付けた本文を get_text で読み返すと、返ってきたのは画面に表示されている範囲だけでした。長い文書を扱うエディタは、表示範囲だけを描画していることが多いためです(仮想スクロール)。そのため、UIA から全文を照合することはできませんでした。今回は、末尾へ移動して行番号を見ることで代わりにしています。
「下書き保存」の invoke が効かなかった
ボタンを UIA の Invoke で押すと、反応がありませんでした。click(ボタンの中心を実際にクリック)に替えると、保存されて下書き一覧に移りました。Web ページのボタンは、Invoke ではなくクリックで押した方が確実なようです。
API ではなく winuse を使う意味
Qiita には API があるので、投稿の自動化だけが目的なら API を使う方が確実です。それでも winuse で試した意味は、次の2点にあると考えています。
- API が無いサービスでも同じやり方が通用する:ログイン済みのブラウザを、人と同じ画面で操作できます。
-
「画面上で本当にそうなったか」を確かめられる:保存後の一覧を
assertで確認できます。API の戻り値だけでは、画面にどう表示されるかまではわかりません。
まとめ
- ログイン済みの Chrome を winuse で操作し、Qiita の下書き保存までを自動化できました。
- タイトルとタグは UIA の
set_textで入り、React の状態にも反映されました。 - 長い本文はクリップボード経由で貼り付けるのが確実でした。
- 画面を見て判断して失敗し、
assertで確かめることの大切さを改めて確認しました。
この記事も、同じ手順で下書き保存しています。