komagataのブログ

git worktreeで同じサーバーアプリをを複数チェックアウトして並行で動かそうとするとポートが衝突してだるい。

「3000〜3100の範囲で最初に空いてるポートを返す」を1ライナーで書くと下記、

$ comm -23 <(seq 3000 3100) <(ss -tlnH | awk -F: '{print $NF+0}' | sort -un) | head -1
3000

rubyのメソッドとして書くと下記、

require 'socket'

def find_free_port(range = 3000..3100)
  range.find { |p| (TCPServer.new(p).close; true) rescue false }
end

localhostへのbindはちょっぱやで100個見ても数msしかかからないらしいので気軽に探せる。

worktreeに適用する場合は、空いてるポートを環境変数に設定しつつworktreeを作って、アプリ側ではそれを見て起動ポートを決めればいい。

Claude CodeをOpenClawっぽく使うためのランチャーをomarchy向けに作りました。

omarchy-claude-launcher

背景

Claude Codeの外部からの利用はAPI経由扱いになったことで、Claude CodeをOpenClawからメインで使ってた我々が死にました。

OpenClawの何が良かったかというと下記の部分です。

  • (Discordなどから使うと)Web UIみたいに複数の話題を並列で簡単に切り替えられる。
  • 新規に別のプロジェクト・話題を作るのが楽。(Claude Codeだと対応するディレクトリが必要)

無いとキツイので急いでOpenClawの使い勝手をClaude Codeに持ってくることを目的にランチャーを作りました。

どういうもの?

Super+I を押すとwalkerのポップアップが出て、プロジェクトを選ぶとそこでClaude Codeが起動します。

walkerのpicker

それぞれのプロジェクトがtmuxの別ウィンドウとして開きます。

tmuxのタブで切り替わる

一度開いたら、2個目以降のプロジェクトはtmux windowとして追加されて、Alt+1Alt+9 で行き来できます。OpenClawをDiscordで使った時のチャンネル切り替えに近い感覚。

tmuxの設定は独自じゃなくて、omarchyはtmuxもかなりデフォルトで活用されているのでそれに乗っかっています。

そのままgithubリポジトリになることが多いので、~/Works(デフォルト)以下に namespace/project-nameというディレクトリが作られて、その中でClaude Codeが立ち上がるだけです。

マシン再起動してもまたSuper+Iすれば前回の会話が自動復元されます。

技術的な話

  • ランチャーUI: walker (omarchyデフォルト、dmenuモード)
  • ターミナル多重化: tmux
  • ターミナル: alacritty
  • ディレクトリ構造: ~/Works/<namespace>/<name>/ の2階層固定

一部、自分の環境特有のハマりどころもあって:

  • ghosttyをサブプロセス起動するとNVIDIAカード(RTX 4070)でmesa llvmpipeフォールバック経由のLLVMクラッシュが起きる → alacrittyで回避
  • ghosttyのgtk-single-instance=detectがあると-eで渡したコマンドが無視されて新規プロセスが即終了する → これも別ターミナル or --gtk-single-instance=falseで回避

普通に動く人の環境ではCLAUDE_LAUNCHER_TERMINALで好きなターミナルに切り替え可能にしてあります。

インストール

omarchyユーザー向けです(walker, tmux, hyprctlが前提)。

git clone https://github.com/komagata/omarchy-claude-launcher.git
cd omarchy-claude-launcher
./install.sh
hyprctl reload

環境変数での設定:

export CLAUDE_LAUNCHER_DEFAULT_NS="yourname" # namespace省略時のデフォルト
export CLAUDE_LAUNCHER_TERMINAL="alacritty"
export CLAUDE_LAUNCHER_CLAUDE_ARGS="--dangerously-skip-permissions"

詳しくはREADMEを見てください。

おまけ: グローバルメモリ

今回OSSにしたのは「ランチャー」部分だけですが、自分の個人環境では ~/.claude/CLAUDE.md@~/.claude/profile.md@~/.claude/active-projects.md をimportして、全プロジェクト横断のメモリを持たせてます。

これで「儲かるビジネス何?」みたいな発散的な質問を投げたら、並行して作業している他のプロジェクトを引き合いに出して、「あの作りかけのサービスを有料化するのがいいのでは?」みたいなOpenClaw的な示唆が返ってくるようになりました。

