From 373aa18c829b8cafbfa84fa87e8e0585114de7fe Mon Sep 17 00:00:00 2001
From: Cristian Maglie <c.maglie@arduino.cc>
Date: Thu, 3 Oct 2024 00:45:02 +0200
Subject: [PATCH 1/8] Allow port/protocol keys in sketch profile

---
 internal/arduino/sketch/profiles.go         | 10 +++++
 rpc/cc/arduino/cli/commands/v1/common.pb.go | 45 +++++++++++++++------
 rpc/cc/arduino/cli/commands/v1/common.proto |  4 ++
 3 files changed, 47 insertions(+), 12 deletions(-)

diff --git a/internal/arduino/sketch/profiles.go b/internal/arduino/sketch/profiles.go
index b01bec167f2..f55be884835 100644
--- a/internal/arduino/sketch/profiles.go
+++ b/internal/arduino/sketch/profiles.go
@@ -103,6 +103,8 @@ type Profile struct {
 	Name       string
 	Notes      string                   `yaml:"notes"`
 	FQBN       string                   `yaml:"fqbn"`
+	Port       string                   `yaml:"port"`
+	Protocol   string                   `yaml:"protocol"`
 	Programmer string                   `yaml:"programmer"`
 	Platforms  ProfileRequiredPlatforms `yaml:"platforms"`
 	Libraries  ProfileRequiredLibraries `yaml:"libraries"`
@@ -114,6 +116,8 @@ func (p *Profile) ToRpc() *rpc.SketchProfile {
 		Name:       p.Name,
 		Fqbn:       p.FQBN,
 		Programmer: p.Programmer,
+		Port:       p.Port,
+		Protocol:   p.Protocol,
 	}
 }
 
