Clipboard SDK
Clipboard SDK
Overview
The Clipboard SDK lets plugins access system clipboard features, including:
- Basic operations: read/write clipboard content (text, HTML, images, files)
- History management: query, search, and delete clipboard history
- Copy & paste: write content to clipboard and auto-paste into the active app
- Selected text: capture the active app's current text selection without leaving clipboard mutations behind
- Automatic tags: classify text content (URL, API Key, Token, account/password, email) for quick matching
All operations are executed in the main process via TuffTransport to avoid WebContents focus issues.
Communication Strategy (Transport First)
useClipboard()now usesClipboardEvents.*as the primary transport domain (getHistory,read,copyAndPaste, etc.).- Clipboard SDK no longer relies on
clipboard:*raw channel events as the main path. - Plugin code must use the SDK/typed transport entry points. Historical raw
clipboard:*channel names are migration references only, not a supported extension surface. system.captureSelection()uses the typed App/System event and requires a verified plugin withclipboard.read; it does not expose a raw selection channel.
Introduction
Quick Start
import { system, useClipboard } from '@talex-touch/utils/plugin/sdk'
const clipboard = useClipboard()
// Write text
await clipboard.writeText('Hello World')
// Read clipboard
const content = await clipboard.read()
console.log(content.text, content.formats)
// Copy and paste to active app
await clipboard.copyAndPaste({ text: 'Pasted content' })
// Capture selected text from the active app
const selection = await system.captureSelection()
if (!selection.text) console.warn(selection.issueCode)
API Reference
useClipboard()
Returns a unified clipboard SDK instance.
const clipboard = useClipboard()
Selected Text Capture
system.captureSelection() / captureSelectedText()
Capture the current text selection from the active application. The host verifies plugin identity and the clipboard.read permission before touching accessibility APIs, shortcuts, or the clipboard. macOS prefers AXSelectedText; the fallback snapshots every clipboard format, issues the platform copy shortcut, and restores the snapshot.
The result includes text, supportLevel, capturedAt, and optional issueCode, issueMessage, and limitations. Treat empty, disabled, failed, and unsupported as explicit non-success states. Do not write selected text to ordinary logs, persistent history, or audit metadata.
import { system } from '@talex-touch/utils/plugin/sdk'
const result = await system.captureSelection()
if (!result.text) {
console.warn(result.issueCode, result.issueMessage)
return
}
// Use result.text only for the user-triggered action.
Basic Operations
writeText(text)
Write plain text to the clipboard.
await clipboard.writeText('Hello World')
write(options)
Write multiple formats to the clipboard.
// Text + HTML
await clipboard.write({
text: 'Hello',
html: '<b>Hello</b>'
})
// Image (data URL)
await clipboard.write({
image: 'data:image/png;base64,...'
})
// Files
await clipboard.write({
files: ['/path/to/file.txt', '/path/to/image.png']
})
Parameters:
| Field | Type | Description |
|---|---|---|
text | string | Plain text |
html | string | HTML content |
image | string | Image data URL |
files | string[] | File paths |
read()
Read current clipboard content.
const content = await clipboard.read()
// {
// text: 'Hello',
// html: '<b>Hello</b>',
// hasImage: false,
// hasFiles: false,
// formats: ['text/plain', 'text/html']
// }
Returns:
| Field | Type | Description |
|---|---|---|
text | string | Text content |
html | string | HTML content |
hasImage | boolean | Whether image exists |
hasFiles | boolean | Whether files exist |
formats | string[] | Available formats |
readImage()
Read image from clipboard.
const image = await clipboard.readImage()
if (image) {
console.log(image.dataUrl, image.width, image.height)
}
Returns: { dataUrl: string, width: number, height: number } | null
getHistoryImageUrl(id)
Resolve the original image URL (tfile://) for a history item to avoid large base64 payloads in plugin code.
const url = await clipboard.getHistoryImageUrl(123)
if (url) {
console.log('original image:', url)
}
history.annotate({ id, note, tags })
Writes the user's own note and tags onto a history item.
The two fields are independent: sending only note leaves the tags alone and vice versa, so an editor for one does not have to hold the other to avoid wiping it. Pass null or an empty string to clear the note, an empty array to clear the tags.
Resolves with what was actually stored — the main process trims, collapses whitespace, de-duplicates case-insensitively and applies the caps (200 characters for the note, 24 per tag, 12 tags). Render the result rather than the text that was typed.
Annotations live in the record's metadata, which the keyword search already matches, so a tag is searchable as soon as it is written.
const { note, tags } = await clipboard.history.annotate({
id: 123,
note: 'production key for ego lite',
tags: ['prod', 'openai'],
})
Returns: { updated: boolean, note: string | null, tags: string[] }. updated is false when no such record exists.
previewHistoryImage(id)
Hand a history image item to the operating system's own previewer (Preview on macOS, the registered default application elsewhere).
Takes a record id rather than a path: the main process resolves the file inside its own clipboard image directory, so a plugin cannot use this to open anything outside it. Returns false when the record has no stored image left.
const opened = await clipboard.previewHistoryImage(123)
if (!opened) {
console.warn('this record has no image left to preview')
}
Returns: boolean
readFiles()
Read file paths from clipboard.
const files = await clipboard.readFiles()
// ['/path/to/file1.txt', '/path/to/file2.png']
clear()
Clear the clipboard.
await clipboard.clear()
Copy and Paste
copyAndPaste(options)
Write content to the clipboard and simulate paste into the active app.
// Paste text
await clipboard.copyAndPaste({ text: 'Hello' })
// Paste formatted text
await clipboard.copyAndPaste({
text: 'Hello',
html: '<b>Hello</b>'
})
// Paste image
await clipboard.copyAndPaste({
image: 'data:image/png;base64,...'
})
// Paste files
await clipboard.copyAndPaste({
files: ['/path/to/file.txt']
})
// Custom delay and behavior
await clipboard.copyAndPaste({
text: 'Hello',
delayMs: 200, // delay before paste (default 150ms)
hideCoreBox: true // hide CoreBox before paste (default true)
})
Parameters:
| Field | Type | Description |
|---|---|---|
text | string | Text content |
html | string | HTML content |
image | string | Image data URL |
files | string[] | File paths |
delayMs | number | Delay before paste |
hideCoreBox | boolean | Hide CoreBox before paste |
Returns: Promise<boolean> - whether the operation succeeded
History
Access history operations via clipboard.history.
history.getLatest()
Get the latest clipboard item.
const latest = await clipboard.history.getLatest()
if (latest) {
console.log(latest.type, latest.content)
}
history.getHistory(options)
Get clipboard history with pagination.
const { history, total, page, pageSize } = await clipboard.history.getHistory({
page: 1,
pageSize: 20
})
history.searchHistory(options)
Advanced search.
// Keyword search
const result = await clipboard.history.searchHistory({
keyword: 'hello'
})
// Filter by type
const textItems = await clipboard.history.searchHistory({
type: 'text'
})
// Time range
const recent = await clipboard.history.searchHistory({
startTime: Date.now() - 24 * 60 * 60 * 1000
})
// Combined filters
const filtered = await clipboard.history.searchHistory({
type: 'text',
isFavorite: true,
sourceApp: 'com.apple.Safari',
page: 1,
pageSize: 10
})
Search parameters:
| Field | Type | Description |
|---|---|---|
keyword | string | Content keyword |
type | 'text' | 'image' | 'files' | Type filter |
startTime | number | Start timestamp |
endTime | number | End timestamp |
isFavorite | boolean | Favorite filter |
sourceApp | string | Source app |
page | number | Page number |
pageSize | number | Page size |
sortOrder | 'asc' | 'desc' | Sort order |
history.setFavorite(options)
Set favorite status.
await clipboard.history.setFavorite({
id: 123,
isFavorite: true
})
history.deleteItem(options)
Delete a history item.
await clipboard.history.deleteItem({ id: 123 })
history.clearHistory()
Clear all history.
await clipboard.history.clearHistory()
Listen to Clipboard Changes
history.onDidChange(callback)
Listen to clipboard changes.
Important: Plugins must call
box.allowClipboard(types)first, otherwise no events are emitted.
import { useBox, ClipboardType } from '@talex-touch/utils/plugin/sdk'
const box = useBox()
const clipboard = useClipboard()
// 1. Enable clipboard monitoring
await box.allowClipboard(ClipboardType.TEXT | ClipboardType.IMAGE)
// 2. Register listener
const unsubscribe = clipboard.history.onDidChange((item) => {
console.log('Clipboard changed:', item.type, item.content)
})
// 3. Stop listening
unsubscribe()
ClipboardType enum:
| Value | Binary | Description |
|---|---|---|
TEXT | 0b0001 | Description for TEXT. |
IMAGE | 0b0010 | Image |
FILE | 0b0100 | File |
Presets:
import { ClipboardTypePresets } from '@talex-touch/utils/plugin/sdk'
// Text only
await box.allowClipboard(ClipboardTypePresets.TEXT_ONLY)
// Text + image
await box.allowClipboard(ClipboardTypePresets.TEXT_AND_IMAGE)
// All types
await box.allowClipboard(ClipboardTypePresets.ALL)
Clipboard Item Shape
interface PluginClipboardItem {
id?: number
type: 'text' | 'image' | 'files'
content: string // text / image dataURL / file paths JSON
thumbnail?: string // thumbnail dataURL
rawContent?: string // HTML raw content
sourceApp?: string // source app
timestamp?: Date // timestamp
isFavorite?: boolean // favorite
meta?: Record<string, unknown> // metadata (including tags)
}
Automatic Tags (tags)
When clipboard content is text, the system applies lightweight rules and stores tags in meta.tags.
Tags describe categories only and never include raw sensitive values.
Current tags:
url: URL/linkapi_key: API key patternstoken: Token/Bearerpassword: Password fieldaccount: Account/username fieldemail: Email
Example:
const latest = await clipboard.history.getLatest()
const tags = Array.isArray(latest?.meta?.tags) ? latest?.meta?.tags : []
if (tags.includes('api_key') || tags.includes('password')) {
// e.g. warn the user about sensitive content
}
Tip: For
history.searchHistory()results, filter bymeta.tagsin your plugin to build more precise matching.
Technical Notes
- Clipboard read/write, history, and auto-paste are executed in the main process via TuffTransport to avoid focus-related failures.
- History is persisted in the database;
meta/metadatacarry extra signals for technical filtering and matching. - Automatic tags are lightweight rule-based categories; raw sensitive values are never exposed.
Migration Guide
Migrate from useClipboardHistory
useClipboardHistory() is deprecated. Use useClipboard() instead:
// Old
const history = useClipboardHistory()
await history.getLatest()
await history.applyToActiveApp({ text: 'Hello' })
// New
const clipboard = useClipboard()
await clipboard.history.getLatest()
await clipboard.copyAndPaste({ text: 'Hello' })
Best Practices
- Use copyAndPaste instead of manual operations: it handles CoreBox hiding, delays, and cross-platform paste behavior.
- Limit monitoring types: only enable required types to reduce overhead.
- Unsubscribe promptly: call
unsubscribe()when not needed. - Handle nulls:
readImage()andhistory.getLatest()may returnnull.