📰 newsreader

twostopbits score 0.24 好み 2.00 en

macOS版Clippy – コンピュータ操作機能を備えたレトロなフローティング・ペーパークリップ

原題: Clippy for macOS – retro floating paperclip with computer use (github.com)

macosai assistantcomputer useautomationai agentaccessibility treedesktop automationscreen recording
原文 ↗

日本語訳

# タイトル

Clippy for macOS – コンピュータ操作機能を備えたレトロなフローティング・ペーパークリップ (github.com)

# 本文

Macで何かをするよう頼めば、Clippyはスクリーンショットを撮り、目の前にあるもののアクセシビリティツリーを読み取り、実行します。手順を説明してユーザーにクリックさせるのではなく、自ら動きます。

デスクトップに常駐し、自律的に動作するClippy。

多くの「AIデスクトップアシスタント」のデモはチャットで止まっています。質問すれば回答は返ってきますが、クリックするのは依然としてユーザーです。Clippyはその最後の溝を埋めます。

「ダークモードをオンにするには、システム設定を開き、サイドバーの『外観』をクリックして『ダーク』を選択してください」という説明を聞くのと、チェックリストが埋まっていくのを眺めながらClippyが実行するのとでは、決定的な違いがあります。

デスクトップ上に小さなフローティング・ペーパークリップとして存在します。短い回答は吹き出しに表示され、長い会話、音声による返答、ディクテーション、ファイルの添付などが必要な場合は、その下にフルサイズのチャットウィンドウが開きます。90年代のバグを除けば、まさにクラシックなアシスタント体験です。

### 重要

Clippyは、取り消し不可能な操作の直前で停止します。「送信」「送信(Submit)」「購入」「支払い」「削除」「同意」、そしてすべてのパスワード入力フィールドは無条件に拒否されます。Clippyは最後のステップまで進め、そこから先はユーザーにキーボードを渡します。詳細は「ガードレール(Guardrails)」を参照してください。

- 最新のDMGをダウンロードしてください — Apple SiliconとIntelの両方に対応したユニ

原文(英語)を表示

Ask it to do something on your Mac and it takes a screenshot, reads the accessibility tree of whatever's in front of you, and does it — instead of describing the steps back to you and leaving you to click.

Clippy, live on the desktop, working out on making itself

Most "AI desktop assistant" demos stop at chat: you ask, it answers, and you still do the clicking. Clippy closes that last gap. It's the difference between:

"To turn on Dark Mode, open System Settings, click Appearance in the sidebar, then choose Dark."

and Clippy just doing it while you watch the checklist tick over.

It lives as a small floating paperclip on your desktop: short answers come back in the speech balloon, and the full chat window opens underneath it for longer conversations, spoken replies, dictation, and file attachments. The classic assistant experience, minus the 90s bugs.

Important

Clippy stops before anything irreversible. Send, Submit, buy, pay, delete, agree, and every password field are refused unconditionally — it gets you to the last step and hands you the keyboard. See Guardrails.

- Download the latest DMG — one universal build, Apple Silicon and Intel.

- Open it, drag Clippy to Applications.

- First launch: right-click ▸ Open (the build is ad-hoc signed, so Gatekeeper warns once).

- Grant Accessibility and Screen Recording when asked. Without them Clippy still chats, it just can't see or act.

Then pick how it thinks, in Settings: your existing Claude Code or Codex login (no extra key needed), or your own OpenAI / Anthropic API key, stored in the macOS Keychain.

Every screen request runs the same loop, one step at a time:

look ──▶ plan one step ──▶ do it ──▶ look again ──▶ done?

▲ │

└────────────── no: what changed? re-plan ◀──────────────┘

It never builds a ten-step plan up front and runs it blind — a real screen rarely matches a prediction, and looking again after every action is how Clippy notices.

The details that make it work (click to expand)

- Looks when it matters, and only then. A request that could be about your screen gets a fresh screenshot plus an accessibility scan — control labels, roles, positions, and each control's current state. A self-contained question ("explain tail recursion") skips the capture entirely and streams the answer instead. If a skipped look turns out to have been needed, Clippy notices from its own answer and retries with real screen context, so a miss costs a second, not a wrong answer.

