Skip to main content

Plugins

VisiData's plugin system extends the tool with additional file format support, new commands, and third-party integrations. Plugins are Python files loaded at startup via .visidatarc.

Learning Focus

Learn how to install plugins from the built-in plugin index and how to write a minimal custom plugin for your own use case.

Plugin Index​

# Open the plugin index inside VisiData
Space
# Enter: open-plugins
# OR use the menu: Alt+H → Plugins

# Or from the CLI
vd -P open-plugins

The plugin index lists available community plugins with descriptions.

Installing a Plugin​

# From the Plugin Index sheet:
Enter # install the plugin under cursor
# VisiData downloads and enables it

# Or manually, add to ~/.visidatarc:
import importlib
# (plugins are Python modules dropped in the visidata plugins dir)

Default plugin directory:

~/.config/visidata/plugins/

To list installed plugins:

ls ~/.config/visidata/plugins/

Enabling/Disabling Plugin Autoload​

# ~/.visidatarc

# Disable autoloading of all plugins
options.plugins_autoload = False

# Selectively import specific plugins
import visidata.plugins.vds3 # S3 support
PluginWhat it adds
vds3Browse Amazon S3 buckets like directories
vdplusAdditional aggregators and commands
vgitBrowse git history as a sheet
vdredditBrowse Reddit as a VisiData sheet
vdzulipZulip chat as a sheet
vdairtableAirtable as a VisiData sheet
vdgpxGPX GPS track files
vdfixerLive currency conversion

Writing a Custom Plugin​

A minimal plugin is a Python file placed in the plugin directory:

# ~/.config/visidata/plugins/my_plugin.py

from visidata import vd, Sheet, Column

# Add a custom command to all sheets
Sheet.addCommand(
'F5', # keybinding
'my-custom-command', # longname
'vd.status("Hello VisiData!")', # Python expression to execute
'Show a status message' # help text
)

To load it:

# ~/.visidatarc
import sys, os
sys.path.insert(0, os.path.expanduser('~/.config/visidata/plugins'))
import my_plugin

Adding Custom Column Transformations​

# ~/.visidatarc

from visidata import Sheet, Column, vd

# Add a command to add a 'size' column showing length of each cell
@Sheet.api
def add_len_column(sheet):
col = sheet.cursorCol
sheet.addColumn(
Column(
f'len_{col.name}',
getter=lambda col, row: len(str(col.sheet.cursorCol.getDisplayValue(row)))
)
)

Sheet.addCommand('zL', 'add-len-col', 'sheet.add_len_column()', 'Add length column')

Plugin Security​

warning

VisiData plugins are executed as Python code with full system access. Only install plugins from trusted sources. Review plugin source code before enabling in production environments.

ProblemCauseFix
Plugin not loadingSyntax error in plugin fileRun python3 plugin.py to check
Command not foundPlugin not importedCheck .visidatarc import statement
Plugin conflicts with keyKey already boundChange the keybinding in the plugin
S3 plugin failsMissing boto3pip install boto3

Best Practices​

  • Keep plugins minimal — VisiData's core is powerful without plugins for most use cases.
  • Pin plugin versions in a requirements.txt if using plugins in automated pipelines.
  • Test plugins on non-production data first — a poorly written plugin can corrupt data.

Custom Plugin: Cell-Level Selection​

The cell_select.py plugin adds the ability to select individual cells (instead of entire rows) with visual highlighting. Cell selection is purely visual — it does not affect row-level operations like filtering, delete, or copy/paste. To copy a cell value, use zy → zp (or gzp for selected rows) — not Alt+5.

Keybindings​

KeyAction
Alt+5Toggle selection of current cell (5 resembles s for select)
Alt+uClear all cell selections (u for unselect)

Selected cells appear highlighted with a configurable color (default: bold yellow on blue).

Source​

~/.visidata/plugins/cell_select.py

How It Works​

  • Selected cells are tracked per sheet as (rowid, column_name) pairs in _selectedCells
  • Uses CellColorizer for visual highlighting — does not interact with VisiData's row-level selection system
  • Selection persists through sort and row reordering (uses stable rowid internally)
  • Alt+5 toggles the current cell on/off with each press

Registering the Plugin​

Add to ~/.visidatarc:

