How to Integrate Codex Directly into Xcode — Plus the Best SwiftUI Skills

Xcode can now host Codex directly inside its Coding Assistant. That changes the workflow completely: instead of keeping an AI agent in a separate terminal or desktop window, you can start a Codex conversation beside your source code, give it project context, review edits in place, and let Xcode expose native capabilities such as building and testing.

This guide covers the settings-level integration, the separate MCP route for external Codex sessions, and a careful way to add third-party SwiftUI and Swift Concurrency skills.

Before you start

Use a current Xcode release that includes Intelligence settings and the Coding Assistant. Availability can depend on the Xcode release, region, account, and managed-device policy. Update Xcode first, then open a project that already builds successfully. Commit or create a Git checkpoint before asking any agent to edit the code.

1. Install Codex from Xcode Settings

  1. Choose Xcode > Settings.
  2. Select Intelligence in the sidebar.
  3. Under Agents, find Codex and click Get.
  4. Review the installation sheet and click Install.
  5. Open the Codex agent settings. In the Account row, click the More button and follow the sign-in flow if you want to use your account.

Xcode can update downloaded agents automatically when possible. Before using an agent on proprietary code, read the privacy information linked from Intelligence settings. The selected agent may receive project files and other context needed to process a request.

2. Open Codex in the Coding Assistant

Open the Coding Assistant with its toolbar button or press Command-0. Start a new conversation and choose Codex as the agent. The selected agent runs in Xcode’s conversation workspace, where you can keep the transcript, source, and generated artifacts visible together.

For a focused source-editor request, select code and use the coding tools popover, or press Command-Option-0. Starting from a selection is especially useful for explaining unfamiliar code, adding documentation, or refactoring one type without inviting a repository-wide rewrite.

A good first prompt is:

Inspect this project without editing files. Identify the active app target, deployment target, test targets, concurrency settings, and the safest build-and-test plan. Report any assumptions before making changes.

3. Configure permissions deliberately

Agents can become much more useful when they may run build tools, tests, formatters, and project-specific scripts. They also become more powerful, so treat permissions as part of the project’s security model.

In Xcode > Settings > Intelligence, open the Permissions row under Agents. Review previously allowed commands and tools. Add only the command-line tools the project actually needs, such as a formatter or a project-owned test script.

A sensible starting policy is:

  • Allow read-only project inspection and normal builds.
  • Allow the project’s tests and formatter.
  • Require review for dependency changes, scripts downloaded from the internet, signing changes, and destructive commands.
  • Do not grant broad shell access merely to avoid an occasional approval.

4. Customize Codex specifically for Xcode

Xcode keeps agent-specific configuration in subfolders beneath:

~/Library/Developer/Xcode/CodingAssistant

Codex configuration used only when Codex launches inside Xcode belongs in:

~/Library/Developer/Xcode/CodingAssistant/codex

This separation is useful: settings for Codex inside Xcode do not have to affect every Codex session on your Mac. You can set an appropriate model, add MCP servers, or provide Xcode-specific guidance while keeping external workflows independent.

Also place an AGENTS.md file in the repository root for project rules that should travel with the code:

# Apple project guidance
- Use SwiftUI and modern Swift Concurrency.
- Assume strict concurrency checking.
- Prefer async/await, actors, and structured concurrency over GCD.
- Preserve bundle identifiers, signing, capabilities, and entitlements.
- Do not add dependencies without approval.
- Run the app target build and relevant tests before finishing.
- Use availability checks and fallbacks for newer platform APIs.
- Keep views accessible with Dynamic Type and VoiceOver.

5. Add SwiftUI and concurrency skills

Agent skills are focused instruction packages that teach an agent a repeatable workflow or domain-specific rules. In current Xcode releases, agentic coding plug-ins can contain skills, subagents, and MCP servers.

  1. Open Xcode > Settings > Intelligence.
  2. Choose the Plug-ins row under Agents.
  3. Click Add Plug-in.
  4. Choose an import method. For a repository, select the URL option and paste its GitHub URL.
  5. Review the components, select only the skills you need, and click Install.

Not every repository is packaged as an Xcode-compatible agent plug-in. If Xcode does not accept it, use the project’s documented Agent Skills installation method for an external Codex workflow instead of forcing it into Xcode.