こういうグローバルメモリ?的なものは既にみんな独自にやってたり、もっと公式なやり方が出たりすると思うので、今回のはあくまで簡単に立ち上げられるランチャーだけにしました。

おまけ2:OpenClawからの引っ越し

~/.claude~/.openclawに旧OpenClawの記憶やスキルやログが残っているので、「引っ越してマージして」って言ったらほとんど受け継ぐことができました。

ただ、定期実行関係はAnthropicのクラウド上で動かすためにスクリプトを修正したりちょっと面倒でした。

omarchyで日本語変換にmozcを使っていたんですが、mac時代に比べてちょっと変換が弱い気がしたのでもっといいのがないか調べたところ、Hazkeyというfcitx5用の日本語IMEを知って乗り換えた。

HazkeyはiOS/macOS向けの日本語入力アプリazooKeyの変換エンジンを使ったIMEで、ライブ変換(自動変換)ができる。macのライブ変換に慣れてる人はこっちの方がしっくりくると思う。

インストール

Arch Linux(Omarchy)ならAURから入る。

yay -S fcitx5-hazkey-bin

ZenzaiというGPT-2ベースのニューラル変換モジュールもある。文脈を考慮した変換ができるやつ。使いたければモデルも入れる。

yay -S hazkey-zenzai-model

設定

インストールしたらfcitx5を再起動。

fcitx5 -rd

その後、fcitx5-configtoolを開いて右のリストからHazkeyを選んで有効化する。mozcは外しても残しておいてもいい。

使ってみて

ライブ変換が快適。タイプしてる途中からリアルタイムで変換されるので、変換キーを押す回数が激減する。macのライブ変換とほぼ同じ感覚で使える。

Zenzaiを有効にすると変換精度が上がるけど、GPUメモリをそこそこ食うのでスペックと相談。オフでもmozcと同等以上の変換精度はあると思う。これは良いものを知りました。

プログラミングスクールでおしえていることもあって、railsを初めて使う時の敷居を下げたかった。

そこでpure Rubyで画像処理ができるgemシリーズ pura-* を作りました。

railsで使う

# Gemfile
gem "image_processing"
gem "pura-image"

user.avatar.variant(resize_to_limit: [200, 200]) とかがlibvipsなしで動く。

コマンドとして使う

各gemにCLIがついてるので、コマンドラインから使える。

# 画像の情報を見る
pura-jpeg decode photo.jpg --info

# リサイズ
pura-jpeg resize photo.jpg --width 200 --height 200 --out thumb.jpg

# アスペクト比を維持してリサイズ
pura-png resize screenshot.png --fit 800x600 --out fitted.png

# フォーマット変換(JPEGで読んでPNGで書く)
pura-jpeg decode photo.jpg --out pixels.dat
pura-png encode pixels.dat --width 400 --height 400 --out photo.png

Rubyから使う

require "pura-image"

# 読み込み(フォーマット自動判別)
image = Pura::Image.load("photo.jpg")

# リサイズして別フォーマットで保存
thumb = image.resize_to_limit(200, 200)
Pura::Image.save(thumb, "thumb.png")

# フォーマット変換
Pura::Image.convert("input.bmp", "output.jpg", quality: 85)

ベンチマーク

コマンドとして実行。400×400の画像デコード(Ruby 4.0.2 + YJIT)。

  • TIFF: 14ms(ffmpegコマンド 59ms → 4倍速い)
  • BMP: 39ms(ffmpegコマンド 59ms → 速い)
  • GIF: 77ms(ffmpegコマンド 65ms → ほぼ互角)
  • PNG: 111ms(ffmpegコマンド 60ms)
  • WebP: 207ms(ffmpegコマンド 66ms)
  • JPEG: 304ms(ffmpegコマンド 55ms)

コマンドの起動コストがあるので軽いフォーマット(TIFF, BMP)だとffmpegコマンドより速くなる。逆にJPEGみたいに計算量が多いフォーマットだとCの圧倒的な速さに勝てない。

ただ、開発環境やCIでサムネイル生成する程度なら数百msは許容範囲だと思う。

