ちなみに

火曜日の空は僕を押しつぶした。

AIに否定的な人ほどAIを万能だと思っている

AIに否定的な人と話していると、むしろその人たちの方がAIを万能だと思っているような気がする。

万能幻想と失望

万能だと思っているから、一度試して思い通りにならないと「やっぱ使えない」で終わってしまう。でもそれは、とても優秀な新メンバーに何の説明もなく「よろしく」って言ってるようなもので、うまくいかなくて当然だと思う。

AIは(今のところ)経験を蓄積できないので、あなたの常識を知らない。プロジェクトの経緯も、コードベースの癖も、チームの暗黙のルールも。知らなくて当然なのだけれど、万能だと思っていると「なんでこんなことも知らないの」になってしまう。

対話でコンテキストを伝える

1プロンプトで全部できるというのは幻想で、何度かやり取りしてコンテキストが伝わってから、計画を立てて、それから実行する。人間相手でも同じことをしているはず。

lintや設定ファイルで暗黙知を仕組み化して、ハーネスとして築いていくと、この対話がどんどん楽になる。一度作った仕組みは次の会話でもそのまま使えるので、使えば使うほど伝達コストが下がっていく。

まあ、進歩が速すぎて、来週にはこういう苦労もなくなるかもしれないのが恐ろしいところなのだけれど。

自分でやった方が早い?

「そんな手間かけるなら自分でやった方が早い」という人がいるのだけれど、それは自分を過大評価しすぎている気がする。AIの方がすでにほとんどの領域で優秀だし、その優秀さを並列で利用できる。自分一人では同時に一つのことしかできないけれど、AIなら複数の作業を同時に走らせられる。

コンテキストを伝える手間を差し引いても、十分すぎるほどお釣りがくる。

コードがタダ同然になった時代の開発原則 - Zen of AI Coding

Zen of AI Coding という記事を読んだ。コーディングエージェントを1年使い込んだ人が、AI時代の開発原則を16個にまとめたもの。Zen of Pythonのオマージュだ。

出発点はシンプルで、「コードを書くコストがほぼゼロになった。そこから全部変わる」という話。この前提から何が変わるかを一つずつ整理していて、構造がとてもいい。

コストが下がると何が変わるか

まずリファクタリングのハードルが下がる。「Reactを選んだけど2ヶ月で後悔した。エージェントに書き直させればいい」。一度決めたら戻れなかった技術選定が、仮置きになる。実際に著者は3ヶ月でCMSを4回スクラッチで作り直したらしい。間違った判断がそこまで痛くなくなると、とりあえず動くものを作って試すのが正解になる。綺麗な設計書よりも動くコードのほうがエージェントにとってはいいコンテキストになる、というのも面白い。

技術的負債も返しやすくなる。依存の更新、APIのマイグレーション、古いパターンの書き換え。どれもエージェントに投げれば終わる類の作業だ。負債がなくなるわけではないけど、返済コストが下がると「あとでやる」の言い訳が通らなくなる。

そしてボトルネックが移動する。実装がボトルネックでなくなると、10個を並行で作れてしまう。でも10個を並行でレビューして、判断して、リリースすることはできない。詰まるのはプロダクトの意思決定、要件定義、セキュリティレビュー、リリースフローのほうになる。ボトルネックはコードではなく人間の頭になった。

全部「コードが安くなった」という一点から導かれていて、説得力がある。

それでも速く作ればいいわけではない

「速く作ったゴミはゴミだ」。速さは気持ちいい。でもベロシティやコード行数で進捗を測るのは昔から悪手だった。何でもすぐ作れるようになった今だからこそ、何を作るかの判断に規律がいる。

「壊れ方を先に考えろ」。エンジニアの仕事はコードを書くことではなく、システムが壊れないことを保証することだ、と。実際に著者のエージェントは.envファイルをgitにコミットしようとしたらしい。こういうリアルな事故の話があるから信用できる。

ソフトウェアは作った瞬間から保守コストが発生する。プロダクトとして使われて初めて資産になる。作るのが簡単になった今、機能を足したくなる誘惑はどんどん強くなる。でも使われない機能を作っても負債が増えるだけだ。

他にも16個の原則すべてが読み応えあるので、ぜひ元記事を読んでほしい。

nonstructured.com

最新の音声入力の方法

Vibe Coding中の筆者

