Skip to content

Fresh Editor Plugin API

This document describes the TypeScript API available to Fresh editor plugins.

Core Concepts

Buffers

A buffer holds text content and may or may not be associated with a file. Each buffer has a unique numeric ID that persists for the editor session. Buffers track their content, modification state, cursor positions, and path. All text operations (insert, delete, read) use byte offsets, not character indices.

Splits

A split is a viewport pane that displays a buffer. The editor can have multiple splits arranged in a tree layout. Each split shows exactly one buffer, but the same buffer can be displayed in multiple splits. Use split IDs to control which pane displays which buffer.

Virtual Buffers

Special buffers created by plugins to display structured data like search results, diagnostics, or git logs. Virtual buffers support text properties (metadata attached to text ranges) that plugins can query when the user selects a line. Unlike normal buffers, virtual buffers are typically read-only and not backed by files.

Text Properties

Metadata attached to text ranges in virtual buffers. Each entry has text content and a properties object with arbitrary key-value pairs. Use getTextPropertiesAtCursor to retrieve properties at the cursor position (e.g., to get file/line info for "go to").

Overlays

Visual decorations applied to buffer text without modifying content. Overlays can change text color and add underlines. Use overlay IDs to manage them; prefix IDs enable batch removal (e.g., "lint:" prefix for all linter highlights).

Modes

Keybinding contexts that determine how keypresses are interpreted. Each buffer has a mode (e.g., "normal", "insert", "special"). Custom modes can inherit from parents and define buffer-local keybindings. Virtual buffers typically use custom modes.

Types

FileExplorerDecoration

File explorer decoration entry provided by plugins

typescript
interface FileExplorerDecoration {
  path: string;
  symbol?: string | null;
  color?: [u8; 3] | null;
  priority?: number | null;
}
FieldDescription
pathAbsolute or workspace-relative path to decorate
symbolSymbol to display (single character recommended)
colorRGB color for the symbol
priorityPriority for resolving conflicts (higher wins)

SpawnResult

Result from spawnProcess

typescript
interface SpawnResult {
  stdout: string;
  stderr: string;
  exit_code: number;
}
FieldDescription
stdoutComplete stdout as string. Newlines preserved; trailing newline included.
stderrComplete stderr as string. Contains error messages and warnings.
exit_codeProcess exit code. 0 usually means success; -1 if process was killed.

BackgroundProcessResult

Result from spawnBackgroundProcess - just the process ID

typescript
interface BackgroundProcessResult {
  process_id: number;
}
FieldDescription
process_idUnique process ID for later reference (kill, status check)

FileStat

File stat information

typescript
interface FileStat {
  exists: boolean;
  is_file: boolean;
  is_dir: boolean;
  size: number;
  readonly: boolean;
}
FieldDescription
existsWhether the path exists
is_fileWhether the path is a file
is_dirWhether the path is a directory
sizeFile size in bytes
readonlyWhether the file is read-only

BufferInfo

Buffer information

typescript
interface BufferInfo {
  id: number;
  path: string;
  modified: boolean;
  length: number;
}
FieldDescription
idUnique buffer ID
pathFile path (empty string if no path)
modifiedWhether buffer has unsaved changes
lengthBuffer length in bytes

TsBufferSavedDiff

Diff vs last save for a buffer

typescript
interface TsBufferSavedDiff {
  equal: boolean;
  byte_ranges: [number, number][];
  line_ranges?: [number, number][] | null;
}

SelectionRange

Selection range

typescript
interface SelectionRange {
  start: number;
  end: number;
}
FieldDescription
startStart byte position
endEnd byte position

CursorInfo

Cursor information with optional selection

typescript
interface CursorInfo {
  position: number;
  selection?: SelectionRange | null;
}
FieldDescription
positionByte position of the cursor
selectionSelection range if text is selected, null otherwise

TsDiagnosticPosition

LSP diagnostic position

typescript
interface TsDiagnosticPosition {
  line: number;
  character: number;
}

TsDiagnosticRange

LSP diagnostic range

