2025

AIでiOSアプリを作ってリリースする

(2025.4.26追記)

「Vibe Coding」では、コードを人間が読んではいけないそうです。あくまでAIが作った成果を楽しむもので、どう実装したか確認したらそれはただの「コーディングアシスト」だから、だそうで。ということは自分はVibe Coding界隈とは相入れないんだな、というのを確信しました。ごめんなさい。

きっかけ

今年の2月にGitHub Copilotにエージェントモードが追加された。 コードを直接書くのではなくAIに望んでいるもの(機能、画面レイアウトなど)を伝えてプログラムを書いてもらうことを「Vibe Coding」というらしい。そして、このバイブコーディングを嗜んでいる人々の中には「1行たりともコードを書かない」という縛りプレイを楽しんでいる人もいるらしい。なにそれ楽しい。

知らないエディタで知らない言語を使う

バイブコーディング環境の流行とはだいぶ違うが、すでに課金済みという理由からGitHub Copilot エージェントをバイブコーディングのお供に選んだ。 このGitHub Copilot エージェントを導入するには、開発環境(IDE)として Visual Studio Code を選択するしかない。自分は普段はJetBrains社製のIDEを使っているため、VS Codeの使い方で若干手間取ってしまう。いまどきのプログラム初学者はVS Code一択だろうから、これは老兵ならではの悩みといえる。とはいえ、設定は拡張機能としてGitHub Copilotを追加するくらいだ。アカウントを紐づけて、VS Codeの設定画面からエージェント機能をONにすればもうバイブコーディングの準備は完了だ。 そもそもバイブコーディングではコードを書く行為はメインではない。なのでエディタとしての使い勝手を上げるチューニングは、あまり頑張らなくて良い。自分の場合は普段使っているIDEとは別の環境になっているので、むしろもっと「バイブコーディング専用IDE」にチューニングしても良さそうだ。

Visual Studio Codeに拡張機能 GitHub Copilotを入れた様子

コードエディタとして考えると邪魔なくらいチャット画面を広げている。実際の作業が始まるとソースコードもちゃんと追いかける必要はある(後述)のだが、バイブコーディングではチャット画面を起点にして作業をすることになるので、まずはチャット画面の使い勝手を追求したほうが良い。なんならば、ど真ん中にチャット、右にエディタという構成にしたいくらいだ。チャットの入力フィールドももっと大きく打ちやすくできると嬉しいのだが、そういうチューニングはまだ追求できていない。

今回は、 Flutter というマルチプラットフォーム対応のフレームワークを使ってユーティリティーアプリを開発することにした。プログラム言語はDart。FlutterもDartもほぼ未経験だが、GitHub Copilotに「Flutter知ってる?」と質問したら「知ってる」と返してきたので採用した。まるで炎上案件の火種なのだが、ここからでもなんとかなっちゃうんだな、AIなら。 とりあえず、空っぽのディレクトリを開いて、エージェントに「Flutterでアプリを作りたいからセットアップして」とお願いしてみた。なお、ここから先も含めて、実際にどういうリクエストをエージェントに送ったのかは残念ながら忘れてしまったのでニュアンスで読んでほしい。Flutterフレームワークをマシンに設定するところは(アクセス権限の兼ね合いもあるので)流石にエージェントが自動で……とはいかなかったが、手順はエージェントが教えてくれたのでそれに従いFlutterのプロジェクトをセットアップした。きちんとFlutterプロジェクトのセットアップが完了してしまえば、その後のパッケージの追加やビルドなどはエージェントがコマンドをターミナルに入力・実行してくれるようになる。

気を取り直して、エージェントに「タイマーアプリを作って」とお願いしてみた。すると、なんということでしょう、タイマーとスタートボタン、停止ボタンが出来上がって、実際に動くではありませんか。ソースコードを確認してみる。うーん、よく分からないがそれっぽい。シンプルなアプリをお願いしたのでうまくできるだろうとは思っていたが、ぱっと見では強引そうなところも読みづらいところもない。関数名、変数名もしっかりしている。これからのプログラムの勉強は、AIがまずお手本の「Hello World」を生成してくれて、それを学習していくスタイルになるかもしれない。

結局コードは読むし、書くことがある

