Thank you for your interest in contributing to MLX-Go! This document provides guidelines and instructions for contributing to the project.
This project follows the Contributor Covenant Code of Conduct. By participating, you are expected to uphold this code.
- Go 1.25 or later
- CMake 3.24 or later
- g++ or clang++
- Xcode Command Line Tools on macOS
- Git with submodule support
-
Fork the repository on GitHub
-
Clone your fork with submodules:
git clone --recursive https://github.com/YOUR_USERNAME/mlx_go cd mlx_go -
Add the upstream remote:
git remote add upstream https://github.com/guptaaryan16/mlx_go
-
Build contributor-local MLX dependencies:
./scripts/build_local.sh
-
Verify the contributor build:
go test -v -tags mlx_vendor ./core go test -v -tags mlx_vendor ./nn
If you are only changing Go code and want to test the default install mode,
install the native MLX libraries once with the release installer or
./scripts/install.sh, then run the normal go test ./... workflow.
Always create a new branch for your changes:
git checkout -b feature/your-feature-nameUse descriptive branch names:
feature/add-conv2d— New featuresfix/memory-leak-indexing— Bug fixesdocs/improve-readme— Documentation improvementsperf/optimize-matmul— Performance improvements
- Write clean, idiomatic Go code
- Follow the existing code style
- Add tests for new functionality
- Update documentation as needed
Run unit tests:
go test -v ./...Run specific package tests:
go test -v ./core
go test -v ./nnRun benchmarks:
go test -bench=. -benchtime=5s ./coreCheck test coverage:
go test -coverprofile=coverage.out ./...
go tool cover -html=coverage.outFormat your code:
gofmt -w .Run go vet:
go vet ./...Run golangci-lint (if installed):
golangci-lint runWrite clear, descriptive commit messages:
Add Conv2d layer implementation
- Implement Conv2d wrapper around MLX C API
- Add comprehensive tests for various kernel sizes
- Update documentation with usage examples
Closes #42
Commit message guidelines:
- Use present tense ("Add feature" not "Added feature")
- First line should be a concise summary (50 chars or less)
- Add detailed description after a blank line if needed
- Reference relevant issues (e.g., "Closes #42", "Fixes #123")
git push origin feature/your-feature-nameThen create a pull request on GitHub with:
- Clear title describing the change
- Description of what changed and why
- Reference to related issues
- Screenshots/benchmarks if relevant
- Follow the Effective Go guidelines
- Use
gofmtfor formatting - Use meaningful variable and function names
- Add comments for exported functions following godoc conventions
All exported functions should have documentation comments:
// MatMul performs matrix multiplication of two arrays.
//
// The function follows NumPy broadcasting rules. The last two dimensions
// are treated as matrices and multiplied. All other dimensions are broadcast.
//
// Example:
// a := mx.RandomUniform(0, 1, []int32{10, 20}, mx.Float32)
// b := mx.RandomUniform(0, 1, []int32{20, 30}, mx.Float32)
// c := mx.MatMul(a, b) // Shape: [10, 30]
//
// Options:
// - WithStream: Specify computation stream
// - WithDevice: Override default device
func MatMul(a, b Array, opts ...Option) Array {
// implementation
}- Write table-driven tests where appropriate
- Test edge cases and error conditions
- Use descriptive test names:
TestMatMul_BroadcastShapes - Add benchmarks for performance-critical code
Example test:
func TestTranspose(t *testing.T) {
tests := []struct {
name string
shape []int32
expected []int32
}{
{"2D", []int32{3, 4}, []int32{4, 3}},
{"3D", []int32{2, 3, 4}, []int32{4, 3, 2}},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
arr := mx.Ones(tt.shape, mx.Float32)
result := mx.Transpose(arr)
if !reflect.DeepEqual(result.Shape(), tt.expected) {
t.Errorf("got %v, want %v", result.Shape(), tt.expected)
}
})
}
}- Bug fixes — Especially memory leaks or crashes
- Performance improvements — Benchmarks and optimizations
- Documentation — Examples, guides, API docs
- Tests — Improve coverage, add edge cases
- Core features — Training support, quantization, model implementations
- New operations — Additional MLX operations not yet wrapped
- Utility functions — Helper functions for common tasks
- Examples — Real-world use cases and demos
- Benchmarks — Performance comparisons vs other frameworks
- Feature proposals — Open an issue to discuss before implementing
- API improvements — Suggestions for better ergonomics
- Performance ideas — Profiling results and optimization proposals
- Ensure all tests pass locally before submitting
- Update documentation for any API changes
- Add tests for new functionality
- Keep PRs focused — One feature/fix per PR
- Respond to feedback — Address review comments promptly
- Squash commits if requested before merging
Your PR will be reviewed for:
- Correctness — Does it work as intended?
- Tests — Is new code adequately tested?
- Performance — Does it maintain or improve performance?
- Code quality — Is it readable and maintainable?
- Documentation — Are changes documented?
- Compatibility — Does it break existing APIs?
Include:
- MLX-Go version (commit hash)
- Go version (
go version) - macOS version and chip (M1/M2/M3/M4)
- Minimal code to reproduce the issue
- Expected vs actual behavior
- Error messages and stack traces
Include:
- Clear use case and motivation
- Proposed API (if applicable)
- Alternatives considered
- Willingness to contribute implementation
- General questions — Open a GitHub Discussion
- Bug reports — Open an Issue
- Security issues — Email the maintainers directly
By contributing, you agree that your contributions will be licensed under the project's MIT License.
Thank you for helping make MLX-Go better! 🚀