Thank you for your interest in contributing to MachScope!
- macOS 14.0 or later
- Xcode 16.0 or later
- Swift 6.0 or later
- Git
# Clone the repository
git clone https://github.com/sadopc/machscope.git
cd MachScope
# Build
swift build
# Run tests
swift test
# Run the CLI
swift run machscope --versionWe use swift-format for consistent code style:
# Check formatting
xcrun swift-format lint -r Sources/ Tests/
# Auto-format
xcrun swift-format -i -r Sources/ Tests/- Indentation: 2 spaces (swift-format default)
- Line Length: 100 characters max
- Imports: Sorted alphabetically
- Access Control: Explicit (
public,private, etc.)
All types must be Sendable:
// Good
public struct MyType: Sendable {
let value: Int
}
// Bad - not Sendable
public struct MyType {
var callback: () -> Void
}Use domain-specific error types:
// Good
throw MachOParseError.fileNotFound(path: path)
// Bad
throw NSError(domain: "MyError", code: 1)Document public APIs:
/// Parses a Mach-O binary from the given path.
///
/// - Parameters:
/// - path: Absolute path to the binary file
/// - architecture: Target architecture for Universal binaries
/// - Returns: Parsed binary representation
/// - Throws: `MachOParseError` if parsing fails
public init(path: String, architecture: CPUType = .arm64) throwsSources/
├── MachOKit/ # Core Mach-O parsing (no dependencies)
├── Disassembler/ # ARM64 decoder (depends on MachOKit)
├── DebuggerCore/ # Process debugging (depends on both)
└── MachScope/ # CLI application (depends on all)
Tests/
├── MachOKitTests/
├── DisassemblerTests/
├── DebuggerCoreTests/
└── IntegrationTests/
- MachOKit: No external dependencies, pure parsing
- Disassembler: Only depends on MachOKit via protocols
- DebuggerCore: Can use all modules
- MachScope: CLI only, no business logic
# All tests
swift test
# Specific test target
swift test --filter MachOKitTests
# Specific test
swift test --filter MachOKitTests.HeaderTests/testCPUTypeARM64import XCTest
@testable import MachOKit
final class MyTests: XCTestCase {
func testSomething() throws {
// Arrange
let input = ...
// Act
let result = try myFunction(input)
// Assert
XCTAssertEqual(result, expected)
}
func testError() {
// Test error cases
XCTAssertThrowsError(try myFunction(badInput)) { error in
XCTAssertTrue(error is MachOParseError)
}
}
}Test binaries are in Tests/MachOKitTests/Fixtures/:
Tests/MachOKitTests/Fixtures/
├── simple_arm64 # Basic ARM64 executable
├── fat_binary # Universal binary
├── malformed/
│ ├── truncated # Truncated header
│ └── invalid_magic # Wrong magic number
└── README.md # Fixture creation instructions# Create a simple test binary
echo 'int main() { return 0; }' > test.c
clang -arch arm64 -o simple_arm64 test.c
# Create Universal binary
clang -arch arm64 -o arm64_bin test.c
clang -arch x86_64 -o x64_bin test.c
lipo -create arm64_bin x64_bin -output fat_binarygit checkout -b feature/my-feature
# or
git checkout -b fix/bug-description- Write code following style guidelines
- Add tests for new functionality
- Update documentation if needed
# Build
swift build
# Run all tests
swift test
# Format code
xcrun swift-format -i -r Sources/ Tests/git add .
git commit -m "Add feature X
- Detailed description
- Of changes made
Co-Authored-By: Your Name <email@example.com>"git push origin feature/my-featureThen create a Pull Request on GitHub.
- Clear title describing the change
- Description of what and why
- Link to related issues
- Tests passing
- Documentation updated
- Check existing issues
- Create issue if new bug
- Fork, fix, test, PR
- Open issue to discuss
- Get approval on approach
- Implement with tests
- Update docs
- PR
- Fix typos and errors
- Add examples
- Improve clarity
- Translate
- Profile before optimizing
- Include benchmarks
- Document improvements
- Add case to
LoadCommandTypeenum - Create payload struct if needed
- Add parsing in
LoadCommand.parseAll - Add tests
// In LoadCommand.swift
case myNewCommand = 0x99
// Parsing
case .myNewCommand:
let data = try parseMyNewCommand(from: reader, at: offset, size: Int(size))
return LoadCommand(type: type, size: size, payload: .myNewCommand(data))- Identify instruction encoding pattern
- Add to appropriate decoder file
- Add formatting
- Add tests
- Create
NewCommand.swiftinCommands/ - Add case in
main.swift - Add help text
- Add tests
- Correctness
- Tests coverage
- Performance implications
- API design
- Documentation
- Swift idioms
- Be constructive
- Explain reasoning
- Suggest alternatives
- Be respectful
- GitHub Issues for bugs/features
- GitHub Discussions for questions
- Code comments for clarification
- Be respectful and inclusive
- Welcome newcomers
- Focus on constructive feedback
- No harassment or discrimination
- Update version in
main.swift - Update CLAUDE.md
- Run full test suite
- Create git tag
- Build release binary
- Create GitHub release
By contributing, you agree that your contributions will be licensed under the same license as the project (MIT).
Thank you for contributing to MachScope!