Open-Source Wikis

/

Starship

/

Subsystems

/

Statusline integration

starship/starship

Statusline integration

The starship statusline subcommand renders prompts for non-shell statuslines. Today it has one provider: Claude Code.

Flow

sequenceDiagram
    participant ClaudeCode as Claude Code
    participant Main as src/main.rs
    participant Print as src/print.rs
    participant Statusline as src/utils/statusline.rs
    participant Context

    ClaudeCode->>Main: pipes JSON | starship statusline claude-code
    Main->>Print: prompt_with_claude_code(props, Target::Profile("claude-code"))
    Print->>Statusline: serde_json::from_reader(stdin) → ClaudeCodeData
    Print->>Context: Context::new(...)
    Print->>Context: with_claude_code_data(data)
    Note over Context: shell = Shell::Unknown (no real shell)
    Print->>Print: get_prompt(context)
    Note over Print: target picks up<br/>internal_profiles["claude-code"]
    Print-->>ClaudeCode: rendered string

Data shape

ClaudeCodeData and friends are defined in src/utils/statusline.rs:

pub struct ClaudeCodeData {
    pub cwd: Option<String>,
    pub model: ModelInfo,
    pub context_window: ContextWindow,
    pub cost: Option<CostInfo>,
    pub workspace: Option<Workspace>,
}

All deserialization fields use #[serde(default)] so missing fields don't fail parsing. If stdin is empty or invalid, serde_json::from_reader returns an error; prompt_with_claude_code logs it at error level and falls back to ClaudeCodeData::default(), which means every Claude module returns None and the prompt renders as if Claude data is absent.

Built-in profile

The "claude-code" profile is registered in default_profiles() in src/configs/starship_root.rs:

pub fn default_profiles() -> IndexMap<String, String> {
    IndexMap::from_iter([(
        "claude-code".to_string(),
        "$claude_model$git_branch$claude_context$claude_cost".to_string(),
    )])
}

It is stored separately from the user's [profiles] table on StarshipRootConfig:

pub user_profiles: IndexMap<String, String>,     // from TOML
#[serde(skip)]
pub internal_profiles: IndexMap<String, String>, // hardcoded defaults

The renderer in print::load_formatter_and_modules looks up Target::Profile(name) first in user_profiles, then in internal_profiles. Users can override the built-in by defining [profiles] claude-code = "..." in their starship.toml — see the test_prefer_user_profile test in src/print.rs.

Why shell = Unknown

The Claude Code statusline is not a real shell. There is no PROMPT_COMMAND, no cwd from process state, no SSH session, and no signal-handling. Setting context.shell = Shell::Unknown (which prompt_with_claude_code does explicitly) prevents shell-specific code paths in modules like character (which has vi-mode handling per shell) from misfiring.

Provider extensibility

The provider is a clap-derive enum:

#[derive(Debug, Clone, Copy, PartialEq, Eq, ValueEnum)]
enum Statuslines {
    #[clap(alias = "claude")]
    ClaudeCode,
}

Adding a second provider (say "cursor" for Cursor's status line) means:

  • Add a variant to Statuslines.
  • Add a JSON shape in src/utils/statusline.rs (and re-export from src/context.rs).
  • Add cwd: ... field on Context if needed (currently only claude_code_data lives there; you'd add <provider>_data: Option<...>).
  • Add a built-in profile in default_profiles.
  • Wire the new provider in the match block of Commands::Statusline in src/main.rs.
  • Write modules that read the new context field.

Entry points for modification

  • Override the built-in claude-code profile: define [profiles] claude-code = "..." in your starship.toml.
  • Disable the timer/cost separately: set [claude_cost] disabled = true and similar in your starship.toml.
  • Pipe in a different JSON shape: see provider extensibility above.
  • Stop reading stdin: replace the serde_json::from_reader(stdin) call in prompt_with_claude_code with a direct ClaudeCodeData::default() (only useful for testing).

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

Statusline integration – Starship wiki | Factory