さて、ここから作りたい機能をひとつづつ、エージェントに指示を出して増やしてもらうことになるのだが、この「ひとつづつ増やしていく」というところはバイブコーディングのポイントかな、と感じた。 人間が行う作業でもそうなのだが、エージェントに曖昧で大味な指示を出すと齟齬が生まれやすく、余計なことまで実装してしまう傾向があるようだ。上記の「画面にタイマーを表示するアプリを作って」の指示からは、タイマーアプリを作るというからにはスタートボタンと停止ボタンは必要だろう、というところまでエージェントは推測してくれた。これは良い方向にお節介が働いた例だが、こういう事例で「AIは賢い」といってしまうのはあまり良くないことだと感じた。曖昧な指示から勘違いな機能が実装されてしまうと、削除したり修正しなくてはならなくなる。指示と違う部分を指摘して、こういうふうに直してくれとエージェントにお願いすることになるが、これは単純に時間とコストのロスだ。 また、エージェントは自分が提案したコードを覚えているので、エージェントではなく人間がそれを修正してしまうと、次にエージェントがコードを修正するときに「齟齬」が生まれてしまうようだ。いずれ技術が進むともう少し協業できるようになるかもしれないが、原則としてバイブコーディングでは人間はコードを「書いてはいけない」のだろう。

そんな経験から、新機能を一部分でも実装できたらいったんGitにpushするなどしてコードを保全するようにするようにした。そして、エージェントが更新したコードとのdiffを毎回確認し、違和感があればコードをロールバックして、エージェントとのセッションは新しく立て直す。そして改めてエージェントには齟齬の余地を減らすような工夫を加えた新しい指示を送ってみる、トライアンドエラーの手順を確立していった。

品質という点でみると、エージェントが提案してくるコードの中には配布元が「近い将来、非推奨になるよ」としている関数を使ったものが含まれることがある。AIが学習したコードの中では古い書き方の評価が高いのだろう、そういうときは配布元URLを引用して指摘してもなかなかうまく修正をしてくれない。これはたまたま気づけたから指摘できた事例だったが、「エージェントが提案してきたコードを自分でも調べてみる」というのはなかなかにコスト高だし難しい作業だ。 エージェントが書いたコードが必ず一発で動くとも限らない。そういうときはエージェントにエラーメッセージを伝えて修正を依頼するのだが、修正を依頼しても直せずにループに陥ってしまい最後はコード修正を諦めてしまう、という場面もあった。その場面では、そもそもエージェントが考えた修正のアプローチがまずかったらしく、最後は諦めて自分でコードを直してしまった。

エージェントにもできないことはあり、そのときは当然だが自分でコードを書くしかない。つまり現状のバイブコーディングというのは、AIの力量を把握して、いざとなれば自分でコードを読み書きする前提で、その上であえてなるべくエージェントに書いてもらう、という塩梅のコーディング手法なんだろうな、と思った。

AIのことを「時給500円の疲れ知らずのバイト君」と表現したブログを拝見したことがあるが、まさしくそんな感じだ。指示を的確に出し続ければ、その分だけずっと同じクオリティで仕事をし続けてくれる。だが、その疲れ知らずなバイト君にずっと付き合って指示を的確に出し続けなければならないのは店長である人間なのだ。そして出来上がったものを確認するのも人間。そりゃそうだよね。

iOS / macOSアプリを出したんだ

そんなこんなで作られたのが「Chain Timer」というアプリ。Flutterなのでマルチプラットフォームで動作するのが非常に便利。4月24日にiOS版とmacOS版を無事公開することができた。

アイコンはChatGPTに作ってもらった。UIデザインについては、そもそもFlutter自身がMaterial Designに忠実なので適当にパーツを並べただけでも破綻しづらく、カラーテーマもFigmaの Material Theme Builder を使ってダークテーマも含めてすぐに導入できた。 こんな単機能なアプリで日本語専用にするのは勿体無いので、このアプリは日本語と英語に対応している。翻訳の一部は、i18nパッケージ(slang)を導入していることをエージェントが認識していて、都度いい感じに翻訳ファイルを更新してくれた。

タイマーを連続で起動させるというアイディアは、数年前にMakerFaireTokyoに出展したハードウェアが元ネタで、アナログ写真の現像のときに濡れた手でいくつもタイマーを切り替えないといけないのが不便だったので思いついたものだ。 個人的には、シンプルながらそれなりに便利なアプリになったと思う。タイマーリストをQRコード化する機能は、デバッグ時に非常に重宝した。このQRコードの中にはタイマーリストの構造をJSON→gzip圧縮→BASE64エンコードした文字列を格納しているが、QRコードに含められる文字長に限界があるのであまり大きなデータ構造にすることができなかった。

