ColorCoder: Trigger-Driven Terminal Colors#

Implements the colorcode console script: at every shell prompt, the shell invokes it with the current directory and/or the last command name and exit status, and ColorCoder decides which Irix color (if any) to apply by emitting an OSC 11 escape sequence to the terminal. Trigger rules are read from a user YAML config and cached with pickle between prompts.

A global manual override can be set with colorcode set <color> and cleared with colorcode clear; while active it takes absolute precedence over all trigger rules. colorcode multiset <color>... persists a separate override for every affected Kitty window, so each manual pane color also survives later directory changes. Calling colorcode clear from one of those panes removes only that pane’s assignment.

Named Radix chambers#

clcm is the shell alias for colorcode multiset. Give it one chamber name to color every window in the current Kitty tab; its four colors repeat when the tab has more than four windows. Each chamber begins with a quiet Radix neutral, then travels through three related non-neutral hues.

clcm fern

CLI alias

Full name

Colors

fern

Fernfolk

sage, grass, green, lime

moss

Mossglow

olive, jade, mint, teal

tide

Tideline

slate, cyan, sky, blue

rain

Rainspell

gray, blue, indigo, iris

violet

Violetveil

mauve, violet, purple, plum

rose

Rosewater

mauve, pink, crimson, ruby

poppy

Poppyfire

sand, red, tomato, orange

sun

Sunhush

bronze, yellow, amber, gold

copper

Copperleaf

bronze, brown, clay, magma

dusk

Duskline

gray, iris, indigo, denim

The aliases apply only when supplied alone: clcm violet selects the Violetveil chamber, while a literal list such as clcm violet blue keeps its existing behavior.

Type Aliases#

irix.colorcode.DirTrigger = DirTrigger#

Type alias.

Type aliases are created through the type statement:

type Alias = int

In this example, Alias and int will be treated equivalently by static type checkers.

At runtime, Alias is an instance of TypeAliasType. The __name__ attribute holds the name of the type alias. The value of the type alias is stored in the __value__ attribute. It is evaluated lazily, so the value is computed only if the attribute is accessed.

Type aliases can also be generic:

type ListOrSet[T] = list[T] | set[T]

In this case, the type parameters of the alias are stored in the __type_params__ attribute.

See PEP 695 for more information.

irix.colorcode.CmdTrigger = CmdTrigger#

Type alias.

Type aliases are created through the type statement:

type Alias = int

In this example, Alias and int will be treated equivalently by static type checkers.

At runtime, Alias is an instance of TypeAliasType. The __name__ attribute holds the name of the type alias. The value of the type alias is stored in the __value__ attribute. It is evaluated lazily, so the value is computed only if the attribute is accessed.

Type aliases can also be generic:

type ListOrSet[T] = list[T] | set[T]

In this case, the type parameters of the alias are stored in the __type_params__ attribute.

See PEP 695 for more information.

class irix.colorcode.Code(color: str, dir_trigger: DirTrigger | None = None, cmd_trigger: CmdTrigger | None = None, pattern: str = '')#

A color assignment with optional directory and/or command triggers.

pattern is the raw regex text the trigger was built from; it carries no behavior but lets ColorCoder.codes order triggers most-specific-first (by the normalized _specificity length) so a broad path prefix never shadows a more specific override.

class irix.colorcode.ColorCoder(*, directory: Path = <factory>, palette: Palette = <factory>, base_color: Hue = 'slate', config: Path | None = None, clear_cache: bool = False, verbose: bool = False, color: str = '', name: str = '', status: int = 0)#

Manages terminal background color changes driven by directory and command triggers.

On each shell prompt, the shell calls this tool with the current directory and/or the last command name + exit status. The coder consults its trigger rules (loaded from a YAML config file) and emits an OSC 11 escape sequence to change the terminal background color.

The full (Radix) dark palette is used by default; the full light palette is used when $IRIX_MODE=light or --mode light is given (see _default_palette). Supply a custom irix.Palette.Palette instance to override either.

A persistent manual override (colorcode set <color>) takes absolute precedence over all trigger rules until cleared (colorcode clear).

Config file (triggers) is looked up at, in order:

  1. $IRIX_CONFIG environment variable.

  2. $XDG_CONFIG_HOME/irix/colorcode.yaml (Linux/macOS).

  3. %APPDATA%\irix\colorcode.yaml (Windows).

