---
title: "AI Caret"
description: "Display a cursor that shows where the AI is inserting content during streaming operations."
canonical_url: "https://tiptap.dev/docs/content-ai/capabilities/ai-toolkit/advanced-guides/ai-caret"
---

# AI Caret

Display a cursor that shows where the AI is inserting content during streaming operations.

The `AiCaret` extension displays a cursor decoration at the position where the AI is currently inserting content. It provides real-time visual feedback during streaming operations, similar to the [Collaboration Caret extension](https://tiptap.dev/docs/editor/extensions/functionality/collaboration-caret.md).

## Usage

Import the `AiCaret` extension from `@tiptap-pro/ai-toolkit` and add it to your editor extensions.

```tsx
import { AiCaret, AiToolkit } from '@tiptap-pro/ai-toolkit'

const editor = useEditor({
  extensions: [StarterKit, AiToolkit, AiCaret],
})
```

The caret appears automatically during streaming operations like `streamHtml`, `streamTool`, and `tiptapEditWorkflow`. It disappears after the streaming finishes.

## Configuration

You can configure the caret's timeout, user label, and rendering.

```tsx
AiCaret.configure({
  // How long the caret stays visible after the last update (ms)
  timeout: 2000,
  // User details for the caret label
  user: {
    name: 'AI',
    color: '#a5b4fc',
  },
})
```

### Options

| Option    | Type                                 | Default                            | Description                                                  |
| --------- | ------------------------------------ | ---------------------------------- | ------------------------------------------------------------ |
| `timeout` | `number`                             | `2000`                             | How long the caret stays visible after the last update (ms). |
| `user`    | `{ name: string, color: string }`    | `{ name: 'AI', color: '#a5b4fc' }` | The name and color displayed on the caret label.             |
| `render`  | `(user: AiCaretUser) => HTMLElement` | Built-in render function           | Custom function to render the caret DOM element.             |

## CSS styles

The default render function creates a DOM element with the class `tiptap-ai-caret` and a label with the class `tiptap-ai-caret__label`. Add the following CSS to style the caret:

```css
.tiptap .tiptap-ai-caret {
  border-left: 1px solid #0d0d0d;
  border-right: 1px solid #0d0d0d;
  margin-left: -1px;
  margin-right: -1px;
  pointer-events: none;
  position: relative;
  word-break: normal;
}

.tiptap .tiptap-ai-caret__label {
  border-radius: 3px 3px 3px 0;
  color: #0d0d0d;
  font-size: 12px;
  font-style: normal;
  font-weight: 600;
  left: -1px;
  line-height: normal;
  padding: 0.1rem 0.3rem;
  position: absolute;
  top: -1.4em;
  user-select: none;
  white-space: nowrap;
}
```

The `border-color` and `background-color` of the caret and label are set inline based on the `user.color` option.

## Custom rendering

You can provide a custom `render` function to fully control the caret DOM element.

```tsx
AiCaret.configure({
  render: (user) => {
    const el = document.createElement('span')
    el.className = 'my-custom-ai-caret'
    el.style.borderColor = user.color
    el.textContent = user.name
    return el
  },
})
```

## Events

The `AiCaret` extension emits events through the Tiptap events API. You can subscribe to them to react to the caret's movement — for example, to follow the AI's writing position with custom UI behavior.

### Available events

| Event                     | Description                                                                           | Payload                |
| ------------------------- | ------------------------------------------------------------------------------------- | ---------------------- |
| `aiCaret:positionChanged` | Fired whenever the AI caret position is updated during a streaming or edit operation. | `{ position: number }` |

The `position` value is a ProseMirror document position pointing to where the AI caret is currently placed.

### Subscribing to events

Use `editor.on` to listen for the event, and `editor.off` to unsubscribe when no longer needed.

```tsx
editor.on('aiCaret:positionChanged', ({ position }) => {
  console.log('AI caret moved to position', position)
})
```

The `aiCaret:positionChanged` event can fire frequently during streaming — once per streamed chunk. If your handler performs expensive work, consider throttling it with `requestAnimationFrame` or a utility like `lodash.throttle`.
