How bat's Configuration System Works: File-Based CLI Argument Management

bat's configuration system uses a plain-text file at ~/.config/bat/config that stores command-line arguments, which are parsed at startup and merged with system-wide settings, environment variables, and explicit CLI flags.

The bat syntax-highlighting pager implements a lightweight, file-based configuration system that mirrors its command-line interface. Unlike complex configuration formats, bat's configuration system treats each line in a config file as if it were a command-line argument, allowing users to persist any valid flag without learning new syntax.

Core Components of bat's Configuration System

The Configuration File Structure

The user configuration file lives at ~/.config/bat/config on Linux and macOS, or %APPDATA%\bat\config on Windows. This plain-text file contains one command-line argument per line, with comments starting with #.

In src/bin/bat/config.rs, the config_file() function resolves this path using the directories crate, while get_args_from_config_file() handles reading and concatenating contents:

// From src/bin/bat/config.rs
pub fn config_file() -> Option<PathBuf> {
    env::var("BAT_CONFIG_PATH")
        .ok()
        .map(PathBuf::from)
        .or_else(|| PROJECT_DIRS.config_dir().join("config").into())
}

System-Wide Configuration

Administrators can set defaults for all users via system-wide configuration files. The system_config_file() function locates these at /etc/bat/config on Unix systems or C:\ProgramData\bat\config on Windows.

The system configuration is read first, followed by the user configuration, allowing users to override system defaults while inheriting common settings.

Environment Variable Overrides

bat's configuration system recognizes several environment variables that expand into command-line arguments:

  • BAT_OPTS: Raw argument string appended directly to the command line
  • BAT_CONFIG_PATH: Override the default config file location
  • BAT_THEME, BAT_THEME_DARK, BAT_THEME_LIGHT: Theme selection
  • BAT_PAGER, BAT_PAGING: Pager configuration
  • BAT_TABS: Tab width
  • BAT_STYLE: Display components (numbers, grid, header, etc.)

In src/bin/bat/config.rs, the get_args_from_env_vars() function maps these to --flag=value pairs, while get_args_from_env_opts_var() parses the free-form BAT_OPTS string using shell_words::split.

How bat Reads and Merges Configuration

The configuration loading workflow follows a strict precedence order, implemented in src/bin/bat/config.rs:

  1. System config is located via system_config_file() and read first
  2. User config is located via config_file() and appended to the system config
  3. Environment variables are converted to arguments via get_args_from_env_vars() and get_args_from_env_opts_var()
  4. CLI arguments passed directly to the executable are appended last

The get_args_from_str() function parses configuration file contents using shell_words::split, which properly handles quoted strings and escape sequences. This produces a Vec<OsString> that mirrors actual command-line arguments.

Finally, this merged argument vector is passed to clap for parsing into the Config struct defined in src/config.rs:

// Simplified representation from src/config.rs
pub struct Config {
    pub language: Option<String>,
    pub theme: String,
    pub style_components: Vec<StyleComponent>,
    pub tab_width: usize,
    pub paging_mode: PagingMode,
    pub pager: Option<String>,
    // ... additional fields
}

Practical Configuration Examples

Generating a Starter Configuration

bat includes a utility to generate a template configuration file with all common options commented out:

bat --generate-config-file

This invokes the generate_config_file() function, which creates the parent directories if needed and writes a skeleton file to the default config location.

Common User Configurations

A typical ~/.config/bat/config might look like this:


# Use the TwoDark theme for syntax highlighting

--theme="TwoDark"

# Display line numbers, Git changes, and file headers

--style="numbers,changes,header"

# Enable italic text if the terminal supports it

--italic-text=always

# Map Arduino .ino files to C++ syntax highlighting

--map-syntax "*.ino:C++"

# Set tab width to 4 spaces

--tabs=4

Programmatic Access in Rust

Applications embedding bat can replicate the configuration loading process:

use bat::config::Config;
use std::ffi::OsString;

// Collect arguments from all configuration sources
let mut args: Vec<OsString> = Vec::new();

// Add config file arguments
if let Ok(config_args) = bat::bin::bat::config::get_args_from_config_file() {
    args.extend(config_args);
}

// Add environment variable arguments
if let Ok(env_opts) = bat::bin::bat::config::get_args_from_env_opts_var() {
    args.extend(env_opts);
}
args.extend(bat::bin::bat::config::get_args_from_env_vars());

// Parse into Config struct
let config = Config::parse_from(args);

Summary

  • bat's configuration system treats configuration files as persistent command-line arguments, with one flag per line in ~/.config/bat/config.
  • The system merges configuration in strict order: system-wide config → user config → environment variables → explicit CLI arguments.
  • Key implementation files include src/bin/bat/config.rs (loading and parsing) and src/config.rs (the Config struct definition).
  • Environment variables like BAT_OPTS, BAT_THEME, and BAT_CONFIG_PATH provide additional override mechanisms.
  • Use bat --generate-config-file to create a template configuration with all available options.

Frequently Asked Questions

Where does bat store its configuration file?

By default, bat stores its configuration file at ~/.config/bat/config on Linux and macOS, or %APPDATA%\bat\config on Windows. You can override this location by setting the BAT_CONFIG_PATH environment variable to a custom file path.

What format does bat's configuration file use?

bat's configuration file uses a simple line-based format where each line represents a command-line argument. Comments start with #, and values containing spaces should be quoted. For example, --theme="TwoDark" or --style=numbers,changes. This format is parsed using shell_words::split in src/bin/bat/config.rs.

Can I set system-wide defaults for all users?

Yes, administrators can create a system-wide configuration file at /etc/bat/config on Unix systems or C:\ProgramData\bat\config on Windows. The system_config_file() function in src/bin/bat/config.rs locates this file, and its settings are loaded before user-specific configurations, allowing users to override system defaults while inheriting common settings.

How do environment variables interact with the configuration file?

Environment variables are processed after configuration files but before explicit command-line arguments. Specific variables like BAT_THEME, BAT_PAGER, and BAT_TABS are mapped to their corresponding command-line flags, while BAT_OPTS accepts raw argument strings. This hierarchy ensures that CLI flags always take highest precedence, followed by environment variables, then user config, and finally system config.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →