Posts

Claude Code の git push が壊れた日:バイナリ解析よりリリースノートを先に読め

Claude Code で git push できなくなった。原因調査の過程を Claude とのやりとりで再現する。結論を先に言うと、リリースノートを最初に見ていれば 5 分で終わった話だった。

TL;DR

根本原因: v2.1.91 で excludedCommands のマッチング挙動が修正された

バージョンexcludedCommands: ["git"] の動作
v2.1.90 以前バグで git push origin main にもマッチ → sandbox 完全 bypass
v2.1.91 以降仕様通りに修正。"git" は bare git のみにマッチ → sandbox 適用 → 認証情報へのアクセスがブロックされ失敗

修正した設定:

// Before
"excludedCommands": ["git"]

// After
"excludedCommands": ["git *"]

今回は俺と Claude さんの会話を再現してます。一部省略。

Scene 1:動くはずのものが動かない

俺:この環境で git push できる?ターミナル(CLI)だと
  サンドボックスで阻まれてプッシュできないって言われたんだけど。

Claude はまず調査に入った。リモートを確認し、dry-run を試みる。

fatal: could not read Username for 'https://github.com': No such device or address

失敗。

Anthropic の OAuth 禁止で NanoClaw 大丈夫?→大丈夫(?)だと思うけど別の問題があった

Anthropic がサードパーティツールでの OAuth トークン利用を禁止したというニュースを見て、自分の NanoClaw は大丈夫かと確認しに行ったら、OAuth とは別のところに問題があった。

Anthropic の OAuth 禁止とは

Anthropic が Claude Pro/Max のサブスクリプション認証トークンをサードパーティツール経由で使う行為を禁止した。

要するに「月 20 ドルの Claude Pro に加入して、API キーの代わりにそのセッショントークンを使えば月 200〜500 ドル相当の API をほぼタダで使える」という抜け道を塞いだ話。

昨今の Claude への流入増大も影響あったんだろうね。

NanoClaw への影響は?

(おそらく)なし。

公式がそう言ってる、けどまあどうなるか分かんないけどね。
NanoClaw は、Anthropic の正規 API キーを使う構成で、OAuth には一切依存していない。認証まわりは OneCLI という credential proxy が担っていて、コンテナ起動時に ANTHROPIC_BASE_URL 経由でキーを注入する仕組みになっている。

Credentials are injected by the host’s credential proxy via ANTHROPIC_BASE_URL.

直接 .env に API キーを書くわけでもなく、OAuth トークンを流用するわけでもないので、今回の禁止措置とは完全に無関係って言ってる。まあ若干不安だけど。
ということで確かめてみることにしました。

OneCLI の設定確認しておくか

onecli コマンドで実際の状態を確認しようとしたら…

$ onecli auth status

{
  "error": "getting user: executing request: Get \"http://127.0.0.1:10254/api/user\": dial tcp 127.0.0.1:10254: connect: connection refused",
  "code": "ERROR"
}

OneCLI のサーバーが落ちてる…
いやいや、最初から躓くの?
NanoClaw 自体は動いてるんだっけ?

Ubuntu + fcitx5 で IME モードをトップバーの色で示す GNOME 拡張を作った(作ってもらった)

Ubuntu デスクトップで日本語入力してると、いま英語モードなのか日本語モードなのかわからなくなることがよくある。トップバーの右端に「あ」とか「A」は出てるんだけど、作業中は目線が画面中央にあるので全然気づかない。

何回も Ghostty の tmux でプレフィックス打って効かないことが続くの嫌になった。心底嫌になった。

macOS だと入力モード切り替え時に画面上に色付きのバーで今のモードを表示してくれるやつがあったのに…

既製品を探した

Claude さんに相談してみて、GNOME Extensions も漁ったけど、ぴったりのものがない。

  • Kimpanel(extension/261): fcitx5 と連携してトップバーにモード表示できる。でも文字表示なので見づらさは変わらない
  • Input-Method Status Indicator(extension/68): IBus 向けなので fcitx5 環境では微妙
  • カーソル近くに表示するやつ: Linux/GNOME には存在しなかった