Popular skills worth evaluating

  • SwiftUI Pro by Paul Hudson — covers modern SwiftUI APIs, state management, navigation, layout, performance, accessibility, and common model mistakes.
  • Swift Concurrency Pro by Paul Hudson — targets async/await, actors, Sendable, task groups, structured concurrency, and newer language behavior.
  • SwiftUI Expert by Antoine van der Lee — emphasizes modern APIs, view composition, invalidation and performance, lists, localization, Liquid Glass, and Instruments traces.
  • Swift Concurrency by Antoine van der Lee — includes Swift 6 migration, actor isolation, async sequences, testing, performance, and concurrency triage.
  • Swift iOS Skills by Daniel Pearson — a broad collection with focused skills for SwiftUI, concurrency, SwiftData, StoreKit, accessibility, networking, testing, and Apple frameworks. Install only the modules you use.

For an external Codex installation, many of these repositories document a command such as:

npx skills add https://github.com/twostraws/swiftui-agent-skill --skill swiftui-pro
npx skills add https://github.com/twostraws/swift-concurrency-agent-skill --skill swift-concurrency-pro

These commands install third-party code and instructions. Review the repository, license, recent maintenance, SKILL.md, scripts, and permissions before running them. Prefer a pinned release or commit for a team workflow, and retest skills after major Xcode or Swift changes.

6. Use external Codex with Xcode’s MCP bridge

Installing Codex inside Xcode and connecting an external Codex session are two different workflows. If you want the Codex CLI or desktop workflow to use the open Xcode project and its tools, enable Xcode’s MCP bridge:

  1. Choose Xcode > Settings > Intelligence.
  2. Under Model Context Protocol, turn on Allow external agents to use Xcode tools.
  3. In Terminal, run:
codex mcp add xcode -- xcrun mcpbridge
codex mcp list

Keep the intended project open in Xcode before prompting the external agent. Xcode displays when an external agent connects and when it is active.

This route is ideal when you prefer the Codex app or CLI but still want Xcode-native build, test, project, and simulator capabilities. The in-Xcode agent route is better when you want conversations, diffs, and source context inside the Xcode workspace.

7. A modern Swift Concurrency prompt

Skills work best when the task still states the target and proof clearly:

Use the Swift Concurrency skill to review this feature for Swift 6 strict-concurrency issues. Check actor isolation, Sendable conformance, task lifetime, cancellation, and accidental unstructured concurrency. Do not silence diagnostics with unchecked conformance. Make minimal fixes, build the app, run focused tests, and explain any remaining warnings.

For SwiftUI, ask the skill to inspect data ownership, @Observable flow, ForEach identity, view invalidation, accessibility, navigation, and availability checks. Do not ask it to “modernize everything” in one pass; separate correctness, migration, and performance work.

Pro tips

  • Use one skill per concern. Loading every iOS skill wastes context and can produce conflicting advice.
  • Keep skills advisory. Your deployment target, architecture, and product requirements outrank generic rules.
  • Review generated project-file changes. Treat edits to project.pbxproj, entitlements, capabilities, build settings, and signing as high risk.
  • Ask for evidence. Require the build command, test result, changed files, and remaining diagnostics.
  • Create checkpoints. Xcode conversation rollback is helpful, but Git remains the durable source of truth.
  • Audit updates. A popular skill can still become outdated or compromised. Re-review changes before updating a shared installation.

Official references

The strongest setup is intentionally small: Codex enabled in Xcode, carefully scoped permissions, a concise AGENTS.md, one SwiftUI skill, one concurrency skill, and a build-and-test loop you trust.

How to Configure Codex for Xcode: A Practical Setup and Pro Tips

Codex can be a remarkably effective partner for iOS and macOS development, but there is one important detail to understand first: you do not configure it as a native Xcode extension. The best workflow is to let Xcode remain your visual editor, signing environment, preview canvas, and debugger while Codex works directly with the same project folder from the Codex app or CLI.

Once both tools point at the same repository, Codex can inspect Swift and SwiftUI code, make focused edits, run builds with xcodebuild, analyze compiler errors, write tests, and help debug simulator issues.

1. Prepare the Xcode project

Start with a project that builds successfully in Xcode. Resolve signing errors, select the intended scheme, and run the app once on your preferred simulator. This gives Codex a clean baseline and avoids confusing an existing project problem with an AI-generated change.

If the project uses Swift Package Manager, let Xcode finish resolving packages first. For workspaces, open the .xcworkspace rather than the .xcodeproj when CocoaPods or another tool generated the workspace.

2. Open the same repository in Codex

In the Codex desktop app, create or open a project that points to the folder containing the Xcode project or workspace. If you prefer the terminal, change into that directory before starting Codex. Keeping the repository root as the working directory gives the agent access to source files, tests, configuration, assets, and project instructions.

