diff --git a/docs/sketch-build-process.md b/docs/sketch-build-process.md
index 9f1f0067571..eda83a0cadd 100644
--- a/docs/sketch-build-process.md
+++ b/docs/sketch-build-process.md
@@ -52,19 +52,19 @@ generated for the path to each library dependency and appended to the
 If multiple libraries contain a file that matches the `#include` directive, the priority is determined by applying the
 following rules, one by one in this order, until a rule determines a winner:
 
-1. A library that has been specified using the [`--library` option](commands/arduino-cli_compile.md#options) of
-   `arduino-cli compile` wins against a library in other locations
+1. A library has been specified using the [`--library` option](commands/arduino-cli_compile.md#options) of
+   `arduino-cli compile`.
+1. A library is found in the `libraries` subfolder of the sketch.
 1. A library that is architecture compatible wins against a library that is not architecture compatible (see
    [**Architecture Matching**](#architecture-matching))
 1. A library with both [library name](#library-name-priority) and [folder name](#folder-name-priority) matching the
-   include wins
-1. A library that has better "library name priority" or "folder name priority" wins (see
-   [**Library Name Priority**](#library-name-priority) and [**Folder Name Priority**](#folder-name-priority))
-1. A library that is architecture optimized wins against a library that is not architecture optimized (see
-   [**Architecture Matching**](#architecture-matching))
-1. A library that has a better "location priority" wins (see [**Location Priority**](#location-priority))
-1. A library that has a folder name with a better score using the "closest-match" algorithm wins
-1. A library that has a folder name that comes first in alphanumeric order wins
+   include.
+1. A library has better "library name priority" or "folder name priority" (see
+   [**Library Name Priority**](#library-name-priority) and [**Folder Name Priority**](#folder-name-priority)).
+1. A library is architecture optimized (see [**Architecture Matching**](#architecture-matching)).
+1. A library has a better "location priority" (see [**Location Priority**](#location-priority)).
+1. A library has a folder name with a better score using the "closest-match" algorithm.
+1. A library has a folder name that comes first in alphanumeric order.
 
 ### Architecture Matching
 
@@ -126,14 +126,15 @@ The "location priority" is determined as follows (in order of highest to lowest
 
 1. The library is under a custom libraries path specified via the
    [`--libraries` option](commands/arduino-cli_compile.md#options) of `arduino-cli compile` (in decreasing order of
-   priority when multiple custom paths are defined)
-1. The library is under the `libraries` subfolder of the IDE's sketchbook or Arduino CLI's user directory
+   priority when multiple custom paths are defined).
+1. The library is under the `libraries` subfolder of the sketch.
+1. The library is under the `libraries` subfolder of the IDE's sketchbook or Arduino CLI's user directory.
 1. The library is bundled with the board platform/core
-   ([`{runtime.platform.path}/libraries`](platform-specification.md#global-predefined-properties))
+   ([`{runtime.platform.path}/libraries`](platform-specification.md#global-predefined-properties)).
 1. The library is bundled with the [referenced](platform-specification.md#referencing-another-core-variant-or-tool)
-   board platform/core
+   board platform/core.
 1. The library is bundled with the Arduino IDE (this location is determined by the Arduino CLI configuration setting
-   `directories.builtin.libraries`)
+   `directories.builtin.libraries`).
 
 #### Location priorities in Arduino Web Editor
 
diff --git a/docs/sketch-specification.md b/docs/sketch-specification.md
index 316787476c6..04e48d3c59e 100644
--- a/docs/sketch-specification.md
+++ b/docs/sketch-specification.md
@@ -72,6 +72,14 @@ Files added to the sketch via the Arduino IDE's **Sketch > Add File...** are pla
 The Arduino IDE's **File > Save As...** only copies the code files in the sketch root folder and the full contents of
 the `data` folder, so any non-code files outside the `data` folder are stripped.
 
+### `libraries` subfolder
+
+The `libraries` folder is used to store libraries compiled with the sketch. This folder should be used to store
+libraries that have been patched or to store libraries that are not available through the official library repository.
+
+- This feature is available since Arduino CLI 1.1.1
+- This feature is not yet available in Arduino IDE and Arduino Web Editor.
+
 ### Metadata
 
 #### `sketch.json`
@@ -118,25 +126,27 @@ Web Editor.
 ### Sketch file structure example
 
 ```
-Foo
+MotorController
 |_ arduino_secrets.h
-|_ Abc.ino
-|_ Def.cpp
-|_ Def.h
-|_ Foo.ino
-|_ Ghi.c
-|_ Ghi.h
-|_ Jkl.h
-|_ Jkl.S
+|_ motors.ino
+|_ defs.cpp
+|_ defs.h
+|_ MotorController.ino
+|_ someASM.h
+|_ someASM.S
 |_ sketch.yaml
 |_ data
 |  |_ Schematic.pdf
+|_ libraries
+|  |_ SomeLib
+|     |_ library.properties
+|     |_ src
+|        |_ SomeLib.h
+|        |_ SomeLib.cpp
 |_ src
-   |_ SomeLib
-      |_ library.properties
-      |_ src
-         |_ SomeLib.h
-         |_ SomeLib.cpp
+   |_ encoders
+      |_ encoders.h
+      |_ encoders.cpp
 ```
 
 ## Sketchbook
diff --git a/internal/arduino/builder/builder.go b/internal/arduino/builder/builder.go
index 91c74965782..3e71c22e46a 100644
--- a/internal/arduino/builder/builder.go
+++ b/internal/arduino/builder/builder.go
@@ -191,7 +191,7 @@ func NewBuilder(
 	logger := logger.New(stdout, stderr, verbose, warningsLevel)
 	libsManager, libsResolver, verboseOut, err := detector.LibrariesLoader(
 		useCachedLibrariesResolution, librariesManager,
-		builtInLibrariesDirs, libraryDirs, otherLibrariesDirs,
+		sk, builtInLibrariesDirs, libraryDirs, otherLibrariesDirs,
 		actualPlatform, targetPlatform,
 	)
 	if err != nil {
diff --git a/internal/arduino/builder/internal/detector/detector.go b/internal/arduino/builder/internal/detector/detector.go
index 17de9377833..84463d41e27 100644
--- a/internal/arduino/builder/internal/detector/detector.go
+++ b/internal/arduino/builder/internal/detector/detector.go
@@ -597,6 +597,7 @@ func (f *sourceFile) DepfilePath() *paths.Path {
 func LibrariesLoader(
 	useCachedLibrariesResolution bool,
 	librariesManager *librariesmanager.LibrariesManager,
+	sk *sketch.Sketch,
 	builtInLibrariesDirs *paths.Path, libraryDirs, otherLibrariesDirs paths.PathList,
 	actualPlatform, targetPlatform *cores.PlatformRelease,
 ) (*librariesmanager.LibrariesManager, *librariesresolver.Cpp, []byte, error) {
@@ -667,7 +668,7 @@ func LibrariesLoader(
 	}
 
 	allLibs := lm.FindAllInstalled()
-	resolver := librariesresolver.NewCppResolver(allLibs, targetPlatform, actualPlatform)
+	resolver := librariesresolver.NewCppResolver(allLibs, sk, targetPlatform, actualPlatform)
 	return lm, resolver, verboseOut.Bytes(), nil
 }
 
diff --git a/internal/arduino/libraries/libraries_location.go b/internal/arduino/libraries/libraries_location.go
index a2a4423a54d..8070cd99d1f 100644
--- a/internal/arduino/libraries/libraries_location.go
+++ b/internal/arduino/libraries/libraries_location.go
@@ -40,6 +40,8 @@ const (
 	// Unmanaged is for libraries set manually by the user in the CLI command or from the gRPC function.
 	// Ideally it's used for `libraries` outside folders managed by the CLI.
 	Unmanaged
+	// Sketch is for libraries that are part of the sketch (inside the `libraries` subfolder of the sketch).
+	Sketch
 )
 
 func (d *LibraryLocation) String() string {
@@ -54,6 +56,8 @@ func (d *LibraryLocation) String() string {
 		return "user"
 	case Unmanaged:
 		return "unmanaged"
+	case Sketch:
+		return "sketch"
 	default:
 		panic(fmt.Sprintf("invalid LibraryLocation value %d", *d))
 	}
@@ -86,6 +90,9 @@ func (d *LibraryLocation) UnmarshalJSON(b []byte) error {
 	case "unmanaged":
 		*d = Unmanaged
 		return nil
+	case "sketch":
+		*d = Sketch
+		return nil
 	default:
 		return errors.New(i18n.Tr("invalid library location: %s", s))
 	}
@@ -104,6 +111,8 @@ func (d *LibraryLocation) ToRPCLibraryLocation() rpc.LibraryLocation {
 		return rpc.LibraryLocation_LIBRARY_LOCATION_USER
 	case Unmanaged:
 		return rpc.LibraryLocation_LIBRARY_LOCATION_UNMANAGED
+	case Sketch:
+		return rpc.LibraryLocation_LIBRARY_LOCATION_SKETCH
 	default:
 		panic(fmt.Sprintf("invalid LibraryLocation value %d", *d))
 	}
@@ -122,6 +131,8 @@ func FromRPCLibraryLocation(l rpc.LibraryLocation) LibraryLocation {
 		return User
 	case rpc.LibraryLocation_LIBRARY_LOCATION_UNMANAGED:
 		return Unmanaged
+	case rpc.LibraryLocation_LIBRARY_LOCATION_SKETCH:
+		return Sketch
 	default:
 		panic(fmt.Sprintf("invalid rpc.LibraryLocation value %d", l))
 	}
diff --git a/internal/arduino/libraries/libraries_test.go b/internal/arduino/libraries/libraries_test.go
index 33b0de48a3b..bcec281ce99 100644
--- a/internal/arduino/libraries/libraries_test.go
+++ b/internal/arduino/libraries/libraries_test.go
@@ -50,6 +50,7 @@ func TestLibLayoutAndLocationJSONUnMarshaler(t *testing.T) {
 	testLocation(ReferencedPlatformBuiltIn)
 	testLocation(User)
 	testLocation(Unmanaged)
+	testLocation(Sketch)
 }
 
 func TestLibrariesLoader(t *testing.T) {
diff --git a/internal/arduino/libraries/librariesresolver/cpp.go b/internal/arduino/libraries/librariesresolver/cpp.go
index e842b764ace..3597fe28606 100644
--- a/internal/arduino/libraries/librariesresolver/cpp.go
+++ b/internal/arduino/libraries/librariesresolver/cpp.go
@@ -23,6 +23,7 @@ import (
 
 	"github.com/arduino/arduino-cli/internal/arduino/cores"
 	"github.com/arduino/arduino-cli/internal/arduino/libraries"
+	"github.com/arduino/arduino-cli/internal/arduino/sketch"
 	"github.com/arduino/arduino-cli/internal/arduino/utils"
 	"github.com/arduino/arduino-cli/internal/i18n"
 	"github.com/schollz/closestmatch"
@@ -35,7 +36,7 @@ type Cpp struct {
 }
 
 // NewCppResolver creates a new Cpp resolver
-func NewCppResolver(allLibs []*libraries.Library, targetPlatform, actualPlatform *cores.PlatformRelease) *Cpp {
+func NewCppResolver(allLibs []*libraries.Library, sk *sketch.Sketch, targetPlatform, actualPlatform *cores.PlatformRelease) *Cpp {
 	resolver := &Cpp{
 		headers: map[string]libraries.List{},
 	}
@@ -45,10 +46,17 @@ func NewCppResolver(allLibs []*libraries.Library, targetPlatform, actualPlatform
 	if actualPlatform != targetPlatform {
 		resolver.ScanPlatformLibraries(allLibs, actualPlatform)
 	}
-
+	resolver.ScanSketchLibraries(sk)
 	return resolver
 }
 
+// ScanSketchLibraries loads libraries bundled with the sketch
+func (resolver *Cpp) ScanSketchLibraries(sk *sketch.Sketch) {
+	for _, lib := range sk.VendoredLibraries() {
+		_ = resolver.ScanLibrary(lib)
+	}
+}
+
 // ScanIDEBuiltinLibraries reads ide-builtin librariers loaded in the LibrariesManager to find
 // and cache all C++ headers for later retrieval.
 func (resolver *Cpp) ScanIDEBuiltinLibraries(allLibs []*libraries.Library) {
@@ -199,9 +207,12 @@ func ComputePriority(lib *libraries.Library, header, arch string) int {
 		priority += 2
 	case libraries.User:
 		priority += 3
+	case libraries.Sketch:
+		// Bonus for sketch libraries, those libraries get a better priority than others
+		priority += 10000
 	case libraries.Unmanaged:
 		// Bonus for libraries specified via --libraries flags, those libraries gets the highest priority
-		priority += 10000
+		priority += 20000
 	default:
 		panic(fmt.Sprintf("Invalid library location: %d", lib.Location))
 	}
diff --git a/internal/arduino/sketch/sketch.go b/internal/arduino/sketch/sketch.go
index 5cdfb6f3ee8..cf119d329b8 100644
--- a/internal/arduino/sketch/sketch.go
+++ b/internal/arduino/sketch/sketch.go
@@ -26,6 +26,7 @@ import (
 	"github.com/arduino/arduino-cli/commands/cmderrors"
 	f "github.com/arduino/arduino-cli/internal/algorithms"
 	"github.com/arduino/arduino-cli/internal/arduino/globals"
+	"github.com/arduino/arduino-cli/internal/arduino/libraries"
 	"github.com/arduino/arduino-cli/internal/i18n"
 	rpc "github.com/arduino/arduino-cli/rpc/cc/arduino/cli/commands/v1"
 	"github.com/arduino/go-paths-helper"
@@ -33,13 +34,14 @@ import (
 
 // Sketch holds all the files composing a sketch
 type Sketch struct {
-	Name             string
-	MainFile         *paths.Path
-	FullPath         *paths.Path    // FullPath is the path to the Sketch folder
-	OtherSketchFiles paths.PathList // Sketch files that end in .ino other than main file
-	AdditionalFiles  paths.PathList
-	RootFolderFiles  paths.PathList // All files that are in the Sketch root
-	Project          *Project
+	Name              string
+	MainFile          *paths.Path
+	FullPath          *paths.Path    // FullPath is the path to the Sketch folder
+	OtherSketchFiles  paths.PathList // Sketch files that end in .ino other than main file
+	AdditionalFiles   paths.PathList
+	RootFolderFiles   paths.PathList       // All files that are in the Sketch root
+	vendoredLibraries []*libraries.Library // All libraries in the 'libraries' directory in the sketch
+	Project           *Project
 }
 
 // New creates an Sketch instance by reading all the files composing a sketch and grouping them
@@ -142,9 +144,41 @@ func New(path *paths.Path) (*Sketch, error) {
 	sort.Sort(&sketch.OtherSketchFiles)
 	sort.Sort(&sketch.RootFolderFiles)
 
+	// Collect vedndored libraries
+	if librariesPath, ok := sketch.GetVendoredLibrariesDir(); ok {
+		libDirs, err := librariesPath.ReadDir()
+		if err != nil {
+			return nil, fmt.Errorf("%s: %w", i18n.Tr("reading sketch libraries"), err)
+		}
+		libDirs.FilterDirs()
+		for _, libDir := range libDirs {
+			lib, err := libraries.Load(libDir, libraries.Sketch)
+			if err != nil {
+				return nil, fmt.Errorf("%s: %w", i18n.Tr("reading sketch libraries"), err)
+			}
+			sketch.vendoredLibraries = append(sketch.vendoredLibraries, lib)
+		}
+	}
+
 	return sketch, nil
 }
 
+// GetVendoredLibrariesDir returns the 'libraries' directory path.
+// The result is in the res,ok format ok is true if the 'libraries' directory
+// is present in the sketch, false otherwise.
+func (s *Sketch) GetVendoredLibrariesDir() (res *paths.Path, ok bool) {
+	libsDir := s.FullPath.Join("libraries")
+	if libsDir.IsDir() {
+		return libsDir, true
+	}
+	return nil, false
+}
+
+// VendoredLibraries returns the libraries bundled in the sketch' 'libraries' directory.
+func (s *Sketch) VendoredLibraries() []*libraries.Library {
+	return s.vendoredLibraries
+}
+
 // supportedFiles reads all files recursively contained in Sketch and
 // filter out unneded or unsupported ones and returns them
 func (s *Sketch) supportedFiles() (paths.PathList, error) {
diff --git a/internal/arduino/sketch/sketch_test.go b/internal/arduino/sketch/sketch_test.go
index f16ae8bfdcc..f56fe26990c 100644
--- a/internal/arduino/sketch/sketch_test.go
+++ b/internal/arduino/sketch/sketch_test.go
@@ -381,3 +381,11 @@ func TestSketchWithMultipleSymlinkLoops(t *testing.T) {
 	require.Error(t, err)
 	require.Nil(t, sketch)
 }
+
+func TestSketchWithVendoredLibraries(t *testing.T) {
+	sketchPath := paths.New("testdata", "SketchWithLibraries")
+	sk, err := New(sketchPath)
+	require.NoError(t, err)
+	require.Len(t, sk.vendoredLibraries, 1)
+	require.Equal(t, "MyLib", sk.vendoredLibraries[0].Name)
+}
diff --git a/internal/arduino/sketch/testdata/SketchWithLibraries/SketchWithLibraries.ino b/internal/arduino/sketch/testdata/SketchWithLibraries/SketchWithLibraries.ino
new file mode 100644
index 00000000000..b66e280362f
--- /dev/null
+++ b/internal/arduino/sketch/testdata/SketchWithLibraries/SketchWithLibraries.ino
@@ -0,0 +1,6 @@
+#include <MyLib.h>
+
+void setup() {}
+void loop() {
+    myFunction();
+}
diff --git a/internal/arduino/sketch/testdata/SketchWithLibraries/libraries/MyLib/MyLib.h b/internal/arduino/sketch/testdata/SketchWithLibraries/libraries/MyLib/MyLib.h
new file mode 100644
index 00000000000..5ed3d655e94
--- /dev/null
+++ b/internal/arduino/sketch/testdata/SketchWithLibraries/libraries/MyLib/MyLib.h
@@ -0,0 +1,3 @@
+
+void myFunction() {
+}
diff --git a/internal/arduino/sketch/testdata/SketchWithLibraries/libraries/MyLib/library.properties b/internal/arduino/sketch/testdata/SketchWithLibraries/libraries/MyLib/library.properties
new file mode 100644
index 00000000000..6c3124235ce
--- /dev/null
+++ b/internal/arduino/sketch/testdata/SketchWithLibraries/libraries/MyLib/library.properties
@@ -0,0 +1 @@
+name=MyLib
diff --git a/internal/cli/feedback/result/rpc.go b/internal/cli/feedback/result/rpc.go
index a1b464a89b1..379dcb14542 100644
--- a/internal/cli/feedback/result/rpc.go
+++ b/internal/cli/feedback/result/rpc.go
@@ -172,6 +172,7 @@ const (
 	LibraryLocationPlatformBuiltin           LibraryLocation = "platform"
 	LibraryLocationReferencedPlatformBuiltin LibraryLocation = "ref-platform"
 	LibraryLocationUnmanged                  LibraryLocation = "unmanaged"
+	LibraryLocationSketch                    LibraryLocation = "sketch"
 )
 
 func NewLibraryLocation(r rpc.LibraryLocation) LibraryLocation {
@@ -186,6 +187,8 @@ func NewLibraryLocation(r rpc.LibraryLocation) LibraryLocation {
 		return LibraryLocationUser
 	case rpc.LibraryLocation_LIBRARY_LOCATION_UNMANAGED:
 		return LibraryLocationUnmanged
+	case rpc.LibraryLocation_LIBRARY_LOCATION_SKETCH:
+		return LibraryLocationSketch
 	}
 	return LibraryLocationIDEBuiltin
 }
diff --git a/internal/integrationtest/arduino-cli.go b/internal/integrationtest/arduino-cli.go
index 231065843d4..59a6deb7081 100644
--- a/internal/integrationtest/arduino-cli.go
+++ b/internal/integrationtest/arduino-cli.go
@@ -158,6 +158,12 @@ func (cli *ArduinoCLI) SketchbookDir() *paths.Path {
 	return cli.sketchbookDir
 }
 
+// SetSketchbookDir sets the sketchbook directory
+func (cli *ArduinoCLI) SetSketchbookDir(d *paths.Path) {
+	cli.sketchbookDir = d
+	cli.cliEnvVars["ARDUINO_SKETCHBOOK_DIR"] = d.String()
+}
+
 // WorkingDir returns the working directory
 func (cli *ArduinoCLI) WorkingDir() *paths.Path {
 	return cli.workingDir
diff --git a/internal/integrationtest/compile_2/compile_test.go b/internal/integrationtest/compile_2/compile_test.go
index 42312ca7477..f5ba921bbb2 100644
--- a/internal/integrationtest/compile_2/compile_test.go
+++ b/internal/integrationtest/compile_2/compile_test.go
@@ -26,6 +26,7 @@ import (
 	"github.com/go-git/go-git/v5"
 	"github.com/go-git/go-git/v5/plumbing"
 	"github.com/stretchr/testify/require"
+	"go.bug.st/testifyjson/requirejson"
 )
 
 func TestCompilePart4(t *testing.T) {
@@ -449,3 +450,41 @@ func TestCompileWithKnownPlatformNotInstalled(t *testing.T) {
 	// Verifies command to fix error is shown to user
 	require.Contains(t, string(stderr), "Try running `arduino-cli core install arduino:avr`")
 }
+
+func TestSketchWithVendoredLibraries(t *testing.T) {
+	sketchBook, err := paths.New("testdata", "sketchbook_1").Abs()
+	require.NoError(t, err)
+
+	env, cli := integrationtest.CreateArduinoCLIWithEnvironment(t)
+	defer env.CleanUp()
+
+	cli.SetSketchbookDir(sketchBook)
+
+	_, _, err = cli.Run("core", "install", "arduino:avr")
+	require.NoError(t, err)
+
+	{
+		sketchWithLibsPath := sketchBook.Join("SketchWithLibraries")
+		// Sketch should use sketch bundled "MyLib" with and without profiles
+		out, _, err := cli.Run("compile", "-b", "arduino:avr:uno", sketchWithLibsPath.String(), "--format", "json")
+		require.NoError(t, err)
+		requirejson.Query(t, out, ".builder_result.used_libraries[0].name", `"MyLib"`)
+		requirejson.Query(t, out, ".builder_result.used_libraries[0].author", `"user"`)
+		out, _, err = cli.Run("compile", "--profile", "uno", sketchWithLibsPath.String(), "--format", "json")
+		require.NoError(t, err)
+		requirejson.Query(t, out, ".builder_result.used_libraries[0].name", `"MyLib"`)
+		requirejson.Query(t, out, ".builder_result.used_libraries[0].author", `"user"`)
+	}
+
+	{
+		sketchWithoutLibsPath := sketchBook.Join("SketchWithoutLibraries")
+		// This sketch should take the user-installed MyLib
+		out, _, err := cli.Run("compile", "-b", "arduino:avr:uno", sketchWithoutLibsPath.String(), "--format", "json")
+		require.NoError(t, err)
+		requirejson.Query(t, out, ".builder_result.used_libraries[0].name", `"MyLib"`)
+		requirejson.Query(t, out, ".builder_result.used_libraries[0].author", `"upstream"`)
+		// This sketch should fail to compile since profiles will not see the user-installed MyLib
+		_, _, err = cli.Run("compile", "--profile", "uno", sketchWithoutLibsPath.String())
+		require.Error(t, err)
+	}
+}
diff --git a/internal/integrationtest/compile_2/testdata/sketchbook_1/SketchWithLibraries/SketchWithLibraries.ino b/internal/integrationtest/compile_2/testdata/sketchbook_1/SketchWithLibraries/SketchWithLibraries.ino
new file mode 100644
index 00000000000..b66e280362f
--- /dev/null
+++ b/internal/integrationtest/compile_2/testdata/sketchbook_1/SketchWithLibraries/SketchWithLibraries.ino
@@ -0,0 +1,6 @@
+#include <MyLib.h>
+
+void setup() {}
+void loop() {
+    myFunction();
+}
diff --git a/internal/integrationtest/compile_2/testdata/sketchbook_1/SketchWithLibraries/libraries/AnotherLib/AnotherLib.h b/internal/integrationtest/compile_2/testdata/sketchbook_1/SketchWithLibraries/libraries/AnotherLib/AnotherLib.h
new file mode 100644
index 00000000000..96e57ec5d58
--- /dev/null
+++ b/internal/integrationtest/compile_2/testdata/sketchbook_1/SketchWithLibraries/libraries/AnotherLib/AnotherLib.h
@@ -0,0 +1,3 @@
+
+void anotherFunction() {
+}
diff --git a/internal/integrationtest/compile_2/testdata/sketchbook_1/SketchWithLibraries/libraries/AnotherLib/library.properties b/internal/integrationtest/compile_2/testdata/sketchbook_1/SketchWithLibraries/libraries/AnotherLib/library.properties
new file mode 100644
index 00000000000..f165fefe9ec
--- /dev/null
+++ b/internal/integrationtest/compile_2/testdata/sketchbook_1/SketchWithLibraries/libraries/AnotherLib/library.properties
@@ -0,0 +1 @@
+name=AnotherLib
diff --git a/internal/integrationtest/compile_2/testdata/sketchbook_1/SketchWithLibraries/libraries/MyLib/MyLib.h b/internal/integrationtest/compile_2/testdata/sketchbook_1/SketchWithLibraries/libraries/MyLib/MyLib.h
new file mode 100644
index 00000000000..5ed3d655e94
--- /dev/null
+++ b/internal/integrationtest/compile_2/testdata/sketchbook_1/SketchWithLibraries/libraries/MyLib/MyLib.h
@@ -0,0 +1,3 @@
+
+void myFunction() {
+}
diff --git a/internal/integrationtest/compile_2/testdata/sketchbook_1/SketchWithLibraries/libraries/MyLib/library.properties b/internal/integrationtest/compile_2/testdata/sketchbook_1/SketchWithLibraries/libraries/MyLib/library.properties
new file mode 100644
index 00000000000..07f99b93d96
--- /dev/null
+++ b/internal/integrationtest/compile_2/testdata/sketchbook_1/SketchWithLibraries/libraries/MyLib/library.properties
@@ -0,0 +1,2 @@
+name=MyLib
+author=user
diff --git a/internal/integrationtest/compile_2/testdata/sketchbook_1/SketchWithLibraries/sketch.yaml b/internal/integrationtest/compile_2/testdata/sketchbook_1/SketchWithLibraries/sketch.yaml
new file mode 100644
index 00000000000..79937bdfac2
--- /dev/null
+++ b/internal/integrationtest/compile_2/testdata/sketchbook_1/SketchWithLibraries/sketch.yaml
@@ -0,0 +1,6 @@
+profiles:
+  uno:
+    fqbn: arduino:avr:uno
+    platforms:
+      - platform: arduino:avr (1.8.5)
+
diff --git a/internal/integrationtest/compile_2/testdata/sketchbook_1/SketchWithoutLibraries/SketchWithoutLibraries.ino b/internal/integrationtest/compile_2/testdata/sketchbook_1/SketchWithoutLibraries/SketchWithoutLibraries.ino
new file mode 100644
index 00000000000..a0220e4a7f1
--- /dev/null
+++ b/internal/integrationtest/compile_2/testdata/sketchbook_1/SketchWithoutLibraries/SketchWithoutLibraries.ino
@@ -0,0 +1,6 @@
+#include <MyLib.h>
+
+void setup() {}
+void loop() {
+    myWrongFunction();
+}
diff --git a/internal/integrationtest/compile_2/testdata/sketchbook_1/SketchWithoutLibraries/sketch.yaml b/internal/integrationtest/compile_2/testdata/sketchbook_1/SketchWithoutLibraries/sketch.yaml
new file mode 100644
index 00000000000..79937bdfac2
--- /dev/null
+++ b/internal/integrationtest/compile_2/testdata/sketchbook_1/SketchWithoutLibraries/sketch.yaml
@@ -0,0 +1,6 @@
+profiles:
+  uno:
+    fqbn: arduino:avr:uno
+    platforms:
+      - platform: arduino:avr (1.8.5)
+
diff --git a/internal/integrationtest/compile_2/testdata/sketchbook_1/libraries/MyLib/MyLib.h b/internal/integrationtest/compile_2/testdata/sketchbook_1/libraries/MyLib/MyLib.h
new file mode 100644
index 00000000000..2ce641a99a4
--- /dev/null
+++ b/internal/integrationtest/compile_2/testdata/sketchbook_1/libraries/MyLib/MyLib.h
@@ -0,0 +1,5 @@
+
+// This is the wrong library to include (the sketch-bundled one should take priority)
+
+void myWrongFunction() {
+}
diff --git a/internal/integrationtest/compile_2/testdata/sketchbook_1/libraries/MyLib/library.properties b/internal/integrationtest/compile_2/testdata/sketchbook_1/libraries/MyLib/library.properties
new file mode 100644
index 00000000000..0d0b76480a9
--- /dev/null
+++ b/internal/integrationtest/compile_2/testdata/sketchbook_1/libraries/MyLib/library.properties
@@ -0,0 +1,2 @@
+name=MyLib
+author=upstream
diff --git a/rpc/cc/arduino/cli/commands/v1/lib.pb.go b/rpc/cc/arduino/cli/commands/v1/lib.pb.go
index 0910be91d8a..b4b23e3d0b3 100644
--- a/rpc/cc/arduino/cli/commands/v1/lib.pb.go
+++ b/rpc/cc/arduino/cli/commands/v1/lib.pb.go
@@ -200,6 +200,8 @@ const (
 	LibraryLocation_LIBRARY_LOCATION_REFERENCED_PLATFORM_BUILTIN LibraryLocation = 3
 	// Outside the `libraries` folders managed by the CLI.
 	LibraryLocation_LIBRARY_LOCATION_UNMANAGED LibraryLocation = 4
+	// Inside the `libraries` folder of the sketch.
+	LibraryLocation_LIBRARY_LOCATION_SKETCH LibraryLocation = 5
 )
 
 // Enum value maps for LibraryLocation.
@@ -210,6 +212,7 @@ var (
 		2: "LIBRARY_LOCATION_PLATFORM_BUILTIN",
 		3: "LIBRARY_LOCATION_REFERENCED_PLATFORM_BUILTIN",
 		4: "LIBRARY_LOCATION_UNMANAGED",
+		5: "LIBRARY_LOCATION_SKETCH",
 	}
 	LibraryLocation_value = map[string]int32{
 		"LIBRARY_LOCATION_BUILTIN":                     0,
@@ -217,6 +220,7 @@ var (
 		"LIBRARY_LOCATION_PLATFORM_BUILTIN":            2,
 		"LIBRARY_LOCATION_REFERENCED_PLATFORM_BUILTIN": 3,
 		"LIBRARY_LOCATION_UNMANAGED":                   4,
+		"LIBRARY_LOCATION_SKETCH":                      5,
 	}
 )
 
@@ -3206,7 +3210,7 @@ var file_cc_arduino_cli_commands_v1_lib_proto_rawDesc = []byte{
 	0x49, 0x42, 0x52, 0x41, 0x52, 0x59, 0x5f, 0x4c, 0x41, 0x59, 0x4f, 0x55, 0x54, 0x5f, 0x46, 0x4c,
 	0x41, 0x54, 0x10, 0x00, 0x12, 0x1c, 0x0a, 0x18, 0x4c, 0x49, 0x42, 0x52, 0x41, 0x52, 0x59, 0x5f,
 	0x4c, 0x41, 0x59, 0x4f, 0x55, 0x54, 0x5f, 0x52, 0x45, 0x43, 0x55, 0x52, 0x53, 0x49, 0x56, 0x45,
-	0x10, 0x01, 0x2a, 0xc3, 0x01, 0x0a, 0x0f, 0x4c, 0x69, 0x62, 0x72, 0x61, 0x72, 0x79, 0x4c, 0x6f,
+	0x10, 0x01, 0x2a, 0xe0, 0x01, 0x0a, 0x0f, 0x4c, 0x69, 0x62, 0x72, 0x61, 0x72, 0x79, 0x4c, 0x6f,
 	0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x1c, 0x0a, 0x18, 0x4c, 0x49, 0x42, 0x52, 0x41, 0x52,
 	0x59, 0x5f, 0x4c, 0x4f, 0x43, 0x41, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x42, 0x55, 0x49, 0x4c, 0x54,
 	0x49, 0x4e, 0x10, 0x00, 0x12, 0x19, 0x0a, 0x15, 0x4c, 0x49, 0x42, 0x52, 0x41, 0x52, 0x59, 0x5f,
@@ -3218,12 +3222,14 @@ var file_cc_arduino_cli_commands_v1_lib_proto_rawDesc = []byte{
 	0x45, 0x4e, 0x43, 0x45, 0x44, 0x5f, 0x50, 0x4c, 0x41, 0x54, 0x46, 0x4f, 0x52, 0x4d, 0x5f, 0x42,
 	0x55, 0x49, 0x4c, 0x54, 0x49, 0x4e, 0x10, 0x03, 0x12, 0x1e, 0x0a, 0x1a, 0x4c, 0x49, 0x42, 0x52,
 	0x41, 0x52, 0x59, 0x5f, 0x4c, 0x4f, 0x43, 0x41, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x55, 0x4e, 0x4d,
-	0x41, 0x4e, 0x41, 0x47, 0x45, 0x44, 0x10, 0x04, 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,
+	0x41, 0x4e, 0x41, 0x47, 0x45, 0x44, 0x10, 0x04, 0x12, 0x1b, 0x0a, 0x17, 0x4c, 0x49, 0x42, 0x52,
+	0x41, 0x52, 0x59, 0x5f, 0x4c, 0x4f, 0x43, 0x41, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x53, 0x4b, 0x45,
+	0x54, 0x43, 0x48, 0x10, 0x05, 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/lib.proto b/rpc/cc/arduino/cli/commands/v1/lib.proto
index 1878b07ec53..ef13812103b 100644
--- a/rpc/cc/arduino/cli/commands/v1/lib.proto
+++ b/rpc/cc/arduino/cli/commands/v1/lib.proto
@@ -379,6 +379,8 @@ enum LibraryLocation {
   LIBRARY_LOCATION_REFERENCED_PLATFORM_BUILTIN = 3;
   // Outside the `libraries` folders managed by the CLI.
   LIBRARY_LOCATION_UNMANAGED = 4;
+  // Inside the `libraries` folder of the sketch.
+  LIBRARY_LOCATION_SKETCH = 5;
 }
 
 message ZipLibraryInstallRequest {