本当はAndroid版とWindows版もあるのだが、Android版をGoogle Playに登録するには12人のテスターが必要なので保留中。Windows版は、そもそも開発者アカウントの登録に手間取って謎の足踏み中だが、出せるもんなら出してみたい。減るもんじゃないし。


Obsidianで日記サイトを構築して、ついでにAIと戯れる

この日記はHugoで生成している。Hugoの書式はMarkdownなので、テキストエディタでも書くことはできるがリッチエディタっぽいツールを使うとさらに便利になる。そこでObsidianだ。Obsidianはオープンソースのメモアプリで、拡張性が魅力だが、まずは基本機能の「デイリーノート」をそのまんまHugoのフォーマットに合わせて使うこととする。 Obsidianは「保管庫」と呼ばれるフォルダを指定してその中にある .md ファイルのひとつひとつをメモとして扱う。フォルダやファイルの構成をHugoのcontentディレクトリのままにできるので、そのまま読み書きできる。 例えば以下のようなテンプレートをデイリーノートのテンプレートとして指定すると、いきなりHugoのドラフトページを書き始められる。

---
title: titleを入れる
date: {{date:YYYY-MM-DD}}T{{time:HH:mm:ss}}+09:00
url: {{date:YYYY/MM/DD/}}
tags:
  - PC
draft: true
---
本文を入れる

書き終わったらGitにあげる

拡張機能「git」を導入する。これで、書いた日記をGitHubにpushできるはずだ。 Obsidianは保管庫に指定したフォルダに隠しフォルダを作って諸々の設定を保存している。なので、.gitignore でそのディレクトリを除外しておくことにする。

.obsidian

Git Source Panelを表示すると、この日記ファイルがまだstageされていないことがわかる。ここから諸々の操作が可能なようだ。デフォルトのコミットメッセージは vault backup: {{date}} となっている。ここにも変数使えるのね。

さらにAIを導入してみる

いまナウで最先端なAIというやつを入れてみる。 近頃はコードを書くときにはGitHub Copilotをメインで使っているが、日記はコードじゃないので使わない。ちょっとしたコードを書いたり雑多な質問にはChat GPTを使っているがこれはWebベースで使っているし自分は課金していないのでAPIとして組み込むには向かない。ここでは拡張機能「copilot」を使ってGoogle Gemini APIの無料枠を導入してみることにする。 AIには日記の誤字・脱字を直してもらったり、読みやすいように校正してもらいたい。だが、日記のような砕けた文章を校正してくれるだろうか。「自分っぽい書き方」をしているところとの相性が気になる。

よーし、校正をお願いしてみるか。chatウインドウから

この記事の校正をお願いします。誤字や脱字、読みづらいところなどがあれば指摘してください

……、お願いします。

校正をご希望の記事が提供されていません。

……、はい。開いているページを「{activeNote}」と書いて指定しないといかんのね。

{activeNote}の校正をお願いします。誤字や脱字、読みづらいところなどがあれば指摘してください

……、おお。割と平たい文章になるように言い回しを提案してくれるじゃないか。ただ、なんというか、いわゆる「いかがでしたかブログ」っぽい文章にどんどん直されていく印象もあり。この校正そのまんまは受け入れ難いなぁ。

- 「いまナウで最先端なAIというやつを入れてみる。」→ 「最新のAIを導入してみます。」

これとか受け入れ難い。ナウで最先端なほうが良くないですか?ダメですか?そうですか。

というわけで、今日の日記はここまで書いたObsidianの使い方を実験するための日記でした。最後に今日の日記を要約してください、AIさん。

この日記は、Hugoで生成している日記サイトの作成に、Obsidianというメモアプリを活用する試みについて書かれています。Obsidianのデイリーノート機能をHugoのフォーマットに合わせて使用し、日記を書き終わった後はObsidianの拡張機能「git」を使ってGitHubにpushする方法を試しています。さらに、Google Gemini APIを導入してAIによる校正を試していますが、AIによる校正は文章を平坦にし、「いかがでしたかブログ」のような印象を与えるため、全面的には受け入れられないと感じています。全体として、Obsidianの様々な機能を活用して日記サイトを構築する実験的な内容となっています。

あ、あなたの文体を否定的に書いた部分をそのまま要約に採用しましたね……。最後にちくりと人間側を腐しておきたいと……。


2024

「文章のどこかに『生成AI』を入れてください」

すごいなぁ、とは思うんですよ。生成AI。文章にしても、絵にしても、音楽にしても。

