Skip to content

v2.6.0

Choose a tag to compare

@crftwr crftwr released this 21 Oct 01:18
· 55 commits to main since this release

Keyhac 2.6.0

If you use the AI skills, replace them. The two skills,
keyhac-key-table-configuration and keyhac-action-authoring, are now one
skill, keyhac, shipped as keyhac-2.6.0-skill.zip. Remove the two old
ones when you install it.
If you leave them installed, they answer the same
requests with an older API.

If you use focus_path_pattern= on Windows, your tables now follow the
focus inside a window.
Keyhac used to re-read the focused element only when
the window, its focused control or its title changed. So a table could stay
active while you tabbed around inside one browser page or Electron app. Now
it is read on every key, as on macOS. A table that relied on the old coarse
matching switches off when focus leaves the matched element.

If you write actions, two things change under them. On macOS, an element
read that times out against a hung application now raises Unresponsive
instead of returning None, as on Windows. Waits treat it as "not yet" and
retry. And Keyhac's own windows (console, chooser) no longer exist to the
API: window lookups skip them, Focus.element is None while Keyhac is in
front, and window actions do nothing on the console.

If you use a password manager, clear your clipboard history once.
Passwords copied before this release may already be in it (see below).

  • The macOS app launches on macOS 26 again. Keyhac 2.5.0 showed a version
    mismatch and a prohibited icon on macOS 26, because its launcher was built for
    the build machine's macOS rather than the 11.0 it declares. The bundle is now
    built for its stated minimum, the build refuses anything newer, and the
    installed app stays correctly signed instead of failing codesign --verify
    after its first run.
  • Clipboard history keeps rich text, images and files. An entry used to be
    its text alone, so pasting from history flattened formatting and an image-only
    copy was not recorded at all. Entries now keep RTF/HTML, one image and file
    lists. Image copies appear as Image 1280 × 720, and files are labelled by
    name. Option/Alt-Enter pastes the text alone. Only text and file entries are
    written to disk; images and formatting live for the session, within a 64 MB
    budget (max_session_data_size).
  • The chooser previews the selected row. Rest on a row for a moment and a
    window beside the chooser shows it: the image, the full text or the file paths
    of a clipboard entry, a snippet's text, a clipboard tool's converted result,
    or an action's description. Custom sources can offer one through
    CandidateSource.preview().
  • Shift-Delete removes a clipboard history entry. Select the entry in the
    clipboard chooser and press Shift-Delete.
  • Clipboard history leaves a password manager's copy alone. Copies marked
    as concealed or transient (macOS) or excluded from clipboard history
    (Windows) were recorded like any other, and kept in clipboard.json. They
    are now never read or recorded, and an action that saves and restores the
    clipboard puts such content back with its marker.
  • The tray shows a running action and unread errors. While an action runs,
    the tray icon animates and its menu offers Running: X — Stop. Errors you
    have not seen put a red dot on the icon and an Open Console entry in the
    menu.
  • A hung application costs one short wait, not the key hook. Every UI read
    is capped at 250 ms on both OSes, and a key event pays at most one timeout.
    Key tables fall back to matching the application alone, and the full focus
    path returns on the first key after the application answers again.
  • Actions run on their own thread, everywhere. Element reads, waits, window
    lookups and the ui verbs now run on the caller's thread, so a run() no
    longer needs to hop to the main thread for them.
  • The MCP tools are easier to author with. start_action takes
    constructor arguments for one run (try an action on one item first), and
    runs the edited code when only an imported file changed. describe_screen
    takes within= and cuts replies too large for the client, read_text pages
    through long text, find_elements says when a match is ambiguous, and the
    tools carry read-only and destructive hints.
  • read_text reads all of a long text field on Windows. It used to stop at
    4,096 characters in a native Edit and read some fields only through their
    Value; it now reads the whole document and never reads a password field.

Also: an action's click retry stops when its target has gone instead of pressing
behind a modal; Front(node=) and activate(node=) name one window; injected
macOS clicks hold the button down for 20 ms, so Safari no longer drops some of
them; the guide explains that with the top row on media keys, macOS F1 arrives
as Fn-F1; a failed reload keeps the previous key tables; and the authoring
skill and examples were reworked throughout.

Full Changelog: v2.5.0...v2.6.0