Skip to content

Fix: Apple Terminal contrast by detecting macOS dark mode - #204

Open
prasadus92 wants to merge 2 commits into
Maciek-roboblog:mainfrom
prasadus92:fix/macos-terminal-contrast
Open

Fix: Apple Terminal contrast by detecting macOS dark mode#204
prasadus92 wants to merge 2 commits into
Maciek-roboblog:mainfrom
prasadus92:fix/macos-terminal-contrast

Conversation

@prasadus92

@prasadus92 prasadus92 commented Apr 12, 2026

Copy link
Copy Markdown

Problem

Apple Terminal (TERM_PROGRAM=Apple_Terminal) is hard-coded to return BackgroundType.LIGHT in BackgroundDetector._check_environment_hints(). However, since macOS Mojave (2018), Apple Terminal follows the system appearance — and most modern macOS users run dark mode.

This causes light-theme colors (dark foreground text) to be applied on a dark terminal background, resulting in near-zero contrast where labels, values, and progress bars are barely readable.

Affected: Any macOS user running dark mode with the native Terminal.app.
Not affected: iTerm2 users (correctly detected as DARK).

Screenshots

macOS Terminal.app (before fix — barely readable)

Native_Terminal_App

iTerm2 (works correctly)

iTerm

Fix

Instead of assuming LIGHT for Apple Terminal, the detector now calls a new _check_macos_appearance() method that queries the actual macOS system appearance:

defaults read -g AppleInterfaceStyle
  • Returns "Dark"BackgroundType.DARK
  • Command fails (key absent in light mode) → BackgroundType.LIGHT
  • Any error (timeout, non-macOS, permissions) → falls back to BackgroundType.DARK

The fallback to DARK matches the reality that most macOS users today have dark mode enabled.

Changes

  • src/claude_monitor/terminal/themes.py: Added _check_macos_appearance() static method to BackgroundDetector. Updated _check_environment_hints() to call it for Apple Terminal instead of returning hard-coded LIGHT.
  • src/tests/test_background_detection.py: 7 new tests covering dark mode detection, light mode detection, timeout/error fallbacks, and Apple Terminal delegation.

Testing

  • All 524 existing tests pass (0 failures)
  • 7 new tests added and passing
  • Verified live on macOS with dark mode enabled — Apple Terminal now correctly returns DARK

Summary by CodeRabbit

  • Bug Fixes

    • Apple Terminal on macOS now respects the system dark/light appearance via a new macOS appearance check, with improved fallbacks and error handling for timeouts, missing utilities, or unexpected responses.
  • Tests

    • Added unit tests covering macOS appearance detection and Apple Terminal theme detection behavior.

Apple Terminal was hard-coded as LIGHT background, but since macOS
Mojave it follows the system appearance setting. Most modern macOS
users run dark mode, causing light-theme colors (dark text) to render
on dark backgrounds with near-zero contrast.

Instead of assuming LIGHT, Apple Terminal now checks the actual macOS
system appearance via `defaults read -g AppleInterfaceStyle`. Falls
back to DARK if detection fails (matching the majority of users).

Includes 7 new tests covering dark mode, light mode, and error
fallback scenarios.
@coderabbitai

coderabbitai Bot commented Apr 12, 2026

Copy link
Copy Markdown

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 4203a8e6-28ab-4e06-aed4-5907a538849c

📥 Commits

Reviewing files that changed from the base of the PR and between 44ad123 and 81d7f0f.

📒 Files selected for processing (2)
  • src/claude_monitor/terminal/themes.py
  • src/tests/test_background_detection.py
✅ Files skipped from review due to trivial changes (1)
  • src/claude_monitor/terminal/themes.py
🚧 Files skipped from review as they are similar to previous changes (1)
  • src/tests/test_background_detection.py

📝 Walkthrough

Walkthrough

Apple Terminal detection now queries macOS appearance via a new _check_macos_appearance() instead of defaulting to light; it runs defaults read -g AppleInterfaceStyle with timeout and fallback handling. Tests for the new behavior and error cases were added.

Changes