スクリプト言語でJPEGをfull decodeしてるpure実装はJavaScript(jpeg-js)とTcl(ptjd)と、このpura-jpegしかない。PythonにもPerlにもPHPにもないので良い比較相手がいない。

メリット

セットアップが簡単な点以外にも、ruby.wasmやエッジコンピューティングの文脈でC拡張が使えない環境は増えてる。pure Rubyで完結するメリットは今後大きくなると思う。

gemシリーズ

RubyGemsにも公開済み。gem install pura-image で全部入る。

今後

各種高速化、WebPエンコーダのnormal huffman対応、Rails本体への提案(variant_processor = :puraのビルトインサポート)とかやっていきたい。

Lokka REST API v1 リリース

本日、LokkaにREST API v1機能が追加されました。

主な機能

  • Bearer Token認証
  • Posts/Pages/Categories/Tags/Comments/Snippets の CRUD操作
  • User/Site管理(admin権限)
  • JSON形式のレスポンス

使用方法

# トークン取得
curl -X POST /api/v1/token \
  -H "Content-Type: application/json" \
  -d '{"name":"username","password":"password"}'

# 記事投稿
curl -X POST /api/v1/posts \
  -H "Authorization: Bearer TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"post":{"title":"Hello","body":"World"}}'

OpenClawからの自動投稿テストとして、この記事をAPIで投稿しています。

結論

必須ではない。

ただ、ハイパフォーマンスなマシンやmacのマシンだと得することがある。

得すること

  • ハイパフォーマンスマシン:ローカルLLMで実質無料ができる。
    • GUIの操作ができる。
    • 開発させるときにローカル環境が揃ってると色々はかどる。
  • mac:現状唯一の公式クライアントであるmac版が使える。
    • GUIで色々できる。
    • 音声で起動して音声で頼むのが簡単にできる。
    • カメラがついてるmacなら外界認識が簡単にできる。
    • iMessageとかmacのみのソフトが色々使える。

まとめ

ClaudeのMAXプランを使ってるならクラウドや格安VPSがファーストチョイスで良いと思う。ただ、GUI使わせたりガッツリ開発させたりするには$10/moクラスのVPSだとちょい非力かも。家に余ってるハードがあるならお金の節約にもなるぐらい。

僕の場合

一週間ぐらい使ってみて「こりゃいい」となったので、家にあるIntel Macを捧げた。引っ越しも基本的には.openclawディレクトリをコピーすればいいらしく、頼んだらやってくれた。

openclaw

Intel CPUなのでUbuntuを入れようと思ってたんだけど、意外にもmacOS Tahoeが動く機種であることがわかったので急遽Intel macとして使うことに。

実ブラウザやGUIを使わせると手っ取り早いことがおおいのでGUI環境はなかなか良い。rails開発につかうので自分が慣れてる環境でやってくれるのも楽。

「ぽん(我が家の猫)はどこにいる?」と聞くと家にある監視カメラ(TP-Link C200 x 5台)をつかって、家のどこに猫がいるのか探してスクショしてくれるskillなども簡単に作ってくれたが、めっちゃ怖いので停止。

開発は基本的にOpenClawにやってもらって、PRやGitHub上でレビューして、自分で直したい場合に自分のマシンにcloneしてきてClaude Codeを使うって感じ。

このブログは僕が作ってるLokkaというOSSのブログツールで書いているんですが、放置気味になっていたのでAIで復帰させました。

LokkaはORMがDataMapperというとっくにサポートされなくなったライブラリに依存していて、それをActiveRecordに変える作業が大変でなかなか踏み切れずにいましたが、AIのおかげでエイヤと移行できました。

DataMapperからのDB移行についてのスクリプトとドキュメントも用意しました。(してもらいました)

Migration Guide from DataMapper · lokka/lokka Wiki

これで最新のrubyでも動くようになって自分のブログテーマもちょっと変えました。

Internet Archiveから記事を拾ってきてlokka.org も復活させたり、人力では大変過ぎることも大した苦労なしにできてAIさまさまですな。

こういう「緊急でない、必須でない、面倒な作業」って2日間(土日)で終わらないサイズだと永遠におわらなかったんですが、(途中までやって放置するので再開したときにまた1からを繰り返す)AIのおかげで1日でおわるようになって、めでたく完遂できました。

