From 3b0fc91ef777001e2260d727e6d84ed203391b07 Mon Sep 17 00:00:00 2001 From: Lucas Garron Date: Tue, 16 Jun 2026 15:48:57 -0700 Subject: [PATCH 1/3] Default to ~/.config/gmailctl for newly created config dirs. This is a minimal fix for https://github.com/mbrt/gmailctl/issues/144 It is a revision of https://github.com/mbrt/gmailctl/pull/393 and uses a library for the internal XDG path calculation per feedback there. --- README.md | 22 +++++++++++++++++----- cmd/gmailctl/cmd/root_cmd.go | 11 +++++++++-- go.mod | 1 + go.sum | 2 ++ 4 files changed, 29 insertions(+), 7 deletions(-) diff --git a/README.md b/README.md index 6a3e432c..43d47c57 100644 --- a/README.md +++ b/README.md @@ -13,6 +13,7 @@ label, archive and manage your inbox automatically. - [Motivation](#motivation) - [Install](#install) - [Usage](#usage) + - [Config directory](#config-directory) - [Migrate from another solution](#migrate-from-another-solution) - [Other commands](#other-commands) - [Configuration](#configuration) @@ -136,10 +137,10 @@ settings without leaving your command line. [![asciicast](https://asciinema.org/a/1NIWhzeJNcrN7cCe7mGjWQQnx.svg)](https://asciinema.org/a/1NIWhzeJNcrN7cCe7mGjWQQnx) The easiest way to use gmailctl is to run `gmailctl edit`. This will open the -local `.gmailctl/config.jsonnet` file in your editor. After you exit the editor -the configuration is applied to Gmail. See [Configuration](#configuration) for -the configuration file format. This is the preferred way if you want to start -your filters from scratch. +local config file in your editor. After you exit +the editor the configuration is applied to Gmail. See +[Configuration](#configuration) for the configuration file format. This is the +preferred way if you want to start your filters from scratch. **NOTE:** It's recommended to backup your current configuration before you apply the generated one for the first time. Your current filters will be wiped and @@ -147,6 +148,16 @@ replaced with the ones specified in the config file. The diff you'll get during the first run will probably be pretty big, but from that point on, all changes should generate a small and simple to review diff. +### Config directory + +Configuration and credentials are in a shared directory, either in a default orq +custom location. + +- `~/.config/gmailctl` — This is the current default location. +- `~/.gmailctl` — This was the previous default location. `gmailctl` will continue + to use this location if it exists on your device. +- Custom location: use the `--config` argument. + ### Migrate from another solution If you want to preserve your current filters and migrate to a more sane @@ -164,7 +175,8 @@ Example of usage: ```bash # download the filters to the default configuration file -gmailctl download > ~/.gmailctl/config.jsonnet +mkdir -p ~/.config/gmailctl +gmailctl download > ~/.config/gmailctl/config.jsonnet # check that the diff is empty and no errors are present gmailctl diff # happy editing! diff --git a/cmd/gmailctl/cmd/root_cmd.go b/cmd/gmailctl/cmd/root_cmd.go index 97360e5d..9b46e866 100644 --- a/cmd/gmailctl/cmd/root_cmd.go +++ b/cmd/gmailctl/cmd/root_cmd.go @@ -6,6 +6,7 @@ import ( "os/user" "path" + "github.com/adrg/xdg" "github.com/mattn/go-isatty" "github.com/spf13/cobra" ) @@ -53,7 +54,7 @@ func init() { // Here you will define your flags and configuration settings. // Cobra supports persistent flags, which, if defined here, // will be global for your application. - rootCmd.PersistentFlags().StringVar(&cfgDir, "config", "", "config directory (default is $HOME/.gmailctl)") + rootCmd.PersistentFlags().StringVar(&cfgDir, "config", "", "config directory (defaults to legacy path $HOME/.gmailctl if it exists, else $HOME/.config/gmailctl)") rootCmd.PersistentFlags().StringVar(&colorFlag, "color", "auto", "whether to enable color output ('always', 'auto' or 'never')") rootCmd.PersistentFlags().Lookup("color").NoOptDefVal = "always" @@ -71,7 +72,13 @@ func initConfig() { fmt.Println(err) os.Exit(1) } - cfgDir = path.Join(usr.HomeDir, ".gmailctl") + + legacyCfgDir := path.Join(usr.HomeDir, ".gmailctl") + if _, err := os.Stat(legacyCfgDir); err != nil && os.IsNotExist(err) { + cfgDir = path.Join(xdg.ConfigHome, "gmailctl") + } else { + cfgDir = legacyCfgDir + } } // shouldUseColorDiff decides, based on the value of the color flag and other diff --git a/go.mod b/go.mod index 4f16a419..6b57fbb0 100644 --- a/go.mod +++ b/go.mod @@ -5,6 +5,7 @@ go 1.25.0 toolchain go1.26.1 require ( + github.com/adrg/xdg v0.5.3 github.com/fatih/color v1.18.1-0.20251010072730-26fd5780133d github.com/google/go-jsonnet v0.21.0 github.com/gorilla/mux v1.8.1 diff --git a/go.sum b/go.sum index b8623d94..a6f83d19 100644 --- a/go.sum +++ b/go.sum @@ -4,6 +4,8 @@ cloud.google.com/go/auth/oauth2adapt v0.2.8 h1:keo8NaayQZ6wimpNSmW5OPc283g65QNIi cloud.google.com/go/auth/oauth2adapt v0.2.8/go.mod h1:XQ9y31RkqZCcwJWNSx2Xvric3RrU88hAYYbjDWYDL+c= cloud.google.com/go/compute/metadata v0.9.0 h1:pDUj4QMoPejqq20dK0Pg2N4yG9zIkYGdBtwLoEkH9Zs= cloud.google.com/go/compute/metadata v0.9.0/go.mod h1:E0bWwX5wTnLPedCKqk3pJmVgCBSM6qQI1yTBdEb3C10= +github.com/adrg/xdg v0.5.3 h1:xRnxJXne7+oWDatRhR1JLnvuccuIeCoBu2rtuLqQB78= +github.com/adrg/xdg v0.5.3/go.mod h1:nlTsY+NNiCBGCK2tpm09vRqfVzrc2fLmXGpBLF0zlTQ= github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs= github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/cpuguy83/go-md2man/v2 v2.0.6/go.mod h1:oOW0eioCTA6cOiMLiUPZOpcVxMig6NIQQ7OS05n1F4g= From 2f01d102d06c0a555503d7189a294a113b67f621 Mon Sep 17 00:00:00 2001 From: Lucas Garron Date: Wed, 17 Jun 2026 12:02:11 -0700 Subject: [PATCH 2/3] Update cmd/gmailctl/cmd/root_cmd.go Co-authored-by: Michele Bertasi <405934+mbrt@users.noreply.github.com> --- cmd/gmailctl/cmd/root_cmd.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmd/gmailctl/cmd/root_cmd.go b/cmd/gmailctl/cmd/root_cmd.go index 9b46e866..90668089 100644 --- a/cmd/gmailctl/cmd/root_cmd.go +++ b/cmd/gmailctl/cmd/root_cmd.go @@ -54,7 +54,7 @@ func init() { // Here you will define your flags and configuration settings. // Cobra supports persistent flags, which, if defined here, // will be global for your application. - rootCmd.PersistentFlags().StringVar(&cfgDir, "config", "", "config directory (defaults to legacy path $HOME/.gmailctl if it exists, else $HOME/.config/gmailctl)") + rootCmd.PersistentFlags().StringVar(&cfgDir, "config", "", "config directory (defaults to $HOME/.gmailctl if it exists, else $HOME/.config/gmailctl)") rootCmd.PersistentFlags().StringVar(&colorFlag, "color", "auto", "whether to enable color output ('always', 'auto' or 'never')") rootCmd.PersistentFlags().Lookup("color").NoOptDefVal = "always" From 05bc582488604931418a4dba8cb8956123f75643 Mon Sep 17 00:00:00 2001 From: Michele Bertasi <405934+mbrt@users.noreply.github.com> Date: Fri, 19 Jun 2026 08:23:06 +0200 Subject: [PATCH 3/3] Update README.md --- README.md | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index 43d47c57..fb66e538 100644 --- a/README.md +++ b/README.md @@ -150,14 +150,11 @@ should generate a small and simple to review diff. ### Config directory -Configuration and credentials are in a shared directory, either in a default orq -custom location. +Configuration and credentials are in either: -- `~/.config/gmailctl` — This is the current default location. -- `~/.gmailctl` — This was the previous default location. `gmailctl` will continue - to use this location if it exists on your device. +- `/gmailctl` (using the [XDG base directory spec](https://specifications.freedesktop.org/basedir-spec/basedir-spec-latest.html), commonly `~/.config/gmailctl` on Linux. +- `~/.gmailctl`: The previous default location. If the directory exists `gmailctl` will continue to use it for backward compatibility - Custom location: use the `--config` argument. - ### Migrate from another solution If you want to preserve your current filters and migrate to a more sane