Open-Source Wikis

/

Starship

/

Subsystems

/

Configuration

starship/starship

Configuration

How a starship.toml file becomes the typed structs that modules read. The work is split between src/config.rs (the runtime loader and style parsing) and src/configs/ (the per-module <Name>Config structs).

File resolution

The file path is resolved by get_config_path_os in src/context.rs:

  1. $STARSHIP_CONFIG, if set, wins.
  2. Otherwise: ~/.config/starship.toml.
  3. If neither exists, the config is empty and every module uses its Default impl.

StarshipConfig::initialize loads and parses the TOML via the toml crate. Parse errors are logged at error level and the file is treated as missing — so a broken config doesn't break the prompt entirely, it just resets to defaults.

graph TD
    Env["$STARSHIP_CONFIG<br/>or ~/.config/starship.toml"] --> Load["StarshipConfig::initialize<br/>(src/config.rs)"]
    Load --> Toml["toml::from_str<br/>→ toml::Table"]
    Toml --> Root["StarshipRootConfig::load<br/>(src/configs/starship_root.rs)"]
    Toml --> Get["StarshipConfig::get_module_config(name)<br/>per-module lookup"]
    Get --> Mod["<Name>Config::try_load(value)<br/>via ModuleConfig trait"]
    Mod --> Default["fallback to <Name>Config::default()"]

StarshipConfig

A thin wrapper around Option<toml::Table> that exposes:

  • get_config(&["a", "b"]) — walk into nested tables, returning Option<&toml::Value>.
  • get_module_config("rust") — sugar for get_config(&["rust"]).
  • get_custom_module_config("foo") — sugar for get_config(&["custom", "foo"]).
  • get_custom_modules() / get_env_var_modules() — return the entire custom / env_var sub-tables.

A subtle behavior: get_config walks every key except the last and asserts each is a table. If a non-table appears partway, it logs at trace level and returns None. This makes typos like [git_status.disable] (note the missing d) fail silently with a log message rather than crashing.

ModuleConfig trait

Every module's config struct implements ModuleConfig<'a, E> (defined in src/config.rs):

pub trait ModuleConfig<'a, E> where Self: Default, E: SerdeError {
    fn from_config<V: Into<ValueRef<'a>>>(config: V) -> Result<Self, E>;
    fn load<V: Into<ValueRef<'a>>>(config: V) -> Self;
    fn try_load<V: Into<ValueRef<'a>>>(config: Option<V>) -> Self;
}

The blanket impl on T: Deserialize<'a> + Default is what makes the boilerplate-free pattern work. from_config:

  1. Wraps the toml::Value in a ValueDeserializer (defined in src/utils/serde.rs).
  2. Calls T::deserialize(deserializer).
  3. On error, if the message contains "Unknown key", switches to a tolerant deserializer (with_allow_unknown_keys()) and retries — that way a typo in one field warns the user but doesn't blow away the rest of their config.

try_load(Some(table)) returns the parsed config; try_load(None) returns Self::default().

FullConfig and StarshipRootConfig

StarshipRootConfig (src/configs/starship_root.rs) holds the top-level prompt knobs: format, right_format, continuation_prompt, scan_timeout, command_timeout, add_newline, follow_symlinks, palette, [palettes.<name>], and the user/internal [profiles] tables.

FullConfig (src/configs/mod.rs) is a struct of all per-module configs flattened together. It is only used for two purposes:

  • print-config --default deserializes a default FullConfig, converts it to TOML, and prints it.
  • The config-schema feature uses schemars::schema_for!(FullConfig) to generate the JSON Schema at .github/config-schema.json.

FullConfig is not used at prompt time — modules look up their own subset via Context::new_module(name) (which reads the named subtable) and <Name>Config::try_load.

The JSON Schema

schemars generates a JSON Schema from FullConfig when the config-schema feature is enabled. Each per-module config:

  • derives JsonSchema (via the cfg_attr macro pattern shown below).
  • declares schemars(deny_unknown_fields) to flag typos in editors.
  • exports the doc comment on each field as the schema's description.
#[derive(Clone, Deserialize, Serialize)]
#[cfg_attr(feature = "config-schema",
           derive(schemars::JsonSchema),
           schemars(deny_unknown_fields))]
#[serde(default)]
pub struct AwsConfig<'a> { /* ... */ }

The CI workflow check_if_config_schema_up_to_date regenerates the schema and fails if it differs from .github/config-schema.json — see .github/workflows/workflow.yml.

Style strings

Style strings live in user-supplied format strings as [text](style). Parsing is in src/config.rs:

  • parse_style_string(s, palettes) splits the space-separated tokens.
  • Each token is either a color (red, #abc, 255, palette.foo), an attribute (bold, italic, underline, dimmed, inverted), a background (bg:<color>), none (clear style), prev_fg / prev_bg (refer to the previous segment), or invalid (logged and skipped).
  • The result is a crate::config::Style (a thin wrapper over nu_ansi_term::Style that supports the prev_fg/prev_bg indirections).

Style::to_ansi_style(prev_style) resolves any prev_* indirections at render time using the previous segment's style, which is what makes powerline-style transitions work cleanly.

Palettes

Palettes are user-defined named color tables:

palette = "ocean"
[palettes.ocean]
primary = "#0bc5ea"
accent = "#f6d860"

Style resolution walks the active palette before falling back to native colors. palette.foo references resolve to the palette entry; bare names like foo are resolved as palette entries first and then as nu-ansi-term color names.

Wrappers and helpers

| Helper | Purpose | | --------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------- | | VecOr<T> | Field that accepts either a single T or a Vec<T> in TOML. Used heavily in detection lists (e.g. command = "node --version" vs command = ["node", "--version"]). | | Either<A, B> | Untagged enum used by VecOr and by custom's when = true | "cmd". | | deserialize_style | Custom serde deserializer that yields a parsed Style directly. | | ValueDeserializer (in src/utils/serde.rs) | Custom serde deserializer that wraps toml::Value and emits friendly "Unknown key" errors. |

Editing config from the CLI

The starship config <key> <value> and toggle <key> commands operate on the user's TOML file via toml_edit::DocumentMut, which preserves comments and formatting. The implementation lives in src/configure.rs and is described in Configure subcommands.

Entry points for modification

  • New module config field — add to the struct in src/configs/<name>.rs, set its default, regenerate the schema (cargo run --features config-schema -- config-schema > .github/config-schema.json).
  • New top-level field (palette key, profile, etc.) — add to StarshipRootConfig in src/configs/starship_root.rs. Update the docs in docs/config/README.md.
  • New style token — extend parse_style_string in src/config.rs. Note that the Style wrapper carries optional bg/fg PrevColor for the indirection feature.
  • Different default config path — edit get_config_path_os in src/context.rs.

Built by Factory AutoWiki from public repository content. It is a generated preview for codebase exploration, not source-maintained documentation.

Configuration – Starship wiki | Factory