Parameters:
  • directory – The current working directory, tested against directory triggers.

  • palette – The color palette used for name → hex resolution.

  • base_color – The hue name to revert to when no trigger matches.

  • config – Explicit path to the YAML trigger config. Overrides all automatic lookup.

  • clear_cache – When True, invalidate the trigger-code cache on startup.

  • verbose – When True, print diagnostic messages to stderr.

  • color – Explicit color to apply immediately, bypassing all triggers.

  • name – Name of the last executed command, tested against command triggers.

  • status – Exit status of the last executed command.

I Initial Methods#

ColorCoder.model_copy(*, update: Mapping[str, Any] | None = None, deep: bool = False) → Self#

Copy the coder without retaining prompt-time status observations.

II Private Methods#

property ColorCoder.last_path: Path | None#

Return the previous working directory from $OLDPWD, if set.

property ColorCoder.last_color: str | None#

Return the color that was active in the previous directory, if determinable.

III Primary Methods#

property ColorCoder.override: str | None#

Return the active persistent manual override, if one is set.

A Kitty-window assignment made by multiset takes precedence over the global set override, so independently colored panes retain their manual colors while directory triggers continue to run.

ColorCoder.set_override(color: str) → None#

Persist one global manual color override.

The color is validated against the palette before storing. A global override replaces any pane-specific multiset assignments.

Parameters:

color – Hue name (e.g. 'jade'), hue-shade key, or #rrggbb hex.

Raises:

ValueError – If color cannot be resolved to a hex value.

ColorCoder.clear_override() → bool#

Clear the current window’s and global manual overrides.

When run from a Kitty window, its pane-specific multiset assignment is cleared without disturbing other panes.

Returns:

True if an override was cleared, False if none was active.

property ColorCoder.codes: list[Code]#

Return the list of trigger-based color codes, loading from cache if fresh.

Codes are parsed from the user’s config YAML (if present) and cached via pickle in the XDG cache directory to avoid re-parsing on every prompt.

ColorCoder.check_directory(path: str | Path) → str | None#

Return the color triggered by path, or None if no trigger matches.

Parameters:

path – The directory path to test against all directory triggers.

ColorCoder.check_command(cmd: str, status: str | int = 0) → str | None#

Return the color triggered by cmd / status, or None.

Parameters:
  • cmd – The name of the last executed command.

  • status – The exit status of the last executed command.

property ColorCoder.git_dirty: bool#

Cache the current directory’s Git state for this invocation.

property ColorCoder.last_effective_color: str | None#

Return the preceding directory’s base hue at its current effective shade.

ColorCoder.apply_color(color: str, strict: bool = True) → None#

Emit the OSC 11 escape sequence to set the terminal background.

Resolves color through the palette (accepting a bare hue name, a fully-qualified hue-shade key, or a raw #rrggbb hex value) and writes the escape sequence directly to the terminal device.

Parameters:
  • color – The color to apply.

  • strict – When True (default), an unresolvable color raises. When False, it is logged and skipped instead – used by the shell hook path, where a bad trigger hue must never crash the disowned background process (it would fail silently and leave no color).

Raises:

ValueError – If color cannot be resolved and strict is True.

ColorCoder.decide() → str#

Choose the effective color for the current state.

Manual shell and persistent overrides plus an explicit --color stay authoritative. Command, configured-directory, computed-directory, and reset base hues are composed with the clean, dirty, or failure shade.

ColorCoder.show_status() → None#

Print the current override and effective color to stdout.

ColorCoder.multiset(colors: list[str]) → None#

Set background colors on all kitty windows in the current tab.

Uses the kitty remote control protocol (kitten @) to apply a sequence of hue names to each window in the current tab. A single named Radix chamber expands to its four built-in hues. If fewer colors are given than windows, the pattern repeats (CSS-style: cyan amber over 4 windows yields cyan, amber, cyan, amber).

Parameters:

colors – A list of hue names or hex values, one per target window (with CSS repeat if fewer than the window count).

Raises:
  • RuntimeError – If not running inside kitty, or if kitty remote control is unavailable.

  • ValueError – If colors is empty or contains an unresolvable hue.

IV Main#

irix.colorcode.emit_osc11(hex_color: str) → None#

Write an OSC 11 escape sequence to the terminal device.

Uses /dev/tty on POSIX systems (robust against stdout redirection) and falls back to sys.stdout on Windows or when the device is unavailable.

Parameters:

hex_color – The hex color value (e.g. '#1A2B3C').

irix.colorcode.main(*vargs: str) → None#

CLI entry point: resolve and apply the appropriate terminal background color.