Skip to content

Split CLI theme command out of cmux.swift - #3226

Merged
lawrencecchen merged 4 commits into
mainfrom
refactor-cli-command-split
Apr 28, 2026
Merged

lawrencecchen merged 4 commits into
mainfrom
refactor-cli-command-split

Conversation

@lawrencecchen

@lawrencecchen lawrencecchen commented Apr 28, 2026 •

Copy link
Copy Markdown
Contributor

Summary:

  • Move the CLI themes command into focused CMUXCLI extension files.
  • Keep both new files below the 500-line file-length threshold.
  • Tighten the Swift file-length budget for CLI/cmux.swift by 716 lines.

Verification:

  • ./scripts/reload.sh --tag cli-theme-split
  • python3 scripts/swift_file_length_budget.py --budget .github/swift-file-length-budget.tsv
  • python3 scripts/swift_warning_budget.py --log /tmp/cmux-reload-cli-theme-split.log
  • Built CLI: cmux --json themes list

Summary by cubic

Split the cmux themes command out of CLI/cmux.swift into focused CMUXCLI extensions. Also refined config search to prefer config.ghostty, tightened the file-length budget, and fixed tagged reload to build the Ghostty CLI helper.

  • Refactors

    • Added CLI/CMUXCLI+Themes.swift and CLI/CMUXCLI+ThemeSupport.swift (each <500 lines); moved theme list/set/clear and helpers.
    • Reduced CLI/cmux.swift by 716 lines; tightened its file-length budget from 18,705 to 17,989.
    • Relaxed access on shared helpers for reuse: parseOption, jsonString, parentSearchURL, resolvedExecutableURL.
    • Updated Xcode project to include the new files.
  • Bug Fixes

    • Config search now prefers config.ghostty and only falls back to legacy config when the new file exists but is empty.
    • Tagged reload now builds the Ghostty CLI helper by default; only honors CMUX_SKIP_ZIG_BUILD=1 when set explicitly.

Written for commit 70710c7. Summary will update on new commits. Review in cubic

Summary by CodeRabbit

  • New Features
    • CLI commands for theme management: list, set (with optional light/dark variants), and clear theme selection.
    • Interactive terminal theme picker when run in a TTY.
    • JSON output for machine-readable results.
    • Persists a managed theme override and attempts to reload the app’s theme immediately.
    • Shows current resolved light/dark values and the active config/source.

@vercel

vercel Bot commented Apr 28, 2026 •

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
cmux Ready Ready Preview, Comment Apr 28, 2026 11:30pm
cmux-staging Building Building Preview, Comment Apr 28, 2026 11:30pm

@coderabbitai

coderabbitai Bot commented Apr 28, 2026 •

Copy link
Copy Markdown
📝 Walkthrough

Walkthrough

Adds comprehensive theme management to CMUXCLI: discovers and validates themes across multiple resource locations, reads/writes a managed theme override in Ghostty config, exposes a CLI themes subcommand with list/set/clear and interactive picker support, and triggers theme reloads via distributed notifications.

Changes

Cohort / File(s) Summary
Theme Support Implementation
CLI/CMUXCLI+ThemeSupport.swift
New theme-discovery, validation, config search, managed override read/write, and reload-triggering APIs; resolves bundle identifier and constructs candidate Ghostty config URLs.
CLI Themes Command
CLI/CMUXCLI+Themes.swift
Adds runThemes entrypoint and types for ThemeSelection/ThemeReloadStatus/ThemePickerTargetMode; implements themes subcommands (list, set, clear), JSON/text output, and TTY-launched Ghostty picker execve.
Main CLI Adjustments
CLI/cmux.swift
Removes inline theme-management code; relaxes visibility of utility helpers (parseOption, jsonString, parentSearchURL, resolvedExecutableURL) from private to internal.
Project File Update
GhosttyTabs.xcodeproj/project.pbxproj
Registers the two new Swift sources in the cmux-cli target so they are compiled into the tool.

Sequence Diagram(s)

