Skip to content

[codex] Improve setup errors for missing Xcode and GhosttyKit cache locks#6443

Open
archit-goyal wants to merge 7 commits into
manaflow-ai:mainfrom
archit-goyal:codex/setup-prereq-errors
Open

[codex] Improve setup errors for missing Xcode and GhosttyKit cache locks#6443
archit-goyal wants to merge 7 commits into
manaflow-ai:mainfrom
archit-goyal:codex/setup-prereq-errors

Conversation

@archit-goyal

@archit-goyal archit-goyal commented Jun 19, 2026

Copy link
Copy Markdown

Summary

  • fail early in scripts/setup.sh when full Xcode is not selected
  • report GhosttyKit cache lock creation errors instead of waiting on a nonexistent lock

Why

During a fresh-clone setup pass, ./scripts/setup.sh eventually depends on full Xcode tooling, but a Command Line Tools-only machine did not get a clear prerequisite failure until later. The GhosttyKit helper also treated any lock mkdir failure as lock contention, which can make permission errors look like an indefinite wait on a cache lock that does not exist.

Verification

  • bash -n scripts/setup.sh
  • bash -n scripts/ensure-ghosttykit.sh
  • git diff --check
  • fresh recursive clone plus patched ./scripts/setup.sh on a CLT-only machine now prints a clear Xcode prerequisite error
  • simulated non-writable GhosttyKit cache now reports the underlying mkdir permission error immediately

View with Codesmith Autofix with Codesmith
Need help on this PR? Tag /codesmith with what you need. Autofix is disabled.


Summary by cubic

Fail fast when full Xcode isn’t selected and harden GhosttyKit cache lock handling. Setup blocks CLT-only configs, validates the active developer dir, and surfaces sanitized, actionable lock errors instead of waiting on a bad lock.

  • Bug Fixes
    • scripts/setup.sh: Xcode 15+ preflight — check for xcodebuild, ensure xcode-select points to an Xcode app, verify xcodebuild -version runs; print install/select/license steps; standardized errors.
    • scripts/ensure-ghosttykit.sh: Sanitize mkdir errors and user paths; detect contention vs permission/path failures and fail fast with a clear message; register lock ownership and only clean up after acquire; remove stale locks via rmdir and exit with guidance if removal fails (no rm -rf).

Written for commit 7c491c9. Summary will update on new commits.

Review in cubic

Summary by CodeRabbit

  • Bug Fixes

    • Improved cache-lock handling by capturing mkdir error output, adding an extra retry when appropriate, and ensuring lock cleanup only runs after a lock is successfully acquired.
  • Chores

    • Updated setup to validate Xcode prerequisites before continuing: checks for xcodebuild, verifies the active developer directory, and confirms xcodebuild -version works, with clearer remediation and license-acceptance guidance on failure.

@vercel

vercel Bot commented Jun 19, 2026

Copy link
Copy Markdown

@archit-goyal is attempting to deploy a commit to the Manaflow Team on Vercel.

A member of the Team first needs to authorize it.

@coderabbitai

coderabbitai Bot commented Jun 19, 2026

Copy link
Copy Markdown

Review Change Stack

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

Two setup scripts receive diagnostic improvements: setup.sh gains an upfront xcodebuild availability and configuration check that exits with installation and license instructions on failure, and ensure-ghosttykit.sh captures mkdir stderr into a temp file during cache-lock acquisition to surface writable-cache errors before exiting.

Changes

Setup Script Diagnostics

Layer / File(s) Summary
Xcode prerequisite check
scripts/setup.sh
Inserts validation that xcodebuild exists and the active xcode-select developer directory points to an Xcode app; runs xcodebuild -version and prints Xcode installation and license instructions before exiting on failure.
Cache-lock mkdir error diagnostics
scripts/ensure-ghosttykit.sh
Captures mkdir stderr to a mktemp temp file during lock-acquisition retry logic; on persistent failure prints the captured error output and exits. After successful lock acquisition, removes the temp file and sets LOCK_ACQUIRED=1 so the EXIT trap cleanup will remove the lock directory.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~7 minutes

Poem

🐇 Hop hop, the setup path is clear,
Xcode must be present, never fear!
If mkdir stumbles in the night,
A temp file captures all the blight—
The rabbit checks each lock and door,
No silent failures anymore! 🔒