typescript
interface TsDiagnosticRange {
  start: TsDiagnosticPosition;
  end: TsDiagnosticPosition;
}

TsDiagnostic

LSP diagnostic item for TypeScript plugins

typescript
interface TsDiagnostic {
  uri: string;
  severity: number;
  message: string;
  source?: string | null;
  range: TsDiagnosticRange;
}
FieldDescription
uriFile URI (e.g., "file:///path/to/file.rs")
severityDiagnostic severity: 1=Error, 2=Warning, 3=Info, 4=Hint
messageDiagnostic message
sourceSource of the diagnostic (e.g., "rust-analyzer")
rangeLocation range in the file

ViewportInfo

Viewport information

typescript
interface ViewportInfo {
  top_byte: number;
  left_column: number;
  width: number;
  height: number;
}
FieldDescription
top_byteByte offset of the top-left visible position
left_columnColumn offset for horizontal scrolling
widthViewport width in columns
heightViewport height in rows

PromptSuggestion

Suggestion for prompt autocomplete

typescript
interface PromptSuggestion {
  text: string;
  description?: string | null;
  value?: string | null;
  disabled?: boolean | null;
  keybinding?: string | null;
}
FieldDescription
textDisplay text for the suggestion
descriptionOptional description shown alongside
valueOptional value to use instead of text when selected
disabledWhether the suggestion is disabled
keybindingOptional keybinding hint

DirEntry

Directory entry from readDir

typescript
interface DirEntry {
  name: string;
  is_file: boolean;
  is_dir: boolean;
}
FieldDescription
nameEntry name only (not full path). Join with parent path to get absolute path.
is_fileTrue if entry is a regular file
is_dirTrue if entry is a directory. Note: symlinks report the target type.

TextPropertyEntry

Entry for virtual buffer content with embedded metadata

typescript
interface TextPropertyEntry {
  text: string;
  properties: Record<string, unknown>;
}
FieldDescription
textText to display. Include trailing newline for separate lines.
propertiesArbitrary metadata queryable via getTextPropertiesAtCursor.

CreateVirtualBufferResult

Result from createVirtualBufferInSplit

typescript
interface CreateVirtualBufferResult {
  buffer_id: number;
  split_id?: number | null;
}

CreateVirtualBufferOptions

Configuration for createVirtualBufferInSplit

typescript
interface CreateVirtualBufferOptions {
  name: string;
  mode: string;
  read_only: boolean;
  entries: TextPropertyEntry[];
  ratio: number;
  direction?: string | null;
  panel_id?: string | null;
  show_line_numbers?: boolean | null;
  show_cursors?: boolean | null;
  editing_disabled?: boolean | null;
  line_wrap?: boolean | null;
}
FieldDescription
nameBuffer name shown in status bar (convention: "Name")
modeMode for keybindings; define with defineMode first
read_onlyPrevent text modifications
entriesContent with embedded metadata
ratioSplit ratio (0.3 = new pane gets 30% of space)
directionSplit direction: "horizontal" (below) or "vertical" (side-by-side). Default: horizontal
panel_idIf set and panel exists, update content instead of creating new buffer
show_line_numbersShow line numbers gutter (default: true)
show_cursorsShow cursor in buffer (default: true)
editing_disabledDisable all editing commands (default: false)
line_wrapEnable/disable line wrapping (None = use global setting)

CreateVirtualBufferInExistingSplitOptions

Options for creating a virtual buffer in an existing split

typescript
interface CreateVirtualBufferInExistingSplitOptions {
  name: string;
  mode: string;
  read_only: boolean;
  entries: TextPropertyEntry[];
  split_id: number;
  show_line_numbers?: boolean | null;
  show_cursors?: boolean | null;
  editing_disabled?: boolean | null;
  line_wrap?: boolean | null;
}
FieldDescription
nameDisplay name (e.g., "Commit Details")
modeMode name for buffer-local keybindings
read_onlyWhether the buffer is read-only
entriesEntries with text and embedded properties
split_idTarget split ID where the buffer should be displayed
show_line_numbersWhether to show line numbers in the buffer (default true)
show_cursorsWhether to show cursors in the buffer (default true)
editing_disabledWhether editing is disabled for this buffer (default false)
line_wrapEnable/disable line wrapping (None = use global setting)

