diff --git a/src/mbed_tools/cli/project_management.py b/src/mbed_tools/cli/project_management.py
index a0b3b762..28c78264 100644
--- a/src/mbed_tools/cli/project_management.py
+++ b/src/mbed_tools/cli/project_management.py
@@ -17,8 +17,10 @@
 
 @click.command()
 @click.option("--create-only", "-c", is_flag=True, show_default=True, help="Create a program without fetching mbed-os.")
+@click.option("--mbed-os-path", "-o", type=click.Path(),
+              default=None, help="Relative path where the mbed os is located.")
 @click.argument("path", type=click.Path(resolve_path=True))
-def new(path: str, create_only: bool) -> None:
+def new(path: str, create_only: bool, mbed_os_path: Any) -> None:
     """Creates a new Mbed project at the specified path. Downloads mbed-os and adds it to the project.
 
     PATH: Path to the destination directory for the project. Will be created if it does not exist.
@@ -27,7 +29,7 @@ def new(path: str, create_only: bool) -> None:
     if not create_only:
         click.echo("Downloading mbed-os and adding it to the project.")
 
-    initialise_project(pathlib.Path(path), create_only)
+    initialise_project(pathlib.Path(path), create_only, mbed_os_path)
 
 
 @click.command()
diff --git a/src/mbed_tools/project/_internal/project_data.py b/src/mbed_tools/project/_internal/project_data.py
index 92e1c85a..72447c03 100644
--- a/src/mbed_tools/project/_internal/project_data.py
+++ b/src/mbed_tools/project/_internal/project_data.py
@@ -8,7 +8,7 @@
 
 from dataclasses import dataclass
 from pathlib import Path
-from typing import Optional
+from typing import Optional, Any
 
 from mbed_tools.project._internal.render_templates import (
     render_cmakelists_template,
@@ -60,13 +60,14 @@ class MbedProgramFiles:
     custom_targets_json: Path
 
     @classmethod
-    def from_new(cls, root_path: Path) -> "MbedProgramFiles":
+    def from_new(cls, root_path: Path, os_path: Any) -> "MbedProgramFiles":
         """Create MbedProgramFiles from a new directory.
 
         A "new directory" in this context means it doesn't already contain an Mbed program.
 
         Args:
             root_path: The directory in which to create the program data files.
+            os_path: The directory in which the mbed-os can be found.
 
         Raises:
             ValueError: A program .mbed or mbed-os.lib file already exists at this path.
@@ -84,7 +85,7 @@ def from_new(cls, root_path: Path) -> "MbedProgramFiles":
 
         app_config.write_text(json.dumps(DEFAULT_APP_CONFIG, indent=4))
         mbed_os_ref.write_text(f"{MBED_OS_REFERENCE_URL}#{MBED_OS_REFERENCE_ID}")