Important

Pre-merge checks failed

Please resolve all errors before merging. Addressing warnings is optional.

❌ Failed checks (2 errors, 1 warning)

Check name Status Explanation Resolution
Cmux Swiftui State Layout ❌ Error The PR introduces 40 new ObservableObject classes with 192 @Published properties violating swiftui-state-layout.md: should use @Observable instead of ObservableObject/@published for new cmux-owned... Replace ObservableObject/@published declarations with @Observable plus @State or value snapshots per .github/review-bot-rules/swiftui-state-layout.md requirements for new state.
Cmux Source Artifacts ❌ Error PR adds 5583 files including .claude/ and .agents/ artifact directories (.claude/scheduled_tasks.lock, .agents/skills) that violate the source-control-artifacts policy. Remove .claude/ and .agents/ directories from the commit, or add them to .gitignore as hidden scratch directories per policy.
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (19 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly identifies the two main improvements: Xcode setup validation and GhosttyKit cache lock error handling, accurately reflecting the changeset.
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.
Cmux Swift Actor Isolation ✅ Passed PR modifies only bash shell scripts (ensure-ghosttykit.sh, setup.sh), not Swift code; actor isolation check applies only to Swift production changes.
Cmux Swift Blocking Runtime ✅ Passed Custom check applies to Swift code with blocking synchronization. PR modifies only bash scripts (scripts/ensure-ghosttykit.sh, scripts/setup.sh), not Swift files.
Cmux Expensive Synchronous Load ✅ Passed PR modifies only bash shell scripts (scripts/ensure-ghosttykit.sh and scripts/setup.sh); no Swift code changes found, so expensive sync load check does not apply.
Cmux Cache Substitution Correctness ✅ Passed The PR modifies only bash shell scripts (scripts/ensure-ghosttykit.sh and scripts/setup.sh), not production Swift, TypeScript, or JavaScript files. The custom check explicitly applies "For producti...
Cmux No Hacky Sleeps ✅ Passed The PR does not introduce or worsen any hacky sleeps. The sleep 1 in the lock-waiting loop is existing code from the previous version, which is explicitly allowed by the rule.
Cmux Algorithmic Complexity ✅ Passed Both modified scripts are build/setup automation code that don't handle scalable user-owned collections (workspaces, panes, files, etc.) per the rule's scope. No algorithmic complexity violations d...
Cmux Swift Concurrency ✅ Passed PR adds shell script improvements (setup.sh, ensure-ghosttykit.sh) with no Swift concurrency changes. Mega-commit also includes 3082 new CLI Swift files; their DispatchQueue.global().async patterns...
Cmux Swift @Concurrent ✅ Passed This PR modifies only bash scripts (scripts/ensure-ghosttykit.sh and scripts/setup.sh), not Swift files. The check for Swift @concurrent annotations is not applicable.
Cmux Swift File And Package Boundaries ✅ Passed PR only modifies shell scripts (scripts/ensure-ghosttykit.sh, scripts/setup.sh); check applies exclusively to Swift file and package boundary violations.
Cmux Swiftpm Lockfiles ✅ Passed PR only modifies shell scripts (scripts/ensure-ghosttykit.sh, scripts/setup.sh); no SwiftPM packages, Package.resolved, .gitignore, or Xcode project configuration changes detected. Rule does not ap...
Cmux Swift Logging ✅ Passed PR modifies only shell scripts (setup.sh, ensure-ghosttykit.sh), not Swift code. Swift logging rules in .github/review-bot-rules/swift-logging.md only apply to Swift files.
Cmux User-Facing Error Privacy ✅ Passed All user-facing error messages comply with privacy rules: no env var names exposed, paths sanitized to generics, only public documented CLI flags used, no credentials or internal details leaked.
Cmux Full Internationalization ✅ Passed PR modifies only developer-only operational scripts (scripts/setup.sh and scripts/ensure-ghosttykit.sh) with developer-facing error messages and progress indicators. Falls under allowed exception f...
Cmux Architecture Rethink ✅ Passed The custom check applies to Swift architecture changes, but this PR only modifies shell scripts (scripts/ensure-ghosttykit.sh and scripts/setup.sh), not Swift code. Check not applicable.
Cmux Swift Auxiliary Window Close Shortcuts ✅ Passed PR modifies only bash shell scripts (scripts/ensure-ghosttykit.sh, scripts/setup.sh) with no Swift code changes, so the Swift auxiliary window close shortcuts check is not applicable.
Description check ✅ Passed The PR description addresses all required template sections with comprehensive details on what changed, why, and verification steps performed.
✨ 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.

@archit-goyal archit-goyal marked this pull request as ready for review June 19, 2026 10:05
@greptile-apps

greptile-apps Bot commented Jun 19, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

This PR adds early Xcode prerequisite validation to setup.sh and fixes incorrect error classification in the GhosttyKit cache lock loop in ensure-ghosttykit.sh, so both a CLT-only machine and a permission-denied scenario now get clear, actionable error messages instead of a confusing late failure or an infinite wait.

  • scripts/setup.sh: Three sequential preflight guards check that xcodebuild is on PATH, that xcode-select -p resolves to an Xcode app (not CLT), and that xcodebuild -version actually runs (catching un-accepted license agreements), each with targeted remediation copy.
  • scripts/ensure-ghosttykit.sh: The lock loop now captures mkdir stderr into a shell variable, distinguishes permission failures from contention via a directory-existence check and an "File exists" error-message regex, moves the EXIT trap before the loop so it covers signal exits during lock wait, and gates lock cleanup on LOCK_ACQUIRED to avoid deleting a lock the script never held.

Confidence Score: 5/5

Both shell scripts are safe to merge; changes are tightly scoped to error-path reporting and an Xcode preflight, with no impact on the happy path or existing lock-protocol semantics.

The Xcode checks in setup.sh are straightforward conditionals with no side effects on success. The ensure-ghosttykit.sh rework correctly distinguishes permission errors from contention using both a directory-existence probe and an error-message regex fallback that covers the TOCTOU window; the EXIT trap is now set before the loop; and sanitized error output is actually surfaced on the failure path. No regressions are introduced in the normal or concurrent-runner paths.

No files require special attention.

Important Files Changed

Filename Overview
scripts/setup.sh Adds three-step Xcode prerequisite check (command availability, developer-dir pattern, xcodebuild -version) before proceeding with setup; logic and error messages are clear and actionable.
scripts/ensure-ghosttykit.sh Reworks the lock-acquisition loop to distinguish permission failures from contention, moves the EXIT trap before the loop, captures and sanitizes mkdir stderr, and avoids cleaning up a lock that was never acquired; logic is correct for the addressed race scenarios.

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart TD
    A[setup.sh start] --> B{xcodebuild in PATH?}
    B -- No --> C[Error: install Xcode 15+\nexit 1]
    B -- Yes --> D{xcode-select -p\nmatches Xcode*.app?}
    D -- No --> E[Error: full Xcode required\nexit 1]
    D -- Yes --> F{xcodebuild -version\nsucceeds?}
    F -- No --> G[Error: license not accepted\nexit 1]
    F -- Yes --> H[ensure-ghosttykit.sh]
    H --> I[mkdir LOCK_DIR]
    I -- success --> J[LOCK_ACQUIRED=1 / break]
    I -- failure --> K{lock_mkdir_failed_because_contention?}
    K -- No = real error --> L[print sanitized mkdir error / exit 1]
    K -- Yes = contention --> M{timeout > 300s?}
    M -- Yes --> N{rmdir stale lock?}
    N -- success --> I
    N -- failure --> O[Error: stale lock / exit 1]
    M -- No --> P[sleep 1 / retry]
    P --> I
    J --> Q[fetch/build GhosttyKit]
    Q --> R[EXIT trap: rmdir LOCK_DIR]
Loading
%%{init: {'theme': 'base', 'themeVariables': {"darkMode": true, "background": "#0d1117", "primaryColor": "#21262d", "primaryTextColor": "#e6edf3", "primaryBorderColor": "#8b949e", "lineColor": "#8b949e", "textColor": "#e6edf3", "edgeLabelBackground": "#161b22", "actorBkg": "#21262d", "actorBorder": "#8b949e", "actorTextColor": "#e6edf3", "actorLineColor": "#8b949e", "signalColor": "#8b949e", "signalTextColor": "#e6edf3", "noteBkgColor": "#373320", "noteBorderColor": "#d4a72c", "noteTextColor": "#f0e6c0", "labelBoxBkgColor": "#21262d", "labelBoxBorderColor": "#8b949e", "labelTextColor": "#e6edf3", "loopTextColor": "#e6edf3", "activationBkgColor": "#30363d", "activationBorderColor": "#8b949e"}}}%%
flowchart TD
    A[setup.sh start] --> B{xcodebuild in PATH?}
    B -- No --> C[Error: install Xcode 15+\nexit 1]
    B -- Yes --> D{xcode-select -p\nmatches Xcode*.app?}
    D -- No --> E[Error: full Xcode required\nexit 1]
    D -- Yes --> F{xcodebuild -version\nsucceeds?}
    F -- No --> G[Error: license not accepted\nexit 1]
    F -- Yes --> H[ensure-ghosttykit.sh]
    H --> I[mkdir LOCK_DIR]
    I -- success --> J[LOCK_ACQUIRED=1 / break]
    I -- failure --> K{lock_mkdir_failed_because_contention?}
    K -- No = real error --> L[print sanitized mkdir error / exit 1]
    K -- Yes = contention --> M{timeout > 300s?}
    M -- Yes --> N{rmdir stale lock?}
    N -- success --> I
    N -- failure --> O[Error: stale lock / exit 1]
    M -- No --> P[sleep 1 / retry]
    P --> I
    J --> Q[fetch/build GhosttyKit]
    Q --> R[EXIT trap: rmdir LOCK_DIR]
Loading

Reviews (6): Last reviewed commit: "Harden GhosttyKit lock diagnostics" | Re-trigger Greptile

Comment thread scripts/ensure-ghosttykit.sh Outdated
Comment on lines +119 to +128
while ! mkdir "$LOCK_DIR" 2>"$LOCK_MKDIR_ERR"; do
if [[ ! -d "$LOCK_DIR" ]]; then
echo "error: could not create GhosttyKit cache lock at $LOCK_DIR." >&2
if [[ -s "$LOCK_MKDIR_ERR" ]]; then
sed 's/^/ /' "$LOCK_MKDIR_ERR" >&2
fi
echo "Check that CMUX_GHOSTTYKIT_CACHE_DIR, or its parent cache directory, is writable." >&2
rm -f "$LOCK_MKDIR_ERR"
exit 1
fi

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

P2 TOCTOU race can misdiagnose lock contention as a permission error

mkdir failing because another process currently holds the lock and mkdir failing because the parent directory is not writable both set a non-zero exit code. Between those two events, a concurrent holder could release the lock (remove $LOCK_DIR). When that happens, the [[ ! -d "$LOCK_DIR" ]] guard fires, the script exits 1 with "could not create GhosttyKit cache lock", and a perfectly valid concurrent setup run is killed with a misleading permission-error message. This is a regression from the previous behavior, which simply waited. The window is tiny but nonzero; on shared CI caches with parallel runners it is more likely.

Comment thread scripts/ensure-ghosttykit.sh Outdated
Comment on lines 118 to 138
@@ -124,6 +134,7 @@ while ! mkdir "$LOCK_DIR" 2>/dev/null; do
echo "==> Waiting for GhosttyKit cache lock for $GHOSTTY_KEY..."
sleep 1
done
rm -f "$LOCK_MKDIR_ERR"
trap 'rmdir "$LOCK_DIR" >/dev/null 2>&1 || true' EXIT

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

P2 $LOCK_MKDIR_ERR not included in the EXIT trap

$LOCK_MKDIR_ERR is created on line 118, but the trap … EXIT is not set until line 138 (after the lock is acquired). If the script receives SIGINT or SIGTERM during the lock-wait loop, neither the lock dir nor the temp file has a trap handler at that point, so $LOCK_MKDIR_ERR is orphaned in $TMPDIR. The two explicit rm -f calls handle the normal success path and the permission-error exit, but not signal-driven exits. Moving the trap earlier (before the loop) and including rm -f "$LOCK_MKDIR_ERR" in it would close this gap.

@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: 8a8a09d665

ℹ️ 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 scripts/setup.sh Outdated
Comment on lines +20 to +23
if ! xcodebuild -version >/dev/null 2>&1; then
echo "Error: full Xcode is required, but xcodebuild is not available from an Xcode developer directory."
echo "Install Xcode 15+ from the App Store, then run:"
echo " sudo xcode-select -s /Applications/Xcode.app/Contents/Developer"

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Validate the pinned Xcode version

On machines with a full but unsupported Xcode selected, this check still succeeds because it only verifies that xcodebuild -version exits successfully, and the added guidance explicitly says Xcode 15+ is enough. The repo's source of truth is .xcode-version:1 (26.0), and scripts/select-nightly-xcodes.sh:69 already treats absence of a macOS 26+ SDK as an error, so setup can now report success for contributors who will hit a later build failure. Please compare the selected Xcode/SDK against the pinned version instead of accepting any full Xcode.

Useful? React with 👍 / 👎.

Comment thread scripts/ensure-ghosttykit.sh Outdated
while ! mkdir "$LOCK_DIR" 2>/dev/null; do
LOCK_MKDIR_ERR="$(mktemp "${TMPDIR:-/tmp}/cmux-ghosttykit-lock.XXXXXX")"
while ! mkdir "$LOCK_DIR" 2>"$LOCK_MKDIR_ERR"; do
if [[ ! -d "$LOCK_DIR" ]]; then

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Retry when the lock holder releases first

When another ensure-ghosttykit.sh process releases the cache lock after this process's mkdir fails with EEXIST but before the -d check runs, this branch treats normal lock contention as a cache-writability error and exits. The lock loop is meant to serialize concurrent setup/reload invocations, so this TOCTOU can make one of two parallel builds fail spuriously; retry the mkdir path before surfacing a non-lock error.

Useful? React with 👍 / 👎.

@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: 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 `@scripts/setup.sh`:
- Around line 20-24: The xcodebuild -version check in the if statement does not
differentiate between Xcode not being installed and other failure modes such as
license or setup issues. Modify the check to first verify that xcodebuild exists
or is accessible, then separately check if it executes successfully. Provide
distinct error messages for each failure scenario: one for missing or
inaccessible xcodebuild (directing users to install Xcode), and another for
execution failures (directing users to address license/setup issues). This
allows users to receive appropriate guidance based on their actual problem.
🪄 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: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: 365178cf-3ee0-4037-a2f9-5cb9c01c6aeb

📥 Commits

Reviewing files that changed from the base of the PR and between 6439062 and 8a8a09d.

📒 Files selected for processing (2)
  • scripts/ensure-ghosttykit.sh
  • scripts/setup.sh

Comment thread scripts/setup.sh Outdated
Comment on lines +138 to +141
echo "error: could not create the GhosttyKit cache lock." >&2
echo "The underlying mkdir command failed while creating the lock directory." >&2
echo "Check that the GhosttyKit cache directory is writable." >&2
exit 1

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

P1 mkdir error output captured but never printed

$LOCK_MKDIR_ERR is redirected into a temp file on every mkdir call (lines 127 and 131), but when the permission-error path fires the file's contents are never written to stderr before exit 1. The EXIT trap then deletes it. The user sees only a static "Check that the GhosttyKit cache directory is writable" hint and never the actual mkdir diagnostic (e.g. mkdir: /path/.lock: Permission denied, or a "read-only filesystem" error). The whole point of introducing $LOCK_MKDIR_ERR was to surface this detail, so its absence here is a functional gap.

Suggested change
echo "error: could not create the GhosttyKit cache lock." >&2
echo "The underlying mkdir command failed while creating the lock directory." >&2
echo "Check that the GhosttyKit cache directory is writable." >&2
exit 1
echo "error: could not create the GhosttyKit cache lock." >&2
echo "The underlying mkdir command failed while creating the lock directory." >&2
if [[ -s "$LOCK_MKDIR_ERR" ]]; then
cat "$LOCK_MKDIR_ERR" >&2
fi
echo "Check that $CMUX_GHOSTTYKIT_CACHE_DIR (or its parent directory) is writable." >&2
exit 1

@archit-goyal

Copy link
Copy Markdown
Author

All code-review/security checks are green on the latest head (Greptile 5/5, CodeRabbit success, Socket success). The only remaining failures are the Vercel preview deployment checks, which require Manaflow team authorization for an external contributor deployment.

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