sequenceDiagram
    actor User
    participant CLI as CMUXCLI
    participant Discovery as Theme Discovery
    participant Config as Ghostty Config
    participant Notify as Distributed Notify
    participant Ghostty as Ghostty App

    User->>CLI: themes list
    CLI->>Discovery: availableThemeNames()
    Discovery->>Config: scan candidate config URLs
    Config-->>Discovery: last theme directives
    Discovery-->>CLI: theme list
    CLI-->>User: display themes
Loading
sequenceDiagram
    actor User
    participant CLI as CMUXCLI
    participant Discovery as Theme Discovery
    participant Config as Ghostty Config
    participant Notify as Distributed Notify
    participant Ghostty as Ghostty App

    User->>CLI: themes set --light MyTheme
    CLI->>Discovery: validatedThemeName("MyTheme")
    Discovery-->>CLI: validated name
    CLI->>Config: writeManagedThemeOverride(validated)
    Config-->>CLI: override file URL
    CLI->>Notify: post reload notification (bundle id)
    Notify->>Ghostty: reload themes
    Ghostty-->>User: apply theme
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related PRs

Poem

🐰 I hopped through folders, sniffed each theme,

Light and dark now dance in my dream.
A tiny managed block I wrote with care,
A distributed nudge, and colors flair.
Hooray — themes set, and joy to share! 🥕✨

🚥 Pre-merge checks | ✅ 3 | ❌ 2

