1.8.1のApp Storeのリリースノートは、仮想マウスについての4行です。その裏にあるビルドは 9日ぶんの作業で、iPhone・iPadアプリにとって今年最大の一歩でした。任意のAIレイヤーを備えた 音声入力、実データに基づいて作り直したキーボード、3つ目のターミナルプロトコルのクライアント、 Macの共有リンク、そして自分自身の将来のバージョンを生き延びるよう設計された同期形式。 こちらは長い方の版です。
耳を持ちました
スマートフォンでターミナルを使うとき、いちばんつらいのはシェルのコマンドを打つことです。 そこで1.8.1では、およそ1週間かけて段階的に音声入力を作りました。
最初の段階が、いちばん重要で、しかも無料の部分です。マイクを長押しして話すと、認識は端末上で 動きます。無料、オフライン、そしてスマートフォンから何も出ていきません。聞き取った内容は 編集できるテキストとして音声パネルに現れ、良さそうだと思えた時点で — その前ではなく — ターミナルへ挿入します。
2つ目の段階は、良さそうに見えないときのためのものです。録音はセグメントとして保持されるので、 文全体を言い直すのではなく、ひとつを切り取ってその部分だけ再認識できます。履歴には過去の 録音が残り、試聴やもう一度の認識に使えます。iPadでは、音声パネルは透明キーボードと同じように 浮かび、拡大縮小できます。大きな画面では、間違った場所に固定されたパネルはそれ自体が 問題になるからです。
そして望むなら、考えます
認識が返してくれるのは言葉です。コマンドには言葉以上のものが要ります — 正しい順序の フラグと、あってはいけないところに入らない空白です。1.8.1のAIレイヤーは完全に任意で、 認識とは完全に切り離されています。
自分のプロバイダを持ち込めます。OpenAI、Claude、Gemini、Kimi、GLMのAPI形式に対応しており、 チャットモデルと、そのプロバイダに文字起こしモデルがあればそれも設定します。Claudeはチャット 専用で音声APIを持たないため、録音は失敗する代わりにオンデバイスの認識へフォールバックします。 プロバイダのキーはこの端末のKeychainにあり、意図的に同期の対象から外してあります。
プロバイダをつなぐと、プロンプトモードが話した内容を整ったテキストや、そのまま実行できる コマンドに変えます。ターミナルの文脈を添付するオプションを使えば、モデルは答える前に 画面の実際の内容を見られます。チャットパネルもあるので、ふだんならブラウザのタブで 調べていた質問を、セッションの隣で聞けます。
APIキーを管理したくない方のために、サインインすれば公式のクラウドモデルを使えます。支払いは アプリ内課金で購入したポイントで行い、ポイントは端末間で共有されます。どちらを選んでも オンデバイスの認識は無料のままで、そちらが既定です。
本物の配列を持つキーボード
1.8までのフローティングキーボードは、ハードコードされたUS配列ひとつでした。1.8.1でこれを データ駆動にし、6種類を用意しました。アメリカ英語、イギリス英語、日本語 (JIS)、 フランス語 (AZERTY)、ドイツ語 (QWERTZ)、スペイン語です。使うパネルの選択と 合わせて、設定で切り替えられます。
データ駆動の配列には、ハードコードされたものには要らないテストが必要になります。配列が
誰かの入力した表になったからです。そこで文字の到達可能性テストを追加しました —
どの配列でも、あるはずの文字がキーの組み合わせで実際に到達できるか、というテストです。
これがすぐに本物のバグを2つ見つけました。AZERTYには
* がまったくなく、
JIS配列はfnを間違ったキーに紐づけていたためF列がずれていました。どちらも、英語で
テストしている人には見つけられなかったはずです。
キーの上には、ターミナルの文脈とよく使うコマンドに合わせて調整した単語サジェスタを 裏に持つ候補バーが付きました。マイクは上部バーへ移り、2つの動作を持ちます。タップすると 音声パネルに切り替わり、長押しするとそのまま話しかけて候補バーへ入力できます。この長押しの 動作は見た目より厄介でした — SwiftUIのいかにも使えそうな長押しAPIは、指が離れた ことを教えてくれません。その話は 長押し録音ボタンについての記事に別途書きました。
3つ目の入口:Eternal Terminal
Moshはトンネルを抜けてもセッションを保ってくれる仕組みで、UDPの上で動きます。企業やホテルの
ネットワークにはTCPしか通さないものが少なくなく、そうした場所にいる人には素のSSHと、
セッションの持続がまったくない状態だけが残ります。
Eternal Terminal
は同じ問題をTCPで解いており、すでに
etserver を動かしている人も
大勢います。私たちは
その前の週にこのクライアントについて書きました。
1.8.1は、それが実際に載ったビルドです。
実験的なトランスポートにふさわしいやり方で届きました。まず、他の何もそれに依存できない 独立したRustのクレートとして。次にフラグの裏で、FFI経由でSwiftのアプリへ接続。そして動くと 分かってから、本物のホストエディタのUI、設定のトグル、原因をそのまま名指しするエラー メッセージ、そして翻訳を追加しました。そのあと失敗経路について2度のレビューが入りました。 ネットワークのクライアントが静かに間違っている可能性がいちばん高いのが、そこだからです。
既定ではオフのままです。設定でETトランスポートをオンにすると、SSHとMoshの隣に3つ目の 接続方式として現れます。ひとつ考慮しておきたい点があります。MoshのUDPと同じく、ETの データ接続は端末からetserverのポートへ直接向かい、踏み台ホスト経由では転送されません。
自分自身の将来を生き延びる設定
この時期、Macのエージェント側にも独自のホスト一覧とターミナルが育ちました。つまり スマートフォンとMacが、ホストとは何かについて合意する必要が生じたということです。 1.8.1では、両方が使う正式なホストとスクリプトのスキーマを収めた共有パッケージと、 設定同期のクライアント、そしてそれを動かすコーディネータを導入しました。
独立して更新される2つのアプリでスキーマを共有すると、特有の危険が生まれます。そして私たちは それを踏みました。古いクライアントが、見たこともない値をデコードし、そのままレコード全体を 書き戻して壊してしまうのです。その修正 — 生の値を保つ列挙型、未知のフィールドを 入れておく袋、そして約束を固定するテスト — については 前方互換な Codable に書きました。このビルドでは、そのパターンをまずホストに適用し、続いて残りのすべての 同期対象モデルへ広げました。保存済みデスクトップの項目ごとの未知フィールドも含みます。
何が同期され、何が同期されないかは、変わらず明示的なままです。ホスト、スクリプト、 ドライブのマッピング、テンプレート、設定は、あなたのアカウントのもとでサーバーに同期されます。 パスワード、SSHの秘密鍵、そのパスフレーズは端末から出ません — iOSのKeychainの中に あり、任意でiCloud Keychainを通じてエンドツーエンドに渡るだけで、サーバー側に漏れる ものはありません。
Macを誰かと共有する
1.8.1では共有リンクのビューア側が入りました。自分に共有の一覧、ペアリング文字列ではなく 共有を経由して接続するためのトランスポート対応、そして所有者の承認を挟むセッションの 取り扱いです。エラーが具体的なのは意図的です — 期限切れのリンク、取り消されたリンク、 同時接続枠がすべて埋まっている、許可リストに載っていないアカウント、予約した時間帯の外での 接続。そのどれが起きたのかをそれぞれ伝えます。対処が理由によって変わるとき、 「接続できませんでした」では何の役にも立たないからです。
こちらも同時に。リモートデスクトップを切断してもタブは残るようになりました。SSHの接続が ずっとそうだったのと同じで、一から設定し直す代わりに、オーバーレイから再接続できます。
仮想マウスに居場所ができました
App Storeのリリースノートが書いているのはこの部分です。マウスのボタンは分割して好きな場所に 置けました。柔軟ではありましたが、裏を返せば、手のある場所にぴったり収まることは一度も なかったということです。今はドッキングします。画面下部に沿った1枚のパネルになり、端末を 持っている側へ左右にスライドし、画面キーボードが開いているときはその上へ持ち上がります。
ドッキングは、ルーペのいちばん悪い癖も直しました。自由に浮かんでいたころは画面の端を 避ける必要があり、そのせいで思わぬときに動き、拡大された映像がカーソルと合いませんでした。 ドッキングすれば、カーソルの真上に出てそこにとどまります。関連する修正が2つ。画面の端から 指を滑らせて外してもカーソルが飛ばず、ボタンが押されたままになることもなくなりました — キャンセルされたタッチを、キャンセルされたタッチとして扱うようにしたからです。 そして⌘、⌥、⌃がときどき押されたままになり、次の打鍵が思いがけないショートカットに 変わることもなくなりました。
別のアプリからでも聞こえるベル
ターミナルがベルを鳴らしたとき、そのセッションが今見ているものでなければ、iOSが通知を
出すようになりました。時間のかかるビルドの末尾に
printf '\a' を足しておけば、
終わったときにスマートフォンが教えてくれます。今まさに見ているセッションのベルは
鳴りません。要はそこが肝心なところです。
触れておきたい細かな手入れ
- キーボードの作業の締めくくりに、ローカライズの全面監査。639個のキーを確認し、重複はゼロになりました。
- レビューから出た正しさの修正が2件。デコーダの状態の競合と、ホストが消えたときに孤立しうるKeychainのパスワードです。
- 1.8から続くOpusの音声経路がここで完成しました — 任意のPCMから20 msのフレームを作るバッファ付きエンコーダ、ビューアでの再生、そしてオーディオバッファリストからインターリーブされたPCMを読み出す部分の修正です。
- テストターゲットをアプリ本体に合わせてiOS 17.0まで下げました。アプリが動くところなら、どこでもテストが走ります。
そのすべてが無料です。オンデバイスの音声認識も含めて。
他の言語で読む: English · 中文 · 日本語 · Español · Français · 한국어 · Українська
アプリそのものについてはSharkTTY ガイド、利用者向けの短い更新情報は新着情報をご覧ください。ご連絡はフィードバックボードがいちばん早い方法です。開発ブログへ戻る。