feat: add named color profile launchers - #34
Conversation
📝 WalkthroughWalkthroughAdds macOS-only managed launchers for individual profiles, including generated tinted icons, lifecycle commands, shell completions, isolated tests, configuration overrides, and documentation updates. ChangesManaged macOS launchers
Estimated code review effort: 4 (Complex) | ~45 minutes Sequence Diagram(s)sequenceDiagram
participant User
participant command_launcher
participant launcher_render_icon
participant launcher_build_bundle
participant codex_profile_app
User->>command_launcher: launcher create profile
command_launcher->>launcher_render_icon: render tinted icon
launcher_render_icon->>launcher_build_bundle: provide icon resource
launcher_build_bundle->>codex_profile_app: route launch to app profile
Suggested reviewers: 🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches🧪 Generate unit tests (beta)
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. Comment |
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@bin/codex-profile`:
- Around line 1287-1294: Update the launcher list loop around
launcher_load_state and launcher_is_managed_for_profile so invalid or stale
state entries emit a warning and continue to the next profile instead of calling
die. Preserve healthy entries and ensure --json output remains valid by avoiding
error text on stdout and allowing the list operation to complete.
🪄 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: 98346ce4-faf2-4d06-b0c8-4b32900500d1
📒 Files selected for processing (8)
CHANGELOG.mdREADME.mdbin/codex-profiledocs/index.htmldocs/llms.txttest/cli/launcher-test.shtest/cli/shell-test.shtest/lib/cli-fixtures.sh
| if [[ -d "$LAUNCHER_STATE_DIR" && ! -L "$LAUNCHER_STATE_DIR" ]]; then | ||
| for state_file in "$LAUNCHER_STATE_DIR"/*.state; do | ||
| [[ -f "$state_file" && ! -L "$state_file" ]] || continue | ||
| profile="${state_file##*/}" | ||
| profile="${profile%.state}" | ||
| launcher_load_state "$profile" || die "Invalid launcher state: $state_file" | ||
| launcher_is_managed_for_profile "$LAUNCHER_STATE_PATH" "$profile" || | ||
| die "Managed launcher is missing or invalid: $LAUNCHER_STATE_PATH" |
There was a problem hiding this comment.
🩺 Stability & Availability | 🟡 Minor | ⚡ Quick win
launcher list aborts on the first stale/invalid entry. If a managed .app is removed out-of-band, launcher_load_state/launcher_is_managed_for_profile fails and die kills the entire listing — so one broken launcher hides all healthy ones. In --json mode the opening [ and any earlier objects are already on stdout, so callers get truncated, unparseable JSON alongside the stderr error. Prefer skipping (and warning) so list stays usable and JSON stays well-formed.
🛠️ Skip invalid entries instead of aborting
- launcher_load_state "$profile" || die "Invalid launcher state: $state_file"
- launcher_is_managed_for_profile "$LAUNCHER_STATE_PATH" "$profile" ||
- die "Managed launcher is missing or invalid: $LAUNCHER_STATE_PATH"
+ launcher_load_state "$profile" || {
+ printf 'warning: skipping invalid launcher state: %s\n' "$state_file" >&2
+ continue
+ }
+ launcher_is_managed_for_profile "$LAUNCHER_STATE_PATH" "$profile" || {
+ printf 'warning: skipping missing/invalid managed launcher: %s\n' "$LAUNCHER_STATE_PATH" >&2
+ continue
+ }📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| if [[ -d "$LAUNCHER_STATE_DIR" && ! -L "$LAUNCHER_STATE_DIR" ]]; then | |
| for state_file in "$LAUNCHER_STATE_DIR"/*.state; do | |
| [[ -f "$state_file" && ! -L "$state_file" ]] || continue | |
| profile="${state_file##*/}" | |
| profile="${profile%.state}" | |
| launcher_load_state "$profile" || die "Invalid launcher state: $state_file" | |
| launcher_is_managed_for_profile "$LAUNCHER_STATE_PATH" "$profile" || | |
| die "Managed launcher is missing or invalid: $LAUNCHER_STATE_PATH" | |
| if [[ -d "$LAUNCHER_STATE_DIR" && ! -L "$LAUNCHER_STATE_DIR" ]]; then | |
| for state_file in "$LAUNCHER_STATE_DIR"/*.state; do | |
| [[ -f "$state_file" && ! -L "$state_file" ]] || continue | |
| profile="${state_file##*/}" | |
| profile="${profile%.state}" | |
| launcher_load_state "$profile" || { | |
| printf 'warning: skipping invalid launcher state: %s\n' "$state_file" >&2 | |
| continue | |
| } | |
| launcher_is_managed_for_profile "$LAUNCHER_STATE_PATH" "$profile" || { | |
| printf 'warning: skipping missing/invalid managed launcher: %s\n' "$LAUNCHER_STATE_PATH" >&2 | |
| continue | |
| } |
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@bin/codex-profile` around lines 1287 - 1294, Update the launcher list loop
around launcher_load_state and launcher_is_managed_for_profile so invalid or
stale state entries emit a warning and continue to the next profile instead of
calling die. Preserve healthy entries and ensure --json output remains valid by
avoiding error text on stdout and allowing the list operation to complete.
Summary
launcher create,list,path, andremovefor managed macOS profile launchers.codex-profile app <profile>.Testing
make checkcodesign --verify --deep --strictstill passedScope and compatibility
appbehavior.sips,qlmanage, andiconutil). Inspection and removal remain scriptable.Checklist
make check; if the environment lacks ShellCheck, I ranmake testand documented the missing lint result instead.app defaultsession and use the original signed app bundle.Summary by CodeRabbit
New Features
Documentation
Tests