Skip to content
Open
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
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ Matcha has a built-in plugin system with 35+ community plugins. Browse and insta
matcha marketplace # browse plugins in the TUI
matcha install <url_or_file> # install a plugin
matcha config <plugin_name> # configure an installed plugin
matcha config path # print the config file location
```

Anyone can submit their own plugin — just add an entry to `plugins/registry.json` and open a PR. [Learn more](https://docs.matcha.email/Features/Plugins#submit-your-plugin)
Expand Down
12 changes: 12 additions & 0 deletions cli/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,22 @@ import (
"os"
"os/exec"
"path/filepath"

"github.com/floatpane/matcha/config"
)

// RunConfig handles `matcha config [plugin_name]`.
func RunConfig(args []string) error {
// `matcha config path` prints the resolved config file location and exits.
if len(args) == 1 && args[0] == "path" {
path, err := config.GetConfigFile()
if err != nil {
return fmt.Errorf("cannot resolve config path: %w", err)
}
fmt.Println(path)
return nil
}

editor := os.Getenv("EDITOR")
if editor == "" {
editor = "vi"
Expand Down
46 changes: 46 additions & 0 deletions cli/config_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
package cli

import (
"io"
"os"
"path/filepath"
"strings"
"testing"

"github.com/floatpane/matcha/config"
)

func TestRunConfigPath(t *testing.T) {
tempDir := t.TempDir()
t.Setenv("HOME", tempDir)

want, err := config.GetConfigFile()
if err != nil {
t.Fatalf("GetConfigFile failed: %v", err)
}

orig := os.Stdout
r, w, err := os.Pipe()
if err != nil {
t.Fatalf("pipe failed: %v", err)
}
os.Stdout = w

runErr := RunConfig([]string{"path"})

w.Close()
os.Stdout = orig
out, _ := io.ReadAll(r)

if runErr != nil {
t.Fatalf("RunConfig(path) returned error: %v", runErr)
}

got := strings.TrimSpace(string(out))
if got != want {
t.Errorf("RunConfig(path) printed %q, want %q", got, want)
}
if filepath.Base(got) != "config.json" {
t.Errorf("printed path %q does not end in config.json", got)
}
}
5 changes: 5 additions & 0 deletions config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -392,6 +392,11 @@ func GetConfigDir() (string, error) {
return configDir()
}

// GetConfigFile returns the full path to the configuration file (exported).
func GetConfigFile() (string, error) {
return configFile()
}

// configDir returns the path to the configuration directory (internal).
func configDir() (string, error) {
home, err := os.UserHomeDir()
Expand Down
28 changes: 28 additions & 0 deletions config/config_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -725,3 +725,31 @@ func TestResolvePassword(t *testing.T) {
}
})
}

// TestGetConfigFile verifies the resolved config file path is built from the
// config directory and ends at config.json.
func TestGetConfigFile(t *testing.T) {
tempDir := t.TempDir()
t.Setenv("HOME", tempDir)
// os.UserHomeDir() reads USERPROFILE on Windows, so set it too or the
// override is ignored and the resolved path points at the real home.
t.Setenv("USERPROFILE", tempDir)

got, err := GetConfigFile()
if err != nil {
t.Fatalf("GetConfigFile failed: %v", err)
}

want := filepath.Join(tempDir, ".config", "matcha", "config.json")
if got != want {
t.Errorf("GetConfigFile() = %q, want %q", got, want)
}

dir, err := GetConfigDir()
if err != nil {
t.Fatalf("GetConfigDir failed: %v", err)
}
if filepath.Dir(got) != dir {
t.Errorf("config file %q is not inside config dir %q", got, dir)
}
}
8 changes: 8 additions & 0 deletions docs/docs/Features/CLI.md
Original file line number Diff line number Diff line change
Expand Up @@ -240,6 +240,14 @@ matcha config ai_rewrite

Opens `~/.config/matcha/plugins/ai_rewrite.lua` so you can edit settings like API keys or model names.

**Print the config file location:**

```bash
matcha config path
```

Prints the resolved path to `config.json` and exits without opening an editor. Useful in scripts or when you just need to know where Matcha keeps its configuration.

## matcha update

Check for and install the latest version of Matcha.
Expand Down
Loading