- Reads state, not just labels. Every control reports what's already in it — the text sitting in a field, whether a checkbox is on or off, what currently has keyboard focus. That's what stops it retyping a search box that already holds the right query, or toggling a setting that was already on, and it's how it confirms a step did what it intended.

- Scrolls to find things. An accessibility scan only ever describes what's on screen right now, so a control below the fold looks exactly like a control that doesn't exist. Clippy can scroll and look again — a few ticks at a time, re-observing between them — instead of concluding the target isn't there.

- Retries on its own. A failed step (wrong label, a menu that opened somewhere else) triggers an automatic retry from a fresh screenshot, bounded to a few consecutive attempts before it stops and asks you.

- Clicks and types by coordinate when labels can't be trusted. Browser address bars are the classic case: their accessibility label varies by version, and a page can have a look-alike search box with the exact same placeholder text sitting right next to the real one. Clippy can click the literal pixel it sees in the screenshot instead of gambling on a label match.

- Aware of what's already open. Before launching a fresh app instance, it checks what's already running and prefers switching to it.

- Shows its work. Every plan runs through a live checklist (✓ done, ✗ failed, • pending) and, once it finishes, gets posted to the chat transcript as a permanent record of what actually happened.

- Remembers you. Tell it your name, what you're building, or how you like answers, and it carries that across chats and relaunches instead of asking again on Monday. Everything it has stored is listed verbatim in Settings ▸ What Clippy remembers, and deletable one line at a time — memory you can't see is memory you can't correct.

The paperclip is a nod to Microsoft's old Office Assistant. Everything else — the screen reasoning, the safety checks, the retry logic — is original.

It's a solo side project, rebuilt in public commits as bugs turned up from using it day to day. Most of the interesting work is in getting the automation to fail safely: a step that can't find its target should stop and ask, not click something at random.

- Every step is validated before it runs: Send, Submit, publish, buy, pay, delete, accept or agree, sign out, and password or passcode controls are always refused. This check is unconditional and independent of everything else below.

- Return is never sent by Clippy, with exactly one exception: submitting a browser's own address or search field (navigating to a URL or running a search). Every other field gets typed into but never submitted; you press Enter yourself.

- Secure and password fields are refused outright, regardless of what's asked.

- Scrolling is the one action that runs without confirmation: it only changes what's visible, commits nothing, and destroys nothing. It still refuses to scroll a restricted app, since that's still synthetic input aimed at one.

- By default, this build's terminal and agent-CLI restriction is off

(

gui-restricted-app

,enabled: false

): Clippy can click and type into Terminal, Warp, iTerm, and similar apps, on the reasoning that everything runs on your own machine and Return still can't be sent there. Flip that one flag to restore it. - Nothing runs without both Accessibility and Screen & System Audio Recording permission granted in System Settings. Clippy prompts for both the first time it needs them.

Every refusal above comes from

Resources/prismor-policy.yaml

— a

Prismor Warden policy file. AutomationSafety.swift

holds no rule text any more; it asks the policy and reports the answer. So

changing what Clippy will and won't touch is a diff to a YAML file, reviewable

on its own, with no rebuild of anyone's mental model of the Swift.

- id: gui-final-action

severity: CRITICAL

category: final_action

title: Control performs a consequential, non-reversible action

event_types: [ui_action]

fields: [control_label]

mode: enforce

patterns: ['\bsend\b', '\bsubmit\b', '\bbuy\b', '\bdelete\b', ...]

After editing, recompile the form the app loads (CI fails the build if you forget):

./scripts/compile-policy.sh

It fails closed. A policy that's missing, corrupt, or contains a regex that won't compile does not degrade into "allow" — Clippy treats every control as a final action and stops touching the screen entirely. A guardrail that quietly stops guarding is worse than one that visibly stops working.

Note

Clippy's dangerous act is "operate the control labelled Send", which

Warden's original event_types

enum couldn't express — it described agents

that run commands and edit files (shell

, file_read

, network

, …). These

rules use a ui_action

event type with control_label

/ ax_role

/

app_name

/ typed_text

fields, contributed

upstream along with the type: veto

allowlist

precedence the address-bar exception depends on. Everything else — severity,

