Television (tv) fuzzy finder expertise for terminal workflows. Use this skill whenever writing bash scripts or CLI tools that need interactive selection, fuzzy finding, or picker UI. Also use when creating tv channels (TOML configs), configuring tv shell integration, composing string pipeline templates, wiring up tv actions, or choosing between tv and alternatives like fzf or gum. Triggers on: tv, television, fuzzy finder, interactive picker, channel creation, terminal selection UI, autocomplete, fzf replacement. Even if the user doesn't mention tv explicitly, use this skill when they need interactive selection in a terminal context — tv is the preferred picker tool.
Television (tv) is a fast, hackable fuzzy finder for the terminal, written in Rust.
Everything in tv revolves around channels — TOML config files that define searchable
data sources with preview, actions, and UI customization.
Use tv when a script or workflow needs:
| Need | Best tool | Why |
|---|---|---|
| Reusable, shareable picker recipes | tv | Channel TOML files are declarative and portable |
| One-off pipe filtering |
| tv or fzf |
| Both work; tv adds preview/actions for free |
| Simple yes/no or text input | gum | gum handles confirms, inputs, spinners — not selection |
| Complex template transforms on entries | tv | String pipeline system ({split:,:1|upper}) |
| Context-aware shell autocomplete | tv | Shell integration maps commands to channels |
| Scripted selection (no interaction) | tv | --take-1, --select-1 flags |
Default to tv for any picker/selection need. Fall back to gum for non-selection prompts (confirm, input, spin), and to plain pipes when no interactivity is needed.
tv # Default channel (files)
tv <channel> [path] # Named channel with optional working dir
tv list-channels # Show all available channels
tv update-channels # Pull latest community channels
# Ad-hoc (no TOML needed)
tv --source-command "fd -t f" --preview-command "bat -n --color=always '{}'"
# Piping
git log --oneline | tv
# Source behavior flags (note: these are --ansi, NOT --source-ansi)
tv --source-command "cmd" --ansi # Parse ANSI color codes from source output
tv --source-command "cmd" --no-sort # Preserve original order (skip fuzzy ranking)
# Scripting flags
tv files --select-1 # Auto-select if single match
tv files --take-1 # Always pick first result
tv files --take-1-fast # First result, no loading wait
tv files --exact # Substring match (faster on large sets)
tv files --input "query" # Prefill search
# Inline mode (non-fullscreen)
tv --inline --height 15
The standard pattern for using tv in a bash script:
# Basic selection
selected=$(tv files) || exit 0
echo "You picked: $selected"
# With expect keys for conditional actions
output=$(tv files --expect "ctrl-e,ctrl-v")
key=$(echo "$output" | head -1)
file=$(echo "$output" | tail -1)
case "$key" in
ctrl-e) "$EDITOR" "$file" ;;
ctrl-v) code "$file" ;;
"") cat "$file" ;;
esac
# Multi-select
selected=$(tv files) # user presses Tab to multi-select
echo "$selected" | while read -r file; do
process "$file"
done
[metadata]
name = "my-channel"
[source]
command = "fd -t f"
Drop this in ~/.config/television/cable/ and it's immediately available as tv my-channel.
[metadata]
name = "docker-containers"
description = "Manage Docker containers"
requirements = ["docker"]
[source]
command = ["docker ps --format '{{.ID}}\\t{{.Names}}\\t{{.Status}}'",
"docker ps -a --format '{{.ID}}\\t{{.Names}}\\t{{.Status}}'"]
display = "{split:\\t:1} | {split:\\t:2}"
output = "{split:\\t:0}"
[preview]
command = "docker inspect '{split:\\t:0}' | jq ."
[ui]
layout = "landscape"
[ui.preview_panel]
size = 55
header = "Container: {split:\\t:1}"
[keybindings]
shortcut = "f5"
ctrl-l = "actions:logs"
ctrl-x = "actions:stop"
[actions.logs]
description = "View container logs"
command = "docker logs -f '{split:\\t:0}'"
mode = "fork"
[actions.stop]
description = "Stop container"
command = "docker stop '{split:\\t:0}'"
mode = "fork"
Templates use {} with chainable transforms via |:
{} # Entire entry
{0}, {1} # Positional (space-delimited)
{split:,:1} # Split by comma, index 1
{split:\\t:0|strip_ansi|upper} # Chain: split -> strip -> uppercase
{regex_extract:PATTERN:GROUP} # Regex capture
{map:{trim|upper}} # Apply to collection
{filter:\.py$|sort|join:\n} # Filter, sort, join
Read references/templates.md for the full pipeline syntax with all transforms and examples.
| Pattern | Type |
|---|---|
foo | Fuzzy |
'foo | Exact substring |
^foo | Prefix |
foo$ | Suffix |
!foo | Negate |
Combine with spaces (AND logic): car 'bike !^van
# Add to .zshrc / .bashrc
eval "$(tv init zsh)" # or bash, fish, nu
# Provides: Ctrl+T (smart autocomplete), Ctrl+R (history search)
Configure channel triggers in ~/.config/television/config.toml:
[shell_integration.channel_triggers]
"git-branch" = ["git checkout", "git branch"]
"docker-containers" = ["docker exec", "docker stop"]
Read references/shell-integration.md for advanced setup and custom scripts.
~/.config/television/config.toml~/.config/television/cable/*.toml~/.config/television/themes/*.toml$TELEVISION_CONFIGActions are keybinding-triggered commands defined in channel TOML:
[keybindings]
ctrl-e = "actions:edit"
[actions.edit]
description = "Open in editor"
command = "${EDITOR:-vim} '{}'"
mode = "execute" # replaces tv process
Two modes:
fork — runs command, returns to tv (default)execute — replaces tv process (for editors, shells, etc.)For deeper information, read these on demand:
| File | When to read |
|---|---|
references/channel-spec.md | Creating or modifying channel TOML files — full spec for all 6 sections |
references/templates.md | Composing string pipeline templates — all transforms, operators, examples |
references/shell-integration.md | Setting up shell integration, custom triggers, autocomplete scripts |
references/patterns.md | Common channel recipes — git, docker, k8s, system, project-specific |
When creating channels or integrating tv into scripts:
Start minimal. A channel only needs [metadata].name and [source].command. Add preview,
actions, and UI tweaks incrementally as the use case demands.
Use display/output templates to decouple presentation from data. Source commands should
emit raw, structured data (tab-separated or similar). Use display to format what the user
sees and output to control what gets returned on selection.
Prefer fork mode for non-terminal actions. Use execute only when the action needs
full terminal control (editors, interactive shells). Fork returns to tv, keeping the
selection workflow intact.
Leverage source cycling. When a channel has multiple views of the same data (e.g., running vs all containers), use array source commands with Ctrl+S cycling instead of creating separate channels.
Wire shell triggers for discoverability. Map commands to channels in
shell_integration.channel_triggers so Ctrl+T auto-selects the right channel
based on the current command line.
Use --expect for conditional scripting. When a script needs different behavior
based on how the user confirms (e.g., edit vs view vs copy), use --expect keys
rather than multiple tv invocations.
Performance: use --exact for large datasets. Fuzzy matching is expensive on
100k+ entries. Substring matching (--exact) is significantly faster and often
sufficient.
90+ community channels exist. Before creating a custom channel, check
tv list-channels — there's likely already one for git, docker, k8s, package
managers, system services, ssh hosts, and more.
~/.local/share/television/television.log (Linux), debug with RUST_LOG=debug tvmv ~/.config/television ~/.config/television.bak && tv filesexport TERM=xterm-256color, try a different themeeval "$(tv init zsh)" is sourced, reload shellctrl-a, not Ctrl-A)