Cohort / File(s) Summary
macOS Appearance Detection
src/claude_monitor/terminal/themes.py
Added BackgroundDetector._check_macos_appearance() that runs defaults read -g AppleInterfaceStyle (with a 2s timeout), maps "dark" output to BackgroundType.DARK, otherwise LIGHT, and returns DARK as a safety fallback on errors. Updated Apple Terminal branch to delegate to this method.
Test Coverage
src/tests/test_background_detection.py
New pytest suite covering successful dark/light parsing, non-zero exit handling when the key is absent, and fallbacks for subprocess.TimeoutExpired, FileNotFoundError, and OSError. Also tests delegation from Apple Terminal detection to the macOS check.

Sequence Diagram

sequenceDiagram
    participant Detector as BackgroundDetector
    participant Env as Environment Hints
    participant Subproc as subprocess.run
    participant macOS as macOS System
    participant Handler as Error Handler

    Detector->>Env: detect_background()
    Env->>Env: _check_environment_hints()
    Env->>Env: TERM_PROGRAM == "Apple_Terminal" ?
    alt Apple Terminal
        Env->>Detector: _check_macos_appearance()
        Detector->>Subproc: run("defaults read -g AppleInterfaceStyle", timeout=2)
        Subproc->>macOS: query AppleInterfaceStyle
        alt returns "Dark\n"
            macOS-->>Subproc: stdout "Dark\n"
            Subproc-->>Detector: CompletedProcess(stdout="Dark\n")
            Detector-->>Env: BackgroundType.DARK
        else returns "" / key absent
            macOS-->>Subproc: stderr indicates key missing / stdout ""
            Subproc-->>Detector: CompletedProcess(non-zero / empty)
            Detector-->>Env: BackgroundType.LIGHT
        else Timeout/FileNotFound/OSError
            Subproc-->>Handler: raises exception
            Handler-->>Detector: fallback -> BackgroundType.DARK
            Detector-->>Env: BackgroundType.DARK
        end
    else Other terminal
        Env-->>Detector: continue other checks
    end
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Poem

🐰 I sniffed the defaults, a tiny hop and peep,

Through dark and light the system's secrets keep.
Apple Terminal asked, so I looked with care—
A bounce for "Dark", a wiggle for the fair.
Now detection hops true, both cautious and spry.

🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title directly and concisely describes the main change: fixing Apple Terminal contrast by implementing macOS dark mode detection.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@src/claude_monitor/terminal/themes.py`:
- Around line 355-364: The subprocess.run call that checks macOS
AppleInterfaceStyle currently treats any non-zero exit as LIGHT; change the
logic so that after running subprocess.run (used to decide BackgroundType), you
still return BackgroundType.DARK for unexpected non-zero exits: if
result.returncode == 0 and "dark" in result.stdout.strip().lower() return
BackgroundType.DARK; else if result.returncode != 0 inspect result.stderr (or
result.stdout) and return BackgroundType.LIGHT only when the stderr/error text
indicates the key is missing (e.g., contains "does not exist" or "The
domain/default pair"); for any other non-zero exit or unexpected output, return
BackgroundType.DARK to preserve contrast; keep the existing except
(subprocess.TimeoutExpired, FileNotFoundError, OSError) behavior.

In `@src/tests/test_background_detection.py`:
- Around line 53-66: The Apple Terminal tests use `@patch.dict`("os.environ",
{"TERM_PROGRAM": "Apple_Terminal"}, clear=False) which can leak other env vars
and change test behavior; update these tests
(test_apple_terminal_delegates_to_macos_appearance and
test_apple_terminal_light_mode) to use clear=True so only TERM_PROGRAM is
present during BackgroundDetector._check_environment_hints() execution, ensuring
deterministic delegation to BackgroundDetector._check_macos_appearance().
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 93cbb548-3dae-46a7-a3ec-ce9352a2a749

📥 Commits

Reviewing files that changed from the base of the PR and between 06f0fe1 and 44ad123.

📒 Files selected for processing (2)
  • src/claude_monitor/terminal/themes.py
  • src/tests/test_background_detection.py

Comment thread src/claude_monitor/terminal/themes.py
Comment thread src/tests/test_background_detection.py Outdated
- Only return LIGHT when defaults stderr confirms the
  AppleInterfaceStyle key is absent. Other non-zero exits
  now fall back to DARK for contrast safety.
- Use clear=True in test env patches to prevent env var
  leakage from affecting test determinism.
- Add test for unexpected non-zero exit fallback.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant