Carpe Diem

備忘録

yabai で scripting-addition failed to load

背景

以前、外部ディスプレイを付けたり外したりする度に、上記のアプリの配置を手動で直さないといけない手間を省くツールとして、yabaiを紹介しました。

christina04.hatenablog.com

このツールが v7.1.16, v7.1.17 では、sudo yabai --load-saを実行した際に次のエラーが出るようになり、動かなくなりました。

scripting-addition failed to load

今回はその対応方法を紹介します。

環境

  • macOS 15.7.3
  • yabai v7.1.17

原因

これは以下のIssueで議論されています。

github.com

原因としてはPointer Authentication (PAC) の ABI バージョン不一致とのことです。

  • 新しい clang は arm64e バイナリをデフォルトで PAC ABI v1(caps 0x81)でビルドするようになった
  • 一方、注入先の Dock.app は PAC ABI v0(caps 0x80)でビルドされている
  • カーネル/dyld が ABI の厳密な互換性を強制し、v1 → v0 プロセスへのインジェクションを拒否する
  • v7.1.15 は古い Clang/SDK でコンパイルされていたため、PAC ABI v0 で問題なく動作していた

回避策

次のパッチを適用すると動くようになります。

#!/bin/bash

# https://github.com/asmvik/yabai/issues/2686

patch_caps() {
    [ ! -f "$1" ] && echo "Error: '$1' not found" && return 1

    # Get index (I) and offset (O) for caps 0x81
    read I O <<< $(otool -f "$1" | awk '/architecture/{i=$2} /capabilities 0x81/{f=1} f&&/offset/{print i, $2; exit}')

    if [ -n "$O" ]; then
        # Patch Fat (offset+4) and Mach-O (slice+11) -> 0x80
        printf '\x80' | dd of="$1" bs=1 seek=$((8 + I*20 + 4)) count=1 conv=notrunc 2>/dev/null
        printf '\x80' | dd of="$1" bs=1 seek=$((O + 11)) count=1 conv=notrunc 2>/dev/null
        
        echo "Patched $1 (Arch $I). Resigning..."
        codesign -f -s - "$1" &>/dev/null
    else
        echo "No target architecture (caps 0x81) found in '$1'."
    fi
}

patch_caps "/Library/ScriptingAdditions/yabai.osax/Contents/MacOS/loader"

これを.config/yabai/yabaircで読み込ませればOKです。

#!/usr/bin/env sh

#
# for this to work you must configure sudo such that
# it will be able to run the command without password
#
# see this wiki page for information:
#  - https://github.com/koekeishiya/yabai/wiki/Installing-yabai-(latest-release)#configure-scripting-addition
#
sudo sh ${HOME}/.config/yabai/patch.sh
yabai -m signal --add event=dock_did_restart action="sudo yabai --load-sa"
sudo yabai --load-sa

まとめ

色んな場所で働く上でyabaiが手放せない状況になっている人の助けになれば幸いです。