Skip to main content
Fresh plugins are written in TypeScript and run in a sandboxed QuickJS environment. This guide covers everything you need to build your own plugins.

Quick Start

Create your first plugin in under 2 minutes:
1

Create Plugin File

Create a new TypeScript file in the plugins directory:
2

Add Plugin Code

my_plugin.ts
3

Restart Fresh

Restart Fresh to load your plugin.
4

Test Your Plugin

Press Ctrl+P > and search for “My Plugin: Say Hello”.
All .ts files in the plugins/ directory are automatically loaded when Fresh starts.

Plugin Architecture

Runtime Environment

Plugins run in a sandboxed QuickJS JavaScript runtime:

Transpilation

TypeScript is transpiled to JavaScript using oxc_transformer (a fast, Rust-based compiler).

Sandboxing

Each plugin runs in an isolated QuickJS environment, preventing interference between plugins.

Async Support

Full async/await support for non-blocking I/O, process spawning, and LSP requests.

Type Safety

TypeScript definitions provide autocomplete and type checking in your editor.

The editor Global Object

The editor object is the main API surface:
The editor object provides access to:
  • Buffer operations (read, write, modify)
  • Command registration
  • Event handling
  • Process spawning
  • File system operations
  • LSP integration
  • Visual overlays and decorations

Core Concepts

Commands

Commands are actions that appear in the command palette and can be bound to keys.

Registering Commands

Command handlers must be attached to globalThis because the editor calls them by name.

Command Contexts

Contexts control when commands are available:

Async Operations

Many API calls return Promises. Use async/await:

Event Handlers

Subscribe to editor events with editor.on():
Available Events:
  • buffer_save - After a buffer is saved to disk
  • buffer_closed - When a buffer is closed
  • cursor_moved - When cursor position changes
  • render_start - Before screen renders (for overlays)
  • lines_changed - When visible lines change
  • prompt_confirmed - When user confirms a prompt
  • prompt_cancelled - When user cancels a prompt

Buffers

Buffers hold text content. Each buffer has a unique numeric ID.

Querying Buffers

Reading Buffer Content

Modifying Buffers

Virtual Buffers

Create special buffers for displaying structured data like search results, diagnostics, or logs.

Accessing Properties

Overlays

Add visual decorations without modifying buffer content:

Process Spawning

Run external commands and tools:

LSP Integration

Invoke language server requests:

File System Operations

Read and write files:

Common Patterns

Highlighting Text

Interactive Prompts

Custom Modes

Internationalization

Plugins can support multiple languages using i18n:
Create a .i18n.json file next to your plugin:
my_plugin.i18n.json

Debugging

Debug Logging

Run Fresh with debug logging:

Status Messages

Status messages appear in the status bar.

Best Practices

Always include the type reference at the top of your plugin:
Always wrap async operations in try/catch:
Use consistent namespaces to enable batch removal:
Use editor.delay() to debounce rapid events:
Subscribe to buffer_closed to clean up resources:

Publishing Your Plugin

To share your plugin with others:
1

Create Git Repository

Initialize a git repository for your plugin:
2

Add package.json

Create a package.json with metadata:
3

Push to GitHub

Push your repository to GitHub or any git hosting service.
4

Share the URL

Users can install your plugin with:

Next Steps

Plugin Examples

Explore real plugin examples with complete code

API Reference

Complete API documentation with all methods

Plugin Overview

Learn about the plugin system architecture

Getting Started

Install and manage plugins