Repository navigation
v1.5.25
Changed
- A step the agent may not take is handed over, not the whole task. Agents
turned down whole tasks (an APNs key, an App Store review account, notarization)
because one step was something their own rules forbid: creating an account,
downloading a private key, entering a secret. The MCP instructions, the
pause_for_userdescription and the skill now say that such a step is a
roadblock like a sign-in: hand over that step, as wide as the agent's rules draw
it, and do the rest they allow. When a secret must go into a field or a terminal
prompt, the agent puts the cursor there and asks only for the paste ("Paste your
app-specific password, press Enter, then click Resume"),
then passes the saved key's file path or keychain profile name, never the secret. - The daemon binds
127.0.0.1only, and--allow-remoteis gone (#293).
server.hostin the config was never read, so the daemon always bound
loopback and--allow-remotenever did anything. Rather than open the
desktop-control port to the network, the flag and theserver.hostsetting
are removed. To drive clawdcursor from another machine, tunnel the port:
ssh -L 3847:127.0.0.1:3847 user@host.
Security
- Dependency advisory cleared.
follow-redirects(pulled in through
jimp) is updated to 1.16.2 for GHSA-mrwp-f3q8-3g9p (high). Lockfile only.
Fixed
-
A stop really stops, and keys go only to the agent's window (#294). An
agent queued a batch: wait 30 s, then Ctrl+L and paste a URL with Enter.
During the wait the user stopped clawdcursor and switched to the Claude app.
The keys and the URL landed in the Claude app, and every step said ok. There
were three causes:- "Stop" was not a state. The pill's double-click ended the stdio server, and
the host started a fresh one on the agent's next call, which knew nothing of
the stop.clawdcursor stopcould not reach stdio servers at all. - Nothing checked which window was in front before a key, a paste or a click.
- The pill hides 30 s after the last action, and a wait is not an action, so
during the wait there was no pill to double-click.
Now a stop (the pill,
clawdcursor stop, or the dashboard's Stop) is shared by
every clawdcursor process and survives a restart:- every call answers "stopped by the user", a running
waitends at once, the
rest of a batch does not run, and a call already running is refused at its
next key, click, element action, window change or page action; - only the user gives control back: their Resume on the agent's next
pause_for_userprompt,clawdcursor resume, or starting the daemon. The
daemon no longer exits on a double-click.
Every key, paste, click, drag and scroll first checks that the window in front
is still the one the agent was working in. If it is not, nothing is sent and
the agent is told "foreground changed: you were working in msedge, but claude
is in front now". A new window within 5 s of the agent's own click, Return or
shortcut is the agent's own doing; a change after a longer gap is the user's.
window focusbinds the agent to a window on purpose.A batch that acts at any step shows the pill from its start, and the pill
stays up while a call is still running. - "Stop" was not a state. The pill's double-click ended the stdio server, and
-
macOS: a capture without Screen Recording is refused on every install,
anddoctorasks the same question (#276). 1.5.24 said every capture is
checked first, but it checked only when the screenshot helper was built.
An npm install without the Xcode Command Line Tools has no helper, so the
check was skipped and screenshots and OCR still returned the wallpaper and
menu bar. With no helper, macOS's own permission check
(CGPreflightScreenCaptureAccess) is now asked throughosascript, which
needs no Command Line Tools and captures nothing (no prompt, no flash). The
function is bound by hand: CoreGraphics' scripting bridge does not declare
it, and on macOS 26.5 the plain call failed, so the check never answered. A
denial isCAPTURE_DENIED. A grant is remembered for the process, so
captures no longer each start a check. A denial, a check that could not
answer, and a helper that would not run are never remembered, and a failed
helper capture forgets the grant. When the check cannot answer, the capture
still goes ahead, and thecomputer screenshotandzoomreplies now say
that Screen Recording could not be checked: the stderr warning never
reached an MCP agent.doctorand status asked
ClawdCursor.app's own entry, which captures never use: on a real Mac they
printed "DENIED ... enable ClawdCursor" while captures worked. They now
run the capture check, say "could not check" when it cannot answer, and
name the app to enable: the app running clawdcursor.doctornotes that
its answer is for its own terminal, and that the MCP server captures as its
host app (e.g. Claude), which needs its own grant. The denial says that a server started
without an app (launchd, ssh) needs node and screenshot-helper enabled
instead. The build hint no longer sayscd native && ./build.sh, which
fails from an npm install: it namesxcode-select --installand the
package's own build script by its full path. -
server.portin the config is used (#293). The daemon only read a flat
"port", and--portalways defaulted to 3847, which outranked the config
file.{"server":{"port":N}}and{"port":N}now both work,--portstill
wins when given, and the "port already in use" check looks at the port the
daemon will really bind. The files are read in layer order, so a flatport
in the project's.clawdcursor-config.jsonoutranks a nestedserver.port
in~/.clawdcursor/config.json.stop,resumeandtaskfind the daemon
on the port it recorded in its own lock file (~/.clawdcursor/start.pid,
used only while that process is alive), else 3847. Like the token file, the
lock is mode 0600 on macOS and Linux; on Windows it inherits your user
profile's permissions. They never
read the port from a config file, so a repo you run them in cannot redirect
the bearer token to another port. A--portthat is not a whole number from
1 to 65535 is refused with "Invalid port number" on every command. -
--no-visionkeeps screenshots from every model. The flag (and
CLAWD_DISABLE_VISION=1/"disableVision": true) was read and then
ignored, so screenshots still went to the model. Now the built-in agent is
not offered a screenshot tool, even inside a batch, its instructions no
longer mention screenshots, and it never sends an image. The MCP surface
(HTTP daemon, and stdio for the env var or config key) refuses any call or
batch step that would return an image. Accessibility and OCR still work. The unused
CLAWD_DISABLE_VERIFIER/disableVerifiersetting is removed; the
verifier it switched off no longer exists. -
The destructive-label rule checks every element
invoke_elementmay act
on. The gate took the first non-empty of target/name/text/label/title/
selector. It never looked atautomationId, and it only looked at an
element_idref when no name was given.invoke_elementacts on the ref
first, thenname, thenautomationId. So{automationId:"Send"}, or
{name:"Reply", element_id:<the Send button>}, pressed Send with no
confirmation. The MCP gate, the agent loop and itsbatchnow check every
selector present, each on its own, and the strictest decision wins: any one
that matches (Send, Delete, Pay…) asks for confirmation, unless the user's
task asked for that same action. -
A key combo that isn't a string can't skip the keyboard gate. The
safety gate classifiedcombo/keyonly when it was a string, while the key
tool pressedString(value). Abatchstep, which gets no per-step schema
check, withkey: ["alt+f4"]therefore skipped the confirm tier and pressed
Alt+F4. The gate now reads a non-string value the way the handlers do, and
the key tool refuses one outright. -
The key blocklist matches a combo however its modifiers are spelled. It
compared spellings, while the executors accept aliases:control,
option/opt,escape, andsuper/meta/windows/cmd/commandfor
the OS's super key. Sosuper+l,control+shift+escapeandoption+f4
matched nothing, passed the safety gate and the hard-block backstop, and were
pressed as Win+L, Ctrl+Shift+Esc and Alt+F4. The blocklist now reads each
+-separated token whole, as the executors do. It resolves every spelling an
executor accepts, including the nut-js key names, left/right variants
(LeftWin,rightctrl,super_l) andforwarddelete, and puts modifiers in
one order before matching. It classifies a super-family
token as what this OS presses for it: Command on macOS, the Super key on
Linux (socmd+lis blocked there: it locks the screen), and on Windows the
Windows key forsuper/winbut Ctrl forcmd/command/meta. The two
Windows executors used to disagree on that (one pressedcmd+las Ctrl+L,
the other as Win+L); both now press Ctrl, so a Mac-trained model'scmd+lis
the address bar on Windows, not the lock screen. -
shortcuts_executegates the chord it resolves. The safety gate saw only
{intent, context}, and the chord the intent resolved to was then pressed
with no blocklist or destructive-label check. Soclose windowpressed Alt+F4
andsend emailpressed the send shortcut with no confirmation. The resolved
chord now goes through the same gate askey_press, with the shortcut's intent
as the label. A blocked chord is refused. A confirm-tier chord, or an intent
like send/delete, returnssafety confirmand says to press the chord with
key_pressonce the user approves. -
A compound action is gated like the granular tool it runs. The gate took
a compound action's tier from its own name table. That table hadopen_file
andnavigate_browserat input tier, while both tools declare tier 2. So
window/system {action:"open_file"}andwindow/browser {action:"navigate"}ran without the confirmation the granular tools ask for.
The gate now never goes below the declared tier of the tool a compound action
dispatches to. The projectedminimize_window_to_taskbardeclared tier 2,
against the tier 1 its own source and thewindowcompound give it. It is
now tier 1, so minimize stays unconfirmed on both surfaces. -
macOS:
window listsays which apps have windows on another desktop
Space (#278). The accessibility API only sees the windows of the Space on
screen. With one hop to a full-screen Space, the list read "Windows (2)"
while a whole desktop of windows sat on Desktop 1, and nothing said the
list was incomplete. The helper now finds those windows with CGWindowList
plus the WindowServer's Spaces lookup. The list ends with a line naming the
apps whose windows are on another Space, and it notes thatwindow focus
on one of them switches the screen to that Space. On a macOS where the
Spaces lookup isn't available, nothing is claimed either way.