diff --git a/eclipse/spring-boot-project.setup b/eclipse/spring-boot-project.setup
index b940e2276f..608ecf8a84 100644
--- a/eclipse/spring-boot-project.setup
+++ b/eclipse/spring-boot-project.setup
@@ -127,7 +127,7 @@
name="spring-boot-tools">
+ pattern="spring-boot-(tools|antlib|configuration-.*|loader|.*-tools|*.layertools|.*-plugin|autoconfigure-processor|cloudnativebuildpack)"/>
diff --git a/settings.gradle b/settings.gradle
index b04b4ca821..13c5353026 100644
--- a/settings.gradle
+++ b/settings.gradle
@@ -45,6 +45,7 @@ include 'spring-boot-project:spring-boot-tools:spring-boot-cloudnativebuildpack'
include 'spring-boot-project:spring-boot-tools:spring-boot-configuration-metadata'
include 'spring-boot-project:spring-boot-tools:spring-boot-configuration-processor'
include 'spring-boot-project:spring-boot-tools:spring-boot-gradle-plugin'
+include 'spring-boot-project:spring-boot-tools:spring-boot-layertools'
include 'spring-boot-project:spring-boot-tools:spring-boot-loader'
include 'spring-boot-project:spring-boot-tools:spring-boot-loader-tools'
include 'spring-boot-project:spring-boot-tools:spring-boot-maven-plugin'
diff --git a/spring-boot-project/spring-boot-dependencies/build.gradle b/spring-boot-project/spring-boot-dependencies/build.gradle
index 0b37761d8d..0b60838002 100644
--- a/spring-boot-project/spring-boot-dependencies/build.gradle
+++ b/spring-boot-project/spring-boot-dependencies/build.gradle
@@ -1425,6 +1425,7 @@ bom {
'spring-boot-configuration-metadata',
'spring-boot-configuration-processor',
'spring-boot-devtools',
+ 'spring-boot-layertools',
'spring-boot-loader',
'spring-boot-loader-tools',
'spring-boot-properties-migrator',
diff --git a/spring-boot-project/spring-boot-tools/spring-boot-layertools/build.gradle b/spring-boot-project/spring-boot-tools/spring-boot-layertools/build.gradle
new file mode 100644
index 0000000000..9ffb23e381
--- /dev/null
+++ b/spring-boot-project/spring-boot-tools/spring-boot-layertools/build.gradle
@@ -0,0 +1,21 @@
+plugins {
+ id 'java-library'
+ id 'org.springframework.boot.conventions'
+ id 'org.springframework.boot.deployed'
+ id 'org.springframework.boot.internal-dependency-management'
+}
+
+description = 'Spring Boot Layers Tools'
+
+dependencies {
+ api platform(project(':spring-boot-project:spring-boot-parent'))
+
+ implementation project(':spring-boot-project:spring-boot-tools:spring-boot-loader')
+ implementation project(':spring-boot-project:spring-boot')
+ implementation 'org.springframework:spring-core'
+
+ testImplementation "org.assertj:assertj-core"
+ testImplementation "org.junit.jupiter:junit-jupiter"
+ testImplementation "org.mockito:mockito-core"
+}
+
diff --git a/spring-boot-project/spring-boot-tools/spring-boot-layertools/src/main/java/org/springframework/boot/layertools/Command.java b/spring-boot-project/spring-boot-tools/spring-boot-layertools/src/main/java/org/springframework/boot/layertools/Command.java
new file mode 100644
index 0000000000..49623002fe
--- /dev/null
+++ b/spring-boot-project/spring-boot-tools/spring-boot-layertools/src/main/java/org/springframework/boot/layertools/Command.java
@@ -0,0 +1,335 @@
+/*
+ * Copyright 2012-2020 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * https://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.springframework.boot.layertools;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Deque;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.stream.Stream;
+
+/**
+ * A command that can be launched from the layertools jarmode.
+ *
+ * @author Phillip Webb
+ */
+abstract class Command {
+
+ private final String name;
+
+ private final String description;
+
+ private final Options options;
+
+ private final Parameters parameters;
+
+ /**
+ * Create a new {@link Command} instance.
+ * @param name the name of the command
+ * @param description a description of the command
+ * @param options the command options
+ * @param parameters the command parameters
+ */
+ Command(String name, String description, Options options, Parameters parameters) {
+ this.name = name;
+ this.description = description;
+ this.options = options;
+ this.parameters = parameters;
+ }
+
+ /**
+ * Return the name of this command.
+ * @return the command name
+ */
+ String getName() {
+ return this.name;
+ }
+
+ /**
+ * Return the description of this command.
+ * @return the command description
+ */
+ String getDescription() {
+ return this.description;
+ }
+
+ /**
+ * Return options that this command accepts.
+ * @return the command options
+ */
+ Options getOptions() {
+ return this.options;
+ }
+
+ /**
+ * Return parameters that this command accepts.
+ * @return the command parameters
+ */
+ Parameters getParameters() {
+ return this.parameters;
+ }
+
+ /**
+ * Run the command by processing the remaining arguments.
+ * @param args a mutable deque of the remaining arguments
+ */
+ final void run(Deque args) {
+ List parameters = new ArrayList<>();
+ Map