Thank you for your interest in contributing to claude-mux! This document provides guidelines and instructions for contributing.
Be kind, respectful, and considerate to others. We're all here to make claude-mux better.
- Check if the issue already exists
- Include steps to reproduce the issue
- Include your OS, Go version, and claude-mux version
- Include any relevant error messages or logs
- Open an issue with the "enhancement" label
- Describe the use case and why it would be valuable
- Be open to discussion and alternative approaches
-
Fork the repository and create your branch from
main -
Set up your development environment:
git clone https://github.com/enriikke/claude-mux.git cd claude-mux make dev-deps # Install development dependencies
-
Make your changes:
- Write clear, concise commit messages
- Add tests for new functionality
- Update documentation as needed
- Follow the existing code style
-
Ensure quality:
make check # Runs fmt, vet, lint, security, and tests -
Submit your PR:
- Provide a clear description of the changes
- Reference any related issues
- Be responsive to feedback
claude-mux/
├── cmd/claude-mux/ # CLI entry point
├── internal/ # Private packages
│ ├── git/ # Git operations
│ ├── worktree/ # Worktree management
│ └── config/ # Configuration
└── pkg/ # Public packages (future)
# Install dev dependencies
make dev-deps
# Build the binary
make build
# Run tests
make test
# Run linter
make lint
# Format code
make fmt
# Run security scan
make security
# Run all checks
make check
# Test release process
make release-dry- Write unit tests for new functions
- Use table-driven tests where appropriate
- Mock external dependencies (git commands)
- Aim for >80% code coverage
Example test:
func TestFeature(t *testing.Testimport os.Args) {
tests := []struct {
name string
input string
want string
wantErr bool
}{
{"valid input", "test", "expected", false},
{"invalid input", "", "", true},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
got, err := Feature(tt.input)
if (err != nil) != tt.wantErr {
t.Errorf("Feature() error = %v, wantErr %v", err, tt.wantErr)
}
if got != tt.want {
t.Errorf("Feature() = %v, want %v", got, tt.want)
}
})
}
}- Use
goimportsfor formatting (viamake fmt) - Follow Effective Go
- Keep functions small and focused
- Use meaningful variable and function names
- Add comments for exported functions
- Handle errors explicitly
Follow conventional commits format:
type: subject
body (optional)
footer (optional)
Types:
feat:New featurefix:Bug fixdocs:Documentation changestest:Test changesrefactor:Code refactoringchore:Build/tooling changes
Example:
feat: add session persistence
Implement basic session management to allow switching between
active Claude sessions without losing state.
Closes #42
Releases are automated via GitHub Actions when a tag is pushed:
- Ensure all tests pass on
main - Update version if needed
- Create and push a tag:
git tag v0.2.0 git push origin v0.2.0
- GitHub Actions will create the release with binaries
- Open an issue for bugs or feature requests
- Join discussions in existing issues
- Check the README for usage information
By contributing, you agree that your contributions will be licensed under the MIT License.