自分だってAIをまったく使っていないわけではない。いろんなプログラミング支援AIを試してみて、今はGitHub Copilotに落ち着きそうだ。

プログラミング支援AIは、そのサジェストの出し方、手の差し伸べ方が非常に上手い。冗長な内容の入力途中で残りを補完してくれる、というものならこれまでもあった。最近は、変数名の付け方がちゃんとしているとその単語の意味まで理解して補完してくれる。

この間ですね、emailvalidationという名前の関数を使ったif文を書いていたら、変数messageを作ろうとしたらそこに"メールアドレスが違います"を代入してきたんですよ。へえ、AI君やるじゃない、と思うでしょ。それで、そのmessageを仮想配列に変えて"ja"というキーをつけたら、今度はAIがその次の行に"en"をキーにして"email address is incorrect."って書いてきたんですよ、これにはまぁ驚いたねぇ、頼もしいわぁAI先輩かっこいいっす。

こういうの、本当に自分たちが望んでいた未来のコンピューターな感じがして嬉しい。執事ってこういうものだよね。言わなくても察する、先回りして準備しておく、押し付けがましくない。我々はこういうものを求めていたんだ。

でもね。

「対話型の生成AIに、こういう文章で質問を投げるとこんな答えが返ってくるんですよ、すごいでしょ」

と言われたら、それは本当に「未来」なのか、納得できかねる。

「こういう文章で質問を投げる」ノウハウ自体で一喜一憂している様が「未来」じゃない。コミュニケーションが苦手な性格の人間にはAIとの対話にもハードルがある。人間の側が自分の考えていることをうまくアウトプットできないとなれば、今はまだAIのほうでもそれをうまく汲み取れない。そこは人間と変わらない。むしろAIはカメラや音声でこちらをのぞいているわけではないので文章という限られたインプットから察するしかない。「こういう文章で質問を投げる」ノウハウとは対AIコミュニケーション能力とも言い換えることができて、現段階でそれをうまくできる人はそもそも自分の考えをうまく文章化してアウトプットできる人で、おそらく実生活においても他者と円滑にコミュニケーションできるんじゃないだろうか。

前述のプログラミング支援AIが自分にとって心地よいのは、プログラムの世界ではコンピューターに対して正しいプログラムを書いてあげる能力がそもそも必要で、それはコンピューターに対してのコミュニケーション能力と言い換えることもできる。AIも同じプログラムを読むことから、プログラムを介して間接的にAIに対してのコミュニケーションが成り立つ。AIに対して直接話しているわけじゃないが同じ方向を向いて同じ言葉(プログラム)で対話が成立するから心地よいのだ。

AIを使うノウハウなんてものは一過性のブームだ。本当にAIが賢くなる未来においては、必要なのは人として極めて一般的なコミュニケーション能力であって特殊なノウハウではないはずだ。その未来はすぐ来るだろうから一喜一憂することじゃない。AIを使う、というのはすなわちコンピューターと共に生きていくライフスタイルそのもののことだと思う。それは、人間の生活を助けるように寄り添ってくれるものであって、人間がご機嫌をとりにいくようなものではない。

AIが寄り添ってくれる未来とはコンピューターの活躍する未来として、20世紀の頃からずっと我々が想像してきた未来のまんまであるはずだ。


2023

おひとりさまインスタンスでなんとかしたい

おい、2022年は一日も日記書いていないぞ。

Twitterで時折ツイートしているから生存確認できているだろうと油断していた。インターネット、とりわけSNSは不思議なもので、自宅に引きこもっているだけの零細フリーランスなのに社会に繋がっているような錯覚を与える。他人の書き込みを眺めていいねボタンを押すだけで、なにか社会の裾のところにしがみついているような感覚。ところが、昨年後半からそのTwitterの運営が迷走しだした。

考えてみれば、落書きのようなメモ書きとはいえ、一応は自分の著作物である。SNSというプラットフォームは商品を並べたり配送を依頼する場所であって、工場を貸してもらっているわけではない。ちゃんと自分のドメインで製造して管理して、並べたり配送したりするところから他者にお願いするのが「筋」なのではないか。

そこでMastodonなどでお馴染みの、ActivityPubに対応したインスタンス(サーバー)を立ち上げることにした。自分の発言を自分のドメインに置くための、いわゆる「おひとりさまインスタンス」である。

