Environment Variables - dathere/qsv GitHub Wiki

Environment Variables

Tier: Advanced

Note

Canonical reference: docs/ENVIRONMENT_VARIABLES.md. 85+ variables total β€” this page groups them by purpose and links the canonical reference for definitions.

Run qsv --envlist to see all active qsv-relevant env vars in your environment.

qsv also supports .env files. See docs/ENVIRONMENT_VARIABLES.md#env-file-support for the lookup order.

Quick reference β€” the most-used vars

Variable What it does
QSV_AUTOINDEX_SIZE Auto-create .idx for files > N bytes (and auto-refresh stale ones)
QSV_STATSCACHE_MODE auto (default), force (auto-create cache), or none
QSV_MAX_JOBS Cap the number of parallel jobs
QSV_LLM_BASE_URL, QSV_LLM_APIKEY, QSV_LLM_MODEL describegpt LLM config
QSV_DEFAULT_DELIMITER Fallback delimiter for stdin, unrecognized extensions, and output
QSV_SNIFF_DELIMITER Auto-detect the input delimiter
QSV_LOG_LEVEL, QSV_LOG_DIR Logging

I/O & format

  • QSV_DEFAULT_DELIMITER β€” the delimiter used when neither --delimiter nor a .csv/.tsv/.tab/.ssv extension sets one: stdin, other extensions, and output written to stdout. Default ,. It does not override --delimiter or a recognized extension.
  • QSV_SNIFF_DELIMITER β€” auto-detect the input delimiter; takes precedence over extensions and QSV_DEFAULT_DELIMITER, but not over --delimiter.
  • Precedence, highest first: --delimiter β†’ QSV_SNIFF_DELIMITER β†’ file extension β†’ QSV_DEFAULT_DELIMITER β†’ ,.
    • Exception: joinp, sqlp, scoresql and readstat always use tab for a .tsv/.tab path and semicolon for an .ssv path, whether reading it or writing it with --output, even when --delimiter is given.
  • QSV_SNIFF_PREAMBLE β€” auto-detect preamble line count
  • QSV_NO_HEADERS β€” treat the first row as data, not headers
  • QSV_TOGGLE_HEADERS β€” invert header behavior
  • QSV_COMMENT_CHAR β€” skip lines starting with this character
  • QSV_OUTPUT_BOM β€” add a UTF-8 BOM to outputs (Excel-friendly on Windows)
  • QSV_RDR_BUFFER_CAPACITY β€” reader buffer size (default 128 KB)
  • QSV_WTR_BUFFER_CAPACITY β€” writer buffer size (default 512 KB)
  • QSV_SKIP_FORMAT_CHECK β€” skip MIME-type inference for inputs

Performance & memory

  • QSV_AUTOINDEX_SIZE β€” auto-create / refresh index for files > N bytes
  • QSV_MAX_JOBS β€” max parallel jobs (default: all logical CPUs)
  • QSV_MEMORY_CHECK β€” enable pre-check that the file fits before running memory-mode commands
  • QSV_FREEMEMORY_HEADROOM_PCT β€” reserve N% of free RAM (default 20)
  • QSV_STATS_CHUNK_MEMORY_MB β€” per-chunk memory limit in stats
  • QSV_FREQ_CHUNK_MEMORY_MB β€” per-chunk memory limit in frequency
  • QSV_FREQ_HIGH_CARD_THRESHOLD β€” absolute cardinality threshold for HIGH_CARDINALITY classification
  • QSV_FREQ_HIGH_CARD_PCT β€” percentage-of-rowcount cardinality threshold
  • QSV_NO_ALLOC_TUNING β€” disable qsv's automatic jemalloc tuning (jemalloc builds only). By default qsv enables jemalloc background_thread purging where supported (Linux) at no extra memory cost, and on platforms without it (e.g. macOS) retains freed pages more aggressively

See Performance Tuning for how these interact.

