Getting started
After this guide, CodeGuard is installed, finds its tools and has checked a first project.
Requirements
| What | Requirement |
|---|---|
| Operating system | macOS 15 or later. The target minimum is 15.6; certification for it is still pending. |
| To build CodeGuard | Swift toolchain with swift-tools-version 6.3 |
| Xcode | For swift-format, swift, xcodebuild and simctl. xcodebuild must have a version >= 26.0.0 and < 28.0.0. |
swift-format | From the active Xcode toolchain. Supported are 6.3.x and the unversioned build from Xcode 27 (reports itself as main). |
swiftlint | Required by default. If it is missing, every check run ends with exit 3. |
git | For check-diff, resolved from a trusted directory (e.g. /usr/bin). |
The sample output in this help comes from real runs of codeguard 0.3.5 on macOS 27.0.1 (Apple Silicon) with Xcode 27.0 (build 27A266a), SwiftLint 0.65.1 and iOS simulator runtime 27.0. On other versions, version numbers, durations and device names may differ.
Installation
CodeGuard is built from source. The install script builds in release mode as your user and then uses sudo to copy the binary and the three resource bundles into the same directory, owned by root:wheel.
-
Get the source code:
git clone <REPOSITORY-URL> CodeGuard # placeholder: enter the repository URLcd CodeGuard -
Build and install:
Scripts/install.sh # installs to /usr/local/binScripts/install.sh --bindir DIR # installs to DIRThe script refuses to run as
root. It only callssudofor copying. -
Verify the installation:
codeguard versioncodeguard 0.3.5 (configuration schema 1, report schema 1)
These bundles must sit next to the binary:
CodeGuard_CodeGuardConfiguration.bundleCodeGuard_CodeGuardReporting.bundleCodeGuard_CodeGuardAnalysis.bundle
If one is missing, every command aborts with exit 9 and reports installation incomplete: resource bundle … not found next to the codeguard executable. So never copy the binary on its own.
Set up the organization policy
CodeGuard only starts tools from trusted directories (trusted_roots). Without your own policy, these defaults apply:
/usr/bin
/usr/local/bin
/opt/homebrew/bin
/Applications/Xcode.app/Contents/Developer/usr/bin
A standard Xcode installation, however, ships swift-format and swift under /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin. Without a policy, doctor therefore reports swift-format: unavailable, checks of .swift files end with exit 6, and the SwiftPM build can end with exit 3. A project configuration can't fix this; tool paths belong to the organization policy.
-
Create the policy (template from the repository,
docs/help/policy.example.yml):policy_version: 1configuration_versions: [1]enforcement:tools:trusted_roots:- /usr/bin- /usr/local/bin- /Applications/Xcode.app/Contents/Developer/usr/bin- /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin -
Install it with the correct permissions. The file and all directories above it must be owned by
rootand must not be group- or world-writable:sudo mkdir -p "/Library/Application Support/CodeGuard"sudo install -o root -g wheel -m 0644 docs/help/policy.example.yml \"/Library/Application Support/CodeGuard/policy.yml" -
Verify:
codeguard config validateThe output names the policy with its hash, for example:
configuration valid (schema 1, sha256:b6d2da11a83b32a5c08fd1941bc85affa4a50ed7ec50c93d975457ff05a23dad)policy: /Library/Application Support/CodeGuard/policy.yml (sha256:22a9eaedcf877ffbbdcbcaad6d510810c334a29c194ea81404cd2eca324aee80)
All policy keys are listed on the Organization policy page.
Provide SwiftLint
SwiftLint doesn't ship with Xcode. CodeGuard only looks for it under the trusted directories.
/opt/homebrew/bin and /opt/homebrew/Cellar/… belong to the user who installed Homebrew. Any process of that user, such as a SwiftPM plugin, could replace swiftlint there while the root-owned policy keeps trusting it. CodeGuard doesn't check the owner of a trusted directory itself.
Create a root-owned copy instead:
sudo install -o root -g wheel -m 0755 "$(realpath /opt/homebrew/bin/swiftlint)" /usr/local/bin/swiftlint
Repeat this after every brew upgrade swiftlint. On Apple silicon Macs, /usr/local/bin is owned by root. On Intel Macs it is usually owned by Homebrew; in that case, create another root-owned directory and add it to trusted_roots.
If CodeGuard finds a tool under two trusted directories (for example a symlink in one root and its target in another), the resolver rejects it as ambiguous. doctor then shows the tool as unavailable.
Check your environment
codeguard doctor
Output on the reference machine, run in an empty folder (hence compile/tests: inactive):
ready: true
policy: /Library/Application Support/CodeGuard/policy.yml (sha256:22a9eaedcf877ffbbdcbcaad6d510810c334a29c194ea81404cd2eca324aee80)
configuration: active
git-diff: active
path-policy: active
read-only-checks: active
reports: active
trust-state: active
swift-format: active (main)
swiftlint: active
compile: inactive
tests: inactive
autofix: inactive
agent-adapters: inactive
platform-checks: active (1)
content-rules: active (secret-detectors-v1)
unauthorized-network-destination: inactive
platform.macos: available (27.0)
platform.ios: available (27.0)
platform.watchos: available (27.0)
platform.tvos: available (27.0)
platform.visionos: available (27.0)
simctl: active (1171.7.0) /Applications/Xcode.app/Contents/Developer/usr/bin/simctl
simulator.ios: available (device type: iPhone 18 Pro)
simulator.ios.runtime: 27.0 (24A434)
simulator.ios.runtime: 26.5 (23F77)
simulator.ios.runtime: 18.5 (22F77)
simulator.watchos: unavailable
simulator.tvos: unavailable
simulator.visionos: unavailable
Verwaiste CodeGuard-Geräte: 0
How to read the output:
| Status | Meaning |
|---|---|
active | The capability is available |
unavailable | Tool enabled but can't be resolved |
incompatible | Tool found, but the version doesn't match |
inactive | Disabled or not relevant in this context |
ready: truemeans every enabled format and lint check is ready to use.platform.<name>shows whether the SDK is installed,simulator.<name>whether a simulator runtime exists for it. In the example, all SDKs are present, but only iOS runtimes. Tests for watchOS, tvOS and visionOS would therefore be skipped.doctornever runs a lint or a build. It only determines paths and versions.
First check run
-
Change to the root of your project (where
Package.swiftor the.xcodeprojis). -
Check a single file:
codeguard check-file Sources/MeinModul/Datei.swift -
Check your Git changes against
main:codeguard check-diff --base main --include-untrackedWithout a trust ticket, this ends with
CODEGUARD_BLOCKEDand exit 6 for projects with aPackage.swiftor Xcode project, becausecompileandtestswould run project code. The static checks still run and appear in the report. -
Grant trust to the project (in the terminal, confirm with
yes):codeguard trust grant --duration 24hAfter that,
check-diffbuilds and tests the project. For more, see Trust and security.
The day-to-day workflow is described under Manual use, the meaning of every line in the report under Reading reports.