HammerspoonでClaudeデスクトップアプリの「常に許可」を自動クリックする

HammerspoonでClaudeデスクトップアプリの「常に許可」を自動クリックする

Claudeデスクトップアプリを使っていると「常に許可」「一度だけ許可」のダイアログが頻繁に出る。毎回クリックするのが面倒なので、Hammerspoonで自動化した。

背景

Claudeデスクトップアプリ(Mac版)はツール(MCP経由のファイル操作、Webアクセス等)を使うたびに承認ダイアログが出る。セキュリティ上は正しい動作だが、信頼できる作業中は毎回クリックするのが煩わしい。

なお、Claude Codeの場合は --dangerously-skip-permissions のようなオプションでスキップできるが、Claudeデスクトップアプリにはそのようなオプションがない。なので、Hammerspoonのhs.axuielement(macOS Accessibility API)を使ってウィンドウ内のUI要素を読み取ってボタンをクリックすることで、ダイアログを自動承認する。

参考にした記事:Hammerspoonで自動「許可」クリックを実装する|noa_saruta

init.lua のコード

~/.hammerspoon/init.lua に以下を追記:

-- 既存のタイマー・メニューバーがあればクリーンアップ
if _G.allowTimer then
    _G.allowTimer:stop()
end
if _G.menuBar then
    _G.menuBar:delete()
end

-- 「常に許可」「一度だけ許可」ボタンを探してクリック
local function clickAllowButton()
    local ok, err = pcall(function()
        local claude = hs.application.find("Claude")
        if not claude then return end
        local claudeWin = claude:mainWindow()
        if not claudeWin then return end
        local axWin = hs.axuielement.windowElement(claudeWin)
        if not axWin then return end

        local function findAndClick(element)
            local title = element:attributeValue("AXTitle") or ""
            if title:find("常に許可") then
                print("✅ 常に許可クリック: " .. os.date("%H:%M:%S"))
                element:performAction("AXPress")
                return true
            end
            if title:find("一度だけ許可") then
                print("✅ 一度だけ許可クリック: " .. os.date("%H:%M:%S"))
                element:performAction("AXPress")
                return true
            end
            for _, child in ipairs(element:attributeValue("AXChildren") or {}) do
                if findAndClick(child) then return true end
            end
            return false
        end

        findAndClick(axWin)
    end)
    if not ok then print("❌ エラー: " .. tostring(err)) end
end

-- メニューバーの状態更新
local function updateMenu()
    local running = _G.allowTimer and _G.allowTimer:running()
    _G.menuBar:setTitle(running and "🟢" or "🔴")
end

-- メニューバークリックでON/OFF切り替え
local function toggleTimer()
    if _G.allowTimer:running() then
        _G.allowTimer:stop()
    else
        _G.allowTimer:start()
    end
    updateMenu()
end

-- 1秒ごとにスキャン
_G.allowTimer = hs.timer.doEvery(1, clickAllowButton)
_G.menuBar = hs.menubar.new()
_G.menuBar:setClickCallback(toggleTimer)
updateMenu()
print("✅ Timer started: " .. os.date("%H:%M:%S"))

動作

必要な権限

このスクリプトは hs.axuielement を使うので、macOSのAccessibility権限が必要:

システム設定 → プライバシーとセキュリティ → アクセシビリティ → Hammerspoon にチェック

権限がないとClaudeのウィンドウ内を読めず、ボタンが見つからない。

つまづいたポイント

🟢 が出てこない

最初、init.lua をリロードしても 🟢 がメニューバーに出てこなかった。コンソールには ✅ Timer started: ... のログが出ていて、エラーもない。

原因: メニューバーが満杯で、ノッチに隠れていた。M系Macの定番問題。

確認方法: Hammerspoonコンソールで以下を実行する:

print(_G.menuBar)

nil 以外が返ってくれば、メニューバーオブジェクトは作られている=ノッチで見えていないだけ。

解決策: Iceを導入 してメニューバーを管理。隠れていたアイコンが見えるようになり、🟢 も無事登場。

_G.menuBar が nil の場合

メニューバー作成に失敗している。手動で再作成:

_G.menuBar = hs.menubar.new()
_G.menuBar:setTitle("🟢")

-- Done. というログ

リロード後にコンソールに -- Done. が出るが、これはHammerspoonのリロード完了メッセージ。エラーではない。

セキュリティ上の注意

このスクリプトはClaudeの承認ダイアログをすべて自動クリックする。これは:

なので、メニューバーアイコンクリックでON/OFFを切り替えられるようにしてある。重要な作業をする時や、信頼できない指示を試す時はOFFにすること。

まとめ


参考

関連記事