そんなとき

「無ければ作ればいいじゃんw」

みたいなノリで Claude 様がおっしゃられたので

「まじっすか、それでお願いします!」

って言ったら10分もかからずにできた。すげーなおい。

俺指示したの「色の指定は外出しファイルにしてリアルタイムに反映できるようにしといて」の雑な1行だけ。

そんな雑な指示によって作られたものが以下です。

作ったもの(作ってもらったもの)

fcitx5 が提供している fcitx5-remote コマンドをポーリングして、返り値に応じてトップバーの色を切り替える GNOME Shell 拡張。

~/.local/share/gnome-shell/extensions/ime-indicator@local/
├── extension.js
├── colors.json
└── metadata.json

metadata.json

{
  "name": "IME Indicator",
  "description": "fcitx5 の入力モードに応じてトップバーの背景色を切り替える",
  "uuid": "ime-indicator@local",
  "shell-version": ["46"],
  "version": 1
}

colors.json

色の設定だけを切り出したファイル。ここを編集すると即時反映される。

{
  "jp": "#641414",
  "en": "#000000"
}

extension.js

import { Extension } from "resource:///org/gnome/shell/extensions/extension.js";
import * as Main from "resource:///org/gnome/shell/ui/main.js";
import GLib from "gi://GLib";
import Gio from "gi://Gio";

export default class IMEIndicatorExtension extends Extension {
  enable() {
    this._colors = { jp: "#641414", en: "#000000" };
    this._isJp = null;
    this._loadColors();
    this._watchColors();
    this._updateState();
    this._timeout = GLib.timeout_add(GLib.PRIORITY_DEFAULT, 400, () => {
      this._updateState();
      return GLib.SOURCE_CONTINUE;
    });
  }

  disable() {
    if (this._timeout) {
      GLib.source_remove(this._timeout);
      this._timeout = null;
    }
    if (this._monitor) {
      this._monitor.cancel();
      this._monitor = null;
    }
    Main.panel.set_style("");
  }

  _loadColors() {
    try {
      const [ok, contents] = GLib.file_get_contents(`${this.path}/colors.json`);
      if (ok) {
        this._colors = JSON.parse(new TextDecoder().decode(contents));
        if (this._isJp !== null) this._applyColor(this._isJp);
      }
    } catch (_) {}
  }

  _watchColors() {
    const file = Gio.File.new_for_path(`${this.path}/colors.json`);
    this._monitor = file.monitor_file(Gio.FileMonitorFlags.NONE, null);
    this._monitor.connect("changed", (_m, _f, _o, eventType) => {
      if (eventType === Gio.FileMonitorEvent.CHANGES_DONE_HINT)
        this._loadColors();
    });
  }

  _updateState() {
    try {
      let proc = Gio.Subprocess.new(
        ["fcitx5-remote"],
        Gio.SubprocessFlags.STDOUT_PIPE
      );
      proc.communicate_utf8_async(null, null, (proc, res) => {
        try {
          const [, stdout] = proc.communicate_utf8_finish(res);
          const state = parseInt(stdout.trim());
          const isJp = state === 2;
          if (isJp === this._isJp) return;
          this._isJp = isJp;
          this._applyColor(isJp);
        } catch (_) {}
      });
    } catch (_) {}
  }

  _applyColor(isJp) {
    const color = isJp ? this._colors.jp : this._colors.en;
    Main.panel.set_style(`background-color: ${color};`);
  }
}

ポイント

fcitx5-remote の返り値

VSCode Copilot Chat と Claude Code、bash の扱いが違う

午前中、Copilot Chat のエージェントモードでコマンド実行したら止まるという事象が頻発した。.bashrc に仕掛け作って凌いだ。定時過ぎに Claude Code の仕組みを調べたらなんか知らんけど上手く動いてた、という一日の話。