import sys
sys.path.insert(0, os.path.expanduser('~/.config/visidata/plugins'))
import cell_select

Or use the common-config loader pattern:

import sys
sys.path.insert(0, '/path/to/shared/plugins')
import cell_select

Customizing the Highlight Color​

Add to ~/.visidatarc:

vd.options.color_selected_cell = 'bold cyan on black'

Custom Plugin: Column Selection System​

The 42-column-selection.py plugin adds 18 commands for selecting, toggling, hiding, and operating on columns directly from the main sheet — without opening the Columns Sheet (Shift+C). Selected columns are highlighted in bold cyan for clear visual feedback.

This mirrors VisiData's row selection pattern (s/t/u) but for columns, using the Alt+ prefix which VisiData reserves for user customization.

Keybindings​

Selection:

KeyAction
Alt+sSelect current column
Alt+tToggle column selection
Alt+uUnselect current column
Alt+gsSelect all visible columns
Alt+guUnselect all columns (multi-key)
Alt+Shift+UUnselect all columns (single key)
Alt+gzToggle all columns selection

Hide / Unhide:

KeyAction
Alt+-Hide all selected columns
Alt+gvUnhide selected columns
Alt+gVUnhide all hidden columns

Bulk Type Operations:

KeyAction
Alt+g#Set type = int for selected columns
Alt+g%Set type = float for selected columns
Alt+g~Set type = str for selected columns
Alt+g$Set type = currency for selected columns
Alt+g@Set type = date for selected columns

Width Operations:

KeyAction
Alt+g_Set width for selected columns (prompts for value)
Alt+z_Auto-fit width for selected columns

Status:

KeyAction
Alt+:Show selected column names in status bar

Source​

~/.visidatarc.d/Keybindings/42-column-selection.py

How It Works​

  • Selected columns are tracked per sheet as a set of Column objects in TableSheet.selectedCols
  • Uses ColumnColorizer._make((8, 'color_selected_col', is_selected_col)) for bold cyan highlighting — note this uses the tuple constructor, not class instantiation
  • All commands use @TableSheet.api decorators for clean registration
  • State is session-only — selections clear when VisiData closes (intentional)

Kitty + tmux Compatibility​

Multi-key Alt+ sequences (e.g. Alt+gu) may not work reliably in Kitty + tmux. When you hold Alt across both letters, VisiData receives Alt+g then Alt+u — where Alt+u means "unselect current column," not "unselect all."

Workarounds:

SequenceHow it works
Esc g uRelease Alt, press g, then u — works reliably
Alt+Shift+USingle-key fallback for unselect-all

Single-key Alt+ bindings (Alt+s, Alt+-, Alt+gv, Alt+Shift+U) work directly in Kitty + tmux.

# Recommended workflow in Kitty + tmux
Alt+Shift+U # unselect all
Alt+s # select column
Alt+- # hide selected
Alt+gv # unhide selected

tmux tip: Set escape-time 0 in ~/.tmux.conf for cleaner Alt prefix resolution:

set -sg escape-time 0

Registering the Plugin​

This plugin loads automatically via the common-config .visidatarc.d/ loader pattern. If you want to use it standalone, add to ~/.visidatarc:

import sys
sys.path.insert(0, '/path/to/your/keybindings')
import column_selection

Or copy the file directly into ~/.config/visidata/plugins/ and import it.

Customizing the Highlight Color​

Add to ~/.visidatarc:

vd.option('color_selected_col', 'bold yellow on blue', 'color for selected columns')

Example Workflow​

vd data.csv

# Select columns to hide
Alt+s # select first column (e.g. 'id')
l # move right
Alt+s # select second column (e.g. 'internal_ref')
l
Alt+s # select third column (e.g. 'created_at')

# Hide them all at once
Alt+- # all 3 columns disappear

# Later, bring them back
Alt+gv # unhide the selected columns

Kitty + tmux Workflow​

vd data.csv

# Clear any previous selection
Alt+Shift+U # unselect all

# Select columns to hide
Alt+s # select first column
l
Alt+s # select second column
l
Alt+s # select third column

# Hide them all at once
Alt+- # all 3 columns disappear

# Later, bring them back
Alt+gv # unhide the selected columns

Custom Plugin: Tmux Copy​