@@ -127,6 +131,12 @@ func (p *Profile) AsYaml() string {
 	if p.Programmer != "" {
 		res += fmt.Sprintf("    programmer: %s\n", p.Programmer)
 	}
+	if p.Port != "" {
+		res += fmt.Sprintf("    port: %s\n", p.Port)
+	}
+	if p.Protocol != "" {
+		res += fmt.Sprintf("    protocol: %s\n", p.Protocol)
+	}
 	res += p.Platforms.AsYaml()
 	res += p.Libraries.AsYaml()
 	return res
diff --git a/rpc/cc/arduino/cli/commands/v1/common.pb.go b/rpc/cc/arduino/cli/commands/v1/common.pb.go
index 47f4b1e3ba1..49414bce4ec 100644
--- a/rpc/cc/arduino/cli/commands/v1/common.pb.go
+++ b/rpc/cc/arduino/cli/commands/v1/common.pb.go
@@ -1238,6 +1238,10 @@ type SketchProfile struct {
 	Fqbn string `protobuf:"bytes,2,opt,name=fqbn,proto3" json:"fqbn,omitempty"`
 	// Programmer used by the profile
 	Programmer string `protobuf:"bytes,3,opt,name=programmer,proto3" json:"programmer,omitempty"`
+	// Default Port in this profile
+	Port string `protobuf:"bytes,4,opt,name=port,proto3" json:"port,omitempty"`
+	// Default Protocol in this profile
+	Protocol string `protobuf:"bytes,5,opt,name=protocol,proto3" json:"protocol,omitempty"`
 }
 
 func (x *SketchProfile) Reset() {
@@ -1293,6 +1297,20 @@ func (x *SketchProfile) GetProgrammer() string {
 	return ""
 }
 
+func (x *SketchProfile) GetPort() string {
+	if x != nil {
+		return x.Port
+	}
+	return ""
+}
+
+func (x *SketchProfile) GetProtocol() string {
+	if x != nil {
+		return x.Protocol
+	}
+	return ""
+}
+
 var File_cc_arduino_cli_commands_v1_common_proto protoreflect.FileDescriptor
 
 var file_cc_arduino_cli_commands_v1_common_proto_rawDesc = []byte{
@@ -1461,18 +1479,21 @@ var file_cc_arduino_cli_commands_v1_common_proto_rawDesc = []byte{
 	0x0e, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x50, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x12,
 	0x2d, 0x0a, 0x12, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x5f, 0x70, 0x72, 0x6f, 0x67, 0x72,
 	0x61, 0x6d, 0x6d, 0x65, 0x72, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x09, 0x52, 0x11, 0x64, 0x65, 0x66,
-	0x61, 0x75, 0x6c, 0x74, 0x50, 0x72, 0x6f, 0x67, 0x72, 0x61, 0x6d, 0x6d, 0x65, 0x72, 0x22, 0x57,
-	0x0a, 0x0d, 0x53, 0x6b, 0x65, 0x74, 0x63, 0x68, 0x50, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x12,
-	0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e,
-	0x61, 0x6d, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x66, 0x71, 0x62, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28,
-	0x09, 0x52, 0x04, 0x66, 0x71, 0x62, 0x6e, 0x12, 0x1e, 0x0a, 0x0a, 0x70, 0x72, 0x6f, 0x67, 0x72,
-	0x61, 0x6d, 0x6d, 0x65, 0x72, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x70, 0x72, 0x6f,
-	0x67, 0x72, 0x61, 0x6d, 0x6d, 0x65, 0x72, 0x42, 0x48, 0x5a, 0x46, 0x67, 0x69, 0x74, 0x68, 0x75,
-	0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x61, 0x72, 0x64, 0x75, 0x69, 0x6e, 0x6f, 0x2f, 0x61, 0x72,
-	0x64, 0x75, 0x69, 0x6e, 0x6f, 0x2d, 0x63, 0x6c, 0x69, 0x2f, 0x72, 0x70, 0x63, 0x2f, 0x63, 0x63,
-	0x2f, 0x61, 0x72, 0x64, 0x75, 0x69, 0x6e, 0x6f, 0x2f, 0x63, 0x6c, 0x69, 0x2f, 0x63, 0x6f, 0x6d,
-	0x6d, 0x61, 0x6e, 0x64, 0x73, 0x2f, 0x76, 0x31, 0x3b, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64,
-	0x73, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
+	0x61, 0x75, 0x6c, 0x74, 0x50, 0x72, 0x6f, 0x67, 0x72, 0x61, 0x6d, 0x6d, 0x65, 0x72, 0x22, 0x87,
+	0x01, 0x0a, 0x0d, 0x53, 0x6b, 0x65, 0x74, 0x63, 0x68, 0x50, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65,
+	0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04,
+	0x6e, 0x61, 0x6d, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x66, 0x71, 0x62, 0x6e, 0x18, 0x02, 0x20, 0x01,
+	0x28, 0x09, 0x52, 0x04, 0x66, 0x71, 0x62, 0x6e, 0x12, 0x1e, 0x0a, 0x0a, 0x70, 0x72, 0x6f, 0x67,
+	0x72, 0x61, 0x6d, 0x6d, 0x65, 0x72, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x70, 0x72,
+	0x6f, 0x67, 0x72, 0x61, 0x6d, 0x6d, 0x65, 0x72, 0x12, 0x12, 0x0a, 0x04, 0x70, 0x6f, 0x72, 0x74,
+	0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x70, 0x6f, 0x72, 0x74, 0x12, 0x1a, 0x0a, 0x08,
+	0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08,
+	0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x42, 0x48, 0x5a, 0x46, 0x67, 0x69, 0x74, 0x68,
+	0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x61, 0x72, 0x64, 0x75, 0x69, 0x6e, 0x6f, 0x2f, 0x61,
+	0x72, 0x64, 0x75, 0x69, 0x6e, 0x6f, 0x2d, 0x63, 0x6c, 0x69, 0x2f, 0x72, 0x70, 0x63, 0x2f, 0x63,
+	0x63, 0x2f, 0x61, 0x72, 0x64, 0x75, 0x69, 0x6e, 0x6f, 0x2f, 0x63, 0x6c, 0x69, 0x2f, 0x63, 0x6f,
+	0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x73, 0x2f, 0x76, 0x31, 0x3b, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e,
+	0x64, 0x73, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
 }
 
 var (
diff --git a/rpc/cc/arduino/cli/commands/v1/common.proto b/rpc/cc/arduino/cli/commands/v1/common.proto
index 8c166ee13e4..9e329b535a1 100644
--- a/rpc/cc/arduino/cli/commands/v1/common.proto
+++ b/rpc/cc/arduino/cli/commands/v1/common.proto
@@ -213,4 +213,8 @@ message SketchProfile {
   string fqbn = 2;
   // Programmer used by the profile
   string programmer = 3;
+  // Default Port in this profile
+  string port = 4;
+  // Default Protocol in this profile
+  string protocol = 5;
 }

From 53b6c88bbfe8798fb96e3c71d7c8b245a3a850c3 Mon Sep 17 00:00:00 2001
From: Cristian Maglie <c.maglie@arduino.cc>
Date: Thu, 3 Oct 2024 01:07:56 +0200
Subject: [PATCH 2/8] Allow port/protocol in profiles

---
 internal/cli/arguments/fqbn.go  | 8 +++++++-
 internal/cli/compile/compile.go | 2 +-
 internal/cli/debug/debug.go     | 2 +-
 internal/cli/upload/upload.go   | 2 +-
 4 files changed, 10 insertions(+), 4 deletions(-)

diff --git a/internal/cli/arguments/fqbn.go b/internal/cli/arguments/fqbn.go
index 7783cdaf69a..3989cbf6aba 100644
--- a/internal/cli/arguments/fqbn.go
+++ b/internal/cli/arguments/fqbn.go
@@ -71,7 +71,7 @@ func (f *Fqbn) Set(fqbn string) {
 //   - the port is not found, in this case nil is returned
 //   - the FQBN autodetection fail, in this case the function prints an error and
 //     terminates the execution
-func CalculateFQBNAndPort(ctx context.Context, portArgs *Port, fqbnArg *Fqbn, instance *rpc.Instance, srv rpc.ArduinoCoreServiceServer, defaultFQBN, defaultAddress, defaultProtocol string) (string, *rpc.Port) {
+func CalculateFQBNAndPort(ctx context.Context, portArgs *Port, fqbnArg *Fqbn, instance *rpc.Instance, srv rpc.ArduinoCoreServiceServer, defaultFQBN, defaultAddress, defaultProtocol string, profile *rpc.SketchProfile) (string, *rpc.Port) {
 	fqbn := fqbnArg.String()
 	if fqbn == "" {
 		fqbn = defaultFQBN
@@ -87,6 +87,12 @@ func CalculateFQBNAndPort(ctx context.Context, portArgs *Port, fqbnArg *Fqbn, in
 		return fqbn, port
 	}
 
+	if profile.GetPort() != "" {
+		defaultAddress = profile.GetPort()
+	}
+	if profile.GetProtocol() != "" {
+		defaultProtocol = profile.GetProtocol()
+	}
 	port, err := portArgs.GetPort(ctx, instance, srv, defaultAddress, defaultProtocol)
 	if err != nil {
 		feedback.Fatal(i18n.Tr("Error getting port metadata: %v", err), feedback.ErrGeneric)
diff --git a/internal/cli/compile/compile.go b/internal/cli/compile/compile.go
index b4c093127b1..0fda0ec3dc6 100644
--- a/internal/cli/compile/compile.go
+++ b/internal/cli/compile/compile.go
@@ -180,7 +180,7 @@ func runCompileCommand(cmd *cobra.Command, args []string, srv rpc.ArduinoCoreSer
 		fqbnArg.Set(profile.GetFqbn())
 	}
 
-	fqbn, port := arguments.CalculateFQBNAndPort(ctx, &portArgs, &fqbnArg, inst, srv, sk.GetDefaultFqbn(), sk.GetDefaultPort(), sk.GetDefaultProtocol())
+	fqbn, port := arguments.CalculateFQBNAndPort(ctx, &portArgs, &fqbnArg, inst, srv, sk.GetDefaultFqbn(), sk.GetDefaultPort(), sk.GetDefaultProtocol(), profile)
 
 	if keysKeychain != "" || signKey != "" || encryptKey != "" {
 		arguments.CheckFlagsMandatory(cmd, "keys-keychain", "sign-key", "encrypt-key")
diff --git a/internal/cli/debug/debug.go b/internal/cli/debug/debug.go
index a9dd9d976a0..a4cce1815e7 100644
--- a/internal/cli/debug/debug.go
+++ b/internal/cli/debug/debug.go
@@ -108,7 +108,7 @@ func runDebugCommand(ctx context.Context, srv rpc.ArduinoCoreServiceServer, args
 		fqbnArg.Set(profile.GetFqbn())
 	}
 
-	fqbn, port := arguments.CalculateFQBNAndPort(ctx, portArgs, fqbnArg, inst, srv, sk.GetDefaultFqbn(), sk.GetDefaultPort(), sk.GetDefaultProtocol())
+	fqbn, port := arguments.CalculateFQBNAndPort(ctx, portArgs, fqbnArg, inst, srv, sk.GetDefaultFqbn(), sk.GetDefaultPort(), sk.GetDefaultProtocol(), profile)
 
 	prog := profile.GetProgrammer()
 	if prog == "" || programmer.GetProgrammer() != "" {
diff --git a/internal/cli/upload/upload.go b/internal/cli/upload/upload.go
index b33c5d1a4fc..61994d61826 100644
--- a/internal/cli/upload/upload.go
+++ b/internal/cli/upload/upload.go
@@ -117,7 +117,7 @@ func runUploadCommand(ctx context.Context, srv rpc.ArduinoCoreServiceServer, arg
 	defaultFQBN := sketch.GetDefaultFqbn()
 	defaultAddress := sketch.GetDefaultPort()
 	defaultProtocol := sketch.GetDefaultProtocol()
-	fqbn, port := arguments.CalculateFQBNAndPort(ctx, &portArgs, &fqbnArg, inst, srv, defaultFQBN, defaultAddress, defaultProtocol)
+	fqbn, port := arguments.CalculateFQBNAndPort(ctx, &portArgs, &fqbnArg, inst, srv, defaultFQBN, defaultAddress, defaultProtocol, profile)
 
 	userFieldRes, err := srv.SupportedUserFields(ctx, &rpc.SupportedUserFieldsRequest{
 		Instance: inst,

From e22b2a1b0251b0499ae17d687ffa3c2e09f8e593 Mon Sep 17 00:00:00 2001
From: Cristian Maglie <c.maglie@arduino.cc>
Date: Thu, 3 Oct 2024 18:52:37 +0200
Subject: [PATCH 3/8] Added port settings in sketch profile

---
 internal/arduino/sketch/profiles.go          |  39 ++-
 internal/arduino/sketch/sketch.go            |  11 +
 rpc/cc/arduino/cli/commands/v1/common.pb.go  | 227 ++++++++++++--
 rpc/cc/arduino/cli/commands/v1/common.proto  |  16 +-
 rpc/cc/arduino/cli/commands/v1/monitor.pb.go | 305 +++++--------------
 rpc/cc/arduino/cli/commands/v1/monitor.proto |  10 -
 6 files changed, 341 insertions(+), 267 deletions(-)

diff --git a/internal/arduino/sketch/profiles.go b/internal/arduino/sketch/profiles.go
index f55be884835..cd32ccdf681 100644
--- a/internal/arduino/sketch/profiles.go
+++ b/internal/arduino/sketch/profiles.go
@@ -34,12 +34,13 @@ import (
 
 // projectRaw is a support struct used only to unmarshal the yaml
 type projectRaw struct {
-	ProfilesRaw       yaml.Node `yaml:"profiles"`
-	DefaultProfile    string    `yaml:"default_profile"`
-	DefaultFqbn       string    `yaml:"default_fqbn"`
-	DefaultPort       string    `yaml:"default_port,omitempty"`
-	DefaultProtocol   string    `yaml:"default_protocol,omitempty"`
-	DefaultProgrammer string    `yaml:"default_programmer,omitempty"`
+	ProfilesRaw       yaml.Node         `yaml:"profiles"`
+	DefaultProfile    string            `yaml:"default_profile"`
+	DefaultFqbn       string            `yaml:"default_fqbn"`
+	DefaultPort       string            `yaml:"default_port,omitempty"`
+	DefaultPortConfig map[string]string `yaml:"default_port_config,omitempty"`
+	DefaultProtocol   string            `yaml:"default_protocol,omitempty"`
+	DefaultProgrammer string            `yaml:"default_programmer,omitempty"`
 }
 
 // Project represents the sketch project file
@@ -48,6 +49,7 @@ type Project struct {
 	DefaultProfile    string
 	DefaultFqbn       string
 	DefaultPort       string
+	DefaultPortConfig map[string]string
 	DefaultProtocol   string
 	DefaultProgrammer string
 }
@@ -70,6 +72,12 @@ func (p *Project) AsYaml() string {
 	if p.DefaultPort != "" {
 		res += fmt.Sprintf("default_port: %s\n", p.DefaultPort)
 	}
+	if len(p.DefaultPortConfig) > 0 {
+		res += "default_port_config:\n"
+		for k, v := range p.DefaultPortConfig {
+			res += fmt.Sprintf("  %s: %s\n", k, v)
+		}
+	}
 	if p.DefaultProtocol != "" {
 		res += fmt.Sprintf("default_protocol: %s\n", p.DefaultProtocol)
 	}
@@ -104,6 +112,7 @@ type Profile struct {
 	Notes      string                   `yaml:"notes"`
 	FQBN       string                   `yaml:"fqbn"`
 	Port       string                   `yaml:"port"`
+	PortConfig map[string]string        `yaml:"port_config"`
 	Protocol   string                   `yaml:"protocol"`
 	Programmer string                   `yaml:"programmer"`
 	Platforms  ProfileRequiredPlatforms `yaml:"platforms"`
@@ -112,11 +121,22 @@ type Profile struct {
 
 // ToRpc converts this Profile to an rpc.SketchProfile
 func (p *Profile) ToRpc() *rpc.SketchProfile {
+	var portConfig *rpc.MonitorPortConfiguration
+	if len(p.PortConfig) > 0 {
+		portConfig = &rpc.MonitorPortConfiguration{}
+		for k, v := range p.PortConfig {
+			portConfig.Settings = append(portConfig.Settings, &rpc.MonitorPortSetting{
+				SettingId: k,
+				Value:     v,
+			})
+		}
+	}
 	return &rpc.SketchProfile{
 		Name:       p.Name,
 		Fqbn:       p.FQBN,
 		Programmer: p.Programmer,
 		Port:       p.Port,
+		PortConfig: portConfig,
 		Protocol:   p.Protocol,
 	}
 }
@@ -137,6 +157,12 @@ func (p *Profile) AsYaml() string {
 	if p.Protocol != "" {
 		res += fmt.Sprintf("    protocol: %s\n", p.Protocol)
 	}
+	if len(p.PortConfig) > 0 {
+		res += "     port_config:\n"
+		for k, v := range p.PortConfig {
+			res += fmt.Sprintf("       %s: %s\n", k, v)
+		}
+	}
 	res += p.Platforms.AsYaml()
 	res += p.Libraries.AsYaml()
 	return res
@@ -301,6 +327,7 @@ func LoadProjectFile(file *paths.Path) (*Project, error) {
 		DefaultProfile:    raw.DefaultProfile,
 		DefaultFqbn:       raw.DefaultFqbn,
 		DefaultPort:       raw.DefaultPort,
+		DefaultPortConfig: raw.DefaultPortConfig,
 		DefaultProtocol:   raw.DefaultProtocol,
 		DefaultProgrammer: raw.DefaultProgrammer,
 	}, nil
diff --git a/internal/arduino/sketch/sketch.go b/internal/arduino/sketch/sketch.go
index 8be6e790345..5cdfb6f3ee8 100644
--- a/internal/arduino/sketch/sketch.go
+++ b/internal/arduino/sketch/sketch.go
@@ -289,6 +289,16 @@ func (s *Sketch) Hash() string {
 // ToRpc converts this Sketch into a rpc.LoadSketchResponse
 func (s *Sketch) ToRpc() *rpc.Sketch {
 	defaultPort, defaultProtocol := s.GetDefaultPortAddressAndProtocol()
+	var defaultPortConfig *rpc.MonitorPortConfiguration
+	if len(s.Project.DefaultPortConfig) > 0 {
+		defaultPortConfig = &rpc.MonitorPortConfiguration{}
+		for k, v := range s.Project.DefaultPortConfig {
+			defaultPortConfig.Settings = append(defaultPortConfig.Settings, &rpc.MonitorPortSetting{
+				SettingId: k,
+				Value:     v,
+			})
+		}
+	}
 	res := &rpc.Sketch{
 		MainFile:          s.MainFile.String(),
 		LocationPath:      s.FullPath.String(),
@@ -297,6 +307,7 @@ func (s *Sketch) ToRpc() *rpc.Sketch {
 		RootFolderFiles:   s.RootFolderFiles.AsStrings(),
 		DefaultFqbn:       s.GetDefaultFQBN(),
 		DefaultPort:       defaultPort,
+		DefaultPortConfig: defaultPortConfig,
 		DefaultProtocol:   defaultProtocol,
 		DefaultProgrammer: s.GetDefaultProgrammer(),
 		Profiles:          f.Map(s.Project.Profiles, (*Profile).ToRpc),
diff --git a/rpc/cc/arduino/cli/commands/v1/common.pb.go b/rpc/cc/arduino/cli/commands/v1/common.pb.go
index 49414bce4ec..c18b5491a4e 100644
--- a/rpc/cc/arduino/cli/commands/v1/common.pb.go
+++ b/rpc/cc/arduino/cli/commands/v1/common.pb.go
@@ -1116,6 +1116,8 @@ type Sketch struct {
 	DefaultProfile *SketchProfile `protobuf:"bytes,10,opt,name=default_profile,json=defaultProfile,proto3" json:"default_profile,omitempty"`
 	// Default Programmer set in project file (sketch.yaml)
 	DefaultProgrammer string `protobuf:"bytes,11,opt,name=default_programmer,json=defaultProgrammer,proto3" json:"default_programmer,omitempty"`
+	// Default Port configuration set in project file (sketch.yaml)
+	DefaultPortConfig *MonitorPortConfiguration `protobuf:"bytes,12,opt,name=default_port_config,json=defaultPortConfig,proto3" json:"default_port_config,omitempty"`
 }
 
 func (x *Sketch) Reset() {
@@ -1227,6 +1229,116 @@ func (x *Sketch) GetDefaultProgrammer() string {
 	return ""
 }
 
+func (x *Sketch) GetDefaultPortConfig() *MonitorPortConfiguration {
+	if x != nil {
+		return x.DefaultPortConfig
+	}
+	return nil
+}
+
+type MonitorPortConfiguration struct {
+	state         protoimpl.MessageState
+	sizeCache     protoimpl.SizeCache
+	unknownFields protoimpl.UnknownFields
+
+	// The port configuration parameters
+	Settings []*MonitorPortSetting `protobuf:"bytes,1,rep,name=settings,proto3" json:"settings,omitempty"`
+}
+
+func (x *MonitorPortConfiguration) Reset() {
+	*x = MonitorPortConfiguration{}
+	if protoimpl.UnsafeEnabled {
+		mi := &file_cc_arduino_cli_commands_v1_common_proto_msgTypes[16]
+		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+		ms.StoreMessageInfo(mi)
+	}
+}
+
+func (x *MonitorPortConfiguration) String() string {
+	return protoimpl.X.MessageStringOf(x)
+}
+
+func (*MonitorPortConfiguration) ProtoMessage() {}
+
+func (x *MonitorPortConfiguration) ProtoReflect() protoreflect.Message {
+	mi := &file_cc_arduino_cli_commands_v1_common_proto_msgTypes[16]
+	if protoimpl.UnsafeEnabled && x != nil {
+		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+		if ms.LoadMessageInfo() == nil {
+			ms.StoreMessageInfo(mi)
+		}
+		return ms
+	}
+	return mi.MessageOf(x)
+}
+
+// Deprecated: Use MonitorPortConfiguration.ProtoReflect.Descriptor instead.
+func (*MonitorPortConfiguration) Descriptor() ([]byte, []int) {
+	return file_cc_arduino_cli_commands_v1_common_proto_rawDescGZIP(), []int{16}
+}
+
+func (x *MonitorPortConfiguration) GetSettings() []*MonitorPortSetting {
+	if x != nil {
+		return x.Settings
+	}
+	return nil
+}
+
+type MonitorPortSetting struct {
+	state         protoimpl.MessageState
+	sizeCache     protoimpl.SizeCache
+	unknownFields protoimpl.UnknownFields
+
+	SettingId string `protobuf:"bytes,1,opt,name=setting_id,json=settingId,proto3" json:"setting_id,omitempty"`
+	Value     string `protobuf:"bytes,2,opt,name=value,proto3" json:"value,omitempty"`
+}
+
+func (x *MonitorPortSetting) Reset() {
+	*x = MonitorPortSetting{}
+	if protoimpl.UnsafeEnabled {
+		mi := &file_cc_arduino_cli_commands_v1_common_proto_msgTypes[17]
+		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+		ms.StoreMessageInfo(mi)
+	}
+}
+
+func (x *MonitorPortSetting) String() string {
+	return protoimpl.X.MessageStringOf(x)
+}
+
+func (*MonitorPortSetting) ProtoMessage() {}
+
+func (x *MonitorPortSetting) ProtoReflect() protoreflect.Message {
+	mi := &file_cc_arduino_cli_commands_v1_common_proto_msgTypes[17]
+	if protoimpl.UnsafeEnabled && x != nil {
+		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+		if ms.LoadMessageInfo() == nil {
+			ms.StoreMessageInfo(mi)
+		}
+		return ms
+	}
+	return mi.MessageOf(x)
+}
+
+// Deprecated: Use MonitorPortSetting.ProtoReflect.Descriptor instead.
+func (*MonitorPortSetting) Descriptor() ([]byte, []int) {
+	return file_cc_arduino_cli_commands_v1_common_proto_rawDescGZIP(), []int{17}
+}
+
+func (x *MonitorPortSetting) GetSettingId() string {
+	if x != nil {
+		return x.SettingId
+	}
+	return ""
+}
+
+func (x *MonitorPortSetting) GetValue() string {
+	if x != nil {
+		return x.Value
+	}
+	return ""
+}
+
 type SketchProfile struct {
 	state         protoimpl.MessageState
 	sizeCache     protoimpl.SizeCache
@@ -1240,14 +1352,16 @@ type SketchProfile struct {
 	Programmer string `protobuf:"bytes,3,opt,name=programmer,proto3" json:"programmer,omitempty"`
 	// Default Port in this profile
 	Port string `protobuf:"bytes,4,opt,name=port,proto3" json:"port,omitempty"`
+	// Default Port configuration set in project file (sketch.yaml)
+	PortConfig *MonitorPortConfiguration `protobuf:"bytes,5,opt,name=port_config,json=portConfig,proto3" json:"port_config,omitempty"`
 	// Default Protocol in this profile
-	Protocol string `protobuf:"bytes,5,opt,name=protocol,proto3" json:"protocol,omitempty"`
+	Protocol string `protobuf:"bytes,6,opt,name=protocol,proto3" json:"protocol,omitempty"`
 }
 
 func (x *SketchProfile) Reset() {
 	*x = SketchProfile{}
 	if protoimpl.UnsafeEnabled {
-		mi := &file_cc_arduino_cli_commands_v1_common_proto_msgTypes[16]
+		mi := &file_cc_arduino_cli_commands_v1_common_proto_msgTypes[18]
 		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
 		ms.StoreMessageInfo(mi)
 	}
@@ -1260,7 +1374,7 @@ func (x *SketchProfile) String() string {
 func (*SketchProfile) ProtoMessage() {}
 
 func (x *SketchProfile) ProtoReflect() protoreflect.Message {
-	mi := &file_cc_arduino_cli_commands_v1_common_proto_msgTypes[16]
+	mi := &file_cc_arduino_cli_commands_v1_common_proto_msgTypes[18]
 	if protoimpl.UnsafeEnabled && x != nil {
 		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
 		if ms.LoadMessageInfo() == nil {
@@ -1273,7 +1387,7 @@ func (x *SketchProfile) ProtoReflect() protoreflect.Message {
 
 // Deprecated: Use SketchProfile.ProtoReflect.Descriptor instead.
 func (*SketchProfile) Descriptor() ([]byte, []int) {
-	return file_cc_arduino_cli_commands_v1_common_proto_rawDescGZIP(), []int{16}
+	return file_cc_arduino_cli_commands_v1_common_proto_rawDescGZIP(), []int{18}
 }
 
 func (x *SketchProfile) GetName() string {
@@ -1304,6 +1418,13 @@ func (x *SketchProfile) GetPort() string {
 	return ""
 }
 
+func (x *SketchProfile) GetPortConfig() *MonitorPortConfiguration {
+	if x != nil {
+		return x.PortConfig
+	}
+	return nil
+}
+
 func (x *SketchProfile) GetProtocol() string {
 	if x != nil {
 		return x.Protocol
@@ -1447,7 +1568,7 @@ var file_cc_arduino_cli_commands_v1_common_proto_rawDesc = []byte{
 	0x28, 0x09, 0x52, 0x04, 0x66, 0x71, 0x62, 0x6e, 0x22, 0x27, 0x0a, 0x0d, 0x48, 0x65, 0x6c, 0x70,
 	0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x12, 0x16, 0x0a, 0x06, 0x6f, 0x6e, 0x6c,
 	0x69, 0x6e, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x6f, 0x6e, 0x6c, 0x69, 0x6e,
-	0x65, 0x22, 0x8a, 0x04, 0x0a, 0x06, 0x53, 0x6b, 0x65, 0x74, 0x63, 0x68, 0x12, 0x1b, 0x0a, 0x09,
+	0x65, 0x22, 0xf0, 0x04, 0x0a, 0x06, 0x53, 0x6b, 0x65, 0x74, 0x63, 0x68, 0x12, 0x1b, 0x0a, 0x09,
 	0x6d, 0x61, 0x69, 0x6e, 0x5f, 0x66, 0x69, 0x6c, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52,
 	0x08, 0x6d, 0x61, 0x69, 0x6e, 0x46, 0x69, 0x6c, 0x65, 0x12, 0x23, 0x0a, 0x0d, 0x6c, 0x6f, 0x63,
 	0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x70, 0x61, 0x74, 0x68, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09,
@@ -1479,15 +1600,38 @@ var file_cc_arduino_cli_commands_v1_common_proto_rawDesc = []byte{
 	0x0e, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x50, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x12,
 	0x2d, 0x0a, 0x12, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x5f, 0x70, 0x72, 0x6f, 0x67, 0x72,
 	0x61, 0x6d, 0x6d, 0x65, 0x72, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x09, 0x52, 0x11, 0x64, 0x65, 0x66,
-	0x61, 0x75, 0x6c, 0x74, 0x50, 0x72, 0x6f, 0x67, 0x72, 0x61, 0x6d, 0x6d, 0x65, 0x72, 0x22, 0x87,
-	0x01, 0x0a, 0x0d, 0x53, 0x6b, 0x65, 0x74, 0x63, 0x68, 0x50, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65,
-	0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04,
-	0x6e, 0x61, 0x6d, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x66, 0x71, 0x62, 0x6e, 0x18, 0x02, 0x20, 0x01,
-	0x28, 0x09, 0x52, 0x04, 0x66, 0x71, 0x62, 0x6e, 0x12, 0x1e, 0x0a, 0x0a, 0x70, 0x72, 0x6f, 0x67,
-	0x72, 0x61, 0x6d, 0x6d, 0x65, 0x72, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x70, 0x72,
-	0x6f, 0x67, 0x72, 0x61, 0x6d, 0x6d, 0x65, 0x72, 0x12, 0x12, 0x0a, 0x04, 0x70, 0x6f, 0x72, 0x74,
-	0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x70, 0x6f, 0x72, 0x74, 0x12, 0x1a, 0x0a, 0x08,
-	0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08,
+	0x61, 0x75, 0x6c, 0x74, 0x50, 0x72, 0x6f, 0x67, 0x72, 0x61, 0x6d, 0x6d, 0x65, 0x72, 0x12, 0x64,
+	0x0a, 0x13, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x5f, 0x70, 0x6f, 0x72, 0x74, 0x5f, 0x63,
+	0x6f, 0x6e, 0x66, 0x69, 0x67, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x34, 0x2e, 0x63, 0x63,
+	0x2e, 0x61, 0x72, 0x64, 0x75, 0x69, 0x6e, 0x6f, 0x2e, 0x63, 0x6c, 0x69, 0x2e, 0x63, 0x6f, 0x6d,
+	0x6d, 0x61, 0x6e, 0x64, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x4d, 0x6f, 0x6e, 0x69, 0x74, 0x6f, 0x72,
+	0x50, 0x6f, 0x72, 0x74, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f,
+	0x6e, 0x52, 0x11, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x50, 0x6f, 0x72, 0x74, 0x43, 0x6f,
+	0x6e, 0x66, 0x69, 0x67, 0x22, 0x66, 0x0a, 0x18, 0x4d, 0x6f, 0x6e, 0x69, 0x74, 0x6f, 0x72, 0x50,
+	0x6f, 0x72, 0x74, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e,
+	0x12, 0x4a, 0x0a, 0x08, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x18, 0x01, 0x20, 0x03,
+	0x28, 0x0b, 0x32, 0x2e, 0x2e, 0x63, 0x63, 0x2e, 0x61, 0x72, 0x64, 0x75, 0x69, 0x6e, 0x6f, 0x2e,
+	0x63, 0x6c, 0x69, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x73, 0x2e, 0x76, 0x31, 0x2e,
+	0x4d, 0x6f, 0x6e, 0x69, 0x74, 0x6f, 0x72, 0x50, 0x6f, 0x72, 0x74, 0x53, 0x65, 0x74, 0x74, 0x69,
+	0x6e, 0x67, 0x52, 0x08, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x22, 0x49, 0x0a, 0x12,
+	0x4d, 0x6f, 0x6e, 0x69, 0x74, 0x6f, 0x72, 0x50, 0x6f, 0x72, 0x74, 0x53, 0x65, 0x74, 0x74, 0x69,
+	0x6e, 0x67, 0x12, 0x1d, 0x0a, 0x0a, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x5f, 0x69, 0x64,
+	0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x49,
+	0x64, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09,
+	0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x22, 0xde, 0x01, 0x0a, 0x0d, 0x53, 0x6b, 0x65, 0x74,
+	0x63, 0x68, 0x50, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d,
+	0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x12, 0x0a,
+	0x04, 0x66, 0x71, 0x62, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x66, 0x71, 0x62,
+	0x6e, 0x12, 0x1e, 0x0a, 0x0a, 0x70, 0x72, 0x6f, 0x67, 0x72, 0x61, 0x6d, 0x6d, 0x65, 0x72, 0x18,
+	0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x70, 0x72, 0x6f, 0x67, 0x72, 0x61, 0x6d, 0x6d, 0x65,
+	0x72, 0x12, 0x12, 0x0a, 0x04, 0x70, 0x6f, 0x72, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52,
+	0x04, 0x70, 0x6f, 0x72, 0x74, 0x12, 0x55, 0x0a, 0x0b, 0x70, 0x6f, 0x72, 0x74, 0x5f, 0x63, 0x6f,
+	0x6e, 0x66, 0x69, 0x67, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x34, 0x2e, 0x63, 0x63, 0x2e,
+	0x61, 0x72, 0x64, 0x75, 0x69, 0x6e, 0x6f, 0x2e, 0x63, 0x6c, 0x69, 0x2e, 0x63, 0x6f, 0x6d, 0x6d,
+	0x61, 0x6e, 0x64, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x4d, 0x6f, 0x6e, 0x69, 0x74, 0x6f, 0x72, 0x50,
+	0x6f, 0x72, 0x74, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e,
+	0x52, 0x0a, 0x70, 0x6f, 0x72, 0x74, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x1a, 0x0a, 0x08,
+	0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08,
 	0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x42, 0x48, 0x5a, 0x46, 0x67, 0x69, 0x74, 0x68,
 	0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x61, 0x72, 0x64, 0x75, 0x69, 0x6e, 0x6f, 0x2f, 0x61,
 	0x72, 0x64, 0x75, 0x69, 0x6e, 0x6f, 0x2d, 0x63, 0x6c, 0x69, 0x2f, 0x72, 0x70, 0x63, 0x2f, 0x63,
@@ -1508,7 +1652,7 @@ func file_cc_arduino_cli_commands_v1_common_proto_rawDescGZIP() []byte {
 	return file_cc_arduino_cli_commands_v1_common_proto_rawDescData
 }
 
-var file_cc_arduino_cli_commands_v1_common_proto_msgTypes = make([]protoimpl.MessageInfo, 18)
+var file_cc_arduino_cli_commands_v1_common_proto_msgTypes = make([]protoimpl.MessageInfo, 20)
 var file_cc_arduino_cli_commands_v1_common_proto_goTypes = []any{
 	(*Instance)(nil),                   // 0: cc.arduino.cli.commands.v1.Instance
 	(*DownloadProgress)(nil),           // 1: cc.arduino.cli.commands.v1.DownloadProgress
@@ -1526,8 +1670,10 @@ var file_cc_arduino_cli_commands_v1_common_proto_goTypes = []any{
 	(*Board)(nil),                      // 13: cc.arduino.cli.commands.v1.Board
 	(*HelpResources)(nil),              // 14: cc.arduino.cli.commands.v1.HelpResources
 	(*Sketch)(nil),                     // 15: cc.arduino.cli.commands.v1.Sketch
-	(*SketchProfile)(nil),              // 16: cc.arduino.cli.commands.v1.SketchProfile
-	nil,                                // 17: cc.arduino.cli.commands.v1.PlatformSummary.ReleasesEntry
+	(*MonitorPortConfiguration)(nil),   // 16: cc.arduino.cli.commands.v1.MonitorPortConfiguration
+	(*MonitorPortSetting)(nil),         // 17: cc.arduino.cli.commands.v1.MonitorPortSetting
+	(*SketchProfile)(nil),              // 18: cc.arduino.cli.commands.v1.SketchProfile
+	nil,                                // 19: cc.arduino.cli.commands.v1.PlatformSummary.ReleasesEntry
 }
 var file_cc_arduino_cli_commands_v1_common_proto_depIdxs = []int32{
 	2,  // 0: cc.arduino.cli.commands.v1.DownloadProgress.start:type_name -> cc.arduino.cli.commands.v1.DownloadProgressStart
@@ -1536,17 +1682,20 @@ var file_cc_arduino_cli_commands_v1_common_proto_depIdxs = []int32{
 	10, // 3: cc.arduino.cli.commands.v1.Platform.metadata:type_name -> cc.arduino.cli.commands.v1.PlatformMetadata
 	11, // 4: cc.arduino.cli.commands.v1.Platform.release:type_name -> cc.arduino.cli.commands.v1.PlatformRelease
 	10, // 5: cc.arduino.cli.commands.v1.PlatformSummary.metadata:type_name -> cc.arduino.cli.commands.v1.PlatformMetadata
-	17, // 6: cc.arduino.cli.commands.v1.PlatformSummary.releases:type_name -> cc.arduino.cli.commands.v1.PlatformSummary.ReleasesEntry
+	19, // 6: cc.arduino.cli.commands.v1.PlatformSummary.releases:type_name -> cc.arduino.cli.commands.v1.PlatformSummary.ReleasesEntry
 	13, // 7: cc.arduino.cli.commands.v1.PlatformRelease.boards:type_name -> cc.arduino.cli.commands.v1.Board
 	14, // 8: cc.arduino.cli.commands.v1.PlatformRelease.help:type_name -> cc.arduino.cli.commands.v1.HelpResources
-	16, // 9: cc.arduino.cli.commands.v1.Sketch.profiles:type_name -> cc.arduino.cli.commands.v1.SketchProfile
-	16, // 10: cc.arduino.cli.commands.v1.Sketch.default_profile:type_name -> cc.arduino.cli.commands.v1.SketchProfile
-	11, // 11: cc.arduino.cli.commands.v1.PlatformSummary.ReleasesEntry.value:type_name -> cc.arduino.cli.commands.v1.PlatformRelease
-	12, // [12:12] is the sub-list for method output_type
-	12, // [12:12] is the sub-list for method input_type
-	12, // [12:12] is the sub-list for extension type_name
-	12, // [12:12] is the sub-list for extension extendee
-	0,  // [0:12] is the sub-list for field type_name
+	18, // 9: cc.arduino.cli.commands.v1.Sketch.profiles:type_name -> cc.arduino.cli.commands.v1.SketchProfile
+	18, // 10: cc.arduino.cli.commands.v1.Sketch.default_profile:type_name -> cc.arduino.cli.commands.v1.SketchProfile
+	16, // 11: cc.arduino.cli.commands.v1.Sketch.default_port_config:type_name -> cc.arduino.cli.commands.v1.MonitorPortConfiguration
+	17, // 12: cc.arduino.cli.commands.v1.MonitorPortConfiguration.settings:type_name -> cc.arduino.cli.commands.v1.MonitorPortSetting
+	16, // 13: cc.arduino.cli.commands.v1.SketchProfile.port_config:type_name -> cc.arduino.cli.commands.v1.MonitorPortConfiguration
+	11, // 14: cc.arduino.cli.commands.v1.PlatformSummary.ReleasesEntry.value:type_name -> cc.arduino.cli.commands.v1.PlatformRelease
+	15, // [15:15] is the sub-list for method output_type
+	15, // [15:15] is the sub-list for method input_type
+	15, // [15:15] is the sub-list for extension type_name
+	15, // [15:15] is the sub-list for extension extendee
+	0,  // [0:15] is the sub-list for field type_name
 }
 
 func init() { file_cc_arduino_cli_commands_v1_common_proto_init() }
@@ -1748,6 +1897,30 @@ func file_cc_arduino_cli_commands_v1_common_proto_init() {
 			}
 		}
 		file_cc_arduino_cli_commands_v1_common_proto_msgTypes[16].Exporter = func(v any, i int) any {
+			switch v := v.(*MonitorPortConfiguration); i {
+			case 0:
+				return &v.state
+			case 1:
+				return &v.sizeCache
+			case 2:
+				return &v.unknownFields
+			default:
+				return nil
+			}
+		}
+		file_cc_arduino_cli_commands_v1_common_proto_msgTypes[17].Exporter = func(v any, i int) any {
+			switch v := v.(*MonitorPortSetting); i {
+			case 0:
+				return &v.state
+			case 1:
+				return &v.sizeCache
+			case 2:
+				return &v.unknownFields
+			default:
+				return nil
+			}
+		}
+		file_cc_arduino_cli_commands_v1_common_proto_msgTypes[18].Exporter = func(v any, i int) any {
 			switch v := v.(*SketchProfile); i {
 			case 0:
 				return &v.state
@@ -1771,7 +1944,7 @@ func file_cc_arduino_cli_commands_v1_common_proto_init() {
 			GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
 			RawDescriptor: file_cc_arduino_cli_commands_v1_common_proto_rawDesc,
 			NumEnums:      0,
-			NumMessages:   18,
+			NumMessages:   20,
 			NumExtensions: 0,
 			NumServices:   0,
 		},
diff --git a/rpc/cc/arduino/cli/commands/v1/common.proto b/rpc/cc/arduino/cli/commands/v1/common.proto
index 9e329b535a1..99cd611bfde 100644
--- a/rpc/cc/arduino/cli/commands/v1/common.proto
+++ b/rpc/cc/arduino/cli/commands/v1/common.proto
@@ -204,6 +204,18 @@ message Sketch {
   SketchProfile default_profile = 10;
   // Default Programmer set in project file (sketch.yaml)
   string default_programmer = 11;
+  // Default Port configuration set in project file (sketch.yaml)
+  MonitorPortConfiguration default_port_config = 12;
+}
+
+message MonitorPortConfiguration {
+  // The port configuration parameters
+  repeated MonitorPortSetting settings = 1;
+}
+
+message MonitorPortSetting {
+  string setting_id = 1;
+  string value = 2;
 }
 
 message SketchProfile {
@@ -215,6 +227,8 @@ message SketchProfile {
   string programmer = 3;
   // Default Port in this profile
   string port = 4;
+  // Default Port configuration set in project file (sketch.yaml)
+  MonitorPortConfiguration port_config = 5;
   // Default Protocol in this profile
-  string protocol = 5;
+  string protocol = 6;
 }
diff --git a/rpc/cc/arduino/cli/commands/v1/monitor.pb.go b/rpc/cc/arduino/cli/commands/v1/monitor.pb.go
index d931321480f..7a655956660 100644
--- a/rpc/cc/arduino/cli/commands/v1/monitor.pb.go
+++ b/rpc/cc/arduino/cli/commands/v1/monitor.pb.go
@@ -228,54 +228,6 @@ func (x *MonitorPortOpenRequest) GetPortConfiguration() *MonitorPortConfiguratio
 	return nil
 }
 
-type MonitorPortConfiguration struct {
-	state         protoimpl.MessageState
-	sizeCache     protoimpl.SizeCache
-	unknownFields protoimpl.UnknownFields
-
-	// The port configuration parameters
-	Settings []*MonitorPortSetting `protobuf:"bytes,1,rep,name=settings,proto3" json:"settings,omitempty"`
-}
-
-func (x *MonitorPortConfiguration) Reset() {
-	*x = MonitorPortConfiguration{}
-	if protoimpl.UnsafeEnabled {
-		mi := &file_cc_arduino_cli_commands_v1_monitor_proto_msgTypes[2]
-		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
-		ms.StoreMessageInfo(mi)
-	}
-}
-
-func (x *MonitorPortConfiguration) String() string {
-	return protoimpl.X.MessageStringOf(x)
-}
-
-func (*MonitorPortConfiguration) ProtoMessage() {}
-
-func (x *MonitorPortConfiguration) ProtoReflect() protoreflect.Message {
-	mi := &file_cc_arduino_cli_commands_v1_monitor_proto_msgTypes[2]
-	if protoimpl.UnsafeEnabled && x != nil {
-		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
-		if ms.LoadMessageInfo() == nil {
-			ms.StoreMessageInfo(mi)
-		}
-		return ms
-	}
-	return mi.MessageOf(x)
-}
-
-// Deprecated: Use MonitorPortConfiguration.ProtoReflect.Descriptor instead.
-func (*MonitorPortConfiguration) Descriptor() ([]byte, []int) {
-	return file_cc_arduino_cli_commands_v1_monitor_proto_rawDescGZIP(), []int{2}
-}
-
-func (x *MonitorPortConfiguration) GetSettings() []*MonitorPortSetting {
-	if x != nil {
-		return x.Settings
-	}
-	return nil
-}
-
 type MonitorResponse struct {
 	state         protoimpl.MessageState
 	sizeCache     protoimpl.SizeCache
@@ -293,7 +245,7 @@ type MonitorResponse struct {
 func (x *MonitorResponse) Reset() {
 	*x = MonitorResponse{}
 	if protoimpl.UnsafeEnabled {
-		mi := &file_cc_arduino_cli_commands_v1_monitor_proto_msgTypes[3]
+		mi := &file_cc_arduino_cli_commands_v1_monitor_proto_msgTypes[2]
 		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
 		ms.StoreMessageInfo(mi)
 	}
@@ -306,7 +258,7 @@ func (x *MonitorResponse) String() string {
 func (*MonitorResponse) ProtoMessage() {}
 
 func (x *MonitorResponse) ProtoReflect() protoreflect.Message {
-	mi := &file_cc_arduino_cli_commands_v1_monitor_proto_msgTypes[3]
+	mi := &file_cc_arduino_cli_commands_v1_monitor_proto_msgTypes[2]
 	if protoimpl.UnsafeEnabled && x != nil {
 		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
 		if ms.LoadMessageInfo() == nil {
@@ -319,7 +271,7 @@ func (x *MonitorResponse) ProtoReflect() protoreflect.Message {
 
 // Deprecated: Use MonitorResponse.ProtoReflect.Descriptor instead.
 func (*MonitorResponse) Descriptor() ([]byte, []int) {
-	return file_cc_arduino_cli_commands_v1_monitor_proto_rawDescGZIP(), []int{3}
+	return file_cc_arduino_cli_commands_v1_monitor_proto_rawDescGZIP(), []int{2}
 }
 
 func (m *MonitorResponse) GetMessage() isMonitorResponse_Message {
@@ -392,61 +344,6 @@ func (*MonitorResponse_AppliedSettings) isMonitorResponse_Message() {}
 
 func (*MonitorResponse_Success) isMonitorResponse_Message() {}
 
-type MonitorPortSetting struct {
-	state         protoimpl.MessageState
-	sizeCache     protoimpl.SizeCache
-	unknownFields protoimpl.UnknownFields
-
-	SettingId string `protobuf:"bytes,1,opt,name=setting_id,json=settingId,proto3" json:"setting_id,omitempty"`
-	Value     string `protobuf:"bytes,2,opt,name=value,proto3" json:"value,omitempty"`
-}
-
-func (x *MonitorPortSetting) Reset() {
-	*x = MonitorPortSetting{}
-	if protoimpl.UnsafeEnabled {
-		mi := &file_cc_arduino_cli_commands_v1_monitor_proto_msgTypes[4]
-		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
-		ms.StoreMessageInfo(mi)
-	}
-}
-
-func (x *MonitorPortSetting) String() string {
-	return protoimpl.X.MessageStringOf(x)
-}
-
-func (*MonitorPortSetting) ProtoMessage() {}
-
-func (x *MonitorPortSetting) ProtoReflect() protoreflect.Message {
-	mi := &file_cc_arduino_cli_commands_v1_monitor_proto_msgTypes[4]
-	if protoimpl.UnsafeEnabled && x != nil {
-		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
-		if ms.LoadMessageInfo() == nil {
-			ms.StoreMessageInfo(mi)
-		}
-		return ms
-	}
-	return mi.MessageOf(x)
-}
-
-// Deprecated: Use MonitorPortSetting.ProtoReflect.Descriptor instead.
-func (*MonitorPortSetting) Descriptor() ([]byte, []int) {
-	return file_cc_arduino_cli_commands_v1_monitor_proto_rawDescGZIP(), []int{4}
-}
-
-func (x *MonitorPortSetting) GetSettingId() string {
-	if x != nil {
-		return x.SettingId
-	}
-	return ""
-}
-
-func (x *MonitorPortSetting) GetValue() string {
-	if x != nil {
-		return x.Value
-	}
-	return ""
-}
-
 type EnumerateMonitorPortSettingsRequest struct {
 	state         protoimpl.MessageState
 	sizeCache     protoimpl.SizeCache
@@ -465,7 +362,7 @@ type EnumerateMonitorPortSettingsRequest struct {
 func (x *EnumerateMonitorPortSettingsRequest) Reset() {
 	*x = EnumerateMonitorPortSettingsRequest{}
 	if protoimpl.UnsafeEnabled {
-		mi := &file_cc_arduino_cli_commands_v1_monitor_proto_msgTypes[5]
+		mi := &file_cc_arduino_cli_commands_v1_monitor_proto_msgTypes[3]
 		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
 		ms.StoreMessageInfo(mi)
 	}
@@ -478,7 +375,7 @@ func (x *EnumerateMonitorPortSettingsRequest) String() string {
 func (*EnumerateMonitorPortSettingsRequest) ProtoMessage() {}
 
 func (x *EnumerateMonitorPortSettingsRequest) ProtoReflect() protoreflect.Message {
-	mi := &file_cc_arduino_cli_commands_v1_monitor_proto_msgTypes[5]
+	mi := &file_cc_arduino_cli_commands_v1_monitor_proto_msgTypes[3]
 	if protoimpl.UnsafeEnabled && x != nil {
 		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
 		if ms.LoadMessageInfo() == nil {
@@ -491,7 +388,7 @@ func (x *EnumerateMonitorPortSettingsRequest) ProtoReflect() protoreflect.Messag
 
 // Deprecated: Use EnumerateMonitorPortSettingsRequest.ProtoReflect.Descriptor instead.
 func (*EnumerateMonitorPortSettingsRequest) Descriptor() ([]byte, []int) {
-	return file_cc_arduino_cli_commands_v1_monitor_proto_rawDescGZIP(), []int{5}
+	return file_cc_arduino_cli_commands_v1_monitor_proto_rawDescGZIP(), []int{3}
 }
 
 func (x *EnumerateMonitorPortSettingsRequest) GetInstance() *Instance {
@@ -528,7 +425,7 @@ type EnumerateMonitorPortSettingsResponse struct {
 func (x *EnumerateMonitorPortSettingsResponse) Reset() {
 	*x = EnumerateMonitorPortSettingsResponse{}
 	if protoimpl.UnsafeEnabled {
-		mi := &file_cc_arduino_cli_commands_v1_monitor_proto_msgTypes[6]
+		mi := &file_cc_arduino_cli_commands_v1_monitor_proto_msgTypes[4]
 		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
 		ms.StoreMessageInfo(mi)
 	}
@@ -541,7 +438,7 @@ func (x *EnumerateMonitorPortSettingsResponse) String() string {
 func (*EnumerateMonitorPortSettingsResponse) ProtoMessage() {}
 
 func (x *EnumerateMonitorPortSettingsResponse) ProtoReflect() protoreflect.Message {
-	mi := &file_cc_arduino_cli_commands_v1_monitor_proto_msgTypes[6]
+	mi := &file_cc_arduino_cli_commands_v1_monitor_proto_msgTypes[4]
 	if protoimpl.UnsafeEnabled && x != nil {
 		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
 		if ms.LoadMessageInfo() == nil {
@@ -554,7 +451,7 @@ func (x *EnumerateMonitorPortSettingsResponse) ProtoReflect() protoreflect.Messa
 
 // Deprecated: Use EnumerateMonitorPortSettingsResponse.ProtoReflect.Descriptor instead.
 func (*EnumerateMonitorPortSettingsResponse) Descriptor() ([]byte, []int) {
-	return file_cc_arduino_cli_commands_v1_monitor_proto_rawDescGZIP(), []int{6}
+	return file_cc_arduino_cli_commands_v1_monitor_proto_rawDescGZIP(), []int{4}
 }
 
 func (x *EnumerateMonitorPortSettingsResponse) GetSettings() []*MonitorPortSettingDescriptor {
@@ -584,7 +481,7 @@ type MonitorPortSettingDescriptor struct {
 func (x *MonitorPortSettingDescriptor) Reset() {
 	*x = MonitorPortSettingDescriptor{}
 	if protoimpl.UnsafeEnabled {
-		mi := &file_cc_arduino_cli_commands_v1_monitor_proto_msgTypes[7]
+		mi := &file_cc_arduino_cli_commands_v1_monitor_proto_msgTypes[5]
 		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
 		ms.StoreMessageInfo(mi)
 	}
@@ -597,7 +494,7 @@ func (x *MonitorPortSettingDescriptor) String() string {
 func (*MonitorPortSettingDescriptor) ProtoMessage() {}
 
 func (x *MonitorPortSettingDescriptor) ProtoReflect() protoreflect.Message {
-	mi := &file_cc_arduino_cli_commands_v1_monitor_proto_msgTypes[7]
+	mi := &file_cc_arduino_cli_commands_v1_monitor_proto_msgTypes[5]
 	if protoimpl.UnsafeEnabled && x != nil {
 		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
 		if ms.LoadMessageInfo() == nil {
@@ -610,7 +507,7 @@ func (x *MonitorPortSettingDescriptor) ProtoReflect() protoreflect.Message {
 
 // Deprecated: Use MonitorPortSettingDescriptor.ProtoReflect.Descriptor instead.
 func (*MonitorPortSettingDescriptor) Descriptor() ([]byte, []int) {
-	return file_cc_arduino_cli_commands_v1_monitor_proto_rawDescGZIP(), []int{7}
+	return file_cc_arduino_cli_commands_v1_monitor_proto_rawDescGZIP(), []int{5}
 }
 
 func (x *MonitorPortSettingDescriptor) GetSettingId() string {
@@ -694,65 +591,53 @@ var file_cc_arduino_cli_commands_v1_monitor_proto_rawDesc = []byte{
 	0x69, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x4d, 0x6f,
 	0x6e, 0x69, 0x74, 0x6f, 0x72, 0x50, 0x6f, 0x72, 0x74, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75,
 	0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x11, 0x70, 0x6f, 0x72, 0x74, 0x43, 0x6f, 0x6e, 0x66,
-	0x69, 0x67, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0x66, 0x0a, 0x18, 0x4d, 0x6f, 0x6e,
-	0x69, 0x74, 0x6f, 0x72, 0x50, 0x6f, 0x72, 0x74, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72,
-	0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x4a, 0x0a, 0x08, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67,
-	0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2e, 0x2e, 0x63, 0x63, 0x2e, 0x61, 0x72, 0x64,
-	0x75, 0x69, 0x6e, 0x6f, 0x2e, 0x63, 0x6c, 0x69, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64,
-	0x73, 0x2e, 0x76, 0x31, 0x2e, 0x4d, 0x6f, 0x6e, 0x69, 0x74, 0x6f, 0x72, 0x50, 0x6f, 0x72, 0x74,
-	0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x52, 0x08, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67,
-	0x73, 0x22, 0xce, 0x01, 0x0a, 0x0f, 0x4d, 0x6f, 0x6e, 0x69, 0x74, 0x6f, 0x72, 0x52, 0x65, 0x73,
-	0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x16, 0x0a, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x18, 0x01,
-	0x20, 0x01, 0x28, 0x09, 0x48, 0x00, 0x52, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x12, 0x19, 0x0a,
-	0x07, 0x72, 0x78, 0x5f, 0x64, 0x61, 0x74, 0x61, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x48, 0x00,
-	0x52, 0x06, 0x72, 0x78, 0x44, 0x61, 0x74, 0x61, 0x12, 0x61, 0x0a, 0x10, 0x61, 0x70, 0x70, 0x6c,
-	0x69, 0x65, 0x64, 0x5f, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x18, 0x03, 0x20, 0x01,
-	0x28, 0x0b, 0x32, 0x34, 0x2e, 0x63, 0x63, 0x2e, 0x61, 0x72, 0x64, 0x75, 0x69, 0x6e, 0x6f, 0x2e,
-	0x63, 0x6c, 0x69, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x73, 0x2e, 0x76, 0x31, 0x2e,
-	0x4d, 0x6f, 0x6e, 0x69, 0x74, 0x6f, 0x72, 0x50, 0x6f, 0x72, 0x74, 0x43, 0x6f, 0x6e, 0x66, 0x69,
-	0x67, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x48, 0x00, 0x52, 0x0f, 0x61, 0x70, 0x70, 0x6c,
-	0x69, 0x65, 0x64, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x12, 0x1a, 0x0a, 0x07, 0x73,
-	0x75, 0x63, 0x63, 0x65, 0x73, 0x73, 0x18, 0x04, 0x20, 0x01, 0x28, 0x08, 0x48, 0x00, 0x52, 0x07,
-	0x73, 0x75, 0x63, 0x63, 0x65, 0x73, 0x73, 0x42, 0x09, 0x0a, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61,
-	0x67, 0x65, 0x22, 0x49, 0x0a, 0x12, 0x4d, 0x6f, 0x6e, 0x69, 0x74, 0x6f, 0x72, 0x50, 0x6f, 0x72,
-	0x74, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x12, 0x1d, 0x0a, 0x0a, 0x73, 0x65, 0x74, 0x74,
-	0x69, 0x6e, 0x67, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x73, 0x65,
-	0x74, 0x74, 0x69, 0x6e, 0x67, 0x49, 0x64, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65,
-	0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x22, 0xa0, 0x01,
-	0x0a, 0x23, 0x45, 0x6e, 0x75, 0x6d, 0x65, 0x72, 0x61, 0x74, 0x65, 0x4d, 0x6f, 0x6e, 0x69, 0x74,
-	0x6f, 0x72, 0x50, 0x6f, 0x72, 0x74, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x52, 0x65,
-	0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x40, 0x0a, 0x08, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63,
-	0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x63, 0x63, 0x2e, 0x61, 0x72, 0x64,
-	0x75, 0x69, 0x6e, 0x6f, 0x2e, 0x63, 0x6c, 0x69, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64,
-	0x73, 0x2e, 0x76, 0x31, 0x2e, 0x49, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x52, 0x08, 0x69,
-	0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x12, 0x23, 0x0a, 0x0d, 0x70, 0x6f, 0x72, 0x74, 0x5f,
-	0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c,
-	0x70, 0x6f, 0x72, 0x74, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x12, 0x12, 0x0a, 0x04,
-	0x66, 0x71, 0x62, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x66, 0x71, 0x62, 0x6e,
-	0x22, 0x7c, 0x0a, 0x24, 0x45, 0x6e, 0x75, 0x6d, 0x65, 0x72, 0x61, 0x74, 0x65, 0x4d, 0x6f, 0x6e,
-	0x69, 0x74, 0x6f, 0x72, 0x50, 0x6f, 0x72, 0x74, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73,
-	0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x54, 0x0a, 0x08, 0x73, 0x65, 0x74, 0x74,
-	0x69, 0x6e, 0x67, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x38, 0x2e, 0x63, 0x63, 0x2e,
+	0x69, 0x67, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0xce, 0x01, 0x0a, 0x0f, 0x4d, 0x6f,
+	0x6e, 0x69, 0x74, 0x6f, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x16, 0x0a,
+	0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x48, 0x00, 0x52, 0x05,
+	0x65, 0x72, 0x72, 0x6f, 0x72, 0x12, 0x19, 0x0a, 0x07, 0x72, 0x78, 0x5f, 0x64, 0x61, 0x74, 0x61,
+	0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x48, 0x00, 0x52, 0x06, 0x72, 0x78, 0x44, 0x61, 0x74, 0x61,
+	0x12, 0x61, 0x0a, 0x10, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x65, 0x64, 0x5f, 0x73, 0x65, 0x74, 0x74,
+	0x69, 0x6e, 0x67, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x34, 0x2e, 0x63, 0x63, 0x2e,
 	0x61, 0x72, 0x64, 0x75, 0x69, 0x6e, 0x6f, 0x2e, 0x63, 0x6c, 0x69, 0x2e, 0x63, 0x6f, 0x6d, 0x6d,
 	0x61, 0x6e, 0x64, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x4d, 0x6f, 0x6e, 0x69, 0x74, 0x6f, 0x72, 0x50,
-	0x6f, 0x72, 0x74, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69,
-	0x70, 0x74, 0x6f, 0x72, 0x52, 0x08, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x22, 0x9e,
-	0x01, 0x0a, 0x1c, 0x4d, 0x6f, 0x6e, 0x69, 0x74, 0x6f, 0x72, 0x50, 0x6f, 0x72, 0x74, 0x53, 0x65,
-	0x74, 0x74, 0x69, 0x6e, 0x67, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x6f, 0x72, 0x12,
-	0x1d, 0x0a, 0x0a, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20,
-	0x01, 0x28, 0x09, 0x52, 0x09, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x49, 0x64, 0x12, 0x14,
-	0x0a, 0x05, 0x6c, 0x61, 0x62, 0x65, 0x6c, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x6c,
-	0x61, 0x62, 0x65, 0x6c, 0x12, 0x12, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x03, 0x20, 0x01,
-	0x28, 0x09, 0x52, 0x04, 0x74, 0x79, 0x70, 0x65, 0x12, 0x1f, 0x0a, 0x0b, 0x65, 0x6e, 0x75, 0x6d,
-	0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0a, 0x65,
-	0x6e, 0x75, 0x6d, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c,
-	0x75, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x42,
-	0x48, 0x5a, 0x46, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x61, 0x72,
-	0x64, 0x75, 0x69, 0x6e, 0x6f, 0x2f, 0x61, 0x72, 0x64, 0x75, 0x69, 0x6e, 0x6f, 0x2d, 0x63, 0x6c,
-	0x69, 0x2f, 0x72, 0x70, 0x63, 0x2f, 0x63, 0x63, 0x2f, 0x61, 0x72, 0x64, 0x75, 0x69, 0x6e, 0x6f,
-	0x2f, 0x63, 0x6c, 0x69, 0x2f, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x73, 0x2f, 0x76, 0x31,
-	0x3b, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x73, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f,
-	0x33,
+	0x6f, 0x72, 0x74, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e,
+	0x48, 0x00, 0x52, 0x0f, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x65, 0x64, 0x53, 0x65, 0x74, 0x74, 0x69,
+	0x6e, 0x67, 0x73, 0x12, 0x1a, 0x0a, 0x07, 0x73, 0x75, 0x63, 0x63, 0x65, 0x73, 0x73, 0x18, 0x04,
+	0x20, 0x01, 0x28, 0x08, 0x48, 0x00, 0x52, 0x07, 0x73, 0x75, 0x63, 0x63, 0x65, 0x73, 0x73, 0x42,
+	0x09, 0x0a, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x22, 0xa0, 0x01, 0x0a, 0x23, 0x45,
+	0x6e, 0x75, 0x6d, 0x65, 0x72, 0x61, 0x74, 0x65, 0x4d, 0x6f, 0x6e, 0x69, 0x74, 0x6f, 0x72, 0x50,
+	0x6f, 0x72, 0x74, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65,
+	0x73, 0x74, 0x12, 0x40, 0x0a, 0x08, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x18, 0x01,
+	0x20, 0x01, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x63, 0x63, 0x2e, 0x61, 0x72, 0x64, 0x75, 0x69, 0x6e,
+	0x6f, 0x2e, 0x63, 0x6c, 0x69, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x73, 0x2e, 0x76,
+	0x31, 0x2e, 0x49, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x52, 0x08, 0x69, 0x6e, 0x73, 0x74,
+	0x61, 0x6e, 0x63, 0x65, 0x12, 0x23, 0x0a, 0x0d, 0x70, 0x6f, 0x72, 0x74, 0x5f, 0x70, 0x72, 0x6f,
+	0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x70, 0x6f, 0x72,
+	0x74, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x12, 0x12, 0x0a, 0x04, 0x66, 0x71, 0x62,
+	0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x66, 0x71, 0x62, 0x6e, 0x22, 0x7c, 0x0a,
+	0x24, 0x45, 0x6e, 0x75, 0x6d, 0x65, 0x72, 0x61, 0x74, 0x65, 0x4d, 0x6f, 0x6e, 0x69, 0x74, 0x6f,
+	0x72, 0x50, 0x6f, 0x72, 0x74, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x52, 0x65, 0x73,
+	0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x54, 0x0a, 0x08, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67,
+	0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x38, 0x2e, 0x63, 0x63, 0x2e, 0x61, 0x72, 0x64,
+	0x75, 0x69, 0x6e, 0x6f, 0x2e, 0x63, 0x6c, 0x69, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64,
+	0x73, 0x2e, 0x76, 0x31, 0x2e, 0x4d, 0x6f, 0x6e, 0x69, 0x74, 0x6f, 0x72, 0x50, 0x6f, 0x72, 0x74,
+	0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x6f,
+	0x72, 0x52, 0x08, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x22, 0x9e, 0x01, 0x0a, 0x1c,
+	0x4d, 0x6f, 0x6e, 0x69, 0x74, 0x6f, 0x72, 0x50, 0x6f, 0x72, 0x74, 0x53, 0x65, 0x74, 0x74, 0x69,
+	0x6e, 0x67, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x6f, 0x72, 0x12, 0x1d, 0x0a, 0x0a,
+	0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09,
+	0x52, 0x09, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x49, 0x64, 0x12, 0x14, 0x0a, 0x05, 0x6c,
+	0x61, 0x62, 0x65, 0x6c, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x6c, 0x61, 0x62, 0x65,
+	0x6c, 0x12, 0x12, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52,
+	0x04, 0x74, 0x79, 0x70, 0x65, 0x12, 0x1f, 0x0a, 0x0b, 0x65, 0x6e, 0x75, 0x6d, 0x5f, 0x76, 0x61,
+	0x6c, 0x75, 0x65, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0a, 0x65, 0x6e, 0x75, 0x6d,
+	0x56, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18,
+	0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x42, 0x48, 0x5a, 0x46,
+	0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x61, 0x72, 0x64, 0x75, 0x69,
+	0x6e, 0x6f, 0x2f, 0x61, 0x72, 0x64, 0x75, 0x69, 0x6e, 0x6f, 0x2d, 0x63, 0x6c, 0x69, 0x2f, 0x72,
+	0x70, 0x63, 0x2f, 0x63, 0x63, 0x2f, 0x61, 0x72, 0x64, 0x75, 0x69, 0x6e, 0x6f, 0x2f, 0x63, 0x6c,
+	0x69, 0x2f, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x73, 0x2f, 0x76, 0x31, 0x3b, 0x63, 0x6f,
+	0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x73, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
 }
 
 var (
@@ -767,34 +652,32 @@ func file_cc_arduino_cli_commands_v1_monitor_proto_rawDescGZIP() []byte {
 	return file_cc_arduino_cli_commands_v1_monitor_proto_rawDescData
 }
 
-var file_cc_arduino_cli_commands_v1_monitor_proto_msgTypes = make([]protoimpl.MessageInfo, 8)
+var file_cc_arduino_cli_commands_v1_monitor_proto_msgTypes = make([]protoimpl.MessageInfo, 6)
 var file_cc_arduino_cli_commands_v1_monitor_proto_goTypes = []any{
 	(*MonitorRequest)(nil),                       // 0: cc.arduino.cli.commands.v1.MonitorRequest
 	(*MonitorPortOpenRequest)(nil),               // 1: cc.arduino.cli.commands.v1.MonitorPortOpenRequest
-	(*MonitorPortConfiguration)(nil),             // 2: cc.arduino.cli.commands.v1.MonitorPortConfiguration
-	(*MonitorResponse)(nil),                      // 3: cc.arduino.cli.commands.v1.MonitorResponse
-	(*MonitorPortSetting)(nil),                   // 4: cc.arduino.cli.commands.v1.MonitorPortSetting
-	(*EnumerateMonitorPortSettingsRequest)(nil),  // 5: cc.arduino.cli.commands.v1.EnumerateMonitorPortSettingsRequest
-	(*EnumerateMonitorPortSettingsResponse)(nil), // 6: cc.arduino.cli.commands.v1.EnumerateMonitorPortSettingsResponse
-	(*MonitorPortSettingDescriptor)(nil),         // 7: cc.arduino.cli.commands.v1.MonitorPortSettingDescriptor
-	(*Instance)(nil),                             // 8: cc.arduino.cli.commands.v1.Instance
-	(*Port)(nil),                                 // 9: cc.arduino.cli.commands.v1.Port
+	(*MonitorResponse)(nil),                      // 2: cc.arduino.cli.commands.v1.MonitorResponse
+	(*EnumerateMonitorPortSettingsRequest)(nil),  // 3: cc.arduino.cli.commands.v1.EnumerateMonitorPortSettingsRequest
+	(*EnumerateMonitorPortSettingsResponse)(nil), // 4: cc.arduino.cli.commands.v1.EnumerateMonitorPortSettingsResponse
+	(*MonitorPortSettingDescriptor)(nil),         // 5: cc.arduino.cli.commands.v1.MonitorPortSettingDescriptor
+	(*MonitorPortConfiguration)(nil),             // 6: cc.arduino.cli.commands.v1.MonitorPortConfiguration
+	(*Instance)(nil),                             // 7: cc.arduino.cli.commands.v1.Instance
+	(*Port)(nil),                                 // 8: cc.arduino.cli.commands.v1.Port
 }
 var file_cc_arduino_cli_commands_v1_monitor_proto_depIdxs = []int32{
 	1, // 0: cc.arduino.cli.commands.v1.MonitorRequest.open_request:type_name -> cc.arduino.cli.commands.v1.MonitorPortOpenRequest
-	2, // 1: cc.arduino.cli.commands.v1.MonitorRequest.updated_configuration:type_name -> cc.arduino.cli.commands.v1.MonitorPortConfiguration
-	8, // 2: cc.arduino.cli.commands.v1.MonitorPortOpenRequest.instance:type_name -> cc.arduino.cli.commands.v1.Instance
-	9, // 3: cc.arduino.cli.commands.v1.MonitorPortOpenRequest.port:type_name -> cc.arduino.cli.commands.v1.Port
-	2, // 4: cc.arduino.cli.commands.v1.MonitorPortOpenRequest.port_configuration:type_name -> cc.arduino.cli.commands.v1.MonitorPortConfiguration
-	4, // 5: cc.arduino.cli.commands.v1.MonitorPortConfiguration.settings:type_name -> cc.arduino.cli.commands.v1.MonitorPortSetting
-	2, // 6: cc.arduino.cli.commands.v1.MonitorResponse.applied_settings:type_name -> cc.arduino.cli.commands.v1.MonitorPortConfiguration
-	8, // 7: cc.arduino.cli.commands.v1.EnumerateMonitorPortSettingsRequest.instance:type_name -> cc.arduino.cli.commands.v1.Instance
-	7, // 8: cc.arduino.cli.commands.v1.EnumerateMonitorPortSettingsResponse.settings:type_name -> cc.arduino.cli.commands.v1.MonitorPortSettingDescriptor
-	9, // [9:9] is the sub-list for method output_type
-	9, // [9:9] is the sub-list for method input_type
-	9, // [9:9] is the sub-list for extension type_name
-	9, // [9:9] is the sub-list for extension extendee
-	0, // [0:9] is the sub-list for field type_name
+	6, // 1: cc.arduino.cli.commands.v1.MonitorRequest.updated_configuration:type_name -> cc.arduino.cli.commands.v1.MonitorPortConfiguration
+	7, // 2: cc.arduino.cli.commands.v1.MonitorPortOpenRequest.instance:type_name -> cc.arduino.cli.commands.v1.Instance
+	8, // 3: cc.arduino.cli.commands.v1.MonitorPortOpenRequest.port:type_name -> cc.arduino.cli.commands.v1.Port
+	6, // 4: cc.arduino.cli.commands.v1.MonitorPortOpenRequest.port_configuration:type_name -> cc.arduino.cli.commands.v1.MonitorPortConfiguration
+	6, // 5: cc.arduino.cli.commands.v1.MonitorResponse.applied_settings:type_name -> cc.arduino.cli.commands.v1.MonitorPortConfiguration
+	7, // 6: cc.arduino.cli.commands.v1.EnumerateMonitorPortSettingsRequest.instance:type_name -> cc.arduino.cli.commands.v1.Instance
+	5, // 7: cc.arduino.cli.commands.v1.EnumerateMonitorPortSettingsResponse.settings:type_name -> cc.arduino.cli.commands.v1.MonitorPortSettingDescriptor
+	8, // [8:8] is the sub-list for method output_type
+	8, // [8:8] is the sub-list for method input_type
+	8, // [8:8] is the sub-list for extension type_name
+	8, // [8:8] is the sub-list for extension extendee
+	0, // [0:8] is the sub-list for field type_name
 }
 
 func init() { file_cc_arduino_cli_commands_v1_monitor_proto_init() }
@@ -830,18 +713,6 @@ func file_cc_arduino_cli_commands_v1_monitor_proto_init() {
 			}
 		}
 		file_cc_arduino_cli_commands_v1_monitor_proto_msgTypes[2].Exporter = func(v any, i int) any {
-			switch v := v.(*MonitorPortConfiguration); i {
-			case 0:
-				return &v.state
-			case 1:
-				return &v.sizeCache
-			case 2:
-				return &v.unknownFields
-			default:
-				return nil
-			}
-		}
-		file_cc_arduino_cli_commands_v1_monitor_proto_msgTypes[3].Exporter = func(v any, i int) any {
 			switch v := v.(*MonitorResponse); i {
 			case 0:
 				return &v.state
@@ -853,19 +724,7 @@ func file_cc_arduino_cli_commands_v1_monitor_proto_init() {
 				return nil
 			}
 		}
-		file_cc_arduino_cli_commands_v1_monitor_proto_msgTypes[4].Exporter = func(v any, i int) any {
-			switch v := v.(*MonitorPortSetting); i {
-			case 0:
-				return &v.state
-			case 1:
-				return &v.sizeCache
-			case 2:
-				return &v.unknownFields
-			default:
-				return nil
-			}
-		}
-		file_cc_arduino_cli_commands_v1_monitor_proto_msgTypes[5].Exporter = func(v any, i int) any {
+		file_cc_arduino_cli_commands_v1_monitor_proto_msgTypes[3].Exporter = func(v any, i int) any {
 			switch v := v.(*EnumerateMonitorPortSettingsRequest); i {
 			case 0:
 				return &v.state
@@ -877,7 +736,7 @@ func file_cc_arduino_cli_commands_v1_monitor_proto_init() {
 				return nil
 			}
 		}
-		file_cc_arduino_cli_commands_v1_monitor_proto_msgTypes[6].Exporter = func(v any, i int) any {
+		file_cc_arduino_cli_commands_v1_monitor_proto_msgTypes[4].Exporter = func(v any, i int) any {
 			switch v := v.(*EnumerateMonitorPortSettingsResponse); i {
 			case 0:
 				return &v.state
@@ -889,7 +748,7 @@ func file_cc_arduino_cli_commands_v1_monitor_proto_init() {
 				return nil
 			}
 		}
-		file_cc_arduino_cli_commands_v1_monitor_proto_msgTypes[7].Exporter = func(v any, i int) any {
+		file_cc_arduino_cli_commands_v1_monitor_proto_msgTypes[5].Exporter = func(v any, i int) any {
 			switch v := v.(*MonitorPortSettingDescriptor); i {
 			case 0:
 				return &v.state
@@ -908,7 +767,7 @@ func file_cc_arduino_cli_commands_v1_monitor_proto_init() {
 		(*MonitorRequest_UpdatedConfiguration)(nil),
 		(*MonitorRequest_Close)(nil),
 	}
-	file_cc_arduino_cli_commands_v1_monitor_proto_msgTypes[3].OneofWrappers = []any{
+	file_cc_arduino_cli_commands_v1_monitor_proto_msgTypes[2].OneofWrappers = []any{
 		(*MonitorResponse_Error)(nil),
 		(*MonitorResponse_RxData)(nil),
 		(*MonitorResponse_AppliedSettings)(nil),
@@ -920,7 +779,7 @@ func file_cc_arduino_cli_commands_v1_monitor_proto_init() {
 			GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
 			RawDescriptor: file_cc_arduino_cli_commands_v1_monitor_proto_rawDesc,
 			NumEnums:      0,
-			NumMessages:   8,
+			NumMessages:   6,
 			NumExtensions: 0,
 			NumServices:   0,
 		},
diff --git a/rpc/cc/arduino/cli/commands/v1/monitor.proto b/rpc/cc/arduino/cli/commands/v1/monitor.proto
index a7bffc1431f..a15cc490849 100644
--- a/rpc/cc/arduino/cli/commands/v1/monitor.proto
+++ b/rpc/cc/arduino/cli/commands/v1/monitor.proto
@@ -51,11 +51,6 @@ message MonitorPortOpenRequest {
   MonitorPortConfiguration port_configuration = 4;
 }
 
-message MonitorPortConfiguration {
-  // The port configuration parameters
-  repeated MonitorPortSetting settings = 1;
-}
-
 message MonitorResponse {
   oneof message {
     // Eventual errors dealing with monitor port
@@ -72,11 +67,6 @@ message MonitorResponse {
   }
 }
 
-message MonitorPortSetting {
-  string setting_id = 1;
-  string value = 2;
-}
-
 message EnumerateMonitorPortSettingsRequest {
   // Arduino Core Service instance from the `Init` response.
   Instance instance = 1;

From 59af89d66975e17c1a0701ad900840199cd51ea4 Mon Sep 17 00:00:00 2001
From: Cristian Maglie <c.maglie@arduino.cc>
Date: Thu, 3 Oct 2024 21:38:50 +0200
Subject: [PATCH 4/8] Allow port configuration from sketch profile

---
 internal/cli/monitor/monitor.go | 112 ++++++++++++++++++--------------
 1 file changed, 65 insertions(+), 47 deletions(-)

diff --git a/internal/cli/monitor/monitor.go b/internal/cli/monitor/monitor.go
index e0cc0ffde41..39c2ed5d320 100644
--- a/internal/cli/monitor/monitor.go
+++ b/internal/cli/monitor/monitor.go
@@ -17,6 +17,7 @@ package monitor
 
 import (
 	"bytes"
+	"cmp"
 	"context"
 	"errors"
 	"io"
@@ -163,50 +164,52 @@ func runMonitorCmd(
 		return
 	}
 
-	actualConfigurationLabels := properties.NewMap()
-	for _, setting := range defaultSettings.GetSettings() {
-		actualConfigurationLabels.Set(setting.GetSettingId(), setting.GetValue())
-	}
-
-	configuration := &rpc.MonitorPortConfiguration{}
-	if len(configs) > 0 {
-		for _, config := range configs {
-			split := strings.SplitN(config, "=", 2)
-			k := ""
-			v := config
-			if len(split) == 2 {
-				k = split[0]
-				v = split[1]
-			}
-
-			var setting *rpc.MonitorPortSettingDescriptor
-			for _, s := range defaultSettings.GetSettings() {
-				if k == "" {
-					if contains(s.GetEnumValues(), v) {
-						setting = s
-						break
-					}
-				} else {
-					if strings.EqualFold(s.GetSettingId(), k) {
-						if !contains(s.GetEnumValues(), v) {
-							feedback.Fatal(i18n.Tr("invalid port configuration value for %s: %s", k, v), feedback.ErrBadArgument)
-						}
-						setting = s
-						break
+	// This utility finds the settings descriptor from key/value or only from key.
+	// It fails fatal if the key or value are invalid.
+	searchSettingDescriptor := func(k, v string) *rpc.MonitorPortSettingDescriptor {
+		for _, s := range defaultSettings.GetSettings() {
+			if k == "" {
+				if contains(s.GetEnumValues(), v) {
+					return s
+				}
+			} else {
+				if strings.EqualFold(s.GetSettingId(), k) {
+					if !contains(s.GetEnumValues(), v) {
+						feedback.Fatal(i18n.Tr("invalid port configuration value for %s: %s", k, v), feedback.ErrBadArgument)
 					}
+					return s
 				}
 			}
-			if setting == nil {
-				feedback.Fatal(i18n.Tr("invalid port configuration: %s", config), feedback.ErrBadArgument)
-			}
-			configuration.Settings = append(configuration.GetSettings(), &rpc.MonitorPortSetting{
-				SettingId: setting.GetSettingId(),
-				Value:     v,
-			})
-			actualConfigurationLabels.Set(setting.GetSettingId(), v)
 		}
+		feedback.Fatal(i18n.Tr("invalid port configuration: %s=%s", k, v), feedback.ErrBadArgument)
+		return nil
+	}
+
+	// Build configuration by layering
+	layeredPortConfig := properties.NewMap()
+	setConfig := func(k, v string) {
+		settingDesc := searchSettingDescriptor(k, v)
+		layeredPortConfig.Set(settingDesc.GetSettingId(), v)
 	}
 
+	// Layer 1: apply configuration from sketch profile...
+	profileConfig := profile.GetPortConfig()
+	if profileConfig == nil {
+		// ...or from sketch default...
+		profileConfig = sketch.GetDefaultPortConfig()
+	}
+	for _, setting := range profileConfig.GetSettings() {
+		setConfig(setting.SettingId, setting.Value)
+	}
+
+	// Layer 2: apply configuration from command line...
+	for _, config := range configs {
+		if split := strings.SplitN(config, "=", 2); len(split) == 2 {
+			setConfig(split[0], split[1])
+		} else {
+			setConfig("", config)
+		}
+	}
 	ttyIn, ttyOut, err := feedback.InteractiveStreams()
 	if err != nil {
 		feedback.FatalError(err, feedback.ErrGeneric)
@@ -233,15 +236,24 @@ func runMonitorCmd(
 		}
 		ttyIn = io.TeeReader(ttyIn, ctrlCDetector)
 	}
+	var portConfiguration []*rpc.MonitorPortSetting
+	for k, v := range layeredPortConfig.AsMap() {
+		portConfiguration = append(portConfiguration, &rpc.MonitorPortSetting{
+			SettingId: k,
+			Value:     v,
+		})
+	}
 	monitorServer, portProxy := commands.MonitorServerToReadWriteCloser(ctx, &rpc.MonitorPortOpenRequest{
-		Instance:          inst,
-		Port:              &rpc.Port{Address: portAddress, Protocol: portProtocol},
-		Fqbn:              fqbn,
-		PortConfiguration: configuration,
+		Instance: inst,
+		Port:     &rpc.Port{Address: portAddress, Protocol: portProtocol},
+		Fqbn:     fqbn,
+		PortConfiguration: &rpc.MonitorPortConfiguration{
+			Settings: portConfiguration,
+		},
 	})
 	go func() {
 		if !quiet {
-			if len(configs) == 0 {
+			if layeredPortConfig.Size() == 0 {
 				if fqbn != "" {
 					feedback.Print(i18n.Tr("Using default monitor configuration for board: %s", fqbn))
 				} else if portProtocol == "serial" {
@@ -249,10 +261,16 @@ func runMonitorCmd(
 				}
 			}
 			feedback.Print(i18n.Tr("Monitor port settings:"))
-			keys := actualConfigurationLabels.Keys()
-			slices.Sort(keys)
-			for _, k := range keys {
-				feedback.Printf("  %s=%s", k, actualConfigurationLabels.Get(k))
+			slices.SortFunc(defaultSettings.GetSettings(), func(a, b *rpc.MonitorPortSettingDescriptor) int {
+				return cmp.Compare(a.GetSettingId(), b.GetSettingId())
+			})
+			for _, defaultSetting := range defaultSettings.GetSettings() {
+				k := defaultSetting.GetSettingId()
+				v, ok := layeredPortConfig.GetOk(k)
+				if !ok {
+					v = defaultSetting.GetValue()
+				}
+				feedback.Printf("  %s=%s", k, v)
 			}
 			feedback.Print("")
 

From 0271d36d9f6bc8831d020e9dfbeeccee5675481c Mon Sep 17 00:00:00 2001
From: Cristian Maglie <c.maglie@arduino.cc>
Date: Thu, 3 Oct 2024 22:58:16 +0200
Subject: [PATCH 5/8] Added docs

---
 docs/sketch-project-file.md | 26 ++++++++++++++++++++++++--
 1 file changed, 24 insertions(+), 2 deletions(-)

diff --git a/docs/sketch-project-file.md b/docs/sketch-project-file.md
index 896e66eb16a..1660bba9f1b 100644
--- a/docs/sketch-project-file.md
+++ b/docs/sketch-project-file.md
@@ -15,6 +15,7 @@ Each profile will define:
 - A possible core platform name and version, that is a dependency of the target core platform (with the 3rd party
   platform index URL if needed)
 - The libraries used in the sketch (including their version)
+- The port and protocol to upload the sketch and monitor the board
 
 The format of the file is the following:
 
@@ -33,7 +34,11 @@ profiles:
       - <LIB_NAME> (<LIB_VERSION>)
       - <LIB_NAME> (<LIB_VERSION>)
       - <LIB_NAME> (<LIB_VERSION>)
-
+    port: <PORT_NAME>
+    port_config:
+      <PORT_SETTING_NAME>: <PORT_SETTING_VALUE>
+      ...
+    protocol: <PORT_PROTOCOL>
   ...more profiles here...
 ```
 
@@ -54,6 +59,15 @@ otherwise below). The available fields are:
 - `<USER_NOTES>` is a free text string available to the developer to add comments. This field is optional.
 - `<PROGRAMMER>` is the programmer that will be used. This field is optional.
 
+The following fields are available since Arduino CLI 1.1.0:
+
+- `<PORT_NAME>` is the port that will be used to upload and monitor the board (unless explicitly set otherwise). This
+  field is optional.
+- `port_config` section with `<PORT_SETTING_NAME>` and `<PORT_SETTING_VALUE>` defines the port settings that will be
+  used in the `monitor` command. Typically is used to set the baudrate for the serial port (for example
+  `baudrate: 115200`) but any setting/value can be specified. Multiple settings can be set. These fields are optional.
+- `<PORT_PROTOCOL>` is the protocol for the port used to upload and monitor the board. This field is optional.
+
 A complete example of a sketch project file may be the following:
 
 ```
@@ -76,6 +90,9 @@ profiles:
       - VitconMQTT (1.0.1)
       - Arduino_ConnectionHandler (0.6.4)
       - TinyDHT sensor library (1.1.0)
+    port: /dev/ttyACM0
+    port_config:
+      baudrate: 115200
 
   tiny:
     notes: testing the very limit of the AVR platform, it will be very unstable
@@ -139,6 +156,8 @@ particular:
 - The `default_fqbn` key sets the default value for the `--fqbn` flag
 - The `default_programmer` key sets the default value for the `--programmer` flag
 - The `default_port` key sets the default value for the `--port` flag
+- The `default_port_config` key sets the default values for the `--config` flag in the `monitor` command (available
+  since Arduino CLI 1.1.0)
 - The `default_protocol` key sets the default value for the `--protocol` flag
 - The `default_profile` key sets the default value for the `--profile` flag
 
@@ -148,6 +167,8 @@ For example:
 default_fqbn: arduino:samd:mkr1000
 default_programmer: atmel_ice
 default_port: /dev/ttyACM0
+default_port_config:
+  baudrate: 115200
 default_protocol: serial
 default_profile: myprofile
 ```
@@ -155,4 +176,5 @@ default_profile: myprofile
 With this configuration set, it is not necessary to specify the `--fqbn`, `--programmer`, `--port`, `--protocol` or
 `--profile` flags to the [`arduino-cli compile`](commands/arduino-cli_compile.md),
 [`arduino-cli upload`](commands/arduino-cli_upload.md) or [`arduino-cli debug`](commands/arduino-cli_debug.md) commands
-when compiling, uploading or debugging the sketch.
+when compiling, uploading or debugging the sketch. Moreover in the `monitor` command it is not necessary to specify the
+`--config baudrate=115200` to communicate with the monitor port of the board.

From 776736a60aa0e8d999f60ae163565d6764704874 Mon Sep 17 00:00:00 2001
From: Cristian Maglie <c.maglie@arduino.cc>
Date: Sat, 5 Oct 2024 00:02:28 +0200
Subject: [PATCH 6/8] fix: Moved port-from-profile logic in
 args.Port.GetPort(...)

This allows to implement the selection logic on more commands.
---
 internal/cli/arguments/fqbn.go                |   8 +-
 internal/cli/arguments/port.go                |  12 +-
 internal/cli/board/attach.go                  |   2 +-
 internal/cli/burnbootloader/burnbootloader.go |   2 +-
 internal/cli/debug/debug_check.go             |   2 +-
 internal/cli/monitor/monitor.go               |   2 +-
 .../integrationtest/monitor/monitor_test.go   | 112 ++++++++++++++++++
 .../SketchWithDefaultPortAndConfig.ino        |   3 +
 .../sketch.yaml                               |   4 +
 ...etchWithDefaultPortAndConfigAndProfile.ino |   3 +
 .../sketch.yaml                               |  13 ++
 11 files changed, 149 insertions(+), 14 deletions(-)
 create mode 100644 internal/integrationtest/monitor/testdata/SketchWithDefaultPortAndConfig/SketchWithDefaultPortAndConfig.ino
 create mode 100644 internal/integrationtest/monitor/testdata/SketchWithDefaultPortAndConfig/sketch.yaml
 create mode 100644 internal/integrationtest/monitor/testdata/SketchWithDefaultPortAndConfigAndProfile/SketchWithDefaultPortAndConfigAndProfile.ino
 create mode 100644 internal/integrationtest/monitor/testdata/SketchWithDefaultPortAndConfigAndProfile/sketch.yaml

diff --git a/internal/cli/arguments/fqbn.go b/internal/cli/arguments/fqbn.go
index 3989cbf6aba..32d619bca79 100644
--- a/internal/cli/arguments/fqbn.go
+++ b/internal/cli/arguments/fqbn.go
@@ -87,13 +87,7 @@ func CalculateFQBNAndPort(ctx context.Context, portArgs *Port, fqbnArg *Fqbn, in
 		return fqbn, port
 	}
 
-	if profile.GetPort() != "" {
-		defaultAddress = profile.GetPort()
-	}
-	if profile.GetProtocol() != "" {
-		defaultProtocol = profile.GetProtocol()
-	}
-	port, err := portArgs.GetPort(ctx, instance, srv, defaultAddress, defaultProtocol)
+	port, err := portArgs.GetPort(ctx, instance, srv, defaultAddress, defaultProtocol, profile)
 	if err != nil {
 		feedback.Fatal(i18n.Tr("Error getting port metadata: %v", err), feedback.ErrGeneric)
 	}
diff --git a/internal/cli/arguments/port.go b/internal/cli/arguments/port.go
index dfd120f162f..fea0b475db5 100644
--- a/internal/cli/arguments/port.go
+++ b/internal/cli/arguments/port.go
@@ -57,12 +57,12 @@ func (p *Port) AddToCommand(cmd *cobra.Command, srv rpc.ArduinoCoreServiceServer
 // This method allows will bypass the discoveries if:
 // - a nil instance is passed: in this case the plain port and protocol arguments are returned (even if empty)
 // - a protocol is specified: in this case the discoveries are not needed to autodetect the protocol.
-func (p *Port) GetPortAddressAndProtocol(ctx context.Context, instance *rpc.Instance, srv rpc.ArduinoCoreServiceServer, defaultAddress, defaultProtocol string) (string, string, error) {
+func (p *Port) GetPortAddressAndProtocol(ctx context.Context, instance *rpc.Instance, srv rpc.ArduinoCoreServiceServer, defaultAddress, defaultProtocol string, profile *rpc.SketchProfile) (string, string, error) {
 	if p.protocol != "" || instance == nil {
 		return p.address, p.protocol, nil
 	}
 
-	port, err := p.GetPort(ctx, instance, srv, defaultAddress, defaultProtocol)
+	port, err := p.GetPort(ctx, instance, srv, defaultAddress, defaultProtocol, profile)
 	if err != nil {
 		return "", "", err
 	}
@@ -71,7 +71,13 @@ func (p *Port) GetPortAddressAndProtocol(ctx context.Context, instance *rpc.Inst
 
 // GetPort returns the Port obtained by parsing command line arguments.
 // The extra metadata for the ports is obtained using the pluggable discoveries.
-func (p *Port) GetPort(ctx context.Context, instance *rpc.Instance, srv rpc.ArduinoCoreServiceServer, defaultAddress, defaultProtocol string) (*rpc.Port, error) {
+func (p *Port) GetPort(ctx context.Context, instance *rpc.Instance, srv rpc.ArduinoCoreServiceServer, defaultAddress, defaultProtocol string, profile *rpc.SketchProfile) (*rpc.Port, error) {
+	if profile.GetPort() != "" {
+		defaultAddress = profile.GetPort()
+	}
+	if profile.GetProtocol() != "" {
+		defaultProtocol = profile.GetProtocol()
+	}
 	address := p.address
 	protocol := p.protocol
 	if address == "" && (defaultAddress != "" || defaultProtocol != "") {
diff --git a/internal/cli/board/attach.go b/internal/cli/board/attach.go
index 871f0bbd5dc..51a5275908f 100644
--- a/internal/cli/board/attach.go
+++ b/internal/cli/board/attach.go
@@ -59,7 +59,7 @@ func initAttachCommand(srv rpc.ArduinoCoreServiceServer) *cobra.Command {
 func runAttachCommand(ctx context.Context, srv rpc.ArduinoCoreServiceServer, path string, port *arguments.Port, fqbn string, programmer *arguments.Programmer) {
 	sketchPath := arguments.InitSketchPath(path)
 
-	portAddress, portProtocol, _ := port.GetPortAddressAndProtocol(ctx, nil, srv, "", "")
+	portAddress, portProtocol, _ := port.GetPortAddressAndProtocol(ctx, nil, srv, "", "", nil)
 	newDefaults, err := srv.SetSketchDefaults(ctx, &rpc.SetSketchDefaultsRequest{
 		SketchPath:          sketchPath.String(),
 		DefaultFqbn:         fqbn,
diff --git a/internal/cli/burnbootloader/burnbootloader.go b/internal/cli/burnbootloader/burnbootloader.go
index 8b479e896e7..a9798259a14 100644
--- a/internal/cli/burnbootloader/burnbootloader.go
+++ b/internal/cli/burnbootloader/burnbootloader.go
@@ -73,7 +73,7 @@ func runBootloaderCommand(ctx context.Context, srv rpc.ArduinoCoreServiceServer)
 	logrus.Info("Executing `arduino-cli burn-bootloader`")
 
 	// We don't need a Sketch to upload a board's bootloader
-	discoveryPort, err := port.GetPort(ctx, instance, srv, "", "")
+	discoveryPort, err := port.GetPort(ctx, instance, srv, "", "", nil)
 	if err != nil {
 		feedback.Fatal(i18n.Tr("Error during Upload: %v", err), feedback.ErrGeneric)
 	}
diff --git a/internal/cli/debug/debug_check.go b/internal/cli/debug/debug_check.go
index 779348c8a82..7061d6e5412 100644
--- a/internal/cli/debug/debug_check.go
+++ b/internal/cli/debug/debug_check.go
@@ -60,7 +60,7 @@ func runDebugCheckCommand(ctx context.Context, srv rpc.ArduinoCoreServiceServer,
 	instance := instance.CreateAndInit(ctx, srv)
 	logrus.Info("Executing `arduino-cli debug`")
 
-	port, err := portArgs.GetPort(ctx, instance, srv, "", "")
+	port, err := portArgs.GetPort(ctx, instance, srv, "", "", nil)
 	if err != nil {
 		feedback.FatalError(err, feedback.ErrBadArgument)
 	}
diff --git a/internal/cli/monitor/monitor.go b/internal/cli/monitor/monitor.go
index 39c2ed5d320..290b63cd172 100644
--- a/internal/cli/monitor/monitor.go
+++ b/internal/cli/monitor/monitor.go
@@ -142,7 +142,7 @@ func runMonitorCmd(
 	if sketch != nil {
 		defaultPort, defaultProtocol = sketch.GetDefaultPort(), sketch.GetDefaultProtocol()
 	}
-	portAddress, portProtocol, err := portArgs.GetPortAddressAndProtocol(ctx, inst, srv, defaultPort, defaultProtocol)
+	portAddress, portProtocol, err := portArgs.GetPortAddressAndProtocol(ctx, inst, srv, defaultPort, defaultProtocol, profile)
 	if err != nil {
 		feedback.FatalError(err, feedback.ErrGeneric)
 	}
diff --git a/internal/integrationtest/monitor/monitor_test.go b/internal/integrationtest/monitor/monitor_test.go
index 256d8e0f8cb..7f5e3935723 100644
--- a/internal/integrationtest/monitor/monitor_test.go
+++ b/internal/integrationtest/monitor/monitor_test.go
@@ -125,6 +125,8 @@ yun.serial.disableDTR=true
 	sketchWithPort := getSketchPath("SketchWithDefaultPort")
 	sketchWithFQBN := getSketchPath("SketchWithDefaultFQBN")
 	sketchWithPortAndFQBN := getSketchPath("SketchWithDefaultPortAndFQBN")
+	sketchWithPortAndConfig := getSketchPath("SketchWithDefaultPortAndConfig")
+	sketchWithPortAndConfigAndProfile := getSketchPath("SketchWithDefaultPortAndConfigAndProfile")
 
 	t.Run("NoFlags", func(t *testing.T) {
 		t.Run("NoDefaultPortNoDefaultFQBN", func(t *testing.T) {
@@ -161,6 +163,30 @@ yun.serial.disableDTR=true
 			require.Error(t, err)
 			require.Contains(t, string(stderr), "not an FQBN: broken_fqbn")
 		})
+
+		t.Run("WithDefaultPortAndConfig", func(t *testing.T) {
+			stdout, _, err := cli.RunWithCustomInput(quitMonitor(), "monitor", "--raw", sketchWithPortAndConfig)
+			require.NoError(t, err)
+			require.Contains(t, string(stdout), "Opened port: /dev/ttyDEF")
+			require.Contains(t, string(stdout), "Configuration rts = on")
+			require.Contains(t, string(stdout), "Configuration dtr = on")
+			require.Contains(t, string(stdout), "Configuration baudrate = 57600")
+			require.Contains(t, string(stdout), "Configuration bits = 9")
+			require.Contains(t, string(stdout), "Configuration parity = none")
+			require.Contains(t, string(stdout), "Configuration stop_bits = 1")
+		})
+
+		t.Run("WithDefaultPortAndConfigAndProfile", func(t *testing.T) {
+			stdout, _, err := cli.RunWithCustomInput(quitMonitor(), "monitor", "--raw", sketchWithPortAndConfigAndProfile)
+			require.NoError(t, err)
+			require.Contains(t, string(stdout), "Opened port: /dev/ttyDEF")
+			require.Contains(t, string(stdout), "Configuration rts = on")
+			require.Contains(t, string(stdout), "Configuration dtr = on")
+			require.Contains(t, string(stdout), "Configuration baudrate = 57600")
+			require.Contains(t, string(stdout), "Configuration bits = 9")
+			require.Contains(t, string(stdout), "Configuration parity = none")
+			require.Contains(t, string(stdout), "Configuration stop_bits = 1")
+		})
 	})
 
 	t.Run("WithPortFlag", func(t *testing.T) {
@@ -202,6 +228,30 @@ yun.serial.disableDTR=true
 			require.Error(t, err)
 			require.Contains(t, string(stderr), "not an FQBN: broken_fqbn")
 		})
+
+		t.Run("WithDefaultPortAndConfig", func(t *testing.T) {
+			stdout, _, err := cli.RunWithCustomInput(quitMonitor(), "monitor", "-p", "/dev/ttyARGS", "--raw", sketchWithPortAndConfig)
+			require.NoError(t, err)
+			require.Contains(t, string(stdout), "Opened port: /dev/ttyARGS")
+			require.Contains(t, string(stdout), "Configuration rts = on")
+			require.Contains(t, string(stdout), "Configuration dtr = on")
+			require.Contains(t, string(stdout), "Configuration baudrate = 57600")
+			require.Contains(t, string(stdout), "Configuration bits = 9")
+			require.Contains(t, string(stdout), "Configuration parity = none")
+			require.Contains(t, string(stdout), "Configuration stop_bits = 1")
+		})
+
+		t.Run("WithDefaultPortAndConfigAndProfile", func(t *testing.T) {
+			stdout, _, err := cli.RunWithCustomInput(quitMonitor(), "monitor", "-p", "/dev/ttyARGS", "--raw", sketchWithPortAndConfigAndProfile)
+			require.NoError(t, err)
+			require.Contains(t, string(stdout), "Opened port: /dev/ttyARGS")
+			require.Contains(t, string(stdout), "Configuration rts = on")
+			require.Contains(t, string(stdout), "Configuration dtr = on")
+			require.Contains(t, string(stdout), "Configuration baudrate = 57600")
+			require.Contains(t, string(stdout), "Configuration bits = 9")
+			require.Contains(t, string(stdout), "Configuration parity = none")
+			require.Contains(t, string(stdout), "Configuration stop_bits = 1")
+		})
 	})
 
 	t.Run("WithFQBNFlag", func(t *testing.T) {
@@ -240,6 +290,30 @@ yun.serial.disableDTR=true
 			require.Contains(t, string(stdout), "Configuration rts = off")
 			require.Contains(t, string(stdout), "Configuration dtr = on")
 		})
+
+		t.Run("WithDefaultPortAndConfig", func(t *testing.T) {
+			stdout, _, err := cli.RunWithCustomInput(quitMonitor(), "monitor", "-b", "arduino:avr:uno", "--raw", "--profile", "profile1", sketchWithPortAndConfig)
+			require.NoError(t, err)
+			require.Contains(t, string(stdout), "Opened port: /dev/ttyDEF")
+			require.Contains(t, string(stdout), "Configuration rts = off")
+			require.Contains(t, string(stdout), "Configuration dtr = on")
+			require.Contains(t, string(stdout), "Configuration baudrate = 57600")
+			require.Contains(t, string(stdout), "Configuration bits = 9")
+			require.Contains(t, string(stdout), "Configuration parity = none")
+			require.Contains(t, string(stdout), "Configuration stop_bits = 1")
+		})
+
+		t.Run("WithDefaultPortAndConfigAndProfile", func(t *testing.T) {
+			stdout, _, err := cli.RunWithCustomInput(quitMonitor(), "monitor", "-b", "arduino:avr:uno", "--raw", "--profile", "profile1", sketchWithPortAndConfigAndProfile)
+			require.NoError(t, err)
+			require.Contains(t, string(stdout), "Opened port: /dev/ttyDEF")
+			require.Contains(t, string(stdout), "Configuration rts = off")
+			require.Contains(t, string(stdout), "Configuration dtr = on")
+			require.Contains(t, string(stdout), "Configuration baudrate = 57600")
+			require.Contains(t, string(stdout), "Configuration bits = 9")
+			require.Contains(t, string(stdout), "Configuration parity = none")
+			require.Contains(t, string(stdout), "Configuration stop_bits = 1")
+		})
 	})
 
 	t.Run("WithPortAndFQBNFlags", func(t *testing.T) {
@@ -275,6 +349,30 @@ yun.serial.disableDTR=true
 			require.Contains(t, string(stdout), "Configuration dtr = on")
 		})
 
+		t.Run("WithDefaultPortAndConfig", func(t *testing.T) {
+			stdout, _, err := cli.RunWithCustomInput(quitMonitor(), "monitor", "-p", "/dev/ttyARGS", "-b", "arduino:avr:uno", "--raw", sketchWithPortAndConfig)
+			require.NoError(t, err)
+			require.Contains(t, string(stdout), "Opened port: /dev/ttyARGS")
+			require.Contains(t, string(stdout), "Configuration rts = off")
+			require.Contains(t, string(stdout), "Configuration dtr = on")
+			require.Contains(t, string(stdout), "Configuration baudrate = 57600")
+			require.Contains(t, string(stdout), "Configuration bits = 9")
+			require.Contains(t, string(stdout), "Configuration parity = none")
+			require.Contains(t, string(stdout), "Configuration stop_bits = 1")
+		})
+
+		t.Run("WithDefaultPortAndConfigAndProfile", func(t *testing.T) {
+			stdout, _, err := cli.RunWithCustomInput(quitMonitor(), "monitor", "-p", "/dev/ttyARGS", "-b", "arduino:avr:uno", "--raw", sketchWithPortAndConfigAndProfile)
+			require.NoError(t, err)
+			require.Contains(t, string(stdout), "Opened port: /dev/ttyARGS")
+			require.Contains(t, string(stdout), "Configuration rts = off")
+			require.Contains(t, string(stdout), "Configuration dtr = on")
+			require.Contains(t, string(stdout), "Configuration baudrate = 57600")
+			require.Contains(t, string(stdout), "Configuration bits = 9")
+			require.Contains(t, string(stdout), "Configuration parity = none")
+			require.Contains(t, string(stdout), "Configuration stop_bits = 1")
+		})
+
 		t.Run("IgnoreProfile", func(t *testing.T) {
 			stdout, _, err := cli.RunWithCustomInput(quitMonitor(), "monitor", "-p", "/dev/ttyARGS", "-b", "arduino:avr:uno", "--raw", "--profile", "profile1", sketchWithPortAndFQBN)
 			require.NoError(t, err)
@@ -283,4 +381,18 @@ yun.serial.disableDTR=true
 			require.Contains(t, string(stdout), "Configuration dtr = on")
 		})
 	})
+
+	t.Run("WithProfileFlags", func(t *testing.T) {
+		t.Run("NoOtherArgs", func(t *testing.T) {
+			stdout, _, err := cli.RunWithCustomInput(quitMonitor(), "monitor", "-m", "uno", "--raw", sketchWithPortAndConfigAndProfile)
+			require.NoError(t, err)
+			require.Contains(t, string(stdout), "Opened port: /dev/ttyPROF")
+			require.Contains(t, string(stdout), "Configuration rts = on") // This is taken from profile-installed AVR core (not patched by this test)
+			require.Contains(t, string(stdout), "Configuration dtr = on")
+			require.Contains(t, string(stdout), "Configuration baudrate = 19200")
+			require.Contains(t, string(stdout), "Configuration bits = 8")
+			require.Contains(t, string(stdout), "Configuration parity = none")
+			require.Contains(t, string(stdout), "Configuration stop_bits = 1")
+		})
+	})
 }
diff --git a/internal/integrationtest/monitor/testdata/SketchWithDefaultPortAndConfig/SketchWithDefaultPortAndConfig.ino b/internal/integrationtest/monitor/testdata/SketchWithDefaultPortAndConfig/SketchWithDefaultPortAndConfig.ino
new file mode 100644
index 00000000000..5054c040393
--- /dev/null
+++ b/internal/integrationtest/monitor/testdata/SketchWithDefaultPortAndConfig/SketchWithDefaultPortAndConfig.ino
@@ -0,0 +1,3 @@
+
+void setup() {}
+void loop() {}
diff --git a/internal/integrationtest/monitor/testdata/SketchWithDefaultPortAndConfig/sketch.yaml b/internal/integrationtest/monitor/testdata/SketchWithDefaultPortAndConfig/sketch.yaml
new file mode 100644
index 00000000000..4bf8973a9ed
--- /dev/null
+++ b/internal/integrationtest/monitor/testdata/SketchWithDefaultPortAndConfig/sketch.yaml
@@ -0,0 +1,4 @@
+default_port: /dev/ttyDEF
+default_port_config:
+  baudrate: 57600
+  bits: 9
diff --git a/internal/integrationtest/monitor/testdata/SketchWithDefaultPortAndConfigAndProfile/SketchWithDefaultPortAndConfigAndProfile.ino b/internal/integrationtest/monitor/testdata/SketchWithDefaultPortAndConfigAndProfile/SketchWithDefaultPortAndConfigAndProfile.ino
new file mode 100644
index 00000000000..5054c040393
--- /dev/null
+++ b/internal/integrationtest/monitor/testdata/SketchWithDefaultPortAndConfigAndProfile/SketchWithDefaultPortAndConfigAndProfile.ino
@@ -0,0 +1,3 @@
+
+void setup() {}
+void loop() {}
diff --git a/internal/integrationtest/monitor/testdata/SketchWithDefaultPortAndConfigAndProfile/sketch.yaml b/internal/integrationtest/monitor/testdata/SketchWithDefaultPortAndConfigAndProfile/sketch.yaml
new file mode 100644
index 00000000000..106efce780c
--- /dev/null
+++ b/internal/integrationtest/monitor/testdata/SketchWithDefaultPortAndConfigAndProfile/sketch.yaml
@@ -0,0 +1,13 @@
+profiles:
+  uno:
+    fqbn: arduino:avr:uno
+    platforms:
+      - platform: arduino:avr (1.8.6)
+    port: /dev/ttyPROF
+    port_config:
+      baudrate: 19200
+
+default_port: /dev/ttyDEF
+default_port_config:
+  baudrate: 57600
+  bits: 9

From 2194a372bbe7d115a6d6772644b706165637003a Mon Sep 17 00:00:00 2001
From: Cristian Maglie <c.maglie@arduino.cc>
Date: Mon, 7 Oct 2024 10:38:11 +0200
Subject: [PATCH 7/8] Fixed FQBN selection logic in monitor/arg command

---
 internal/cli/arguments/fqbn.go                |  4 ++++
 internal/cli/monitor/monitor.go               | 10 ++++----
 .../integrationtest/monitor/monitor_test.go   | 24 +++++++++++++++++++
 3 files changed, 32 insertions(+), 6 deletions(-)

diff --git a/internal/cli/arguments/fqbn.go b/internal/cli/arguments/fqbn.go
index 32d619bca79..f2248bcd424 100644
--- a/internal/cli/arguments/fqbn.go
+++ b/internal/cli/arguments/fqbn.go
@@ -64,6 +64,7 @@ func (f *Fqbn) Set(fqbn string) {
 // parameters provided by the user.
 // This determine the FQBN based on:
 // - the value of the FQBN flag if explicitly specified, otherwise
+// - the FQBN of the selected profile if available, otherwise
 // - the default FQBN value in sketch.yaml (`default_fqbn` key) if available, otherwise
 // - it tries to autodetect the board connected to the given port flags
 // If all above methods fails, it returns the empty string.
@@ -73,6 +74,9 @@ func (f *Fqbn) Set(fqbn string) {
 //     terminates the execution
 func CalculateFQBNAndPort(ctx context.Context, portArgs *Port, fqbnArg *Fqbn, instance *rpc.Instance, srv rpc.ArduinoCoreServiceServer, defaultFQBN, defaultAddress, defaultProtocol string, profile *rpc.SketchProfile) (string, *rpc.Port) {
 	fqbn := fqbnArg.String()
+	if fqbn == "" {
+		fqbn = profile.GetFqbn()
+	}
 	if fqbn == "" {
 		fqbn = defaultFQBN
 	}
diff --git a/internal/cli/monitor/monitor.go b/internal/cli/monitor/monitor.go
index 290b63cd172..0254e174553 100644
--- a/internal/cli/monitor/monitor.go
+++ b/internal/cli/monitor/monitor.go
@@ -110,12 +110,10 @@ func runMonitorCmd(
 
 	var inst *rpc.Instance
 	var profile *rpc.SketchProfile
-	if fqbnArg.String() == "" {
-		if profileArg.Get() == "" {
-			inst, profile = instance.CreateAndInitWithProfile(ctx, srv, sketch.GetDefaultProfile().GetName(), sketchPath)
-		} else {
-			inst, profile = instance.CreateAndInitWithProfile(ctx, srv, profileArg.Get(), sketchPath)
-		}
+	if profileArg.Get() == "" {
+		inst, profile = instance.CreateAndInitWithProfile(ctx, srv, sketch.GetDefaultProfile().GetName(), sketchPath)
+	} else {
+		inst, profile = instance.CreateAndInitWithProfile(ctx, srv, profileArg.Get(), sketchPath)
 	}
 	if inst == nil {
 		inst = instance.CreateAndInit(ctx, srv)
diff --git a/internal/integrationtest/monitor/monitor_test.go b/internal/integrationtest/monitor/monitor_test.go
index 7f5e3935723..7dd301532bf 100644
--- a/internal/integrationtest/monitor/monitor_test.go
+++ b/internal/integrationtest/monitor/monitor_test.go
@@ -394,5 +394,29 @@ yun.serial.disableDTR=true
 			require.Contains(t, string(stdout), "Configuration parity = none")
 			require.Contains(t, string(stdout), "Configuration stop_bits = 1")
 		})
+
+		t.Run("WithFQBN", func(t *testing.T) {
+			stdout, _, err := cli.RunWithCustomInput(quitMonitor(), "monitor", "-b", "arduino:avr:yun", "-m", "uno", "--raw", sketchWithPortAndConfigAndProfile)
+			require.NoError(t, err)
+			require.Contains(t, string(stdout), "Opened port: /dev/ttyPROF")
+			require.Contains(t, string(stdout), "Configuration rts = on") // This is taken from profile-installed AVR core (not patched by this test)
+			require.Contains(t, string(stdout), "Configuration dtr = on")
+			require.Contains(t, string(stdout), "Configuration baudrate = 19200")
+			require.Contains(t, string(stdout), "Configuration bits = 8")
+			require.Contains(t, string(stdout), "Configuration parity = none")
+			require.Contains(t, string(stdout), "Configuration stop_bits = 1")
+		})
+
+		t.Run("WithConfigFlag", func(t *testing.T) {
+			stdout, _, err := cli.RunWithCustomInput(quitMonitor(), "monitor", "-c", "odd", "-m", "uno", "--raw", sketchWithPortAndConfigAndProfile)
+			require.NoError(t, err)
+			require.Contains(t, string(stdout), "Opened port: /dev/ttyPROF")
+			require.Contains(t, string(stdout), "Configuration rts = on") // This is taken from profile-installed AVR core (not patched by this test)
+			require.Contains(t, string(stdout), "Configuration dtr = on")
+			require.Contains(t, string(stdout), "Configuration baudrate = 19200")
+			require.Contains(t, string(stdout), "Configuration bits = 8")
+			require.Contains(t, string(stdout), "Configuration parity = odd")
+			require.Contains(t, string(stdout), "Configuration stop_bits = 1")
+		})
 	})
 }

From e13d66ebffdf128c4fd94dcf836ecac40a5d6d9f Mon Sep 17 00:00:00 2001
From: Cristian Maglie <c.maglie@arduino.cc>
Date: Mon, 7 Oct 2024 11:21:33 +0200
Subject: [PATCH 8/8] Fixed incorrect tests

The previous fixes now let the CLI to produce the correct output.
---
 .../integrationtest/monitor/monitor_test.go   | 27 ++++++++-----------
 .../SketchWithDefaultPortAndFQBN/sketch.yaml  |  7 +++--
 2 files changed, 16 insertions(+), 18 deletions(-)

diff --git a/internal/integrationtest/monitor/monitor_test.go b/internal/integrationtest/monitor/monitor_test.go
index 7dd301532bf..f8a708e09d1 100644
--- a/internal/integrationtest/monitor/monitor_test.go
+++ b/internal/integrationtest/monitor/monitor_test.go
@@ -287,30 +287,25 @@ yun.serial.disableDTR=true
 			stdout, _, err := cli.RunWithCustomInput(quitMonitor(), "monitor", "-b", "arduino:avr:uno", "--raw", "--profile", "profile1", sketchWithPortAndFQBN)
 			require.NoError(t, err)
 			require.Contains(t, string(stdout), "Opened port: /dev/ttyDEF")
-			require.Contains(t, string(stdout), "Configuration rts = off")
+			require.Contains(t, string(stdout), "Configuration rts = on") // This is taken from profile-downloaded platform that is not patched for test
 			require.Contains(t, string(stdout), "Configuration dtr = on")
 		})
 
 		t.Run("WithDefaultPortAndConfig", func(t *testing.T) {
-			stdout, _, err := cli.RunWithCustomInput(quitMonitor(), "monitor", "-b", "arduino:avr:uno", "--raw", "--profile", "profile1", sketchWithPortAndConfig)
-			require.NoError(t, err)
-			require.Contains(t, string(stdout), "Opened port: /dev/ttyDEF")
-			require.Contains(t, string(stdout), "Configuration rts = off")
-			require.Contains(t, string(stdout), "Configuration dtr = on")
-			require.Contains(t, string(stdout), "Configuration baudrate = 57600")
-			require.Contains(t, string(stdout), "Configuration bits = 9")
-			require.Contains(t, string(stdout), "Configuration parity = none")
-			require.Contains(t, string(stdout), "Configuration stop_bits = 1")
+			_, stderr, err := cli.RunWithCustomInput(quitMonitor(), "monitor", "-b", "arduino:avr:uno", "--raw", "--profile", "profile1", sketchWithPortAndConfig)
+			require.Error(t, err)
+			require.Contains(t, string(stderr), "Profile 'profile1' not found")
+			require.Contains(t, string(stderr), "Unknown FQBN: unknown package arduino")
 		})
 
 		t.Run("WithDefaultPortAndConfigAndProfile", func(t *testing.T) {
-			stdout, _, err := cli.RunWithCustomInput(quitMonitor(), "monitor", "-b", "arduino:avr:uno", "--raw", "--profile", "profile1", sketchWithPortAndConfigAndProfile)
+			stdout, _, err := cli.RunWithCustomInput(quitMonitor(), "monitor", "-b", "arduino:avr:uno", "--raw", "--profile", "uno", sketchWithPortAndConfigAndProfile)
 			require.NoError(t, err)
-			require.Contains(t, string(stdout), "Opened port: /dev/ttyDEF")
-			require.Contains(t, string(stdout), "Configuration rts = off")
+			require.Contains(t, string(stdout), "Opened port: /dev/ttyPROF")
+			require.Contains(t, string(stdout), "Configuration rts = on") // This is taken from profile-downloaded platform that is not patched for test
 			require.Contains(t, string(stdout), "Configuration dtr = on")
-			require.Contains(t, string(stdout), "Configuration baudrate = 57600")
-			require.Contains(t, string(stdout), "Configuration bits = 9")
+			require.Contains(t, string(stdout), "Configuration baudrate = 19200")
+			require.Contains(t, string(stdout), "Configuration bits = 8")
 			require.Contains(t, string(stdout), "Configuration parity = none")
 			require.Contains(t, string(stdout), "Configuration stop_bits = 1")
 		})
@@ -377,7 +372,7 @@ yun.serial.disableDTR=true
 			stdout, _, err := cli.RunWithCustomInput(quitMonitor(), "monitor", "-p", "/dev/ttyARGS", "-b", "arduino:avr:uno", "--raw", "--profile", "profile1", sketchWithPortAndFQBN)
 			require.NoError(t, err)
 			require.Contains(t, string(stdout), "Opened port: /dev/ttyARGS")
-			require.Contains(t, string(stdout), "Configuration rts = off")
+			require.Contains(t, string(stdout), "Configuration rts = on") // This is taken from profile-downloaded platform that is not patched for test
 			require.Contains(t, string(stdout), "Configuration dtr = on")
 		})
 	})
diff --git a/internal/integrationtest/monitor/testdata/SketchWithDefaultPortAndFQBN/sketch.yaml b/internal/integrationtest/monitor/testdata/SketchWithDefaultPortAndFQBN/sketch.yaml
index c8549c21b99..f8cc65153ce 100644
--- a/internal/integrationtest/monitor/testdata/SketchWithDefaultPortAndFQBN/sketch.yaml
+++ b/internal/integrationtest/monitor/testdata/SketchWithDefaultPortAndFQBN/sketch.yaml
@@ -1,5 +1,8 @@
-default_port: /dev/ttyDEF
-default_fqbn: arduino:avr:yun
 profiles:
   profile1:
     fqbn: "broken_fqbn"
+    platforms:
+      - platform: arduino:avr (1.8.6)
+
+default_port: /dev/ttyDEF
+default_fqbn: arduino:avr:yun