mode

, add_patterns

/ disable_patterns

and their strengthen-only

semantics — is stock and implemented to match, and the same file loads

identically in Warden and in Clippy.

Prefer not to trust a stranger's DMG? Fair. Requirements: macOS 14+, Xcode command-line tools, and Swift 5.10+.

chmod +x scripts/build-dmg.sh

./scripts/build-dmg.sh

The output is written to build/Clippy-macOS-universal.dmg

. The included app

runs natively on both Apple Silicon and Intel Macs.

Local builds automatically use the first Apple Development code-signing identity in the current keychain. This keeps macOS Accessibility permission stable across rebuilds. If no development identity is available, the script falls back to ad-hoc signing.

For public distribution without Gatekeeper warnings, set a Developer ID identity before building:

CODESIGN_IDENTITY="Developer ID Application: Your Name (TEAMID)" ./scripts/build-dmg.sh

Then notarize the resulting DMG with your Apple Developer credentials and staple the ticket.

Published releases are built the same way by

.github/workflows/release.yml

, which runs

the tests and the offline safety eval first and refuses to ship a DMG that

lost either architecture slice.

Run the checks yourself with:

swift test # 280 unit tests

swift run clippy-eval --offline # replays recorded screens; safety regression gate

Install Claude Code and authenticate once in Terminal. Clippy finds common

Homebrew, npm, and user-local install locations and runs claude -p

.

Install Codex and authenticate once in Terminal. Clippy runs codex exec

with

network and file mutation disabled by the read-only

sandbox.

Select OpenAI API or Anthropic API in Settings, enter a model and API key, then click Save key. Keys never enter app preferences; they are stored in the user's macOS Keychain.

-

Slash commands.

/clear

clears the chat and starts a new session,/help

lists everything. Save prompts you use often as your own commands in Settings ▸ Custom prompts — anything typed after the command is appended, so/review this function

works as well as a bare/review

. Typing/

shows the matching commands above the composer. -

An editable balloon menu. The floating paperclip's options can be renamed, reordered, or hidden in Settings ▸ Balloon menu, and any custom prompt can be surfaced there as a one-click row. Each built-in row keeps its behaviour — only the wording is yours.

-

Follows your active display. On a multi-monitor setup Clippy moves to whichever screen holds the app you just switched to, keeping its relative position, and recovers itself if the display it was on is unplugged.

-

Spoken replies and microphone dictation, with an optional local Whisper engine (inspired by OpenWhispr) for more accurate, fully offline transcription — off by default, offered once at first launch and toggleable any time in Settings

-

Push-to-talk dictation — hold a chord to speak, release to stop. Two destinations:

- Hold ⌘⌥ to type into whatever editable field you had focused. If there's nowhere safe to put it — no editable target, or a password field, which is always refused — it lands on your clipboard instead and Clippy says so. Held while Clippy itself is frontmost, it fills Clippy's composer rather than another app.

- Hold ⌥⇧ to send what you said to Clippy as a chat message.

Both work from any app (needs Accessibility; otherwise only while Clippy is frontmost). Pressing any key mid-hold cancels the recording, so the chords stay usable as ordinary typing modifiers. Edit ▸ Toggle Dictation is the hands-free alternative.

-

Classic Office-style balloon above the floating character, with an expandable full chat window

-

Live provider-aware work stages, elapsed time, and accessible status announcements

-

Compact action center for opening trusted apps and common folders

-

Local Codex and Claude session discovery with explicit resume-in-Terminal actions

-

Contextual answer actions for copying results and opening cited links

-

True request cancellation for API calls and local Claude Code/Codex processes

-

Compact-balloon attachments for images, PDFs, and text/code files: paste images or file URLs directly with Command-V

-

Persistent conversation history

-

Optional always-on-top window

PRs welcome — see CONTRIBUTING.md for setup, the two checks CI runs, and what changing a guardrail involves. If you're using Claude Code or a similar agent, it can read this whole codebase in one pass; just point it at what you want changed.

Found a way to make Clippy operate a control it should refuse? That's the bug class this project cares most about — report it privately via SECURITY.md.

Release notes are in CHANGELOG.md.

← 一覧に戻る