Repository: mgechev/revive

Issue:
var-naming: allow disabling flags on common initial
** Is your feature request related to a problem? Please describe. **

I introduced revive as part of my golangci-lint setup to enforce variable naming conventions. However, revive automatically enforces capitalization of common acronyms (like ID, JSON, HTTP) in variable and function names. For example, it insists on getJSON instead of getJson. This strict enforcement causes friction for some projects or teams that prefer to allow lowercase acronyms such as getJson or userId.

Currently, the only way to disable this acronym enforcement is by running revive standalone with a custom revive.toml config, which is not supported when using revive through golangci-lint. This limits flexibility and forces teams either to accept these acronym rules or run revive separately.

 ** Describe the solution you'd like ** 

Please add a configuration option to the var-naming rule—such as disableAcronymEnforcement—that allows users to disable or customize the acronym capitalization checks directly from the YAML config (including when used via golangci-lint). This would:

1. Allow users to disable acronym enforcement while still benefiting from other naming checks.

2. Enable customization of which acronyms are enforced or ignored.

3. Improve revive’s usability and adoption in environments with different naming preferences.

** Describe alternatives you've considered **

1. Running revive standalone with a revive.toml file to disable acronym enforcement, but this is cumbersome and incompatible with golangci-lint.

2. Manually renaming variables to comply with the enforced acronyms, which is not always feasible or desirable, and even native Go itself doesn’t always follow these rules.

3. Trying to align the list of acronyms in my config with revive’s internal list is not feasible.

Discussion:
@alexandear: Thanks for the detailed request!

Just to clarify: it is possible to configure the `revive.var-naming` rule to accept lowercase acronyms like `Id`, `Http`, and `Json` when using `revive` through `golangci-lint`. You can do this by customizing the allow list in your `.golangci.yml` like so:

```yaml
linters:
  settings:
    revive:
      rules:
        - name: var-naming
          arguments:
            - ["ID", "JSON", "HTTP"]
```

Let me know if you run into issues with this approach—happy to help further if needed!

See https://github.com/golangci/golangci-lint/blob/b0c55d28660363573984e9e76214d2136973963b/.golangci.reference.yml#L2744@krenzler: Thanks for the response.

I'm aware that it's possible to specify initials manually, but in the project I’m working on, we use a large number of common acronyms—including all the ones your project currently recognizes, and quite a few others that are likely to be added in future versions.

That’s why I believe adding the configuration option I suggested earlier could be really helpful. It would make the linter more flexible, allowing teams to flag only the relevant issues without too much overhead.

Let me know what you think—and I’d be happy to help if there’s anything I can contribute :)@alexandear: Got it.

Your use case makes sense, and adding a configuration option like `disable-acronym-enforcement` (or similar) sounds like a reasonable enhancement.

We’d definitely welcome a contribution if you're interested in implementing this! Feel free to open a PR.

Thanks again for the thoughtful suggestion!

Solution patch:
diff --git a/RULES_DESCRIPTIONS.md b/RULES_DESCRIPTIONS.md
index 813b718..99c4125 100644
--- a/RULES_DESCRIPTIONS.md
+++ b/RULES_DESCRIPTIONS.md
@@ -1363,6 +1363,9 @@ It ignores functions starting with `Example`, `Test`, `Benchmark`, and `Fuzz` in
 _Configuration_: This rule accepts two slices of strings and one optional slice containing a single map with named parameters.
 (This is because TOML does not support "slice of any," and we maintain backward compatibility with the previous configuration version).
 The first slice is an allowlist, and the second one is a blocklist of initialisms.
+You can add a boolean parameter `skipInitialismNameChecks` (`skipinitialismnamechecks` or `skip-initialism-name-checks`) to control how names
+of functions, variables, consts, and structs handle known initialisms (e.g., JSON, HTTP, etc.) when written in `camelCase`.
+When `skipInitialismNameChecks` is set to true, the rule allows names like `readJson`, `HttpMethod` etc.
 In the map, you can add a boolean `upperCaseConst` (`uppercaseconst`, `upper-case-const`) parameter to allow `UPPER_CASE` for `const`.
 You can also add a boolean `skipPackageNameChecks` (`skippackagenamechecks`, `skip-package-name-checks`) to skip package name checks.
 When `skipPackageNameChecks` is false (the default), you can configure `extraBadPackageNames` (`extrabadpackagenames`, `extra-bad-package-names`)
