Thank you for considering contributing to claude-code-sync! This document outlines the contribution process and guidelines.
- Code of Conduct
- How Can I Contribute?
- Development Setup
- Submitting Changes
- Coding Guidelines
- Testing
- Documentation
- Release Process
This project adheres to a code of conduct based on the Contributor Covenant. By participating, you are expected to uphold this code. Please report unacceptable behavior to the project maintainers.
In short:
- Be respectful and inclusive
- Provide constructive feedback
- Focus on what is best for the community
- Show empathy towards other community members
Before creating a bug report, please check the existing issues to avoid duplicates.
When filing a bug report, include:
- Clear title describing the issue
- Steps to reproduce the behavior
- Expected behavior vs actual behavior
- Environment details:
- OS (Windows/macOS/Linux)
- Version of
claude-code-sync(claude-code-sync version) - Git version (
git --version)
- Logs (run with
--verboseif available) - Screenshots if applicable
Enhancement suggestions are welcome! Before submitting:
- Check if the feature already exists or is planned
- Search existing issues for similar requests
When suggesting an enhancement, include:
- Clear title summarizing the feature
- Use case - Why is this feature needed?
- Proposed solution - How should it work?
- Alternatives considered - Other ways to achieve the goal
- Additional context - Examples, mockups, etc.
Documentation improvements are highly appreciated! You can:
- Fix typos or unclear wording
- Add examples
- Improve clarity
- Translate documentation (future)
- Add missing information
See Development Setup and Submitting Changes below.
- Go 1.21+ (download)
- Git 2.0+
- age (for testing encryption) -
brew install ageor download from releases
git clone https://github.com/felixisaac/claude-code-sync.git
cd claude-code-syncgo mod download# Build for your current platform
go build -o claude-code-sync ./cmd/claude-code-sync/
# Or use the Makefile (if available)
make build./claude-code-sync --helpgo build -ldflags="-X main.version=dev" -o claude-code-sync ./cmd/claude-code-sync/- Fork the repository
- Create a branch from
main:git checkout -b feature/your-feature-name # or git checkout -b fix/your-bug-fix - Make your changes
- Test your changes (see Testing)
- Commit with clear messages (see Commit Messages)
- Push to your fork:
git push origin feature/your-feature-name
- Open a Pull Request to the
mainbranch
Before submitting:
- Code follows the Coding Guidelines
- All tests pass (
go test ./...) - Added tests for new functionality
- Updated documentation (README, code comments)
- Ran
go fmtandgo vet - Checked for compiler warnings
- Tested on your platform (mention in PR description)
PR Description should include:
- What does this PR do?
- Why is this change needed?
- How does it work?
- Testing - How did you test this?
- Screenshots (if UI changes)
- Related issues - Closes #123
Follow Conventional Commits:
<type>: <description>
[optional body]
[optional footer]
Types:
feat:New featurefix:Bug fixdocs:Documentation changesrefactor:Code refactoring (no behavior change)test:Adding or updating testschore:Build process, tooling, dependencies
Examples:
feat: add custom encryption patterns in config
Allow users to specify custom patterns for encryption
in ~/.claude-sync/config.yaml
Closes #45
fix: handle unrelated histories in git pull
Automatically retry with --allow-unrelated-histories
when pulling fails due to divergent branches
Fixes #67
- Follow Effective Go
- Use
gofmtfor formatting (orgoimports) - Run
go vetto catch common issues - Keep functions small and focused
- Prefer clarity over cleverness
claude-code-sync/
├── cmd/claude-code-sync/ # Main entry point
│ └── main.go
├── internal/ # Internal packages (not importable)
│ ├── cmd/ # Cobra commands
│ │ ├── root.go
│ │ ├── init.go
│ │ ├── push.go
│ │ └── pull.go
│ ├── config/ # Configuration logic
│ ├── crypto/ # Encryption/decryption
│ ├── git/ # Git operations
│ └── sync/ # Sync logic
├── .github/ # GitHub Actions
└── README.md
- Return errors, don't panic (except in
main) - Wrap errors with context:
fmt.Errorf("failed to encrypt: %w", err) - Use descriptive error messages
Good:
if err != nil {
return fmt.Errorf("failed to read file %s: %w", path, err)
}Bad:
if err != nil {
return err // Lost context
}Use the logInfo, logSuccess, logWarn, logError helpers:
logInfo("Initializing sync...")
logSuccess("Push complete!")
logWarn("Key already exists")
logError("Failed to connect to repo")- Write comments for exported functions/types (godoc format)
- Explain why, not what (code should be self-explanatory)
- Keep comments up-to-date
Good:
// ShouldEncrypt returns true if the file should be encrypted
// based on the configured encryption patterns.
func (c *Config) ShouldEncrypt(path string) bool {Bad:
// This function checks if file should be encrypted
func (c *Config) ShouldEncrypt(path string) bool {# Run all tests
go test ./...
# Run tests with coverage
go test -cover ./...
# Run tests verbosely
go test -v ./...
# Run specific test
go test -run TestShouldEncrypt ./internal/config/- Place tests in
*_test.gofiles next to the code - Use table-driven tests for multiple cases
- Mock external dependencies (git, filesystem)
Example:
func TestShouldEncrypt(t *testing.T) {
tests := []struct {
name string
path string
expected bool
}{
{"settings.json", "settings.json", true},
{"CLAUDE.md", "CLAUDE.md", false},
{"skill resource", "skills/pdf/resources/key.txt", true},
}
cfg := &Config{EncryptPatterns: DefaultEncryptPatterns}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
got := cfg.ShouldEncrypt(tt.path)
if got != tt.expected {
t.Errorf("ShouldEncrypt(%q) = %v, want %v", tt.path, got, tt.expected)
}
})
}
}Test with a real git repo (use temp directories):
func TestPushPull(t *testing.T) {
// Create temp directories
tmpDir := t.TempDir()
// ... test push/pull flow
}The README should be:
- Comprehensive yet scannable
- Include quickstart examples
- Explain all concepts clearly
- Link to relevant external docs
When making changes:
- Update relevant sections
- Keep table of contents in sync
- Add examples for new features
- Document exported functions, types, constants
- Use godoc format
- Include examples in comments when helpful
- Explain non-obvious code
- Document workarounds or edge cases
- Clarify intent when code might be confusing
Note: This section is for maintainers.
We use Semantic Versioning:
MAJOR.MINOR.PATCHMAJOR: Breaking changesMINOR: New features (backward-compatible)PATCH: Bug fixes
- Update version in relevant places (if not automated)
- Update CHANGELOG (or generate from commits)
- Create git tag:
git tag -a v0.3.0 -m "Release v0.3.0" git push origin v0.3.0 - GitHub Actions automatically:
- Builds binaries for all platforms
- Creates GitHub release
- Updates Homebrew tap
- Updates Scoop bucket
# Install goreleaser
go install github.com/goreleaser/goreleaser@latest
# Run release (dry-run)
goreleaser release --snapshot --clean
# Run actual release
export GITHUB_TOKEN=your_token
goreleaser release --cleanIf you have questions:
- Check existing issues and discussions
- Open a new discussion
- Reach out to maintainers
By contributing, you agree that your contributions will be licensed under the MIT License.
Thank you for contributing to claude-code-sync! 🎉