Google Cloud Platform (GCP) の無料枠でe2-microというスペックのVMインスタンス(簡単にいうとレンタルサーバー)を一つもらえる。これでPleromaという実装(ActivityPubに対応したソフトウェア)を使ってインスタンスを立ち上げた(https://social.a3size.com/@king_nomura)。これからはこちらを「自分が発言するときの」メインのSNSに出来ないかな、と考えている。PleromaはMastodonよりも軽量らしく、またビューワーとしてこのインスタンスを利用しているのは自分ひとりしかいないので、それほどの負荷にはならなそうだ。また、将来もしも別の実装に取り替えたくなっても、まあデータのインポートエクスポートでなんとかなるんじゃないかなぁ、と楽観的に考えている。

将来的にThreadsもActivityPubに対応することが発表されているので、そうなればThreads上のユーザーをフォローしやすくなるし、自分のアドレス( @king_nomura@social.a3size.com )も伝えやすくなるだろう。相手がどこのサービスのインスタンスに所属しているかをいちいち気にしないで良い、というのがスマートで美しい。自分のアドレスが自分のドメインなのも、「ちゃんとしている」感じが嬉しい。

なので、SNSならなんでもいいという人はとりあえずThreadsにしたらいいんじゃないかな、などと考えている2023年なのでありました。


2021

2006年に買ったマウスを静音マウスにする

普段、Macではトラックパッド(Magic Trackpad 2)を、主にゲーム(とかブラウザ確認とか)に使っているWindowsマシンではマウスを使っている。このWindowsのマウスは、LogitechのMX Revolutionで、2006年に買ったものだ1。しばらくWindows機を立ち上げていなかったのでブランクはありつつも、もう15年も使ってきたマウスだ。

Magic Trackpad 2のクリック音は「コツッ」という少しくぐもった音色で(わざとそういう音を鳴らしているところが凄い)、MX Revolutionのクリック音は「カチッ」といういかにもなマイクロスイッチの音色だ。この、「カチッ」という音は、いろんな音がなっている中でなら気にならないが、比較的高い音でキンキン鳴るように聞こえて、ちょっと「カチカチカチカチ」と連打するとあまり気分が良い音とは思えなくなってきた。そこで、思い切ってスイッチを換装することにした。 こちらがスイッチ換装作業の様子。元々ついていたスイッチを外して、新しいスイッチをつけたところだ。

MX Revolutionのスイッチを換装した

静音マウス改造は実に様々な方がチャレンジされていて、その多くの方が静音スイッチの部品として「Kailh ミュートマイクロスイッチ」などの名前で検索すると出てくる6mm × 6mm × 7.3mmのマイクロスイッチを使用している。なるほど、これをMX Revolutionに乗せてしまえばいいのだな?とやや乱暴に思いついて、それを実行した。写真を見て貰えばわかるが、左下側に転がっているのがもともとついていた3本足の長方形スイッチで、付け替えた静音タイプのスイッチは正方形。うっかりするとクリックする部分がうまく噛み合わなくて押せなくなってしまうのだが、あまり深く考えずに実行してしまった。

ちなみに、このKailhのマイクロスイッチ、Amazonなどでも買えるのだがmercariで出品されているものを購入すると1個あたり100円未満で買えるというので、初めてmercariを使った。次に使うのは何年後になるだろうか。

実際の換装作業だが、知識のある方なら写真から想像つくと思うが、元々あったスイッチを取るためにハンダを吸い取るのに大変手間取ってしまった。吸い取り器じゃなくて吸い取り線で頑張ったんだぜ、これ。その結果、基盤パターンがもげてしまったので仕方なくリード線で配線を繋ぎ直した(マウス左ボタンの付近の黄色いリード線がそれ)。この場所以外にも、写真には写っていないが「マウスを持ったとき手前にくる側」にも基盤と部品がハンダ付けされている部分があり、そもそも先にそこを外さないとこのスイッチ換装の作業自体ができない構造になっているが、これもなかなか取れなかった。体感では、全体の作業の合わせておよそ2/3くらいをハンダを取るのに費やした気がする。

スイッチ換装のついでに、バッテリーも交換した。写真からわかるだろうか、すでにこのバッテリー、真ん中が大きく膨らんでしまっていたのだ。15年前のマウスなので純正パーツはもう手に入らないだろう、ということで互換バッテリー台湾から送ってもらい、つい先ほど載せ替えた。

作業終了後、まだ長時間使ってみてはいないが、今のところ順調に動いている模様。クリック音は「トン」というか「ト」というくらいの本当に静かな音に変わってくれたので、このまましばらく使ってみて動作に支障が出ないようならば、この換装は成功だったといえるだろう。