Linux

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 の返り値

余った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 いったるかーというところで様子がおかしくなった。