This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
PhoneNumberKit is a Swift framework for parsing, formatting, and validating international phone numbers, inspired by Google's libphonenumber. Supports iOS, macOS, tvOS, watchOS, and Linux.
This is the foundation package (core parsing/formatting/validation + metadata). It is the
continuation of the original marmelroy/PhoneNumberKit, now maintained under the PhoneNumberKit
organization. UI components (PhoneNumberTextField, country-code picker) live in a separate
package: PhoneNumberKitUI, which depends
on this one. Distribution is Swift Package Manager only (CocoaPods/Carthage were dropped in 5.0).
This is a pure Swift package — use the swift toolchain only (no .xcodeproj, no xcodebuild).
# Test (works on Linux and macOS)
swift test
# Build
swift build
# Update metadata from Google's libphonenumber (requires Python 3.12+ and xmljson)
cd Sources/PhoneNumberKit/Resources && sh ./update_metadata.shSource lives under Sources/PhoneNumberKit/, tests under Tests/PhoneNumberKitTests/.
- PhoneNumberUtility (
Sources/PhoneNumberKit/PhoneNumberUtility.swift) — main entry point for all operations. Expensive to allocate (parses metadata into memory); instantiate once and reuse. - PhoneNumber (
Sources/PhoneNumberKit/PhoneNumber.swift) — immutable,Sendablestruct: numberString, countryCode, leadingZero, nationalNumber, numberExtension, type, regionID. Equatable, Hashable, Codable. - MetadataManager (
Sources/PhoneNumberKit/MetadataManager.swift) — loads metadata from the bundled JSON; O(1) lookup by country code / region ID; handles shared calling codes (e.g. NANPA). - PhoneNumberParser (
Sources/PhoneNumberKit/PhoneNumberParser.swift) — internal normalization, prefix/extension stripping, type determination. - ParseManager (
Sources/PhoneNumberKit/ParseManager.swift) — coordinates parser + metadata; single and batch parsing.
- Formatter (
Sources/PhoneNumberKit/Formatter.swift) —internal. Formats to E164, international, national. - PartialFormatter (
Sources/PhoneNumberKit/PartialFormatter.swift) —publicas-you-type formatter. Gated#if canImport(ObjectiveC)— not available on Linux. Consumed by PhoneNumberKitUI's text field, but lives here.
- Metadata loading: loaded once at
PhoneNumberUtilityinit via a callback; default reads the bundledPhoneNumberMetadata.jsonfromBundle.module. Inject a custom source viametadataCallback. - Type validation: parser matches metadata patterns per type; skip with
ignoreTypefor performance. Hierarchy: specific types (mobile, pager…) → fixedOrMobile → unknown. - Region detection:
CNContactsUserDefaultscountry code, falling back toLocale.current; handles macCatalyst edge cases. - Performance: batch array parsing; regex cached in RegexManager; O(1) metadata dictionaries.
swift-tools-version: 5.9. Platforms: iOS 13, macOS 10.15, tvOS 13, watchOS 6 (+ Linux).- Products:
PhoneNumberKit(auto),PhoneNumberKit-Static,PhoneNumberKit-Dynamic. - Target
PhoneNumberKitatSources/PhoneNumberKit; resources:PhoneNumberMetadata.json(processed),PrivacyInfo.xcprivacy(copied).Resources/Original(source XML) and the update script are excluded from the target. - Public value types conform to
Sendable(PhoneNumber, the Metadata* structs, enums in Constants).
- Source: Google's libphonenumber. Script:
Sources/PhoneNumberKit/Resources/update_metadata.sh(note itscd ../../..returns to repo root from the Resources dir — tied to the Sources layout). - Workflow
.github/workflows/update_metadata.ymlruns every 12h (and on demand), opens a PR. .github/workflows/release.ymlcuts a patch release (tag + GitHub release) when.metadata-versionchanges; the version is derived from the latest semver git tag (no podspec).
pr.ymlruns three parallel jobs:swift teston Linux,swift teston macOS, and an iOS compile guarantee (xcodebuild -scheme PhoneNumberKit -destination generic/platform=iOS buildagainstPackage.swift—swift buildcan't target iOS). macOS covers iOS's source paths (no iOS-only code); Linux differs via thecanImport(ObjectiveC)/!os(Linux)guards, so it's tested separately.- All CI shells use
set -o pipefail.
- Create
PhoneNumberviaPhoneNumberUtility, not directly (deprecated initializers fail). - Reuse
PhoneNumberUtilityinstances — they're expensive to allocate. PartialFormatterrequires ObjectiveC (not on Linux).- Use
ignoreTypeand the array parsing method for performance-sensitive paths. - UI work belongs in PhoneNumberKitUI, not here. Keep this package UI-free (no UIKit imports).