Skip to content

v1.5.24

Choose a tag to compare

@github-actions github-actions released this 27 Oct 03:07
· 99 commits to main since this release
764ac70

Fixed

  • A refused call is logged and reported as refused. The safety gate logs
    safety.decision allow before the screenshot-binding and pause/own-UI
    guards run. When one of those then refused the call, nothing else was
    logged, so stderr showed only "allow" for a call that never ran. Those
    guards now log safety.refused with the guard and the reason, on the
    direct route and for each batch step. The session report (system report, clawdcursor report) counts refusals separately from errors and
    lists their reasons on their own, so a session where the pause guard did
    its job no longer reads "errors: 3". This covers a batch a guard halted and
    a call stopped by the consent prompt.

  • OCR confidence is the engine's own value or absent (#275). It was
    presented as a comparable per-word score, but:

    • Windows.Media.Ocr has no confidence, so every Windows word claimed 1.0;
    • macOS Vision returns a per-line level (0.3 / 0.5 / 1 in the shipped
      configuration, measured on a Mac), not a fine-grained score;
    • a missing value was read as 0, which made the word look unreadable.

    The Windows scripts no longer invent a value, and a missing score stays
    absent. The ui-map and smart_click paths treat no score as neutral, so
    Windows behaves as before. The ocr tool description says what the value
    means: low means the engine likely misread the text, and 1 does not mean
    the text is right.

  • clawdcursor doctor and the status check work on a Mac without the native
    helpers.
    When the helpers had not been built (no Xcode Command Line
    Tools), the permission check stopped at "ClawdCursor app binary not found"
    instead of falling back to its own probes, so doctor and status failed.
    It now falls back as intended. Asking for the permissions without the
    binary says how to build it.

  • Each compact action's required fields are published (#273). The
    compound schemas merge every action's fields and mark them all optional, so
    nothing said which action needs which: accessibility find_button with
    target (a real field of smart_click) passed the MCP layer and then failed
    on the missing intent. The action description of every compound now
    lists each action's required fields under the names it accepts, generated
    from the delegates (e.g. find_button: intent; find_field: purpose).

  • macOS: an open popover is no longer invisible (#273). With Freeform's
    "Insert Shape" popover open, read_tree, compile_ui, find_button,
    find and invoke saw the button that opened it and nothing inside it.
    AppKit puts an open popover under the control that presented it, and the
    walk never reads a button's children (they are decoration). It now reads
    them only for an open popover, in the helper and the JXA fallbacks. In the
    helper, a control with no title, description or text label is now named by
    its help text (tooltip), so icon-only buttons can be found by name.

  • The browser comes to the front when the agent opens a page (#277).
    browser actions work over CDP whatever the window order, so the browser
    the agent drove could stay hidden behind other apps for a whole session,
    and the person watching never saw it. New policy, on every OS: a
    successful navigate selects the agent's tab and raises that browser's
    window. The window is found by the process id of the browser the agent is
    connected to, so a second Chrome running alongside is never raised by
    mistake. Connecting alone stays quiet. If the
    raise fails, it is logged and the navigation still succeeds.

  • A failed capture or OCR read says so instead of passing for a real result.
    On macOS without Screen Recording, screenshots and OCR used to return an
    image of only the wallpaper and menu bar, which looked like a real but
    stale screen (#276). Every capture is now checked first and refused with
    "Screen Recording permission denied" (CAPTURE_DENIED). An OCR read that
    fails now reports its error. It used to come back as "No text detected",
    which hid the cause on macOS window reads (#274). A window that is partly
    off screen is read only where it is on screen, instead of shifting the
    region onto other pixels.

  • expect is checked on every action. Only some tools checked it; on the
    others (window, system, browser) the parameter wasn't even published,
    so it was stripped before arriving (live macOS: window focus with a failing
    expect said nothing). Every action except batch and task now publishes
    it. Actions that don't check it themselves get the same check after they
    run; a malformed expect is refused before anything runs.

  • The pill is the user's: the agent never reads, presses or types into it.
    On a live Mac, accessibility read_tree with the pill's process id returned
    its tree, and the pause prompt's Resume button could be found and invoked by
    name, which would have faked the user's answer. Now any call aimed at an
    overlay process (by pid, or by its process name) is refused (OWN_UI). While
    a pause waits for the user, every call is refused (PAUSED), reads included,
    except the ones that wait on, end or report the pause. This holds across
    processes: a pause shown by the daemon also stops a separate MCP server, and
    a new pause waits behind it rather than stacking a second prompt. The
    overlay never shows up in window lists, so a lookup by a shared name such as
    powershell cannot land on it. A done_when check that the prompt itself
    would satisfy (its text, or a button such as Resume) is rejected. On macOS,
    the pause prompt's reply box is no longer counted as an app that may be
    typed into.

  • A failed window focus says why, on every OS. On macOS, focusing by name
    or title while the screen was locked said "No matching window found." (the
    lock error was swallowed). It now refuses with the locked-screen message.
    Windows and Linux reported no reason at all: they now name the missing
    window, a missing wmctrl, or a window Windows would not bring to the front.
    Windows no longer sends a focus with nothing to aim at when no window
    matches the name.

  • A failed action keeps its own error. With an expect, a failure like
    "window not found" used to wait 2 s and then be reported as a DEVIATION
    ("it ran but the effect was not seen"), when nothing had run.

  • computer drag_path takes the array it is documented with. The schema said
    array, the code only accepted a JSON string, so every well-formed call failed
    and nothing could be drawn. A new test fails if two actions of one tool ever
    declare the same parameter with different types.

  • A failed window-title check names only the window in front, not every
    open app's title (other titles can hold private text).

  • Security: zod 4.6.7 (GHSA-mrhx-c7xc-m3w5, high) and body-parser 2.4.0
    (GHSA-27r3-jxmh-p828, high; under express).

  • The pill and glow are no longer in screenshots or OCR. They're for the
    person at the screen, but were real windows in every capture and sat over
    apps' toolbars. Now:

    • Windows: excluded from capture (SetWindowDisplayAffinity).
    • macOS: sharingType = .none, and the screenshot helper filters the
      clawd-overlay app out.
    • Linux: the pill steps aside for the capture (the glow stays; X11 and
      Wayland cannot exclude a window).
      Excluded windows still show on your own screen and take clicks. They are
      also left out of your own screenshots and of screen sharing (Teams, Zoom).
  • find that matches nothing says why. In a window with real structure it
    now says "no element named X among N named elements" and lists the closest
    names (as untrusted screen content). It used to claim the app had "little or
    no accessibility structure" (live macOS: Freeform has 34 named elements).
    That advice is now given only for genuinely thin windows.

  • Found in a live macOS test run:

    • A password field's text is never echoed. Typing into one now
      reports into a password field (not echoed); the reply used to repeat
      the secret.
    • No more queued, stale pause prompts. A pause_for_user with a
      different message while another is on screen returns busy right
      away, instead of queuing a prompt that would surface later.
    • expect passed to a tool that does not check it is reported as
      ignored,
      instead of being dropped silently.
    • copy_all_text returns a document's text exactly when there is
      nothing to clean: blank and space-only lines are kept.
    • Typed character counts count an emoji as one.

Added

  • Typing leaves your clipboard alone, and reads the field back. Plain
    text up to 120 characters is typed as keystrokes; the clipboard is never
    read or written. Longer text, or text with a newline, tab or non-ASCII
    character, is still pasted as literal text (verified, clipboard restored).
    After typing, the focused field is read back. If it shows the text, the
    result says (keys, read back ✓) and counts as [confirmed]. Before a
    submit (text ending in a newline), Return is pressed only when the field
    ends with the typed text; otherwise it is not pressed (READBACK_MISMATCH)
    and the result shows what the field holds, as untrusted text, so the caller
    can decide. Password fields and fields that expose no text are not judged.
    On Linux/Wayland, where the typing helpers would show the text in the
    process list, text is pasted, and a failed paste stops rather than types.

  • Screenshot-bound clicks. Each screenshot now has an id (s3), and
    remembers which windows existed. An image-space click, drag or scroll is
    refused before anything moves when it names an older screenshot, when there
    is no screenshot at all, or when a window the screenshot did not show is in
    front (a dialog or another app opened). Clicking into a window that was on
    it is fine. Limits: where the platform gives no window handles (macOS),
    windows are told apart by process; a second taskbar click from one
    screenshot can be refused (the taskbar is not a listed window). The refusal says so
    (STALE_SCREENSHOT) and suggests a fresh screenshot. This applies inside a
    batch too. Accessibility coordinates (space:"screen") and actions by
    name are unaffected. computer takes an optional shot to name the
    screenshot.

  • Every action result and every error says what happened, in one line.
    [confirmed] (an expect check saw the effect), [unverified] (it ran,
    nothing checked it), [refused · CODE …] (it did not run: safety gate,
    consent, locked screen, a system dialog has the keyboard) or
    [failed · CODE · hint · next]. The codes are stable (NOT_FOUND,
    TIMEOUT, STALE_REF, DEVIATION, INVALID_ARGS,
    NEEDS_CONFIRMATION, …), and next is a safe call in the caller's own
    tool names. MCP results get it on every action (not on reads, or on
    calls that return a value such as build_uri); the built-in agent on
    errors only, so successful steps cost its model nothing. JSON results and
    batch reports are unchanged.