This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
SwiftCommons is a collection of simple, small, and reusable Swift components created to support command line tools in macvm. The project currently provides SCInject, a minimalistic and efficient dependency injection container.
This project uses mise as the task runner. Common commands:
# Build the project
make build
# or directly:
mise run build
# Run tests
make test
# or:
mise run test
# Run a single test
swift test --filter <test-name>
# Format code (uses SwiftFormat)
make format
# Lint code (uses SwiftLint and SwiftFormat)
make lint
# Auto-fix lint issues
make autocorrect
# Clean build artifacts
make clean
# Show build environment
make envSCInject is the primary module providing a lightweight DI container with the following key components:
Core Protocols:
Container: Combines Registry and Resolver functionalityRegistry: Interface for registering dependenciesResolver: Interface for resolving dependenciesAssembly: Protocol for organizing dependency registrations into modular units
Main Implementation:
DefaultContainer: Thread-safe container supporting hierarchical DI with parent-child relationships- Supports two scopes:
.transient: Creates a new instance on each resolution.container: Singleton behavior - creates once and reuses
Registration Patterns:
// Basic registration
container.register(MyService.self) { r in MyService() }
// With scope
container.register(MyService.self, .container) { r in MyService() }
// With name
container.register(MyService.self, name: "special") { r in MyService() }Resolution:
let service = container.resolve(MyService.self)
let named = container.resolve(MyService.self, name: "special")
let optional = container.tryResolve(MyService.self) // Returns nil if not registeredAssembly Pattern:
Use Assembler to organize registrations into modular Assembly units:
class MyAssembly: Assembly {
func assemble(_ registry: Registry) {
registry.register(MyService.self) { r in MyService() }
}
}
let assembler = Assembler(container: DefaultContainer())
.assemble([MyAssembly()])
let resolver = assembler.resolver()Validation:
The container provides a validate() method to verify all dependencies can be resolved, useful for catching configuration issues during testing.
Sources/SCInject/: Main DI container implementationContainer.swift: Container protocol and DefaultContainer implementationRegistry.swift,Resolver.swift: Core protocolsAssembly.swift,Assembler.swift: Modular registration patternScope.swift: Lifecycle managementRegistrationName.swift: Named registration support
Sources/SCInjectObjc/: Objective-C support moduleTests/SCInjectTests/: Test suite with XCTest
Required Versions:
- Xcode 26.0.1
- Swift 6.2
- macOS 26 (for CI compatibility)
Swift Language:
- Project uses Swift 6 language mode (strict concurrency)
- Minimum platform versions:
- macOS 10.13
- iOS 15
- visionOS 1
- watchOS 9
- tvOS 16
The project enforces code quality through SwiftLint and SwiftFormat:
SwiftFormat config (.swiftformat):
- Max line width: 120 characters
- Swift version: 5.10
- Attributes on previous line for functions, types, and vars
- Wrap arguments/parameters before first
SwiftLint config (.swiftlint.yml):
- Disabled rules: trailing_comma, opening_brace, force_try
- Identifier name exceptions:
r,id - Type name exceptions:
T
# Install mise (if not already installed)
make setup
# First time setup
mise installThe project uses mise (.mise.toml) to manage tool versions:
- swiftlint 0.54.0
- swiftformat 0.53.3
The project uses GitHub Actions (.github/workflows/main.yml) with three jobs:
- Lint: Runs SwiftLint and SwiftFormat checks
- Build: Builds the project with SPM caching
- Test: Runs the test suite with SPM caching
All jobs run on macos-26 with Xcode 26.0.1.