Docs/Clipboard SDK

Clipboard SDK

Universal Developer

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 uses ClipboardEvents.* 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 with clipboard.read; it does not expose a raw selection channel.

Introduction

Quick Start

EXAMPLE.TYPESCRIPT
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.

EXAMPLE.TYPESCRIPT
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.

EXAMPLE.TYPESCRIPT
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.

EXAMPLE.TYPESCRIPT
await clipboard.writeText('Hello World')

write(options)

Write multiple formats to the clipboard.

EXAMPLE.TYPESCRIPT
// 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:

FieldTypeDescription
textstringPlain text
htmlstringHTML content
imagestringImage data URL
filesstring[]File paths

read()

Read current clipboard content.

EXAMPLE.TYPESCRIPT
const content = await clipboard.read()
// {
//   text: 'Hello',
//   html: '<b>Hello</b>',
//   hasImage: false,
//   hasFiles: false,
//   formats: ['text/plain', 'text/html']
// }

Returns:

FieldTypeDescription
textstringText content
htmlstringHTML content
hasImagebooleanWhether image exists
hasFilesbooleanWhether files exist
formatsstring[]Available formats

readImage()

Read image from clipboard.

EXAMPLE.TYPESCRIPT
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.

EXAMPLE.TYPESCRIPT
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.

EXAMPLE.TYPESCRIPT
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.

EXAMPLE.TYPESCRIPT
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.

EXAMPLE.TYPESCRIPT
const files = await clipboard.readFiles()
// ['/path/to/file1.txt', '/path/to/file2.png']

clear()

Clear the clipboard.

EXAMPLE.TYPESCRIPT
await clipboard.clear()

Copy and Paste

copyAndPaste(options)

Write content to the clipboard and simulate paste into the active app.

EXAMPLE.TYPESCRIPT
// 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:

FieldTypeDescription
textstringText content
htmlstringHTML content
imagestringImage data URL
filesstring[]File paths
delayMsnumberDelay before paste
hideCoreBoxbooleanHide CoreBox before paste

Returns: Promise<boolean> - whether the operation succeeded


History

Access history operations via clipboard.history.

history.getLatest()

Get the latest clipboard item.

EXAMPLE.TYPESCRIPT
const latest = await clipboard.history.getLatest()
if (latest) {
  console.log(latest.type, latest.content)
}

history.getHistory(options)

Get clipboard history with pagination.

EXAMPLE.TYPESCRIPT
const { history, total, page, pageSize } = await clipboard.history.getHistory({
  page: 1,
  pageSize: 20
})

history.searchHistory(options)

Advanced search.

EXAMPLE.TYPESCRIPT
// 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:

FieldTypeDescription
keywordstringContent keyword
type'text' | 'image' | 'files'Type filter
startTimenumberStart timestamp
endTimenumberEnd timestamp
isFavoritebooleanFavorite filter
sourceAppstringSource app
pagenumberPage number
pageSizenumberPage size
sortOrder'asc' | 'desc'Sort order

history.setFavorite(options)

Set favorite status.

EXAMPLE.TYPESCRIPT
await clipboard.history.setFavorite({
  id: 123,
  isFavorite: true
})

history.deleteItem(options)

Delete a history item.

EXAMPLE.TYPESCRIPT
await clipboard.history.deleteItem({ id: 123 })

history.clearHistory()

Clear all history.

EXAMPLE.TYPESCRIPT
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.

EXAMPLE.TYPESCRIPT
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:

ValueBinaryDescription
TEXT0b0001Description for TEXT.
IMAGE0b0010Image
FILE0b0100File

Presets:

EXAMPLE.TYPESCRIPT
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

EXAMPLE.TYPESCRIPT
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/link
  • api_key: API key patterns
  • token: Token/Bearer
  • password: Password field
  • account: Account/username field
  • email: Email

Example:

EXAMPLE.TYPESCRIPT
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 by meta.tags in 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/metadata carry 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:

EXAMPLE.TYPESCRIPT
// 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

  1. Use copyAndPaste instead of manual operations: it handles CoreBox hiding, delays, and cross-platform paste behavior.
  2. Limit monitoring types: only enable required types to reduce overhead.
  3. Unsubscribe promptly: call unsubscribe() when not needed.
  4. Handle nulls: readImage() and history.getLatest() may return null.