A native Node.js module with Node-API that allows monitoring text selections across applications using multiple methods.
Maybe the first-ever open-source, fully functional text selection tool.
- Cross-application text selection monitoring
- Capture selected text content and its screen coordinates
- Auto-triggers on user selection, or manual API triggers
- Rich API to control the selection behaviors
- Input event listeners
- Mouse events:
down/up/wheel/movewith buttons information - Keyboard events:
keydown/keyupwith keys information - No additional hooks required – works natively.
- Mouse events:
- Multi-method to get selected text (automatic fallback):
- For Windows:
- UI Automation (modern apps)
- Accessibility API (legacy apps)
- For macOS:
- Accessibility API (AXAPI)
- For all platforms:
- Clipboard fallback (simulated
Ctrl + C/⌘ + Cwith optimizations when all other methods fail)
- Clipboard fallback (simulated
- For Windows:
- Clipboard
- Read/write clipboard
- Compatibility
- Node.js
v10+| Electronv3+ - TypeScript support included.
- Node.js
| Platform | Status |
|---|---|
| Windows | ✅ Fully supported. Windows 7+ |
| macOS | ✅ Fully supported. macOS 10.14+ |
| Linux | 🚧 Coming soon |
npm install selection-hooknpm run demoThe npm package ships with pre-built .node files in prebuilds/* — no rebuilding needed.
- Use
npm run rebuildto build your platform's specific package. - Use
npm run prebuildto build packages for all the supported platforms.
When building, if the ModuleNotFoundError: No module named 'distutils' error prompt appears, please install the necessary Python library via pip install setuptools.
When using electron-builder for packaging, Electron will forcibly rebuild Node packages. In this case, you may need to run npm install in ./node_modules/selection-hook in advance to ensure the necessary packages are downloaded.
When using electron-forge for packaging, you can add these values to your electron-forge config to avoid rebuilding:
rebuildConfig: {
onlyModules: [],
},const SelectionHook = require("selection-hook");
// Create a new instance
// You can design it as a singleton pattern to avoid resource consumption from multiple instantiations
const selectionHook = new SelectionHook();
// Listen for text selection events
selectionHook.on("text-selection", (data) => {
console.log("Selected text:", data.text);
// For mouse start/end position and text range coornidates
// see API Reference below.
});
// Start monitoring (with default configuration)
selectionHook.start();
// When you want to get the current selection directly
const currentSelection = selectionHook.getCurrentSelection();
if (currentSelection) {
console.log("Current selection:", currentSelection.text);
}
// Stop, you can start it again
selectionHook.stop();
// Clean up when done
selectionHook.cleanup();See examples/node-demo.js for detailed usage.
const hook = new SelectionHook();Start monitoring text selections.
Config options (with default values):
{
debug?: false, // Enable debug logging
enableMouseMoveEvent?: false, // Enable mouse move tracking, can be set in runtime
enableClipboard?: true, // Enable clipboard fallback, can be set in runtime
selectionPassiveMode?: false, // Enable passive mode, can be set in runtime
clipboardMode?: SelectionHook.FilterMode.DEFAULT, // Clipboard mode, can be set in runtime
clipboardFilterList?: string[] // Program list for clipboard mode, can be set in runtime
globalFilterMode?: SelectionHook.FilterMode.DEFAULT, // Global filter mode, can be set in runtime
globalFilterList?: string[] // Global program list for global filter mode, can be set in runtime
}see SelectionHook.FilterMode for details
For macOS: macOS requires accessibility permissions for the selection-hook to function properly. Please ensure that the user has enabled accessibility permissions before calling start().
- Node: use
selection-hook'smacIsProcessTrustedandmacRequestProcessTrustto check whether the permission is granted. - Electron: use
electon'ssystemPreferences.isTrustedAccessibilityClientto check whether the permission is granted.
Stop monitoring text selections.
Get the current text selection if any exists.
Enable mouse move events (high CPU usage). Disabled by default.
Disable mouse move events. Disabled by default.
Enable clipboard fallback for text selection. Enabled by default.
Disable clipboard fallback for text selection. Enabled by default.
Configure how clipboard fallback works with different programs. See SelectionHook.FilterMode constants for details.
Configure which applications should trigger text selection events. You can include or exclude specific applications from the selection monitoring. See SelectionHook.FilterMode constants for details.
Windows Only
Configure fine-tuned lists for specific application behaviors. This allows you to customize how the selection hook behaves with certain applications that may have unique characteristics.
For example, you can add acrobat.exe to those lists to enable text seleted in Acrobat.
List types:
EXCLUDE_CLIPBOARD_CURSOR_DETECT: Exclude cursor detection for clipboard operationsINCLUDE_CLIPBOARD_DELAY_READ: Include delay when reading clipboard content
See SelectionHook.FineTunedListType constants for details.
Set passive mode for selection (only triggered by getCurrentSelection, text-selection event will not be emitted).
Write text to the system clipboard. This is useful for implementing custom copy functions.
Read text from the system clipboard. Returns clipboard text content as string, or null if clipboard is empty or contains non-text data.
macOS Only
Check if the process is trusted for accessibility. If the process is not trusted, selection-hook will still run, but it won't respond to any events. Make sure to guide the user through the authorization process before calling start().
macOS Only
Try to request accessibility permissions. This MAY show a dialog to the user if permissions are not granted.
Note: The return value indicates the current permission status, not the request result.
Check if selection-hook is currently running.
Release resources and stop monitoring.
Emitted when text is selected, see TextSelectionData for data structure
hook.on("text-selection", (data: TextSelectionData) => {
// data contains selection information
});Mouse events, see MouseEventData for data structure
hook.on("mouse-XXX", (data: MouseEventData) => {
// data contains mouse coordinates and button info
});Mouse wheel events, see MouseWheelEventData for data structure
hook.on("mouse-wheel", (data: MouseWheelEventData) => {
// data contains wheel direction info
});Keyboard events, see KeyboardEventData for data structure
hook.on("key-XXX", (data: KeyboardEventData) => {
// data contains key code and modifier info
});Hook status changes
hook.on("status", (status: string) => {
// status is a string, e.g. "started", "stopped"
});Error events
Only display errors when debug set to true when start()
hook.on("error", (error: Error) => {
// error is an Error object
});Note: All coordinates are in physical coordinates (virtual screen coordinates) in Windows. You can use screen.screenToDipPoint(point) in Electron to convert the point to logical coordinates. In macOS, you don't need to do extra work.
Represents text selection information including content, source application, and coordinates.
| Property | Type | Description |
|---|---|---|
text |
string |
The selected text content |
programName |
string |
Name of the application where selection occurred |
startTop |
Point |
First paragraph's top-left coordinates (px) |
startBottom |
Point |
First paragraph's bottom-left coordinates (px) |
endTop |
Point |
Last paragraph's top-right coordinates (px) |
endBottom |
Point |
Last paragraph's bottom-right coordinates (px) |
mousePosStart |
Point |
Mouse position when selection started (px) |
mousePosEnd |
Point |
Mouse position when selection ended (px) |
method |
SelectionMethod |
Indicates which method was used to detect the text selection. |
posLevel |
PositionLevel |
Indicates which positional data is provided. |
isFullscreen |
boolean |
macOS Only Whether the window is in fullscreen mode |
Type Point is { x: number; y: number }
When PositionLevel is:
MOUSE_SINGLE:onlymousePosStartandmousePosEndis provided, andmousePosStartequalsmousePosEndMOUSE_DUAL: onlymousePosStartandmousePosEndis providedSEL_FULL: all the mouse position and paragraph's coordinates are provided
Contains mouse click/movement information in screen coordinates.
| Property | Type | Description |
|---|---|---|
x |
number |
Horizontal pointer position (px) |
y |
number |
Vertical pointer position (px) |
button |
number |
Same as WebAPIs' MouseEvent.button 0=Left, 1=Middle, 2=Right, 3=Back, 4=Forward -1=None, 99=Unknown |
If button != -1 when mouse-move, which means it's dragging.
Describes mouse wheel scrolling events.
| Property | Type | Description |
|---|---|---|
button |
number |
0=Vertical, 1=Horizontal scroll |
flag |
number |
1=Up/Right, -1=Down/Left |
Represents keyboard key presses/releases.
| Property | Type | Description |
|---|---|---|
uniKey |
string |
Unified key name, refer to MDN KeyboardEvent.key, converted from vkCode |
vkCode |
number |
Virtual key code. Definitions and values vary by platforms. |
sys |
boolean |
Whether modifier keys (Alt/Ctrl/Win/⌘/⌥/Fn) are pressed simultaneously |
scanCode |
number? |
Hardware scan code. Windows Only |
flags |
number |
Additional state flags. |
type |
string? |
Internal event type |
action |
string? |
"key-down" or "key-up" |
About vkCode:
- Windows: VK_* values of vkCode
- macOS: kVK_* values of kCGKeyboardEventKeycode
Indicates which method was used to detect the text selection:
NONE: No selection detectedUIA: UI Automation (Windows)ACCESSIBLE: Accessibility interface (Windows)AXAPI: Accessibility API (macOS)CLIPBOARD: Clipboard fallback
Indicates which positional data is provided:
NONE: No position informationMOUSE_SINGLE: Only single mouse positionMOUSE_DUAL: Mouse start and end positions (when dragging to select)SEL_FULL: Full selection coordinates (seeTextSelectionDatastructure for details)SEL_DETAILED: Detailed selection coordinates (reserved for future use)
Before version v0.9.16, this variable was named ClipboardMode
DEFAULT: The filter mode is disabledINCLUDE_LIST: Only the programs in list will pass the filterEXCLUDE_LIST: Only the progrmas NOT in in list will pass the filter
Defines types for fine-tuned application behavior lists:
EXCLUDE_CLIPBOARD_CURSOR_DETECT: Exclude cursor detection for clipboard operations. Useful for applications with custom cursors (e.g., Adobe Acrobat) where cursor shape detection may not work reliably.INCLUDE_CLIPBOARD_DELAY_READ: Include delay when reading clipboard content. Useful for applications that modify clipboard content multiple times in quick succession (e.g., Adobe Acrobat).
This module includes TypeScript definitions. Import the module in TypeScript as:
import {
SelectionHookConstructor,
SelectionHookInstance,
SelectionConfig,
TextSelectionData,
MouseEventData,
MouseWheelEventData,
KeyboardEventData,
} from "selection-hook";
// use `SelectionHookConstructor` for SelectionHook Class
const SelectionHook: SelectionHookConstructor = require("selection-hook");
// use `SelectionHookInstance` for SelectionHook instance
const hook: SelectionHookInstance = new SelectionHook();See index.d.ts for details.
This project is used by:
- Cherry Studio: A full-featured AI client, with Selection Assistant that conveniently enables AI-powered translation, explanation, summarization, and more for selected text. (This lib was originally developed specifically for Cherry Studio, which showcases the best practices for using)