午前:Copilot Chat のエージェントモードでコマンド実行すると以後進まない

VSCode の Copilot Chat をエージェントモードで使っていたら、コマンドを実行させるとそこで「Preparing」が点滅し続けてそこから進まなくなった。

なんだよこれと思って調べてみると、oh-my-posh が原因。oh-my-posh v28.1.1 以降で VSCode Shell Integration と競合するようになったらしく、エージェントが叩いた bash がそのまま固まる。

解決策として .bashrc に VSCode 向けの早期リターンを仕込んだ。$TERM_PROGRAM は VSCode が統合ターミナルを開くときにセットする変数で、WSL・ネイティブ Ubuntu どちらでも vscode になる。

# mise shims(全環境で必要)
eval "$(mise activate bash --shims)"

# VSCode 統合ターミナルはここで早期リターン
if [[ "$TERM_PROGRAM" == "vscode" ]]; then
  return
fi

# 以降はインタラクティブ専用(Tabby / GNOME Terminal など)
eval "$(oh-my-posh init bash ...)"
# ghq, fzf など...

これで Copilot Chat のエージェントモードは直った。さくさく進むようになった。でも午前の業務は溶けた。う○こですよ。

余ったMacBook Pro 2015でUbuntuを動かすまでの地獄

はじめに

先日 Windows 11 のノートPCを手に入れた。会社でも WSL で Ubuntu 使ってるので喜び勇んで WSL をセットアップして満足。うちでも開発できる環境ができた。
それはそれでいいんだけど、それまでメインで使っていた MacBook Pro 2015 は完全に引退となった。

macOS はとっくに更新できなくなっているし、このまま眠らせておくのも勿体ない。

OpenClaw

最近、猫も杓子も OpenClaw という世の中の流れになっているらしい。中国ではセットアップするサービスに行列が出来たとか何とか。
自宅サーバーに置いてローカルで動き、WhatsApp や Telegram など使い慣れたチャットアプリから操作できる。メール管理やカレンダー操作、ファイル操作まで自動化できるというやつですね。 面白そうだし、試してみようかなーと思ったけど、いざ調べてみたら結構セキュリティやばそう。

  • RCE 脆弱性(CVE-2026-25253、CVSS 8.8)が報告されており、認証なしで公開されているインスタンスが世界に 42,000 件以上
  • プラグインマーケットプレイス(ClawHub)の約 12% が悪意あるスキル
  • メール・カレンダー・購入・ファイルと権限が広すぎるので、侵害されたときの被害が大きい

いや、これ普通にやったらやばいだろ。

nanoclaw

で、他のないかなと探していたら、nanoclaw を見つけた。コンテナで隔離して動かせる設計になっているし、これならホストへの影響も最小限になりそう。

ということで、MacBook Pro 2015 に Ubuntu を入れて、その上で nanoclaw をコンテナで動かすことにしたんだけど、そこからはまりまくった。

Claude の Pro プラン入ってなかったら確実に諦めてたわ。それが以下の話。

Ubuntu インストール

Ubuntu のインストール自体は公式のやり方にしたがって、Amazon ブランドの USB (なかなか評判いいんですね)にインストールイメージを焼いて起動、手順通りに進めるだけでOK。

apt update / upgrade も通る。linuxbrew, gh, fzf, ghq, oh-my-posh, google-chrome, claudecode などなどを入れ始めて、さあ nanoclaw いったるかーというところで様子がおかしくなった。

このブログについて

システムエンジニアやってます。

GitHubCopilot や ClaudeCode をいじって遊んでて、「AI すげーな」みたいな小並感を日々感じてます。

このブログのサブタイトルが 〜大体動かない〜 なのは、新しいツール使ってみたりすると大体動かないから。最近では AI があるので本当に助かってます。嘘をつかれないようにインストラクションをいじいじして試行錯誤したりしてます。そんなメモ書きのブログです。