このツイートを見て天才だと思ったので僕も買いました。受話器型マイク。

音声入力を何度か試しているのだけれど、どうしても定着しない。 音声入力だと考えると最初に文字列を思い浮かべてそれを声にするみたいなプロセスになってしまっていて、すごく違和感がある。 電話やミーティングなら気軽に話せるので、電話型だったらいいのではと思ったら大当たり。音楽も聴けます。

見た目も可愛いし、ウルフ・オブ・ウォールストリートのディカプリオになった気分になれるのでおすすめです。

ライトセーバーは自分で作る(2026年)

ジェダイはライトセーバーを自分で作る。フォースの力を借りて。

ソフトウェアエンジニアが自分のためのツールを作るのは昔から当たり前のことだ。ただ最近、AIの力を借りてそのコストがめちゃくちゃ下がった。

最近Rustで自分専用のCLIツールをいくつか作った。ブログを書くための bsfs、PRレビュー用のTUIクライアント rui(まだ未公開)など。

bsは blogsync 互換のCLIで、fsははてなフォトライフに画像をアップするやつ。この辺りはOpus 4.6がでたことでどのくらい出来るのかを試すために作り始めた。

ruiはターミナルでPRのdiffを読むやつ。ローカルのdiffも表示できる。diffを好みになるように調整しまくったのでブラウザより快適になった。

rui用に ma(MermaidのASCII描画)、waku(git worktree管理)、shiwake(diffスコアラー)も作った。自分専用ツールのために自分専用ツールを作る入れ子になっている。

他にも日々なにかしら作っていて、この積み重ねでQoLがどんどん上がっていく。自分専用ツールのいいところは自分以外のことを考えなくていいこと。 README、CI、issue対応、そういうのは全部要らない。動けばいい、壊れたら直せばいい。

ただOSSへの敬意という点では考えてしまうことがある。blogsyncがなければbsの設計は一瞬で決まらなかったし、ratatui がなければruiは存在しない。 なかなか難しい問題だと思っている。

去年も cctopgotestshowccl とGoでいくつか作っていたのだけれど、思った通りには仕上がらなかった。ここ最近のLLMの進化がすごい。

開発環境の設定もAIに任せられるので、ツールを作れば作るほど環境ごと便利になっていく。まだまだ作りたいものがある。

Agent Safehouseを使い出した

Claude Codeに--permission-mode=autoが追加されてだいぶ安心感は増したけど、結局LLMが判断しているので完璧ではない。Agent SafehouseはmacOSのsandbox-execを使って、カーネルレベルでエージェントのファイルアクセスを制限してくれるやつ。LLMの判断に関係なく、OSが強制的にブロックしてくれる。

brew install eugene1g/safehouse/agent-safehouse
safehouse -- claude --dangerously-skip-permissions

sandbox-execはmacOSに元々あるサンドボックスの仕組みで、カーネルがシステムコールの段階でアクセスを拒否する。manページにはDEPRECATEDと書いてあるけど、CLI向けの代替がないので現役で動いている(App Sandboxはアプリ向け)。

safehouseはこのsandbox-execにdeny-firstのポリシーを食わせるやつで、作業ディレクトリ以外はすべてブロックされる(~/.ssh~/.awsにはもちろん触れない)。万能なセキュリティ境界ではなく防御層の一つだけど、--dangerously-skip-permissionsを安心して使えるようになるのが大きい。内部ではSandbox Profile Language(SBPL)でポリシーを組み立てていて、safehouse --stdoutで生成されたプロファイルを確認できる。実装の99.8%がシェルスクリプトなので読みやすい。

面白いのが公式サイトにLLM向けのプロンプトテンプレートが置いてあって、エージェントに自分の環境を検出させてカスタムプロファイルを生成させることができる。サンドボックスの設定をサンドボックスされる側に作らせるという発想がちょっと面白い。

僕は毎回使うオプションをまとめたsafeというラッパーを書いて使っている。

#!/usr/bin/env bash
set -euo pipefail

args=(
  --env-pass=CLAUDE_CONFIG_DIR,DD_SITE,EDITOR,GOPATH,GOBIN
  --add-dirs-ro="$HOME/.config"
  --add-dirs-ro="$HOME/.codex"
  --add-dirs-ro="$HOME/.gnupg"
  --add-dirs-ro="$HOME/blog"
  --add-dirs-ro="$HOME/local"
  --add-dirs="$HOME/.cache"
  --add-dirs=/private/tmp
  --enable=clipboard,cleanshot,1password
)

