Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
51 changes: 26 additions & 25 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ AI-powered Git commit message generator that analyzes your staged changes and ou
- Generates configurable number of commit message suggestions from your staged diff
- Generates 10 pull request titles based on the diff between the current branch and a target branch
- Providers: GitHub Copilot (default), OpenAI, Anthropic (Claude Code CLI)
- Multi-language support: English and Spanish
- Multi-language support: Any language (English, Arabic, Korean, etc.)
- Interactive config to pick provider/model/language and set keys
- Simple output suitable for piping into TUI menus (one message per line)

Expand Down Expand Up @@ -81,7 +81,6 @@ Contains API keys, tokens, and provider-specific settings. **Do not share this f

```yaml
active_provider: copilot # default if a GitHub token is found
language: en # commit message language: "en" (English) or "es" (Spanish)
providers:
copilot:
api_key: "$GITHUB_TOKEN" # Uses GitHub token; token is exchanged internally
Expand All @@ -94,29 +93,33 @@ providers:
anthropic:
model: "claude-haiku-4-5" # Uses Claude Code CLI - no API key needed
num_suggestions: 10 # Number of commit suggestions to generate
# Custom provider example (e.g., local Ollama):
# local:
# api_key: "not-needed"
# model: "llama3.1:8b"
# endpoint_url: "http://localhost:11434/v1"
```

#### Anthropic Provider (Claude Code CLI)
> [!NOTE]
> `.lazycommit.yaml: language` is removed and please use `.lazycommit.prompts.yaml` instead.