CreateVirtualBufferInCurrentSplitOptions

Options for creating a virtual buffer in the current split as a new tab

typescript
interface CreateVirtualBufferInCurrentSplitOptions {
  name: string;
  mode: string;
  read_only: boolean;
  entries: TextPropertyEntry[];
  show_line_numbers?: boolean | null;
  show_cursors?: boolean | null;
  editing_disabled?: boolean | null;
  hidden_from_tabs?: boolean | null;
}
FieldDescription
nameDisplay name (e.g., "Help")
modeMode name for buffer-local keybindings
read_onlyWhether the buffer is read-only
entriesEntries with text and embedded properties
show_line_numbersWhether to show line numbers in the buffer (default false for help/docs)
show_cursorsWhether to show cursors in the buffer (default true)
editing_disabledWhether editing is disabled for this buffer (default false)
hidden_from_tabsWhether this buffer should be hidden from tabs (for composite source buffers)

TsCompositeLayoutConfig

Layout configuration for composite buffers

typescript
interface TsCompositeLayoutConfig {
  layout_type: string;
  ratios?: number[] | null;
  show_separator?: boolean | null;
  spacing?: number | null;
}
FieldDescription
layout_typeLayout type: "side-by-side", "stacked", or "unified"
ratiosRelative widths for side-by-side layout (e.g., [0.5, 0.5])
show_separatorShow separator between panes
spacingSpacing between stacked panes

TsCompositePaneStyle

Pane style configuration

typescript
interface TsCompositePaneStyle {
  add_bg?: [number, number, number] | null;
  remove_bg?: [number, number, number] | null;
  modify_bg?: [number, number, number] | null;
  gutter_style?: string | null;
}
FieldDescription
add_bgBackground color for added lines (RGB tuple)
remove_bgBackground color for removed lines (RGB tuple)
modify_bgBackground color for modified lines (RGB tuple)
gutter_styleGutter style: "line-numbers", "diff-markers", "both", "none"

TsCompositeSourceConfig

Source pane configuration for composite buffers

typescript
interface TsCompositeSourceConfig {
  buffer_id: number;
  label?: string | null;
  editable: boolean;
  style?: TsCompositePaneStyle | null;
}
FieldDescription
buffer_idBuffer ID to display in this pane
labelLabel for the pane (shown in header)
editableWhether the pane is editable
stylePane styling options

TsCompositeHunk

Diff hunk configuration

typescript
interface TsCompositeHunk {
  old_start: number;
  old_count: number;
  new_start: number;
  new_count: number;
}
FieldDescription
old_startStart line in old file (0-indexed)
old_countNumber of lines in old file
new_startStart line in new file (0-indexed)
new_countNumber of lines in new file

CreateCompositeBufferOptions

Options for creating a composite buffer

typescript
interface CreateCompositeBufferOptions {
  name: string;
  mode: string;
  layout: TsCompositeLayoutConfig;
  sources: TsCompositeSourceConfig[];
  hunks?: TsCompositeHunk[] | null;
}
FieldDescription
nameDisplay name for the composite buffer (shown in tab)
modeMode for keybindings (e.g., "diff-view")
layoutLayout configuration
sourcesSource panes to display
hunksOptional diff hunks for line alignment

ActionSpecJs

JavaScript representation of ActionSpec (with optional count)

typescript
interface ActionSpecJs {
  action: string;
  count?: number | null;
}

TsActionPopupAction

TypeScript struct for action popup action

typescript
interface TsActionPopupAction {
  id: string;
  label: string;
}

TsActionPopupOptions

TypeScript struct for action popup options

typescript
interface TsActionPopupOptions {
  id: string;
  title: string;
  message: string;
  actions: TsActionPopupAction[];
}

Released under the Apache 2.0 License