-        render_cmakelists_template(cmakelists_file, root_path.stem)
+        render_cmakelists_template(cmakelists_file, root_path.stem, os_path)
         render_main_cpp_template(main_cpp)
         render_gitignore_template(gitignore)
         return cls(
diff --git a/src/mbed_tools/project/_internal/render_templates.py b/src/mbed_tools/project/_internal/render_templates.py
index cb8e1043..c3dd26cc 100644
--- a/src/mbed_tools/project/_internal/render_templates.py
+++ b/src/mbed_tools/project/_internal/render_templates.py
@@ -12,16 +12,18 @@
 TEMPLATES_DIRECTORY = Path("_internal", "templates")
 
 
-def render_cmakelists_template(cmakelists_file: Path, program_name: str) -> None:
+def render_cmakelists_template(cmakelists_file: Path, program_name: str, os_path: str) -> None:
     """Render CMakeLists.tmpl with the copyright year and program name as the app target name.
 
     Args:
         cmakelists_file: The path where CMakeLists.txt will be written.
         program_name: The name of the program, will be used as the app target name.
+        os_path: The directory where the mbed os is stored.
     """
     cmakelists_file.write_text(
         render_jinja_template(
-            "CMakeLists.tmpl", {"program_name": program_name, "year": str(datetime.datetime.now().year)}
+            "CMakeLists.tmpl", {"program_name": program_name, "os_path": os_path,
+                                "year": str(datetime.datetime.now().year)}
         )
     )
 
diff --git a/src/mbed_tools/project/_internal/templates/CMakeLists.tmpl b/src/mbed_tools/project/_internal/templates/CMakeLists.tmpl
index 6e1fb1e5..be3345ee 100644
--- a/src/mbed_tools/project/_internal/templates/CMakeLists.tmpl
+++ b/src/mbed_tools/project/_internal/templates/CMakeLists.tmpl
@@ -3,7 +3,7 @@
 
 cmake_minimum_required(VERSION 3.19.0)
 
-set(MBED_PATH ${CMAKE_CURRENT_SOURCE_DIR}/mbed-os CACHE INTERNAL "")
+set(MBED_PATH ${CMAKE_CURRENT_SOURCE_DIR}/{{os_path}} CACHE INTERNAL "")
 set(MBED_CONFIG_PATH ${CMAKE_CURRENT_BINARY_DIR} CACHE INTERNAL "")
 set(APP_TARGET {{program_name}})
 
@@ -11,7 +11,7 @@ include(${MBED_PATH}/tools/cmake/app.cmake)
 
 project(${APP_TARGET})
 
-add_subdirectory(${MBED_PATH})
+add_subdirectory(${MBED_PATH} build)
 
 add_executable(${APP_TARGET}
     main.cpp
diff --git a/src/mbed_tools/project/mbed_program.py b/src/mbed_tools/project/mbed_program.py
index c3a95362..5c6a6305 100644
--- a/src/mbed_tools/project/mbed_program.py
+++ b/src/mbed_tools/project/mbed_program.py
@@ -6,7 +6,7 @@
 import logging
 
 from pathlib import Path
-from typing import Dict
+from typing import Dict, Any
 from urllib.parse import urlparse
 
 from mbed_tools.project.exceptions import ProgramNotFound, ExistingProgram, MbedOSNotFound
@@ -41,13 +41,14 @@ def __init__(self, program_files: MbedProgramFiles, mbed_os: MbedOS) -> None:
         self.mbed_os = mbed_os
 
     @classmethod
-    def from_new(cls, dir_path: Path) -> "MbedProgram":
+    def from_new(cls, dir_path: Path, os_path: Any) -> "MbedProgram":
         """Create an MbedProgram from an empty directory.
 
         Creates the directory if it doesn't exist.
 
         Args:
             dir_path: Directory in which to create the program.
+            os_path: Directory where the mbed os is stored.
 
         Raises:
             ExistingProgram: An existing program was found in the path.
@@ -60,9 +61,10 @@ def from_new(cls, dir_path: Path) -> "MbedProgram":
 
         logger.info(f"Creating Mbed program at path '{dir_path.resolve()}'")
         dir_path.mkdir(exist_ok=True)
-        program_files = MbedProgramFiles.from_new(dir_path)
+        program_files = MbedProgramFiles.from_new(dir_path, os_path)
         logger.info(f"Creating git repository for the Mbed program '{dir_path}'")
-        mbed_os = MbedOS.from_new(dir_path / MBED_OS_DIR_NAME)
+        os_path = Path(os_path) if os_path else dir_path / MBED_OS_DIR_NAME
+        mbed_os = MbedOS.from_new(os_path)
         return cls(program_files, mbed_os)
 
     @classmethod
diff --git a/src/mbed_tools/project/project.py b/src/mbed_tools/project/project.py
index df7fedda..d4f7183b 100644
--- a/src/mbed_tools/project/project.py
+++ b/src/mbed_tools/project/project.py
@@ -39,14 +39,15 @@ def import_project(url: str, dst_path: Any = None, recursive: bool = False) -> p
     return dst_path
 
 
-def initialise_project(path: pathlib.Path, create_only: bool) -> None:
+def initialise_project(path: pathlib.Path, create_only: bool, os_path: Any) -> None:
     """Create a new Mbed project, optionally fetching and adding mbed-os.
 
     Args:
         path: Path to the project folder. Created if it doesn't exist.
         create_only: Flag which suppreses fetching mbed-os. If the value is `False`, fetch mbed-os from the remote.
+        os_path: Path to where the mbed os is loacated. defaults to ./mbed-os
     """
-    program = MbedProgram.from_new(path)
+    program = MbedProgram.from_new(path, os_path)
     if not create_only:
         libs = LibraryReferences(root=program.root, ignore_paths=["mbed-os"])
         libs.fetch()