Record and Replay User Actions

@univerjs/action-recorder records selected Univer commands and operations, exports them as JSON, and replays them later. It is useful for debugging hard-to-reproduce UI issues, preparing deterministic demos, and sharing a workflow with another developer.

When to Use It

Use the action recorder when you need to:

  • Capture a short workflow that changes a workbook.
  • Replay a workflow against the current workbook, the active sheet, or a sheet with the same name.
  • Attach reproducible command JSON to a bug report.
  • Build a development-only plugin that registers extra commands for recording.

Do not treat the recorded JSON as a long-term business audit log. It stores executable command ids and params, so it is tied to the current command model and package version.

Install

Shell
pnpm add @univerjs/action-recorder

Register the Plugin

TypeScript
import { UniverActionRecorderPlugin } from '@univerjs/action-recorder'import ActionRecorderEnUS from '@univerjs/action-recorder/locale/en-US'import { LocaleType, mergeLocales, Univer } from '@univerjs/core'import '@univerjs/action-recorder/lib/index.css'const univer = new Univer({  locale: LocaleType.EN_US,  locales: {    [LocaleType.EN_US]: mergeLocales(ActionRecorderEnUS),  },})univer.registerPlugin(UniverActionRecorderPlugin)

If you only need to replay existing command JSON and do not want to record new actions, register the plugin with replayOnly.

TypeScript
univer.registerPlugin(UniverActionRecorderPlugin, {  replayOnly: true,})

Use the Recorder UI

After registration, the plugin adds a recorder entry under the built-in Others ribbon group.

  1. Open the recorder panel.
  2. Start recording.
  3. Perform the workflow you want to reproduce.
  4. Complete the recording to download recorded-commands.json.
  5. Use a replay menu item to load the JSON file and run the commands again.

The built-in replay service supports three modes:

ModeBehavior
defaultReplays commands on the currently focused unit.
nameMaps recorded sheet names back to sheet ids with the same name.
activeReplays sheet commands on the currently active sheet.

Register Additional Commands

The recorder only captures commands that are explicitly registered with ActionRecorderService. The built-in controller registers common Sheets commands such as range edits, formatting, row/column operations, freeze panes, filtering, copy/paste, and selection changes.

If your plugin owns a command that should be captured, inject ActionRecorderService and register the command during your controller initialization.

TypeScript
import { ActionRecorderService } from '@univerjs/action-recorder'import { Inject } from '@univerjs/core'export class MyFeatureRecorderController {  constructor(@Inject(ActionRecorderService) private readonly actionRecorderService: ActionRecorderService) {    this.actionRecorderService.registerRecordedCommand(MyFeatureCommand)  }}

registerRecordedCommand accepts commands and operations, but not mutation commands. Mutations are lower-level data changes and should be produced by replaying the recorded command instead.

Replay from Code

When building a development tool, use ActionReplayService to replay command JSON yourself.

TypeScript
import { ActionReplayService } from '@univerjs/action-recorder'import { Inject } from '@univerjs/core'export class MyReplayController {  constructor(@Inject(ActionReplayService) private readonly replayService: ActionReplayService) {}  async replay(commands: ICommandInfo[]) {    return this.replayService.replayCommands(commands)  }}

Notes

  • Keep @univerjs/action-recorder on the same version as the rest of your @univerjs/* packages.
  • Recorded command params should be serializable.
  • Prefer short recordings. Long recordings are harder to review and more likely to depend on unrelated document state.
  • Replaying command JSON from untrusted sources can execute edits in the current Univer instance. Treat it like executable test data.

© 2026 DreamNum Co., Ltd.