A useful first prompt is:

Inspect this Xcode project without changing files. Identify the app target, scheme, deployment target, test targets, package dependencies, and the safest xcodebuild command for a simulator build.

Ask Codex to inspect first, then make changes. That small habit prevents many incorrect assumptions about schemes, destinations, and project structure.

3. Establish a repeatable command-line build

Codex is most reliable when it can verify work without depending on clicks in the Xcode GUI. Ask it to list available schemes:

xcodebuild -list -project MyApp.xcodeproj

Then establish a simulator build command, for example:

xcodebuild \
  -project MyApp.xcodeproj \
  -scheme MyApp \
  -sdk iphonesimulator \
  -destination 'platform=iOS Simulator,name=iPhone 17 Pro' \
  build

For a workspace, replace -project with -workspace MyApp.xcworkspace. Simulator names vary by installed Xcode version, so let Codex query available devices instead of hard-coding one blindly.

4. Add project instructions with AGENTS.md

Create an AGENTS.md file at the repository root. Codex reads this file as project-specific guidance, making it the ideal place to record conventions that should survive across tasks.

# Project guidelines
- Use SwiftUI and Swift Concurrency.
- Support iOS 18 and newer.
- Prefer @Observable for new shared state.
- Do not add dependencies without approval.
- Keep views small and extract reusable subviews.
- Run the app scheme build and unit tests before finishing.
- Never modify signing, bundle identifiers, or entitlements unless asked.

Include real commands for formatting, linting, tests, and code generation. The more deterministic the verification loop, the more useful Codex becomes.

5. Give Codex focused tasks

Good tasks include the desired behavior, constraints, and the proof required before completion. Instead of saying “fix the settings screen,” try:

Fix the settings screen layout on compact-width iPhones. Preserve current behavior and accessibility identifiers. Build the app for an available iPhone simulator, run the relevant tests, and summarize every changed file.

For risky refactors, ask for a plan first. For small visual tweaks, keep the task narrow and request a screenshot or simulator verification when available.

Pro tips for experienced Xcode users

Use a dedicated derived-data directory

Give automated builds their own derived-data path. This makes cleanup predictable and reduces interference with an Xcode session:

xcodebuild ... -derivedDataPath .build/DerivedData

Add the directory to .gitignore.

Prefer structured compiler output

Long build logs consume attention and context. Use a formatter such as xcbeautify if it is already part of the project, or ask Codex to focus on error: and warning: lines. Do not let it hide the original exit status.

Separate build, test, and UI-debug loops

A fast compile loop should not always launch the simulator. Use three explicit commands: one for building, one for unit tests, and one for UI or simulator debugging. Codex can then choose the least expensive proof for each change.

Protect signing and project metadata

Changes to project.pbxproj, entitlements, capabilities, and signing settings deserve extra review. Tell Codex not to touch them unless the task requires it, and inspect those diffs carefully before committing.

Use worktrees for parallel experiments

When exploring multiple implementations, use Git worktrees or separate branches so each Codex task has an isolated checkout. This avoids overlapping edits and makes it easy to compare approaches before merging one.

Add XcodeBuildMCP for deeper automation

Advanced users can add an Xcode-focused MCP server such as XcodeBuildMCP. It can provide a more structured bridge to schemes, builds, simulators, screenshots, and UI automation. Treat third-party MCP servers like development tools: review their permissions, pin versions where possible, and start with the narrowest access that works.

Ask for evidence, not confidence

The best final prompt is often simple: “Show me the build command, test result, remaining warnings, and the exact diff.” A successful build and focused tests are much more valuable than a confident explanation.

A practical daily workflow

  1. Open the project in Xcode and confirm the current branch builds.
  2. Open the same repository in Codex.
  3. Ask Codex to inspect the relevant files and propose a short plan.
  4. Approve a focused implementation.
  5. Let Codex build and test from the command line.
  6. Review the diff in Codex or Xcode.
  7. Run the final UI check, previews, signing, and archive flow in Xcode.

This division of labor works well: Xcode remains the authoritative Apple development environment, while Codex handles codebase navigation, repetitive edits, tests, build diagnostics, and carefully scoped automation.

Official resources

Tip: keep the first version of your setup deliberately simple. A reliable xcodebuild command plus a clear AGENTS.md file delivers more value than a large collection of tools that nobody maintains.

SwiftUI Adaptive Design: Creating Flexible UIs for All Devices

