> ## Documentation Index
> Fetch the complete documentation index at: https://ngquct-feat-ai-sql-walkthroughs.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# Development Setup

> Clone, configure signing, and build TablePro in Xcode

# Development Setup

## Prerequisites

| Software | Version        | Notes              |
| -------- | -------------- | ------------------ |
| macOS    | 14.0+ (Sonoma) | Target platform    |
| Xcode    | 15.0+          | Includes Swift 5.9 |

Optional but recommended:

| Tool        | Install                    | Purpose                    |
| ----------- | -------------------------- | -------------------------- |
| SwiftLint   | `brew install swiftlint`   | Linting                    |
| SwiftFormat | `brew install swiftformat` | Code formatting            |
| GitHub CLI  | `brew install gh`          | Used by `download-libs.sh` |

## Quick Start

<Steps>
  <Step title="Clone the repository">
    ```bash theme={null}
    git clone https://github.com/TableProApp/TablePro.git && cd TablePro
    ```
  </Step>

  <Step title="Download native libraries">
    ```bash theme={null}
    scripts/download-libs.sh
    ```

    This pulls pre-built `.a` files (libmariadb, libpq, etc.) from GitHub Releases into `Libs/`. Takes a few seconds.

    <Warning>
      Skipping this step causes linker errors. The static libraries are not checked into git.
    </Warning>
  </Step>

  <Step title="Create build config">
    ```bash theme={null}
    touch Secrets.xcconfig
    ```

    Empty file is fine for development. Production builds use this for API keys.
  </Step>

  <Step title="Install tools">
    ```bash theme={null}
    brew install swiftlint swiftformat
    ```
  </Step>

  <Step title="Open in Xcode">
    ```bash theme={null}
    open TablePro.xcodeproj
    ```
  </Step>

  <Step title="Configure signing">
    1. Select the **TablePro** target
    2. Go to **Signing & Capabilities**, **Debug** sub-tab
    3. Change **Team** to your Apple Developer account (a free personal team works)
    4. Change the **Bundle Identifier** from `com.TablePro` to something unique, for example `com.yourhandle.TablePro`

    The Debug configuration signs with `TablePro.Debug.entitlements`, which drops
    the iCloud capability, so a free personal team can sign it without a paid
    Apple Developer Program membership. If another target still shows a team
    error (a driver plugin or the MCP server), set its **Team** the same way.

    Do not commit the resulting `project.pbxproj` changes; they break official
    Release signing. Hide them locally:

    ```bash theme={null}
    git update-index --skip-worktree TablePro.xcodeproj/project.pbxproj
    ```
  </Step>

  <Step title="Build and run">
    Select the **TablePro** scheme, set destination to **My Mac**, press `Cmd+R`.

    Or from the command line:

    ```bash theme={null}
    xcodebuild -project TablePro.xcodeproj -scheme TablePro -configuration Debug build -skipPackagePluginValidation
    ```

    Xcode writes the built app to DerivedData
    (`~/Library/Developer/Xcode/DerivedData/TablePro-*/Build/Products/Debug`).
  </Step>
</Steps>

Writing a driver plugin? See [Plugin Development](/development/plugin-development) to build one and [Testing a Custom Plugin](/development/testing-plugins) to run it in your local build.

<Frame caption="Xcode project setup">
  <img className="block dark:hidden" src="https://mintcdn.com/ngquct-feat-ai-sql-walkthroughs/Bj1EoTflf_jG6N_3/images/xcode-setup.png?fit=max&auto=format&n=Bj1EoTflf_jG6N_3&q=85&s=1a67319c3ae7841ffd39d1919a783ec7" alt="Xcode setup" width="3024" height="1722" data-path="images/xcode-setup.png" />

  <img className="hidden dark:block" src="https://mintcdn.com/ngquct-feat-ai-sql-walkthroughs/Bj1EoTflf_jG6N_3/images/xcode-setup-dark.png?fit=max&auto=format&n=Bj1EoTflf_jG6N_3&q=85&s=e37bb77e6ec27689b2e1ece034a9eb6b" alt="Xcode setup" width="3024" height="1722" data-path="images/xcode-setup-dark.png" />
</Frame>

## Project Structure

<Tree>
  <Tree.Folder name="TablePro" defaultOpen>
    <Tree.Folder name="Core">
      <Tree.File name="Database/, Plugins/, Services/, Utilities/, SSH/, Autocomplete/" />
    </Tree.Folder>

    <Tree.Folder name="Views">
      <Tree.File name="Connection/, Editor/, Main/, Results/, Settings/, Sidebar/" />
    </Tree.Folder>

    <Tree.Folder name="Models" />

    <Tree.Folder name="ViewModels" />

    <Tree.Folder name="Extensions" />

    <Tree.Folder name="Theme" />

    <Tree.Folder name="Resources" />
  </Tree.Folder>

  <Tree.Folder name="Plugins">
    <Tree.File name=".tableplugin bundles + TableProPluginKit framework" />
  </Tree.Folder>

  <Tree.Folder name="Libs">
    <Tree.File name="Pre-built static libraries (downloaded, not in git)" />
  </Tree.Folder>

  <Tree.Folder name="TableProTests" />

  <Tree.Folder name="docs">
    <Tree.File name="Mintlify docs site" />
  </Tree.Folder>

  <Tree.Folder name="scripts">
    <Tree.File name="build-release.sh, create-dmg.sh, download-libs.sh" />
  </Tree.Folder>
</Tree>

## Running Tests

```bash theme={null}
xcodebuild -project TablePro.xcodeproj -scheme TablePro test -skipPackagePluginValidation
```

Or in Xcode: `Cmd+U`. To run a single class or method, pass `-only-testing:TableProTests/TestClassName` or `-only-testing:TableProTests/TestClassName/testMethodName`.

## Linting and Formatting

Before committing:

```bash theme={null}
swiftlint lint --strict
swiftformat .
```

CI rejects warnings, so plain `swiftlint lint` is not enough. Full tooling reference: [Code Style](/development/code-style).

## Troubleshooting

| Problem                             | Fix                                                                 |
| ----------------------------------- | ------------------------------------------------------------------- |
| Linker errors about missing symbols | Run `scripts/download-libs.sh`                                      |
| SPM resolution fails                | Clean build folder (`Cmd+Shift+K`), reopen Xcode                    |
| Build fails after pulling           | Delete derived data: `rm -rf ~/Library/Developer/Xcode/DerivedData` |
| Missing `Secrets.xcconfig` error    | Run `touch Secrets.xcconfig` in project root                        |
| Code signing errors                 | Change Team in Signing & Capabilities                               |

<Note>
  The `-skipPackagePluginValidation` flag is required because CodeEditSourceEditor (an SPM dependency) bundles a SwiftLint plugin. Without this flag, CLI builds fail with a validation error.
</Note>