The Anthropic provider integrates with your local [Claude Code CLI](https://github.com/anthropics/claude-code) installation:
### 2. Prompt Configuration (`~/.config/.lazycommit.prompts.yaml`)
Contains prompt templates and message configurations. **Safe to share in dotfiles and Git.**

```yaml
language: English # commit message language (e.g., "English", "Arabic", "Korean")
system_message: "You are a helpful assistant that generates git commit messages, and pull request titles."
commit_message_template: "Based on the following git diff, generate 10 conventional commit messages. Each message should be on a new line, without any numbering or bullet points:\n\n%s"
pr_title_template: "Based on the following git diff, generate 10 pull request title suggestions. Each title should be on a new line, without any numbering or bullet points:\n\n%s"
```

- **No API key required**: Uses your existing Claude Code authentication
- **Fast and cost-effective**: Leverages Claude Haiku model
- **Configurable**: Set custom number of suggestions per provider
### Per-Repository Configuration

Requirements:
- Claude Code CLI installed and authenticated
- Command `claude` available in PATH
You can override the prompt configuration on a per-repository basis by creating a `.lazycommit.prompts.yaml` file in the root of your git repository. This is useful for projects that require different languages or commit message formats.

### 2. Prompt Configuration (`~/.config/.lazycommit.prompts.yaml`)
Contains prompt templates and message configurations. **Safe to share in dotfiles and Git.**
If a field is missing in your repository-local configuration, the value from the global configuration will be used.

This file is automatically created on first run with sensible defaults:
Example `.lazycommit.prompts.yaml` for a Korean project:
```yaml
language: Korean
commit_message_template: "Based on the following git diff, generate 5 conventional commit messages:\n\n%s"
```
This file is automatically created on first run in the global config directory with sensible defaults:

```yaml
system_message: "You are a helpful assistant that generates git commit messages, and pull request titles."
Expand Down Expand Up @@ -158,12 +161,14 @@ providers:

### Language Configuration

lazycommit supports generating commit messages in different languages. Set the `language` field in your config:
lazycommit supports generating commit messages in any language. Set the `language` field in your prompt config (`.lazycommit.prompts.yaml`):

```yaml
language: es # Spanish
language: Spanish
# or
language: Arabic
# or
language: en # English (default)
language: English # (default)
```

You can also configure it interactively:
Expand All @@ -174,10 +179,6 @@ lazycommit config set # Select language in the interactive menu

The language setting automatically instructs the AI to generate commit messages in the specified language, regardless of the provider used.

**Supported languages:**
- `en` - English (default)
- `es` - Spanish (Español)

## Integration with TUI Git clients

Because `lazycommit commit` prints plain lines, it plugs nicely into menu UIs.
Expand Down
39 changes: 28 additions & 11 deletions cmd/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -103,14 +103,19 @@ func runInteractiveConfig() {

// Language configuration
currentLanguage := config.GetLanguage()
languageOptions := []string{"English", "Spanish", "Other..."}
languagePrompt := &survey.Select{
Message: "Choose a language for commit messages:",
Options: []string{"English (en)", "Español (es)"},
Options: languageOptions,
Default: func() string {
if currentLanguage == "es" {
return "Español (es)"
switch currentLanguage {
case "Spanish":
return "Spanish"
case "English":
return "English"
default:
return "Other..."
}
return "English (en)"
}(),
}
var selectedLanguage string
Expand All @@ -120,19 +125,31 @@ func runInteractiveConfig() {
return
}

// Extract language code from selection
langCode := "en"
if selectedLanguage == "Español (es)" {
langCode = "es"
var langValue string
switch selectedLanguage {
case "Spanish":
langValue = "Spanish"
case "English":
langValue = "English"
case "Other...":
otherPrompt := &survey.Input{
Message: "Enter language name (e.g., 'Arabic', 'Korean', 'French'):",
Default: currentLanguage,
}
err = survey.AskOne(otherPrompt, &langValue)
if err != nil {
fmt.Println(err.Error())
return
}
}

if langCode != currentLanguage {
err := config.SetLanguage(langCode)
if langValue != "" && langValue != currentLanguage {
err := config.SetLanguage(langValue)
if err != nil {
fmt.Printf("Error setting language: %v\n", err)
return
}
fmt.Printf("Language set to: %s\n", langCode)
fmt.Printf("Language set to: %s\n", langValue)
}

// API key configuration - skip for copilot and anthropic
Expand Down
27 changes: 1 addition & 26 deletions internal/config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,6 @@ type ProviderConfig struct {
type Config struct {
Providers map[string]ProviderConfig `mapstructure:"providers"`
ActiveProvider string `mapstructure:"active_provider"`
Language string `mapstructure:"language"`
}

var cfg *Config
Expand All @@ -32,6 +31,7 @@ func InitConfig() {
viper.SetConfigName(".lazycommit")
viper.SetConfigType("yaml")
viper.AddConfigPath(getConfigDir())

viper.SetConfigFile(filepath.Join(getConfigDir(), ".lazycommit.yaml"))

if token, err := LoadGitHubToken(); err == nil && token != "" {
Expand All @@ -43,13 +43,8 @@ func InitConfig() {
viper.SetDefault("providers.openai.model", "openai/gpt-5-mini")
}

// Set defaults for anthropic provider
viper.SetDefault("providers.anthropic.model", "claude-haiku-4-5")
viper.SetDefault("providers.anthropic.num_suggestions", 10)

// Set default language
viper.SetDefault("language", "en")

viper.AutomaticEnv()

if err := viper.ReadInConfig(); err != nil {
Expand All @@ -73,7 +68,6 @@ func InitConfig() {
os.Exit(1)
}

// Initialize prompt configuration
InitPromptConfig()
}

Expand Down Expand Up @@ -290,25 +284,6 @@ func SetNumSuggestions(provider, numSuggestions string) error {
return viper.WriteConfig()
}

func GetLanguage() string {
if cfg == nil {
InitConfig()
}
if cfg.Language == "" {
return "en" // Default to English
}
return cfg.Language
}

func SetLanguage(language string) error {
if cfg == nil {
InitConfig()
}
cfg.Language = language
viper.Set("language", language)
return viper.WriteConfig()
}

func getConfigDir() string {
if xdgConfig := os.Getenv("XDG_CONFIG_HOME"); xdgConfig != "" {
return xdgConfig
Expand Down
Loading
Loading