* feat: 第一版大重构 * fix: 修复类型问题 * chore: 更新版本到 1.3.2 * Add brave as alternative WebSearchTool * fix: 修正顺序 * fix: 修复对穷鬼模式的 auto dream 和 session memory 越过 * feat: 穷鬼模式去除 session-summary * feat: 创建 builtin-tools 包,搬运所有工具实现 将 src/tools/ 下的全部 60 个工具目录迁移至 packages/builtin-tools/src/tools/, 内部导入路径已更新为 src/ alias 模式。 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * refactor: 更新 src/ 中所有工具引用至 builtin-tools 包,删除 src/tools/ - src/tools.ts 及 178 个 src/ 文件的 import 路径从 ./tools/ 改为 builtin-tools/tools/ - 删除 src/tools/ 整个目录(已迁移至 packages/builtin-tools/) Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * chore: 添加 builtin-tools 路径别名至 tsconfig,更新 bun.lock - tsconfig.json 新增 builtin-tools/* 和 builtin-tools 路径映射 - 新增 packages/builtin-tools/src 至 include Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * refactor: 为 builtin-tools、mcp-client、agent-tools 添加 @claude-code-best 作用域前缀 所有包名及 import 路径统一添加 @claude-code-best/ 前缀: - builtin-tools → @claude-code-best/builtin-tools - mcp-client → @claude-code-best/mcp-client - agent-tools → @claude-code-best/agent-tools Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * fix: 修复 node 环境没有 bun 的问题 --------- Co-authored-by: Eric-Guo <eric.guocz@gmail.com> Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
8.0 KiB
Chapter 12: Terminal Integration
This chapter covers terminal-specific features: alternate screen, mouse tracking, clipboard, notifications, and terminal querying.
Alternate Screen
Enter a fullscreen alternate screen buffer (like vim, less, htop).
import { AlternateScreen } from '@anthropic/ink'
<AlternateScreen mouseTracking={true}>
<Box flexDirection="column" height="100%">
<Text>Fullscreen content</Text>
</Box>
</AlternateScreen>
Props
| Prop | Type | Default | Description |
|---|---|---|---|
children |
ReactNode |
- | Content |
mouseTracking |
boolean |
true |
Enable SGR mouse tracking |
Behavior
On mount:
- Enters DEC 1049 alternate screen buffer
- Hides cursor
- Enables mouse tracking (if
mouseTracking=true) - Constrains rendering height to terminal rows
On unmount:
- Exits alternate screen buffer
- Shows cursor
- Disables mouse tracking
- Restores original terminal content
Mouse Tracking Modes
When enabled:
- Mode 1003 -- Button press/release + motion (hover)
- Mode 1006 -- SGR extended mouse format (coordinates > 223)
- Wheel events -- Scroll up/down
External Editor Handoff
The Ink instance supports pausing for an external editor:
// Pause Ink, run external command, resume
ink.enterAlternateScreen() // Save state
// ... external editor runs ...
ink.reassertTerminalModes() // Restore on resume
This is triggered by Ctrl+Z (SIGTSTP) and SIGCONT.
Mouse Events
Click Events
<Box onClick={(event) => {
console.log(`Clicked at col=${event.x}, row=${event.y}`)
event.stopImmediatePropagation()
}}>
<Text>Clickable area</Text>
</Box>
Multi-Click
Double-click selects a word, triple-click selects a line. Handled by the App component:
// App prop
onMultiClick: (col: number, row: number, count: 2 | 3) => void
Hover Events
<Box
onMouseEnter={() => setHovered(true)}
onMouseLeave={() => setHovered(false)}
>
<Text>{hovered ? 'Hovered!' : 'Hover me'}</Text>
</Box>
Hover uses mouseenter/mouseleave semantics (no bubbling between children).
Drag-to-Select
In alt-screen mode, click-drag creates a text selection:
// App prop
onSelectionDrag: (col: number, row: number) => void
Clipboard
OSC 52 Clipboard
import { setClipboard } from '@anthropic/ink'
await setClipboard('Copied text')
Copy Selection
const { copySelection } = useSelection()
const text = copySelection() // Copies to clipboard and clears highlight
Copy Without Clear
const { copySelectionNoClear } = useSelection()
const text = copySelectionNoClear() // Copies but keeps highlight
Terminal Notifications
Send desktop notifications from the terminal.
import { useTerminalNotification } from '@anthropic/ink'
function MyComponent() {
const { notifyBell, progress } = useTerminalNotification()
// Terminal bell (audible/system notification)
notifyBell()
// Progress bar in terminal title/tab
progress('running', 65) // 65% complete
progress('completed') // Done
progress('error') // Error state
progress('indeterminate') // Unknown progress
progress(null) // Clear
}
Terminal-Specific Notifications
const { notifyITerm2, notifyKitty, notifyGhostty } = useTerminalNotification()
// iTerm2
notifyITerm2({ message: 'Build complete', title: 'My App' })
// Kitty
notifyKitty({ message: 'Build complete', title: 'My App', id: 1 })
// Ghostty
notifyGhostty({ message: 'Build complete', title: 'My App' })
Terminal Queries
Background Color (OSC 11)
Used for auto-theme detection:
import { getTerminalBackground } from '@anthropic/ink'
const bg = await getTerminalBackground()
// e.g., 'rgb:0000/0000/0000' (dark) or 'rgb:ffff/ffff/ffff' (light)
Terminal Version (XTVERSION)
import { isXtermJs, setXtversionName, getXtversionName } from '@anthropic/ink'
Feature Detection
import { supportsHyperlinks } from '@anthropic/ink'
if (supportsHyperlinks()) {
// OSC 8 hyperlinks supported
}
import { supportsExtendedKeys } from '@anthropic/ink'
if (supportsExtendedKeys()) {
// Kitty keyboard protocol / modifyOtherKeys available
}
Terminal Focus
Track terminal window focus/unfocus:
import { useTerminalFocus } from '@anthropic/ink'
const isFocused = useTerminalFocus()
Low-level API:
import { getTerminalFocused, subscribeTerminalFocus } from '@anthropic/ink'
getTerminalFocused() // boolean
subscribeTerminalFocus((focused: boolean) => {
// Called on focus change
})
Uses DECSET 1004 focus reporting.
Terminal Title
Set the terminal window title:
import { useTerminalTitle } from '@anthropic/ink'
useTerminalTitle('My App - Dashboard')
Clear:
useTerminalTitle(null)
Terminal I/O Sequences
Low-level ANSI sequence constants for advanced use.
Cursor Control
import {
SHOW_CURSOR,
HIDE_CURSOR,
CURSOR_HOME,
} from '@anthropic/ink'
// cursorPosition(row, col) -- Move cursor to absolute position
// cursorMove(dx, dy) -- Move cursor relative
Screen Control
import {
ENTER_ALT_SCREEN,
EXIT_ALT_SCREEN,
ERASE_SCREEN,
} from '@anthropic/ink'
Mouse Control
import {
ENABLE_MOUSE_TRACKING,
DISABLE_MOUSE_TRACKING,
} from '@anthropic/ink'
Keyboard Protocols
import {
ENABLE_KITTY_KEYBOARD,
DISABLE_KITTY_KEYBOARD,
ENABLE_MODIFY_OTHER_KEYS,
DISABLE_MODIFY_OTHER_KEYS,
} from '@anthropic/ink'
Clipboard & Tab Status
import {
CLEAR_ITERM2_PROGRESS,
CLEAR_TAB_STATUS,
CLEAR_TERMINAL_TITLE,
wrapForMultiplexer,
} from '@anthropic/ink'
wrapForMultiplexer wraps OSC sequences for tmux compatibility.
Terminal Compatibility
Supported Terminals
| Terminal | Features |
|---|---|
| iTerm2 | Full support (hyperlinks, notifications, progress) |
| Kitty | Full support (keyboard protocol, notifications) |
| Ghostty | Full support |
| WezTerm | Full support |
| Alacritty | Most features |
| Windows Terminal | Most features |
| Apple Terminal | 256-color fallback |
| xterm.js (VS Code) | Detected and special-cased |
| tmux | Wrapped sequences via wrapForMultiplexer |
| Screen | Basic support |
Feature Degradation
The framework gracefully degrades:
- No true color → Falls back to ANSI 16-color themes
- No OSC 52 → Clipboard operations silently fail
- No mouse tracking → Click/hover events are no-ops
- No extended keys → Standard escape sequences used
- No bracketed paste → Paste detected by timing heuristic
Synchronized Output
import { isSynchronizedOutputSupported } from '@anthropic/ink'
if (isSynchronizedOutputSupported()) {
// BSU/ESU for tear-free rendering
}
Uses DECSET 2026 synchronized output to prevent partial frame display.
Bracketed Paste
Uses DECSET 2004 to distinguish paste events from rapid typing. Automatically enabled by the App component.
Text Selection (Alt-Screen)
Selection State
type SelectionState = {
anchor: Point | null // Drag start
focus: Point | null // Current position
isDragging: boolean
anchorSpan: { lo: Point; hi: Point; kind: 'word' | 'line' } | null
scrolledOffAbove: string[] // Text scrolled out above
scrolledOffBelow: string[] // Text scrolled out below
}
Selection Operations
- Click-drag -- Free-form selection
- Double-click -- Word selection
- Triple-click -- Line selection
- Shift+Arrow -- Extend selection from keyboard
- Drag-to-scroll -- Auto-scroll when dragging near edges
noSelect Regions
Exclude areas from selection (gutters, line numbers):
<Box noSelect={true}>
<Text>1 │</Text>
</Box>
<Box>
<Text>code here</Text> {/* Only this is selectable */}
</Box>
Soft-Wrap Awareness
Selection correctly handles text that was wrapped across multiple rows:
- Wrapped lines are joined when copied
- Trailing whitespace is trimmed
- The
softWrapbitmap tracks which rows are continuations