The 41-tmux-copy.py plugin adds a zm keybinding that copies the current cell value to the tmux paste buffer, enabling cross-pane pasting with Ctrl+b ].

Keybindings​

KeyAction
zmCopy current cell to tmux paste buffer

Source​

~/.visidatarc.d/Keybindings/41-tmux-copy.py

How It Works​

  • Uses cursorDisplay to get the formatted cell value (same as zY for system clipboard)
  • Pipes the value to tmux load-buffer - via subprocess.run
  • Works with any tmux pane — paste in another pane with Ctrl+b ]

Usage​

# Copy a cell value
# Move to any cell, press:
zm # "copied cell to tmux buffer" appears in status

# Switch to another tmux pane
Ctrl+b ] # cell value is pasted

Prerequisite​

tmux must be running. The plugin does nothing if tmux is not available.

Custom Plugin: Registry Alias Launcher​

The registry_launcher.py plugin extends the standard o command with $alias support, so frequently used CSV sources registered in the VisiData listing registry can be opened directly from inside a running session.

The intent is one VisiData session and one prompt: press o, type $ plus the short alias you already know (vd-2, vd-dc, ...), and the registered file (or files) open as sheets in the current session. Pressing o, then $, then Enter opens an fzf picker over the whole registry, which removes the need for separate vd-* shell aliases just to launch a data source.

Usage​

# Inside VisiData:
o
open: $vd-2 # open the two-sheet demo entry

o
open: $ # press Enter → fzf picker over every registered alias

Matching​

InputMeaning
$vd-2Match a command name exactly
$vd013Match a registry ID
$wordpressCase-insensitive partial match
$vd-wp*Glob pattern match
/path/to/file.csvNormal VisiData file opening (unchanged)

Inputs without $ keep the stock o behavior, including normal filesystem path completion.

Source​

~/.config/visidata/plugins/registry_launcher.py

# common-config source:
/home/rezriz/github/common-config/visidata/plugins/registry_launcher.py

Registry:

/home/rezriz/github/cli-projects/visidata-listing/visidata-listing.csv

How It Works​

  • Replaces the default open-file implementation with vd.open_registry_or_file, so the o keybinding, the File menu entry, and CommandLog naming stay consistent.
  • Reads the registry CSV and resolves the typed query by exact command/rec_id, case-insensitive partial text, or fnmatch glob.
  • A custom completer mixes $alias completion with VisiData's built-in filename completion, so Tab still completes ordinary paths.
  • An empty query ($) or an ambiguous query opens an fzf picker via SuspendCurses; Esc cancels.
  • Every ;-separated path in the matched entry is pushed as a separate sheet in the current session; missing paths are reported in the status bar instead of failing the open.

Registering the Plugin​

Loaded automatically by the common-config plugin loader:

# .visidatarc.d/Plugins/10-plugins.py
import sys
sys.path.insert(0, '/home/rezriz/github/common-config/visidata/plugins')
import registry_launcher

For a standalone setup, drop the file into ~/.config/visidata/plugins/ and import it from ~/.visidatarc.

Configuration​

Point the plugin at a different compatible registry:

# ~/.visidatarc
vd.options.registry_path = "/path/to/another-registry.csv"

Requirements​

  • fzf must be on PATH for empty or ambiguous $ queries.
  • Targets the installed VisiData 3.0.2 interfaces, including VisiData's internal _completeFilename.
  • Restart VisiData after changing the plugin or the loader.

Hands-On Practice​

# Open VisiData and launch plugin index
vd -P open-plugins

# Browse available plugins
# Move cursor to a plugin you want to try
# Press Enter to install

# Or create a minimal custom status command:
mkdir -p ~/.config/visidata/plugins
cat > ~/.config/visidata/plugins/hello.py << 'EOF'
from visidata import Sheet
Sheet.addCommand('F12', 'hello-world', 'vd.status("Hello from plugin!")', 'Say hello')
EOF

# Add to ~/.visidatarc:
echo "import sys; sys.path.insert(0, '/root/.config/visidata/plugins'); import hello" >> ~/.visidatarc

# Test:
vd ~/github/practice-folder/visidata/03-join/01-servers.csv
# Press F12 → see "Hello from plugin!" in status bar

What's Next​