❌ Failed checks (2 warnings)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 7.69% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
Description check ⚠️ Warning The pull request description is incomplete and does not follow the required template structure with all mandatory sections. Add the following required sections: Testing (how tested and verified), Demo Video (if applicable), Review Trigger comment block, and complete Checklist with all items checked/addressed.
✅ Passed checks (3 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately describes the main refactoring: moving theme command functionality from cmux.swift into separate extension files for better organization.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

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

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch refactor-cli-command-split

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.

@greptile-apps

greptile-apps Bot commented Apr 28, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

This PR is a pure refactoring that extracts the CLI themes command (~716 lines) from the monolithic CLI/cmux.swift into two focused extension files: CMUXCLI+Themes.swift (command dispatch + output logic) and CMUXCLI+ThemeSupport.swift (file-system helpers). No functional changes are made; the file-length budget for cmux.swift is tightened accordingly, and both new files are registered in the Xcode project.

Confidence Score: 5/5

Safe to merge — pure code movement with no functional changes.

All logic is identical to the removed block in cmux.swift. The only observable change is access-level widening (private → internal) for methods that must cross file boundaries, which is the correct and necessary Swift idiom for multi-file extensions. Both new files respect the 500-line ceiling, the budget TSV is updated correctly, and the Xcode project registers both files.

No files require special attention.

Important Files Changed

Filename Overview
CLI/CMUXCLI+ThemeSupport.swift New 303-line extension file; contains file-system helpers (theme directory discovery, config read/write, managed-block regex). Functionally identical to the removed block in cmux.swift; helper methods correctly narrowed to private where possible.
CLI/CMUXCLI+Themes.swift New 420-line extension file; contains theme command dispatch (list/set/clear), interactive picker launcher, and JSON/text output. Static constants and nested types widened from private to internal as required for cross-file access.
CLI/cmux.swift ~716 lines of theme code removed; parseOption, jsonString, parentSearchURL, and resolvedExecutableURL widened from private to internal so the new extension files can call them.
.github/swift-file-length-budget.tsv CLI/cmux.swift budget reduced from 18705 to 17989 (-716), matching the lines removed. New files are intentionally below the 500-line threshold and are not tracked.
GhosttyTabs.xcodeproj/project.pbxproj Registers both new Swift files in the CLI group and the cmux target Sources build phase. No other changes.

Class Diagram

%%{init: {'theme': 'neutral'}}%%
classDiagram
    class `cmux.swift` {
        +parseOption()
        +jsonString()
        +parentSearchURL()
        +resolvedExecutableURL()
        -runCommand()
    }

    class `CMUXCLI+Themes.swift` {
        +cmuxThemeOverrideBundleIdentifier: String
        +cmuxThemesBlockStart: String
        +cmuxThemesBlockEnd: String
        +cmuxThemesReloadNotificationName: String
        +ThemeSelection
        +ThemeReloadStatus
        +ThemePickerTargetMode
        +runThemes()
        -printThemesList()
        -runThemesSet()
        -runThemesClear()
        -currentThemeSelection()
        -parseThemeSelection()
        -runInteractiveThemes()
        -bundledHelperURL()
        -execInteractiveHelper()
    }

    class `CMUXCLI+ThemeSupport.swift` {
        +availableThemeNames()
        +validatedThemeName()
        +themeConfigSearchURLs()
        +lastThemeDirective()
        +cmuxThemeOverrideConfigURL()
        +writeManagedThemeOverride()
        +clearManagedThemeOverride()
        +reloadThemesIfPossible()
        +currentCmuxAppBundleIdentifier()
        -themeDirectoryURLs()
        -removingManagedThemeOverride()
        -readOptionalThemeOverrideContents()
        -isThemeOverrideFileNotFoundError()
    }

    `cmux.swift` <|-- `CMUXCLI+Themes.swift` : extension CMUXCLI
    `cmux.swift` <|-- `CMUXCLI+ThemeSupport.swift` : extension CMUXCLI
    `CMUXCLI+Themes.swift` --> `CMUXCLI+ThemeSupport.swift` : calls helpers
Loading

Reviews (1): Last reviewed commit: "refactor: split CLI theme command" | Re-trigger Greptile

@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 `@CLI/CMUXCLI`+Themes.swift:
- Around line 400-402: parseThemeSelection currently backfills light from dark
and dark from light by using lightTheme ?? fallbackTheme ?? darkTheme and vice
versa; change this so one-sided directives remain one-sided by computing
resolvedLight = lightTheme ?? fallbackTheme and resolvedDark = darkTheme ??
fallbackTheme (keep using ThemeSelection(rawValue:rawValue, light:resolvedLight,
dark:resolvedDark, sourcePath:sourcePath)). This removes the fallback to the
opposite side (darkTheme/lightTheme) so an explicitly one-sided declaration
isn't treated as both.

In `@CLI/CMUXCLI`+ThemeSupport.swift:
- Around line 128-141: themeConfigSearchURLs() currently always includes the
legacy Application Support paths, which lets the CLI pick up legacy theme
settings the app may ignore; change themeConfigSearchURLs() to only include the
"~/Library/Application Support/com.mitchellh.ghostty/config" (and its .ghostty
variant) when shouldLoadLegacyGhosttyConfig(...) returns true (mirror the same
gating used by GhosttyApp.loadedGhosttyConfigScanPaths and
currentThemeSelection()); implement this by consulting
shouldLoadLegacyGhosttyConfig(...) inside themeConfigSearchURLs() and
conditionally appending the legacy paths instead of unconditionally listing
them.
🪄 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: 88a811e6-c9fb-4f46-86fb-43f403d838c5

📥 Commits

Reviewing files that changed from the base of the PR and between 302382d and 79f0d41.

⛔ Files ignored due to path filters (1)
  • .github/swift-file-length-budget.tsv is excluded by !**/*.tsv
📒 Files selected for processing (4)
  • CLI/CMUXCLI+ThemeSupport.swift
  • CLI/CMUXCLI+Themes.swift
  • CLI/cmux.swift
  • GhosttyTabs.xcodeproj/project.pbxproj

Comment thread CLI/CMUXCLI+Themes.swift Outdated
Comment thread CLI/CMUXCLI+ThemeSupport.swift

@chatgpt-codex-connector chatgpt-codex-connector 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.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 3bfec815df

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread CLI/CMUXCLI+Themes.swift

This branch was successfully deployed

1 active deployment
Preview – cmux — 70710c71 Deployed Apr 28, 2026 by vercel[bot]
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