In the ever-evolving world of iOS development, creating adaptive user interfaces is crucial for delivering a seamless experience across various devices and orientations. SwiftUI provides several powerful tools to help developers craft flexible layouts that respond gracefully to different screen sizes and configurations. Let’s explore some key techniques for adaptive design in SwiftUI.

GP Forecast Adaptive Designs

ViewThatFits: Automatic Layout Adaptation

ViewThatFits is a SwiftUI container view that automatically selects the first child view that fits within the available space. This powerful tool simplifies the process of creating adaptive layouts by allowing you to define multiple layout options and letting SwiftUI choose the most appropriate one. Here’s an example of how to use ViewThatFits:

ViewThatFits {
    HStack {
        Image(systemName: "star.fill")
        Text("Favorite")
    }

    Image(systemName: "star.fill")
}

In this example, SwiftUI will display the HStack with both the image and text if there’s enough space. If not, it will fall back to showing just the image.

Size Classes: Adapting to Device Characteristics

Size Classes in SwiftUI allow you to adapt your layout based on the available space and device characteristics. By using the @Environment property wrapper, you can access the current horizontal and vertical size classes to make layout decisions.
Here’s how you can use size classes to adjust your layout:

@Environment(\.horizontalSizeClass) var horizontalSizeClass

var body: some View {
    Group {
        if horizontalSizeClass == .compact {
            VStack {
                // Compact layout
            }
        } else {
            HStack {
                // Regular layout
            }
        }
    }
}

This approach allows you to create distinct layouts for different device configurations, such as iPhones in portrait mode versus iPads in landscape mode. Here you can find all the size classes for each Apple Device.

GeometryReader: Fine-Grained Layout Control

GeometryReader is a powerful tool that provides detailed information about the size and position of its parent view. This allows for precise control over layout and sizing based on the available space. Here’s an example of using GeometryReader to create a responsive layout:

GeometryReader { geometry in
    VStack {
        Text("Hello, World!")
            .font(.system(size: geometry.size.width / 10))

        Rectangle()
            .fill(Color.blue)
            .frame(width: geometry.size.width * 0.8, height: 50)
    }
}

In this example, the text size and rectangle width are dynamically calculated based on the available width, ensuring the layout remains proportional across different screen sizes.

UIScreen.main.bounds.width: A Practice to Avoid

While it might be tempting to use UIScreen.main.bounds.width for layout calculations, this approach is considered bad practice in SwiftUI. It doesn’t account for factors like Split View on iPad, rotation changes, or future device form factors.
Instead of relying on UIScreen.main.bounds.width, it’s better to use SwiftUI’s built-in layout system, including GeometryReader, size classes, and flexible spacing. These tools provide a more robust and future-proof way to create adaptive layouts.

Conclusion

Adaptive design in SwiftUI is about creating flexible, responsive layouts that work well across all iOS devices. By leveraging tools like ViewThatFits, size classes, and GeometryReader, you can create UIs that automatically adjust to different screen sizes and orientations. Remember to avoid hard-coding dimensions or relying on specific device characteristics, and instead embrace SwiftUI’s powerful layout system for truly adaptive designs.

Here is a Login Screen example;

Login Screen example
import SwiftUI

struct LoginView: View {
    @State private var username = ""
    @State private var password = ""
    @State private var rememberMe = false
    @State private var showingAlert = false
    @Environment(\.horizontalSizeClass) var horizontalSizeClass
    