Cache config

  • QSV_STATSCACHE_MODE β€” auto / force / none

  • QSV_CACHE_DIR β€” directory for qsv's persistent caches (default ~/.qsv-cache). It holds:

    • lookup tables downloaded by luau (qsv_register_lookup), template and validate
    • geocode's Geonames index, and its OpenCage and Geoclient result caches
    • get's download cache
    • describegpt's tag vocabularies (its LLM completion cache is set separately by --disk-cache-dir, default ~/.qsv-cache/describegpt)
    • viz's Census boundary and population caches

    It takes precedence over the --cache-dir option of describegpt, geocode, get, luau, template and validate.

  • QSV_GET_PART_SIZE β€” get byte-range part size for parallel downloads (default 8 MiB)

  • QSV_GET_CONCURRENCY β€” get parallel range-download workers (default 4, clamped 1–64)

  • QSV_DISKCACHE_TTL_SECS β€” fetch / fetchpost / describegpt disk-cache TTL (default 28 days)

  • QSV_DISKCACHE_TTL_REFRESH β€” extend TTL on cache hit

  • QSV_REDIS_CONNSTR β€” Redis connection string for fetch cache (default redis://127.0.0.1:6379/1)

  • QSV_FP_REDIS_CONNSTR β€” Redis connection for fetchpost cache (default db 2)

  • QSV_DG_REDIS_CONNSTR β€” Redis connection for describegpt cache (default db 3)

  • QSV_REDIS_MAX_POOL_SIZE β€” Redis connection pool size

  • QSV_REDIS_TTL_SECS β€” Redis cache TTL

  • QSV_REDIS_TTL_REFRESH β€” extend Redis TTL on cache hit

See Stats Cache & Caching and HTTP & Web.

AI & LLM

  • QSV_LLM_BASE_URL β€” OpenAI-compatible LLM endpoint for describegpt
  • QSV_LLM_APIKEY β€” API key for the LLM
  • QSV_LLM_MODEL β€” model name (e.g. openai/gpt-oss-20b, google/gemma-4-31b)
  • QSV_DUCKDB_PATH β€” DuckDB binary path (enables DuckDB SQL in describegpt & scoresql)
  • QSV_TEST_DESCRIBEGPT β€” enable describegpt tests (requires LM Studio with openai/gpt-oss-20b)

See AI & Documentation.

Web & HTTP

  • QSV_TIMEOUT β€” timeout in seconds for fetch, fetchpost, geocode, sniff, validate, describegpt, template, sample, snappy, luau (default 30). viz has no --timeout option but honors this variable for its Census requests. apply and get have their own --timeout but do not read this variable.
  • QSV_USER_AGENT β€” custom User-Agent header (supports $QSV_VERSION, $QSV_TARGET, $QSV_BIN_NAME, $QSV_COMMAND placeholders)
  • QSV_CKAN_API β€” CKAN action API endpoint for ckan:// URL scheme
  • QSV_CKAN_TOKEN β€” CKAN access token (only required for private resources)
  • Plus standard HTTP_PROXY, HTTPS_PROXY, ALL_PROXY, NO_PROXY. OS-level proxy configuration (macOS SystemConfiguration, Windows registry) is honored as well β€” in 23.0.1 and earlier by the full qsv binary only; New in 24.0.0: also by qsvlite, qsvdp and qsvmcp, which additionally decode responses by their Content-Type charset instead of lossy UTF-8

Geocoding

  • QSV_GEOIP2_FILENAME β€” MaxMind GeoLite2 binary database filename (default GeoLite2-City.mmdb)
  • QSV_GEOCODE_INDEX_FILENAME β€” custom Geonames index file
  • QSV_OPENCAGE_API_KEY β€” API key for the geocode opencage / opencagenow online geocoding subcommands (the --api-key flag, if given, takes precedence)
  • QSV_GEOCLIENT_API_KEY β€” NYC Geoclient subscription key for the geocode geoclient / geoclientnow subcommands (Unreleased, after 24.0.0, #4789). Get one free at https://api-portal.nyc.gov by subscribing to "Geoclient V2 User". --api-key takes precedence. qsv sends it as a request header, never in the URL. Not needed for a self-hosted Geoclient.
  • QSV_GEOCLIENT_API_URL β€” base URL of a self-hosted Geoclient, e.g. http://localhost:8080/geoclient/v2; no key is needed then (default https://api.nyc.gov/geoclient/v2; Unreleased, after 24.0.0)

See Geospatial.

Visualization

All require the viz feature (bundled in the prebuilt qsv/qsvpy binaries and any all_features build).

  • QSV_VIZ_MAX_POINTS β€” max data points viz smart embeds per panel before uniform downsampling (default 150000)
  • QSV_VIZ_CDN β€” load the plotly.js runtime from its CDN (pinned to the embedded version) instead of inlining it; shrinks a smart dashboard by ~1.9 MB but requires network access when the page is viewed β€” intended for web-published charts. Governs only the plotly.js bundle; figure payloads still follow QSV_VIZ_NO_COMPRESS
  • QSV_VIZ_NO_COMPRESS β€” emit fully plain-text HTML (inline plotly.js and figures, decimal map arrays) instead of the default gzip+base64 payloads; larger output, but works on pre-2023 browsers and strict-CSP embeds and is greppable
  • QSV_VIZ_DICT_FRESH β€” set to 1 to force viz smart --dictionary infer to re-run the LLM: ignores an existing <stem>.schema.json sidecar and bypasses describegpt's completion cache, overwriting the sidecar on success. Without it, an existing sidecar is reused as-is (no LLM call) β€” which is what makes hand-tuning a dictionary stick
  • QSV_CENSUS_API_KEY β€” US Census Data API key, required by viz choropleth --denominator census (and the viz smart rate panel it drives) to fetch ACS population denominators. The Bureau redirects unkeyed requests to a "Missing Key" page rather than refusing them, so qsv asks for the key up front. Request a free one
  • QSV_VIZ_BOUNDARY_CACHE_TTL_DAYS β€” days a boundary set fetched by viz --geojson auto (Census TIGERweb polygons) stays fresh in the cache before re-fetching; within the TTL a repeated command makes no network request at all (default 30)
  • QSV_VIZ_DENOMINATOR_CACHE_TTL_DAYS β€” days a population denominator fetched by viz --denominator census stays fresh in the cache (default 30)
  • QSV_GEOJSON_SHORTCUTS β€” a JSON map of shortcut name β†’ {path, id} so viz --geojson <name> resolves by name instead of a full path/URL; the shortcut's id sets --feature-id-key when you don't pass one. Used for region maps and point-in-polygon binning

Static image export (third-party)

These two are not QSV_* variables and do not appear in qsv --envlist β€” they are read directly by plotly_static, which backs viz static image export. They only matter when writing a chart to PNG/SVG/PDF/JPEG/WebP.

  • WEBDRIVER_PATH β€” full path to the chromedriver to render with. On 23.0.1 and earlier, you had to set it yourself whenever static export couldn't find a driver. New in 24.0.0: when unset, or not pointing at an executable file, qsv probes $WEBDRIVER_INSTALL_PATH, ~/.local/bin, your PATH, then (Unix only) /opt/homebrew/bin, /usr/local/bin and /usr/bin, and sets the variable to the first chromedriver it finds β€” which is what repairs prebuilt binaries, whose baked-in path points into the build machine's home directory (#4620). Firefox/geckodriver is not supported. The driver's MAJOR version must match your Chrome
  • BROWSER_PATH β€” full path to a Chrome/Chromium binary, when it isn't the system default

See Visualization.

Stats output config

  • QSV_STATS_STRING_MAX_LENGTH β€” truncate long min/max string values
  • QSV_STATS_SEPARATOR β€” separator for multi-value MODE/ANTIMODE/PERCENTILE cells (default |)
  • QSV_ANTIMODES_LEN β€” max characters when listing antimodes (default 100)

Date parsing

  • QSV_PREFER_DMY β€” parse dates as DMY instead of MDY (affects datefmt, frequency, joinp, moarstats, pivotp, sample, schema, sniff, stats, tojsonl)

Regex

  • QSV_REGEX_UNICODE β€” make search / searchset / replace unicode-aware (slower; default off)

Color / display

  • QSV_FORCE_COLOR β€” force color output even in CI / pipes
  • QSV_THEME β€” DARK or LIGHT (overrides terminal-bg detection)
  • QSV_TERMWIDTH β€” override detected terminal width

See Selection & Inspection β†’ color.

Logging

  • QSV_LOG_LEVEL β€” error / warn / info / trace / debug (default off; qsvmcp defaults to info)
  • QSV_LOG_DIR β€” log file directory (auto-created if missing)
  • QSV_LOG_UNBUFFERED β€” write log lines synchronously
  • QSV_PROGRESSBAR β€” enable --progressbar on commands that support it
  • QSV_NO_UPDATE β€” disable qsv --update self-update version check
  • QSV_ERROR_FORMAT β€” set to json to end a failed run with one JSON line on stderr ({"error":{"kind","level","message","exit_code","command","qsv_version"}}) instead of free text; a no_match exit also gets a line. For programs driving qsv as a subprocess; qsv-client sets it for you (25.0.0)

See docs/Logging.md.

Polars-specific

Polars commands respect Polars's own env vars:

  • POLARS_VERBOSE β€” verbose logging to stderr
  • POLARS_PANIC_ON_ERR β€” panic on Polars errors
  • POLARS_BACKTRACE_IN_ERR β€” include backtrace in Polars errors
  • QSV_POLARS_FLOAT_PRECISION β€” float precision for Polars β†’ CSV conversion
  • QSV_POLARS_DECIMAL_SCALE β€” Polars Decimal scale (default 5)

MCP server (qsvmcp only)

The MCP server has its own dedicated environment variable namespace β€” see MCP Server and the canonical reference's MCP section.

Key ones:

  • QSV_MCP_BIN_PATH β€” full path to qsv/qsvmcp binary
  • QSV_MCP_WORKING_DIR β€” default working directory (supports ${HOME}, ${DOWNLOADS}, ${DOCUMENTS}, …)
  • QSV_MCP_ALLOWED_DIRS β€” additional accessible directories (colon-separated on Unix)
  • QSV_MCP_OPERATION_TIMEOUT_MS β€” operation timeout (default 600,000 = 10 min)
  • QSV_MCP_MAX_OUTPUT_SIZE β€” max bytes before output is saved to disk (default 50 MB)
  • QSV_MCP_MAX_CONCURRENT_OPERATIONS β€” concurrency cap (default 3 in plugin mode, 1 in extension mode)
  • QSV_MCP_LOG_LEVEL β€” info / error / off (separate from QSV_LOG_LEVEL)
  • QSV_MCP_USE_DUCKDB β€” enable DuckDB SQL when available
  • QSV_MCP_OUTPUT_FORMAT β€” tsv (default) or csv
  • QSV_MCP_ENABLE_APPS β€” enable MCP Apps UI features such as the qsv_browse_directory interactive browser (default true)
  • QSV_MCP_SANITIZE_ERRORS β€” strip absolute paths (usernames, directory layout) from command and error output before returning it to the client (default true). Set false only for local debugging β€” sanitization is what protects hosted/shared deployments
  • QSV_MCP_EXPOSE_ALL_TOOLS β€” expose all tools at startup instead of deferred loading (core tools only). For AI clients that don't support deferred tool loading (default: auto-detect)
  • QSV_MCP_SERVER_INSTRUCTIONS β€” custom server instructions that override the built-in workflow guidance (default: empty = built-in)
  • QSV_MCP_MAX_EXAMPLES β€” max examples included in tool descriptions, 0–20 (default 5; 0 disables)
  • QSV_MCP_MAX_FILES_PER_LISTING β€” max files returned in one directory listing (default 1,000)
  • QSV_MCP_CONVERTED_LIFO_SIZE_GB β€” size cap for the converted-file cache (Excelβ†’CSV, JSONLβ†’CSV) in GB, LIFO eviction (default 1.0)
  • QSV_MCP_DUCKDB_BIN_PATH β€” full path to the DuckDB binary (default: auto-detect from PATH)
  • QSV_MCP_NOTIFY_UPDATES β€” log update notifications when a new version is available (default true)
  • QSV_MCP_AUTO_REGENERATE_SKILLS β€” run qsv --update-mcp-skills automatically when the qsv version changes (default false)
  • QSV_MCP_GITHUB_REPO β€” repository used for update checks (default dathere/qsv)
  • QSV_MCP_CHECK_UPDATES_ON_STARTUP β€” check GitHub for a newer qsv release at startup (default true)
  • QSV_MCP_CONCURRENCY_WAIT_TIMEOUT_MS β€” how long a request waits for a free concurrency slot before being rejected; 0 rejects immediately (default 120,000 = 2 min)
  • QSV_MCP_PLUGIN_MODE β€” override plugin-mode detection; set true for non-Claude agent CLIs (e.g. Gemini CLI) whose host already provides filesystem isolation (default: auto-detect)
  • MCPB_EXTENSION_MODE β€” set automatically by Claude Desktop when qsv runs as an extension; enables stricter validation (fully qualified qsv path, version β‰₯ 17.0.0). Don't set it yourself

Claude Cowork plugin

  • QSV_NO_COWORK_SETUP β€” set to 1 to stop the Cowork plugin from auto-deploying its workflow-guidance CLAUDE.md. Set it in your shell before launching Claude Code

Dotenv (.env) files

qsv loads .env files in this order:

  1. The file at QSV_DOTENV_PATH if set (overrides everything; set to <NONE> to disable)
  2. .env in the current working directory
  3. <binary-name>.env next to the qsv binary itself (e.g. /usr/local/bin/qsv.env)

Set QSV_DOTENV_PATH=<NONE> to disable dotenv processing entirely.

Dependencies

Some env vars come from qsv's dependencies, not qsv itself:

Discover at runtime

qsv --envlist
# Lists every QSV_* variable currently set in your environment,
# plus allocator-specific (MIMALLOC_*/JEMALLOC_*) and proxy vars.
qsv --capabilities
# JSON: binary name, version, target, features (with Polars/Luau/Python versions)
# and installed commands. Also in qsvlite and qsvdp (25.0.0).

See also

⚠️ **GitHub.com Fallback** ⚠️