はじめに
2026年6月13日(土)に開催されたシェル芸勉強会の第75回にオンライン(YouTubeの配信)で参加しました。 知らない知識をいろいろ頭に詰め込めてとても勉強になりました。 LTもAIとシェル芸の連携という興味深い内容で知見が得られて良かったです。

参加募集のconnpassのページは下記リンクです。
connpass - jus共催 第75回募集期間短くでごめんなさいファイルの検索を極めるシェル芸勉強会
YouTubeの配信のリンクは下記です。
LTのリンクはこちらです。
シェル芸勉強会の感想
今回はファイル検索がテーマでそれに関する問題が出題されました。 私もfindとgrepでファイルを探すことくらいは普段もしていたのですが、 今回の問題の内容では知らないことがたくさん出てきてこんなことができるんだなぁということと、 全然こんなこと考えたことがなかったなぁということが多かったです。 たとえば「ファイル名に使えない文字」というものをそもそも考えたことがなかったので、 考えるきっかけになっておもしろかったです。
今回学べたこととしてグロブはあまり使ってこなかったけど便利そうなのと、 findのオプションは知らないものがたくさんあるということがありました。 print0オプションで区切り文字をヌル文字に変更できるというのも知りませんでした。 使いどころもたまにありそうで、便利なオプションはちゃんと覚えておきたいですね。
問題は今回も難しいものが多かったです。 3問目あたりから自力で解けなくなってきて調べながら少しずつ進めていきました。 回答と解説がとてもありがたかったです。
今回はオンラインでしたが都合があえば現地参加もしたいと思っています。 現地の空気を浴びたいですね。
LTの感想
LTは2件あってどちらもLLMとシェル芸の連携がテーマだったと思います。 最近はプログラムを書くのも自動化してきていて、 私も流行りに乗っていきたいと思っていたので勉強になりました。 紹介されていたshellgeiaiとlmlineがどちらもおもしろそうで試してみたくなりました。
今回はshellgeiaiで遊ばせていただきます。
shellgeiaiで遊んでみる
LTでamanoeseさんが発表していたshellgeiaiがおもしろそうだったので実際に使ってみました。
GitHubリポジトリのリンクは下記です。
インストール
リポジトリをcloneして使える状態にします。 私の環境のnpmが古かったので更新が必要でした。
git clone https://github.com/amanoese/shellgeiai.git
cd shellgeiai
sudo npm install -g npm@11.17.0
npm install
sudo npm link
実行テスト
shellgeiaiをテストで実行してみます。
--engine mockを付けて実行するとテスト実行できるようです。
OpenAIのAPI Keyを設定していないのでエラーは出ていますが、shellgeiai自体は正常に実行できていそうです。
$ shellgeiai solve "1から10までの合計を出力して" --engine mock
Solve [############] 7/7 completed
message: Solve completed.
selected: worker-1
COMMAND:
printf 'mock-engine could not infer a better command\n'
EXPLANATION:
MVPのmockEngineは既知の例題を優先して処理します。
CHECK:
status: passed
iterations: 1
engine: mock
workers: 1
stop-reason: (none)
selector: best-score-wins
selected-candidate: worker-1
selected-score: 100
score-breakdown: correctness=60, stdout=15, stderr=10, expected=15
selected-shellgei-score: 40
shellgei-breakdown: conciseness=13, shellness=3, ingenuity=4, readability=11, robustness=7, artistry=2
shellgei-notes: (none)
shellgei-penalties: (none)
selector-reason: Selected worker-1 as best passing candidate.
selector-metrics: total=150, shellgei=40, judge=100, consensus=0, stdout=10, duration=704, iterations=1, command-length=55, explanation-length=31
planner-provider: rule-based
planner-attempted-provider: llm
planner-fallback-reason: 429 You exceeded your current quota, please check your plan and billing details. For more information on this error, read the docs: https://platform.openai.com/docs/guides/error-codes/api-errors.
passing-candidates: 1
WORKER VARIANTS:
worker-1 # score: 40 # [awk] # printf 'mock-engine could not infer a better command\n'
RUNNER:
name: docker
sandbox: {"networkAccess":"off","filesystemScope":"workdir-only"}
OpenAIのAPI Keyを設定する
OpenAIの公式サイトでAPI Keyを設定してプログラム上からAPIを叩けるようにします。 どこでAPI Keyを取得できるのかよく分からなかったのですが、下記リンクのようです(先ほどのエラーで提示されていたURL)。
アカウントはすでに持っていたのでログインしてからAPI Keyを生成しました。 API Keyの使用は課金が必要とのことで支払い方法を設定して、さらに前払いのようだったので5ドルを課金しました。 ちなみに「Auto recharge」はひとまずオフにしておきました。
補足: 3時間くらいAPIで遊んで0.6ドル分くらいの消費でした(Total tokens: 258269, Total requests: 351)。
shellgeiaiからAPIを叩くために下記コマンドでAPI Keyとモデルを設定します。
export OPENAI_API_KEY=your_api_key
export OPENAI_MODEL=gpt-5.4-mini
shellgeiaiで問題を解いてみる
それでは実際にshellgeiaiで問題を解いてみました。 簡単な問題だからか一瞬で解けました。 下記が出力です。
$ shellgeiai solve "1から10までの合計を出力して"
Solve [############] 7/7 completed
message: Solve completed.
selected: worker-1
COMMAND:
seq 10 | awk '{s+=$1} END{print s}'
EXPLANATION:
1から10までを生成して1回で合計を出します。
CHECK:
status: passed
iterations: 1
engine: openai
workers: 1
stop-reason: (none)
selector: best-score-wins
selected-candidate: worker-1
selected-score: 100
score-breakdown: correctness=60, stdout=15, stderr=10, expected=15
selected-shellgei-score: 70
shellgei-breakdown: conciseness=14, shellness=15, ingenuity=10, readability=13, robustness=10, artistry=8
shellgei-notes: Uses standard Unix tools., Avoids redundant pipeline stages.
shellgei-penalties: (none)
selector-reason: Selected worker-1 as best passing candidate.
selector-metrics: total=180, shellgei=70, judge=100, consensus=0, stdout=10, duration=469, iterations=1, command-length=35, explanation-length=23
planner-provider: llm
planner-attempted-provider: llm
planner-fallback-reason: (none)
passing-candidates: 1
WORKER VARIANTS:
worker-1 # score: 70 # [seq,awk] # seq 10 | awk '{s+=$1} END{print s}'
RUNNER:
name: docker
sandbox: {"networkAccess":"off","filesystemScope":"workdir-only"}
shellgeiaiが生成したシェル芸を実際に実行してみて出力が正しいことも確認しました。
$ seq 10 | awk '{s+=$1} END{print s}'
55
以上でshellgeiaiが正常に動いていることが確認できました。
シェル芸オンラインジャッジの問題を解いてみる
シェル芸オンラインジャッジというシェル芸で問題を解いて遊ぶウェブサイト(下記リンク)があるので、 shellgeiaiで問題を解いてみようと思います。
Geminiに下記のシェルスクリプトを書いてもらいました。
- 問題IDを指定してシェル芸オンラインジャッジから問題データを取得
- 問題データをshellgeiaiに渡してシェル芸を生成
- 生成したシェル芸をシェル芸オンラインジャッジに投げて結果を取得
- 判定結果を表示
下記シェルスクリプトをshellgeiai_SOJ.bashとして保存しました。
#!/bin/bash
# 1. APIキーのセット忘れ防止
if [ -z "$OPENAI_API_KEY" ]; then
echo "エラー: OPENAI_API_KEY がセットされていません!"
echo "実行前にターミナルで export OPENAI_API_KEY='sk-...' を実行してください。"
exit 1
fi
PROBLEM_ID=${1:-"STANDARD-00000001"}
API_BASE="https://shellgei-online-judge.com/api"
echo "=== 1. 問題の取得: $PROBLEM_ID ==="
PROBLEM_JSON=$(curl -s "$API_BASE/problems/$PROBLEM_ID")
STATEMENT=$(echo "$PROBLEM_JSON" | jq -r '.statement_ja')
INPUT_DATA=$(echo "$PROBLEM_JSON" | jq -r '.input')
EXPECTED_OUTPUT=$(echo "$PROBLEM_JSON" | jq -r '.expected_output')
echo -e "\n【問題文】\n$STATEMENT"
PROMPT="以下のシェル芸の問題を解くワンライナーを作成して。
入力ファイルへのアクセスは必ず相対パスの \`input.txt\` を使用し、絶対パス(/home/...等)は絶対に含めないでください。
【問題】
$STATEMENT
【入力データ(input.txt)】
$INPUT_DATA
【期待される出力】
$EXPECTED_OUTPUT"
echo "=== 2. ShellgeiAIでシェル芸を探索中... ==="
shellgeiai solve "$PROMPT" > ai_output.log 2> ai_error.log
if [ ! -s ai_output.log ]; then
echo "😭 ShellgeiAIの実行に失敗しました。エラー内容は以下の通りです:"
cat ai_error.log
exit 1
fi
# 内部処理:カラーコードを削除して抽出
AI_OUTPUT_CLEAN=$(cat ai_output.log | sed -r "s/\x1B\[([0-9]{1,3}(;[0-9]{1,2})?)?[mGK]//g")
COMMAND=$(echo "$AI_OUTPUT_CLEAN" | awk '/COMMAND:/{flag=1; next} /EXPLANATION:/{flag=0} flag' | grep -v '^$')
# --- スコアの抽出(tail -n 1 を追加して最終結果のみを取得) ---
JUDGE_SCORE=$(echo "$AI_OUTPUT_CLEAN" | grep 'selected-score:' | tail -n 1 | sed 's/selected-score: //')
SHELLGEI_SCORE=$(echo "$AI_OUTPUT_CLEAN" | grep 'selected-shellgei-score:' | tail -n 1 | sed 's/selected-shellgei-score: //')
SHELLGEI_BREAKDOWN=$(echo "$AI_OUTPUT_CLEAN" | grep 'shellgei-breakdown:' | tail -n 1 | sed 's/shellgei-breakdown: //')
if [ -z "$COMMAND" ]; then
echo "😭 コマンドの抽出に失敗しました。"
exit 1
fi
echo -e "\n【AIが最終的に選んだコマンド】"
echo "$COMMAND"
echo -e "\n【AIの最高スコア】"
echo " - 実行スコア: $JUDGE_SCORE"
echo " - シェル芸度: $SHELLGEI_SCORE ($SHELLGEI_BREAKDOWN)"
echo ""
echo "=== 3. SOJに解答を送信中... ==="
PAYLOAD=$(jq -n --arg cmd "$COMMAND" --arg pid "$PROBLEM_ID" '{shellgei: $cmd, problem_id: $pid}')
RESULT=$(curl -s -X POST "$API_BASE/shellgei" -H "Content-Type: application/json" -d "$PAYLOAD")
OUTPUT=$(echo "$RESULT" | jq -r '.output')
JUDGE=$(echo "$RESULT" | jq -r '.judge')
echo "=== 結果 ==="
echo "SOJの出力:"
echo "$OUTPUT"
if [ "$JUDGE" = "1" ]; then
echo "判定: 🎉 正解!! (Judge: 1)"
else
echo "判定: 😭 不正解... (Judge: $JUDGE)"
fi
私の環境だとjqがなかったのでインストールしました。
sudo apt install jq
STANDARD-00000001を解く
shellgeiaiでSTANDARD-00000001の問題を解いてみました。
testを出力するだけですが無事解けました。
5秒くらいでshellgeiaiとシェル芸オンラインジャッジ含めて結果が返ってきました。
$ bash shellgeiai_SOJ.bash STANDARD-00000001
=== 1. 問題の取得: STANDARD-00000001 ===
【問題文】
文字列"test"を出力してください。
ex: echo "test"
=== 2. ShellgeiAIでシェル芸を探索中... ===
【AIが最終的に選んだコマンド】
printf 'test\n'
【AIの最高スコア】
- 実行スコア: 100
- シェル芸度: 47 (conciseness=15, shellness=3, ingenuity=4, readability=15, robustness=8, artistry=2)
=== 3. SOJに解答を送信中... ===
=== 結果 ===
SOJの出力:
test
判定: 🎉 正解!! (Judge: 1)
STANDARD-00000004も解いてみる
STANDARD-00000004も解いてみました。 各行に並んでいる数字を足し合わせる問題です。 こちらも無事解けましたがawkだけで済んでいるためなのかスコアが低いです。
$ bash shellgeiai_SOJ.bash STANDARD-00000004
=== 1. 問題の取得: STANDARD-00000004 ===
【問題文】
各行において、並んでいる数字を足し合わせた合計を出力してください。
=== 2. ShellgeiAIでシェル芸を探索中... ===
【AIが最終的に選んだコマンド】
awk '{s=0; for(i=1;i<=NF;i++) s+=$i; print s}' input.txt
【AIの最高スコア】
- 実行スコア: 15
- シェル芸度: 0 (conciseness=0, shellness=0, ingenuity=0, readability=0, robustness=0, artistry=0)
=== 3. SOJに解答を送信中... ===
=== 結果 ===
SOJの出力:
6
8
6
15
9
判定: 🎉 正解!! (Judge: 1)
STANDARD-00000005も解いてみる
STANDARD-00000005はフィボナッチ数列を第10項まで出力する問題です。 こちらもawkだけで済んでいますがスコアはちょっと高いです。
$ bash shellgeiai_SOJ.bash STANDARD-00000005
=== 1. 問題の取得: STANDARD-00000005 ===
【問題文】
Fibonacci: F(0) = 0, F(1) = 1, F(n+2) = F(n) + F(n+1)
F(0)からF(10)まで出力してください。
=== 2. ShellgeiAIでシェル芸を探索中... ===
【AIが最終的に選んだコマンド】
awk 'BEGIN{a=0;b=1;for(i=0;i<=10;i++){print a;c=a+b;a=b;b=c}}' input.txt
【AIの最高スコア】
- 実行スコア: 100
- シェル芸度: 54 (conciseness=12, shellness=8, ingenuity=4, readability=15, robustness=10, artistry=5)
=== 3. SOJに解答を送信中... ===
=== 結果 ===
SOJの出力:
0
1
1
2
3
5
8
13
21
34
55
判定: 🎉 正解!! (Judge: 1)
51問解いて正解率を出してみる
STANDARD問題が51問あるので全部解いて正解率を出してみます。
Geminiに雑に作成してもらったワンライナーです↓
correct=0; for i in {1..51}; do id=$(printf "STANDARD-%08d" $i); echo -e "\n=== 実行中: $id ==="; OUTPUT=$(bash shellgeiai_SOJ.bash $id); echo "$OUTPUT"; if echo "$OUTPUT" | grep -q "Judge: 1"; then ((correct++)); fi; sleep 2; done; echo -e "\n===================="; echo "🏆 最終結果: $correct/51 問正解"; echo "📊 正解率: $(echo "scale=1; $correct / 51 * 100" | bc) %"; echo "===================="
結果は下記の通りです。
意外と解けない問題もあって興味深いです。
とはいえ今回は--parallelismと--max-iterは設定せずデフォルトのままで、
モデルも変更していないので、
いろいろ調整すれば性能はもっと出そうな気はします。
====================
🏆 最終結果: 38/51 問正解
📊 正解率: 70.0 %
====================
おわりに
今回はシェル芸勉強会の第75回に参加して、その記録を書きました。 シェル芸は日頃から遊んでおくと仕事でも役に立つときがあるし、 パズル感覚で頭の体操にもなるので脳トレにも良いかと思っています。 shellgeiaiも遊んでみて、最近のAIはシェル芸力が高まっていることが分かって良かったです。 人が書いたシェル芸をAIが評価してくれる機能をシェル芸オンラインジャッジに組み込めたらおもしろそうだなとも思いました。 AIを通してシェル芸の奥深さを理解する日がやがて来るかもしれません(雑な感想)。 それでは、また。