    var body: some View {
        GeometryReader { geometry in
            ScrollView {
                VStack(spacing: 20) {
                    // Avatar Image
                    Image(systemName: "person.circle.fill")
                        .resizable()
                        .aspectRatio(contentMode: .fit)
                        .frame(width: horizontalSizeClass == .compact ? geometry.size.width * 0.3 : geometry.size.width * 0.2)
                        .foregroundColor(.blue)
                        .padding(.top, 40)
                    
                    // Welcome Text
                    Text("Welcome Back!")
                        .font(.system(size: geometry.size.width * 0.06))
                        .fontWeight(.bold)
                    
                    // Login Form
                    VStack(spacing: 15) {
                        TextField("Username", text: $username)
                            .textFieldStyle(RoundedBorderTextFieldStyle())
                            .autocapitalization(.none)
                        
                        SecureField("Password", text: $password)
                            .textFieldStyle(RoundedBorderTextFieldStyle())
                        
                        Toggle("Remember Me", isOn: $rememberMe)
                    }
                    .padding(.horizontal)
                    .frame(width: horizontalSizeClass == .compact ? geometry.size.width * 0.5 : geometry.size.width * 0.3)
                    
                    // Login Button
                    Button(action: {
                        // Perform login action
                        showingAlert = true
                    }) {
                        Text("Log In")
                            .fontWeight(.semibold)
                            .foregroundColor(.white)
                            .frame(maxWidth: .infinity)
                            .padding()
                            .background(Color.blue)
                            .cornerRadius(10)
                    }
                    .padding(.horizontal)
                    .frame(width: geometry.size.width * 0.3, height: geometry.size.width * 0.3)
                    
                    // Forgot Password Link
                    Button("Forgot Password?") {
                        // Handle forgot password action
                    }
                    .foregroundColor(.blue)
                    
                    // Social Login Options
                    ViewThatFits {
                        HStack(spacing: 20) {
                            socialLoginButton(imageName: "apple.logo", text: "Sign in with Apple")
                            socialLoginButton(imageName: "g.circle", text: "Sign in with Google")
                        }
                        VStack(spacing: 10) {
                            socialLoginButton(imageName: "apple.logo", text: "Sign in with Apple")
                            socialLoginButton(imageName: "g.circle", text: "Sign in with Google")
                        }
                    }
                    .padding(.top)
                    
                    // Sign Up Link
                    HStack {
                        Text("Don't have an account?")

                        Button("Sign Up") {
                            // Handle sign up action
                        }
                        .foregroundColor(.blue)
                    }
                    .padding(.top)
                }
                .padding()
                .frame(minHeight: geometry.size.height)
            }
        }
        .alert(isPresented: $showingAlert) {
            Alert(title: Text("Login Attempt"), message: Text("Username: \(username)\nPassword: \(password)"), dismissButton: .default(Text("OK")))
        }
    }
    
    private func socialLoginButton(imageName: String, text: String) -> some View {
        Button(action: {
            // Handle social login action
        }) {
            HStack {
                Image(systemName: imageName)

                Text(text)
            }
            .padding()
            .frame(maxWidth: .infinity)
            .background(Color.gray.opacity(0.2))
            .cornerRadius(10)
        }
    }
}


#Preview {
    LoginView()
}

Xcode SwiftUI Preview Tips

Loved by some, hated by many developers — is the SwiftUI preview. I was also in the latter camp to be honest, until recently.

Here are some things you can do to enjoy your SwiftUI previews again.

When you get an error, tap on the error and read it carefully, often it gives a hint. For example, you have been changing code left and right, then you went to this certain view, and you activated the preview pane with Option+Command+Enter — and getting an error.

Make sure before activating a preview canvas, that your code builds and if not, then fix the error and try again.

If you have done this and you still get an error, make sure you don’t have another tab open with a preview active for another target, close those and try again.

If that also fails you can try to clear the preview cache with this terminal command, I made an alias in .zprofile called simprevdel.

Compiler flag PREVIEW

You can add the PREVIEW compiler flag to use it as a compiler directive to load preview mock data.

Don’t forget to inject the EnvironmentObject model in the Preview View.

Enjoy your previews!

SwiftUI autocomplete tricks

Fonts

There are some view properties which you use a lot and are difficult to type like:

.font(.caption)

here you type .font [ENTER] -> this makes .font(), you have to cursor back into the brackets to type .cap[ENTER]

This you can achieve faster by typing .fontcaption[ENTER], or .fonttitle[ENTER]

Frames

You probably know already the properties trick to type the first two characters of the properties to get them preselected like so typing .framewihe[ENTER]:

If you only want one of those sub properties you can type directly

.width[ENTER]

Xcode tip – rename

When you start developing an app, you don’t often know yet what the real name of your app will be, even you think you know. What do I mean by that?

Well, say you call your app TrainSleeper. You create the new app like this in Xcode and all is fine. Once you create the app in App Store Connect, it might shout at you that someone else owns this name and you cannot use it. You start searching for an app with this name in the store to see it, but it does not exist. This is because you can add an app with a certain name but never publish it. That name stays locked to the person who did this.

Anyway we need a lot of renaming during each development cycle, there is nothing to be ashamed about, it’s a very common task.

For this reason I added a keyboard shortcut to rename.

Give the rename menu function a shortcut.

Go to Settings with CMD + ,

Go to the Key Bindings tab

In filter type rename

In the key column after the rename word press all the keys you want, I selected;

SHIFT + CONTROL + OPTION + COMMAND + R

Why so many keys? Well Xcode has many shortcuts, this avoids conflict with other shortcuts