diff --git a/commands/sketch/new.go b/commands/sketch/new.go
index 5efbee8ff48..ff2828b4e6f 100644
--- a/commands/sketch/new.go
+++ b/commands/sketch/new.go
@@ -37,7 +37,7 @@ void loop() {
 
 // sketchNameMaxLength could be part of the regex, but it's intentionally left out for clearer error reporting
 var sketchNameMaxLength = 63
-var sketchNameValidationRegex = regexp.MustCompile(`^[0-9a-zA-Z][0-9a-zA-Z_\.-]*$`)
+var sketchNameValidationRegex = regexp.MustCompile(`^[0-9a-zA-Z_][0-9a-zA-Z_\.-]*$`)
 
 // NewSketch creates a new sketch via gRPC
 func NewSketch(ctx context.Context, req *rpc.NewSketchRequest) (*rpc.NewSketchResponse, error) {
@@ -80,7 +80,7 @@ func validateSketchName(name string) error {
 			sketchNameMaxLength))}
 	}
 	if !sketchNameValidationRegex.MatchString(name) {
-		return &arduino.CantCreateSketchError{Cause: errors.New(tr(`invalid sketch name "%[1]s": the first character must be alphanumeric, the following ones can also contain "_", "-", and ".".`,
+		return &arduino.CantCreateSketchError{Cause: errors.New(tr(`invalid sketch name "%[1]s": the first character must be alphanumeric or "_", the following ones can also contain "-" and ".".`,
 			name))}
 	}
 	return nil
diff --git a/commands/sketch/new_test.go b/commands/sketch/new_test.go
index a0de66710ed..4ef67d50b2d 100644
--- a/commands/sketch/new_test.go
+++ b/commands/sketch/new_test.go
@@ -13,7 +13,6 @@ func Test_SketchNameWrongPattern(t *testing.T) {
 	invalidNames := []string{
 		"&",
 		".hello",
-		"_hello",
 		"-hello",
 		"hello*",
 		"||||||||||||||",
@@ -25,7 +24,7 @@ func Test_SketchNameWrongPattern(t *testing.T) {
 			SketchDir:  t.TempDir(),
 		})
 
-		require.EqualError(t, err, fmt.Sprintf(`Can't create sketch: invalid sketch name "%s": the first character must be alphanumeric, the following ones can also contain "_", "-", and ".".`,
+		require.EqualError(t, err, fmt.Sprintf(`Can't create sketch: invalid sketch name "%s": the first character must be alphanumeric or "_", the following ones can also contain "-" and ".".`,
 			name))
 	}
 }
@@ -66,6 +65,7 @@ func Test_SketchNameOk(t *testing.T) {
 		"h..ello-world",
 		"h..ello-world.",
 		"hello_world__",
+		"_hello_world",
 		string(lengthLimitName),
 	}
 	for _, name := range validNames {
diff --git a/docs/sketch-specification.md b/docs/sketch-specification.md
index 105c220cfed..f7488c794ca 100644
--- a/docs/sketch-specification.md
+++ b/docs/sketch-specification.md
@@ -5,10 +5,13 @@ The programs that run on Arduino boards are called "sketches". This term was inh
 
 ## Sketch folders and files
 
-The sketch root folder name and code file names must start with a basic letter (`A`-`Z` or `a`-`z`) or number (`0`-`9`),
-followed by basic letters, numbers, underscores (`_`), dots (`.`) and dashes (`-`). The maximum length is 63 characters.
+The sketch root folder name and code file names must start with a basic letter (`A`-`Z` or `a`-`z`), number (`0`-`9`)
+[<sup>1</sup>](#leading-number-note), or underscore (`_`) [<sup>2</sup>](#leading-underscore-note) followed by basic
+letters, numbers, underscores, dots (`.`) and dashes (`-`). The maximum length is 63 characters.
 
-Support for names starting with a number was added in Arduino IDE 1.8.4.
+<a id="leading-number-note"></a> <sup>1</sup> Supported from Arduino IDE 1.8.4. <br />
+<a id="leading-underscore-note"></a> <sup>2</sup> Supported in all versions except Arduino IDE 2.0.4/Arduino CLI
+0.30.0 - 0.30.1.
 
 ### Sketch root folder