@@ -1373,6 +1376,11 @@ By default, the rule behaves exactly as the alternative in `golint` but optional
 
 Examples:
 
+```toml
+[rule.var-naming]
+arguments = [[], [], [{ skipInitialismNameChecks = true }]]
+```
+
 ```toml
 [rule.var-naming]
 arguments = [["ID"], ["VM"], [{ upperCaseConst = true }]]
@@ -1388,6 +1396,11 @@ arguments = [[], [], [{ skipPackageNameChecks = true }]]
 arguments = [[], [], [{ extraBadPackageNames = ["helpers", "models"] }]]
 ```
 
+```toml
+[rule.var-naming]
+arguments = [[], [], [{ skip-initialism-name-checks = true }]]
+```
+
 ```toml
 [rule.var-naming]
 arguments = [["ID"], ["VM"], [{ upper-case-const = true }]]
diff --git a/internal/rule/name.go b/internal/rule/name.go
new file mode 100644
index 0000000..6025767
--- /dev/null
+++ b/internal/rule/name.go
@@ -0,0 +1,135 @@
+// Package rule defines utility functions some revive rules can share.
+package rule
+
+import (
+	"strings"
+	"unicode"
+)
+
+// commonInitialisms is a set of common initialisms.
+// Only add entries that are highly unlikely to be non-initialisms.
+// For instance, "ID" is fine (Freudian code is rare), but "AND" is not.
+var commonInitialisms = map[string]bool{
+	"ACL":   true,
+	"API":   true,
+	"ASCII": true,
+	"CPU":   true,
+	"CSS":   true,
+	"DNS":   true,
+	"EOF":   true,
+	"GUID":  true,
+	"HTML":  true,
+	"HTTP":  true,
+	"HTTPS": true,
+	"ID":    true,
+	"IDS":   true,
+	"IP":    true,
+	"JSON":  true,
+	"LHS":   true,
+	"QPS":   true,
+	"RAM":   true,
+	"RHS":   true,
+	"RPC":   true,
+	"SLA":   true,
+	"SMTP":  true,
+	"SQL":   true,
+	"SSH":   true,
+	"TCP":   true,
+	"TLS":   true,
+	"TTL":   true,
+	"UDP":   true,
+	"UI":    true,
+	"UID":   true,
+	"UUID":  true,
+	"URI":   true,
+	"URL":   true,
+	"UTF8":  true,
+	"VM":    true,
+	"XML":   true,
+	"XMPP":  true,
+	"XSRF":  true,
+	"XSS":   true,
+}
+
+// Name returns a different name of struct, var, const, or function if it should be different.
+func Name(name string, allowlist, blocklist []string, skipInitialismNameChecks bool) (should string) {
+	// Fast path for simple cases: "_" and all lowercase.
+	if name == "_" {
+		return name
+	}
+	allLower := true
+	for _, r := range name {
+		if !unicode.IsLower(r) {
+			allLower = false
+			break
+		}
+	}
+	if allLower {
+		return name
+	}
+
+	// Split camelCase at any lower->upper transition, and split on underscores.
+	// Check each word for common initialisms.
+	runes := []rune(name)
+	w, i := 0, 0 // index of start of word, scan
+	for i+1 <= len(runes) {
+		eow := false // whether we hit the end of a word
+		switch {
+		case i+1 == len(runes):
+			eow = true
+		case runes[i+1] == '_':
+			// underscore; shift the remainder forward over any run of underscores
+			eow = true
+			n := 1
+			for i+n+1 < len(runes) && runes[i+n+1] == '_' {
+				n++
+			}
+
+			// Leave at most one underscore if the underscore is between two digits
+			if i+n+1 < len(runes) && unicode.IsDigit(runes[i]) && unicode.IsDigit(runes[i+n+1]) {
+				n--
+			}
+
+			copy(runes[i+1:], runes[i+n+1:])
+			runes = runes[:len(runes)-n]
+		case unicode.IsLower(runes[i]) && !unicode.IsLower(runes[i+1]):
+			// lower->non-lower
+			eow = true
+		}
+		i++
+		if !eow {
+			continue
+		}
+
+		// [w,i) is a word.
+		word := string(runes[w:i])
+		ignoreInitWarnings := map[string]bool{}
+		for _, i := range allowlist {
+			ignoreInitWarnings[i] = true
+		}
+
+		extraInits := map[string]bool{}
+		for _, i := range blocklist {
+			extraInits[i] = true
+		}
+
+		if u := strings.ToUpper(word); !skipInitialismNameChecks && (commonInitialisms[u] || extraInits[u]) && !ignoreInitWarnings[u] {
+			// Keep consistent case, which is lowercase only at the start.
+			if w == 0 && unicode.IsLower(runes[w]) {
+				u = strings.ToLower(u)
+			}
+			// Keep lowercase s for IDs
+			if u == "IDS" {
+				u = "IDs"
+			}
+			// All the common initialisms are ASCII,
+			// so we can replace the bytes exactly.
+			copy(runes[w:], []rune(u))
+		} else if w > 0 && strings.ToLower(word) == word {
+			// already all lowercase, and not the first word, so uppercase the first character.
+			runes[w] = unicode.ToUpper(runes[w])
+		}
+		w = i
+	}
+	return string(runes)
+}
diff --git a/lint/name.go b/lint/name.go
index 4631cec..23ca06c 100644
--- a/lint/name.go
+++ b/lint/name.go
@@ -1,134 +1,10 @@
 package lint
 
-import (
-	"strings"
-	"unicode"
-)
+import "github.com/mgechev/revive/internal/rule"
 
 // Name returns a different name if it should be different.
-func Name(name string, allowlist, blocklist []string) (should string) {
-	// Fast path for simple cases: "_" and all lowercase.
-	if name == "_" {
-		return name
-	}
-	allLower := true
-	for _, r := range name {
-		if !unicode.IsLower(r) {
-			allLower = false
-			break
-		}
-	}
-	if allLower {
-		return name
-	}
-
-	// Split camelCase at any lower->upper transition, and split on underscores.
-	// Check each word for common initialisms.
-	runes := []rune(name)
-	w, i := 0, 0 // index of start of word, scan
-	for i+1 <= len(runes) {
-		eow := false // whether we hit the end of a word
-		switch {
-		case i+1 == len(runes):
-			eow = true
-		case runes[i+1] == '_':
-			// underscore; shift the remainder forward over any run of underscores
-			eow = true
-			n := 1
-			for i+n+1 < len(runes) && runes[i+n+1] == '_' {
-				n++
-			}
-
-			// Leave at most one underscore if the underscore is between two digits
-			if i+n+1 < len(runes) && unicode.IsDigit(runes[i]) && unicode.IsDigit(runes[i+n+1]) {
-				n--
-			}
-
-			copy(runes[i+1:], runes[i+n+1:])
-			runes = runes[:len(runes)-n]
-		case unicode.IsLower(runes[i]) && !unicode.IsLower(runes[i+1]):
-			// lower->non-lower
-			eow = true
-		}
-		i++
-		if !eow {
-			continue
-		}
-
-		// [w,i) is a word.
-		word := string(runes[w:i])
-		ignoreInitWarnings := map[string]bool{}
-		for _, i := range allowlist {
-			ignoreInitWarnings[i] = true
-		}
-
-		extraInits := map[string]bool{}
-		for _, i := range blocklist {
-			extraInits[i] = true
-		}
-
-		if u := strings.ToUpper(word); (commonInitialisms[u] || extraInits[u]) && !ignoreInitWarnings[u] {
-			// Keep consistent case, which is lowercase only at the start.
-			if w == 0 && unicode.IsLower(runes[w]) {
-				u = strings.ToLower(u)
-			}
-			// Keep lowercase s for IDs
-			if u == "IDS" {
-				u = "IDs"
-			}
-			// All the common initialisms are ASCII,
-			// so we can replace the bytes exactly.
-			copy(runes[w:], []rune(u))
-		} else if w > 0 && strings.ToLower(word) == word {
-			// already all lowercase, and not the first word, so uppercase the first character.
-			runes[w] = unicode.ToUpper(runes[w])
-		}
-		w = i
-	}
-	return string(runes)
-}
-
-// commonInitialisms is a set of common initialisms.
-// Only add entries that are highly unlikely to be non-initialisms.
-// For instance, "ID" is fine (Freudian code is rare), but "AND" is not.
-var commonInitialisms = map[string]bool{
-	"ACL":   true,
-	"API":   true,
-	"ASCII": true,
-	"CPU":   true,
-	"CSS":   true,
-	"DNS":   true,
-	"EOF":   true,
-	"GUID":  true,
-	"HTML":  true,
-	"HTTP":  true,
-	"HTTPS": true,
-	"ID":    true,
-	"IDS":   true,
-	"IP":    true,
-	"JSON":  true,
-	"LHS":   true,
-	"QPS":   true,
-	"RAM":   true,
-	"RHS":   true,
-	"RPC":   true,
-	"SLA":   true,
-	"SMTP":  true,
-	"SQL":   true,
-	"SSH":   true,
-	"TCP":   true,
-	"TLS":   true,
-	"TTL":   true,
-	"UDP":   true,
-	"UI":    true,
-	"UID":   true,
-	"UUID":  true,
-	"URI":   true,
-	"URL":   true,
-	"UTF8":  true,
-	"VM":    true,
-	"XML":   true,
-	"XMPP":  true,
-	"XSRF":  true,
-	"XSS":   true,
+//
+// Deprecated: Do not use this function, it will be removed in the next major release.
+func Name(name string, allowlist, blocklist []string) string {
+	return rule.Name(name, allowlist, blocklist, false)
 }
diff --git a/rule/var_naming.go b/rule/var_naming.go
index b1c2489..c8c26a4 100644
--- a/rule/var_naming.go
+++ b/rule/var_naming.go
@@ -9,6 +9,7 @@ import (
 	"sync"
 
 	"github.com/mgechev/revive/internal/astutils"
+	"github.com/mgechev/revive/internal/rule"
 	"github.com/mgechev/revive/lint"
 )
 
@@ -32,8 +33,10 @@ var defaultBadPackageNames = map[string]struct{}{
 
 // VarNamingRule lints the name of a variable.
 type VarNamingRule struct {
-	allowList             []string
-	blockList             []string
+	allowList                []string
+	blockList                []string
+	skipInitialismNameChecks bool // if true disable enforcing capitals for common initialisms
+
 	allowUpperCaseConst   bool                // if true - allows to use UPPER_SOME_NAMES for constants
 	skipPackageNameChecks bool                // check for meaningless and user-defined bad package names
 	extraBadPackageNames  map[string]struct{} // inactive if skipPackageNameChecks is false
@@ -78,6 +81,8 @@ func (r *VarNamingRule) Configure(arguments lint.Arguments) error {
 		}
 		for k, v := range args {
 			switch {
+			case isRuleOption(k, "skipInitialismNameChecks"):
+				r.skipInitialismNameChecks = fmt.Sprint(v) == "true"
 			case isRuleOption(k, "upperCaseConst"):
 				r.allowUpperCaseConst = fmt.Sprint(v) == "true"
 			case isRuleOption(k, "skipPackageNameChecks"):
@@ -116,12 +121,13 @@ func (r *VarNamingRule) Apply(file *lint.File, _ lint.Arguments) []lint.Failure
 
 	fileAst := file.AST
 	walker := lintNames{
-		file:           file,
-		fileAst:        fileAst,
-		allowList:      r.allowList,
-		blockList:      r.blockList,
-		onFailure:      onFailure,
-		upperCaseConst: r.allowUpperCaseConst,
+		file:                 file,
+		fileAst:              fileAst,
+		onFailure:            onFailure,
+		allowList:            r.allowList,
+		blockList:            r.blockList,
+		skipInitialismChecks: r.skipInitialismNameChecks,
+		upperCaseConst:       r.allowUpperCaseConst,
 	}
 
 	ast.Walk(&walker, fileAst)
@@ -177,12 +183,13 @@ func (*VarNamingRule) pkgNameFailure(node ast.Node, msg string, args ...any) lin
 }
 
 type lintNames struct {
-	file           *lint.File
-	fileAst        *ast.File
-	onFailure      func(lint.Failure)
-	allowList      []string
-	blockList      []string
-	upperCaseConst bool
+	file                 *lint.File
+	fileAst              *ast.File
+	onFailure            func(lint.Failure)
+	allowList            []string
+	blockList            []string
+	skipInitialismChecks bool
+	upperCaseConst       bool
 }
 
 func (w *lintNames) checkList(fl *ast.FieldList, thing string) {
@@ -221,7 +228,7 @@ func (w *lintNames) check(id *ast.Ident, thing string) {
 		return
 	}
 
-	should := lint.Name(id.Name, w.allowList, w.blockList)
+	should := rule.Name(id.Name, w.allowList, w.blockList, w.skipInitialismChecks)
 	if id.Name == should {
 		return
 	}



Test patch:
diff --git a/internal/rule/name_test.go b/internal/rule/name_test.go
new file mode 100644
index 0000000..9ba0b4e
--- /dev/null
+++ b/internal/rule/name_test.go
@@ -0,0 +1,195 @@
+package rule_test
+
+import (
+	"testing"
+
+	"github.com/mgechev/revive/internal/rule"
+)
+
+func TestName(t *testing.T) {
+	tests := []struct {
+		name                     string
+		allowlist                []string
+		blocklist                []string
+		skipInitialismNameChecks bool
+		want                     string
+	}{
+		{
+			name: "foo_bar",
+			want: "fooBar",
+		},
+		{
+			name: "foo_bar_baz",
+			want: "fooBarBaz",
+		},
+		{
+			name: "Foo_bar",
+			want: "FooBar",
+		},
+		{
+			name: "foo_WiFi",
+			want: "fooWiFi",
+		},
+		{
+			name: "id",
+			want: "id",
+		},
+		{
+			name: "Id",
+			want: "ID",
+		},
+		{
+			name: "foo_id",
+			want: "fooID",
+		},
+		{
+			name: "fooId",
+			want: "fooID",
+		},
+		{
+			name: "fooUid",
+			want: "fooUID",
+		},
+		{
+			name: "idFoo",
+			want: "idFoo",
+		},
+		{
+			name: "uidFoo",
+			want: "uidFoo",
+		},
+		{
+			name: "midIdDle",
+			want: "midIDDle",
+		},
+		{
+			name: "APIProxy",
+			want: "APIProxy",
+		},
+		{
+			name: "ApiProxy",
+			want: "APIProxy",
+		},
+		{
+			name: "apiProxy",
+			want: "apiProxy",
+		},
+		{
+			name: "_Leading",
+			want: "_Leading",
+		},
+		{
+			name: "___Leading",
+			want: "_Leading",
+		},
+		{
+			name: "trailing_",
+			want: "trailing",
+		},
+		{
+			name: "trailing___",
+			want: "trailing",
+		},
+		{
+			name: "a_b",
+			want: "aB",
+		},
+		{
+			name: "a__b",
+			want: "aB",
+		},
+		{
+			name: "a___b",
+			want: "aB",
+		},
+		{
+			name: "Rpc1150",
+			want: "RPC1150",
+		},
+		{
+			name: "case3_1",
+			want: "case3_1",
+		},
+		{
+			name: "case3__1",
+			want: "case3_1",
+		},
+		{
+			name: "IEEE802_16bit",
+			want: "IEEE802_16bit",
+		},
+		{
+			name: "IEEE802_16Bit",
+			want: "IEEE802_16Bit",
+		},
+		{
+			name: "IDS",
+			want: "IDs",
+		},
+		// Test skipInitialismChecks functionality
+		{
+			name:                     "getJson",
+			skipInitialismNameChecks: true,
+			want:                     "getJson",
+		},
+		{
+			name:                     "userId",
+			skipInitialismNameChecks: true,
+			want:                     "userId",
+		},
+		{
+			name:                     "myHttpClient",
+			skipInitialismNameChecks: true,
+			want:                     "myHttpClient",
+		},
+		// Test allowlist functionality
+		{
+			name:      "fooId",
+			allowlist: []string{"ID"},
+			want:      "fooId",
+		},
+		{
+			name:      "fooApi",
+			allowlist: []string{"API"},
+			want:      "fooApi",
+		},
+		{
+			name:      "fooHttp",
+			allowlist: []string{"HTTP"},
+			want:      "fooHttp",
+		},
+		// Test blocklist functionality
+		{
+			name:      "fooCustom",
+			blocklist: []string{"CUSTOM"},
+			want:      "fooCUSTOM",
+		},
+		{
+			name:      "mySpecial",
+			blocklist: []string{"SPECIAL"},
+			want:      "mySPECIAL",
+		},
+		// Test combination of allowlist and blocklist
+		{
+			name:      "fooIdCustom",
+			allowlist: []string{"ID"},
+			blocklist: []string{"CUSTOM"},
+			want:      "fooIdCUSTOM",
+		},
+		// Test combination of allowlist, blocklist and skipInitialismChecks
+		{
+			name:                     "fooIdCustomHttpJson",
+			allowlist:                []string{"ID"},
+			blocklist:                []string{"CUSTOM"},
+			skipInitialismNameChecks: true,
+			want:                     "fooIdCustomHttpJson",
+		},
+	}
+	for _, test := range tests {
+		got := rule.Name(test.name, test.allowlist, test.blocklist, test.skipInitialismNameChecks)
+		if got != test.want {
+			t.Errorf("name(%q, allowlist=%v, blocklist=%v, skipInitialismNameChecks=%v) = %q, want %q",
+				test.name, test.allowlist, test.blocklist, test.skipInitialismNameChecks, got, test.want)
+		}
+	}
+}
diff --git a/lint/name_test.go b/lint/name_test.go
deleted file mode 100644
index e9cf428..0000000
--- a/lint/name_test.go
+++ /dev/null
@@ -1,44 +0,0 @@
-package lint
-
-import "testing"
-
-// TestName tests Name function.
-func TestName(t *testing.T) {
-	tests := []struct {
-		name, want string
-	}{
-		{"foo_bar", "fooBar"},
-		{"foo_bar_baz", "fooBarBaz"},
-		{"Foo_bar", "FooBar"},
-		{"foo_WiFi", "fooWiFi"},
-		{"id", "id"},
-		{"Id", "ID"},
-		{"foo_id", "fooID"},
-		{"fooId", "fooID"},
-		{"fooUid", "fooUID"},
-		{"idFoo", "idFoo"},
-		{"uidFoo", "uidFoo"},
-		{"midIdDle", "midIDDle"},
-		{"APIProxy", "APIProxy"},
-		{"ApiProxy", "APIProxy"},
-		{"apiProxy", "apiProxy"},
-		{"_Leading", "_Leading"},
-		{"___Leading", "_Leading"},
-		{"trailing_", "trailing"},
-		{"trailing___", "trailing"},
-		{"a_b", "aB"},
-		{"a__b", "aB"},
-		{"a___b", "aB"},
-		{"Rpc1150", "RPC1150"},
-		{"case3_1", "case3_1"},
-		{"case3__1", "case3_1"},
-		{"IEEE802_16bit", "IEEE802_16bit"},
-		{"IEEE802_16Bit", "IEEE802_16Bit"},
-	}
-	for _, test := range tests {
-		got := Name(test.name, nil, nil)
-		if got != test.want {
-			t.Errorf("Name(%q) = %q, want %q", test.name, got, test.want)
-		}
-	}
-}
diff --git a/rule/var_naming_test.go b/rule/var_naming_test.go
index 183ea95..f59c582 100644
--- a/rule/var_naming_test.go
+++ b/rule/var_naming_test.go
@@ -10,23 +10,25 @@ import (
 
 func TestVarNamingRule_Configure(t *testing.T) {
 	tests := []struct {
-		name                      string
-		arguments                 lint.Arguments
-		wantErr                   error
-		wantAllowList             []string
-		wantBlockList             []string
-		wantAllowUpperCaseConst   bool
-		wantSkipPackageNameChecks bool
-		wantBadPackageNames       map[string]struct{}
+		name                         string
+		arguments                    lint.Arguments
+		wantErr                      error
+		wantAllowList                []string
+		wantBlockList                []string
+		wantSkipInitialismNameChecks bool
+		wantAllowUpperCaseConst      bool
+		wantSkipPackageNameChecks    bool
+		wantBadPackageNames          map[string]struct{}
 	}{
 		{
-			name:                      "no arguments",
-			arguments:                 lint.Arguments{},
-			wantErr:                   nil,
-			wantAllowList:             nil,
-			wantBlockList:             nil,
-			wantAllowUpperCaseConst:   false,
-			wantSkipPackageNameChecks: false,
+			name:                         "no arguments",
+			arguments:                    lint.Arguments{},
+			wantErr:                      nil,
+			wantAllowList:                nil,
+			wantBlockList:                nil,
+			wantSkipInitialismNameChecks: false,
+			wantAllowUpperCaseConst:      false,
+			wantSkipPackageNameChecks:    false,
 		},
 		{
 			name: "valid arguments",
@@ -34,17 +36,19 @@ func TestVarNamingRule_Configure(t *testing.T) {
 				[]any{"ID"},
 				[]any{"VM"},
 				[]any{map[string]any{
-					"upperCaseConst":        true,
-					"skipPackageNameChecks": true,
-					"extraBadPackageNames":  []any{"helpers", "models"},
+					"skipInitialismNameChecks": true,
+					"upperCaseConst":           true,
+					"skipPackageNameChecks":    true,
+					"extraBadPackageNames":     []any{"helpers", "models"},
 				}},
 			},
-			wantErr:                   nil,
-			wantAllowList:             []string{"ID"},
-			wantBlockList:             []string{"VM"},
-			wantAllowUpperCaseConst:   true,
-			wantSkipPackageNameChecks: true,
-			wantBadPackageNames:       map[string]struct{}{"helpers": {}, "models": {}},
+			wantErr:                      nil,
+			wantAllowList:                []string{"ID"},
+			wantBlockList:                []string{"VM"},
+			wantSkipInitialismNameChecks: true,
+			wantAllowUpperCaseConst:      true,
+			wantSkipPackageNameChecks:    true,
+			wantBadPackageNames:          map[string]struct{}{"helpers": {}, "models": {}},
 		},
 		{
 			name: "valid lowercased arguments",
@@ -52,17 +56,19 @@ func TestVarNamingRule_Configure(t *testing.T) {
 				[]any{"ID"},
 				[]any{"VM"},
 				[]any{map[string]any{
-					"uppercaseconst":        true,
-					"skippackagenamechecks": true,
-					"extrabadpackagenames":  []any{"helpers", "models"},
+					"skipinitialismnamechecks": true,
+					"uppercaseconst":           true,
+					"skippackagenamechecks":    true,
+					"extrabadpackagenames":     []any{"helpers", "models"},
 				}},
 			},
-			wantErr:                   nil,
-			wantAllowList:             []string{"ID"},
-			wantBlockList:             []string{"VM"},
-			wantAllowUpperCaseConst:   true,
-			wantSkipPackageNameChecks: true,
-			wantBadPackageNames:       map[string]struct{}{"helpers": {}, "models": {}},
+			wantErr:                      nil,
+			wantAllowList:                []string{"ID"},
+			wantBlockList:                []string{"VM"},
+			wantSkipInitialismNameChecks: true,
+			wantAllowUpperCaseConst:      true,
+			wantSkipPackageNameChecks:    true,
+			wantBadPackageNames:          map[string]struct{}{"helpers": {}, "models": {}},
 		},
 		{
 			name: "valid kebab-cased arguments",
@@ -70,17 +76,19 @@ func TestVarNamingRule_Configure(t *testing.T) {
 				[]any{"ID"},
 				[]any{"VM"},
 				[]any{map[string]any{
-					"upper-case-const":         true,
-					"skip-package-name-checks": true,
-					"extra-bad-package-names":  []any{"helpers", "models"},
+					"skip-initialism-name-checks": true,
+					"upper-case-const":            true,
+					"skip-package-name-checks":    true,
+					"extra-bad-package-names":     []any{"helpers", "models"},
 				}},
 			},
-			wantErr:                   nil,
-			wantAllowList:             []string{"ID"},
-			wantBlockList:             []string{"VM"},
-			wantAllowUpperCaseConst:   true,
-			wantSkipPackageNameChecks: true,
-			wantBadPackageNames:       map[string]struct{}{"helpers": {}, "models": {}},
+			wantErr:                      nil,
+			wantAllowList:                []string{"ID"},
+			wantBlockList:                []string{"VM"},
+			wantSkipInitialismNameChecks: true,
+			wantAllowUpperCaseConst:      true,
+			wantSkipPackageNameChecks:    true,
+			wantBadPackageNames:          map[string]struct{}{"helpers": {}, "models": {}},
 		},
 		{
 			name:      "invalid allowlist type",
@@ -149,6 +157,9 @@ func TestVarNamingRule_Configure(t *testing.T) {
 			if rule.skipPackageNameChecks != tt.wantSkipPackageNameChecks {
 				t.Errorf("unexpected skipPackageNameChecks: got = %v, want %v", rule.skipPackageNameChecks, tt.wantSkipPackageNameChecks)
 			}
+			if rule.skipInitialismNameChecks != tt.wantSkipInitialismNameChecks {
+				t.Errorf("unexpected skipInitialismNameChecks: got = %v, want %v", rule.skipInitialismNameChecks, tt.wantSkipInitialismNameChecks)
+			}
 			if !reflect.DeepEqual(rule.extraBadPackageNames, tt.wantBadPackageNames) {
 				t.Errorf("unexpected extraBadPackageNames: got = %v, want %v", rule.extraBadPackageNames, tt.wantBadPackageNames)
 			}
diff --git a/test/var_naming_test.go b/test/var_naming_test.go
index d20c8f0..6a6e616 100644
--- a/test/var_naming_test.go
+++ b/test/var_naming_test.go
@@ -11,6 +11,24 @@ func TestVarNaming(t *testing.T) {
 	testRule(t, "var_naming", &rule.VarNamingRule{}, &lint.RuleConfig{
 		Arguments: []any{[]any{"ID"}, []any{"VM"}},
 	})
+	testRule(t, "var_naming_skip_initialism_name_checks_true", &rule.VarNamingRule{}, &lint.RuleConfig{
+		Arguments: []any{
+			[]any{},
+			[]any{},
+			[]any{map[string]any{"skip-initialism-name-checks": true}},
+		}})
+	testRule(t, "var_naming_skip_initialism_name_checks_false", &rule.VarNamingRule{}, &lint.RuleConfig{
+		Arguments: []any{
+			[]any{},
+			[]any{},
+			[]any{map[string]any{"skip-initialism-name-checks": false}},
+		}})
+	testRule(t, "var_naming_allowlist_blocklist_skip_initialism_name_checks", &rule.VarNamingRule{}, &lint.RuleConfig{
+		Arguments: []any{
+			[]any{"ID"},
+			[]any{"VM"},
+			[]any{map[string]any{"skip-initialism-name-checks": true}},
+		}})
 
 	testRule(t, "var_naming_test", &rule.VarNamingRule{}, &lint.RuleConfig{})
 
diff --git a/testdata/var_naming_allowlist_blocklist_skip_initialism_name_checks.go b/testdata/var_naming_allowlist_blocklist_skip_initialism_name_checks.go
new file mode 100644
index 0000000..0b8243e
--- /dev/null
+++ b/testdata/var_naming_allowlist_blocklist_skip_initialism_name_checks.go
@@ -0,0 +1,10 @@
+package fixtures
+
+func varNamingAllowListBlocklistSkipInitialismNameChecks() string {
+	customId := "result"
+	customVm := "result"
+	_ = customVm
+	customIds := "result"
+	_ = customIds
+	return customId
+}
diff --git a/testdata/var_naming_skip_initialism_name_checks_false.go b/testdata/var_naming_skip_initialism_name_checks_false.go
new file mode 100644
index 0000000..97851ba
--- /dev/null
+++ b/testdata/var_naming_skip_initialism_name_checks_false.go
@@ -0,0 +1,11 @@
+package fixtures
+
+const HTTPRes = 200
+
+func readJSON() {
+	return
+}
+
+type SSHConfig struct {
+	keyPath string
+}
diff --git a/testdata/var_naming_skip_initialism_name_checks_true.go b/testdata/var_naming_skip_initialism_name_checks_true.go
new file mode 100644
index 0000000..69be731
--- /dev/null
+++ b/testdata/var_naming_skip_initialism_name_checks_true.go
@@ -0,0 +1,11 @@
+package fixtures
+
+const HttpRes = 200
+
+func readJson() {
+	return
+}
+
+type SshConfig struct {
+	keyPath string
+}