大きな変更なので「ORM移行・最新のrubyで動くようにする」以外はなるべく変えないようにしたんですが、今後はちょこちょこ変えていきたいです。ただ、このブログもHerokuからさくらVPS + Kamalに変わったし「CMS for Cloud」じゃあ全然ないので、別のコンセプトを考えないとですね。

フィヨルドブートキャンプというプログラミングスクールをやっているわけですが、今はAIが話題で、プログラマーとしての就職に興味がある人にとっては、

「これからどうなるんだろう?AIによってプログラマーが不要になる?」

というのが心配なんじゃないかなと思います。

プログラマーは不要?

正直、誰もわからないんですが、最近やっとAIが何をやってくれるのかについてみんなの期待と実情が落ち着いてきた感はあります。

「AI時代にプログラミングを学ぶ必要があるのか?」

についての答えは、

「人間がAIの書いたコードを理解する必要があるか?」

にかかっていると思います。

プロトタイプとかではないプロダクションレベルでは理解している必要があって、これはしばらく続きそうです。

弊社でやってるエンジニア紹介に関しても「プログラマー採用したい」という会社さんの需要は全く減ってないです。

まあ、なので安心してプログラマーになってほしいなと思うんですが、それとは別に、現在既にプログラマーな人がAIどんな感じなのかを伝えたい。

今最高に面白い

正直、AIがあることで、

「やろうと思えばできるけどクソ面倒だからやりたくなかったこと」

とか、

「そもそも不可能かもしれない壮大な計画や超マニアックなプロジェクトに面白半分でとりかかる」

というのもできて超楽しい。

もちろん、ライブラリのコードを自分でカッチリ書くというようなコーディングの楽しみも失われてないし、プログラマーの情緒的には、

「ダリィことはAIに任せて自分は楽しいところどりできて最高」

という感じ。

また、Webサービス屋としても、

今まで「解決したいけど不可能だった問題」がAIで解決できるようになって、Webサービスとして解決できる問題の幅が超広がって楽しい。

ジョブセキュリティーとかキャリアプランとかどーでもよくなるぐらい面白い。

まとめ

ようするに今までと同じだけど、

「おれもやるからきみもやれ」

ということ。

昔のゲームセンターにあったような立ってプレイするタイプのマシンをアーケードキャビネットといいます。アメリカだとおっさんがこのアーケードキャビネットを自作するっていう趣味があって、僕もゲーセン世代なので面白いなと思ってたんですが下手な冷蔵庫ぐらいのデカさがあるので日本の住宅事情には厳しい。

Image from Gyazo

そこでバーのカウンターに乗るぐらいのサイズのバートップアーケードってのもあるのでそちらを作りたいなと思っていて、しかし、いきなりゼロから作るにはハード的にもソフト的にも知識が無いので敷居が高いと思ってました。

Image from Gyazo

Picade

Raspberry Pi 4+と組み合わせてバートップアーケードを作るキットのPicadeを組み立ててみました。

Image from Gyazo

内容はガワとなるケースとディスプレイ、スピーカー、ラズパイ4+につけるPicade Xという独自のボードになります。

Image from Gyazo

はんだ付けとかは不要なのでなんとか頑張って組み立て。このキット自体、メルカリで古いのを買ったせいかレバー部分のプラスチックがポロポロ崩れるほど脆くなっていて個別に三和のレバーを買い直しました。

ソフト的には、Raspberry Piに最適化されたレトロゲームに特化したOSでRetroPieっていうのがあってそれ前提となっていますが、好きなOSを使えばよいです。

キット自体にPICO-8本体のキーが入っているので、PICO-8ユーザーが作った多数のゲームが無料でダウンロードできます。

Image from Gyazo

動作

https://youtube.com/shorts/WqpwaRHbLGM

その後

ハード的にもソフト的にもとっても勉強になりました。RetroPieの公式イメージはかなり古めのDebian 10(Buster)をベースにしているため何かとソフトが古く、そのあたりを別のOSに変えるのもいいかもしれません。

レバーとボタンに好きなパーツを買って使えるのが面白かったので次はアケコンを作りたいなと思っています。

具体的にはmozcの辞書登録。

必要になるたびに忘れてるので書いておきます。

/usr/lib/mozc/mozc_tool --mode=dictionary_tool

Image from Gyazo