Contributing
Getting Started
- Fork and clone the repository:
git clone https://github.com/YOUR_USERNAME/grepai.gitcd grepai- Install dependencies:
go mod download- Run tests:
make test- Build:
make buildDevelopment Commands
# Build the binarymake build
# Run tests with race detectionmake test
# Run tests with coveragemake test-cover
# Format code with gofmtmake fmt
# Lint with golangci-lintmake lint
# Run ALL checks before committing (recommended)make pre-commit
# Build and runmake run
# Cross-compile for all platformsmake build-all
# Generate CLI documentationmake docs-generateBefore Committing
Always run the pre-commit checks before pushing your changes:
make pre-commitThis single command will:
- Format all Go files with
gofmt - Vet - detect common errors with
go vet - Lint - run comprehensive checks with
golangci-lint - Test - run all tests with race detection
If all checks pass, you’re ready to commit!
Project Structure
grepai/├── cli/ # CLI commands (Cobra)│ ├── root.go│ ├── init.go│ ├── watch.go│ ├── search.go│ └── status.go├── config/ # Configuration loading├── embedder/ # Embedding providers│ ├── embedder.go # Interface│ ├── ollama.go│ └── openai.go├── store/ # Vector storage│ ├── store.go # Interface│ ├── gob.go│ └── postgres.go├── indexer/ # Indexing logic│ ├── scanner.go # File walking│ ├── chunker.go # Text splitting│ └── indexer.go # Orchestration├── search/ # Search logic├── watcher/ # File watching└── docs/ # Documentation (Astro/Starlight)Adding a New Embedder
- Create a new file in
embedder/:
package embedder
type MyEmbedder struct { // ...}
func NewMyEmbedder(config Config) (*MyEmbedder, error) { // ...}
func (e *MyEmbedder) Embed(ctx context.Context, text string) ([]float32, error) { // ...}
func (e *MyEmbedder) EmbedBatch(ctx context.Context, texts []string) ([][]float32, error) { // ...}
func (e *MyEmbedder) Dimensions() int { return 768 // or whatever your embedder produces}-
Add configuration in
config/config.go -
Wire it up in CLI commands
Adding a New Store
- Create a new file in
store/:
package store
type MyStore struct { // ...}
func NewMyStore(config Config) (*MyStore, error) { // ...}
func (s *MyStore) Store(ctx context.Context, chunks []Chunk) error { // ...}
func (s *MyStore) Search(ctx context.Context, embedding []float32, limit int) ([]Result, error) { // ...}
func (s *MyStore) Delete(ctx context.Context, filePath string) error { // ...}
func (s *MyStore) Close() error { // ...}-
Add configuration in
config/config.go -
Wire it up in CLI commands
Commit Convention
Follow conventional commits:
type(scope): description
Types: feat, fix, docs, style, refactor, test, choreExamples:
feat(embedder): add support for Cohere embeddingsfix(watcher): handle symlink loops gracefullydocs(readme): update installation instructionsPull Request Process
- Create a feature branch:
git checkout -b feat/my-feature-
Make your changes and commit
-
Run pre-commit checks:
make pre-commit- Push and create a PR:
git push origin feat/my-feature- Fill out the PR template
Code Style
- Follow standard Go conventions
- Run
make lintbefore committing - Keep functions focused and small
- Add tests for new functionality
- Document exported types and functions