FTB Plugin System

July 8, 2026 · View on GitHub

中文文档 | English

FTB Plugin System

FTB supports a TypeScript/JavaScript plugin system inspired by yazi, allowing you to extend functionality with custom scripts.

Quick Start

Install a Plugin

Place plugin directories in ~/.config/ftb/plugins/:

~/.config/ftb/plugins/
├── hello-world.ftb/
│   ├── main.ts          # Entry point
│   └── package.json     # Metadata & permissions
└── file-info.ftb/
    ├── main.ts
    └── package.json

Open Plugin Manager

Press Ctrl+B then type :plugin or :pl.

Run a Plugin

In the plugin manager panel, select a plugin and press Enter.

Plugin Types

TypeDescriptionEntry FunctionReturn
functionalExecute an actionentry(ftb)Record<string, any>
previewerCustom file previewentry(ftb)Record<string, any>
fetcherAsync metadata fetchentry(ftb)Record<string, any>
statusbarStatus bar displayentry(ftb)StatusBarSegment[]

StatusBar Plugin

StatusBar plugins run automatically every 2 seconds and contribute segments to the status bar. The entry function must return an array of segment objects:

interface StatusBarSegment {
    text: string;       // Display text
    fg: string;         // Foreground color (hex, e.g. "#cdd6f4")
    bg: string;         // Background color (hex, e.g. "#89b4fa")
    bold: boolean;      // Bold text
}

function entry(ftb: FtbAPI): StatusBarSegment[] {
    return [
        { text: " main ", fg: "#1e1e2e", bg: "#a6e3a1", bold: true }
    ];
}

Plugin Structure

package.json

{
    "name": "my-plugin",
    "version": "1.0.0",
    "description": "What this plugin does",
    "author": "Your Name",
    "entry": "main.ts",
    "type": "functional",
    "permissions": {
        "fs_read": true,
        "fs_write": false,
        "fs_list": true,
        "net_fetch": false,
        "env_read": false,
        "clipboard": false,
        "subprocess": false,
        "max_exec_ms": 5000
    },
    "keywords": [".md", "text/markdown"],
    "min_ftb_version": "0.1.0"
}

main.ts

interface FtbContext {
    current_path: string;
    selected_file: string;
    selected_file_path: string;
    selected_is_dir: boolean;
    selected_size: number;
    selected_mime: string;
    args: Record<string, any>;
}

interface FtbAPI {
    ctx: FtbContext;
    fs: {
        readFile: (path: string) => string;
        writeFile: (path: string, content: string) => void;
        listDir: (path: string) => string[];
    };
    clipboard: {
        read: () => string;
        write: (text: string) => void;
    };
    env: {
        get: (key: string) => string;
    };
    ui: {
        message: (text: string) => void;
        confirm: (text: string) => boolean;
    };
    statusBar: {
        set: (segments: StatusBarSegment[]) => void;
    };
    log: (msg: string) => void;
    exec: (cmd: string, args: string[]) => string;
}

function entry(ftb: FtbAPI): Record<string, any> {
    ftb.ui.message("Hello from my plugin!");
    return { success: true };
}

API Reference

ftb.ctx - Execution Context

FieldTypeDescription
current_pathstringCurrent working directory
selected_filestringSelected file name
selected_file_pathstringFull path of selected file
selected_is_dirbooleanIs the selection a directory?
selected_sizenumberFile size in bytes
selected_mimestringMIME type (if known)
argsobjectArguments passed to the plugin
plugin_dirstringPlugin directory path (for python.call module resolution)

ftb.fs - File System (requires permissions)

MethodPermissionDescription
readFile(path)fs_readRead file contents
writeFile(path, content)fs_writeWrite file contents
listDir(path)fs_listList directory entries

ftb.clipboard - Clipboard (requires clipboard)

MethodDescription
read()Read clipboard text
write(text)Write to clipboard

ftb.env - Environment (requires env_read)

MethodDescription
get(key)Get environment variable

ftb.ui - User Interface

MethodDescription
message(text)Show message to user
confirm(text)Ask user for confirmation

ftb.statusBar - Status Bar (for statusbar type plugins)

MethodDescription
set(segments)Set status bar segments

Each segment: { text: string, fg: string, bg: string, bold: boolean }

ftb.log(msg) - Logging

Write to FTB's debug log (only when -l flag is used).

ftb.exec(cmd, args) - Subprocess (requires subprocess)

Execute a command and return its output. Use with caution.

ftb.python.call(file, func, args) - Python Call (requires python_exec)

Call a Python function from a module file in the plugin directory. Returns JSON result:

// In utils.py:
// def compute(data, mode="stats"):
//     return {"sum": sum(data), "mean": sum(data)/len(data)}

const result = ftb.python.call("utils.py", "compute", { data: [1,2,3,4,5], mode: "stats" });
ftb.ui.message(`Mean: ${result.mean}`);

Parameters:

  • file — Python file path (relative to plugin dir, e.g. "utils.py" or "subdir/module.py")
  • func — Function name
  • args — Arguments object (passed as **kwargs to the function)
  • Returns — Python function's return dict, serialized as JSON

Python code runs in an isolated python3 subprocess, bounded by max_exec_ms.

Permissions

Plugins run in a sandboxed environment. Each permission must be explicitly declared in package.json:

PermissionDefaultDescription
fs_readfalseRead files
fs_writefalseWrite/modify files
fs_listfalseList directory contents
net_fetchfalseMake HTTP requests
env_readfalseRead environment variables
clipboardfalseAccess system clipboard
subprocessfalseExecute subprocesses
python_execfalseExecute Python code (ftb.python.call)
max_exec_ms5000Maximum execution time (ms)

Security Model

  1. Sandboxed Execution: Plugins run in an isolated QuickJS process
  2. Permission-Based Access: APIs are only available if declared in package.json
  3. Resource Limits: Execution time is bounded by max_exec_ms
  4. Process Isolation: Plugins cannot access FTB's memory space
  5. No Network by Default: net_fetch must be explicitly granted

Runtime Requirements

Plugins require QuickJS (qjs) to be installed:

# Ubuntu/Debian
sudo apt-get install quickjs

# From source
git clone https://github.com/bellard/quickjs
cd quickjs && make && sudo make install

TypeScript files are automatically transpiled to JavaScript before execution. For complex TypeScript, install esbuild for better compilation:

npm install -g esbuild

Plugins using ftb.python.call() or Python-based previewers also require Python 3 (python3):

# Most systems have Python 3 pre-installed
python3 --version

Examples

See the plugins/ directory for example plugins:

  • hello-world.ftb - Basic greeting plugin (functional)
  • file-info.ftb - File information with size formatting (functional)
  • git-status.ftb - Git branch and status in status bar (statusbar)
  • preview-external.ftb - File preview using external tools + Python APK binary analysis (previewer)

git-status Plugin

The git-status plugin automatically displays git information in the status bar when inside a git repository:

  • Branch name (green when clean, blue when dirty)
  • Staged changes (+N in yellow)
  • Modified files (~N in orange)
  • Conflicts (!N in red)
  • Untracked files (?N in gray)

Requires permissions: fs_read, fs_list, subprocess

Plugin Manager Shortcuts

KeyAction
j/kNavigate plugins
EnterExecute selected plugin
dToggle enable/disable
rReload plugin
q/EscClose panel

See also: Configuration Guide | 配置指南