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/move - Keyboard events:
keydown/keyup - No additional hooks required – works natively.
- Mouse events:
- Multi-method text extraction (automatic fallback):
- UI Automation (modern apps)
- Accessibility APIs (legacy apps)
- Focused control (active input fields)
- Clipboard fallback (simulated
Ctrl+Cwith optimizations)
- Clipboard
- Read/write clipboard
- Compatibility
- Node.js
v10+| Electronv3+ - TypeScript support included.
- Node.js
- Windows: Full support with UI Automation and Accessibility APIs
- macOS: Full support with Accessibility APIs and Quartz Event Taps
- Linux: Coming soon
npm install selection-hookThe npm package ships with a pre-built .node file — no rebuilding needed. For Electron rebuild issues, add these values to your electron-forge config to avoid rebuilding:
rebuildConfig: {
onlyModules: [],
},When building, if the ModuleNotFoundError: No module named 'distutils' error prompt appears, please install the necessary Python library via pip install setuptools.
The same demo works on both Windows and macOS:
npm run demoNote for macOS users: You need to grant Accessibility permissions:
- Open System Preferences > Security & Privacy > Privacy > Accessibility
- Add and enable your terminal application (Terminal.app, iTerm.app, etc.)
- Restart the demo
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
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.
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.
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.
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. |
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 |
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 |
|---|---|---|
sys |
boolean |
System key pressed (Alt/Ctrl/Win) |
vkCode |
number |
Windows virtual key code |
scanCode |
number |
Hardware scan code |
flags |
number |
Additional state flags |
type |
string? |
Internal event type |
action |
string? |
"key-down" or "key-up" |
Indicates which method was used to detect the text selection:
NONE: No selection detectedUIA: UI AutomationFOCUSCTL: Focused controlACCESSIBLE: Accessibility interfaceCLIPBOARD: 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.