Centralize provider caching and rate-limit handling, then add Domain/URL/Hash IOC types and safer VT/IPInfo key resolution so lookups stay reliable on free-tier APIs.
VisiData Config + Plugins
This folder contains a VisiData config.py (symlinked from visidatarc) plus a small set of local plugins under plugins/.
Install
The installer links (or copies) the config and plugins into VisiData’s per-user directory.
./install.sh --link # default, symlinks into place
./install.sh --copy # copies into place
./install.sh --deps # installs optional Python deps into $VD_DIR/plugins-deps
On VisiData 3.3, $VD_DIR defaults to:
- macOS:
~/Library/Preferences/visidata - Linux:
${XDG_CONFIG_HOME:-~/.config}/visidata
Plugins
Plugins are installed into $VD_DIR/plugins/ and imported via the top-level plugins package.
plugins/hidecol.py
Adds a command to hide columns that are empty or constant across all rows.
- Command:
tke-hidecol - Menu:
Column -> Hide -> empty/superfluous columns
plugins/iptype.py
Adds a custom IP datatype that supports:
- IPv4 + IPv6 addresses
- CIDR networks (e.g.
192.168.7.0/24) - Correct sorting (numeric, by version)
- Membership test operator:
ip * net(andnet * ip) - Normalized lookup/enrichment properties, accessible as attributes in expressions
Type + Command
- Type converter:
ip(...) - Type name:
IP - Command:
type-ip(setscursorCol.type=ip)
Operations
Membership test:
ipcol * "192.168.7.0/24"->True/False"192.168.7.0/24" * ipcol->True/False
Attributes (on IP typed cells)
Lookup objects expose both normalized fields and raw response data:
ipcol.ipinfo.countryipcol.ipinfo.data.<any_json_field>ipcol.asn.asn,ipcol.asn.name,ipcol.asn.countryipcol.asn.data.<any_json_field>ipcol.vt.verdict(e.g."3/94"),ipcol.vt.malicious,ipcol.vt.total,ipcol.vt.category(alias:ipcol.vt.type)ipcol.vt.data.<any_json_field>ipcol.geo.*(best-available geo: prefers MaxMind mmdb, else free HTTP providers)ipcol.maxmind.*(offline-only MaxMind lookup; empty if no mmdb)
Caching
All lookup providers cache results in a local sqlite+pickle DB (default ~/.visidata_cache.db).
Lookup Providers + Keys
Options (set in config.py / visidatarc):
options.tke_cache_db_path="~/.visidata_cache.db"options.tke_lookup_cache_ttl=86400options.tke_lookup_error_ttl=300options.tke_lookup_timeout=10options.tke_ipinfo_token="..."(optional; ipinfo can work without it)options.tke_ipapi_key="..."(optional)options.tke_vt_api_key="..."(required for VT lookups unless using~/.virustotal_api_key)options.tke_maxmind_mmdb_path="/path/to/GeoLite2-City.mmdb"(optional)
Env var equivalents:
IPINFO_TOKEN,IPAPI_KEYVT_API_KEYorVIRUSTOTAL_API_KEY(also supports~/.virustotal_api_key)MAXMIND_MMDB_PATHorGEOIP_MMDB_PATH
MaxMind (offline “free” GeoLite2) support:
- Place a
GeoLite2-City.mmdb/GeoLite2-Country.mmdbfile in$VD_DIR/, or setoptions.tke_maxmind_mmdb_path.
plugins/iplib.py
Pure-Python library used by iptype.py for:
- Normalized info classes (
IPInfo,ASNInfo,VTInfo,GeoInfo) JSONNodewrapper (.data.<field>) for safe attribute-style access into raw dict/list JSON- Parsing/normalization helpers for each provider’s response shape
This file intentionally does not import VisiData so it can be validated outside the VisiData runtime.
Config: visidatarc
This repo’s visidatarc is intended to be installed as VisiData’s config.py:
$VD_DIR/config.py(VisiData 3.3 default)- and also
~/.visidatarcas a legacy fallback
It currently contains:
- display/date format options
- a sqlite+pickle caching decorator and a set of general-purpose helpers (aggregators, timestamp parsing, “dirty” JSON parsing, etc)
Are the visidatarc functions superseded?
Partially:
- The IP-centric lookups and normalized attribute access are now primarily handled by
plugins/iptype.pyon typed values (e.g.ipcol.geo.country_code). - Many other helpers in
visidatarc(aggregators likeavgdiff, parsing/time conversion helpers, etc.) are still independent and useful.
Keeping old + new side-by-side (without duplicating code)
Yes. The cleanest pattern in VisiData is:
- Put shared logic into a module under
plugins/(so it’s onsys.pathvia$VD_DIR). - In
visidatarc, import and expose thin wrappers (or just import the module and usemodule.func(...)in expressions).
Concretely:
plugins/iplib.pyalready holds parsing/normalization shared by the IP type.- If you have legacy functions in
visidatarcthat overlap with the new IP lookups, refactor those functions into a shared module (e.g.plugins/lookups.py) and have bothvisidatarcandplugins/iptype.pycall into it.
This keeps backward-compatible names available while ensuring caching/auth/provider behavior is implemented in one place.