# Grant write access to worktree-related directories:
# - {git-root}-worktrees/  (where git-waku creates worktrees)
# - main repo .git/        (worktrees store index/refs inside the main .git)
git_root="$(git rev-parse --show-toplevel 2>/dev/null || true)"
if [[ -n "$git_root" ]]; then
  worktrees_dir="${git_root}-worktrees"
  [[ -d "$worktrees_dir" ]] && args+=(--add-dirs="$worktrees_dir")

  git_common_dir="$(git rev-parse --git-common-dir 2>/dev/null || true)"
  if [[ -n "$git_common_dir" && "$git_common_dir" != ".git" ]]; then
    # Inside a worktree — grant write to the main repo so git can write index.lock etc.
    main_repo="$(dirname "$git_common_dir")"
    args+=(--add-dirs="$main_repo")
  fi
fi

profile="${SAFEHOUSE_APPEND_PROFILE:-}"
[ -n "$profile" ] && [ -f "$profile" ] && args+=(--append-profile="$profile")

# Extract safehouse options (before --) from user args
safehouse_opts=()
cmd_args=()
saw_separator=0
for arg in "$@"; do
  if [[ $saw_separator -eq 1 ]]; then
    cmd_args+=("$arg")
  elif [[ "$arg" == "--" ]]; then
    saw_separator=1
  elif [[ "$arg" == --explain || "$arg" == --stdout || "$arg" == --enable=* || "$arg" == --workdir=* ]]; then
    safehouse_opts+=("$arg")
  else
    cmd_args+=("$arg")
  fi
done

exec safehouse "${args[@]}" ${safehouse_opts[@]+"${safehouse_opts[@]}"} -- "${cmd_args[@]}"

.configは読み取り専用、.cacheは書き込み可、みたいにディレクトリごとに権限を設定できる。--enableでclipboardや1passwordも必要な分だけ許可した。

git worktreeを使う場合はちょっと工夫がいる。worktree内でsafehouseを起動するとworkdirはworktreeのパスになる。けどgitがindex.lock等を書き込む先はメインリポの.git/の中なのでスコープ外になる。git rev-parse --git-common-dirでメインリポを特定して書き込み許可を追加している。

僕はworktree管理にgit-wakuを使っている。git configのwaku.command.agentsafeを設定しておけばgit waku open --agentで常にサンドボックス内のClaude Codeが立ち上がる。

[waku "command"]
    agent = safe claude --dangerously-skip-permissions

ところで、この記事を書いている最中にsafehouseの威力を体感した。Claude Codeにsafeスクリプトの中身を読ませようとしたらOperation not permittedで弾かれた。~/.local/binは許可リストに入れてないので当然だ。ちゃんと動いている。

みなさんもAIエージェントにフルアクセスを渡して祈るのはやめて、サンドボックスに入れましょう。

iPhoneから開発できるようにした

EchoというiOS向けのSSHクライアントが出たので、iPhoneからMacBookSSH接続して開発できるようにした。接続にはTailscaleを使っている。

EchoはGhosttyのターミナルエンジンを使っていて、TUIの表示がめちゃくちゃ綺麗。$2.99の買い切りでサブスクじゃないのも良い。

tmuxのセッションにそのままアタッチできるので、MacBookで作業していた続きをiPhoneから継続できる。Claude Codeの操作もふつうにできた。

セットアップはTailscaleを両デバイスに入れてMacBookのリモートログインを有効にするだけ。ただSSH鍵の設定がちょっと面倒で、Echo側では鍵の生成ができないのでmacOS側で生成した秘密鍵を持ち込む必要がある(しかもパスフレーズなしじゃないとダメ)。

ssh-keygen -t ed25519 -f ~/.ssh/echo_key -N ""

生成した秘密鍵の中身をEchoのSSH Keys設定からインポートすればいい。

MacBookの蓋を閉じて運用したい場合はスリープを無効にしておく。蓋を閉じるとTailscaleがオフラインになるので。

sudo pmset -c sleep 0
sudo pmset -c disablesleep 1

ところで現時点ではEchoで日本語入力ができない。日本語を打ちたいときはiOSの音声入力を使うとわりとなんとかなる。

ソファに寝転がりながらiPhoneで開発できるの、めちゃくちゃ便利。