You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@grails.apache.org by jd...@apache.org on 2026/07/09 19:49:51 UTC

(grails-core) 01/04: Split CLI dependencies from the runtime classpath

This is an automated email from the ASF dual-hosted git repository.

jdaugherty pushed a commit to branch fix/split-cli-dependencies
in repository https://gitbox.apache.org/repos/asf/grails-core.git

commit 36ad682bdf8bbc8c9fa728d7aacd2ff9c43005dc
Author: James Daugherty <jd...@jdresources.net>
AuthorDate: Thu Jul 9 15:02:14 2026 -0400

    Split CLI dependencies from the runtime classpath
---
 build.gradle                                       |   7 +
 dependencies.gradle                                |   2 +-
 gradle/functional-test-config.gradle               |  11 +
 grails-bom/base/build.gradle                       |  33 +++
 .../common/compiler/GroovyTransformOrder.groovy    |   7 +
 grails-console/build.gradle                        |   6 +
 .../GrailsApplicationContextCommandRunner.groovy   |   5 +-
 grails-core/build.gradle                           |  13 ++
 .../grails/core/cli}/ApplicationCommand.groovy     |   3 +-
 .../cli}/ApplicationContextCommandRegistry.groovy  |  11 +-
 .../grails/core/cli}/ConfigReportCommand.groovy    |   2 +-
 .../grails/core/cli}/ExecutionContext.groovy       |   3 +-
 .../core/cli}/GrailsApplicationCommand.groovy      |  10 +-
 .../compiler/CommandFactoriesTransformation.groovy |  91 ++++++++
 .../core/cli}/io/FileSystemInteraction.groovy      |   3 +-
 .../core/cli}/io/FileSystemInteractionImpl.groovy  |   3 +-
 .../core/cli}/template/TemplateException.groovy    |   2 +-
 .../core/cli}/template/TemplateRenderer.groovy     |   2 +-
 .../core/cli}/template/TemplateRendererImpl.groovy |   6 +-
 .../cli/resources/META-INF/grails-cli.factories    |  18 ++
 ...org.codehaus.groovy.transform.ASTTransformation |   1 +
 .../compiler/injection/FactoriesFileWriter.groovy  | 136 ++++++++++++
 .../GlobalGrailsClassInjectorTransformation.groovy |  86 +-------
 .../core/io/support/GrailsFactoriesLoader.groovy   |  29 ++-
 .../core/cli}/ConfigReportCommandSpec.groovy       |   2 +-
 ...balGrailsClassInjectorTransformationSpec.groovy |   4 +-
 grails-data-hibernate5/dbmigration/build.gradle    |  37 +++-
 ...plicationContextDatabaseMigrationCommand.groovy |   4 +-
 .../cli}/DatabaseMigrationCommand.groovy           |   2 +-
 .../cli}/DbmChangelogSyncCommand.groovy            |   4 +-
 .../cli}/DbmChangelogSyncSqlCommand.groovy         |   4 +-
 .../dbmigration/cli}/DbmChangelogToGroovy.groovy   |   2 +-
 .../cli}/DbmClearChecksumsCommand.groovy           |   4 +-
 .../dbmigration/cli}/DbmCreateChangelog.groovy     |   2 +-
 .../dbmigration/cli}/DbmDbDocCommand.groovy        |   4 +-
 .../dbmigration/cli}/DbmDiffCommand.groovy         |   4 +-
 .../dbmigration/cli}/DbmDropAllCommand.groovy      |   4 +-
 .../cli}/DbmFutureRollbackCountSqlCommand.groovy   |   4 +-
 .../cli}/DbmFutureRollbackSqlCommand.groovy        |   4 +-
 .../cli}/DbmGenerateChangelogCommand.groovy        |   4 +-
 .../cli}/DbmGenerateGormChangelogCommand.groovy    |   4 +-
 .../dbmigration/cli}/DbmGormDiffCommand.groovy     |   4 +-
 .../dbmigration/cli}/DbmListLocksCommand.groovy    |   4 +-
 .../cli}/DbmMarkNextChangesetRanCommand.groovy     |   4 +-
 .../cli}/DbmMarkNextChangesetRanSqlCommand.groovy  |   4 +-
 .../cli}/DbmPreviousChangesetSqlCommand.groovy     |   4 +-
 .../dbmigration/cli}/DbmReleaseLocksCommand.groovy |   4 +-
 .../dbmigration/cli}/DbmRollbackCommand.groovy     |   4 +-
 .../cli}/DbmRollbackCountCommand.groovy            |   4 +-
 .../cli}/DbmRollbackCountSqlCommand.groovy         |   4 +-
 .../dbmigration/cli}/DbmRollbackSqlCommand.groovy  |   4 +-
 .../cli}/DbmRollbackToDateCommand.groovy           |   4 +-
 .../cli}/DbmRollbackToDateSqlCommand.groovy        |   4 +-
 .../dbmigration/cli}/DbmStatusCommand.groovy       |   4 +-
 .../dbmigration/cli}/DbmTagCommand.groovy          |   4 +-
 .../dbmigration/cli}/DbmUpdateCommand.groovy       |   4 +-
 .../dbmigration/cli}/DbmUpdateCountCommand.groovy  |   4 +-
 .../cli}/DbmUpdateCountSqlCommand.groovy           |   4 +-
 .../dbmigration/cli}/DbmUpdateSqlCommand.groovy    |   4 +-
 .../dbmigration/cli}/DbmValidateCommand.groovy     |   4 +-
 .../cli}/ScriptDatabaseMigrationCommand.groovy     |   2 +-
 .../commands}/dbm-changelog-to-groovy.groovy       |   2 +-
 .../META-INF/commands}/dbm-create-changelog.groovy |   2 +-
 .../databasemigration/DbUpdateCommandSpec.groovy   |   6 +-
 ...ationContextDatabaseMigrationCommandSpec.groovy |   6 +-
 .../cli}/DatabaseMigrationCommandConfigSpec.groovy |   2 +-
 .../cli}/DatabaseMigrationCommandSpec.groovy       |   2 +-
 .../cli}/DbmChangelogSyncCommandSpec.groovy        |   4 +-
 .../cli}/DbmChangelogSyncCommandSqlSpec.groovy     |   4 +-
 .../cli}/DbmClearChecksumsCommandSpec.groovy       |   4 +-
 .../dbmigration/cli}/DbmDiffCommandSpec.groovy     |   4 +-
 .../dbmigration/cli}/DbmDropAllCommandSpec.groovy  |   4 +-
 .../DbmFutureRollbackCountSqlCommandSpec.groovy    |   4 +-
 .../cli}/DbmFutureRollbackSqlCommandSpec.groovy    |   4 +-
 .../cli}/DbmGenerateChangelogCommandSpec.groovy    |   4 +-
 .../DbmGenerateGormChangelogCommandSpec.groovy     |   4 +-
 .../dbmigration/cli}/DbmGormDiffCommandSpec.groovy |   4 +-
 .../cli}/DbmListLocksCommandSpec.groovy            |   4 +-
 .../cli}/DbmMarkNextChangesetRanCommandSpec.groovy |   4 +-
 .../DbmMarkNextChangesetRanSqlCommandSpec.groovy   |   4 +-
 .../cli}/DbmPreviousChangesetSqlCommandSpec.groovy |   4 +-
 .../cli}/DbmReleaseLocksCommandSpec.groovy         |   4 +-
 .../dbmigration/cli}/DbmRollbackCommandSpec.groovy |   4 +-
 .../cli}/DbmRollbackCountCommandSpec.groovy        |   4 +-
 .../cli}/DbmRollbackCountSqlCommandSpec.groovy     |   4 +-
 .../cli}/DbmRollbackSqlCommandSpec.groovy          |   4 +-
 .../cli}/DbmRollbackToDateCommandSpec.groovy       |   4 +-
 .../cli}/DbmRollbackToDateSqlCommandSpec.groovy    |   4 +-
 .../dbmigration/cli}/DbmStatusCommandSpec.groovy   |   4 +-
 .../dbmigration/cli}/DbmUpdateCommandSpec.groovy   |   4 +-
 .../cli}/DbmUpdateCountCommandSpec.groovy          |   4 +-
 .../cli}/DbmUpdateCountSqlCommandSpec.groovy       |   4 +-
 .../cli}/DbmUpdateSqlCommandSpec.groovy            |   4 +-
 .../dbmigration/cli}/DbmValidateCommandSpec.groovy |   4 +-
 .../cli}/ScriptDatabaseMigrationCommandSpec.groovy |   2 +-
 .../liquibase/GroovyChangeLogSpec.groovy           |  12 +-
 .../liquibase/GroovyPreconditionSpec.groovy        |   4 +-
 grails-data-hibernate5/grails-plugin/build.gradle  |  16 ++
 .../hibernate5/cli}/SchemaExportCommand.groovy     |   6 +-
 grails-data-hibernate7/dbmigration/build.gradle    |  24 +-
 ...plicationContextDatabaseMigrationCommand.groovy |   4 +-
 .../cli}/DatabaseMigrationCommand.groovy           |   2 +-
 .../cli}/DbmChangelogSyncCommand.groovy            |   4 +-
 .../cli}/DbmChangelogSyncSqlCommand.groovy         |   4 +-
 .../dbmigration/cli}/DbmChangelogToGroovy.groovy   |   2 +-
 .../cli}/DbmClearChecksumsCommand.groovy           |   4 +-
 .../dbmigration/cli}/DbmCreateChangelog.groovy     |   2 +-
 .../dbmigration/cli}/DbmDbDocCommand.groovy        |   4 +-
 .../dbmigration/cli}/DbmDiffCommand.groovy         |   4 +-
 .../dbmigration/cli}/DbmDropAllCommand.groovy      |   4 +-
 .../cli}/DbmFutureRollbackCountSqlCommand.groovy   |   4 +-
 .../cli}/DbmFutureRollbackSqlCommand.groovy        |   4 +-
 .../cli}/DbmGenerateChangelogCommand.groovy        |   4 +-
 .../cli}/DbmGenerateGormChangelogCommand.groovy    |   4 +-
 .../dbmigration/cli}/DbmGormDiffCommand.groovy     |   4 +-
 .../dbmigration/cli}/DbmListLocksCommand.groovy    |   4 +-
 .../cli}/DbmMarkNextChangesetRanCommand.groovy     |   4 +-
 .../cli}/DbmMarkNextChangesetRanSqlCommand.groovy  |   4 +-
 .../cli}/DbmPreviousChangesetSqlCommand.groovy     |   4 +-
 .../dbmigration/cli}/DbmReleaseLocksCommand.groovy |   4 +-
 .../dbmigration/cli}/DbmRollbackCommand.groovy     |   4 +-
 .../cli}/DbmRollbackCountCommand.groovy            |   4 +-
 .../cli}/DbmRollbackCountSqlCommand.groovy         |   4 +-
 .../dbmigration/cli}/DbmRollbackSqlCommand.groovy  |   4 +-
 .../cli}/DbmRollbackToDateCommand.groovy           |   4 +-
 .../cli}/DbmRollbackToDateSqlCommand.groovy        |   4 +-
 .../dbmigration/cli}/DbmStatusCommand.groovy       |   4 +-
 .../dbmigration/cli}/DbmTagCommand.groovy          |   4 +-
 .../dbmigration/cli}/DbmUpdateCommand.groovy       |   4 +-
 .../dbmigration/cli}/DbmUpdateCountCommand.groovy  |   4 +-
 .../cli}/DbmUpdateCountSqlCommand.groovy           |   4 +-
 .../dbmigration/cli}/DbmUpdateSqlCommand.groovy    |   4 +-
 .../dbmigration/cli}/DbmValidateCommand.groovy     |   4 +-
 .../cli}/ScriptDatabaseMigrationCommand.groovy     |   2 +-
 .../commands}/dbm-changelog-to-groovy.groovy       |   2 +-
 .../META-INF/commands}/dbm-create-changelog.groovy |   2 +-
 .../databasemigration/DbUpdateCommandSpec.groovy   |   6 +-
 ...ationContextDatabaseMigrationCommandSpec.groovy |   6 +-
 .../cli}/DatabaseMigrationCommandConfigSpec.groovy |   2 +-
 .../cli}/DatabaseMigrationCommandSpec.groovy       |   2 +-
 .../cli}/DbmChangelogSyncCommandSpec.groovy        |   4 +-
 .../cli}/DbmChangelogSyncCommandSqlSpec.groovy     |   4 +-
 .../cli}/DbmClearChecksumsCommandSpec.groovy       |   4 +-
 .../dbmigration/cli}/DbmDiffCommandSpec.groovy     |   4 +-
 .../dbmigration/cli}/DbmDropAllCommandSpec.groovy  |   4 +-
 .../DbmFutureRollbackCountSqlCommandSpec.groovy    |   4 +-
 .../cli}/DbmFutureRollbackSqlCommandSpec.groovy    |   4 +-
 .../cli}/DbmGenerateChangelogCommandSpec.groovy    |   4 +-
 .../DbmGenerateGormChangelogCommandSpec.groovy     |   4 +-
 .../dbmigration/cli}/DbmGormDiffCommandSpec.groovy |   4 +-
 .../cli}/DbmListLocksCommandSpec.groovy            |   4 +-
 .../cli}/DbmMarkNextChangesetRanCommandSpec.groovy |   4 +-
 .../DbmMarkNextChangesetRanSqlCommandSpec.groovy   |   4 +-
 .../cli}/DbmPreviousChangesetSqlCommandSpec.groovy |   4 +-
 .../cli}/DbmReleaseLocksCommandSpec.groovy         |   4 +-
 .../dbmigration/cli}/DbmRollbackCommandSpec.groovy |   4 +-
 .../cli}/DbmRollbackCountCommandSpec.groovy        |   4 +-
 .../cli}/DbmRollbackCountSqlCommandSpec.groovy     |   4 +-
 .../cli}/DbmRollbackSqlCommandSpec.groovy          |   4 +-
 .../cli}/DbmRollbackToDateCommandSpec.groovy       |   4 +-
 .../cli}/DbmRollbackToDateSqlCommandSpec.groovy    |   4 +-
 .../dbmigration/cli}/DbmStatusCommandSpec.groovy   |   4 +-
 .../dbmigration/cli}/DbmUpdateCommandSpec.groovy   |   4 +-
 .../cli}/DbmUpdateCountCommandSpec.groovy          |   4 +-
 .../cli}/DbmUpdateCountSqlCommandSpec.groovy       |   4 +-
 .../cli}/DbmUpdateSqlCommandSpec.groovy            |   4 +-
 .../dbmigration/cli}/DbmValidateCommandSpec.groovy |   4 +-
 .../cli}/ScriptDatabaseMigrationCommandSpec.groovy |   2 +-
 .../liquibase/GroovyChangeLogSpec.groovy           |  12 +-
 .../liquibase/GroovyPreconditionSpec.groovy        |   4 +-
 grails-data-hibernate7/grails-plugin/build.gradle  |  18 ++
 .../hibernate7/cli}/SchemaExportCommand.groovy     |   7 +-
 .../guide/commandLine/creatingCustomCommands.adoc  | 117 ++++++----
 .../commandLine/gradleBuild/gradlePlugins.adoc     |   1 +
 grails-doc/src/en/guide/introduction/whatsNew.adoc |  47 ++++
 .../en/guide/plugins/providingBasicArtefacts.adoc  |  46 +++-
 .../src/en/guide/upgrading/upgrading80x.adoc       |  98 +++++++++
 .../src/en/ref/Command Line/create-command.adoc    |  19 +-
 .../feature/migration/DatabaseMigrationPlugin.java |  12 +-
 .../migration/DatabaseMigrationPluginSpec.groovy   |  13 +-
 .../io/support/FactoriesLoaderSupport.groovy       |  23 +-
 grails-gradle/plugins/build.gradle                 |   6 +
 .../plugin/commands/CliArtifactExtension.groovy    |  49 +++++
 .../commands/GrailsCliArtifactGradlePlugin.groovy  | 241 +++++++++++++++++++++
 .../gradle/plugin/core/GrailsExtension.groovy      |  18 +-
 .../gradle/plugin/core/GrailsGradlePlugin.groovy   | 218 ++++++++++++++++++-
 .../base/templates/artifacts/Command.groovy        |   2 +-
 grails-scaffolding/build.gradle                    |  20 ++
 .../scaffolding/cli}/CommandLineHelper.groovy      |   4 +-
 .../cli}/CreateScaffoldControllerCommand.groovy    |   6 +-
 .../cli}/CreateScaffoldServiceCommand.groovy       |   6 +-
 .../scaffolding/cli}/GenerateAllCommand.groovy     |   6 +-
 .../cli}/GenerateAsyncControllerCommand.groovy     |   6 +-
 .../cli}/GenerateControllerCommand.groovy          |   6 +-
 .../cli}/GenerateScaffoldAllCommand.groovy         |   6 +-
 .../scaffolding/cli}/GenerateServiceCommand.groovy |   6 +-
 .../scaffolding/cli}/GenerateViewsCommand.groovy   |   6 +-
 .../cli}/InstallTemplatesCommand.groovy            |   6 +-
 .../grails/scaffolding/cli}/SkipBootstrap.groovy   |   2 +-
 .../ApplicationContextCommandFactory.groovy        |   4 +-
 grails-spring-security/oauth2/plugin/build.gradle  |  20 ++
 .../security/oauth2/cli}/CommandLineHelper.groovy  |   2 +-
 .../security/oauth2/cli}/InitOAuth2Command.groovy  |   5 +-
 grails-spring-security/plugin/build.gradle         |  20 ++
 .../grails/security/cli}/CommandLineHelper.groovy  |   4 +-
 .../cli}/S2CreatePersistentTokenCommand.groovy     |   5 +-
 .../cli}/S2CreateRoleHierarchyEntryCommand.groovy  |   5 +-
 .../security/cli}/S2QuickstartCommand.groovy       |   5 +-
 .../grails/security/cli}/SkipBootstrap.groovy      |   2 +-
 .../ConfigReportCommandIntegrationSpec.groovy      |   4 +-
 grails-web-url-mappings/build.gradle               |  16 ++
 .../mapping/cli}/UrlMappingsReportCommand.groovy   |   7 +-
 212 files changed, 1694 insertions(+), 547 deletions(-)

diff --git a/build.gradle b/build.gradle
index 433eba3b5a..728315011d 100644
--- a/build.gradle
+++ b/build.gradle
@@ -66,6 +66,13 @@ subprojects {
         }
     }
 
+    // Framework modules wire their cli tier with project dependencies; only the test-example
+    // apps exercise the external-coordinate auto-provisioning (resolved locally through the
+    // dependency substitution in gradle/functional-test-config.gradle) like real applications.
+    if (!name.startsWith('grails-test-examples')) {
+        ext.grailsCliAutoProvision = false
+    }
+
     if (name.startsWith('grails-doc') || name.startsWith('grails-data-doc') || name.endsWith('-docs') || name.endsWith('-test-report')) {
         rootProject.ext['docProjects'] << name
     }
diff --git a/dependencies.gradle b/dependencies.gradle
index 01187a564c..65ba0addf7 100644
--- a/dependencies.gradle
+++ b/dependencies.gradle
@@ -31,7 +31,7 @@ ext {
             'directory-watcher.version'     : '0.19.1',
             'gradle-groovy.version'         : '4.0.32',
             'gradle-spock.version'          : '2.4-groovy-4.0',
-            'grails-publish-plugin.version' : '1.0.0-M1',
+            'grails-publish-plugin.version' : '1.0.0-SNAPSHOT',
             'jansi.version'                 : '2.4.2',
             'javaparser-core.version'       : '3.28.2',
             'jline.version'                 : '3.30.6',
diff --git a/gradle/functional-test-config.gradle b/gradle/functional-test-config.gradle
index bc2c96997d..1c8f38ed4b 100644
--- a/gradle/functional-test-config.gradle
+++ b/gradle/functional-test-config.gradle
@@ -49,6 +49,17 @@ configurations.configureEach {
                 else {
                     substitute module(substitutedArtifact) using project(":$possibleProject.name")
                 }
+
+                // companion cli artifacts are additional publications of the same project,
+                // reachable locally through the project's cli capability
+                def cliArtifactId = possibleProject.findProperty('cliArtifactId')
+                if (cliArtifactId) {
+                    def cliCoordinate = "$possibleProject.group:$cliArtifactId" as String
+                    def cliReplacement = it.variant(project(":$possibleProject.name")) { v ->
+                        v.capabilities { it.requireCapability(cliCoordinate) }
+                    }
+                    substitute module(cliCoordinate) using cliReplacement
+                }
             }
         }
     }
diff --git a/grails-bom/base/build.gradle b/grails-bom/base/build.gradle
index eba2651152..43dabcd7c7 100644
--- a/grails-bom/base/build.gradle
+++ b/grails-bom/base/build.gradle
@@ -99,6 +99,23 @@ dependencies {
     }
 }
 
+// Companion cli artifacts (published by the cli-artifact convention plugin) are additional
+// publications of existing projects, so the subproject enumeration above cannot see them. Each
+// applying project exports its companion coordinate via the `cliArtifactId` extra property, which
+// only exists once that project has been evaluated — so the constraints are computed lazily, in
+// the mutation window Gradle provides right before the configuration is first observed.
+configurations.named('api').configure { apiConfiguration ->
+    apiConfiguration.withDependencies {
+        for (Project subproject : rootProject.subprojects) {
+            def cliArtifactId = subproject.findProperty('cliArtifactId')
+            if (cliArtifactId) {
+                apiConfiguration.dependencyConstraints.add(
+                        project.dependencies.constraints.create("${subproject.group}:${cliArtifactId}:${projectVersion}"))
+            }
+        }
+    }
+}
+
 configurations.register('bomDependencies').configure {
     it.canBeResolved = true
     it.transitive = true
@@ -122,6 +139,11 @@ tasks.register('extractConstraints', ExtractDependenciesTask).configure { Extrac
 
         rootProject.subprojects.each { p ->
             artifactIdMappings[p.name] = p.findProperty('pomArtifactId') ?: p.name
+
+            String cliArtifactId = p.findProperty('cliArtifactId')
+            if (cliArtifactId) {
+                artifactIdMappings[cliArtifactId] = cliArtifactId
+            }
         }
 
         for (Map.Entry<String, String> dependency : project.ext.gradleBuildProjects.entrySet()) {
@@ -138,6 +160,11 @@ tasks.register('extractConstraints', ExtractDependenciesTask).configure { Extrac
             String artifactId = p.findProperty('pomArtifactId') as String ?: p.name
             String baseVersionName = artifactId.replaceAll('[.]', '-')
             projectCoordinates["${p.group}:${ artifactId}:${p.version}" as String] = baseVersionName
+
+            String cliArtifactId = p.findProperty('cliArtifactId')
+            if (cliArtifactId) {
+                projectCoordinates["${p.group}:${cliArtifactId}:${p.version}" as String] = cliArtifactId
+            }
         }
 
         for (Map.Entry<String, String> dependency : project.ext.gradleBuildProjects.entrySet()) {
@@ -193,6 +220,12 @@ ext {
             for (String gradleArtifactId : project.ext.gradleBuildProjects) {
                 propertyNameCalculator.addProject('org.apache.grails.gradle', gradleArtifactId, project.version as String, gradleArtifactId)
             }
+            for (Project p : rootProject.subprojects) {
+                String cliArtifactId = p.findProperty('cliArtifactId')
+                if (cliArtifactId) {
+                    propertyNameCalculator.addProject(p.group as String, cliArtifactId, p.version as String, cliArtifactId)
+                }
+            }
 
             Map<String, String> pomProperties = [:]
             deps.dependency.each { dep ->
diff --git a/grails-common/src/main/groovy/org/apache/grails/common/compiler/GroovyTransformOrder.groovy b/grails-common/src/main/groovy/org/apache/grails/common/compiler/GroovyTransformOrder.groovy
index 6b6cddc7aa..2a234f9573 100644
--- a/grails-common/src/main/groovy/org/apache/grails/common/compiler/GroovyTransformOrder.groovy
+++ b/grails-common/src/main/groovy/org/apache/grails/common/compiler/GroovyTransformOrder.groovy
@@ -215,4 +215,11 @@ interface GroovyTransformOrder {
      * Transforms a method to non-block IO
      */
     static final int RX_SCHEDULER_ORDER = LINK_ORDER + DECREMENT_PRIORITY
+
+    /**
+     * Registers compiled ApplicationCommand implementations in META-INF/grails-cli.factories.
+     * Runs after the global Grails transform; the two write different files so there is no
+     * contention, but a deterministic order keeps compilation output reproducible.
+     */
+    static final int COMMAND_FACTORIES_ORDER = RX_SCHEDULER_ORDER + DECREMENT_PRIORITY
 }
diff --git a/grails-console/build.gradle b/grails-console/build.gradle
index 2320b4d2bc..8ee09d3c78 100644
--- a/grails-console/build.gradle
+++ b/grails-console/build.gradle
@@ -39,6 +39,12 @@ dependencies {
     implementation platform(project(':grails-bom'))
 
     api project(":grails-core")
+    // the command runner executes ApplicationCommands, which live in the cli companion artifact
+    api(project(':grails-core')) {
+        capabilities {
+            requireCapability('org.apache.grails:grails-core-cli')
+        }
+    }
     api 'org.apache.groovy:groovy'
     api 'org.apache.groovy:groovy-console'
     api 'org.apache.groovy:groovy-swing'
diff --git a/grails-console/src/main/groovy/grails/ui/command/GrailsApplicationContextCommandRunner.groovy b/grails-console/src/main/groovy/grails/ui/command/GrailsApplicationContextCommandRunner.groovy
index bc292a074d..1ea9064ed3 100644
--- a/grails-console/src/main/groovy/grails/ui/command/GrailsApplicationContextCommandRunner.groovy
+++ b/grails-console/src/main/groovy/grails/ui/command/GrailsApplicationContextCommandRunner.groovy
@@ -22,14 +22,13 @@ import org.springframework.beans.factory.config.AutowireCapableBeanFactory
 import org.springframework.context.ConfigurableApplicationContext
 
 import grails.config.Settings
-import grails.dev.commands.ApplicationContextCommandRegistry
-import grails.dev.commands.ExecutionContext
+import org.apache.grails.core.cli.ApplicationContextCommandRegistry
+import org.apache.grails.core.cli.ExecutionContext
 import grails.ui.support.DevelopmentGrailsApplication
 import org.grails.build.parsing.CommandLine
 import org.grails.build.parsing.CommandLineParser
 
 /**
- * @author Graeme Rocher
  * @since 3.0
  */
 @CompileStatic
diff --git a/grails-core/build.gradle b/grails-core/build.gradle
index 4c31f7b538..96ba46f4e0 100644
--- a/grails-core/build.gradle
+++ b/grails-core/build.gradle
@@ -23,6 +23,7 @@ plugins {
     id 'project-report'
     id 'org.apache.grails.buildsrc.properties'
     id 'org.apache.grails.buildsrc.dependency-validator'
+    id 'org.apache.grails.gradle.grails-plugin-cli'
     id 'org.apache.grails.buildsrc.compile'
     id 'org.apache.grails.buildsrc.publish'
     id 'org.apache.grails.buildsrc.sbom'
@@ -34,6 +35,12 @@ plugins {
 version = projectVersion
 group = 'org.apache.grails'
 
+cliArtifact {
+    automaticModuleName = 'org.apache.grails.core.cli'
+    // this framework module wires its cli dependencies with project dependencies below
+    defaultDependencies = false
+}
+
 dependencies {
 
     implementation platform(project(':grails-bom'))
@@ -64,6 +71,12 @@ dependencies {
 
     api project(':grails-datastore-core')
 
+    // the cli tier — published separately as org.apache.grails:grails-core-cli
+    cliImplementation platform(project(':grails-bom'))
+    cliApi project(project.path)
+    cliImplementation 'org.apache.groovy:groovy-json'
+    cliImplementation 'org.apache.groovy:groovy-templates'
+
     testImplementation 'org.springframework:spring-jdbc'
 
     testImplementation 'org.hamcrest:hamcrest'
diff --git a/grails-core/src/main/groovy/grails/dev/commands/ApplicationCommand.groovy b/grails-core/src/cli/groovy/org/apache/grails/core/cli/ApplicationCommand.groovy
similarity index 97%
rename from grails-core/src/main/groovy/grails/dev/commands/ApplicationCommand.groovy
rename to grails-core/src/cli/groovy/org/apache/grails/core/cli/ApplicationCommand.groovy
index e9086c16ee..c926ef6c70 100644
--- a/grails-core/src/main/groovy/grails/dev/commands/ApplicationCommand.groovy
+++ b/grails-core/src/cli/groovy/org/apache/grails/core/cli/ApplicationCommand.groovy
@@ -16,7 +16,7 @@
  *  specific language governing permissions and limitations
  *  under the License.
  */
-package grails.dev.commands
+package org.apache.grails.core.cli
 
 import groovy.transform.CompileStatic
 
@@ -30,7 +30,6 @@ import grails.util.Named
  * Represents a command that runs with access to the
  * {@link org.springframework.context.ApplicationContext}.
  *
- * @author Graeme Rocher
  * @since 3.0
  */
 @CompileStatic
diff --git a/grails-core/src/main/groovy/grails/dev/commands/ApplicationContextCommandRegistry.groovy b/grails-core/src/cli/groovy/org/apache/grails/core/cli/ApplicationContextCommandRegistry.groovy
similarity index 78%
rename from grails-core/src/main/groovy/grails/dev/commands/ApplicationContextCommandRegistry.groovy
rename to grails-core/src/cli/groovy/org/apache/grails/core/cli/ApplicationContextCommandRegistry.groovy
index 200e964d89..cc4b75770d 100644
--- a/grails-core/src/main/groovy/grails/dev/commands/ApplicationContextCommandRegistry.groovy
+++ b/grails-core/src/cli/groovy/org/apache/grails/core/cli/ApplicationContextCommandRegistry.groovy
@@ -14,16 +14,15 @@
  *  See the License for the specific language governing permissions and
  *  limitations under the License.
  */
-package grails.dev.commands
+package org.apache.grails.core.cli
 
 import groovy.transform.CompileStatic
 
 import org.grails.core.io.support.GrailsFactoriesLoader
 
 /**
- * A registry of {@grails.dev.commands.ApplicationContextCommand} instances
+ * A registry of {@link org.apache.grails.core.cli.ApplicationCommand} instances
  *
- * @author Graeme Rocher
  * @since 3.0
  */
 @CompileStatic
@@ -33,14 +32,16 @@ class ApplicationContextCommandRegistry {
     private final Map<String, ApplicationCommand> commands = [:]
 
     ApplicationContextCommandRegistry() {
-        for (ApplicationCommand cmd  : GrailsFactoriesLoader.loadFactories(ApplicationCommand)) {
+        for (ApplicationCommand cmd : GrailsFactoriesLoader.loadFactories(ApplicationCommand,
+                ApplicationContextCommandRegistry.classLoader, GrailsFactoriesLoader.CLI_FACTORIES_RESOURCE_LOCATION)) {
             if (!commands.containsKey(cmd.name)) {
                 commands[cmd.name] = cmd
             }
         }
 
         // If this is reflectively loaded from the delegating cli, we need to make sure the context class loader is also used to pull any commands that are loaded from the gradle classpath
-        for (ApplicationCommand cmd : GrailsFactoriesLoader.loadFactories(ApplicationCommand, Thread.currentThread().contextClassLoader)) {
+        for (ApplicationCommand cmd : GrailsFactoriesLoader.loadFactories(ApplicationCommand,
+                Thread.currentThread().contextClassLoader, GrailsFactoriesLoader.CLI_FACTORIES_RESOURCE_LOCATION)) {
             if (!commands.containsKey(cmd.name)) {
                 commands[cmd.name] = cmd
             }
diff --git a/grails-core/src/main/groovy/grails/dev/commands/ConfigReportCommand.groovy b/grails-core/src/cli/groovy/org/apache/grails/core/cli/ConfigReportCommand.groovy
similarity index 99%
rename from grails-core/src/main/groovy/grails/dev/commands/ConfigReportCommand.groovy
rename to grails-core/src/cli/groovy/org/apache/grails/core/cli/ConfigReportCommand.groovy
index 83e9373a20..8b6ab8a06d 100644
--- a/grails-core/src/main/groovy/grails/dev/commands/ConfigReportCommand.groovy
+++ b/grails-core/src/cli/groovy/org/apache/grails/core/cli/ConfigReportCommand.groovy
@@ -16,7 +16,7 @@
  *  specific language governing permissions and limitations
  *  under the License.
  */
-package grails.dev.commands
+package org.apache.grails.core.cli
 
 import groovy.json.JsonSlurper
 import groovy.transform.CompileStatic
diff --git a/grails-core/src/main/groovy/grails/dev/commands/ExecutionContext.groovy b/grails-core/src/cli/groovy/org/apache/grails/core/cli/ExecutionContext.groovy
similarity index 96%
rename from grails-core/src/main/groovy/grails/dev/commands/ExecutionContext.groovy
rename to grails-core/src/cli/groovy/org/apache/grails/core/cli/ExecutionContext.groovy
index a86e4d9096..952857f68a 100644
--- a/grails-core/src/main/groovy/grails/dev/commands/ExecutionContext.groovy
+++ b/grails-core/src/cli/groovy/org/apache/grails/core/cli/ExecutionContext.groovy
@@ -16,7 +16,7 @@
  *  specific language governing permissions and limitations
  *  under the License.
  */
-package grails.dev.commands
+package org.apache.grails.core.cli
 
 import groovy.transform.Canonical
 import groovy.transform.CompileStatic
@@ -27,7 +27,6 @@ import org.grails.build.parsing.CommandLine
 /**
  * A context command to pass to {@link ApplicationCommand} instances
  *
- * @author Graeme Rocher
  * @since 3.0
  */
 @CompileStatic
diff --git a/grails-core/src/main/groovy/grails/dev/commands/GrailsApplicationCommand.groovy b/grails-core/src/cli/groovy/org/apache/grails/core/cli/GrailsApplicationCommand.groovy
similarity index 84%
rename from grails-core/src/main/groovy/grails/dev/commands/GrailsApplicationCommand.groovy
rename to grails-core/src/cli/groovy/org/apache/grails/core/cli/GrailsApplicationCommand.groovy
index c5bd918fc7..5cf8752216 100644
--- a/grails-core/src/main/groovy/grails/dev/commands/GrailsApplicationCommand.groovy
+++ b/grails-core/src/cli/groovy/org/apache/grails/core/cli/GrailsApplicationCommand.groovy
@@ -17,13 +17,13 @@
  *  under the License.
  */
 
-package grails.dev.commands
+package org.apache.grails.core.cli
 
 import grails.codegen.model.ModelBuilder
-import grails.dev.commands.io.FileSystemInteraction
-import grails.dev.commands.io.FileSystemInteractionImpl
-import grails.dev.commands.template.TemplateRenderer
-import grails.dev.commands.template.TemplateRendererImpl
+import org.apache.grails.core.cli.io.FileSystemInteraction
+import org.apache.grails.core.cli.io.FileSystemInteractionImpl
+import org.apache.grails.core.cli.template.TemplateRenderer
+import org.apache.grails.core.cli.template.TemplateRendererImpl
 
 trait GrailsApplicationCommand implements ApplicationCommand, ModelBuilder {
 
diff --git a/grails-core/src/cli/groovy/org/apache/grails/core/cli/compiler/CommandFactoriesTransformation.groovy b/grails-core/src/cli/groovy/org/apache/grails/core/cli/compiler/CommandFactoriesTransformation.groovy
new file mode 100644
index 0000000000..4d9b84fcaf
--- /dev/null
+++ b/grails-core/src/cli/groovy/org/apache/grails/core/cli/compiler/CommandFactoriesTransformation.groovy
@@ -0,0 +1,91 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you 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.apache.grails.core.cli.compiler
+
+import groovy.transform.CompileStatic
+import org.codehaus.groovy.ast.ASTNode
+import org.codehaus.groovy.ast.ClassHelper
+import org.codehaus.groovy.ast.ClassNode
+import org.codehaus.groovy.ast.ModuleNode
+import org.codehaus.groovy.control.CompilePhase
+import org.codehaus.groovy.control.SourceUnit
+import org.codehaus.groovy.transform.ASTTransformation
+import org.codehaus.groovy.transform.GroovyASTTransformation
+import org.codehaus.groovy.transform.TransformWithPriority
+
+import org.apache.grails.common.compiler.GroovyTransformOrder
+import org.grails.compiler.injection.FactoriesFileWriter
+import org.grails.compiler.injection.GlobalGrailsClassInjectorTransformation
+import org.grails.compiler.injection.GrailsASTUtils
+import org.grails.io.support.GrailsResourceUtils
+import org.grails.io.support.UrlResource
+
+/**
+ * A global transformation that registers compiled
+ * {@link org.apache.grails.core.cli.ApplicationCommand} implementations in
+ * {@code META-INF/grails-cli.factories}, keyed by the command contract's class name.
+ *
+ * The transform ships in the {@code grails-core-cli} artifact, so it is active exactly when a
+ * command can compile — a class implementing the contract only resolves when the cli artifact is
+ * on the compile classpath. Command registrations never touch {@code META-INF/grails.factories}.
+ *
+ * @since 8.0
+ */
+@GroovyASTTransformation(phase = CompilePhase.CANONICALIZATION)
+@CompileStatic
+class CommandFactoriesTransformation implements ASTTransformation, TransformWithPriority {
+
+    public static final ClassNode APPLICATION_COMMAND_CLASS = ClassHelper.make('org.apache.grails.core.cli.ApplicationCommand')
+
+    /** The command registration file written into the compilation target directory */
+    public static final String CLI_FACTORIES_LOCATION = 'META-INF/grails-cli.factories'
+
+    /** Hand-authored registrations merged into the generated file */
+    protected static final List<String> SOURCE_CLI_FACTORIES_LOCATIONS = [
+            'src/main/resources/META-INF/grails-cli.factories',
+            'src/cli/resources/META-INF/grails-cli.factories',
+    ].asImmutable()
+
+    @Override
+    int priority() {
+        return GroovyTransformOrder.COMMAND_FACTORIES_ORDER
+    }
+
+    @Override
+    void visit(ASTNode[] nodes, SourceUnit source) {
+        ModuleNode ast = source.getAST()
+        List<ClassNode> classes = new ArrayList<>(ast.getClasses())
+
+        URL url = GrailsASTUtils.getSourceUrl(source)
+
+        if (url == null) {
+            return
+        }
+        if (!GrailsResourceUtils.isProjectSource(new UrlResource(url))) {
+            return
+        }
+
+        File compilationTargetDirectory = GlobalGrailsClassInjectorTransformation.resolveCompilationTargetDirectory(source)
+
+        for (ClassNode classNode : classes) {
+            FactoriesFileWriter.updateFactoriesWithType(classNode, APPLICATION_COMMAND_CLASS,
+                    compilationTargetDirectory, CLI_FACTORIES_LOCATION, SOURCE_CLI_FACTORIES_LOCATIONS)
+        }
+    }
+}
diff --git a/grails-core/src/main/groovy/grails/dev/commands/io/FileSystemInteraction.groovy b/grails-core/src/cli/groovy/org/apache/grails/core/cli/io/FileSystemInteraction.groovy
similarity index 98%
rename from grails-core/src/main/groovy/grails/dev/commands/io/FileSystemInteraction.groovy
rename to grails-core/src/cli/groovy/org/apache/grails/core/cli/io/FileSystemInteraction.groovy
index c7ab0ba9fd..588a1aa31b 100644
--- a/grails-core/src/main/groovy/grails/dev/commands/io/FileSystemInteraction.groovy
+++ b/grails-core/src/cli/groovy/org/apache/grails/core/cli/io/FileSystemInteraction.groovy
@@ -16,14 +16,13 @@
  *  specific language governing permissions and limitations
  *  under the License.
  */
-package grails.dev.commands.io
+package org.apache.grails.core.cli.io
 
 import org.grails.io.support.Resource
 
 /**
  * Utility methods exposed to scripts for interacting with resources (found on the file system or jars) and the file system
  *
- * @author Graeme Rocher
  * @since 3.0
  */
 interface FileSystemInteraction {
diff --git a/grails-core/src/main/groovy/grails/dev/commands/io/FileSystemInteractionImpl.groovy b/grails-core/src/cli/groovy/org/apache/grails/core/cli/io/FileSystemInteractionImpl.groovy
similarity index 99%
rename from grails-core/src/main/groovy/grails/dev/commands/io/FileSystemInteractionImpl.groovy
rename to grails-core/src/cli/groovy/org/apache/grails/core/cli/io/FileSystemInteractionImpl.groovy
index f57e4ffa81..adebd52b9f 100644
--- a/grails-core/src/main/groovy/grails/dev/commands/io/FileSystemInteractionImpl.groovy
+++ b/grails-core/src/cli/groovy/org/apache/grails/core/cli/io/FileSystemInteractionImpl.groovy
@@ -16,7 +16,7 @@
  *  specific language governing permissions and limitations
  *  under the License.
  */
-package grails.dev.commands.io
+package org.apache.grails.core.cli.io
 
 import groovy.transform.CompileStatic
 
@@ -33,7 +33,6 @@ import org.grails.io.support.SpringIOUtils
 /**
  * Utility methods exposed to scripts for interacting with resources (found on the file system or jars) and the file system
  *
- * @author Graeme Rocher
  * @since 3.0
  */
 @CompileStatic
diff --git a/grails-core/src/main/groovy/grails/dev/commands/template/TemplateException.groovy b/grails-core/src/cli/groovy/org/apache/grails/core/cli/template/TemplateException.groovy
similarity index 95%
rename from grails-core/src/main/groovy/grails/dev/commands/template/TemplateException.groovy
rename to grails-core/src/cli/groovy/org/apache/grails/core/cli/template/TemplateException.groovy
index f485fb474d..284f89a7eb 100644
--- a/grails-core/src/main/groovy/grails/dev/commands/template/TemplateException.groovy
+++ b/grails-core/src/cli/groovy/org/apache/grails/core/cli/template/TemplateException.groovy
@@ -16,7 +16,7 @@
  *  specific language governing permissions and limitations
  *  under the License.
  */
-package grails.dev.commands.template
+package org.apache.grails.core.cli.template
 
 import groovy.transform.InheritConstructors
 
diff --git a/grails-core/src/main/groovy/grails/dev/commands/template/TemplateRenderer.groovy b/grails-core/src/cli/groovy/org/apache/grails/core/cli/template/TemplateRenderer.groovy
similarity index 99%
rename from grails-core/src/main/groovy/grails/dev/commands/template/TemplateRenderer.groovy
rename to grails-core/src/cli/groovy/org/apache/grails/core/cli/template/TemplateRenderer.groovy
index 3ef4cc600b..102efbc2b4 100644
--- a/grails-core/src/main/groovy/grails/dev/commands/template/TemplateRenderer.groovy
+++ b/grails-core/src/cli/groovy/org/apache/grails/core/cli/template/TemplateRenderer.groovy
@@ -16,7 +16,7 @@
  *  specific language governing permissions and limitations
  *  under the License.
  */
-package grails.dev.commands.template
+package org.apache.grails.core.cli.template
 
 import groovy.transform.CompileDynamic
 
diff --git a/grails-core/src/main/groovy/grails/dev/commands/template/TemplateRendererImpl.groovy b/grails-core/src/cli/groovy/org/apache/grails/core/cli/template/TemplateRendererImpl.groovy
similarity index 98%
rename from grails-core/src/main/groovy/grails/dev/commands/template/TemplateRendererImpl.groovy
rename to grails-core/src/cli/groovy/org/apache/grails/core/cli/template/TemplateRendererImpl.groovy
index c3b3f1a0a8..60d99ac8bc 100644
--- a/grails-core/src/main/groovy/grails/dev/commands/template/TemplateRendererImpl.groovy
+++ b/grails-core/src/cli/groovy/org/apache/grails/core/cli/template/TemplateRendererImpl.groovy
@@ -17,7 +17,7 @@
  *  under the License.
  */
 
-package grails.dev.commands.template
+package org.apache.grails.core.cli.template
 
 import groovy.text.GStringTemplateEngine
 import groovy.text.Template
@@ -25,8 +25,8 @@ import groovy.transform.CompileDynamic
 import groovy.transform.CompileStatic
 
 import grails.codegen.model.Model
-import grails.dev.commands.io.FileSystemInteraction
-import grails.dev.commands.io.FileSystemInteractionImpl
+import org.apache.grails.core.cli.io.FileSystemInteraction
+import org.apache.grails.core.cli.io.FileSystemInteractionImpl
 import org.grails.io.support.DefaultResourceLoader
 import org.grails.io.support.Resource
 import org.grails.io.support.ResourceLoader
diff --git a/grails-core/src/cli/resources/META-INF/grails-cli.factories b/grails-core/src/cli/resources/META-INF/grails-cli.factories
new file mode 100644
index 0000000000..6282625395
--- /dev/null
+++ b/grails-core/src/cli/resources/META-INF/grails-cli.factories
@@ -0,0 +1,18 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You 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
+#
+#     http://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.
+
+# ConfigReportCommand is registered by hand because CommandFactoriesTransformation compiles in
+# the same source set — a global transform never runs on its own compilation unit.
+org.apache.grails.core.cli.ApplicationCommand=org.apache.grails.core.cli.ConfigReportCommand
diff --git a/grails-core/src/cli/resources/META-INF/services/org.codehaus.groovy.transform.ASTTransformation b/grails-core/src/cli/resources/META-INF/services/org.codehaus.groovy.transform.ASTTransformation
new file mode 100644
index 0000000000..9132a607e0
--- /dev/null
+++ b/grails-core/src/cli/resources/META-INF/services/org.codehaus.groovy.transform.ASTTransformation
@@ -0,0 +1 @@
+org.apache.grails.core.cli.compiler.CommandFactoriesTransformation
diff --git a/grails-core/src/main/groovy/org/grails/compiler/injection/FactoriesFileWriter.groovy b/grails-core/src/main/groovy/org/grails/compiler/injection/FactoriesFileWriter.groovy
new file mode 100644
index 0000000000..2dc0eaf84b
--- /dev/null
+++ b/grails-core/src/main/groovy/org/grails/compiler/injection/FactoriesFileWriter.groovy
@@ -0,0 +1,136 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you 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.grails.compiler.injection
+
+import java.lang.reflect.Modifier
+
+import groovy.transform.CompileStatic
+import org.codehaus.groovy.ast.ClassNode
+
+import org.springframework.core.CollectionFactory
+
+import org.apache.grails.gradle.common.PropertyFileUtils
+
+/**
+ * Writes factory registrations for compiled classes into a factories file in the compilation
+ * target directory, merging any existing entries from previous compilation runs and from
+ * hand-authored source registrations. The factories file location is supplied by the caller,
+ * so the writer is shared by transformations targeting different registration files
+ * (e.g. {@code META-INF/grails.factories} and {@code META-INF/grails-cli.factories}).
+ *
+ * @since 8.0
+ */
+@CompileStatic
+class FactoriesFileWriter {
+
+    /**
+     * Registers the class as an implementation of the given super type in the factories file
+     * when the class is a non-abstract subtype.
+     *
+     * @param classNode the compiled class
+     * @param superType the factory type to register the class under
+     * @param compilationTargetDirectory the compilation output directory
+     * @param factoriesLocation the factories file path relative to the target directory
+     * @param sourceFactoriesLocations project-relative paths of hand-authored factories files to merge
+     * @return {@code true} when the class was a subtype of the factory type
+     */
+    static boolean updateFactoriesWithType(ClassNode classNode, ClassNode superType, File compilationTargetDirectory,
+                                           String factoriesLocation, List<String> sourceFactoriesLocations) {
+        if (GrailsASTUtils.isSubclassOfOrImplementsInterface(classNode, superType)) {
+            if (Modifier.isAbstract(classNode.getModifiers())) {
+                return false
+            }
+
+            def classNodeName = classNode.name
+            // Use SortedProperties to ensure a consistent order of entries for reproducible builds
+            def props = CollectionFactory.createSortedProperties(false)
+            def superTypeName = superType.getName()
+
+            File factoriesFile = new File(compilationTargetDirectory, factoriesLocation)
+            if (!factoriesFile.parentFile.exists()) {
+                factoriesFile.parentFile.mkdirs()
+            }
+            loadFromFile(props, factoriesFile)
+
+            File sourceDirectory = findSourceDirectory(compilationTargetDirectory)
+            if (sourceDirectory != null) {
+                for (String sourceFactoriesLocation : sourceFactoriesLocations) {
+                    File sourceFactoriesFile = new File(sourceDirectory, sourceFactoriesLocation)
+                    loadFromFile(props, sourceFactoriesFile)
+                }
+            }
+
+            addToProps(props, superTypeName, classNodeName)
+
+            factoriesFile.withWriter { Writer writer ->
+                props.store(writer, 'Grails Factories File')
+            }
+
+            PropertyFileUtils.makePropertiesFileReproducible(factoriesFile)
+
+            return true
+        }
+        return false
+    }
+
+    private static void loadFromFile(Properties props, File factoriesFile) {
+        if (factoriesFile.exists()) {
+            Properties fileProps = new Properties()
+            factoriesFile.withInputStream { InputStream input ->
+                fileProps.load(input)
+                fileProps.each { Map.Entry prop ->
+                    addToProps(props, (String) prop.key, (String) prop.value)
+                }
+            }
+        }
+    }
+
+    private static Properties addToProps(Properties props, String superTypeName, String classNodeNames) {
+        final List<String> classNodesNameList = classNodeNames.tokenize(',')
+        classNodesNameList.forEach(classNodeName -> {
+            String existing = props.getProperty(superTypeName)
+            if (!existing) {
+                props.put(superTypeName, classNodeName)
+            } else if (existing && !existing.contains(classNodeName)) {
+                props.put(superTypeName, [existing, classNodeName].join(','))
+            }
+        })
+        props
+    }
+
+    static File findSourceDirectory(File compilationTargetDirectory) {
+        // Prefer the project base directory supplied by the build tool — more reliable than
+        // walking up from the compile target, which may live under a non-standard output
+        // directory (e.g. when project.buildDir is renamed). The Grails Gradle plugin
+        // publishes this via GrailsAppBaseDirProvider on the compiler's forkOptions.
+        String baseDirProp = System.getProperty('base.dir')
+        if (baseDirProp) {
+            File baseDir = new File(baseDirProp)
+            if (baseDir.exists() && baseDir.isDirectory()) {
+                return baseDir
+            }
+        }
+
+        File sourceDirectory = compilationTargetDirectory
+        while (sourceDirectory != null && !(sourceDirectory.name in ['build', 'target'])) {
+            sourceDirectory = sourceDirectory.parentFile
+        }
+        sourceDirectory?.parentFile
+    }
+}
diff --git a/grails-core/src/main/groovy/org/grails/compiler/injection/GlobalGrailsClassInjectorTransformation.groovy b/grails-core/src/main/groovy/org/grails/compiler/injection/GlobalGrailsClassInjectorTransformation.groovy
index 58cafb62e2..a8ac4f2d82 100644
--- a/grails-core/src/main/groovy/org/grails/compiler/injection/GlobalGrailsClassInjectorTransformation.groovy
+++ b/grails-core/src/main/groovy/org/grails/compiler/injection/GlobalGrailsClassInjectorTransformation.groovy
@@ -43,8 +43,6 @@ import org.codehaus.groovy.transform.ASTTransformation
 import org.codehaus.groovy.transform.GroovyASTTransformation
 import org.codehaus.groovy.transform.TransformWithPriority
 
-import org.springframework.core.CollectionFactory
-
 import grails.artefact.Artefact
 import grails.compiler.ast.ClassInjector
 import grails.core.ArtefactHandler
@@ -52,7 +50,6 @@ import grails.io.IOUtils
 import grails.plugins.metadata.GrailsPlugin
 import grails.util.GrailsNameUtils
 import org.apache.grails.common.compiler.GroovyTransformOrder
-import org.apache.grails.gradle.common.PropertyFileUtils
 import org.grails.core.io.support.GrailsFactoriesLoader
 import org.grails.io.support.AntPathMatcher
 import org.grails.io.support.GrailsResourceUtils
@@ -69,7 +66,6 @@ import org.grails.io.support.UrlResource
 class GlobalGrailsClassInjectorTransformation implements ASTTransformation, CompilationUnitAware, TransformWithPriority {
 
     public static final ClassNode ARTEFACT_HANDLER_CLASS = ClassHelper.make('grails.core.ArtefactHandler')
-    public static final ClassNode APPLICATION_CONTEXT_COMMAND_CLASS = ClassHelper.make('grails.dev.commands.ApplicationCommand')
     public static final ClassNode TRAIT_INJECTOR_CLASS = ClassHelper.make('grails.compiler.traits.TraitInjector')
 
     @Override
@@ -125,9 +121,6 @@ class GlobalGrailsClassInjectorTransformation implements ASTTransformation, Comp
             if (updateGrailsFactoriesWithType(classNode, ARTEFACT_HANDLER_CLASS, compilationTargetDirectory)) {
                 continue
             }
-            if (updateGrailsFactoriesWithType(classNode, APPLICATION_CONTEXT_COMMAND_CLASS, compilationTargetDirectory)) {
-                continue
-            }
             if (updateGrailsFactoriesWithType(classNode, TRAIT_INJECTOR_CLASS, compilationTargetDirectory)) {
                 continue
             }
@@ -219,83 +212,8 @@ class GlobalGrailsClassInjectorTransformation implements ASTTransformation, Comp
     }
 
     static boolean updateGrailsFactoriesWithType(ClassNode classNode, ClassNode superType, File compilationTargetDirectory) {
-        if (GrailsASTUtils.isSubclassOfOrImplementsInterface(classNode, superType)) {
-            if (Modifier.isAbstract(classNode.getModifiers())) return false
-
-            def classNodeName = classNode.name
-            // Use SortedProperties to ensure a consistent order of entries for reproducible builds
-            def props = CollectionFactory.createSortedProperties(false)
-            def superTypeName = superType.getName()
-
-            // generate META-INF/grails.factories
-            File factoriesFile = new File(compilationTargetDirectory, 'META-INF/grails.factories')
-            if (!factoriesFile.parentFile.exists()) {
-                factoriesFile.parentFile.mkdirs()
-            }
-            loadFromFile(props, factoriesFile)
-
-            File sourceDirectory = findSourceDirectory(compilationTargetDirectory)
-            if (sourceDirectory != null) {
-                File sourceFactoriesFile = new File(sourceDirectory, 'src/main/resources/META-INF/grails.factories')
-                loadFromFile(props, sourceFactoriesFile)
-            }
-
-            addToProps(props, superTypeName, classNodeName)
-
-            factoriesFile.withWriter { Writer writer ->
-                props.store(writer, 'Grails Factories File')
-            }
-
-            PropertyFileUtils.makePropertiesFileReproducible(factoriesFile)
-
-            return true
-        }
-        return false
-    }
-
-    private static void loadFromFile(Properties props, File factoriesFile) {
-        if (factoriesFile.exists()) {
-            Properties fileProps = new Properties()
-            factoriesFile.withInputStream { InputStream input ->
-                fileProps.load(input)
-                fileProps.each { Map.Entry prop ->
-                    addToProps(props, (String) prop.key, (String) prop.value)
-                }
-            }
-        }
-    }
-
-    private static Properties addToProps(Properties props, String superTypeName, String classNodeNames) {
-        final List<String> classNodesNameList = classNodeNames.tokenize(',')
-        classNodesNameList.forEach(classNodeName -> {
-            String existing = props.getProperty(superTypeName)
-            if (!existing) {
-                props.put(superTypeName, classNodeName)
-            } else if (existing && !existing.contains(classNodeName)) {
-                props.put(superTypeName, [existing, classNodeName].join(','))
-            }
-        })
-        props
-    }
-
-    private static File findSourceDirectory(File compilationTargetDirectory) {
-        // Prefer the project base directory supplied by the build tool — more reliable than
-        // walking up from the compile target, which may live under a non-standard output
-        // directory (e.g. when project.buildDir is renamed). The Grails Gradle plugin
-        // publishes this via GrailsAppBaseDirProvider on the compiler's forkOptions.
-        String baseDirProp = System.getProperty('base.dir')
-        if (baseDirProp) {
-            File baseDir = new File(baseDirProp)
-            if (baseDir.exists() && baseDir.isDirectory()) {
-                return baseDir
-            }
-        }
-
-        File sourceDirectory = compilationTargetDirectory
-        while (sourceDirectory != null && !(sourceDirectory.name in ['build', 'target'])) {
-            sourceDirectory = sourceDirectory.parentFile
-        }
-        sourceDirectory?.parentFile
+        FactoriesFileWriter.updateFactoriesWithType(classNode, superType, compilationTargetDirectory,
+                'META-INF/grails.factories', ['src/main/resources/META-INF/grails.factories'])
     }
 
     static LinkedHashSet<String> pendingPluginClasses = []
diff --git a/grails-core/src/main/groovy/org/grails/core/io/support/GrailsFactoriesLoader.groovy b/grails-core/src/main/groovy/org/grails/core/io/support/GrailsFactoriesLoader.groovy
index 560d23bd2d..51f1843b9c 100644
--- a/grails-core/src/main/groovy/org/grails/core/io/support/GrailsFactoriesLoader.groovy
+++ b/grails-core/src/main/groovy/org/grails/core/io/support/GrailsFactoriesLoader.groovy
@@ -61,6 +61,30 @@ class GrailsFactoriesLoader extends FactoriesLoaderSupport {
         (List<T>) loadFactoriesWithArguments(factoryClass, classLoader, NO_ARGUMENTS)
     }
 
+    /**
+     * Load the factory implementations of the given type from the given resource location,
+     * using the given class loader.
+     * <p>The returned factories are ordered in accordance with the {@link org.springframework.core.OrderComparator}.
+     * @param factoryClass the interface or abstract class representing the factory
+     * @param classLoader the ClassLoader to use for loading (can be {@code null} to use the default)
+     * @param resourceLocation the classpath location of the factories files to read
+     *          (e.g. {@link #CLI_FACTORIES_RESOURCE_LOCATION})
+     */
+    static <T> List<T> loadFactories(Class<T> factoryClass, ClassLoader classLoader, String resourceLocation) {
+        List<T> results = []
+        for (Class<? extends T> clazz : loadFactoryClasses(factoryClass, classLoader, resourceLocation)) {
+            results.add(clazz.getDeclaredConstructor().newInstance())
+        }
+
+        // This list should always be rather small, so sort the handlers by class name.  This will provide
+        // a deterministic order before accounting for PriorityOrdering
+        results.sort { T a, T b ->
+            a?.getClass()?.name <=> b?.getClass()?.name
+        }
+        OrderComparator.sort((List<T>) results)
+        results
+    }
+
     static <T> List<T> loadFactoriesWithArguments(Class<T> factoryClass, ClassLoader classLoader, Object[] arguments) {
         boolean hasArguments = !(arguments != null && arguments.length == 0)
         List<T> results = new ArrayList<T>()
@@ -77,10 +101,11 @@ class GrailsFactoriesLoader extends FactoriesLoaderSupport {
         results
     }
 
-    static <T> List<Class<T>> loadFactoryClasses(Class<T> factoryClass, ClassLoader classLoader = GrailsFactoriesLoader.classLoader) {
+    static <T> List<Class<T>> loadFactoryClasses(Class<T> factoryClass, ClassLoader classLoader = GrailsFactoriesLoader.classLoader,
+                                                 String resourceLocation = FACTORIES_RESOURCE_LOCATION) {
         Assert.notNull(factoryClass, "'factoryClass' must not be null")
 
-        def factoryNames = loadFactoryNames(factoryClass, classLoader)
+        def factoryNames = loadFactoryNames(factoryClass, classLoader, resourceLocation)
 
         List<Class<T>> result = []
         for (String factoryName in factoryNames) {
diff --git a/grails-core/src/test/groovy/grails/dev/commands/ConfigReportCommandSpec.groovy b/grails-core/src/test/groovy/org/apache/grails/core/cli/ConfigReportCommandSpec.groovy
similarity index 99%
rename from grails-core/src/test/groovy/grails/dev/commands/ConfigReportCommandSpec.groovy
rename to grails-core/src/test/groovy/org/apache/grails/core/cli/ConfigReportCommandSpec.groovy
index 524f1e9594..8fb83112d1 100644
--- a/grails-core/src/test/groovy/grails/dev/commands/ConfigReportCommandSpec.groovy
+++ b/grails-core/src/test/groovy/org/apache/grails/core/cli/ConfigReportCommandSpec.groovy
@@ -16,7 +16,7 @@
  *  specific language governing permissions and limitations
  *  under the License.
  */
-package grails.dev.commands
+package org.apache.grails.core.cli
 
 import org.springframework.context.ConfigurableApplicationContext
 import org.springframework.core.env.ConfigurableEnvironment
diff --git a/grails-core/src/test/groovy/org/grails/compiler/injection/GlobalGrailsClassInjectorTransformationSpec.groovy b/grails-core/src/test/groovy/org/grails/compiler/injection/GlobalGrailsClassInjectorTransformationSpec.groovy
index f4370a4ba9..e00c498b68 100644
--- a/grails-core/src/test/groovy/org/grails/compiler/injection/GlobalGrailsClassInjectorTransformationSpec.groovy
+++ b/grails-core/src/test/groovy/org/grails/compiler/injection/GlobalGrailsClassInjectorTransformationSpec.groovy
@@ -196,7 +196,7 @@ class FooGrailsPlugin {
             File target = new File(baseDir, 'build/classes/groovy/main')
 
         when:
-            File resolved = GlobalGrailsClassInjectorTransformation.findSourceDirectory(target)
+            File resolved = FactoriesFileWriter.findSourceDirectory(target)
 
         then: "the build-tool supplied base.dir wins"
             resolved == baseDir
@@ -213,7 +213,7 @@ class FooGrailsPlugin {
             File target = new File(projectDir, 'build/classes/groovy/main')
 
         when:
-            File resolved = GlobalGrailsClassInjectorTransformation.findSourceDirectory(target)
+            File resolved = FactoriesFileWriter.findSourceDirectory(target)
 
         then: "it resolves to the parent of the build directory"
             resolved == projectDir
diff --git a/grails-data-hibernate5/dbmigration/build.gradle b/grails-data-hibernate5/dbmigration/build.gradle
index d04e4eaae4..952ed3ffd6 100644
--- a/grails-data-hibernate5/dbmigration/build.gradle
+++ b/grails-data-hibernate5/dbmigration/build.gradle
@@ -21,6 +21,7 @@ plugins {
     id 'org.apache.grails.buildsrc.properties'
     id 'org.apache.grails.buildsrc.dependency-validator'
     id 'org.apache.grails.gradle.grails-plugin'
+    id 'org.apache.grails.gradle.grails-plugin-cli'
     id 'org.apache.grails.buildsrc.compile'
     id 'org.apache.grails.buildsrc.publish'
     id 'org.apache.grails.buildsrc.sbom'
@@ -32,6 +33,12 @@ plugins {
 version = projectVersion
 group = 'org.apache.grails'
 
+cliArtifact {
+    automaticModuleName = 'org.apache.grails.data.hibernate5.dbmigration.cli'
+    // this framework module wires its cli dependencies with project dependencies below
+    defaultDependencies = false
+}
+
 ext {
     gormApiDocs = true
     pomTitle = 'Grails Database Migration Plugin for Hibernate 5'
@@ -54,12 +61,34 @@ dependencies {
         exclude group: 'org.liquibase', module: 'liquibase-core'
     }
 
-    implementation(project(':grails-shell-cli')) {
+    // the cli tier — published separately as org.apache.grails:grails-data-hibernate5-dbmigration-cli;
+    // the dbm-* commands and their CLI-only dependencies (grails-shell-cli) stay off the
+    // application runtime classpath entirely
+    cliImplementation platform(project(':grails-hibernate5-bom'))
+    cliApi project(project.path)
+    cliApi(project(':grails-core')) {
+        capabilities {
+            requireCapability('org.apache.grails:grails-core-cli')
+        }
+    }
+    cliImplementation("org.liquibase:liquibase-core") {
+        exclude group: 'javax.xml.bind', module: 'jaxb-api'
+    }
+    cliImplementation("org.liquibase.ext:liquibase-hibernate5") {
+        exclude group: 'org.hibernate', module: 'hibernate-core'
+        exclude group: 'org.hibernate', module: 'hibernate-entitymanager'
+        exclude group: 'org.hibernate', module: 'hibernate-envers'
+        exclude group: 'com.h2database', module: 'h2'
+        exclude group: 'org.liquibase', module: 'liquibase-commercial'
+        exclude group: 'org.liquibase', module: 'liquibase-core'
+    }
+    cliImplementation project(':grails-data-hibernate5')
+    cliCompileOnly 'org.apache.groovy:groovy-sql'
+    cliCompileOnly 'org.apache.groovy:groovy-xml'
+    cliImplementation(project(':grails-shell-cli')) {
         exclude group: 'org.slf4j', module: 'slf4j-simple'
 
-        // TODO: the shell cli is exporting groovy 3, while this project is expected to use groovy 4
-        //       this plugin needs split into commands & the plugin itself so that different versions
-        //       of groovy can be used
+        // Keep legacy org.codehaus.groovy artifacts off this plugin's Groovy 5 classpath.
         exclude group: 'org.codehaus.groovy'
     }
 
diff --git a/grails-data-hibernate5/dbmigration/src/main/groovy/org/grails/plugins/databasemigration/command/ApplicationContextDatabaseMigrationCommand.groovy b/grails-data-hibernate5/dbmigration/src/cli/groovy/org/apache/grails/data/hibernate5/dbmigration/cli/ApplicationContextDatabaseMigrationCommand.groovy
similarity index 97%
rename from grails-data-hibernate5/dbmigration/src/main/groovy/org/grails/plugins/databasemigration/command/ApplicationContextDatabaseMigrationCommand.groovy
rename to grails-data-hibernate5/dbmigration/src/cli/groovy/org/apache/grails/data/hibernate5/dbmigration/cli/ApplicationContextDatabaseMigrationCommand.groovy
index 26c4a9cf7c..9d95a9f960 100644
--- a/grails-data-hibernate5/dbmigration/src/main/groovy/org/grails/plugins/databasemigration/command/ApplicationContextDatabaseMigrationCommand.groovy
+++ b/grails-data-hibernate5/dbmigration/src/cli/groovy/org/apache/grails/data/hibernate5/dbmigration/cli/ApplicationContextDatabaseMigrationCommand.groovy
@@ -16,7 +16,7 @@
  *  specific language governing permissions and limitations
  *  under the License.
  */
-package org.grails.plugins.databasemigration.command
+package org.apache.grails.data.hibernate5.dbmigration.cli
 
 import groovy.transform.CompileStatic
 import groovy.transform.stc.ClosureParams
@@ -33,7 +33,7 @@ import org.springframework.context.ConfigurableApplicationContext
 
 import grails.config.ConfigMap
 import grails.core.GrailsApplication
-import grails.dev.commands.ExecutionContext
+import org.apache.grails.core.cli.ExecutionContext
 import grails.util.Environment
 import org.grails.config.PropertySourcesConfig
 import org.grails.orm.hibernate.HibernateDatastore
diff --git a/grails-data-hibernate5/dbmigration/src/main/groovy/org/grails/plugins/databasemigration/command/DatabaseMigrationCommand.groovy b/grails-data-hibernate5/dbmigration/src/cli/groovy/org/apache/grails/data/hibernate5/dbmigration/cli/DatabaseMigrationCommand.groovy
similarity index 99%
rename from grails-data-hibernate5/dbmigration/src/main/groovy/org/grails/plugins/databasemigration/command/DatabaseMigrationCommand.groovy
rename to grails-data-hibernate5/dbmigration/src/cli/groovy/org/apache/grails/data/hibernate5/dbmigration/cli/DatabaseMigrationCommand.groovy
index a397467fda..38a3f69992 100644
--- a/grails-data-hibernate5/dbmigration/src/main/groovy/org/grails/plugins/databasemigration/command/DatabaseMigrationCommand.groovy
+++ b/grails-data-hibernate5/dbmigration/src/cli/groovy/org/apache/grails/data/hibernate5/dbmigration/cli/DatabaseMigrationCommand.groovy
@@ -16,7 +16,7 @@
  *  specific language governing permissions and limitations
  *  under the License.
  */
-package org.grails.plugins.databasemigration.command
+package org.apache.grails.data.hibernate5.dbmigration.cli
 
 import java.nio.file.Path
 import java.text.DateFormat
diff --git a/grails-data-hibernate5/dbmigration/grails-app/commands/org/grails/plugins/databasemigration/command/DbmChangelogSyncCommand.groovy b/grails-data-hibernate5/dbmigration/src/cli/groovy/org/apache/grails/data/hibernate5/dbmigration/cli/DbmChangelogSyncCommand.groovy
similarity index 91%
rename from grails-data-hibernate5/dbmigration/grails-app/commands/org/grails/plugins/databasemigration/command/DbmChangelogSyncCommand.groovy
rename to grails-data-hibernate5/dbmigration/src/cli/groovy/org/apache/grails/data/hibernate5/dbmigration/cli/DbmChangelogSyncCommand.groovy
index 25f30e2287..f5cd59fb76 100644
--- a/grails-data-hibernate5/dbmigration/grails-app/commands/org/grails/plugins/databasemigration/command/DbmChangelogSyncCommand.groovy
+++ b/grails-data-hibernate5/dbmigration/src/cli/groovy/org/apache/grails/data/hibernate5/dbmigration/cli/DbmChangelogSyncCommand.groovy
@@ -16,13 +16,13 @@
  *  specific language governing permissions and limitations
  *  under the License.
  */
-package org.grails.plugins.databasemigration.command
+package org.apache.grails.data.hibernate5.dbmigration.cli
 
 import groovy.transform.CompileStatic
 
 import liquibase.Liquibase
 
-import grails.dev.commands.ApplicationCommand
+import org.apache.grails.core.cli.ApplicationCommand
 
 @CompileStatic
 class DbmChangelogSyncCommand implements ApplicationCommand, ApplicationContextDatabaseMigrationCommand {
diff --git a/grails-data-hibernate7/dbmigration/grails-app/commands/org/grails/plugins/databasemigration/command/DbmChangelogSyncSqlCommand.groovy b/grails-data-hibernate5/dbmigration/src/cli/groovy/org/apache/grails/data/hibernate5/dbmigration/cli/DbmChangelogSyncSqlCommand.groovy
similarity index 92%
rename from grails-data-hibernate7/dbmigration/grails-app/commands/org/grails/plugins/databasemigration/command/DbmChangelogSyncSqlCommand.groovy
rename to grails-data-hibernate5/dbmigration/src/cli/groovy/org/apache/grails/data/hibernate5/dbmigration/cli/DbmChangelogSyncSqlCommand.groovy
index 476d383410..e0ba83f288 100644
--- a/grails-data-hibernate7/dbmigration/grails-app/commands/org/grails/plugins/databasemigration/command/DbmChangelogSyncSqlCommand.groovy
+++ b/grails-data-hibernate5/dbmigration/src/cli/groovy/org/apache/grails/data/hibernate5/dbmigration/cli/DbmChangelogSyncSqlCommand.groovy
@@ -16,13 +16,13 @@
  *  specific language governing permissions and limitations
  *  under the License.
  */
-package org.grails.plugins.databasemigration.command
+package org.apache.grails.data.hibernate5.dbmigration.cli
 
 import groovy.transform.CompileStatic
 
 import liquibase.Liquibase
 
-import grails.dev.commands.ApplicationCommand
+import org.apache.grails.core.cli.ApplicationCommand
 
 @CompileStatic
 class DbmChangelogSyncSqlCommand implements ApplicationCommand, ApplicationContextDatabaseMigrationCommand {
diff --git a/grails-data-hibernate5/dbmigration/src/main/groovy/org/grails/plugins/databasemigration/command/DbmChangelogToGroovy.groovy b/grails-data-hibernate5/dbmigration/src/cli/groovy/org/apache/grails/data/hibernate5/dbmigration/cli/DbmChangelogToGroovy.groovy
similarity index 98%
rename from grails-data-hibernate5/dbmigration/src/main/groovy/org/grails/plugins/databasemigration/command/DbmChangelogToGroovy.groovy
rename to grails-data-hibernate5/dbmigration/src/cli/groovy/org/apache/grails/data/hibernate5/dbmigration/cli/DbmChangelogToGroovy.groovy
index 532ca699bc..1f5c1a0935 100644
--- a/grails-data-hibernate5/dbmigration/src/main/groovy/org/grails/plugins/databasemigration/command/DbmChangelogToGroovy.groovy
+++ b/grails-data-hibernate5/dbmigration/src/cli/groovy/org/apache/grails/data/hibernate5/dbmigration/cli/DbmChangelogToGroovy.groovy
@@ -16,7 +16,7 @@
  *  specific language governing permissions and limitations
  *  under the License.
  */
-package org.grails.plugins.databasemigration.command
+package org.apache.grails.data.hibernate5.dbmigration.cli
 
 import groovy.transform.CompileStatic
 import groovy.transform.stc.ClosureParams
diff --git a/grails-data-hibernate7/dbmigration/grails-app/commands/org/grails/plugins/databasemigration/command/DbmClearChecksumsCommand.groovy b/grails-data-hibernate5/dbmigration/src/cli/groovy/org/apache/grails/data/hibernate5/dbmigration/cli/DbmClearChecksumsCommand.groovy
similarity index 91%
rename from grails-data-hibernate7/dbmigration/grails-app/commands/org/grails/plugins/databasemigration/command/DbmClearChecksumsCommand.groovy
rename to grails-data-hibernate5/dbmigration/src/cli/groovy/org/apache/grails/data/hibernate5/dbmigration/cli/DbmClearChecksumsCommand.groovy
index 0006e1649b..0c81b5b303 100644
--- a/grails-data-hibernate7/dbmigration/grails-app/commands/org/grails/plugins/databasemigration/command/DbmClearChecksumsCommand.groovy
+++ b/grails-data-hibernate5/dbmigration/src/cli/groovy/org/apache/grails/data/hibernate5/dbmigration/cli/DbmClearChecksumsCommand.groovy
@@ -16,13 +16,13 @@
  *  specific language governing permissions and limitations
  *  under the License.
  */
-package org.grails.plugins.databasemigration.command
+package org.apache.grails.data.hibernate5.dbmigration.cli
 
 import groovy.transform.CompileStatic
 
 import liquibase.Liquibase
 
-import grails.dev.commands.ApplicationCommand
+import org.apache.grails.core.cli.ApplicationCommand
 
 @CompileStatic
 class DbmClearChecksumsCommand implements ApplicationCommand, ApplicationContextDatabaseMigrationCommand {
diff --git a/grails-data-hibernate7/dbmigration/src/main/groovy/org/grails/plugins/databasemigration/command/DbmCreateChangelog.groovy b/grails-data-hibernate5/dbmigration/src/cli/groovy/org/apache/grails/data/hibernate5/dbmigration/cli/DbmCreateChangelog.groovy
similarity index 97%
rename from grails-data-hibernate7/dbmigration/src/main/groovy/org/grails/plugins/databasemigration/command/DbmCreateChangelog.groovy
rename to grails-data-hibernate5/dbmigration/src/cli/groovy/org/apache/grails/data/hibernate5/dbmigration/cli/DbmCreateChangelog.groovy
index dddc41bfa6..9f5ff40f88 100644
--- a/grails-data-hibernate7/dbmigration/src/main/groovy/org/grails/plugins/databasemigration/command/DbmCreateChangelog.groovy
+++ b/grails-data-hibernate5/dbmigration/src/cli/groovy/org/apache/grails/data/hibernate5/dbmigration/cli/DbmCreateChangelog.groovy
@@ -16,7 +16,7 @@
  *  specific language governing permissions and limitations
  *  under the License.
  */
-package org.grails.plugins.databasemigration.command
+package org.apache.grails.data.hibernate5.dbmigration.cli
 
 import groovy.transform.CompileStatic
 
diff --git a/grails-data-hibernate7/dbmigration/grails-app/commands/org/grails/plugins/databasemigration/command/DbmDbDocCommand.groovy b/grails-data-hibernate5/dbmigration/src/cli/groovy/org/apache/grails/data/hibernate5/dbmigration/cli/DbmDbDocCommand.groovy
similarity index 92%
rename from grails-data-hibernate7/dbmigration/grails-app/commands/org/grails/plugins/databasemigration/command/DbmDbDocCommand.groovy
rename to grails-data-hibernate5/dbmigration/src/cli/groovy/org/apache/grails/data/hibernate5/dbmigration/cli/DbmDbDocCommand.groovy
index 059ff5208e..6a6e916ee2 100644
--- a/grails-data-hibernate7/dbmigration/grails-app/commands/org/grails/plugins/databasemigration/command/DbmDbDocCommand.groovy
+++ b/grails-data-hibernate5/dbmigration/src/cli/groovy/org/apache/grails/data/hibernate5/dbmigration/cli/DbmDbDocCommand.groovy
@@ -16,13 +16,13 @@
  *  specific language governing permissions and limitations
  *  under the License.
  */
-package org.grails.plugins.databasemigration.command
+package org.apache.grails.data.hibernate5.dbmigration.cli
 
 import groovy.transform.CompileStatic
 
 import liquibase.Liquibase
 
-import grails.dev.commands.ApplicationCommand
+import org.apache.grails.core.cli.ApplicationCommand
 
 @CompileStatic
 class DbmDbDocCommand implements ApplicationCommand, ApplicationContextDatabaseMigrationCommand {
diff --git a/grails-data-hibernate5/dbmigration/grails-app/commands/org/grails/plugins/databasemigration/command/DbmDiffCommand.groovy b/grails-data-hibernate5/dbmigration/src/cli/groovy/org/apache/grails/data/hibernate5/dbmigration/cli/DbmDiffCommand.groovy
similarity index 96%
rename from grails-data-hibernate5/dbmigration/grails-app/commands/org/grails/plugins/databasemigration/command/DbmDiffCommand.groovy
rename to grails-data-hibernate5/dbmigration/src/cli/groovy/org/apache/grails/data/hibernate5/dbmigration/cli/DbmDiffCommand.groovy
index 9e3f1e6a13..8beb8d885a 100644
--- a/grails-data-hibernate5/dbmigration/grails-app/commands/org/grails/plugins/databasemigration/command/DbmDiffCommand.groovy
+++ b/grails-data-hibernate5/dbmigration/src/cli/groovy/org/apache/grails/data/hibernate5/dbmigration/cli/DbmDiffCommand.groovy
@@ -16,13 +16,13 @@
  *  specific language governing permissions and limitations
  *  under the License.
  */
-package org.grails.plugins.databasemigration.command
+package org.apache.grails.data.hibernate5.dbmigration.cli
 
 import groovy.transform.CompileStatic
 
 import liquibase.database.Database
 
-import grails.dev.commands.ApplicationCommand
+import org.apache.grails.core.cli.ApplicationCommand
 import grails.util.Environment
 import org.grails.plugins.databasemigration.DatabaseMigrationException
 
diff --git a/grails-data-hibernate5/dbmigration/grails-app/commands/org/grails/plugins/databasemigration/command/DbmDropAllCommand.groovy b/grails-data-hibernate5/dbmigration/src/cli/groovy/org/apache/grails/data/hibernate5/dbmigration/cli/DbmDropAllCommand.groovy
similarity index 93%
rename from grails-data-hibernate5/dbmigration/grails-app/commands/org/grails/plugins/databasemigration/command/DbmDropAllCommand.groovy
rename to grails-data-hibernate5/dbmigration/src/cli/groovy/org/apache/grails/data/hibernate5/dbmigration/cli/DbmDropAllCommand.groovy
index efbc21c533..cadb3b9bf7 100644
--- a/grails-data-hibernate5/dbmigration/grails-app/commands/org/grails/plugins/databasemigration/command/DbmDropAllCommand.groovy
+++ b/grails-data-hibernate5/dbmigration/src/cli/groovy/org/apache/grails/data/hibernate5/dbmigration/cli/DbmDropAllCommand.groovy
@@ -16,14 +16,14 @@
  *  specific language governing permissions and limitations
  *  under the License.
  */
-package org.grails.plugins.databasemigration.command
+package org.apache.grails.data.hibernate5.dbmigration.cli
 
 import groovy.transform.CompileStatic
 
 import liquibase.CatalogAndSchema
 import liquibase.Liquibase
 
-import grails.dev.commands.ApplicationCommand
+import org.apache.grails.core.cli.ApplicationCommand
 
 @CompileStatic
 class DbmDropAllCommand implements ApplicationCommand, ApplicationContextDatabaseMigrationCommand {
diff --git a/grails-data-hibernate7/dbmigration/grails-app/commands/org/grails/plugins/databasemigration/command/DbmFutureRollbackCountSqlCommand.groovy b/grails-data-hibernate5/dbmigration/src/cli/groovy/org/apache/grails/data/hibernate5/dbmigration/cli/DbmFutureRollbackCountSqlCommand.groovy
similarity index 94%
rename from grails-data-hibernate7/dbmigration/grails-app/commands/org/grails/plugins/databasemigration/command/DbmFutureRollbackCountSqlCommand.groovy
rename to grails-data-hibernate5/dbmigration/src/cli/groovy/org/apache/grails/data/hibernate5/dbmigration/cli/DbmFutureRollbackCountSqlCommand.groovy
index 899a550d92..7141a4f49f 100644
--- a/grails-data-hibernate7/dbmigration/grails-app/commands/org/grails/plugins/databasemigration/command/DbmFutureRollbackCountSqlCommand.groovy
+++ b/grails-data-hibernate5/dbmigration/src/cli/groovy/org/apache/grails/data/hibernate5/dbmigration/cli/DbmFutureRollbackCountSqlCommand.groovy
@@ -16,13 +16,13 @@
  *  specific language governing permissions and limitations
  *  under the License.
  */
-package org.grails.plugins.databasemigration.command
+package org.apache.grails.data.hibernate5.dbmigration.cli
 
 import groovy.transform.CompileStatic
 
 import liquibase.Liquibase
 
-import grails.dev.commands.ApplicationCommand
+import org.apache.grails.core.cli.ApplicationCommand
 import org.grails.plugins.databasemigration.DatabaseMigrationException
 
 @CompileStatic
diff --git a/grails-data-hibernate5/dbmigration/grails-app/commands/org/grails/plugins/databasemigration/command/DbmFutureRollbackSqlCommand.groovy b/grails-data-hibernate5/dbmigration/src/cli/groovy/org/apache/grails/data/hibernate5/dbmigration/cli/DbmFutureRollbackSqlCommand.groovy
similarity index 92%
rename from grails-data-hibernate5/dbmigration/grails-app/commands/org/grails/plugins/databasemigration/command/DbmFutureRollbackSqlCommand.groovy
rename to grails-data-hibernate5/dbmigration/src/cli/groovy/org/apache/grails/data/hibernate5/dbmigration/cli/DbmFutureRollbackSqlCommand.groovy
index 2e7e0d66e0..26f2695889 100644
--- a/grails-data-hibernate5/dbmigration/grails-app/commands/org/grails/plugins/databasemigration/command/DbmFutureRollbackSqlCommand.groovy
+++ b/grails-data-hibernate5/dbmigration/src/cli/groovy/org/apache/grails/data/hibernate5/dbmigration/cli/DbmFutureRollbackSqlCommand.groovy
@@ -16,13 +16,13 @@
  *  specific language governing permissions and limitations
  *  under the License.
  */
-package org.grails.plugins.databasemigration.command
+package org.apache.grails.data.hibernate5.dbmigration.cli
 
 import groovy.transform.CompileStatic
 
 import liquibase.Liquibase
 
-import grails.dev.commands.ApplicationCommand
+import org.apache.grails.core.cli.ApplicationCommand
 
 @CompileStatic
 class DbmFutureRollbackSqlCommand implements ApplicationCommand, ApplicationContextDatabaseMigrationCommand {
diff --git a/grails-data-hibernate7/dbmigration/grails-app/commands/org/grails/plugins/databasemigration/command/DbmGenerateChangelogCommand.groovy b/grails-data-hibernate5/dbmigration/src/cli/groovy/org/apache/grails/data/hibernate5/dbmigration/cli/DbmGenerateChangelogCommand.groovy
similarity index 94%
rename from grails-data-hibernate7/dbmigration/grails-app/commands/org/grails/plugins/databasemigration/command/DbmGenerateChangelogCommand.groovy
rename to grails-data-hibernate5/dbmigration/src/cli/groovy/org/apache/grails/data/hibernate5/dbmigration/cli/DbmGenerateChangelogCommand.groovy
index 73d1e226bd..e719b0392e 100644
--- a/grails-data-hibernate7/dbmigration/grails-app/commands/org/grails/plugins/databasemigration/command/DbmGenerateChangelogCommand.groovy
+++ b/grails-data-hibernate5/dbmigration/src/cli/groovy/org/apache/grails/data/hibernate5/dbmigration/cli/DbmGenerateChangelogCommand.groovy
@@ -16,13 +16,13 @@
  *  specific language governing permissions and limitations
  *  under the License.
  */
-package org.grails.plugins.databasemigration.command
+package org.apache.grails.data.hibernate5.dbmigration.cli
 
 import groovy.transform.CompileStatic
 
 import liquibase.database.Database
 
-import grails.dev.commands.ApplicationCommand
+import org.apache.grails.core.cli.ApplicationCommand
 import org.grails.plugins.databasemigration.DatabaseMigrationException
 
 @CompileStatic
diff --git a/grails-data-hibernate5/dbmigration/grails-app/commands/org/grails/plugins/databasemigration/command/DbmGenerateGormChangelogCommand.groovy b/grails-data-hibernate5/dbmigration/src/cli/groovy/org/apache/grails/data/hibernate5/dbmigration/cli/DbmGenerateGormChangelogCommand.groovy
similarity index 95%
rename from grails-data-hibernate5/dbmigration/grails-app/commands/org/grails/plugins/databasemigration/command/DbmGenerateGormChangelogCommand.groovy
rename to grails-data-hibernate5/dbmigration/src/cli/groovy/org/apache/grails/data/hibernate5/dbmigration/cli/DbmGenerateGormChangelogCommand.groovy
index 8519c83732..fa8ee92a2f 100644
--- a/grails-data-hibernate5/dbmigration/grails-app/commands/org/grails/plugins/databasemigration/command/DbmGenerateGormChangelogCommand.groovy
+++ b/grails-data-hibernate5/dbmigration/src/cli/groovy/org/apache/grails/data/hibernate5/dbmigration/cli/DbmGenerateGormChangelogCommand.groovy
@@ -16,13 +16,13 @@
  *  specific language governing permissions and limitations
  *  under the License.
  */
-package org.grails.plugins.databasemigration.command
+package org.apache.grails.data.hibernate5.dbmigration.cli
 
 import groovy.transform.CompileStatic
 
 import liquibase.database.Database
 
-import grails.dev.commands.ApplicationCommand
+import org.apache.grails.core.cli.ApplicationCommand
 import org.grails.plugins.databasemigration.DatabaseMigrationException
 
 @CompileStatic
diff --git a/grails-data-hibernate7/dbmigration/grails-app/commands/org/grails/plugins/databasemigration/command/DbmGormDiffCommand.groovy b/grails-data-hibernate5/dbmigration/src/cli/groovy/org/apache/grails/data/hibernate5/dbmigration/cli/DbmGormDiffCommand.groovy
similarity index 95%
rename from grails-data-hibernate7/dbmigration/grails-app/commands/org/grails/plugins/databasemigration/command/DbmGormDiffCommand.groovy
rename to grails-data-hibernate5/dbmigration/src/cli/groovy/org/apache/grails/data/hibernate5/dbmigration/cli/DbmGormDiffCommand.groovy
index 52d68b92e0..bd4d649f8d 100644
--- a/grails-data-hibernate7/dbmigration/grails-app/commands/org/grails/plugins/databasemigration/command/DbmGormDiffCommand.groovy
+++ b/grails-data-hibernate5/dbmigration/src/cli/groovy/org/apache/grails/data/hibernate5/dbmigration/cli/DbmGormDiffCommand.groovy
@@ -16,13 +16,13 @@
  *  specific language governing permissions and limitations
  *  under the License.
  */
-package org.grails.plugins.databasemigration.command
+package org.apache.grails.data.hibernate5.dbmigration.cli
 
 import groovy.transform.CompileStatic
 
 import liquibase.database.Database
 
-import grails.dev.commands.ApplicationCommand
+import org.apache.grails.core.cli.ApplicationCommand
 import org.grails.plugins.databasemigration.DatabaseMigrationException
 
 @CompileStatic
diff --git a/grails-data-hibernate5/dbmigration/grails-app/commands/org/grails/plugins/databasemigration/command/DbmListLocksCommand.groovy b/grails-data-hibernate5/dbmigration/src/cli/groovy/org/apache/grails/data/hibernate5/dbmigration/cli/DbmListLocksCommand.groovy
similarity index 94%
rename from grails-data-hibernate5/dbmigration/grails-app/commands/org/grails/plugins/databasemigration/command/DbmListLocksCommand.groovy
rename to grails-data-hibernate5/dbmigration/src/cli/groovy/org/apache/grails/data/hibernate5/dbmigration/cli/DbmListLocksCommand.groovy
index c53d1c9af7..22ae335444 100644
--- a/grails-data-hibernate5/dbmigration/grails-app/commands/org/grails/plugins/databasemigration/command/DbmListLocksCommand.groovy
+++ b/grails-data-hibernate5/dbmigration/src/cli/groovy/org/apache/grails/data/hibernate5/dbmigration/cli/DbmListLocksCommand.groovy
@@ -16,7 +16,7 @@
  *  specific language governing permissions and limitations
  *  under the License.
  */
-package org.grails.plugins.databasemigration.command
+package org.apache.grails.data.hibernate5.dbmigration.cli
 
 import groovy.transform.CompileStatic
 import groovy.transform.stc.ClosureParams
@@ -24,7 +24,7 @@ import groovy.transform.stc.SimpleType
 
 import liquibase.Liquibase
 
-import grails.dev.commands.ApplicationCommand
+import org.apache.grails.core.cli.ApplicationCommand
 
 @CompileStatic
 class DbmListLocksCommand implements ApplicationCommand, ApplicationContextDatabaseMigrationCommand {
diff --git a/grails-data-hibernate7/dbmigration/grails-app/commands/org/grails/plugins/databasemigration/command/DbmMarkNextChangesetRanCommand.groovy b/grails-data-hibernate5/dbmigration/src/cli/groovy/org/apache/grails/data/hibernate5/dbmigration/cli/DbmMarkNextChangesetRanCommand.groovy
similarity index 91%
rename from grails-data-hibernate7/dbmigration/grails-app/commands/org/grails/plugins/databasemigration/command/DbmMarkNextChangesetRanCommand.groovy
rename to grails-data-hibernate5/dbmigration/src/cli/groovy/org/apache/grails/data/hibernate5/dbmigration/cli/DbmMarkNextChangesetRanCommand.groovy
index 4ba6e01987..c95cee7d95 100644
--- a/grails-data-hibernate7/dbmigration/grails-app/commands/org/grails/plugins/databasemigration/command/DbmMarkNextChangesetRanCommand.groovy
+++ b/grails-data-hibernate5/dbmigration/src/cli/groovy/org/apache/grails/data/hibernate5/dbmigration/cli/DbmMarkNextChangesetRanCommand.groovy
@@ -16,13 +16,13 @@
  *  specific language governing permissions and limitations
  *  under the License.
  */
-package org.grails.plugins.databasemigration.command
+package org.apache.grails.data.hibernate5.dbmigration.cli
 
 import groovy.transform.CompileStatic
 
 import liquibase.Liquibase
 
-import grails.dev.commands.ApplicationCommand
+import org.apache.grails.core.cli.ApplicationCommand
 
 @CompileStatic
 class DbmMarkNextChangesetRanCommand implements ApplicationCommand, ApplicationContextDatabaseMigrationCommand {
diff --git a/grails-data-hibernate7/dbmigration/grails-app/commands/org/grails/plugins/databasemigration/command/DbmMarkNextChangesetRanSqlCommand.groovy b/grails-data-hibernate5/dbmigration/src/cli/groovy/org/apache/grails/data/hibernate5/dbmigration/cli/DbmMarkNextChangesetRanSqlCommand.groovy
similarity index 92%
rename from grails-data-hibernate7/dbmigration/grails-app/commands/org/grails/plugins/databasemigration/command/DbmMarkNextChangesetRanSqlCommand.groovy
rename to grails-data-hibernate5/dbmigration/src/cli/groovy/org/apache/grails/data/hibernate5/dbmigration/cli/DbmMarkNextChangesetRanSqlCommand.groovy
index 427c424b94..48e3126d01 100644
--- a/grails-data-hibernate7/dbmigration/grails-app/commands/org/grails/plugins/databasemigration/command/DbmMarkNextChangesetRanSqlCommand.groovy
+++ b/grails-data-hibernate5/dbmigration/src/cli/groovy/org/apache/grails/data/hibernate5/dbmigration/cli/DbmMarkNextChangesetRanSqlCommand.groovy
@@ -16,13 +16,13 @@
  *  specific language governing permissions and limitations
  *  under the License.
  */
-package org.grails.plugins.databasemigration.command
+package org.apache.grails.data.hibernate5.dbmigration.cli
 
 import groovy.transform.CompileStatic
 
 import liquibase.Liquibase
 
-import grails.dev.commands.ApplicationCommand
+import org.apache.grails.core.cli.ApplicationCommand
 
 @CompileStatic
 class DbmMarkNextChangesetRanSqlCommand implements ApplicationCommand, ApplicationContextDatabaseMigrationCommand {
diff --git a/grails-data-hibernate7/dbmigration/grails-app/commands/org/grails/plugins/databasemigration/command/DbmPreviousChangesetSqlCommand.groovy b/grails-data-hibernate5/dbmigration/src/cli/groovy/org/apache/grails/data/hibernate5/dbmigration/cli/DbmPreviousChangesetSqlCommand.groovy
similarity index 95%
rename from grails-data-hibernate7/dbmigration/grails-app/commands/org/grails/plugins/databasemigration/command/DbmPreviousChangesetSqlCommand.groovy
rename to grails-data-hibernate5/dbmigration/src/cli/groovy/org/apache/grails/data/hibernate5/dbmigration/cli/DbmPreviousChangesetSqlCommand.groovy
index 0d4e77405f..242c3fe74d 100644
--- a/grails-data-hibernate7/dbmigration/grails-app/commands/org/grails/plugins/databasemigration/command/DbmPreviousChangesetSqlCommand.groovy
+++ b/grails-data-hibernate5/dbmigration/src/cli/groovy/org/apache/grails/data/hibernate5/dbmigration/cli/DbmPreviousChangesetSqlCommand.groovy
@@ -16,14 +16,14 @@
  *  specific language governing permissions and limitations
  *  under the License.
  */
-package org.grails.plugins.databasemigration.command
+package org.apache.grails.data.hibernate5.dbmigration.cli
 
 import groovy.transform.CompileStatic
 
 import liquibase.Liquibase
 import liquibase.database.Database
 
-import grails.dev.commands.ApplicationCommand
+import org.apache.grails.core.cli.ApplicationCommand
 import org.grails.plugins.databasemigration.DatabaseMigrationException
 
 @CompileStatic
diff --git a/grails-data-hibernate5/dbmigration/grails-app/commands/org/grails/plugins/databasemigration/command/DbmReleaseLocksCommand.groovy b/grails-data-hibernate5/dbmigration/src/cli/groovy/org/apache/grails/data/hibernate5/dbmigration/cli/DbmReleaseLocksCommand.groovy
similarity index 91%
rename from grails-data-hibernate5/dbmigration/grails-app/commands/org/grails/plugins/databasemigration/command/DbmReleaseLocksCommand.groovy
rename to grails-data-hibernate5/dbmigration/src/cli/groovy/org/apache/grails/data/hibernate5/dbmigration/cli/DbmReleaseLocksCommand.groovy
index 61ad05209b..8d010314d9 100644
--- a/grails-data-hibernate5/dbmigration/grails-app/commands/org/grails/plugins/databasemigration/command/DbmReleaseLocksCommand.groovy
+++ b/grails-data-hibernate5/dbmigration/src/cli/groovy/org/apache/grails/data/hibernate5/dbmigration/cli/DbmReleaseLocksCommand.groovy
@@ -16,13 +16,13 @@
  *  specific language governing permissions and limitations
  *  under the License.
  */
-package org.grails.plugins.databasemigration.command
+package org.apache.grails.data.hibernate5.dbmigration.cli
 
 import groovy.transform.CompileStatic
 
 import liquibase.Liquibase
 
-import grails.dev.commands.ApplicationCommand
+import org.apache.grails.core.cli.ApplicationCommand
 
 @CompileStatic
 class DbmReleaseLocksCommand implements ApplicationCommand, ApplicationContextDatabaseMigrationCommand {
diff --git a/grails-data-hibernate7/dbmigration/grails-app/commands/org/grails/plugins/databasemigration/command/DbmRollbackCommand.groovy b/grails-data-hibernate5/dbmigration/src/cli/groovy/org/apache/grails/data/hibernate5/dbmigration/cli/DbmRollbackCommand.groovy
similarity index 93%
rename from grails-data-hibernate7/dbmigration/grails-app/commands/org/grails/plugins/databasemigration/command/DbmRollbackCommand.groovy
rename to grails-data-hibernate5/dbmigration/src/cli/groovy/org/apache/grails/data/hibernate5/dbmigration/cli/DbmRollbackCommand.groovy
index 416ba3c6a4..9dfd84abc0 100644
--- a/grails-data-hibernate7/dbmigration/grails-app/commands/org/grails/plugins/databasemigration/command/DbmRollbackCommand.groovy
+++ b/grails-data-hibernate5/dbmigration/src/cli/groovy/org/apache/grails/data/hibernate5/dbmigration/cli/DbmRollbackCommand.groovy
@@ -16,13 +16,13 @@
  *  specific language governing permissions and limitations
  *  under the License.
  */
-package org.grails.plugins.databasemigration.command
+package org.apache.grails.data.hibernate5.dbmigration.cli
 
 import groovy.transform.CompileStatic
 
 import liquibase.Liquibase
 
-import grails.dev.commands.ApplicationCommand
+import org.apache.grails.core.cli.ApplicationCommand
 import org.grails.plugins.databasemigration.DatabaseMigrationException
 
 @CompileStatic
diff --git a/grails-data-hibernate5/dbmigration/grails-app/commands/org/grails/plugins/databasemigration/command/DbmRollbackCountCommand.groovy b/grails-data-hibernate5/dbmigration/src/cli/groovy/org/apache/grails/data/hibernate5/dbmigration/cli/DbmRollbackCountCommand.groovy
similarity index 93%
rename from grails-data-hibernate5/dbmigration/grails-app/commands/org/grails/plugins/databasemigration/command/DbmRollbackCountCommand.groovy
rename to grails-data-hibernate5/dbmigration/src/cli/groovy/org/apache/grails/data/hibernate5/dbmigration/cli/DbmRollbackCountCommand.groovy
index dc61205b9b..450b8b1a1f 100644
--- a/grails-data-hibernate5/dbmigration/grails-app/commands/org/grails/plugins/databasemigration/command/DbmRollbackCountCommand.groovy
+++ b/grails-data-hibernate5/dbmigration/src/cli/groovy/org/apache/grails/data/hibernate5/dbmigration/cli/DbmRollbackCountCommand.groovy
@@ -16,13 +16,13 @@
  *  specific language governing permissions and limitations
  *  under the License.
  */
-package org.grails.plugins.databasemigration.command
+package org.apache.grails.data.hibernate5.dbmigration.cli
 
 import groovy.transform.CompileStatic
 
 import liquibase.Liquibase
 
-import grails.dev.commands.ApplicationCommand
+import org.apache.grails.core.cli.ApplicationCommand
 import org.grails.plugins.databasemigration.DatabaseMigrationException
 
 @CompileStatic
diff --git a/grails-data-hibernate5/dbmigration/grails-app/commands/org/grails/plugins/databasemigration/command/DbmRollbackCountSqlCommand.groovy b/grails-data-hibernate5/dbmigration/src/cli/groovy/org/apache/grails/data/hibernate5/dbmigration/cli/DbmRollbackCountSqlCommand.groovy
similarity index 94%
rename from grails-data-hibernate5/dbmigration/grails-app/commands/org/grails/plugins/databasemigration/command/DbmRollbackCountSqlCommand.groovy
rename to grails-data-hibernate5/dbmigration/src/cli/groovy/org/apache/grails/data/hibernate5/dbmigration/cli/DbmRollbackCountSqlCommand.groovy
index a9b0a2c313..12eab145f9 100644
--- a/grails-data-hibernate5/dbmigration/grails-app/commands/org/grails/plugins/databasemigration/command/DbmRollbackCountSqlCommand.groovy
+++ b/grails-data-hibernate5/dbmigration/src/cli/groovy/org/apache/grails/data/hibernate5/dbmigration/cli/DbmRollbackCountSqlCommand.groovy
@@ -16,13 +16,13 @@
  *  specific language governing permissions and limitations
  *  under the License.
  */
-package org.grails.plugins.databasemigration.command
+package org.apache.grails.data.hibernate5.dbmigration.cli
 
 import groovy.transform.CompileStatic
 
 import liquibase.Liquibase
 
-import grails.dev.commands.ApplicationCommand
+import org.apache.grails.core.cli.ApplicationCommand
 import org.grails.plugins.databasemigration.DatabaseMigrationException
 
 @CompileStatic
diff --git a/grails-data-hibernate7/dbmigration/grails-app/commands/org/grails/plugins/databasemigration/command/DbmRollbackSqlCommand.groovy b/grails-data-hibernate5/dbmigration/src/cli/groovy/org/apache/grails/data/hibernate5/dbmigration/cli/DbmRollbackSqlCommand.groovy
similarity index 93%
rename from grails-data-hibernate7/dbmigration/grails-app/commands/org/grails/plugins/databasemigration/command/DbmRollbackSqlCommand.groovy
rename to grails-data-hibernate5/dbmigration/src/cli/groovy/org/apache/grails/data/hibernate5/dbmigration/cli/DbmRollbackSqlCommand.groovy
index bea1a2c8bb..b73857762c 100644
--- a/grails-data-hibernate7/dbmigration/grails-app/commands/org/grails/plugins/databasemigration/command/DbmRollbackSqlCommand.groovy
+++ b/grails-data-hibernate5/dbmigration/src/cli/groovy/org/apache/grails/data/hibernate5/dbmigration/cli/DbmRollbackSqlCommand.groovy
@@ -16,13 +16,13 @@
  *  specific language governing permissions and limitations
  *  under the License.
  */
-package org.grails.plugins.databasemigration.command
+package org.apache.grails.data.hibernate5.dbmigration.cli
 
 import groovy.transform.CompileStatic
 
 import liquibase.Liquibase
 
-import grails.dev.commands.ApplicationCommand
+import org.apache.grails.core.cli.ApplicationCommand
 import org.grails.plugins.databasemigration.DatabaseMigrationException
 
 @CompileStatic
diff --git a/grails-data-hibernate5/dbmigration/grails-app/commands/org/grails/plugins/databasemigration/command/DbmRollbackToDateCommand.groovy b/grails-data-hibernate5/dbmigration/src/cli/groovy/org/apache/grails/data/hibernate5/dbmigration/cli/DbmRollbackToDateCommand.groovy
similarity index 94%
rename from grails-data-hibernate5/dbmigration/grails-app/commands/org/grails/plugins/databasemigration/command/DbmRollbackToDateCommand.groovy
rename to grails-data-hibernate5/dbmigration/src/cli/groovy/org/apache/grails/data/hibernate5/dbmigration/cli/DbmRollbackToDateCommand.groovy
index 2b3701a8ef..1eaf5c08bf 100644
--- a/grails-data-hibernate5/dbmigration/grails-app/commands/org/grails/plugins/databasemigration/command/DbmRollbackToDateCommand.groovy
+++ b/grails-data-hibernate5/dbmigration/src/cli/groovy/org/apache/grails/data/hibernate5/dbmigration/cli/DbmRollbackToDateCommand.groovy
@@ -16,7 +16,7 @@
  *  specific language governing permissions and limitations
  *  under the License.
  */
-package org.grails.plugins.databasemigration.command
+package org.apache.grails.data.hibernate5.dbmigration.cli
 
 import java.text.ParseException
 
@@ -24,7 +24,7 @@ import groovy.transform.CompileStatic
 
 import liquibase.Liquibase
 
-import grails.dev.commands.ApplicationCommand
+import org.apache.grails.core.cli.ApplicationCommand
 import org.grails.plugins.databasemigration.DatabaseMigrationException
 
 @CompileStatic
diff --git a/grails-data-hibernate7/dbmigration/grails-app/commands/org/grails/plugins/databasemigration/command/DbmRollbackToDateSqlCommand.groovy b/grails-data-hibernate5/dbmigration/src/cli/groovy/org/apache/grails/data/hibernate5/dbmigration/cli/DbmRollbackToDateSqlCommand.groovy
similarity index 95%
rename from grails-data-hibernate7/dbmigration/grails-app/commands/org/grails/plugins/databasemigration/command/DbmRollbackToDateSqlCommand.groovy
rename to grails-data-hibernate5/dbmigration/src/cli/groovy/org/apache/grails/data/hibernate5/dbmigration/cli/DbmRollbackToDateSqlCommand.groovy
index c263063c92..6b655994d1 100644
--- a/grails-data-hibernate7/dbmigration/grails-app/commands/org/grails/plugins/databasemigration/command/DbmRollbackToDateSqlCommand.groovy
+++ b/grails-data-hibernate5/dbmigration/src/cli/groovy/org/apache/grails/data/hibernate5/dbmigration/cli/DbmRollbackToDateSqlCommand.groovy
@@ -16,7 +16,7 @@
  *  specific language governing permissions and limitations
  *  under the License.
  */
-package org.grails.plugins.databasemigration.command
+package org.apache.grails.data.hibernate5.dbmigration.cli
 
 import java.text.ParseException
 
@@ -24,7 +24,7 @@ import groovy.transform.CompileStatic
 
 import liquibase.Liquibase
 
-import grails.dev.commands.ApplicationCommand
+import org.apache.grails.core.cli.ApplicationCommand
 import org.grails.plugins.databasemigration.DatabaseMigrationException
 
 @CompileStatic
diff --git a/grails-data-hibernate7/dbmigration/grails-app/commands/org/grails/plugins/databasemigration/command/DbmStatusCommand.groovy b/grails-data-hibernate5/dbmigration/src/cli/groovy/org/apache/grails/data/hibernate5/dbmigration/cli/DbmStatusCommand.groovy
similarity index 93%
rename from grails-data-hibernate7/dbmigration/grails-app/commands/org/grails/plugins/databasemigration/command/DbmStatusCommand.groovy
rename to grails-data-hibernate5/dbmigration/src/cli/groovy/org/apache/grails/data/hibernate5/dbmigration/cli/DbmStatusCommand.groovy
index 3465df19d6..26da54945c 100644
--- a/grails-data-hibernate7/dbmigration/grails-app/commands/org/grails/plugins/databasemigration/command/DbmStatusCommand.groovy
+++ b/grails-data-hibernate5/dbmigration/src/cli/groovy/org/apache/grails/data/hibernate5/dbmigration/cli/DbmStatusCommand.groovy
@@ -16,13 +16,13 @@
  *  specific language governing permissions and limitations
  *  under the License.
  */
-package org.grails.plugins.databasemigration.command
+package org.apache.grails.data.hibernate5.dbmigration.cli
 
 import groovy.transform.CompileStatic
 
 import liquibase.Liquibase
 
-import grails.dev.commands.ApplicationCommand
+import org.apache.grails.core.cli.ApplicationCommand
 
 @CompileStatic
 class DbmStatusCommand implements ApplicationCommand, ApplicationContextDatabaseMigrationCommand {
diff --git a/grails-data-hibernate7/dbmigration/grails-app/commands/org/grails/plugins/databasemigration/command/DbmTagCommand.groovy b/grails-data-hibernate5/dbmigration/src/cli/groovy/org/apache/grails/data/hibernate5/dbmigration/cli/DbmTagCommand.groovy
similarity index 92%
rename from grails-data-hibernate7/dbmigration/grails-app/commands/org/grails/plugins/databasemigration/command/DbmTagCommand.groovy
rename to grails-data-hibernate5/dbmigration/src/cli/groovy/org/apache/grails/data/hibernate5/dbmigration/cli/DbmTagCommand.groovy
index ba5e30d591..bb669e6588 100644
--- a/grails-data-hibernate7/dbmigration/grails-app/commands/org/grails/plugins/databasemigration/command/DbmTagCommand.groovy
+++ b/grails-data-hibernate5/dbmigration/src/cli/groovy/org/apache/grails/data/hibernate5/dbmigration/cli/DbmTagCommand.groovy
@@ -16,13 +16,13 @@
  *  specific language governing permissions and limitations
  *  under the License.
  */
-package org.grails.plugins.databasemigration.command
+package org.apache.grails.data.hibernate5.dbmigration.cli
 
 import groovy.transform.CompileStatic
 
 import liquibase.Liquibase
 
-import grails.dev.commands.ApplicationCommand
+import org.apache.grails.core.cli.ApplicationCommand
 import org.grails.plugins.databasemigration.DatabaseMigrationException
 
 @CompileStatic
diff --git a/grails-data-hibernate5/dbmigration/grails-app/commands/org/grails/plugins/databasemigration/command/DbmUpdateCommand.groovy b/grails-data-hibernate5/dbmigration/src/cli/groovy/org/apache/grails/data/hibernate5/dbmigration/cli/DbmUpdateCommand.groovy
similarity index 91%
rename from grails-data-hibernate5/dbmigration/grails-app/commands/org/grails/plugins/databasemigration/command/DbmUpdateCommand.groovy
rename to grails-data-hibernate5/dbmigration/src/cli/groovy/org/apache/grails/data/hibernate5/dbmigration/cli/DbmUpdateCommand.groovy
index 2306b00c1d..16f769c2a3 100644
--- a/grails-data-hibernate5/dbmigration/grails-app/commands/org/grails/plugins/databasemigration/command/DbmUpdateCommand.groovy
+++ b/grails-data-hibernate5/dbmigration/src/cli/groovy/org/apache/grails/data/hibernate5/dbmigration/cli/DbmUpdateCommand.groovy
@@ -16,13 +16,13 @@
  *  specific language governing permissions and limitations
  *  under the License.
  */
-package org.grails.plugins.databasemigration.command
+package org.apache.grails.data.hibernate5.dbmigration.cli
 
 import groovy.transform.CompileStatic
 
 import liquibase.Liquibase
 
-import grails.dev.commands.ApplicationCommand
+import org.apache.grails.core.cli.ApplicationCommand
 
 @CompileStatic
 class DbmUpdateCommand implements ApplicationCommand, ApplicationContextDatabaseMigrationCommand {
diff --git a/grails-data-hibernate5/dbmigration/grails-app/commands/org/grails/plugins/databasemigration/command/DbmUpdateCountCommand.groovy b/grails-data-hibernate5/dbmigration/src/cli/groovy/org/apache/grails/data/hibernate5/dbmigration/cli/DbmUpdateCountCommand.groovy
similarity index 93%
rename from grails-data-hibernate5/dbmigration/grails-app/commands/org/grails/plugins/databasemigration/command/DbmUpdateCountCommand.groovy
rename to grails-data-hibernate5/dbmigration/src/cli/groovy/org/apache/grails/data/hibernate5/dbmigration/cli/DbmUpdateCountCommand.groovy
index 663c73dfc1..dfc21ad123 100644
--- a/grails-data-hibernate5/dbmigration/grails-app/commands/org/grails/plugins/databasemigration/command/DbmUpdateCountCommand.groovy
+++ b/grails-data-hibernate5/dbmigration/src/cli/groovy/org/apache/grails/data/hibernate5/dbmigration/cli/DbmUpdateCountCommand.groovy
@@ -16,13 +16,13 @@
  *  specific language governing permissions and limitations
  *  under the License.
  */
-package org.grails.plugins.databasemigration.command
+package org.apache.grails.data.hibernate5.dbmigration.cli
 
 import groovy.transform.CompileStatic
 
 import liquibase.Liquibase
 
-import grails.dev.commands.ApplicationCommand
+import org.apache.grails.core.cli.ApplicationCommand
 import org.grails.plugins.databasemigration.DatabaseMigrationException
 
 @CompileStatic
diff --git a/grails-data-hibernate5/dbmigration/grails-app/commands/org/grails/plugins/databasemigration/command/DbmUpdateCountSqlCommand.groovy b/grails-data-hibernate5/dbmigration/src/cli/groovy/org/apache/grails/data/hibernate5/dbmigration/cli/DbmUpdateCountSqlCommand.groovy
similarity index 94%
rename from grails-data-hibernate5/dbmigration/grails-app/commands/org/grails/plugins/databasemigration/command/DbmUpdateCountSqlCommand.groovy
rename to grails-data-hibernate5/dbmigration/src/cli/groovy/org/apache/grails/data/hibernate5/dbmigration/cli/DbmUpdateCountSqlCommand.groovy
index be681a37b8..a7ea191c68 100644
--- a/grails-data-hibernate5/dbmigration/grails-app/commands/org/grails/plugins/databasemigration/command/DbmUpdateCountSqlCommand.groovy
+++ b/grails-data-hibernate5/dbmigration/src/cli/groovy/org/apache/grails/data/hibernate5/dbmigration/cli/DbmUpdateCountSqlCommand.groovy
@@ -16,13 +16,13 @@
  *  specific language governing permissions and limitations
  *  under the License.
  */
-package org.grails.plugins.databasemigration.command
+package org.apache.grails.data.hibernate5.dbmigration.cli
 
 import groovy.transform.CompileStatic
 
 import liquibase.Liquibase
 
-import grails.dev.commands.ApplicationCommand
+import org.apache.grails.core.cli.ApplicationCommand
 import org.grails.plugins.databasemigration.DatabaseMigrationException
 
 @CompileStatic
diff --git a/grails-data-hibernate7/dbmigration/grails-app/commands/org/grails/plugins/databasemigration/command/DbmUpdateSqlCommand.groovy b/grails-data-hibernate5/dbmigration/src/cli/groovy/org/apache/grails/data/hibernate5/dbmigration/cli/DbmUpdateSqlCommand.groovy
similarity index 92%
rename from grails-data-hibernate7/dbmigration/grails-app/commands/org/grails/plugins/databasemigration/command/DbmUpdateSqlCommand.groovy
rename to grails-data-hibernate5/dbmigration/src/cli/groovy/org/apache/grails/data/hibernate5/dbmigration/cli/DbmUpdateSqlCommand.groovy
index a58602ef5b..27dd1e5e87 100644
--- a/grails-data-hibernate7/dbmigration/grails-app/commands/org/grails/plugins/databasemigration/command/DbmUpdateSqlCommand.groovy
+++ b/grails-data-hibernate5/dbmigration/src/cli/groovy/org/apache/grails/data/hibernate5/dbmigration/cli/DbmUpdateSqlCommand.groovy
@@ -16,13 +16,13 @@
  *  specific language governing permissions and limitations
  *  under the License.
  */
-package org.grails.plugins.databasemigration.command
+package org.apache.grails.data.hibernate5.dbmigration.cli
 
 import groovy.transform.CompileStatic
 
 import liquibase.Liquibase
 
-import grails.dev.commands.ApplicationCommand
+import org.apache.grails.core.cli.ApplicationCommand
 
 @CompileStatic
 class DbmUpdateSqlCommand implements ApplicationCommand, ApplicationContextDatabaseMigrationCommand {
diff --git a/grails-data-hibernate7/dbmigration/grails-app/commands/org/grails/plugins/databasemigration/command/DbmValidateCommand.groovy b/grails-data-hibernate5/dbmigration/src/cli/groovy/org/apache/grails/data/hibernate5/dbmigration/cli/DbmValidateCommand.groovy
similarity index 91%
rename from grails-data-hibernate7/dbmigration/grails-app/commands/org/grails/plugins/databasemigration/command/DbmValidateCommand.groovy
rename to grails-data-hibernate5/dbmigration/src/cli/groovy/org/apache/grails/data/hibernate5/dbmigration/cli/DbmValidateCommand.groovy
index d62c81b558..b98136cf43 100644
--- a/grails-data-hibernate7/dbmigration/grails-app/commands/org/grails/plugins/databasemigration/command/DbmValidateCommand.groovy
+++ b/grails-data-hibernate5/dbmigration/src/cli/groovy/org/apache/grails/data/hibernate5/dbmigration/cli/DbmValidateCommand.groovy
@@ -16,13 +16,13 @@
  *  specific language governing permissions and limitations
  *  under the License.
  */
-package org.grails.plugins.databasemigration.command
+package org.apache.grails.data.hibernate5.dbmigration.cli
 
 import groovy.transform.CompileStatic
 
 import liquibase.Liquibase
 
-import grails.dev.commands.ApplicationCommand
+import org.apache.grails.core.cli.ApplicationCommand
 
 @CompileStatic
 class DbmValidateCommand implements ApplicationCommand, ApplicationContextDatabaseMigrationCommand {
diff --git a/grails-data-hibernate5/dbmigration/src/main/groovy/org/grails/plugins/databasemigration/command/ScriptDatabaseMigrationCommand.groovy b/grails-data-hibernate5/dbmigration/src/cli/groovy/org/apache/grails/data/hibernate5/dbmigration/cli/ScriptDatabaseMigrationCommand.groovy
similarity index 97%
rename from grails-data-hibernate5/dbmigration/src/main/groovy/org/grails/plugins/databasemigration/command/ScriptDatabaseMigrationCommand.groovy
rename to grails-data-hibernate5/dbmigration/src/cli/groovy/org/apache/grails/data/hibernate5/dbmigration/cli/ScriptDatabaseMigrationCommand.groovy
index 0be43b3e95..11a1bc7598 100644
--- a/grails-data-hibernate5/dbmigration/src/main/groovy/org/grails/plugins/databasemigration/command/ScriptDatabaseMigrationCommand.groovy
+++ b/grails-data-hibernate5/dbmigration/src/cli/groovy/org/apache/grails/data/hibernate5/dbmigration/cli/ScriptDatabaseMigrationCommand.groovy
@@ -16,7 +16,7 @@
  *  specific language governing permissions and limitations
  *  under the License.
  */
-package org.grails.plugins.databasemigration.command
+package org.apache.grails.data.hibernate5.dbmigration.cli
 
 import groovy.transform.CompileStatic
 
diff --git a/grails-data-hibernate5/dbmigration/src/main/scripts/dbm-changelog-to-groovy.groovy b/grails-data-hibernate5/dbmigration/src/cli/resources/META-INF/commands/dbm-changelog-to-groovy.groovy
similarity index 95%
rename from grails-data-hibernate5/dbmigration/src/main/scripts/dbm-changelog-to-groovy.groovy
rename to grails-data-hibernate5/dbmigration/src/cli/resources/META-INF/commands/dbm-changelog-to-groovy.groovy
index 44bd0a7082..fb6a71dbc7 100644
--- a/grails-data-hibernate5/dbmigration/src/main/scripts/dbm-changelog-to-groovy.groovy
+++ b/grails-data-hibernate5/dbmigration/src/cli/resources/META-INF/commands/dbm-changelog-to-groovy.groovy
@@ -18,7 +18,7 @@
  */
 
 import org.grails.plugins.databasemigration.DatabaseMigrationException
-import org.grails.plugins.databasemigration.command.DbmChangelogToGroovy
+import org.apache.grails.data.hibernate5.dbmigration.cli.DbmChangelogToGroovy
 
 description('Converts a changelog file to a Groovy DSL file') {
     usage 'grails [environment] dbm-changelog-to-groovy [src_file_name] [dest_file_name]'
diff --git a/grails-data-hibernate5/dbmigration/src/main/scripts/dbm-create-changelog.groovy b/grails-data-hibernate5/dbmigration/src/cli/resources/META-INF/commands/dbm-create-changelog.groovy
similarity index 95%
rename from grails-data-hibernate5/dbmigration/src/main/scripts/dbm-create-changelog.groovy
rename to grails-data-hibernate5/dbmigration/src/cli/resources/META-INF/commands/dbm-create-changelog.groovy
index accff252db..52340ae277 100644
--- a/grails-data-hibernate5/dbmigration/src/main/scripts/dbm-create-changelog.groovy
+++ b/grails-data-hibernate5/dbmigration/src/cli/resources/META-INF/commands/dbm-create-changelog.groovy
@@ -18,7 +18,7 @@
  */
 
 import org.grails.plugins.databasemigration.DatabaseMigrationException
-import org.grails.plugins.databasemigration.command.DbmCreateChangelog
+import org.apache.grails.data.hibernate5.dbmigration.cli.DbmCreateChangelog
 
 description('Creates an empty changelog file') {
     usage 'grails [environment] dbm-create-changelog [filename]'
diff --git a/grails-data-hibernate5/dbmigration/src/integration-test/groovy/org/grails/plugins/databasemigration/DbUpdateCommandSpec.groovy b/grails-data-hibernate5/dbmigration/src/integration-test/groovy/org/grails/plugins/databasemigration/DbUpdateCommandSpec.groovy
index 466e124794..e5c4abaeb5 100644
--- a/grails-data-hibernate5/dbmigration/src/integration-test/groovy/org/grails/plugins/databasemigration/DbUpdateCommandSpec.groovy
+++ b/grails-data-hibernate5/dbmigration/src/integration-test/groovy/org/grails/plugins/databasemigration/DbUpdateCommandSpec.groovy
@@ -19,8 +19,8 @@
 
 package org.grails.plugins.databasemigration
 
-import grails.dev.commands.ApplicationCommand
-import grails.dev.commands.ExecutionContext
+import org.apache.grails.core.cli.ApplicationCommand
+import org.apache.grails.core.cli.ExecutionContext
 import grails.testing.mixin.integration.Integration
 import grails.util.GrailsNameUtils
 import groovy.sql.Sql
@@ -28,7 +28,7 @@ import liquibase.GlobalConfiguration
 import liquibase.Scope
 import liquibase.exception.LiquibaseException
 import org.grails.build.parsing.CommandLineParser
-import org.grails.plugins.databasemigration.command.DbmUpdateCommand
+import org.apache.grails.data.hibernate5.dbmigration.cli.DbmUpdateCommand
 import org.springframework.beans.factory.annotation.Autowired
 import org.springframework.context.ApplicationContext
 import org.springframework.stereotype.Component
diff --git a/grails-data-hibernate5/dbmigration/src/test/groovy/org/grails/plugins/databasemigration/command/ApplicationContextDatabaseMigrationCommandSpec.groovy b/grails-data-hibernate5/dbmigration/src/test/groovy/org/apache/grails/data/hibernate5/dbmigration/cli/ApplicationContextDatabaseMigrationCommandSpec.groovy
similarity index 96%
rename from grails-data-hibernate5/dbmigration/src/test/groovy/org/grails/plugins/databasemigration/command/ApplicationContextDatabaseMigrationCommandSpec.groovy
rename to grails-data-hibernate5/dbmigration/src/test/groovy/org/apache/grails/data/hibernate5/dbmigration/cli/ApplicationContextDatabaseMigrationCommandSpec.groovy
index 9199398b00..170ecef0b4 100644
--- a/grails-data-hibernate5/dbmigration/src/test/groovy/org/grails/plugins/databasemigration/command/ApplicationContextDatabaseMigrationCommandSpec.groovy
+++ b/grails-data-hibernate5/dbmigration/src/test/groovy/org/apache/grails/data/hibernate5/dbmigration/cli/ApplicationContextDatabaseMigrationCommandSpec.groovy
@@ -17,14 +17,14 @@
  *  under the License.
  */
 
-package org.grails.plugins.databasemigration.command
+package org.apache.grails.data.hibernate5.dbmigration.cli
 
 import grails.config.Config
 import grails.core.DefaultGrailsApplication
 import grails.core.GrailsApplication
 import grails.core.support.GrailsApplicationAware
-import grails.dev.commands.ApplicationCommand
-import grails.dev.commands.ExecutionContext
+import org.apache.grails.core.cli.ApplicationCommand
+import org.apache.grails.core.cli.ExecutionContext
 import grails.orm.bootstrap.HibernateDatastoreSpringInitializer
 import grails.persistence.Entity
 import grails.util.GrailsNameUtils
diff --git a/grails-data-hibernate7/dbmigration/src/test/groovy/org/grails/plugins/databasemigration/command/DatabaseMigrationCommandConfigSpec.groovy b/grails-data-hibernate5/dbmigration/src/test/groovy/org/apache/grails/data/hibernate5/dbmigration/cli/DatabaseMigrationCommandConfigSpec.groovy
similarity index 98%
rename from grails-data-hibernate7/dbmigration/src/test/groovy/org/grails/plugins/databasemigration/command/DatabaseMigrationCommandConfigSpec.groovy
rename to grails-data-hibernate5/dbmigration/src/test/groovy/org/apache/grails/data/hibernate5/dbmigration/cli/DatabaseMigrationCommandConfigSpec.groovy
index 5a0f6baa5d..fcf1274a91 100644
--- a/grails-data-hibernate7/dbmigration/src/test/groovy/org/grails/plugins/databasemigration/command/DatabaseMigrationCommandConfigSpec.groovy
+++ b/grails-data-hibernate5/dbmigration/src/test/groovy/org/apache/grails/data/hibernate5/dbmigration/cli/DatabaseMigrationCommandConfigSpec.groovy
@@ -16,7 +16,7 @@
  *  specific language governing permissions and limitations
  *  under the License.
  */
-package org.grails.plugins.databasemigration.command
+package org.apache.grails.data.hibernate5.dbmigration.cli
 
 import org.h2.Driver
 import spock.lang.Specification
diff --git a/grails-data-hibernate5/dbmigration/src/test/groovy/org/grails/plugins/databasemigration/command/DatabaseMigrationCommandSpec.groovy b/grails-data-hibernate5/dbmigration/src/test/groovy/org/apache/grails/data/hibernate5/dbmigration/cli/DatabaseMigrationCommandSpec.groovy
similarity index 96%
rename from grails-data-hibernate5/dbmigration/src/test/groovy/org/grails/plugins/databasemigration/command/DatabaseMigrationCommandSpec.groovy
rename to grails-data-hibernate5/dbmigration/src/test/groovy/org/apache/grails/data/hibernate5/dbmigration/cli/DatabaseMigrationCommandSpec.groovy
index 574b5807ce..07ec158caf 100644
--- a/grails-data-hibernate5/dbmigration/src/test/groovy/org/grails/plugins/databasemigration/command/DatabaseMigrationCommandSpec.groovy
+++ b/grails-data-hibernate5/dbmigration/src/test/groovy/org/apache/grails/data/hibernate5/dbmigration/cli/DatabaseMigrationCommandSpec.groovy
@@ -16,7 +16,7 @@
  *  specific language governing permissions and limitations
  *  under the License.
  */
-package org.grails.plugins.databasemigration.command
+package org.apache.grails.data.hibernate5.dbmigration.cli
 
 import groovy.sql.Sql
 import org.grails.plugins.databasemigration.testing.annotation.OutputCapture
diff --git a/grails-data-hibernate7/dbmigration/src/test/groovy/org/grails/plugins/databasemigration/command/DbmChangelogSyncCommandSpec.groovy b/grails-data-hibernate5/dbmigration/src/test/groovy/org/apache/grails/data/hibernate5/dbmigration/cli/DbmChangelogSyncCommandSpec.groovy
similarity index 93%
rename from grails-data-hibernate7/dbmigration/src/test/groovy/org/grails/plugins/databasemigration/command/DbmChangelogSyncCommandSpec.groovy
rename to grails-data-hibernate5/dbmigration/src/test/groovy/org/apache/grails/data/hibernate5/dbmigration/cli/DbmChangelogSyncCommandSpec.groovy
index 524e8b2503..8acc1afc1d 100644
--- a/grails-data-hibernate7/dbmigration/src/test/groovy/org/grails/plugins/databasemigration/command/DbmChangelogSyncCommandSpec.groovy
+++ b/grails-data-hibernate5/dbmigration/src/test/groovy/org/apache/grails/data/hibernate5/dbmigration/cli/DbmChangelogSyncCommandSpec.groovy
@@ -16,9 +16,9 @@
  *  specific language governing permissions and limitations
  *  under the License.
  */
-package org.grails.plugins.databasemigration.command
+package org.apache.grails.data.hibernate5.dbmigration.cli
 
-import grails.dev.commands.ApplicationCommand
+import org.apache.grails.core.cli.ApplicationCommand
 
 class DbmChangelogSyncCommandSpec extends ApplicationContextDatabaseMigrationCommandSpec {
 
diff --git a/grails-data-hibernate7/dbmigration/src/test/groovy/org/grails/plugins/databasemigration/command/DbmChangelogSyncCommandSqlSpec.groovy b/grails-data-hibernate5/dbmigration/src/test/groovy/org/apache/grails/data/hibernate5/dbmigration/cli/DbmChangelogSyncCommandSqlSpec.groovy
similarity index 95%
rename from grails-data-hibernate7/dbmigration/src/test/groovy/org/grails/plugins/databasemigration/command/DbmChangelogSyncCommandSqlSpec.groovy
rename to grails-data-hibernate5/dbmigration/src/test/groovy/org/apache/grails/data/hibernate5/dbmigration/cli/DbmChangelogSyncCommandSqlSpec.groovy
index 2db88a8ff5..a4486e64c9 100644
--- a/grails-data-hibernate7/dbmigration/src/test/groovy/org/grails/plugins/databasemigration/command/DbmChangelogSyncCommandSqlSpec.groovy
+++ b/grails-data-hibernate5/dbmigration/src/test/groovy/org/apache/grails/data/hibernate5/dbmigration/cli/DbmChangelogSyncCommandSqlSpec.groovy
@@ -16,9 +16,9 @@
  *  specific language governing permissions and limitations
  *  under the License.
  */
-package org.grails.plugins.databasemigration.command
+package org.apache.grails.data.hibernate5.dbmigration.cli
 
-import grails.dev.commands.ApplicationCommand
+import org.apache.grails.core.cli.ApplicationCommand
 import spock.lang.AutoCleanup
 
 class DbmChangelogSyncCommandSqlSpec extends ApplicationContextDatabaseMigrationCommandSpec {
diff --git a/grails-data-hibernate7/dbmigration/src/test/groovy/org/grails/plugins/databasemigration/command/DbmClearChecksumsCommandSpec.groovy b/grails-data-hibernate5/dbmigration/src/test/groovy/org/apache/grails/data/hibernate5/dbmigration/cli/DbmClearChecksumsCommandSpec.groovy
similarity index 95%
rename from grails-data-hibernate7/dbmigration/src/test/groovy/org/grails/plugins/databasemigration/command/DbmClearChecksumsCommandSpec.groovy
rename to grails-data-hibernate5/dbmigration/src/test/groovy/org/apache/grails/data/hibernate5/dbmigration/cli/DbmClearChecksumsCommandSpec.groovy
index a4e6d04ed8..5d31f168f2 100644
--- a/grails-data-hibernate7/dbmigration/src/test/groovy/org/grails/plugins/databasemigration/command/DbmClearChecksumsCommandSpec.groovy
+++ b/grails-data-hibernate5/dbmigration/src/test/groovy/org/apache/grails/data/hibernate5/dbmigration/cli/DbmClearChecksumsCommandSpec.groovy
@@ -16,9 +16,9 @@
  *  specific language governing permissions and limitations
  *  under the License.
  */
-package org.grails.plugins.databasemigration.command
+package org.apache.grails.data.hibernate5.dbmigration.cli
 
-import grails.dev.commands.ApplicationCommand
+import org.apache.grails.core.cli.ApplicationCommand
 
 class DbmClearChecksumsCommandSpec extends ApplicationContextDatabaseMigrationCommandSpec {
 
diff --git a/grails-data-hibernate5/dbmigration/src/test/groovy/org/grails/plugins/databasemigration/command/DbmDiffCommandSpec.groovy b/grails-data-hibernate5/dbmigration/src/test/groovy/org/apache/grails/data/hibernate5/dbmigration/cli/DbmDiffCommandSpec.groovy
similarity index 97%
rename from grails-data-hibernate5/dbmigration/src/test/groovy/org/grails/plugins/databasemigration/command/DbmDiffCommandSpec.groovy
rename to grails-data-hibernate5/dbmigration/src/test/groovy/org/apache/grails/data/hibernate5/dbmigration/cli/DbmDiffCommandSpec.groovy
index 043b350d46..724c82625a 100644
--- a/grails-data-hibernate5/dbmigration/src/test/groovy/org/grails/plugins/databasemigration/command/DbmDiffCommandSpec.groovy
+++ b/grails-data-hibernate5/dbmigration/src/test/groovy/org/apache/grails/data/hibernate5/dbmigration/cli/DbmDiffCommandSpec.groovy
@@ -16,9 +16,9 @@
  *  specific language governing permissions and limitations
  *  under the License.
  */
-package org.grails.plugins.databasemigration.command
+package org.apache.grails.data.hibernate5.dbmigration.cli
 
-import grails.dev.commands.ApplicationCommand
+import org.apache.grails.core.cli.ApplicationCommand
 import groovy.sql.Sql
 import org.grails.plugins.databasemigration.DatabaseMigrationException
 import org.h2.Driver
diff --git a/grails-data-hibernate5/dbmigration/src/test/groovy/org/grails/plugins/databasemigration/command/DbmDropAllCommandSpec.groovy b/grails-data-hibernate5/dbmigration/src/test/groovy/org/apache/grails/data/hibernate5/dbmigration/cli/DbmDropAllCommandSpec.groovy
similarity index 93%
rename from grails-data-hibernate5/dbmigration/src/test/groovy/org/grails/plugins/databasemigration/command/DbmDropAllCommandSpec.groovy
rename to grails-data-hibernate5/dbmigration/src/test/groovy/org/apache/grails/data/hibernate5/dbmigration/cli/DbmDropAllCommandSpec.groovy
index 7583c4739f..0a943990f9 100644
--- a/grails-data-hibernate5/dbmigration/src/test/groovy/org/grails/plugins/databasemigration/command/DbmDropAllCommandSpec.groovy
+++ b/grails-data-hibernate5/dbmigration/src/test/groovy/org/apache/grails/data/hibernate5/dbmigration/cli/DbmDropAllCommandSpec.groovy
@@ -16,9 +16,9 @@
  *  specific language governing permissions and limitations
  *  under the License.
  */
-package org.grails.plugins.databasemigration.command
+package org.apache.grails.data.hibernate5.dbmigration.cli
 
-import grails.dev.commands.ApplicationCommand
+import org.apache.grails.core.cli.ApplicationCommand
 
 class DbmDropAllCommandSpec extends ApplicationContextDatabaseMigrationCommandSpec {
 
diff --git a/grails-data-hibernate5/dbmigration/src/test/groovy/org/grails/plugins/databasemigration/command/DbmFutureRollbackCountSqlCommandSpec.groovy b/grails-data-hibernate5/dbmigration/src/test/groovy/org/apache/grails/data/hibernate5/dbmigration/cli/DbmFutureRollbackCountSqlCommandSpec.groovy
similarity index 97%
rename from grails-data-hibernate5/dbmigration/src/test/groovy/org/grails/plugins/databasemigration/command/DbmFutureRollbackCountSqlCommandSpec.groovy
rename to grails-data-hibernate5/dbmigration/src/test/groovy/org/apache/grails/data/hibernate5/dbmigration/cli/DbmFutureRollbackCountSqlCommandSpec.groovy
index 9ec47790f3..243c1569de 100644
--- a/grails-data-hibernate5/dbmigration/src/test/groovy/org/grails/plugins/databasemigration/command/DbmFutureRollbackCountSqlCommandSpec.groovy
+++ b/grails-data-hibernate5/dbmigration/src/test/groovy/org/apache/grails/data/hibernate5/dbmigration/cli/DbmFutureRollbackCountSqlCommandSpec.groovy
@@ -16,9 +16,9 @@
  *  specific language governing permissions and limitations
  *  under the License.
  */
-package org.grails.plugins.databasemigration.command
+package org.apache.grails.data.hibernate5.dbmigration.cli
 
-import grails.dev.commands.ApplicationCommand
+import org.apache.grails.core.cli.ApplicationCommand
 import org.grails.plugins.databasemigration.DatabaseMigrationException
 import spock.lang.AutoCleanup
 
diff --git a/grails-data-hibernate7/dbmigration/src/test/groovy/org/grails/plugins/databasemigration/command/DbmFutureRollbackSqlCommandSpec.groovy b/grails-data-hibernate5/dbmigration/src/test/groovy/org/apache/grails/data/hibernate5/dbmigration/cli/DbmFutureRollbackSqlCommandSpec.groovy
similarity index 97%
rename from grails-data-hibernate7/dbmigration/src/test/groovy/org/grails/plugins/databasemigration/command/DbmFutureRollbackSqlCommandSpec.groovy
rename to grails-data-hibernate5/dbmigration/src/test/groovy/org/apache/grails/data/hibernate5/dbmigration/cli/DbmFutureRollbackSqlCommandSpec.groovy
index 7e4203b77e..5d701cdc7b 100644
--- a/grails-data-hibernate7/dbmigration/src/test/groovy/org/grails/plugins/databasemigration/command/DbmFutureRollbackSqlCommandSpec.groovy
+++ b/grails-data-hibernate5/dbmigration/src/test/groovy/org/apache/grails/data/hibernate5/dbmigration/cli/DbmFutureRollbackSqlCommandSpec.groovy
@@ -16,9 +16,9 @@
  *  specific language governing permissions and limitations
  *  under the License.
  */
-package org.grails.plugins.databasemigration.command
+package org.apache.grails.data.hibernate5.dbmigration.cli
 
-import grails.dev.commands.ApplicationCommand
+import org.apache.grails.core.cli.ApplicationCommand
 import spock.lang.AutoCleanup
 
 class DbmFutureRollbackSqlCommandSpec extends ApplicationContextDatabaseMigrationCommandSpec {
diff --git a/grails-data-hibernate5/dbmigration/src/test/groovy/org/grails/plugins/databasemigration/command/DbmGenerateChangelogCommandSpec.groovy b/grails-data-hibernate5/dbmigration/src/test/groovy/org/apache/grails/data/hibernate5/dbmigration/cli/DbmGenerateChangelogCommandSpec.groovy
similarity index 97%
rename from grails-data-hibernate5/dbmigration/src/test/groovy/org/grails/plugins/databasemigration/command/DbmGenerateChangelogCommandSpec.groovy
rename to grails-data-hibernate5/dbmigration/src/test/groovy/org/apache/grails/data/hibernate5/dbmigration/cli/DbmGenerateChangelogCommandSpec.groovy
index a8ac019d28..359956787f 100644
--- a/grails-data-hibernate5/dbmigration/src/test/groovy/org/grails/plugins/databasemigration/command/DbmGenerateChangelogCommandSpec.groovy
+++ b/grails-data-hibernate5/dbmigration/src/test/groovy/org/apache/grails/data/hibernate5/dbmigration/cli/DbmGenerateChangelogCommandSpec.groovy
@@ -16,9 +16,9 @@
  *  specific language governing permissions and limitations
  *  under the License.
  */
-package org.grails.plugins.databasemigration.command
+package org.apache.grails.data.hibernate5.dbmigration.cli
 
-import grails.dev.commands.ApplicationCommand
+import org.apache.grails.core.cli.ApplicationCommand
 
 class DbmGenerateChangelogCommandSpec extends ApplicationContextDatabaseMigrationCommandSpec {
 
diff --git a/grails-data-hibernate5/dbmigration/src/test/groovy/org/grails/plugins/databasemigration/command/DbmGenerateGormChangelogCommandSpec.groovy b/grails-data-hibernate5/dbmigration/src/test/groovy/org/apache/grails/data/hibernate5/dbmigration/cli/DbmGenerateGormChangelogCommandSpec.groovy
similarity index 98%
rename from grails-data-hibernate5/dbmigration/src/test/groovy/org/grails/plugins/databasemigration/command/DbmGenerateGormChangelogCommandSpec.groovy
rename to grails-data-hibernate5/dbmigration/src/test/groovy/org/apache/grails/data/hibernate5/dbmigration/cli/DbmGenerateGormChangelogCommandSpec.groovy
index 059f07da07..b22bc1ff7a 100644
--- a/grails-data-hibernate5/dbmigration/src/test/groovy/org/grails/plugins/databasemigration/command/DbmGenerateGormChangelogCommandSpec.groovy
+++ b/grails-data-hibernate5/dbmigration/src/test/groovy/org/apache/grails/data/hibernate5/dbmigration/cli/DbmGenerateGormChangelogCommandSpec.groovy
@@ -16,9 +16,9 @@
  *  specific language governing permissions and limitations
  *  under the License.
  */
-package org.grails.plugins.databasemigration.command
+package org.apache.grails.data.hibernate5.dbmigration.cli
 
-import grails.dev.commands.ApplicationCommand
+import org.apache.grails.core.cli.ApplicationCommand
 import org.grails.plugins.databasemigration.DatabaseMigrationException
 
 class DbmGenerateGormChangelogCommandSpec extends ApplicationContextDatabaseMigrationCommandSpec {
diff --git a/grails-data-hibernate5/dbmigration/src/test/groovy/org/grails/plugins/databasemigration/command/DbmGormDiffCommandSpec.groovy b/grails-data-hibernate5/dbmigration/src/test/groovy/org/apache/grails/data/hibernate5/dbmigration/cli/DbmGormDiffCommandSpec.groovy
similarity index 97%
rename from grails-data-hibernate5/dbmigration/src/test/groovy/org/grails/plugins/databasemigration/command/DbmGormDiffCommandSpec.groovy
rename to grails-data-hibernate5/dbmigration/src/test/groovy/org/apache/grails/data/hibernate5/dbmigration/cli/DbmGormDiffCommandSpec.groovy
index 9d7d3561ae..31f53d0f09 100644
--- a/grails-data-hibernate5/dbmigration/src/test/groovy/org/grails/plugins/databasemigration/command/DbmGormDiffCommandSpec.groovy
+++ b/grails-data-hibernate5/dbmigration/src/test/groovy/org/apache/grails/data/hibernate5/dbmigration/cli/DbmGormDiffCommandSpec.groovy
@@ -16,9 +16,9 @@
  *  specific language governing permissions and limitations
  *  under the License.
  */
-package org.grails.plugins.databasemigration.command
+package org.apache.grails.data.hibernate5.dbmigration.cli
 
-import grails.dev.commands.ApplicationCommand
+import org.apache.grails.core.cli.ApplicationCommand
 import org.grails.plugins.databasemigration.DatabaseMigrationException
 
 class DbmGormDiffCommandSpec extends ApplicationContextDatabaseMigrationCommandSpec {
diff --git a/grails-data-hibernate5/dbmigration/src/test/groovy/org/grails/plugins/databasemigration/command/DbmListLocksCommandSpec.groovy b/grails-data-hibernate5/dbmigration/src/test/groovy/org/apache/grails/data/hibernate5/dbmigration/cli/DbmListLocksCommandSpec.groovy
similarity index 95%
rename from grails-data-hibernate5/dbmigration/src/test/groovy/org/grails/plugins/databasemigration/command/DbmListLocksCommandSpec.groovy
rename to grails-data-hibernate5/dbmigration/src/test/groovy/org/apache/grails/data/hibernate5/dbmigration/cli/DbmListLocksCommandSpec.groovy
index a58fc104c5..b3a7fa7506 100644
--- a/grails-data-hibernate5/dbmigration/src/test/groovy/org/grails/plugins/databasemigration/command/DbmListLocksCommandSpec.groovy
+++ b/grails-data-hibernate5/dbmigration/src/test/groovy/org/apache/grails/data/hibernate5/dbmigration/cli/DbmListLocksCommandSpec.groovy
@@ -16,9 +16,9 @@
  *  specific language governing permissions and limitations
  *  under the License.
  */
-package org.grails.plugins.databasemigration.command
+package org.apache.grails.data.hibernate5.dbmigration.cli
 
-import grails.dev.commands.ApplicationCommand
+import org.apache.grails.core.cli.ApplicationCommand
 import spock.lang.AutoCleanup
 
 class DbmListLocksCommandSpec extends ApplicationContextDatabaseMigrationCommandSpec {
diff --git a/grails-data-hibernate7/dbmigration/src/test/groovy/org/grails/plugins/databasemigration/command/DbmMarkNextChangesetRanCommandSpec.groovy b/grails-data-hibernate5/dbmigration/src/test/groovy/org/apache/grails/data/hibernate5/dbmigration/cli/DbmMarkNextChangesetRanCommandSpec.groovy
similarity index 93%
rename from grails-data-hibernate7/dbmigration/src/test/groovy/org/grails/plugins/databasemigration/command/DbmMarkNextChangesetRanCommandSpec.groovy
rename to grails-data-hibernate5/dbmigration/src/test/groovy/org/apache/grails/data/hibernate5/dbmigration/cli/DbmMarkNextChangesetRanCommandSpec.groovy
index 717fce94d3..dfc5d2251c 100644
--- a/grails-data-hibernate7/dbmigration/src/test/groovy/org/grails/plugins/databasemigration/command/DbmMarkNextChangesetRanCommandSpec.groovy
+++ b/grails-data-hibernate5/dbmigration/src/test/groovy/org/apache/grails/data/hibernate5/dbmigration/cli/DbmMarkNextChangesetRanCommandSpec.groovy
@@ -16,9 +16,9 @@
  *  specific language governing permissions and limitations
  *  under the License.
  */
-package org.grails.plugins.databasemigration.command
+package org.apache.grails.data.hibernate5.dbmigration.cli
 
-import grails.dev.commands.ApplicationCommand
+import org.apache.grails.core.cli.ApplicationCommand
 
 class DbmMarkNextChangesetRanCommandSpec extends ApplicationContextDatabaseMigrationCommandSpec {
 
diff --git a/grails-data-hibernate7/dbmigration/src/test/groovy/org/grails/plugins/databasemigration/command/DbmMarkNextChangesetRanSqlCommandSpec.groovy b/grails-data-hibernate5/dbmigration/src/test/groovy/org/apache/grails/data/hibernate5/dbmigration/cli/DbmMarkNextChangesetRanSqlCommandSpec.groovy
similarity index 95%
rename from grails-data-hibernate7/dbmigration/src/test/groovy/org/grails/plugins/databasemigration/command/DbmMarkNextChangesetRanSqlCommandSpec.groovy
rename to grails-data-hibernate5/dbmigration/src/test/groovy/org/apache/grails/data/hibernate5/dbmigration/cli/DbmMarkNextChangesetRanSqlCommandSpec.groovy
index 9056fcb969..440b02fb27 100644
--- a/grails-data-hibernate7/dbmigration/src/test/groovy/org/grails/plugins/databasemigration/command/DbmMarkNextChangesetRanSqlCommandSpec.groovy
+++ b/grails-data-hibernate5/dbmigration/src/test/groovy/org/apache/grails/data/hibernate5/dbmigration/cli/DbmMarkNextChangesetRanSqlCommandSpec.groovy
@@ -16,9 +16,9 @@
  *  specific language governing permissions and limitations
  *  under the License.
  */
-package org.grails.plugins.databasemigration.command
+package org.apache.grails.data.hibernate5.dbmigration.cli
 
-import grails.dev.commands.ApplicationCommand
+import org.apache.grails.core.cli.ApplicationCommand
 import spock.lang.AutoCleanup
 
 class DbmMarkNextChangesetRanSqlCommandSpec extends ApplicationContextDatabaseMigrationCommandSpec {
diff --git a/grails-data-hibernate5/dbmigration/src/test/groovy/org/grails/plugins/databasemigration/command/DbmPreviousChangesetSqlCommandSpec.groovy b/grails-data-hibernate5/dbmigration/src/test/groovy/org/apache/grails/data/hibernate5/dbmigration/cli/DbmPreviousChangesetSqlCommandSpec.groovy
similarity index 97%
rename from grails-data-hibernate5/dbmigration/src/test/groovy/org/grails/plugins/databasemigration/command/DbmPreviousChangesetSqlCommandSpec.groovy
rename to grails-data-hibernate5/dbmigration/src/test/groovy/org/apache/grails/data/hibernate5/dbmigration/cli/DbmPreviousChangesetSqlCommandSpec.groovy
index 48d8251141..aa61928ac3 100644
--- a/grails-data-hibernate5/dbmigration/src/test/groovy/org/grails/plugins/databasemigration/command/DbmPreviousChangesetSqlCommandSpec.groovy
+++ b/grails-data-hibernate5/dbmigration/src/test/groovy/org/apache/grails/data/hibernate5/dbmigration/cli/DbmPreviousChangesetSqlCommandSpec.groovy
@@ -16,9 +16,9 @@
  *  specific language governing permissions and limitations
  *  under the License.
  */
-package org.grails.plugins.databasemigration.command
+package org.apache.grails.data.hibernate5.dbmigration.cli
 
-import grails.dev.commands.ApplicationCommand
+import org.apache.grails.core.cli.ApplicationCommand
 import org.grails.plugins.databasemigration.DatabaseMigrationException
 import spock.lang.AutoCleanup
 
diff --git a/grails-data-hibernate5/dbmigration/src/test/groovy/org/grails/plugins/databasemigration/command/DbmReleaseLocksCommandSpec.groovy b/grails-data-hibernate5/dbmigration/src/test/groovy/org/apache/grails/data/hibernate5/dbmigration/cli/DbmReleaseLocksCommandSpec.groovy
similarity index 93%
rename from grails-data-hibernate5/dbmigration/src/test/groovy/org/grails/plugins/databasemigration/command/DbmReleaseLocksCommandSpec.groovy
rename to grails-data-hibernate5/dbmigration/src/test/groovy/org/apache/grails/data/hibernate5/dbmigration/cli/DbmReleaseLocksCommandSpec.groovy
index 75c9983881..42e7104456 100644
--- a/grails-data-hibernate5/dbmigration/src/test/groovy/org/grails/plugins/databasemigration/command/DbmReleaseLocksCommandSpec.groovy
+++ b/grails-data-hibernate5/dbmigration/src/test/groovy/org/apache/grails/data/hibernate5/dbmigration/cli/DbmReleaseLocksCommandSpec.groovy
@@ -16,9 +16,9 @@
  *  specific language governing permissions and limitations
  *  under the License.
  */
-package org.grails.plugins.databasemigration.command
+package org.apache.grails.data.hibernate5.dbmigration.cli
 
-import grails.dev.commands.ApplicationCommand
+import org.apache.grails.core.cli.ApplicationCommand
 
 class DbmReleaseLocksCommandSpec extends ApplicationContextDatabaseMigrationCommandSpec {
 
diff --git a/grails-data-hibernate7/dbmigration/src/test/groovy/org/grails/plugins/databasemigration/command/DbmRollbackCommandSpec.groovy b/grails-data-hibernate5/dbmigration/src/test/groovy/org/apache/grails/data/hibernate5/dbmigration/cli/DbmRollbackCommandSpec.groovy
similarity index 97%
rename from grails-data-hibernate7/dbmigration/src/test/groovy/org/grails/plugins/databasemigration/command/DbmRollbackCommandSpec.groovy
rename to grails-data-hibernate5/dbmigration/src/test/groovy/org/apache/grails/data/hibernate5/dbmigration/cli/DbmRollbackCommandSpec.groovy
index 80de7605b6..7fb72f1854 100644
--- a/grails-data-hibernate7/dbmigration/src/test/groovy/org/grails/plugins/databasemigration/command/DbmRollbackCommandSpec.groovy
+++ b/grails-data-hibernate5/dbmigration/src/test/groovy/org/apache/grails/data/hibernate5/dbmigration/cli/DbmRollbackCommandSpec.groovy
@@ -16,9 +16,9 @@
  *  specific language governing permissions and limitations
  *  under the License.
  */
-package org.grails.plugins.databasemigration.command
+package org.apache.grails.data.hibernate5.dbmigration.cli
 
-import grails.dev.commands.ApplicationCommand
+import org.apache.grails.core.cli.ApplicationCommand
 import org.grails.plugins.databasemigration.DatabaseMigrationException
 
 class DbmRollbackCommandSpec extends ApplicationContextDatabaseMigrationCommandSpec {
diff --git a/grails-data-hibernate5/dbmigration/src/test/groovy/org/grails/plugins/databasemigration/command/DbmRollbackCountCommandSpec.groovy b/grails-data-hibernate5/dbmigration/src/test/groovy/org/apache/grails/data/hibernate5/dbmigration/cli/DbmRollbackCountCommandSpec.groovy
similarity index 97%
rename from grails-data-hibernate5/dbmigration/src/test/groovy/org/grails/plugins/databasemigration/command/DbmRollbackCountCommandSpec.groovy
rename to grails-data-hibernate5/dbmigration/src/test/groovy/org/apache/grails/data/hibernate5/dbmigration/cli/DbmRollbackCountCommandSpec.groovy
index bdca200858..f3d5bbda25 100644
--- a/grails-data-hibernate5/dbmigration/src/test/groovy/org/grails/plugins/databasemigration/command/DbmRollbackCountCommandSpec.groovy
+++ b/grails-data-hibernate5/dbmigration/src/test/groovy/org/apache/grails/data/hibernate5/dbmigration/cli/DbmRollbackCountCommandSpec.groovy
@@ -16,9 +16,9 @@
  *  specific language governing permissions and limitations
  *  under the License.
  */
-package org.grails.plugins.databasemigration.command
+package org.apache.grails.data.hibernate5.dbmigration.cli
 
-import grails.dev.commands.ApplicationCommand
+import org.apache.grails.core.cli.ApplicationCommand
 import org.grails.plugins.databasemigration.DatabaseMigrationException
 
 class DbmRollbackCountCommandSpec extends ApplicationContextDatabaseMigrationCommandSpec {
diff --git a/grails-data-hibernate7/dbmigration/src/test/groovy/org/grails/plugins/databasemigration/command/DbmRollbackCountSqlCommandSpec.groovy b/grails-data-hibernate5/dbmigration/src/test/groovy/org/apache/grails/data/hibernate5/dbmigration/cli/DbmRollbackCountSqlCommandSpec.groovy
similarity index 97%
rename from grails-data-hibernate7/dbmigration/src/test/groovy/org/grails/plugins/databasemigration/command/DbmRollbackCountSqlCommandSpec.groovy
rename to grails-data-hibernate5/dbmigration/src/test/groovy/org/apache/grails/data/hibernate5/dbmigration/cli/DbmRollbackCountSqlCommandSpec.groovy
index e3a1915b13..75e29f19e4 100644
--- a/grails-data-hibernate7/dbmigration/src/test/groovy/org/grails/plugins/databasemigration/command/DbmRollbackCountSqlCommandSpec.groovy
+++ b/grails-data-hibernate5/dbmigration/src/test/groovy/org/apache/grails/data/hibernate5/dbmigration/cli/DbmRollbackCountSqlCommandSpec.groovy
@@ -16,9 +16,9 @@
  *  specific language governing permissions and limitations
  *  under the License.
  */
-package org.grails.plugins.databasemigration.command
+package org.apache.grails.data.hibernate5.dbmigration.cli
 
-import grails.dev.commands.ApplicationCommand
+import org.apache.grails.core.cli.ApplicationCommand
 import org.grails.plugins.databasemigration.DatabaseMigrationException
 import spock.lang.AutoCleanup
 
diff --git a/grails-data-hibernate7/dbmigration/src/test/groovy/org/grails/plugins/databasemigration/command/DbmRollbackSqlCommandSpec.groovy b/grails-data-hibernate5/dbmigration/src/test/groovy/org/apache/grails/data/hibernate5/dbmigration/cli/DbmRollbackSqlCommandSpec.groovy
similarity index 97%
rename from grails-data-hibernate7/dbmigration/src/test/groovy/org/grails/plugins/databasemigration/command/DbmRollbackSqlCommandSpec.groovy
rename to grails-data-hibernate5/dbmigration/src/test/groovy/org/apache/grails/data/hibernate5/dbmigration/cli/DbmRollbackSqlCommandSpec.groovy
index c063046721..f74a9d9eaf 100644
--- a/grails-data-hibernate7/dbmigration/src/test/groovy/org/grails/plugins/databasemigration/command/DbmRollbackSqlCommandSpec.groovy
+++ b/grails-data-hibernate5/dbmigration/src/test/groovy/org/apache/grails/data/hibernate5/dbmigration/cli/DbmRollbackSqlCommandSpec.groovy
@@ -16,9 +16,9 @@
  *  specific language governing permissions and limitations
  *  under the License.
  */
-package org.grails.plugins.databasemigration.command
+package org.apache.grails.data.hibernate5.dbmigration.cli
 
-import grails.dev.commands.ApplicationCommand
+import org.apache.grails.core.cli.ApplicationCommand
 import org.grails.plugins.databasemigration.DatabaseMigrationException
 import spock.lang.AutoCleanup
 
diff --git a/grails-data-hibernate5/dbmigration/src/test/groovy/org/grails/plugins/databasemigration/command/DbmRollbackToDateCommandSpec.groovy b/grails-data-hibernate5/dbmigration/src/test/groovy/org/apache/grails/data/hibernate5/dbmigration/cli/DbmRollbackToDateCommandSpec.groovy
similarity index 97%
rename from grails-data-hibernate5/dbmigration/src/test/groovy/org/grails/plugins/databasemigration/command/DbmRollbackToDateCommandSpec.groovy
rename to grails-data-hibernate5/dbmigration/src/test/groovy/org/apache/grails/data/hibernate5/dbmigration/cli/DbmRollbackToDateCommandSpec.groovy
index 41c450a9c1..abbf2204d4 100644
--- a/grails-data-hibernate5/dbmigration/src/test/groovy/org/grails/plugins/databasemigration/command/DbmRollbackToDateCommandSpec.groovy
+++ b/grails-data-hibernate5/dbmigration/src/test/groovy/org/apache/grails/data/hibernate5/dbmigration/cli/DbmRollbackToDateCommandSpec.groovy
@@ -16,9 +16,9 @@
  *  specific language governing permissions and limitations
  *  under the License.
  */
-package org.grails.plugins.databasemigration.command
+package org.apache.grails.data.hibernate5.dbmigration.cli
 
-import grails.dev.commands.ApplicationCommand
+import org.apache.grails.core.cli.ApplicationCommand
 import org.grails.plugins.databasemigration.DatabaseMigrationException
 
 class DbmRollbackToDateCommandSpec extends ApplicationContextDatabaseMigrationCommandSpec {
diff --git a/grails-data-hibernate5/dbmigration/src/test/groovy/org/grails/plugins/databasemigration/command/DbmRollbackToDateSqlCommandSpec.groovy b/grails-data-hibernate5/dbmigration/src/test/groovy/org/apache/grails/data/hibernate5/dbmigration/cli/DbmRollbackToDateSqlCommandSpec.groovy
similarity index 97%
rename from grails-data-hibernate5/dbmigration/src/test/groovy/org/grails/plugins/databasemigration/command/DbmRollbackToDateSqlCommandSpec.groovy
rename to grails-data-hibernate5/dbmigration/src/test/groovy/org/apache/grails/data/hibernate5/dbmigration/cli/DbmRollbackToDateSqlCommandSpec.groovy
index cca3fb770a..cf7310604e 100644
--- a/grails-data-hibernate5/dbmigration/src/test/groovy/org/grails/plugins/databasemigration/command/DbmRollbackToDateSqlCommandSpec.groovy
+++ b/grails-data-hibernate5/dbmigration/src/test/groovy/org/apache/grails/data/hibernate5/dbmigration/cli/DbmRollbackToDateSqlCommandSpec.groovy
@@ -16,9 +16,9 @@
  *  specific language governing permissions and limitations
  *  under the License.
  */
-package org.grails.plugins.databasemigration.command
+package org.apache.grails.data.hibernate5.dbmigration.cli
 
-import grails.dev.commands.ApplicationCommand
+import org.apache.grails.core.cli.ApplicationCommand
 import org.grails.plugins.databasemigration.DatabaseMigrationException
 import spock.lang.AutoCleanup
 
diff --git a/grails-data-hibernate5/dbmigration/src/test/groovy/org/grails/plugins/databasemigration/command/DbmStatusCommandSpec.groovy b/grails-data-hibernate5/dbmigration/src/test/groovy/org/apache/grails/data/hibernate5/dbmigration/cli/DbmStatusCommandSpec.groovy
similarity index 94%
rename from grails-data-hibernate5/dbmigration/src/test/groovy/org/grails/plugins/databasemigration/command/DbmStatusCommandSpec.groovy
rename to grails-data-hibernate5/dbmigration/src/test/groovy/org/apache/grails/data/hibernate5/dbmigration/cli/DbmStatusCommandSpec.groovy
index 8c364e24f1..12cd4b2e00 100644
--- a/grails-data-hibernate5/dbmigration/src/test/groovy/org/grails/plugins/databasemigration/command/DbmStatusCommandSpec.groovy
+++ b/grails-data-hibernate5/dbmigration/src/test/groovy/org/apache/grails/data/hibernate5/dbmigration/cli/DbmStatusCommandSpec.groovy
@@ -16,9 +16,9 @@
  *  specific language governing permissions and limitations
  *  under the License.
  */
-package org.grails.plugins.databasemigration.command
+package org.apache.grails.data.hibernate5.dbmigration.cli
 
-import grails.dev.commands.ApplicationCommand
+import org.apache.grails.core.cli.ApplicationCommand
 import spock.lang.AutoCleanup
 
 class DbmStatusCommandSpec extends ApplicationContextDatabaseMigrationCommandSpec {
diff --git a/grails-data-hibernate7/dbmigration/src/test/groovy/org/grails/plugins/databasemigration/command/DbmUpdateCommandSpec.groovy b/grails-data-hibernate5/dbmigration/src/test/groovy/org/apache/grails/data/hibernate5/dbmigration/cli/DbmUpdateCommandSpec.groovy
similarity index 97%
rename from grails-data-hibernate7/dbmigration/src/test/groovy/org/grails/plugins/databasemigration/command/DbmUpdateCommandSpec.groovy
rename to grails-data-hibernate5/dbmigration/src/test/groovy/org/apache/grails/data/hibernate5/dbmigration/cli/DbmUpdateCommandSpec.groovy
index 3101e35bdd..fb5266b315 100644
--- a/grails-data-hibernate7/dbmigration/src/test/groovy/org/grails/plugins/databasemigration/command/DbmUpdateCommandSpec.groovy
+++ b/grails-data-hibernate5/dbmigration/src/test/groovy/org/apache/grails/data/hibernate5/dbmigration/cli/DbmUpdateCommandSpec.groovy
@@ -16,9 +16,9 @@
  *  specific language governing permissions and limitations
  *  under the License.
  */
-package org.grails.plugins.databasemigration.command
+package org.apache.grails.data.hibernate5.dbmigration.cli
 
-import grails.dev.commands.ApplicationCommand
+import org.apache.grails.core.cli.ApplicationCommand
 
 class DbmUpdateCommandSpec extends ApplicationContextDatabaseMigrationCommandSpec {
 
diff --git a/grails-data-hibernate5/dbmigration/src/test/groovy/org/grails/plugins/databasemigration/command/DbmUpdateCountCommandSpec.groovy b/grails-data-hibernate5/dbmigration/src/test/groovy/org/apache/grails/data/hibernate5/dbmigration/cli/DbmUpdateCountCommandSpec.groovy
similarity index 96%
rename from grails-data-hibernate5/dbmigration/src/test/groovy/org/grails/plugins/databasemigration/command/DbmUpdateCountCommandSpec.groovy
rename to grails-data-hibernate5/dbmigration/src/test/groovy/org/apache/grails/data/hibernate5/dbmigration/cli/DbmUpdateCountCommandSpec.groovy
index aa4a776c5c..785fcd2278 100644
--- a/grails-data-hibernate5/dbmigration/src/test/groovy/org/grails/plugins/databasemigration/command/DbmUpdateCountCommandSpec.groovy
+++ b/grails-data-hibernate5/dbmigration/src/test/groovy/org/apache/grails/data/hibernate5/dbmigration/cli/DbmUpdateCountCommandSpec.groovy
@@ -16,9 +16,9 @@
  *  specific language governing permissions and limitations
  *  under the License.
  */
-package org.grails.plugins.databasemigration.command
+package org.apache.grails.data.hibernate5.dbmigration.cli
 
-import grails.dev.commands.ApplicationCommand
+import org.apache.grails.core.cli.ApplicationCommand
 import org.grails.plugins.databasemigration.DatabaseMigrationException
 
 class DbmUpdateCountCommandSpec extends ApplicationContextDatabaseMigrationCommandSpec {
diff --git a/grails-data-hibernate7/dbmigration/src/test/groovy/org/grails/plugins/databasemigration/command/DbmUpdateCountSqlCommandSpec.groovy b/grails-data-hibernate5/dbmigration/src/test/groovy/org/apache/grails/data/hibernate5/dbmigration/cli/DbmUpdateCountSqlCommandSpec.groovy
similarity index 97%
rename from grails-data-hibernate7/dbmigration/src/test/groovy/org/grails/plugins/databasemigration/command/DbmUpdateCountSqlCommandSpec.groovy
rename to grails-data-hibernate5/dbmigration/src/test/groovy/org/apache/grails/data/hibernate5/dbmigration/cli/DbmUpdateCountSqlCommandSpec.groovy
index 676ec82a07..094c8739e2 100644
--- a/grails-data-hibernate7/dbmigration/src/test/groovy/org/grails/plugins/databasemigration/command/DbmUpdateCountSqlCommandSpec.groovy
+++ b/grails-data-hibernate5/dbmigration/src/test/groovy/org/apache/grails/data/hibernate5/dbmigration/cli/DbmUpdateCountSqlCommandSpec.groovy
@@ -16,9 +16,9 @@
  *  specific language governing permissions and limitations
  *  under the License.
  */
-package org.grails.plugins.databasemigration.command
+package org.apache.grails.data.hibernate5.dbmigration.cli
 
-import grails.dev.commands.ApplicationCommand
+import org.apache.grails.core.cli.ApplicationCommand
 import org.grails.plugins.databasemigration.DatabaseMigrationException
 import spock.lang.AutoCleanup
 
diff --git a/grails-data-hibernate7/dbmigration/src/test/groovy/org/grails/plugins/databasemigration/command/DbmUpdateSqlCommandSpec.groovy b/grails-data-hibernate5/dbmigration/src/test/groovy/org/apache/grails/data/hibernate5/dbmigration/cli/DbmUpdateSqlCommandSpec.groovy
similarity index 98%
rename from grails-data-hibernate7/dbmigration/src/test/groovy/org/grails/plugins/databasemigration/command/DbmUpdateSqlCommandSpec.groovy
rename to grails-data-hibernate5/dbmigration/src/test/groovy/org/apache/grails/data/hibernate5/dbmigration/cli/DbmUpdateSqlCommandSpec.groovy
index d04a542631..e16b2db63d 100644
--- a/grails-data-hibernate7/dbmigration/src/test/groovy/org/grails/plugins/databasemigration/command/DbmUpdateSqlCommandSpec.groovy
+++ b/grails-data-hibernate5/dbmigration/src/test/groovy/org/apache/grails/data/hibernate5/dbmigration/cli/DbmUpdateSqlCommandSpec.groovy
@@ -16,9 +16,9 @@
  *  specific language governing permissions and limitations
  *  under the License.
  */
-package org.grails.plugins.databasemigration.command
+package org.apache.grails.data.hibernate5.dbmigration.cli
 
-import grails.dev.commands.ApplicationCommand
+import org.apache.grails.core.cli.ApplicationCommand
 import spock.lang.AutoCleanup
 
 class DbmUpdateSqlCommandSpec extends ApplicationContextDatabaseMigrationCommandSpec {
diff --git a/grails-data-hibernate5/dbmigration/src/test/groovy/org/grails/plugins/databasemigration/command/DbmValidateCommandSpec.groovy b/grails-data-hibernate5/dbmigration/src/test/groovy/org/apache/grails/data/hibernate5/dbmigration/cli/DbmValidateCommandSpec.groovy
similarity index 96%
rename from grails-data-hibernate5/dbmigration/src/test/groovy/org/grails/plugins/databasemigration/command/DbmValidateCommandSpec.groovy
rename to grails-data-hibernate5/dbmigration/src/test/groovy/org/apache/grails/data/hibernate5/dbmigration/cli/DbmValidateCommandSpec.groovy
index b49d0db764..8d1b93c99a 100644
--- a/grails-data-hibernate5/dbmigration/src/test/groovy/org/grails/plugins/databasemigration/command/DbmValidateCommandSpec.groovy
+++ b/grails-data-hibernate5/dbmigration/src/test/groovy/org/apache/grails/data/hibernate5/dbmigration/cli/DbmValidateCommandSpec.groovy
@@ -16,9 +16,9 @@
  *  specific language governing permissions and limitations
  *  under the License.
  */
-package org.grails.plugins.databasemigration.command
+package org.apache.grails.data.hibernate5.dbmigration.cli
 
-import grails.dev.commands.ApplicationCommand
+import org.apache.grails.core.cli.ApplicationCommand
 import liquibase.exception.CommandExecutionException
 
 class DbmValidateCommandSpec extends ApplicationContextDatabaseMigrationCommandSpec {
diff --git a/grails-data-hibernate5/dbmigration/src/test/groovy/org/grails/plugins/databasemigration/command/ScriptDatabaseMigrationCommandSpec.groovy b/grails-data-hibernate5/dbmigration/src/test/groovy/org/apache/grails/data/hibernate5/dbmigration/cli/ScriptDatabaseMigrationCommandSpec.groovy
similarity index 97%
rename from grails-data-hibernate5/dbmigration/src/test/groovy/org/grails/plugins/databasemigration/command/ScriptDatabaseMigrationCommandSpec.groovy
rename to grails-data-hibernate5/dbmigration/src/test/groovy/org/apache/grails/data/hibernate5/dbmigration/cli/ScriptDatabaseMigrationCommandSpec.groovy
index 05d5f36cc2..9d72a536e4 100644
--- a/grails-data-hibernate5/dbmigration/src/test/groovy/org/grails/plugins/databasemigration/command/ScriptDatabaseMigrationCommandSpec.groovy
+++ b/grails-data-hibernate5/dbmigration/src/test/groovy/org/apache/grails/data/hibernate5/dbmigration/cli/ScriptDatabaseMigrationCommandSpec.groovy
@@ -16,7 +16,7 @@
  *  specific language governing permissions and limitations
  *  under the License.
  */
-package org.grails.plugins.databasemigration.command
+package org.apache.grails.data.hibernate5.dbmigration.cli
 
 import grails.util.GrailsNameUtils
 import org.grails.build.parsing.CommandLineParser
diff --git a/grails-data-hibernate5/dbmigration/src/test/groovy/org/grails/plugins/databasemigration/liquibase/GroovyChangeLogSpec.groovy b/grails-data-hibernate5/dbmigration/src/test/groovy/org/grails/plugins/databasemigration/liquibase/GroovyChangeLogSpec.groovy
index 0059c43fa2..c07b603695 100644
--- a/grails-data-hibernate5/dbmigration/src/test/groovy/org/grails/plugins/databasemigration/liquibase/GroovyChangeLogSpec.groovy
+++ b/grails-data-hibernate5/dbmigration/src/test/groovy/org/grails/plugins/databasemigration/liquibase/GroovyChangeLogSpec.groovy
@@ -20,12 +20,12 @@ package org.grails.plugins.databasemigration.liquibase
 
 import grails.core.GrailsApplication
 import liquibase.exception.CommandExecutionException
-import org.grails.plugins.databasemigration.command.ApplicationContextDatabaseMigrationCommandSpec
-import org.grails.plugins.databasemigration.command.DbmChangelogSyncCommand
-import org.grails.plugins.databasemigration.command.DbmRollbackCommand
-import org.grails.plugins.databasemigration.command.DbmTagCommand
-import org.grails.plugins.databasemigration.command.DbmUpdateCommand
-import org.grails.plugins.databasemigration.command.DbmUpdateCountCommand
+import org.apache.grails.data.hibernate5.dbmigration.cli.ApplicationContextDatabaseMigrationCommandSpec
+import org.apache.grails.data.hibernate5.dbmigration.cli.DbmChangelogSyncCommand
+import org.apache.grails.data.hibernate5.dbmigration.cli.DbmRollbackCommand
+import org.apache.grails.data.hibernate5.dbmigration.cli.DbmTagCommand
+import org.apache.grails.data.hibernate5.dbmigration.cli.DbmUpdateCommand
+import org.apache.grails.data.hibernate5.dbmigration.cli.DbmUpdateCountCommand
 
 class GroovyChangeLogSpec extends ApplicationContextDatabaseMigrationCommandSpec {
 
diff --git a/grails-data-hibernate5/dbmigration/src/test/groovy/org/grails/plugins/databasemigration/liquibase/GroovyPreconditionSpec.groovy b/grails-data-hibernate5/dbmigration/src/test/groovy/org/grails/plugins/databasemigration/liquibase/GroovyPreconditionSpec.groovy
index 6118abadba..ba5adf1562 100644
--- a/grails-data-hibernate5/dbmigration/src/test/groovy/org/grails/plugins/databasemigration/liquibase/GroovyPreconditionSpec.groovy
+++ b/grails-data-hibernate5/dbmigration/src/test/groovy/org/grails/plugins/databasemigration/liquibase/GroovyPreconditionSpec.groovy
@@ -19,8 +19,8 @@
 package org.grails.plugins.databasemigration.liquibase
 
 import liquibase.exception.CommandExecutionException
-import org.grails.plugins.databasemigration.command.ApplicationContextDatabaseMigrationCommandSpec
-import org.grails.plugins.databasemigration.command.DbmUpdateCommand
+import org.apache.grails.data.hibernate5.dbmigration.cli.ApplicationContextDatabaseMigrationCommandSpec
+import org.apache.grails.data.hibernate5.dbmigration.cli.DbmUpdateCommand
 
 class GroovyPreconditionSpec extends ApplicationContextDatabaseMigrationCommandSpec {
 
diff --git a/grails-data-hibernate5/grails-plugin/build.gradle b/grails-data-hibernate5/grails-plugin/build.gradle
index 30c278467d..7ec025263f 100644
--- a/grails-data-hibernate5/grails-plugin/build.gradle
+++ b/grails-data-hibernate5/grails-plugin/build.gradle
@@ -21,6 +21,7 @@ plugins {
     id 'org.apache.grails.buildsrc.properties'
     id 'org.apache.grails.buildsrc.dependency-validator'
     id 'org.apache.grails.gradle.grails-plugin'
+    id 'org.apache.grails.gradle.grails-plugin-cli'
     id 'org.apache.grails.buildsrc.compile'
     id 'org.apache.grails.buildsrc.publish'
     id 'org.apache.grails.buildsrc.sbom'
@@ -32,6 +33,12 @@ plugins {
 version = projectVersion
 group = 'org.apache.grails'
 
+cliArtifact {
+    automaticModuleName = 'org.apache.grails.data.hibernate5.cli'
+    // this framework module wires its cli dependencies with project dependencies below
+    defaultDependencies = false
+}
+
 ext {
     gormApiDocs = true
     pomTitle = 'Grails GORM Hibernate 5 Plugin'
@@ -39,6 +46,15 @@ ext {
 }
 
 dependencies {
+    // the cli tier — published separately as org.apache.grails:grails-data-hibernate5-cli
+    cliImplementation platform(project(':grails-hibernate5-bom'))
+    cliApi project(project.path)
+    cliApi(project(':grails-core')) {
+        capabilities {
+            requireCapability('org.apache.grails:grails-core-cli')
+        }
+    }
+
     // TODO: Clarify and clean up dependencies
     implementation platform(project(':grails-bom'))
 
diff --git a/grails-data-hibernate5/grails-plugin/src/main/groovy/grails/plugin/hibernate/commands/SchemaExportCommand.groovy b/grails-data-hibernate5/grails-plugin/src/cli/groovy/org/apache/grails/data/hibernate5/cli/SchemaExportCommand.groovy
similarity index 96%
rename from grails-data-hibernate5/grails-plugin/src/main/groovy/grails/plugin/hibernate/commands/SchemaExportCommand.groovy
rename to grails-data-hibernate5/grails-plugin/src/cli/groovy/org/apache/grails/data/hibernate5/cli/SchemaExportCommand.groovy
index 5b6a06a7b9..d3499fcd6b 100644
--- a/grails-data-hibernate5/grails-plugin/src/main/groovy/grails/plugin/hibernate/commands/SchemaExportCommand.groovy
+++ b/grails-data-hibernate5/grails-plugin/src/cli/groovy/org/apache/grails/data/hibernate5/cli/SchemaExportCommand.groovy
@@ -16,7 +16,7 @@
  *  specific language governing permissions and limitations
  *  under the License.
  */
-package grails.plugin.hibernate.commands
+package org.apache.grails.data.hibernate5.cli
 
 import groovy.transform.CompileStatic
 
@@ -24,8 +24,8 @@ import org.hibernate.engine.spi.SessionFactoryImplementor
 import org.hibernate.tool.hbm2ddl.SchemaExport as HibernateSchemaExport
 import org.hibernate.tool.schema.TargetType
 
-import grails.dev.commands.ApplicationCommand
-import grails.dev.commands.ExecutionContext
+import org.apache.grails.core.cli.ApplicationCommand
+import org.apache.grails.core.cli.ExecutionContext
 import grails.util.Environment
 import org.grails.build.parsing.CommandLine
 import org.grails.datastore.mapping.core.connections.ConnectionSource
diff --git a/grails-data-hibernate7/dbmigration/build.gradle b/grails-data-hibernate7/dbmigration/build.gradle
index be1098032d..b5f31beada 100644
--- a/grails-data-hibernate7/dbmigration/build.gradle
+++ b/grails-data-hibernate7/dbmigration/build.gradle
@@ -21,6 +21,7 @@ plugins {
     id 'org.apache.grails.buildsrc.properties'
     id 'org.apache.grails.buildsrc.dependency-validator'
     id 'org.apache.grails.gradle.grails-plugin'
+    id 'org.apache.grails.gradle.grails-plugin-cli'
     id 'org.apache.grails.buildsrc.compile'
     id 'org.apache.grails.buildsrc.publish'
     id 'org.apache.grails.buildsrc.sbom'
@@ -31,6 +32,12 @@ plugins {
 version = projectVersion
 group = 'org.apache.grails'
 
+cliArtifact {
+    automaticModuleName = 'org.apache.grails.data.hibernate7.dbmigration.cli'
+    // this framework module wires its cli dependencies with project dependencies below
+    defaultDependencies = false
+}
+
 ext {
     gormApiDocs = true
     pomTitle = 'Grails Database Migration Plugin for Hibernate 7'
@@ -60,7 +67,22 @@ dependencies {
     testAnnotationProcessor platform(project(':grails-hibernate7-bom'))
     testAnnotationProcessor "org.projectlombok:lombok"
 
-    implementation(project(':grails-shell-cli')) {
+    // the cli tier — published separately as org.apache.grails:grails-data-hibernate7-dbmigration-cli;
+    // the dbm-* commands and their CLI-only dependencies (grails-shell-cli) stay off the
+    // application runtime classpath entirely
+    cliImplementation platform(project(':grails-hibernate7-bom'))
+    cliApi project(project.path)
+    cliApi(project(':grails-core')) {
+        capabilities {
+            requireCapability('org.apache.grails:grails-core-cli')
+        }
+    }
+    cliImplementation 'org.liquibase:liquibase-core'
+    cliImplementation project(':grails-data-hibernate7-dbmigration-core')
+    cliImplementation project(':grails-data-hibernate7')
+    cliCompileOnly 'org.apache.groovy:groovy-sql'
+    cliCompileOnly 'org.apache.groovy:groovy-xml'
+    cliImplementation(project(':grails-shell-cli')) {
         exclude group: 'org.slf4j', module: 'slf4j-simple'
 
         // Keep legacy org.codehaus.groovy artifacts off this plugin's Groovy 5 classpath.
diff --git a/grails-data-hibernate7/dbmigration/src/main/groovy/org/grails/plugins/databasemigration/command/ApplicationContextDatabaseMigrationCommand.groovy b/grails-data-hibernate7/dbmigration/src/cli/groovy/org/apache/grails/data/hibernate7/dbmigration/cli/ApplicationContextDatabaseMigrationCommand.groovy
similarity index 97%
rename from grails-data-hibernate7/dbmigration/src/main/groovy/org/grails/plugins/databasemigration/command/ApplicationContextDatabaseMigrationCommand.groovy
rename to grails-data-hibernate7/dbmigration/src/cli/groovy/org/apache/grails/data/hibernate7/dbmigration/cli/ApplicationContextDatabaseMigrationCommand.groovy
index 3299da1e5e..d66b597d7e 100644
--- a/grails-data-hibernate7/dbmigration/src/main/groovy/org/grails/plugins/databasemigration/command/ApplicationContextDatabaseMigrationCommand.groovy
+++ b/grails-data-hibernate7/dbmigration/src/cli/groovy/org/apache/grails/data/hibernate7/dbmigration/cli/ApplicationContextDatabaseMigrationCommand.groovy
@@ -16,7 +16,7 @@
  *  specific language governing permissions and limitations
  *  under the License.
  */
-package org.grails.plugins.databasemigration.command
+package org.apache.grails.data.hibernate7.dbmigration.cli
 
 import groovy.transform.CompileStatic
 import groovy.transform.stc.ClosureParams
@@ -33,7 +33,7 @@ import org.springframework.context.ConfigurableApplicationContext
 
 import grails.config.ConfigMap
 import grails.core.GrailsApplication
-import grails.dev.commands.ExecutionContext
+import org.apache.grails.core.cli.ExecutionContext
 import grails.util.Environment
 import org.grails.config.PropertySourcesConfig
 import org.grails.orm.hibernate.HibernateDatastore
diff --git a/grails-data-hibernate7/dbmigration/src/main/groovy/org/grails/plugins/databasemigration/command/DatabaseMigrationCommand.groovy b/grails-data-hibernate7/dbmigration/src/cli/groovy/org/apache/grails/data/hibernate7/dbmigration/cli/DatabaseMigrationCommand.groovy
similarity index 99%
rename from grails-data-hibernate7/dbmigration/src/main/groovy/org/grails/plugins/databasemigration/command/DatabaseMigrationCommand.groovy
rename to grails-data-hibernate7/dbmigration/src/cli/groovy/org/apache/grails/data/hibernate7/dbmigration/cli/DatabaseMigrationCommand.groovy
index 3311b7275c..fee9ad371d 100644
--- a/grails-data-hibernate7/dbmigration/src/main/groovy/org/grails/plugins/databasemigration/command/DatabaseMigrationCommand.groovy
+++ b/grails-data-hibernate7/dbmigration/src/cli/groovy/org/apache/grails/data/hibernate7/dbmigration/cli/DatabaseMigrationCommand.groovy
@@ -16,7 +16,7 @@
  *  specific language governing permissions and limitations
  *  under the License.
  */
-package org.grails.plugins.databasemigration.command
+package org.apache.grails.data.hibernate7.dbmigration.cli
 
 import java.nio.charset.StandardCharsets
 import java.nio.file.Path
diff --git a/grails-data-hibernate7/dbmigration/grails-app/commands/org/grails/plugins/databasemigration/command/DbmChangelogSyncCommand.groovy b/grails-data-hibernate7/dbmigration/src/cli/groovy/org/apache/grails/data/hibernate7/dbmigration/cli/DbmChangelogSyncCommand.groovy
similarity index 91%
rename from grails-data-hibernate7/dbmigration/grails-app/commands/org/grails/plugins/databasemigration/command/DbmChangelogSyncCommand.groovy
rename to grails-data-hibernate7/dbmigration/src/cli/groovy/org/apache/grails/data/hibernate7/dbmigration/cli/DbmChangelogSyncCommand.groovy
index 25f30e2287..619014b283 100644
--- a/grails-data-hibernate7/dbmigration/grails-app/commands/org/grails/plugins/databasemigration/command/DbmChangelogSyncCommand.groovy
+++ b/grails-data-hibernate7/dbmigration/src/cli/groovy/org/apache/grails/data/hibernate7/dbmigration/cli/DbmChangelogSyncCommand.groovy
@@ -16,13 +16,13 @@
  *  specific language governing permissions and limitations
  *  under the License.
  */
-package org.grails.plugins.databasemigration.command
+package org.apache.grails.data.hibernate7.dbmigration.cli
 
 import groovy.transform.CompileStatic
 
 import liquibase.Liquibase
 
-import grails.dev.commands.ApplicationCommand
+import org.apache.grails.core.cli.ApplicationCommand
 
 @CompileStatic
 class DbmChangelogSyncCommand implements ApplicationCommand, ApplicationContextDatabaseMigrationCommand {
diff --git a/grails-data-hibernate5/dbmigration/grails-app/commands/org/grails/plugins/databasemigration/command/DbmChangelogSyncSqlCommand.groovy b/grails-data-hibernate7/dbmigration/src/cli/groovy/org/apache/grails/data/hibernate7/dbmigration/cli/DbmChangelogSyncSqlCommand.groovy
similarity index 92%
rename from grails-data-hibernate5/dbmigration/grails-app/commands/org/grails/plugins/databasemigration/command/DbmChangelogSyncSqlCommand.groovy
rename to grails-data-hibernate7/dbmigration/src/cli/groovy/org/apache/grails/data/hibernate7/dbmigration/cli/DbmChangelogSyncSqlCommand.groovy
index 476d383410..af910fb9a7 100644
--- a/grails-data-hibernate5/dbmigration/grails-app/commands/org/grails/plugins/databasemigration/command/DbmChangelogSyncSqlCommand.groovy
+++ b/grails-data-hibernate7/dbmigration/src/cli/groovy/org/apache/grails/data/hibernate7/dbmigration/cli/DbmChangelogSyncSqlCommand.groovy
@@ -16,13 +16,13 @@
  *  specific language governing permissions and limitations
  *  under the License.
  */
-package org.grails.plugins.databasemigration.command
+package org.apache.grails.data.hibernate7.dbmigration.cli
 
 import groovy.transform.CompileStatic
 
 import liquibase.Liquibase
 
-import grails.dev.commands.ApplicationCommand
+import org.apache.grails.core.cli.ApplicationCommand
 
 @CompileStatic
 class DbmChangelogSyncSqlCommand implements ApplicationCommand, ApplicationContextDatabaseMigrationCommand {
diff --git a/grails-data-hibernate7/dbmigration/src/main/groovy/org/grails/plugins/databasemigration/command/DbmChangelogToGroovy.groovy b/grails-data-hibernate7/dbmigration/src/cli/groovy/org/apache/grails/data/hibernate7/dbmigration/cli/DbmChangelogToGroovy.groovy
similarity index 98%
rename from grails-data-hibernate7/dbmigration/src/main/groovy/org/grails/plugins/databasemigration/command/DbmChangelogToGroovy.groovy
rename to grails-data-hibernate7/dbmigration/src/cli/groovy/org/apache/grails/data/hibernate7/dbmigration/cli/DbmChangelogToGroovy.groovy
index 532ca699bc..34326f9972 100644
--- a/grails-data-hibernate7/dbmigration/src/main/groovy/org/grails/plugins/databasemigration/command/DbmChangelogToGroovy.groovy
+++ b/grails-data-hibernate7/dbmigration/src/cli/groovy/org/apache/grails/data/hibernate7/dbmigration/cli/DbmChangelogToGroovy.groovy
@@ -16,7 +16,7 @@
  *  specific language governing permissions and limitations
  *  under the License.
  */
-package org.grails.plugins.databasemigration.command
+package org.apache.grails.data.hibernate7.dbmigration.cli
 
 import groovy.transform.CompileStatic
 import groovy.transform.stc.ClosureParams
diff --git a/grails-data-hibernate5/dbmigration/grails-app/commands/org/grails/plugins/databasemigration/command/DbmClearChecksumsCommand.groovy b/grails-data-hibernate7/dbmigration/src/cli/groovy/org/apache/grails/data/hibernate7/dbmigration/cli/DbmClearChecksumsCommand.groovy
similarity index 91%
rename from grails-data-hibernate5/dbmigration/grails-app/commands/org/grails/plugins/databasemigration/command/DbmClearChecksumsCommand.groovy
rename to grails-data-hibernate7/dbmigration/src/cli/groovy/org/apache/grails/data/hibernate7/dbmigration/cli/DbmClearChecksumsCommand.groovy
index 0006e1649b..843ff030b7 100644
--- a/grails-data-hibernate5/dbmigration/grails-app/commands/org/grails/plugins/databasemigration/command/DbmClearChecksumsCommand.groovy
+++ b/grails-data-hibernate7/dbmigration/src/cli/groovy/org/apache/grails/data/hibernate7/dbmigration/cli/DbmClearChecksumsCommand.groovy
@@ -16,13 +16,13 @@
  *  specific language governing permissions and limitations
  *  under the License.
  */
-package org.grails.plugins.databasemigration.command
+package org.apache.grails.data.hibernate7.dbmigration.cli
 
 import groovy.transform.CompileStatic
 
 import liquibase.Liquibase
 
-import grails.dev.commands.ApplicationCommand
+import org.apache.grails.core.cli.ApplicationCommand
 
 @CompileStatic
 class DbmClearChecksumsCommand implements ApplicationCommand, ApplicationContextDatabaseMigrationCommand {
diff --git a/grails-data-hibernate5/dbmigration/src/main/groovy/org/grails/plugins/databasemigration/command/DbmCreateChangelog.groovy b/grails-data-hibernate7/dbmigration/src/cli/groovy/org/apache/grails/data/hibernate7/dbmigration/cli/DbmCreateChangelog.groovy
similarity index 97%
rename from grails-data-hibernate5/dbmigration/src/main/groovy/org/grails/plugins/databasemigration/command/DbmCreateChangelog.groovy
rename to grails-data-hibernate7/dbmigration/src/cli/groovy/org/apache/grails/data/hibernate7/dbmigration/cli/DbmCreateChangelog.groovy
index dddc41bfa6..b13c24b167 100644
--- a/grails-data-hibernate5/dbmigration/src/main/groovy/org/grails/plugins/databasemigration/command/DbmCreateChangelog.groovy
+++ b/grails-data-hibernate7/dbmigration/src/cli/groovy/org/apache/grails/data/hibernate7/dbmigration/cli/DbmCreateChangelog.groovy
@@ -16,7 +16,7 @@
  *  specific language governing permissions and limitations
  *  under the License.
  */
-package org.grails.plugins.databasemigration.command
+package org.apache.grails.data.hibernate7.dbmigration.cli
 
 import groovy.transform.CompileStatic
 
diff --git a/grails-data-hibernate5/dbmigration/grails-app/commands/org/grails/plugins/databasemigration/command/DbmDbDocCommand.groovy b/grails-data-hibernate7/dbmigration/src/cli/groovy/org/apache/grails/data/hibernate7/dbmigration/cli/DbmDbDocCommand.groovy
similarity index 92%
rename from grails-data-hibernate5/dbmigration/grails-app/commands/org/grails/plugins/databasemigration/command/DbmDbDocCommand.groovy
rename to grails-data-hibernate7/dbmigration/src/cli/groovy/org/apache/grails/data/hibernate7/dbmigration/cli/DbmDbDocCommand.groovy
index 059ff5208e..74293240a3 100644
--- a/grails-data-hibernate5/dbmigration/grails-app/commands/org/grails/plugins/databasemigration/command/DbmDbDocCommand.groovy
+++ b/grails-data-hibernate7/dbmigration/src/cli/groovy/org/apache/grails/data/hibernate7/dbmigration/cli/DbmDbDocCommand.groovy
@@ -16,13 +16,13 @@
  *  specific language governing permissions and limitations
  *  under the License.
  */
-package org.grails.plugins.databasemigration.command
+package org.apache.grails.data.hibernate7.dbmigration.cli
 
 import groovy.transform.CompileStatic
 
 import liquibase.Liquibase
 
-import grails.dev.commands.ApplicationCommand
+import org.apache.grails.core.cli.ApplicationCommand
 
 @CompileStatic
 class DbmDbDocCommand implements ApplicationCommand, ApplicationContextDatabaseMigrationCommand {
diff --git a/grails-data-hibernate7/dbmigration/grails-app/commands/org/grails/plugins/databasemigration/command/DbmDiffCommand.groovy b/grails-data-hibernate7/dbmigration/src/cli/groovy/org/apache/grails/data/hibernate7/dbmigration/cli/DbmDiffCommand.groovy
similarity index 96%
rename from grails-data-hibernate7/dbmigration/grails-app/commands/org/grails/plugins/databasemigration/command/DbmDiffCommand.groovy
rename to grails-data-hibernate7/dbmigration/src/cli/groovy/org/apache/grails/data/hibernate7/dbmigration/cli/DbmDiffCommand.groovy
index 9e3f1e6a13..95cdeece7d 100644
--- a/grails-data-hibernate7/dbmigration/grails-app/commands/org/grails/plugins/databasemigration/command/DbmDiffCommand.groovy
+++ b/grails-data-hibernate7/dbmigration/src/cli/groovy/org/apache/grails/data/hibernate7/dbmigration/cli/DbmDiffCommand.groovy
@@ -16,13 +16,13 @@
  *  specific language governing permissions and limitations
  *  under the License.
  */
-package org.grails.plugins.databasemigration.command
+package org.apache.grails.data.hibernate7.dbmigration.cli
 
 import groovy.transform.CompileStatic
 
 import liquibase.database.Database
 
-import grails.dev.commands.ApplicationCommand
+import org.apache.grails.core.cli.ApplicationCommand
 import grails.util.Environment
 import org.grails.plugins.databasemigration.DatabaseMigrationException
 
diff --git a/grails-data-hibernate7/dbmigration/grails-app/commands/org/grails/plugins/databasemigration/command/DbmDropAllCommand.groovy b/grails-data-hibernate7/dbmigration/src/cli/groovy/org/apache/grails/data/hibernate7/dbmigration/cli/DbmDropAllCommand.groovy
similarity index 93%
rename from grails-data-hibernate7/dbmigration/grails-app/commands/org/grails/plugins/databasemigration/command/DbmDropAllCommand.groovy
rename to grails-data-hibernate7/dbmigration/src/cli/groovy/org/apache/grails/data/hibernate7/dbmigration/cli/DbmDropAllCommand.groovy
index efbc21c533..f7cfca1c5c 100644
--- a/grails-data-hibernate7/dbmigration/grails-app/commands/org/grails/plugins/databasemigration/command/DbmDropAllCommand.groovy
+++ b/grails-data-hibernate7/dbmigration/src/cli/groovy/org/apache/grails/data/hibernate7/dbmigration/cli/DbmDropAllCommand.groovy
@@ -16,14 +16,14 @@
  *  specific language governing permissions and limitations
  *  under the License.
  */
-package org.grails.plugins.databasemigration.command
+package org.apache.grails.data.hibernate7.dbmigration.cli
 
 import groovy.transform.CompileStatic
 
 import liquibase.CatalogAndSchema
 import liquibase.Liquibase
 
-import grails.dev.commands.ApplicationCommand
+import org.apache.grails.core.cli.ApplicationCommand
 
 @CompileStatic
 class DbmDropAllCommand implements ApplicationCommand, ApplicationContextDatabaseMigrationCommand {
diff --git a/grails-data-hibernate5/dbmigration/grails-app/commands/org/grails/plugins/databasemigration/command/DbmFutureRollbackCountSqlCommand.groovy b/grails-data-hibernate7/dbmigration/src/cli/groovy/org/apache/grails/data/hibernate7/dbmigration/cli/DbmFutureRollbackCountSqlCommand.groovy
similarity index 94%
rename from grails-data-hibernate5/dbmigration/grails-app/commands/org/grails/plugins/databasemigration/command/DbmFutureRollbackCountSqlCommand.groovy
rename to grails-data-hibernate7/dbmigration/src/cli/groovy/org/apache/grails/data/hibernate7/dbmigration/cli/DbmFutureRollbackCountSqlCommand.groovy
index 899a550d92..a5ca2faf06 100644
--- a/grails-data-hibernate5/dbmigration/grails-app/commands/org/grails/plugins/databasemigration/command/DbmFutureRollbackCountSqlCommand.groovy
+++ b/grails-data-hibernate7/dbmigration/src/cli/groovy/org/apache/grails/data/hibernate7/dbmigration/cli/DbmFutureRollbackCountSqlCommand.groovy
@@ -16,13 +16,13 @@
  *  specific language governing permissions and limitations
  *  under the License.
  */
-package org.grails.plugins.databasemigration.command
+package org.apache.grails.data.hibernate7.dbmigration.cli
 
 import groovy.transform.CompileStatic
 
 import liquibase.Liquibase
 
-import grails.dev.commands.ApplicationCommand
+import org.apache.grails.core.cli.ApplicationCommand
 import org.grails.plugins.databasemigration.DatabaseMigrationException
 
 @CompileStatic
diff --git a/grails-data-hibernate7/dbmigration/grails-app/commands/org/grails/plugins/databasemigration/command/DbmFutureRollbackSqlCommand.groovy b/grails-data-hibernate7/dbmigration/src/cli/groovy/org/apache/grails/data/hibernate7/dbmigration/cli/DbmFutureRollbackSqlCommand.groovy
similarity index 92%
rename from grails-data-hibernate7/dbmigration/grails-app/commands/org/grails/plugins/databasemigration/command/DbmFutureRollbackSqlCommand.groovy
rename to grails-data-hibernate7/dbmigration/src/cli/groovy/org/apache/grails/data/hibernate7/dbmigration/cli/DbmFutureRollbackSqlCommand.groovy
index 2e7e0d66e0..113f1aa3ec 100644
--- a/grails-data-hibernate7/dbmigration/grails-app/commands/org/grails/plugins/databasemigration/command/DbmFutureRollbackSqlCommand.groovy
+++ b/grails-data-hibernate7/dbmigration/src/cli/groovy/org/apache/grails/data/hibernate7/dbmigration/cli/DbmFutureRollbackSqlCommand.groovy
@@ -16,13 +16,13 @@
  *  specific language governing permissions and limitations
  *  under the License.
  */
-package org.grails.plugins.databasemigration.command
+package org.apache.grails.data.hibernate7.dbmigration.cli
 
 import groovy.transform.CompileStatic
 
 import liquibase.Liquibase
 
-import grails.dev.commands.ApplicationCommand
+import org.apache.grails.core.cli.ApplicationCommand
 
 @CompileStatic
 class DbmFutureRollbackSqlCommand implements ApplicationCommand, ApplicationContextDatabaseMigrationCommand {
diff --git a/grails-data-hibernate5/dbmigration/grails-app/commands/org/grails/plugins/databasemigration/command/DbmGenerateChangelogCommand.groovy b/grails-data-hibernate7/dbmigration/src/cli/groovy/org/apache/grails/data/hibernate7/dbmigration/cli/DbmGenerateChangelogCommand.groovy
similarity index 94%
rename from grails-data-hibernate5/dbmigration/grails-app/commands/org/grails/plugins/databasemigration/command/DbmGenerateChangelogCommand.groovy
rename to grails-data-hibernate7/dbmigration/src/cli/groovy/org/apache/grails/data/hibernate7/dbmigration/cli/DbmGenerateChangelogCommand.groovy
index 73d1e226bd..19fdf861be 100644
--- a/grails-data-hibernate5/dbmigration/grails-app/commands/org/grails/plugins/databasemigration/command/DbmGenerateChangelogCommand.groovy
+++ b/grails-data-hibernate7/dbmigration/src/cli/groovy/org/apache/grails/data/hibernate7/dbmigration/cli/DbmGenerateChangelogCommand.groovy
@@ -16,13 +16,13 @@
  *  specific language governing permissions and limitations
  *  under the License.
  */
-package org.grails.plugins.databasemigration.command
+package org.apache.grails.data.hibernate7.dbmigration.cli
 
 import groovy.transform.CompileStatic
 
 import liquibase.database.Database
 
-import grails.dev.commands.ApplicationCommand
+import org.apache.grails.core.cli.ApplicationCommand
 import org.grails.plugins.databasemigration.DatabaseMigrationException
 
 @CompileStatic
diff --git a/grails-data-hibernate7/dbmigration/grails-app/commands/org/grails/plugins/databasemigration/command/DbmGenerateGormChangelogCommand.groovy b/grails-data-hibernate7/dbmigration/src/cli/groovy/org/apache/grails/data/hibernate7/dbmigration/cli/DbmGenerateGormChangelogCommand.groovy
similarity index 95%
rename from grails-data-hibernate7/dbmigration/grails-app/commands/org/grails/plugins/databasemigration/command/DbmGenerateGormChangelogCommand.groovy
rename to grails-data-hibernate7/dbmigration/src/cli/groovy/org/apache/grails/data/hibernate7/dbmigration/cli/DbmGenerateGormChangelogCommand.groovy
index 8519c83732..56f07453ef 100644
--- a/grails-data-hibernate7/dbmigration/grails-app/commands/org/grails/plugins/databasemigration/command/DbmGenerateGormChangelogCommand.groovy
+++ b/grails-data-hibernate7/dbmigration/src/cli/groovy/org/apache/grails/data/hibernate7/dbmigration/cli/DbmGenerateGormChangelogCommand.groovy
@@ -16,13 +16,13 @@
  *  specific language governing permissions and limitations
  *  under the License.
  */
-package org.grails.plugins.databasemigration.command
+package org.apache.grails.data.hibernate7.dbmigration.cli
 
 import groovy.transform.CompileStatic
 
 import liquibase.database.Database
 
-import grails.dev.commands.ApplicationCommand
+import org.apache.grails.core.cli.ApplicationCommand
 import org.grails.plugins.databasemigration.DatabaseMigrationException
 
 @CompileStatic
diff --git a/grails-data-hibernate5/dbmigration/grails-app/commands/org/grails/plugins/databasemigration/command/DbmGormDiffCommand.groovy b/grails-data-hibernate7/dbmigration/src/cli/groovy/org/apache/grails/data/hibernate7/dbmigration/cli/DbmGormDiffCommand.groovy
similarity index 95%
rename from grails-data-hibernate5/dbmigration/grails-app/commands/org/grails/plugins/databasemigration/command/DbmGormDiffCommand.groovy
rename to grails-data-hibernate7/dbmigration/src/cli/groovy/org/apache/grails/data/hibernate7/dbmigration/cli/DbmGormDiffCommand.groovy
index 52d68b92e0..39202ffb78 100644
--- a/grails-data-hibernate5/dbmigration/grails-app/commands/org/grails/plugins/databasemigration/command/DbmGormDiffCommand.groovy
+++ b/grails-data-hibernate7/dbmigration/src/cli/groovy/org/apache/grails/data/hibernate7/dbmigration/cli/DbmGormDiffCommand.groovy
@@ -16,13 +16,13 @@
  *  specific language governing permissions and limitations
  *  under the License.
  */
-package org.grails.plugins.databasemigration.command
+package org.apache.grails.data.hibernate7.dbmigration.cli
 
 import groovy.transform.CompileStatic
 
 import liquibase.database.Database
 
-import grails.dev.commands.ApplicationCommand
+import org.apache.grails.core.cli.ApplicationCommand
 import org.grails.plugins.databasemigration.DatabaseMigrationException
 
 @CompileStatic
diff --git a/grails-data-hibernate7/dbmigration/grails-app/commands/org/grails/plugins/databasemigration/command/DbmListLocksCommand.groovy b/grails-data-hibernate7/dbmigration/src/cli/groovy/org/apache/grails/data/hibernate7/dbmigration/cli/DbmListLocksCommand.groovy
similarity index 94%
rename from grails-data-hibernate7/dbmigration/grails-app/commands/org/grails/plugins/databasemigration/command/DbmListLocksCommand.groovy
rename to grails-data-hibernate7/dbmigration/src/cli/groovy/org/apache/grails/data/hibernate7/dbmigration/cli/DbmListLocksCommand.groovy
index de2d8c402f..1a99a9139a 100644
--- a/grails-data-hibernate7/dbmigration/grails-app/commands/org/grails/plugins/databasemigration/command/DbmListLocksCommand.groovy
+++ b/grails-data-hibernate7/dbmigration/src/cli/groovy/org/apache/grails/data/hibernate7/dbmigration/cli/DbmListLocksCommand.groovy
@@ -16,7 +16,7 @@
  *  specific language governing permissions and limitations
  *  under the License.
  */
-package org.grails.plugins.databasemigration.command
+package org.apache.grails.data.hibernate7.dbmigration.cli
 
 import groovy.transform.CompileStatic
 import groovy.transform.stc.ClosureParams
@@ -24,7 +24,7 @@ import groovy.transform.stc.SimpleType
 
 import liquibase.Liquibase
 
-import grails.dev.commands.ApplicationCommand
+import org.apache.grails.core.cli.ApplicationCommand
 
 @CompileStatic
 class DbmListLocksCommand implements ApplicationCommand, ApplicationContextDatabaseMigrationCommand {
diff --git a/grails-data-hibernate5/dbmigration/grails-app/commands/org/grails/plugins/databasemigration/command/DbmMarkNextChangesetRanCommand.groovy b/grails-data-hibernate7/dbmigration/src/cli/groovy/org/apache/grails/data/hibernate7/dbmigration/cli/DbmMarkNextChangesetRanCommand.groovy
similarity index 91%
rename from grails-data-hibernate5/dbmigration/grails-app/commands/org/grails/plugins/databasemigration/command/DbmMarkNextChangesetRanCommand.groovy
rename to grails-data-hibernate7/dbmigration/src/cli/groovy/org/apache/grails/data/hibernate7/dbmigration/cli/DbmMarkNextChangesetRanCommand.groovy
index 4ba6e01987..90392f8e8c 100644
--- a/grails-data-hibernate5/dbmigration/grails-app/commands/org/grails/plugins/databasemigration/command/DbmMarkNextChangesetRanCommand.groovy
+++ b/grails-data-hibernate7/dbmigration/src/cli/groovy/org/apache/grails/data/hibernate7/dbmigration/cli/DbmMarkNextChangesetRanCommand.groovy
@@ -16,13 +16,13 @@
  *  specific language governing permissions and limitations
  *  under the License.
  */
-package org.grails.plugins.databasemigration.command
+package org.apache.grails.data.hibernate7.dbmigration.cli
 
 import groovy.transform.CompileStatic
 
 import liquibase.Liquibase
 
-import grails.dev.commands.ApplicationCommand
+import org.apache.grails.core.cli.ApplicationCommand
 
 @CompileStatic
 class DbmMarkNextChangesetRanCommand implements ApplicationCommand, ApplicationContextDatabaseMigrationCommand {
diff --git a/grails-data-hibernate5/dbmigration/grails-app/commands/org/grails/plugins/databasemigration/command/DbmMarkNextChangesetRanSqlCommand.groovy b/grails-data-hibernate7/dbmigration/src/cli/groovy/org/apache/grails/data/hibernate7/dbmigration/cli/DbmMarkNextChangesetRanSqlCommand.groovy
similarity index 92%
rename from grails-data-hibernate5/dbmigration/grails-app/commands/org/grails/plugins/databasemigration/command/DbmMarkNextChangesetRanSqlCommand.groovy
rename to grails-data-hibernate7/dbmigration/src/cli/groovy/org/apache/grails/data/hibernate7/dbmigration/cli/DbmMarkNextChangesetRanSqlCommand.groovy
index 427c424b94..8c4db77066 100644
--- a/grails-data-hibernate5/dbmigration/grails-app/commands/org/grails/plugins/databasemigration/command/DbmMarkNextChangesetRanSqlCommand.groovy
+++ b/grails-data-hibernate7/dbmigration/src/cli/groovy/org/apache/grails/data/hibernate7/dbmigration/cli/DbmMarkNextChangesetRanSqlCommand.groovy
@@ -16,13 +16,13 @@
  *  specific language governing permissions and limitations
  *  under the License.
  */
-package org.grails.plugins.databasemigration.command
+package org.apache.grails.data.hibernate7.dbmigration.cli
 
 import groovy.transform.CompileStatic
 
 import liquibase.Liquibase
 
-import grails.dev.commands.ApplicationCommand
+import org.apache.grails.core.cli.ApplicationCommand
 
 @CompileStatic
 class DbmMarkNextChangesetRanSqlCommand implements ApplicationCommand, ApplicationContextDatabaseMigrationCommand {
diff --git a/grails-data-hibernate5/dbmigration/grails-app/commands/org/grails/plugins/databasemigration/command/DbmPreviousChangesetSqlCommand.groovy b/grails-data-hibernate7/dbmigration/src/cli/groovy/org/apache/grails/data/hibernate7/dbmigration/cli/DbmPreviousChangesetSqlCommand.groovy
similarity index 95%
rename from grails-data-hibernate5/dbmigration/grails-app/commands/org/grails/plugins/databasemigration/command/DbmPreviousChangesetSqlCommand.groovy
rename to grails-data-hibernate7/dbmigration/src/cli/groovy/org/apache/grails/data/hibernate7/dbmigration/cli/DbmPreviousChangesetSqlCommand.groovy
index 0d4e77405f..5fcdb96441 100644
--- a/grails-data-hibernate5/dbmigration/grails-app/commands/org/grails/plugins/databasemigration/command/DbmPreviousChangesetSqlCommand.groovy
+++ b/grails-data-hibernate7/dbmigration/src/cli/groovy/org/apache/grails/data/hibernate7/dbmigration/cli/DbmPreviousChangesetSqlCommand.groovy
@@ -16,14 +16,14 @@
  *  specific language governing permissions and limitations
  *  under the License.
  */
-package org.grails.plugins.databasemigration.command
+package org.apache.grails.data.hibernate7.dbmigration.cli
 
 import groovy.transform.CompileStatic
 
 import liquibase.Liquibase
 import liquibase.database.Database
 
-import grails.dev.commands.ApplicationCommand
+import org.apache.grails.core.cli.ApplicationCommand
 import org.grails.plugins.databasemigration.DatabaseMigrationException
 
 @CompileStatic
diff --git a/grails-data-hibernate7/dbmigration/grails-app/commands/org/grails/plugins/databasemigration/command/DbmReleaseLocksCommand.groovy b/grails-data-hibernate7/dbmigration/src/cli/groovy/org/apache/grails/data/hibernate7/dbmigration/cli/DbmReleaseLocksCommand.groovy
similarity index 91%
rename from grails-data-hibernate7/dbmigration/grails-app/commands/org/grails/plugins/databasemigration/command/DbmReleaseLocksCommand.groovy
rename to grails-data-hibernate7/dbmigration/src/cli/groovy/org/apache/grails/data/hibernate7/dbmigration/cli/DbmReleaseLocksCommand.groovy
index 61ad05209b..f8e3d08831 100644
--- a/grails-data-hibernate7/dbmigration/grails-app/commands/org/grails/plugins/databasemigration/command/DbmReleaseLocksCommand.groovy
+++ b/grails-data-hibernate7/dbmigration/src/cli/groovy/org/apache/grails/data/hibernate7/dbmigration/cli/DbmReleaseLocksCommand.groovy
@@ -16,13 +16,13 @@
  *  specific language governing permissions and limitations
  *  under the License.
  */
-package org.grails.plugins.databasemigration.command
+package org.apache.grails.data.hibernate7.dbmigration.cli
 
 import groovy.transform.CompileStatic
 
 import liquibase.Liquibase
 
-import grails.dev.commands.ApplicationCommand
+import org.apache.grails.core.cli.ApplicationCommand
 
 @CompileStatic
 class DbmReleaseLocksCommand implements ApplicationCommand, ApplicationContextDatabaseMigrationCommand {
diff --git a/grails-data-hibernate5/dbmigration/grails-app/commands/org/grails/plugins/databasemigration/command/DbmRollbackCommand.groovy b/grails-data-hibernate7/dbmigration/src/cli/groovy/org/apache/grails/data/hibernate7/dbmigration/cli/DbmRollbackCommand.groovy
similarity index 93%
rename from grails-data-hibernate5/dbmigration/grails-app/commands/org/grails/plugins/databasemigration/command/DbmRollbackCommand.groovy
rename to grails-data-hibernate7/dbmigration/src/cli/groovy/org/apache/grails/data/hibernate7/dbmigration/cli/DbmRollbackCommand.groovy
index 416ba3c6a4..4ecd2eade4 100644
--- a/grails-data-hibernate5/dbmigration/grails-app/commands/org/grails/plugins/databasemigration/command/DbmRollbackCommand.groovy
+++ b/grails-data-hibernate7/dbmigration/src/cli/groovy/org/apache/grails/data/hibernate7/dbmigration/cli/DbmRollbackCommand.groovy
@@ -16,13 +16,13 @@
  *  specific language governing permissions and limitations
  *  under the License.
  */
-package org.grails.plugins.databasemigration.command
+package org.apache.grails.data.hibernate7.dbmigration.cli
 
 import groovy.transform.CompileStatic
 
 import liquibase.Liquibase
 
-import grails.dev.commands.ApplicationCommand
+import org.apache.grails.core.cli.ApplicationCommand
 import org.grails.plugins.databasemigration.DatabaseMigrationException
 
 @CompileStatic
diff --git a/grails-data-hibernate7/dbmigration/grails-app/commands/org/grails/plugins/databasemigration/command/DbmRollbackCountCommand.groovy b/grails-data-hibernate7/dbmigration/src/cli/groovy/org/apache/grails/data/hibernate7/dbmigration/cli/DbmRollbackCountCommand.groovy
similarity index 93%
rename from grails-data-hibernate7/dbmigration/grails-app/commands/org/grails/plugins/databasemigration/command/DbmRollbackCountCommand.groovy
rename to grails-data-hibernate7/dbmigration/src/cli/groovy/org/apache/grails/data/hibernate7/dbmigration/cli/DbmRollbackCountCommand.groovy
index dc61205b9b..25becfcf00 100644
--- a/grails-data-hibernate7/dbmigration/grails-app/commands/org/grails/plugins/databasemigration/command/DbmRollbackCountCommand.groovy
+++ b/grails-data-hibernate7/dbmigration/src/cli/groovy/org/apache/grails/data/hibernate7/dbmigration/cli/DbmRollbackCountCommand.groovy
@@ -16,13 +16,13 @@
  *  specific language governing permissions and limitations
  *  under the License.
  */
-package org.grails.plugins.databasemigration.command
+package org.apache.grails.data.hibernate7.dbmigration.cli
 
 import groovy.transform.CompileStatic
 
 import liquibase.Liquibase
 
-import grails.dev.commands.ApplicationCommand
+import org.apache.grails.core.cli.ApplicationCommand
 import org.grails.plugins.databasemigration.DatabaseMigrationException
 
 @CompileStatic
diff --git a/grails-data-hibernate7/dbmigration/grails-app/commands/org/grails/plugins/databasemigration/command/DbmRollbackCountSqlCommand.groovy b/grails-data-hibernate7/dbmigration/src/cli/groovy/org/apache/grails/data/hibernate7/dbmigration/cli/DbmRollbackCountSqlCommand.groovy
similarity index 94%
rename from grails-data-hibernate7/dbmigration/grails-app/commands/org/grails/plugins/databasemigration/command/DbmRollbackCountSqlCommand.groovy
rename to grails-data-hibernate7/dbmigration/src/cli/groovy/org/apache/grails/data/hibernate7/dbmigration/cli/DbmRollbackCountSqlCommand.groovy
index a9b0a2c313..357155d872 100644
--- a/grails-data-hibernate7/dbmigration/grails-app/commands/org/grails/plugins/databasemigration/command/DbmRollbackCountSqlCommand.groovy
+++ b/grails-data-hibernate7/dbmigration/src/cli/groovy/org/apache/grails/data/hibernate7/dbmigration/cli/DbmRollbackCountSqlCommand.groovy
@@ -16,13 +16,13 @@
  *  specific language governing permissions and limitations
  *  under the License.
  */
-package org.grails.plugins.databasemigration.command
+package org.apache.grails.data.hibernate7.dbmigration.cli
 
 import groovy.transform.CompileStatic
 
 import liquibase.Liquibase
 
-import grails.dev.commands.ApplicationCommand
+import org.apache.grails.core.cli.ApplicationCommand
 import org.grails.plugins.databasemigration.DatabaseMigrationException
 
 @CompileStatic
diff --git a/grails-data-hibernate5/dbmigration/grails-app/commands/org/grails/plugins/databasemigration/command/DbmRollbackSqlCommand.groovy b/grails-data-hibernate7/dbmigration/src/cli/groovy/org/apache/grails/data/hibernate7/dbmigration/cli/DbmRollbackSqlCommand.groovy
similarity index 93%
rename from grails-data-hibernate5/dbmigration/grails-app/commands/org/grails/plugins/databasemigration/command/DbmRollbackSqlCommand.groovy
rename to grails-data-hibernate7/dbmigration/src/cli/groovy/org/apache/grails/data/hibernate7/dbmigration/cli/DbmRollbackSqlCommand.groovy
index bea1a2c8bb..323467690d 100644
--- a/grails-data-hibernate5/dbmigration/grails-app/commands/org/grails/plugins/databasemigration/command/DbmRollbackSqlCommand.groovy
+++ b/grails-data-hibernate7/dbmigration/src/cli/groovy/org/apache/grails/data/hibernate7/dbmigration/cli/DbmRollbackSqlCommand.groovy
@@ -16,13 +16,13 @@
  *  specific language governing permissions and limitations
  *  under the License.
  */
-package org.grails.plugins.databasemigration.command
+package org.apache.grails.data.hibernate7.dbmigration.cli
 
 import groovy.transform.CompileStatic
 
 import liquibase.Liquibase
 
-import grails.dev.commands.ApplicationCommand
+import org.apache.grails.core.cli.ApplicationCommand
 import org.grails.plugins.databasemigration.DatabaseMigrationException
 
 @CompileStatic
diff --git a/grails-data-hibernate7/dbmigration/grails-app/commands/org/grails/plugins/databasemigration/command/DbmRollbackToDateCommand.groovy b/grails-data-hibernate7/dbmigration/src/cli/groovy/org/apache/grails/data/hibernate7/dbmigration/cli/DbmRollbackToDateCommand.groovy
similarity index 94%
rename from grails-data-hibernate7/dbmigration/grails-app/commands/org/grails/plugins/databasemigration/command/DbmRollbackToDateCommand.groovy
rename to grails-data-hibernate7/dbmigration/src/cli/groovy/org/apache/grails/data/hibernate7/dbmigration/cli/DbmRollbackToDateCommand.groovy
index 2b3701a8ef..997a08dd7e 100644
--- a/grails-data-hibernate7/dbmigration/grails-app/commands/org/grails/plugins/databasemigration/command/DbmRollbackToDateCommand.groovy
+++ b/grails-data-hibernate7/dbmigration/src/cli/groovy/org/apache/grails/data/hibernate7/dbmigration/cli/DbmRollbackToDateCommand.groovy
@@ -16,7 +16,7 @@
  *  specific language governing permissions and limitations
  *  under the License.
  */
-package org.grails.plugins.databasemigration.command
+package org.apache.grails.data.hibernate7.dbmigration.cli
 
 import java.text.ParseException
 
@@ -24,7 +24,7 @@ import groovy.transform.CompileStatic
 
 import liquibase.Liquibase
 
-import grails.dev.commands.ApplicationCommand
+import org.apache.grails.core.cli.ApplicationCommand
 import org.grails.plugins.databasemigration.DatabaseMigrationException
 
 @CompileStatic
diff --git a/grails-data-hibernate5/dbmigration/grails-app/commands/org/grails/plugins/databasemigration/command/DbmRollbackToDateSqlCommand.groovy b/grails-data-hibernate7/dbmigration/src/cli/groovy/org/apache/grails/data/hibernate7/dbmigration/cli/DbmRollbackToDateSqlCommand.groovy
similarity index 95%
rename from grails-data-hibernate5/dbmigration/grails-app/commands/org/grails/plugins/databasemigration/command/DbmRollbackToDateSqlCommand.groovy
rename to grails-data-hibernate7/dbmigration/src/cli/groovy/org/apache/grails/data/hibernate7/dbmigration/cli/DbmRollbackToDateSqlCommand.groovy
index c263063c92..2c7755b88b 100644
--- a/grails-data-hibernate5/dbmigration/grails-app/commands/org/grails/plugins/databasemigration/command/DbmRollbackToDateSqlCommand.groovy
+++ b/grails-data-hibernate7/dbmigration/src/cli/groovy/org/apache/grails/data/hibernate7/dbmigration/cli/DbmRollbackToDateSqlCommand.groovy
@@ -16,7 +16,7 @@
  *  specific language governing permissions and limitations
  *  under the License.
  */
-package org.grails.plugins.databasemigration.command
+package org.apache.grails.data.hibernate7.dbmigration.cli
 
 import java.text.ParseException
 
@@ -24,7 +24,7 @@ import groovy.transform.CompileStatic
 
 import liquibase.Liquibase
 
-import grails.dev.commands.ApplicationCommand
+import org.apache.grails.core.cli.ApplicationCommand
 import org.grails.plugins.databasemigration.DatabaseMigrationException
 
 @CompileStatic
diff --git a/grails-data-hibernate5/dbmigration/grails-app/commands/org/grails/plugins/databasemigration/command/DbmStatusCommand.groovy b/grails-data-hibernate7/dbmigration/src/cli/groovy/org/apache/grails/data/hibernate7/dbmigration/cli/DbmStatusCommand.groovy
similarity index 93%
rename from grails-data-hibernate5/dbmigration/grails-app/commands/org/grails/plugins/databasemigration/command/DbmStatusCommand.groovy
rename to grails-data-hibernate7/dbmigration/src/cli/groovy/org/apache/grails/data/hibernate7/dbmigration/cli/DbmStatusCommand.groovy
index 3465df19d6..a1eee83cc8 100644
--- a/grails-data-hibernate5/dbmigration/grails-app/commands/org/grails/plugins/databasemigration/command/DbmStatusCommand.groovy
+++ b/grails-data-hibernate7/dbmigration/src/cli/groovy/org/apache/grails/data/hibernate7/dbmigration/cli/DbmStatusCommand.groovy
@@ -16,13 +16,13 @@
  *  specific language governing permissions and limitations
  *  under the License.
  */
-package org.grails.plugins.databasemigration.command
+package org.apache.grails.data.hibernate7.dbmigration.cli
 
 import groovy.transform.CompileStatic
 
 import liquibase.Liquibase
 
-import grails.dev.commands.ApplicationCommand
+import org.apache.grails.core.cli.ApplicationCommand
 
 @CompileStatic
 class DbmStatusCommand implements ApplicationCommand, ApplicationContextDatabaseMigrationCommand {
diff --git a/grails-data-hibernate5/dbmigration/grails-app/commands/org/grails/plugins/databasemigration/command/DbmTagCommand.groovy b/grails-data-hibernate7/dbmigration/src/cli/groovy/org/apache/grails/data/hibernate7/dbmigration/cli/DbmTagCommand.groovy
similarity index 92%
rename from grails-data-hibernate5/dbmigration/grails-app/commands/org/grails/plugins/databasemigration/command/DbmTagCommand.groovy
rename to grails-data-hibernate7/dbmigration/src/cli/groovy/org/apache/grails/data/hibernate7/dbmigration/cli/DbmTagCommand.groovy
index ba5e30d591..fcbdd015b0 100644
--- a/grails-data-hibernate5/dbmigration/grails-app/commands/org/grails/plugins/databasemigration/command/DbmTagCommand.groovy
+++ b/grails-data-hibernate7/dbmigration/src/cli/groovy/org/apache/grails/data/hibernate7/dbmigration/cli/DbmTagCommand.groovy
@@ -16,13 +16,13 @@
  *  specific language governing permissions and limitations
  *  under the License.
  */
-package org.grails.plugins.databasemigration.command
+package org.apache.grails.data.hibernate7.dbmigration.cli
 
 import groovy.transform.CompileStatic
 
 import liquibase.Liquibase
 
-import grails.dev.commands.ApplicationCommand
+import org.apache.grails.core.cli.ApplicationCommand
 import org.grails.plugins.databasemigration.DatabaseMigrationException
 
 @CompileStatic
diff --git a/grails-data-hibernate7/dbmigration/grails-app/commands/org/grails/plugins/databasemigration/command/DbmUpdateCommand.groovy b/grails-data-hibernate7/dbmigration/src/cli/groovy/org/apache/grails/data/hibernate7/dbmigration/cli/DbmUpdateCommand.groovy
similarity index 91%
rename from grails-data-hibernate7/dbmigration/grails-app/commands/org/grails/plugins/databasemigration/command/DbmUpdateCommand.groovy
rename to grails-data-hibernate7/dbmigration/src/cli/groovy/org/apache/grails/data/hibernate7/dbmigration/cli/DbmUpdateCommand.groovy
index 2306b00c1d..83082f66c0 100644
--- a/grails-data-hibernate7/dbmigration/grails-app/commands/org/grails/plugins/databasemigration/command/DbmUpdateCommand.groovy
+++ b/grails-data-hibernate7/dbmigration/src/cli/groovy/org/apache/grails/data/hibernate7/dbmigration/cli/DbmUpdateCommand.groovy
@@ -16,13 +16,13 @@
  *  specific language governing permissions and limitations
  *  under the License.
  */
-package org.grails.plugins.databasemigration.command
+package org.apache.grails.data.hibernate7.dbmigration.cli
 
 import groovy.transform.CompileStatic
 
 import liquibase.Liquibase
 
-import grails.dev.commands.ApplicationCommand
+import org.apache.grails.core.cli.ApplicationCommand
 
 @CompileStatic
 class DbmUpdateCommand implements ApplicationCommand, ApplicationContextDatabaseMigrationCommand {
diff --git a/grails-data-hibernate7/dbmigration/grails-app/commands/org/grails/plugins/databasemigration/command/DbmUpdateCountCommand.groovy b/grails-data-hibernate7/dbmigration/src/cli/groovy/org/apache/grails/data/hibernate7/dbmigration/cli/DbmUpdateCountCommand.groovy
similarity index 93%
rename from grails-data-hibernate7/dbmigration/grails-app/commands/org/grails/plugins/databasemigration/command/DbmUpdateCountCommand.groovy
rename to grails-data-hibernate7/dbmigration/src/cli/groovy/org/apache/grails/data/hibernate7/dbmigration/cli/DbmUpdateCountCommand.groovy
index 663c73dfc1..c2d2d5c495 100644
--- a/grails-data-hibernate7/dbmigration/grails-app/commands/org/grails/plugins/databasemigration/command/DbmUpdateCountCommand.groovy
+++ b/grails-data-hibernate7/dbmigration/src/cli/groovy/org/apache/grails/data/hibernate7/dbmigration/cli/DbmUpdateCountCommand.groovy
@@ -16,13 +16,13 @@
  *  specific language governing permissions and limitations
  *  under the License.
  */
-package org.grails.plugins.databasemigration.command
+package org.apache.grails.data.hibernate7.dbmigration.cli
 
 import groovy.transform.CompileStatic
 
 import liquibase.Liquibase
 
-import grails.dev.commands.ApplicationCommand
+import org.apache.grails.core.cli.ApplicationCommand
 import org.grails.plugins.databasemigration.DatabaseMigrationException
 
 @CompileStatic
diff --git a/grails-data-hibernate7/dbmigration/grails-app/commands/org/grails/plugins/databasemigration/command/DbmUpdateCountSqlCommand.groovy b/grails-data-hibernate7/dbmigration/src/cli/groovy/org/apache/grails/data/hibernate7/dbmigration/cli/DbmUpdateCountSqlCommand.groovy
similarity index 94%
rename from grails-data-hibernate7/dbmigration/grails-app/commands/org/grails/plugins/databasemigration/command/DbmUpdateCountSqlCommand.groovy
rename to grails-data-hibernate7/dbmigration/src/cli/groovy/org/apache/grails/data/hibernate7/dbmigration/cli/DbmUpdateCountSqlCommand.groovy
index be681a37b8..634b95987e 100644
--- a/grails-data-hibernate7/dbmigration/grails-app/commands/org/grails/plugins/databasemigration/command/DbmUpdateCountSqlCommand.groovy
+++ b/grails-data-hibernate7/dbmigration/src/cli/groovy/org/apache/grails/data/hibernate7/dbmigration/cli/DbmUpdateCountSqlCommand.groovy
@@ -16,13 +16,13 @@
  *  specific language governing permissions and limitations
  *  under the License.
  */
-package org.grails.plugins.databasemigration.command
+package org.apache.grails.data.hibernate7.dbmigration.cli
 
 import groovy.transform.CompileStatic
 
 import liquibase.Liquibase
 
-import grails.dev.commands.ApplicationCommand
+import org.apache.grails.core.cli.ApplicationCommand
 import org.grails.plugins.databasemigration.DatabaseMigrationException
 
 @CompileStatic
diff --git a/grails-data-hibernate5/dbmigration/grails-app/commands/org/grails/plugins/databasemigration/command/DbmUpdateSqlCommand.groovy b/grails-data-hibernate7/dbmigration/src/cli/groovy/org/apache/grails/data/hibernate7/dbmigration/cli/DbmUpdateSqlCommand.groovy
similarity index 92%
rename from grails-data-hibernate5/dbmigration/grails-app/commands/org/grails/plugins/databasemigration/command/DbmUpdateSqlCommand.groovy
rename to grails-data-hibernate7/dbmigration/src/cli/groovy/org/apache/grails/data/hibernate7/dbmigration/cli/DbmUpdateSqlCommand.groovy
index a58602ef5b..e633715e73 100644
--- a/grails-data-hibernate5/dbmigration/grails-app/commands/org/grails/plugins/databasemigration/command/DbmUpdateSqlCommand.groovy
+++ b/grails-data-hibernate7/dbmigration/src/cli/groovy/org/apache/grails/data/hibernate7/dbmigration/cli/DbmUpdateSqlCommand.groovy
@@ -16,13 +16,13 @@
  *  specific language governing permissions and limitations
  *  under the License.
  */
-package org.grails.plugins.databasemigration.command
+package org.apache.grails.data.hibernate7.dbmigration.cli
 
 import groovy.transform.CompileStatic
 
 import liquibase.Liquibase
 
-import grails.dev.commands.ApplicationCommand
+import org.apache.grails.core.cli.ApplicationCommand
 
 @CompileStatic
 class DbmUpdateSqlCommand implements ApplicationCommand, ApplicationContextDatabaseMigrationCommand {
diff --git a/grails-data-hibernate5/dbmigration/grails-app/commands/org/grails/plugins/databasemigration/command/DbmValidateCommand.groovy b/grails-data-hibernate7/dbmigration/src/cli/groovy/org/apache/grails/data/hibernate7/dbmigration/cli/DbmValidateCommand.groovy
similarity index 91%
rename from grails-data-hibernate5/dbmigration/grails-app/commands/org/grails/plugins/databasemigration/command/DbmValidateCommand.groovy
rename to grails-data-hibernate7/dbmigration/src/cli/groovy/org/apache/grails/data/hibernate7/dbmigration/cli/DbmValidateCommand.groovy
index d62c81b558..3897414626 100644
--- a/grails-data-hibernate5/dbmigration/grails-app/commands/org/grails/plugins/databasemigration/command/DbmValidateCommand.groovy
+++ b/grails-data-hibernate7/dbmigration/src/cli/groovy/org/apache/grails/data/hibernate7/dbmigration/cli/DbmValidateCommand.groovy
@@ -16,13 +16,13 @@
  *  specific language governing permissions and limitations
  *  under the License.
  */
-package org.grails.plugins.databasemigration.command
+package org.apache.grails.data.hibernate7.dbmigration.cli
 
 import groovy.transform.CompileStatic
 
 import liquibase.Liquibase
 
-import grails.dev.commands.ApplicationCommand
+import org.apache.grails.core.cli.ApplicationCommand
 
 @CompileStatic
 class DbmValidateCommand implements ApplicationCommand, ApplicationContextDatabaseMigrationCommand {
diff --git a/grails-data-hibernate7/dbmigration/src/main/groovy/org/grails/plugins/databasemigration/command/ScriptDatabaseMigrationCommand.groovy b/grails-data-hibernate7/dbmigration/src/cli/groovy/org/apache/grails/data/hibernate7/dbmigration/cli/ScriptDatabaseMigrationCommand.groovy
similarity index 97%
rename from grails-data-hibernate7/dbmigration/src/main/groovy/org/grails/plugins/databasemigration/command/ScriptDatabaseMigrationCommand.groovy
rename to grails-data-hibernate7/dbmigration/src/cli/groovy/org/apache/grails/data/hibernate7/dbmigration/cli/ScriptDatabaseMigrationCommand.groovy
index 0be43b3e95..a53d40afcd 100644
--- a/grails-data-hibernate7/dbmigration/src/main/groovy/org/grails/plugins/databasemigration/command/ScriptDatabaseMigrationCommand.groovy
+++ b/grails-data-hibernate7/dbmigration/src/cli/groovy/org/apache/grails/data/hibernate7/dbmigration/cli/ScriptDatabaseMigrationCommand.groovy
@@ -16,7 +16,7 @@
  *  specific language governing permissions and limitations
  *  under the License.
  */
-package org.grails.plugins.databasemigration.command
+package org.apache.grails.data.hibernate7.dbmigration.cli
 
 import groovy.transform.CompileStatic
 
diff --git a/grails-data-hibernate7/dbmigration/src/main/scripts/dbm-changelog-to-groovy.groovy b/grails-data-hibernate7/dbmigration/src/cli/resources/META-INF/commands/dbm-changelog-to-groovy.groovy
similarity index 95%
rename from grails-data-hibernate7/dbmigration/src/main/scripts/dbm-changelog-to-groovy.groovy
rename to grails-data-hibernate7/dbmigration/src/cli/resources/META-INF/commands/dbm-changelog-to-groovy.groovy
index 44bd0a7082..31bb85b1af 100644
--- a/grails-data-hibernate7/dbmigration/src/main/scripts/dbm-changelog-to-groovy.groovy
+++ b/grails-data-hibernate7/dbmigration/src/cli/resources/META-INF/commands/dbm-changelog-to-groovy.groovy
@@ -18,7 +18,7 @@
  */
 
 import org.grails.plugins.databasemigration.DatabaseMigrationException
-import org.grails.plugins.databasemigration.command.DbmChangelogToGroovy
+import org.apache.grails.data.hibernate7.dbmigration.cli.DbmChangelogToGroovy
 
 description('Converts a changelog file to a Groovy DSL file') {
     usage 'grails [environment] dbm-changelog-to-groovy [src_file_name] [dest_file_name]'
diff --git a/grails-data-hibernate7/dbmigration/src/main/scripts/dbm-create-changelog.groovy b/grails-data-hibernate7/dbmigration/src/cli/resources/META-INF/commands/dbm-create-changelog.groovy
similarity index 95%
rename from grails-data-hibernate7/dbmigration/src/main/scripts/dbm-create-changelog.groovy
rename to grails-data-hibernate7/dbmigration/src/cli/resources/META-INF/commands/dbm-create-changelog.groovy
index accff252db..14ae986d72 100644
--- a/grails-data-hibernate7/dbmigration/src/main/scripts/dbm-create-changelog.groovy
+++ b/grails-data-hibernate7/dbmigration/src/cli/resources/META-INF/commands/dbm-create-changelog.groovy
@@ -18,7 +18,7 @@
  */
 
 import org.grails.plugins.databasemigration.DatabaseMigrationException
-import org.grails.plugins.databasemigration.command.DbmCreateChangelog
+import org.apache.grails.data.hibernate7.dbmigration.cli.DbmCreateChangelog
 
 description('Creates an empty changelog file') {
     usage 'grails [environment] dbm-create-changelog [filename]'
diff --git a/grails-data-hibernate7/dbmigration/src/integration-test/groovy/org/grails/plugins/databasemigration/DbUpdateCommandSpec.groovy b/grails-data-hibernate7/dbmigration/src/integration-test/groovy/org/grails/plugins/databasemigration/DbUpdateCommandSpec.groovy
index 466e124794..f82367278e 100644
--- a/grails-data-hibernate7/dbmigration/src/integration-test/groovy/org/grails/plugins/databasemigration/DbUpdateCommandSpec.groovy
+++ b/grails-data-hibernate7/dbmigration/src/integration-test/groovy/org/grails/plugins/databasemigration/DbUpdateCommandSpec.groovy
@@ -19,8 +19,8 @@
 
 package org.grails.plugins.databasemigration
 
-import grails.dev.commands.ApplicationCommand
-import grails.dev.commands.ExecutionContext
+import org.apache.grails.core.cli.ApplicationCommand
+import org.apache.grails.core.cli.ExecutionContext
 import grails.testing.mixin.integration.Integration
 import grails.util.GrailsNameUtils
 import groovy.sql.Sql
@@ -28,7 +28,7 @@ import liquibase.GlobalConfiguration
 import liquibase.Scope
 import liquibase.exception.LiquibaseException
 import org.grails.build.parsing.CommandLineParser
-import org.grails.plugins.databasemigration.command.DbmUpdateCommand
+import org.apache.grails.data.hibernate7.dbmigration.cli.DbmUpdateCommand
 import org.springframework.beans.factory.annotation.Autowired
 import org.springframework.context.ApplicationContext
 import org.springframework.stereotype.Component
diff --git a/grails-data-hibernate7/dbmigration/src/test/groovy/org/grails/plugins/databasemigration/command/ApplicationContextDatabaseMigrationCommandSpec.groovy b/grails-data-hibernate7/dbmigration/src/test/groovy/org/apache/grails/data/hibernate7/dbmigration/cli/ApplicationContextDatabaseMigrationCommandSpec.groovy
similarity index 96%
rename from grails-data-hibernate7/dbmigration/src/test/groovy/org/grails/plugins/databasemigration/command/ApplicationContextDatabaseMigrationCommandSpec.groovy
rename to grails-data-hibernate7/dbmigration/src/test/groovy/org/apache/grails/data/hibernate7/dbmigration/cli/ApplicationContextDatabaseMigrationCommandSpec.groovy
index 5c46ae72bf..f8e2755e78 100644
--- a/grails-data-hibernate7/dbmigration/src/test/groovy/org/grails/plugins/databasemigration/command/ApplicationContextDatabaseMigrationCommandSpec.groovy
+++ b/grails-data-hibernate7/dbmigration/src/test/groovy/org/apache/grails/data/hibernate7/dbmigration/cli/ApplicationContextDatabaseMigrationCommandSpec.groovy
@@ -17,14 +17,14 @@
  *  under the License.
  */
 
-package org.grails.plugins.databasemigration.command
+package org.apache.grails.data.hibernate7.dbmigration.cli
 
 import grails.config.Config
 import grails.core.DefaultGrailsApplication
 import grails.core.GrailsApplication
 import grails.core.support.GrailsApplicationAware
-import grails.dev.commands.ApplicationCommand
-import grails.dev.commands.ExecutionContext
+import org.apache.grails.core.cli.ApplicationCommand
+import org.apache.grails.core.cli.ExecutionContext
 import grails.orm.bootstrap.HibernateDatastoreSpringInitializer
 import grails.persistence.Entity
 import grails.util.GrailsNameUtils
diff --git a/grails-data-hibernate5/dbmigration/src/test/groovy/org/grails/plugins/databasemigration/command/DatabaseMigrationCommandConfigSpec.groovy b/grails-data-hibernate7/dbmigration/src/test/groovy/org/apache/grails/data/hibernate7/dbmigration/cli/DatabaseMigrationCommandConfigSpec.groovy
similarity index 98%
rename from grails-data-hibernate5/dbmigration/src/test/groovy/org/grails/plugins/databasemigration/command/DatabaseMigrationCommandConfigSpec.groovy
rename to grails-data-hibernate7/dbmigration/src/test/groovy/org/apache/grails/data/hibernate7/dbmigration/cli/DatabaseMigrationCommandConfigSpec.groovy
index 5a0f6baa5d..5b269226de 100644
--- a/grails-data-hibernate5/dbmigration/src/test/groovy/org/grails/plugins/databasemigration/command/DatabaseMigrationCommandConfigSpec.groovy
+++ b/grails-data-hibernate7/dbmigration/src/test/groovy/org/apache/grails/data/hibernate7/dbmigration/cli/DatabaseMigrationCommandConfigSpec.groovy
@@ -16,7 +16,7 @@
  *  specific language governing permissions and limitations
  *  under the License.
  */
-package org.grails.plugins.databasemigration.command
+package org.apache.grails.data.hibernate7.dbmigration.cli
 
 import org.h2.Driver
 import spock.lang.Specification
diff --git a/grails-data-hibernate7/dbmigration/src/test/groovy/org/grails/plugins/databasemigration/command/DatabaseMigrationCommandSpec.groovy b/grails-data-hibernate7/dbmigration/src/test/groovy/org/apache/grails/data/hibernate7/dbmigration/cli/DatabaseMigrationCommandSpec.groovy
similarity index 97%
rename from grails-data-hibernate7/dbmigration/src/test/groovy/org/grails/plugins/databasemigration/command/DatabaseMigrationCommandSpec.groovy
rename to grails-data-hibernate7/dbmigration/src/test/groovy/org/apache/grails/data/hibernate7/dbmigration/cli/DatabaseMigrationCommandSpec.groovy
index f3b0e78139..59abe629a3 100644
--- a/grails-data-hibernate7/dbmigration/src/test/groovy/org/grails/plugins/databasemigration/command/DatabaseMigrationCommandSpec.groovy
+++ b/grails-data-hibernate7/dbmigration/src/test/groovy/org/apache/grails/data/hibernate7/dbmigration/cli/DatabaseMigrationCommandSpec.groovy
@@ -16,7 +16,7 @@
  *  specific language governing permissions and limitations
  *  under the License.
  */
-package org.grails.plugins.databasemigration.command
+package org.apache.grails.data.hibernate7.dbmigration.cli
 
 import groovy.sql.Sql
 import org.grails.plugins.databasemigration.testing.annotation.OutputCapture
diff --git a/grails-data-hibernate5/dbmigration/src/test/groovy/org/grails/plugins/databasemigration/command/DbmChangelogSyncCommandSpec.groovy b/grails-data-hibernate7/dbmigration/src/test/groovy/org/apache/grails/data/hibernate7/dbmigration/cli/DbmChangelogSyncCommandSpec.groovy
similarity index 93%
rename from grails-data-hibernate5/dbmigration/src/test/groovy/org/grails/plugins/databasemigration/command/DbmChangelogSyncCommandSpec.groovy
rename to grails-data-hibernate7/dbmigration/src/test/groovy/org/apache/grails/data/hibernate7/dbmigration/cli/DbmChangelogSyncCommandSpec.groovy
index 524e8b2503..bfe950ff9d 100644
--- a/grails-data-hibernate5/dbmigration/src/test/groovy/org/grails/plugins/databasemigration/command/DbmChangelogSyncCommandSpec.groovy
+++ b/grails-data-hibernate7/dbmigration/src/test/groovy/org/apache/grails/data/hibernate7/dbmigration/cli/DbmChangelogSyncCommandSpec.groovy
@@ -16,9 +16,9 @@
  *  specific language governing permissions and limitations
  *  under the License.
  */
-package org.grails.plugins.databasemigration.command
+package org.apache.grails.data.hibernate7.dbmigration.cli
 
-import grails.dev.commands.ApplicationCommand
+import org.apache.grails.core.cli.ApplicationCommand
 
 class DbmChangelogSyncCommandSpec extends ApplicationContextDatabaseMigrationCommandSpec {
 
diff --git a/grails-data-hibernate5/dbmigration/src/test/groovy/org/grails/plugins/databasemigration/command/DbmChangelogSyncCommandSqlSpec.groovy b/grails-data-hibernate7/dbmigration/src/test/groovy/org/apache/grails/data/hibernate7/dbmigration/cli/DbmChangelogSyncCommandSqlSpec.groovy
similarity index 95%
rename from grails-data-hibernate5/dbmigration/src/test/groovy/org/grails/plugins/databasemigration/command/DbmChangelogSyncCommandSqlSpec.groovy
rename to grails-data-hibernate7/dbmigration/src/test/groovy/org/apache/grails/data/hibernate7/dbmigration/cli/DbmChangelogSyncCommandSqlSpec.groovy
index 2db88a8ff5..2a32f73ca2 100644
--- a/grails-data-hibernate5/dbmigration/src/test/groovy/org/grails/plugins/databasemigration/command/DbmChangelogSyncCommandSqlSpec.groovy
+++ b/grails-data-hibernate7/dbmigration/src/test/groovy/org/apache/grails/data/hibernate7/dbmigration/cli/DbmChangelogSyncCommandSqlSpec.groovy
@@ -16,9 +16,9 @@
  *  specific language governing permissions and limitations
  *  under the License.
  */
-package org.grails.plugins.databasemigration.command
+package org.apache.grails.data.hibernate7.dbmigration.cli
 
-import grails.dev.commands.ApplicationCommand
+import org.apache.grails.core.cli.ApplicationCommand
 import spock.lang.AutoCleanup
 
 class DbmChangelogSyncCommandSqlSpec extends ApplicationContextDatabaseMigrationCommandSpec {
diff --git a/grails-data-hibernate5/dbmigration/src/test/groovy/org/grails/plugins/databasemigration/command/DbmClearChecksumsCommandSpec.groovy b/grails-data-hibernate7/dbmigration/src/test/groovy/org/apache/grails/data/hibernate7/dbmigration/cli/DbmClearChecksumsCommandSpec.groovy
similarity index 95%
rename from grails-data-hibernate5/dbmigration/src/test/groovy/org/grails/plugins/databasemigration/command/DbmClearChecksumsCommandSpec.groovy
rename to grails-data-hibernate7/dbmigration/src/test/groovy/org/apache/grails/data/hibernate7/dbmigration/cli/DbmClearChecksumsCommandSpec.groovy
index a4e6d04ed8..6ff545e31b 100644
--- a/grails-data-hibernate5/dbmigration/src/test/groovy/org/grails/plugins/databasemigration/command/DbmClearChecksumsCommandSpec.groovy
+++ b/grails-data-hibernate7/dbmigration/src/test/groovy/org/apache/grails/data/hibernate7/dbmigration/cli/DbmClearChecksumsCommandSpec.groovy
@@ -16,9 +16,9 @@
  *  specific language governing permissions and limitations
  *  under the License.
  */
-package org.grails.plugins.databasemigration.command
+package org.apache.grails.data.hibernate7.dbmigration.cli
 
-import grails.dev.commands.ApplicationCommand
+import org.apache.grails.core.cli.ApplicationCommand
 
 class DbmClearChecksumsCommandSpec extends ApplicationContextDatabaseMigrationCommandSpec {
 
diff --git a/grails-data-hibernate7/dbmigration/src/test/groovy/org/grails/plugins/databasemigration/command/DbmDiffCommandSpec.groovy b/grails-data-hibernate7/dbmigration/src/test/groovy/org/apache/grails/data/hibernate7/dbmigration/cli/DbmDiffCommandSpec.groovy
similarity index 97%
rename from grails-data-hibernate7/dbmigration/src/test/groovy/org/grails/plugins/databasemigration/command/DbmDiffCommandSpec.groovy
rename to grails-data-hibernate7/dbmigration/src/test/groovy/org/apache/grails/data/hibernate7/dbmigration/cli/DbmDiffCommandSpec.groovy
index 48e4604980..de69572345 100644
--- a/grails-data-hibernate7/dbmigration/src/test/groovy/org/grails/plugins/databasemigration/command/DbmDiffCommandSpec.groovy
+++ b/grails-data-hibernate7/dbmigration/src/test/groovy/org/apache/grails/data/hibernate7/dbmigration/cli/DbmDiffCommandSpec.groovy
@@ -16,9 +16,9 @@
  *  specific language governing permissions and limitations
  *  under the License.
  */
-package org.grails.plugins.databasemigration.command
+package org.apache.grails.data.hibernate7.dbmigration.cli
 
-import grails.dev.commands.ApplicationCommand
+import org.apache.grails.core.cli.ApplicationCommand
 import groovy.sql.Sql
 import org.grails.plugins.databasemigration.DatabaseMigrationException
 import org.h2.Driver
diff --git a/grails-data-hibernate7/dbmigration/src/test/groovy/org/grails/plugins/databasemigration/command/DbmDropAllCommandSpec.groovy b/grails-data-hibernate7/dbmigration/src/test/groovy/org/apache/grails/data/hibernate7/dbmigration/cli/DbmDropAllCommandSpec.groovy
similarity index 93%
rename from grails-data-hibernate7/dbmigration/src/test/groovy/org/grails/plugins/databasemigration/command/DbmDropAllCommandSpec.groovy
rename to grails-data-hibernate7/dbmigration/src/test/groovy/org/apache/grails/data/hibernate7/dbmigration/cli/DbmDropAllCommandSpec.groovy
index 7583c4739f..477dfe3053 100644
--- a/grails-data-hibernate7/dbmigration/src/test/groovy/org/grails/plugins/databasemigration/command/DbmDropAllCommandSpec.groovy
+++ b/grails-data-hibernate7/dbmigration/src/test/groovy/org/apache/grails/data/hibernate7/dbmigration/cli/DbmDropAllCommandSpec.groovy
@@ -16,9 +16,9 @@
  *  specific language governing permissions and limitations
  *  under the License.
  */
-package org.grails.plugins.databasemigration.command
+package org.apache.grails.data.hibernate7.dbmigration.cli
 
-import grails.dev.commands.ApplicationCommand
+import org.apache.grails.core.cli.ApplicationCommand
 
 class DbmDropAllCommandSpec extends ApplicationContextDatabaseMigrationCommandSpec {
 
diff --git a/grails-data-hibernate7/dbmigration/src/test/groovy/org/grails/plugins/databasemigration/command/DbmFutureRollbackCountSqlCommandSpec.groovy b/grails-data-hibernate7/dbmigration/src/test/groovy/org/apache/grails/data/hibernate7/dbmigration/cli/DbmFutureRollbackCountSqlCommandSpec.groovy
similarity index 97%
rename from grails-data-hibernate7/dbmigration/src/test/groovy/org/grails/plugins/databasemigration/command/DbmFutureRollbackCountSqlCommandSpec.groovy
rename to grails-data-hibernate7/dbmigration/src/test/groovy/org/apache/grails/data/hibernate7/dbmigration/cli/DbmFutureRollbackCountSqlCommandSpec.groovy
index 9ec47790f3..09d5ad0c79 100644
--- a/grails-data-hibernate7/dbmigration/src/test/groovy/org/grails/plugins/databasemigration/command/DbmFutureRollbackCountSqlCommandSpec.groovy
+++ b/grails-data-hibernate7/dbmigration/src/test/groovy/org/apache/grails/data/hibernate7/dbmigration/cli/DbmFutureRollbackCountSqlCommandSpec.groovy
@@ -16,9 +16,9 @@
  *  specific language governing permissions and limitations
  *  under the License.
  */
-package org.grails.plugins.databasemigration.command
+package org.apache.grails.data.hibernate7.dbmigration.cli
 
-import grails.dev.commands.ApplicationCommand
+import org.apache.grails.core.cli.ApplicationCommand
 import org.grails.plugins.databasemigration.DatabaseMigrationException
 import spock.lang.AutoCleanup
 
diff --git a/grails-data-hibernate5/dbmigration/src/test/groovy/org/grails/plugins/databasemigration/command/DbmFutureRollbackSqlCommandSpec.groovy b/grails-data-hibernate7/dbmigration/src/test/groovy/org/apache/grails/data/hibernate7/dbmigration/cli/DbmFutureRollbackSqlCommandSpec.groovy
similarity index 97%
rename from grails-data-hibernate5/dbmigration/src/test/groovy/org/grails/plugins/databasemigration/command/DbmFutureRollbackSqlCommandSpec.groovy
rename to grails-data-hibernate7/dbmigration/src/test/groovy/org/apache/grails/data/hibernate7/dbmigration/cli/DbmFutureRollbackSqlCommandSpec.groovy
index 7e4203b77e..dc68a06637 100644
--- a/grails-data-hibernate5/dbmigration/src/test/groovy/org/grails/plugins/databasemigration/command/DbmFutureRollbackSqlCommandSpec.groovy
+++ b/grails-data-hibernate7/dbmigration/src/test/groovy/org/apache/grails/data/hibernate7/dbmigration/cli/DbmFutureRollbackSqlCommandSpec.groovy
@@ -16,9 +16,9 @@
  *  specific language governing permissions and limitations
  *  under the License.
  */
-package org.grails.plugins.databasemigration.command
+package org.apache.grails.data.hibernate7.dbmigration.cli
 
-import grails.dev.commands.ApplicationCommand
+import org.apache.grails.core.cli.ApplicationCommand
 import spock.lang.AutoCleanup
 
 class DbmFutureRollbackSqlCommandSpec extends ApplicationContextDatabaseMigrationCommandSpec {
diff --git a/grails-data-hibernate7/dbmigration/src/test/groovy/org/grails/plugins/databasemigration/command/DbmGenerateChangelogCommandSpec.groovy b/grails-data-hibernate7/dbmigration/src/test/groovy/org/apache/grails/data/hibernate7/dbmigration/cli/DbmGenerateChangelogCommandSpec.groovy
similarity index 97%
rename from grails-data-hibernate7/dbmigration/src/test/groovy/org/grails/plugins/databasemigration/command/DbmGenerateChangelogCommandSpec.groovy
rename to grails-data-hibernate7/dbmigration/src/test/groovy/org/apache/grails/data/hibernate7/dbmigration/cli/DbmGenerateChangelogCommandSpec.groovy
index 6928f111c4..9b8059c30e 100644
--- a/grails-data-hibernate7/dbmigration/src/test/groovy/org/grails/plugins/databasemigration/command/DbmGenerateChangelogCommandSpec.groovy
+++ b/grails-data-hibernate7/dbmigration/src/test/groovy/org/apache/grails/data/hibernate7/dbmigration/cli/DbmGenerateChangelogCommandSpec.groovy
@@ -16,9 +16,9 @@
  *  specific language governing permissions and limitations
  *  under the License.
  */
-package org.grails.plugins.databasemigration.command
+package org.apache.grails.data.hibernate7.dbmigration.cli
 
-import grails.dev.commands.ApplicationCommand
+import org.apache.grails.core.cli.ApplicationCommand
 
 class DbmGenerateChangelogCommandSpec extends ApplicationContextDatabaseMigrationCommandSpec {
 
diff --git a/grails-data-hibernate7/dbmigration/src/test/groovy/org/grails/plugins/databasemigration/command/DbmGenerateGormChangelogCommandSpec.groovy b/grails-data-hibernate7/dbmigration/src/test/groovy/org/apache/grails/data/hibernate7/dbmigration/cli/DbmGenerateGormChangelogCommandSpec.groovy
similarity index 98%
rename from grails-data-hibernate7/dbmigration/src/test/groovy/org/grails/plugins/databasemigration/command/DbmGenerateGormChangelogCommandSpec.groovy
rename to grails-data-hibernate7/dbmigration/src/test/groovy/org/apache/grails/data/hibernate7/dbmigration/cli/DbmGenerateGormChangelogCommandSpec.groovy
index 34124ea6eb..8ef523c163 100644
--- a/grails-data-hibernate7/dbmigration/src/test/groovy/org/grails/plugins/databasemigration/command/DbmGenerateGormChangelogCommandSpec.groovy
+++ b/grails-data-hibernate7/dbmigration/src/test/groovy/org/apache/grails/data/hibernate7/dbmigration/cli/DbmGenerateGormChangelogCommandSpec.groovy
@@ -16,9 +16,9 @@
  *  specific language governing permissions and limitations
  *  under the License.
  */
-package org.grails.plugins.databasemigration.command
+package org.apache.grails.data.hibernate7.dbmigration.cli
 
-import grails.dev.commands.ApplicationCommand
+import org.apache.grails.core.cli.ApplicationCommand
 import org.grails.plugins.databasemigration.DatabaseMigrationException
 
 class DbmGenerateGormChangelogCommandSpec extends ApplicationContextDatabaseMigrationCommandSpec {
diff --git a/grails-data-hibernate7/dbmigration/src/test/groovy/org/grails/plugins/databasemigration/command/DbmGormDiffCommandSpec.groovy b/grails-data-hibernate7/dbmigration/src/test/groovy/org/apache/grails/data/hibernate7/dbmigration/cli/DbmGormDiffCommandSpec.groovy
similarity index 97%
rename from grails-data-hibernate7/dbmigration/src/test/groovy/org/grails/plugins/databasemigration/command/DbmGormDiffCommandSpec.groovy
rename to grails-data-hibernate7/dbmigration/src/test/groovy/org/apache/grails/data/hibernate7/dbmigration/cli/DbmGormDiffCommandSpec.groovy
index c5354bbc2f..801e6d5c35 100644
--- a/grails-data-hibernate7/dbmigration/src/test/groovy/org/grails/plugins/databasemigration/command/DbmGormDiffCommandSpec.groovy
+++ b/grails-data-hibernate7/dbmigration/src/test/groovy/org/apache/grails/data/hibernate7/dbmigration/cli/DbmGormDiffCommandSpec.groovy
@@ -16,9 +16,9 @@
  *  specific language governing permissions and limitations
  *  under the License.
  */
-package org.grails.plugins.databasemigration.command
+package org.apache.grails.data.hibernate7.dbmigration.cli
 
-import grails.dev.commands.ApplicationCommand
+import org.apache.grails.core.cli.ApplicationCommand
 import org.grails.plugins.databasemigration.DatabaseMigrationException
 
 class DbmGormDiffCommandSpec extends ApplicationContextDatabaseMigrationCommandSpec {
diff --git a/grails-data-hibernate7/dbmigration/src/test/groovy/org/grails/plugins/databasemigration/command/DbmListLocksCommandSpec.groovy b/grails-data-hibernate7/dbmigration/src/test/groovy/org/apache/grails/data/hibernate7/dbmigration/cli/DbmListLocksCommandSpec.groovy
similarity index 95%
rename from grails-data-hibernate7/dbmigration/src/test/groovy/org/grails/plugins/databasemigration/command/DbmListLocksCommandSpec.groovy
rename to grails-data-hibernate7/dbmigration/src/test/groovy/org/apache/grails/data/hibernate7/dbmigration/cli/DbmListLocksCommandSpec.groovy
index a58fc104c5..56044c417b 100644
--- a/grails-data-hibernate7/dbmigration/src/test/groovy/org/grails/plugins/databasemigration/command/DbmListLocksCommandSpec.groovy
+++ b/grails-data-hibernate7/dbmigration/src/test/groovy/org/apache/grails/data/hibernate7/dbmigration/cli/DbmListLocksCommandSpec.groovy
@@ -16,9 +16,9 @@
  *  specific language governing permissions and limitations
  *  under the License.
  */
-package org.grails.plugins.databasemigration.command
+package org.apache.grails.data.hibernate7.dbmigration.cli
 
-import grails.dev.commands.ApplicationCommand
+import org.apache.grails.core.cli.ApplicationCommand
 import spock.lang.AutoCleanup
 
 class DbmListLocksCommandSpec extends ApplicationContextDatabaseMigrationCommandSpec {
diff --git a/grails-data-hibernate5/dbmigration/src/test/groovy/org/grails/plugins/databasemigration/command/DbmMarkNextChangesetRanCommandSpec.groovy b/grails-data-hibernate7/dbmigration/src/test/groovy/org/apache/grails/data/hibernate7/dbmigration/cli/DbmMarkNextChangesetRanCommandSpec.groovy
similarity index 93%
rename from grails-data-hibernate5/dbmigration/src/test/groovy/org/grails/plugins/databasemigration/command/DbmMarkNextChangesetRanCommandSpec.groovy
rename to grails-data-hibernate7/dbmigration/src/test/groovy/org/apache/grails/data/hibernate7/dbmigration/cli/DbmMarkNextChangesetRanCommandSpec.groovy
index 717fce94d3..c8d0f9189c 100644
--- a/grails-data-hibernate5/dbmigration/src/test/groovy/org/grails/plugins/databasemigration/command/DbmMarkNextChangesetRanCommandSpec.groovy
+++ b/grails-data-hibernate7/dbmigration/src/test/groovy/org/apache/grails/data/hibernate7/dbmigration/cli/DbmMarkNextChangesetRanCommandSpec.groovy
@@ -16,9 +16,9 @@
  *  specific language governing permissions and limitations
  *  under the License.
  */
-package org.grails.plugins.databasemigration.command
+package org.apache.grails.data.hibernate7.dbmigration.cli
 
-import grails.dev.commands.ApplicationCommand
+import org.apache.grails.core.cli.ApplicationCommand
 
 class DbmMarkNextChangesetRanCommandSpec extends ApplicationContextDatabaseMigrationCommandSpec {
 
diff --git a/grails-data-hibernate5/dbmigration/src/test/groovy/org/grails/plugins/databasemigration/command/DbmMarkNextChangesetRanSqlCommandSpec.groovy b/grails-data-hibernate7/dbmigration/src/test/groovy/org/apache/grails/data/hibernate7/dbmigration/cli/DbmMarkNextChangesetRanSqlCommandSpec.groovy
similarity index 95%
rename from grails-data-hibernate5/dbmigration/src/test/groovy/org/grails/plugins/databasemigration/command/DbmMarkNextChangesetRanSqlCommandSpec.groovy
rename to grails-data-hibernate7/dbmigration/src/test/groovy/org/apache/grails/data/hibernate7/dbmigration/cli/DbmMarkNextChangesetRanSqlCommandSpec.groovy
index 9056fcb969..ea9ce53dbd 100644
--- a/grails-data-hibernate5/dbmigration/src/test/groovy/org/grails/plugins/databasemigration/command/DbmMarkNextChangesetRanSqlCommandSpec.groovy
+++ b/grails-data-hibernate7/dbmigration/src/test/groovy/org/apache/grails/data/hibernate7/dbmigration/cli/DbmMarkNextChangesetRanSqlCommandSpec.groovy
@@ -16,9 +16,9 @@
  *  specific language governing permissions and limitations
  *  under the License.
  */
-package org.grails.plugins.databasemigration.command
+package org.apache.grails.data.hibernate7.dbmigration.cli
 
-import grails.dev.commands.ApplicationCommand
+import org.apache.grails.core.cli.ApplicationCommand
 import spock.lang.AutoCleanup
 
 class DbmMarkNextChangesetRanSqlCommandSpec extends ApplicationContextDatabaseMigrationCommandSpec {
diff --git a/grails-data-hibernate7/dbmigration/src/test/groovy/org/grails/plugins/databasemigration/command/DbmPreviousChangesetSqlCommandSpec.groovy b/grails-data-hibernate7/dbmigration/src/test/groovy/org/apache/grails/data/hibernate7/dbmigration/cli/DbmPreviousChangesetSqlCommandSpec.groovy
similarity index 97%
rename from grails-data-hibernate7/dbmigration/src/test/groovy/org/grails/plugins/databasemigration/command/DbmPreviousChangesetSqlCommandSpec.groovy
rename to grails-data-hibernate7/dbmigration/src/test/groovy/org/apache/grails/data/hibernate7/dbmigration/cli/DbmPreviousChangesetSqlCommandSpec.groovy
index 48d8251141..57884ead19 100644
--- a/grails-data-hibernate7/dbmigration/src/test/groovy/org/grails/plugins/databasemigration/command/DbmPreviousChangesetSqlCommandSpec.groovy
+++ b/grails-data-hibernate7/dbmigration/src/test/groovy/org/apache/grails/data/hibernate7/dbmigration/cli/DbmPreviousChangesetSqlCommandSpec.groovy
@@ -16,9 +16,9 @@
  *  specific language governing permissions and limitations
  *  under the License.
  */
-package org.grails.plugins.databasemigration.command
+package org.apache.grails.data.hibernate7.dbmigration.cli
 
-import grails.dev.commands.ApplicationCommand
+import org.apache.grails.core.cli.ApplicationCommand
 import org.grails.plugins.databasemigration.DatabaseMigrationException
 import spock.lang.AutoCleanup
 
diff --git a/grails-data-hibernate7/dbmigration/src/test/groovy/org/grails/plugins/databasemigration/command/DbmReleaseLocksCommandSpec.groovy b/grails-data-hibernate7/dbmigration/src/test/groovy/org/apache/grails/data/hibernate7/dbmigration/cli/DbmReleaseLocksCommandSpec.groovy
similarity index 93%
rename from grails-data-hibernate7/dbmigration/src/test/groovy/org/grails/plugins/databasemigration/command/DbmReleaseLocksCommandSpec.groovy
rename to grails-data-hibernate7/dbmigration/src/test/groovy/org/apache/grails/data/hibernate7/dbmigration/cli/DbmReleaseLocksCommandSpec.groovy
index 75c9983881..72d24520d4 100644
--- a/grails-data-hibernate7/dbmigration/src/test/groovy/org/grails/plugins/databasemigration/command/DbmReleaseLocksCommandSpec.groovy
+++ b/grails-data-hibernate7/dbmigration/src/test/groovy/org/apache/grails/data/hibernate7/dbmigration/cli/DbmReleaseLocksCommandSpec.groovy
@@ -16,9 +16,9 @@
  *  specific language governing permissions and limitations
  *  under the License.
  */
-package org.grails.plugins.databasemigration.command
+package org.apache.grails.data.hibernate7.dbmigration.cli
 
-import grails.dev.commands.ApplicationCommand
+import org.apache.grails.core.cli.ApplicationCommand
 
 class DbmReleaseLocksCommandSpec extends ApplicationContextDatabaseMigrationCommandSpec {
 
diff --git a/grails-data-hibernate5/dbmigration/src/test/groovy/org/grails/plugins/databasemigration/command/DbmRollbackCommandSpec.groovy b/grails-data-hibernate7/dbmigration/src/test/groovy/org/apache/grails/data/hibernate7/dbmigration/cli/DbmRollbackCommandSpec.groovy
similarity index 97%
rename from grails-data-hibernate5/dbmigration/src/test/groovy/org/grails/plugins/databasemigration/command/DbmRollbackCommandSpec.groovy
rename to grails-data-hibernate7/dbmigration/src/test/groovy/org/apache/grails/data/hibernate7/dbmigration/cli/DbmRollbackCommandSpec.groovy
index 80de7605b6..565e5c87b8 100644
--- a/grails-data-hibernate5/dbmigration/src/test/groovy/org/grails/plugins/databasemigration/command/DbmRollbackCommandSpec.groovy
+++ b/grails-data-hibernate7/dbmigration/src/test/groovy/org/apache/grails/data/hibernate7/dbmigration/cli/DbmRollbackCommandSpec.groovy
@@ -16,9 +16,9 @@
  *  specific language governing permissions and limitations
  *  under the License.
  */
-package org.grails.plugins.databasemigration.command
+package org.apache.grails.data.hibernate7.dbmigration.cli
 
-import grails.dev.commands.ApplicationCommand
+import org.apache.grails.core.cli.ApplicationCommand
 import org.grails.plugins.databasemigration.DatabaseMigrationException
 
 class DbmRollbackCommandSpec extends ApplicationContextDatabaseMigrationCommandSpec {
diff --git a/grails-data-hibernate7/dbmigration/src/test/groovy/org/grails/plugins/databasemigration/command/DbmRollbackCountCommandSpec.groovy b/grails-data-hibernate7/dbmigration/src/test/groovy/org/apache/grails/data/hibernate7/dbmigration/cli/DbmRollbackCountCommandSpec.groovy
similarity index 97%
rename from grails-data-hibernate7/dbmigration/src/test/groovy/org/grails/plugins/databasemigration/command/DbmRollbackCountCommandSpec.groovy
rename to grails-data-hibernate7/dbmigration/src/test/groovy/org/apache/grails/data/hibernate7/dbmigration/cli/DbmRollbackCountCommandSpec.groovy
index bdca200858..96654ba68c 100644
--- a/grails-data-hibernate7/dbmigration/src/test/groovy/org/grails/plugins/databasemigration/command/DbmRollbackCountCommandSpec.groovy
+++ b/grails-data-hibernate7/dbmigration/src/test/groovy/org/apache/grails/data/hibernate7/dbmigration/cli/DbmRollbackCountCommandSpec.groovy
@@ -16,9 +16,9 @@
  *  specific language governing permissions and limitations
  *  under the License.
  */
-package org.grails.plugins.databasemigration.command
+package org.apache.grails.data.hibernate7.dbmigration.cli
 
-import grails.dev.commands.ApplicationCommand
+import org.apache.grails.core.cli.ApplicationCommand
 import org.grails.plugins.databasemigration.DatabaseMigrationException
 
 class DbmRollbackCountCommandSpec extends ApplicationContextDatabaseMigrationCommandSpec {
diff --git a/grails-data-hibernate5/dbmigration/src/test/groovy/org/grails/plugins/databasemigration/command/DbmRollbackCountSqlCommandSpec.groovy b/grails-data-hibernate7/dbmigration/src/test/groovy/org/apache/grails/data/hibernate7/dbmigration/cli/DbmRollbackCountSqlCommandSpec.groovy
similarity index 97%
rename from grails-data-hibernate5/dbmigration/src/test/groovy/org/grails/plugins/databasemigration/command/DbmRollbackCountSqlCommandSpec.groovy
rename to grails-data-hibernate7/dbmigration/src/test/groovy/org/apache/grails/data/hibernate7/dbmigration/cli/DbmRollbackCountSqlCommandSpec.groovy
index e3a1915b13..77d83517a2 100644
--- a/grails-data-hibernate5/dbmigration/src/test/groovy/org/grails/plugins/databasemigration/command/DbmRollbackCountSqlCommandSpec.groovy
+++ b/grails-data-hibernate7/dbmigration/src/test/groovy/org/apache/grails/data/hibernate7/dbmigration/cli/DbmRollbackCountSqlCommandSpec.groovy
@@ -16,9 +16,9 @@
  *  specific language governing permissions and limitations
  *  under the License.
  */
-package org.grails.plugins.databasemigration.command
+package org.apache.grails.data.hibernate7.dbmigration.cli
 
-import grails.dev.commands.ApplicationCommand
+import org.apache.grails.core.cli.ApplicationCommand
 import org.grails.plugins.databasemigration.DatabaseMigrationException
 import spock.lang.AutoCleanup
 
diff --git a/grails-data-hibernate5/dbmigration/src/test/groovy/org/grails/plugins/databasemigration/command/DbmRollbackSqlCommandSpec.groovy b/grails-data-hibernate7/dbmigration/src/test/groovy/org/apache/grails/data/hibernate7/dbmigration/cli/DbmRollbackSqlCommandSpec.groovy
similarity index 97%
rename from grails-data-hibernate5/dbmigration/src/test/groovy/org/grails/plugins/databasemigration/command/DbmRollbackSqlCommandSpec.groovy
rename to grails-data-hibernate7/dbmigration/src/test/groovy/org/apache/grails/data/hibernate7/dbmigration/cli/DbmRollbackSqlCommandSpec.groovy
index c063046721..0246ba00d9 100644
--- a/grails-data-hibernate5/dbmigration/src/test/groovy/org/grails/plugins/databasemigration/command/DbmRollbackSqlCommandSpec.groovy
+++ b/grails-data-hibernate7/dbmigration/src/test/groovy/org/apache/grails/data/hibernate7/dbmigration/cli/DbmRollbackSqlCommandSpec.groovy
@@ -16,9 +16,9 @@
  *  specific language governing permissions and limitations
  *  under the License.
  */
-package org.grails.plugins.databasemigration.command
+package org.apache.grails.data.hibernate7.dbmigration.cli
 
-import grails.dev.commands.ApplicationCommand
+import org.apache.grails.core.cli.ApplicationCommand
 import org.grails.plugins.databasemigration.DatabaseMigrationException
 import spock.lang.AutoCleanup
 
diff --git a/grails-data-hibernate7/dbmigration/src/test/groovy/org/grails/plugins/databasemigration/command/DbmRollbackToDateCommandSpec.groovy b/grails-data-hibernate7/dbmigration/src/test/groovy/org/apache/grails/data/hibernate7/dbmigration/cli/DbmRollbackToDateCommandSpec.groovy
similarity index 97%
rename from grails-data-hibernate7/dbmigration/src/test/groovy/org/grails/plugins/databasemigration/command/DbmRollbackToDateCommandSpec.groovy
rename to grails-data-hibernate7/dbmigration/src/test/groovy/org/apache/grails/data/hibernate7/dbmigration/cli/DbmRollbackToDateCommandSpec.groovy
index 41c450a9c1..d7c4d1cc98 100644
--- a/grails-data-hibernate7/dbmigration/src/test/groovy/org/grails/plugins/databasemigration/command/DbmRollbackToDateCommandSpec.groovy
+++ b/grails-data-hibernate7/dbmigration/src/test/groovy/org/apache/grails/data/hibernate7/dbmigration/cli/DbmRollbackToDateCommandSpec.groovy
@@ -16,9 +16,9 @@
  *  specific language governing permissions and limitations
  *  under the License.
  */
-package org.grails.plugins.databasemigration.command
+package org.apache.grails.data.hibernate7.dbmigration.cli
 
-import grails.dev.commands.ApplicationCommand
+import org.apache.grails.core.cli.ApplicationCommand
 import org.grails.plugins.databasemigration.DatabaseMigrationException
 
 class DbmRollbackToDateCommandSpec extends ApplicationContextDatabaseMigrationCommandSpec {
diff --git a/grails-data-hibernate7/dbmigration/src/test/groovy/org/grails/plugins/databasemigration/command/DbmRollbackToDateSqlCommandSpec.groovy b/grails-data-hibernate7/dbmigration/src/test/groovy/org/apache/grails/data/hibernate7/dbmigration/cli/DbmRollbackToDateSqlCommandSpec.groovy
similarity index 97%
rename from grails-data-hibernate7/dbmigration/src/test/groovy/org/grails/plugins/databasemigration/command/DbmRollbackToDateSqlCommandSpec.groovy
rename to grails-data-hibernate7/dbmigration/src/test/groovy/org/apache/grails/data/hibernate7/dbmigration/cli/DbmRollbackToDateSqlCommandSpec.groovy
index cca3fb770a..4039f8fdd4 100644
--- a/grails-data-hibernate7/dbmigration/src/test/groovy/org/grails/plugins/databasemigration/command/DbmRollbackToDateSqlCommandSpec.groovy
+++ b/grails-data-hibernate7/dbmigration/src/test/groovy/org/apache/grails/data/hibernate7/dbmigration/cli/DbmRollbackToDateSqlCommandSpec.groovy
@@ -16,9 +16,9 @@
  *  specific language governing permissions and limitations
  *  under the License.
  */
-package org.grails.plugins.databasemigration.command
+package org.apache.grails.data.hibernate7.dbmigration.cli
 
-import grails.dev.commands.ApplicationCommand
+import org.apache.grails.core.cli.ApplicationCommand
 import org.grails.plugins.databasemigration.DatabaseMigrationException
 import spock.lang.AutoCleanup
 
diff --git a/grails-data-hibernate7/dbmigration/src/test/groovy/org/grails/plugins/databasemigration/command/DbmStatusCommandSpec.groovy b/grails-data-hibernate7/dbmigration/src/test/groovy/org/apache/grails/data/hibernate7/dbmigration/cli/DbmStatusCommandSpec.groovy
similarity index 94%
rename from grails-data-hibernate7/dbmigration/src/test/groovy/org/grails/plugins/databasemigration/command/DbmStatusCommandSpec.groovy
rename to grails-data-hibernate7/dbmigration/src/test/groovy/org/apache/grails/data/hibernate7/dbmigration/cli/DbmStatusCommandSpec.groovy
index 8c364e24f1..0abcca82df 100644
--- a/grails-data-hibernate7/dbmigration/src/test/groovy/org/grails/plugins/databasemigration/command/DbmStatusCommandSpec.groovy
+++ b/grails-data-hibernate7/dbmigration/src/test/groovy/org/apache/grails/data/hibernate7/dbmigration/cli/DbmStatusCommandSpec.groovy
@@ -16,9 +16,9 @@
  *  specific language governing permissions and limitations
  *  under the License.
  */
-package org.grails.plugins.databasemigration.command
+package org.apache.grails.data.hibernate7.dbmigration.cli
 
-import grails.dev.commands.ApplicationCommand
+import org.apache.grails.core.cli.ApplicationCommand
 import spock.lang.AutoCleanup
 
 class DbmStatusCommandSpec extends ApplicationContextDatabaseMigrationCommandSpec {
diff --git a/grails-data-hibernate5/dbmigration/src/test/groovy/org/grails/plugins/databasemigration/command/DbmUpdateCommandSpec.groovy b/grails-data-hibernate7/dbmigration/src/test/groovy/org/apache/grails/data/hibernate7/dbmigration/cli/DbmUpdateCommandSpec.groovy
similarity index 97%
rename from grails-data-hibernate5/dbmigration/src/test/groovy/org/grails/plugins/databasemigration/command/DbmUpdateCommandSpec.groovy
rename to grails-data-hibernate7/dbmigration/src/test/groovy/org/apache/grails/data/hibernate7/dbmigration/cli/DbmUpdateCommandSpec.groovy
index 3101e35bdd..2b338d6d3a 100644
--- a/grails-data-hibernate5/dbmigration/src/test/groovy/org/grails/plugins/databasemigration/command/DbmUpdateCommandSpec.groovy
+++ b/grails-data-hibernate7/dbmigration/src/test/groovy/org/apache/grails/data/hibernate7/dbmigration/cli/DbmUpdateCommandSpec.groovy
@@ -16,9 +16,9 @@
  *  specific language governing permissions and limitations
  *  under the License.
  */
-package org.grails.plugins.databasemigration.command
+package org.apache.grails.data.hibernate7.dbmigration.cli
 
-import grails.dev.commands.ApplicationCommand
+import org.apache.grails.core.cli.ApplicationCommand
 
 class DbmUpdateCommandSpec extends ApplicationContextDatabaseMigrationCommandSpec {
 
diff --git a/grails-data-hibernate7/dbmigration/src/test/groovy/org/grails/plugins/databasemigration/command/DbmUpdateCountCommandSpec.groovy b/grails-data-hibernate7/dbmigration/src/test/groovy/org/apache/grails/data/hibernate7/dbmigration/cli/DbmUpdateCountCommandSpec.groovy
similarity index 96%
rename from grails-data-hibernate7/dbmigration/src/test/groovy/org/grails/plugins/databasemigration/command/DbmUpdateCountCommandSpec.groovy
rename to grails-data-hibernate7/dbmigration/src/test/groovy/org/apache/grails/data/hibernate7/dbmigration/cli/DbmUpdateCountCommandSpec.groovy
index aa4a776c5c..a353597427 100644
--- a/grails-data-hibernate7/dbmigration/src/test/groovy/org/grails/plugins/databasemigration/command/DbmUpdateCountCommandSpec.groovy
+++ b/grails-data-hibernate7/dbmigration/src/test/groovy/org/apache/grails/data/hibernate7/dbmigration/cli/DbmUpdateCountCommandSpec.groovy
@@ -16,9 +16,9 @@
  *  specific language governing permissions and limitations
  *  under the License.
  */
-package org.grails.plugins.databasemigration.command
+package org.apache.grails.data.hibernate7.dbmigration.cli
 
-import grails.dev.commands.ApplicationCommand
+import org.apache.grails.core.cli.ApplicationCommand
 import org.grails.plugins.databasemigration.DatabaseMigrationException
 
 class DbmUpdateCountCommandSpec extends ApplicationContextDatabaseMigrationCommandSpec {
diff --git a/grails-data-hibernate5/dbmigration/src/test/groovy/org/grails/plugins/databasemigration/command/DbmUpdateCountSqlCommandSpec.groovy b/grails-data-hibernate7/dbmigration/src/test/groovy/org/apache/grails/data/hibernate7/dbmigration/cli/DbmUpdateCountSqlCommandSpec.groovy
similarity index 97%
rename from grails-data-hibernate5/dbmigration/src/test/groovy/org/grails/plugins/databasemigration/command/DbmUpdateCountSqlCommandSpec.groovy
rename to grails-data-hibernate7/dbmigration/src/test/groovy/org/apache/grails/data/hibernate7/dbmigration/cli/DbmUpdateCountSqlCommandSpec.groovy
index 676ec82a07..7799488deb 100644
--- a/grails-data-hibernate5/dbmigration/src/test/groovy/org/grails/plugins/databasemigration/command/DbmUpdateCountSqlCommandSpec.groovy
+++ b/grails-data-hibernate7/dbmigration/src/test/groovy/org/apache/grails/data/hibernate7/dbmigration/cli/DbmUpdateCountSqlCommandSpec.groovy
@@ -16,9 +16,9 @@
  *  specific language governing permissions and limitations
  *  under the License.
  */
-package org.grails.plugins.databasemigration.command
+package org.apache.grails.data.hibernate7.dbmigration.cli
 
-import grails.dev.commands.ApplicationCommand
+import org.apache.grails.core.cli.ApplicationCommand
 import org.grails.plugins.databasemigration.DatabaseMigrationException
 import spock.lang.AutoCleanup
 
diff --git a/grails-data-hibernate5/dbmigration/src/test/groovy/org/grails/plugins/databasemigration/command/DbmUpdateSqlCommandSpec.groovy b/grails-data-hibernate7/dbmigration/src/test/groovy/org/apache/grails/data/hibernate7/dbmigration/cli/DbmUpdateSqlCommandSpec.groovy
similarity index 98%
rename from grails-data-hibernate5/dbmigration/src/test/groovy/org/grails/plugins/databasemigration/command/DbmUpdateSqlCommandSpec.groovy
rename to grails-data-hibernate7/dbmigration/src/test/groovy/org/apache/grails/data/hibernate7/dbmigration/cli/DbmUpdateSqlCommandSpec.groovy
index d04a542631..f5acd39341 100644
--- a/grails-data-hibernate5/dbmigration/src/test/groovy/org/grails/plugins/databasemigration/command/DbmUpdateSqlCommandSpec.groovy
+++ b/grails-data-hibernate7/dbmigration/src/test/groovy/org/apache/grails/data/hibernate7/dbmigration/cli/DbmUpdateSqlCommandSpec.groovy
@@ -16,9 +16,9 @@
  *  specific language governing permissions and limitations
  *  under the License.
  */
-package org.grails.plugins.databasemigration.command
+package org.apache.grails.data.hibernate7.dbmigration.cli
 
-import grails.dev.commands.ApplicationCommand
+import org.apache.grails.core.cli.ApplicationCommand
 import spock.lang.AutoCleanup
 
 class DbmUpdateSqlCommandSpec extends ApplicationContextDatabaseMigrationCommandSpec {
diff --git a/grails-data-hibernate7/dbmigration/src/test/groovy/org/grails/plugins/databasemigration/command/DbmValidateCommandSpec.groovy b/grails-data-hibernate7/dbmigration/src/test/groovy/org/apache/grails/data/hibernate7/dbmigration/cli/DbmValidateCommandSpec.groovy
similarity index 96%
rename from grails-data-hibernate7/dbmigration/src/test/groovy/org/grails/plugins/databasemigration/command/DbmValidateCommandSpec.groovy
rename to grails-data-hibernate7/dbmigration/src/test/groovy/org/apache/grails/data/hibernate7/dbmigration/cli/DbmValidateCommandSpec.groovy
index b49d0db764..6eb20449b9 100644
--- a/grails-data-hibernate7/dbmigration/src/test/groovy/org/grails/plugins/databasemigration/command/DbmValidateCommandSpec.groovy
+++ b/grails-data-hibernate7/dbmigration/src/test/groovy/org/apache/grails/data/hibernate7/dbmigration/cli/DbmValidateCommandSpec.groovy
@@ -16,9 +16,9 @@
  *  specific language governing permissions and limitations
  *  under the License.
  */
-package org.grails.plugins.databasemigration.command
+package org.apache.grails.data.hibernate7.dbmigration.cli
 
-import grails.dev.commands.ApplicationCommand
+import org.apache.grails.core.cli.ApplicationCommand
 import liquibase.exception.CommandExecutionException
 
 class DbmValidateCommandSpec extends ApplicationContextDatabaseMigrationCommandSpec {
diff --git a/grails-data-hibernate7/dbmigration/src/test/groovy/org/grails/plugins/databasemigration/command/ScriptDatabaseMigrationCommandSpec.groovy b/grails-data-hibernate7/dbmigration/src/test/groovy/org/apache/grails/data/hibernate7/dbmigration/cli/ScriptDatabaseMigrationCommandSpec.groovy
similarity index 97%
rename from grails-data-hibernate7/dbmigration/src/test/groovy/org/grails/plugins/databasemigration/command/ScriptDatabaseMigrationCommandSpec.groovy
rename to grails-data-hibernate7/dbmigration/src/test/groovy/org/apache/grails/data/hibernate7/dbmigration/cli/ScriptDatabaseMigrationCommandSpec.groovy
index 05d5f36cc2..d83c3a00d4 100644
--- a/grails-data-hibernate7/dbmigration/src/test/groovy/org/grails/plugins/databasemigration/command/ScriptDatabaseMigrationCommandSpec.groovy
+++ b/grails-data-hibernate7/dbmigration/src/test/groovy/org/apache/grails/data/hibernate7/dbmigration/cli/ScriptDatabaseMigrationCommandSpec.groovy
@@ -16,7 +16,7 @@
  *  specific language governing permissions and limitations
  *  under the License.
  */
-package org.grails.plugins.databasemigration.command
+package org.apache.grails.data.hibernate7.dbmigration.cli
 
 import grails.util.GrailsNameUtils
 import org.grails.build.parsing.CommandLineParser
diff --git a/grails-data-hibernate7/dbmigration/src/test/groovy/org/grails/plugins/databasemigration/liquibase/GroovyChangeLogSpec.groovy b/grails-data-hibernate7/dbmigration/src/test/groovy/org/grails/plugins/databasemigration/liquibase/GroovyChangeLogSpec.groovy
index d794640852..62d1460e41 100644
--- a/grails-data-hibernate7/dbmigration/src/test/groovy/org/grails/plugins/databasemigration/liquibase/GroovyChangeLogSpec.groovy
+++ b/grails-data-hibernate7/dbmigration/src/test/groovy/org/grails/plugins/databasemigration/liquibase/GroovyChangeLogSpec.groovy
@@ -20,12 +20,12 @@ package org.grails.plugins.databasemigration.liquibase
 
 import grails.core.GrailsApplication
 import liquibase.exception.CommandExecutionException
-import org.grails.plugins.databasemigration.command.ApplicationContextDatabaseMigrationCommandSpec
-import org.grails.plugins.databasemigration.command.DbmChangelogSyncCommand
-import org.grails.plugins.databasemigration.command.DbmRollbackCommand
-import org.grails.plugins.databasemigration.command.DbmTagCommand
-import org.grails.plugins.databasemigration.command.DbmUpdateCommand
-import org.grails.plugins.databasemigration.command.DbmUpdateCountCommand
+import org.apache.grails.data.hibernate7.dbmigration.cli.ApplicationContextDatabaseMigrationCommandSpec
+import org.apache.grails.data.hibernate7.dbmigration.cli.DbmChangelogSyncCommand
+import org.apache.grails.data.hibernate7.dbmigration.cli.DbmRollbackCommand
+import org.apache.grails.data.hibernate7.dbmigration.cli.DbmTagCommand
+import org.apache.grails.data.hibernate7.dbmigration.cli.DbmUpdateCommand
+import org.apache.grails.data.hibernate7.dbmigration.cli.DbmUpdateCountCommand
 
 class GroovyChangeLogSpec extends ApplicationContextDatabaseMigrationCommandSpec {
 
diff --git a/grails-data-hibernate7/dbmigration/src/test/groovy/org/grails/plugins/databasemigration/liquibase/GroovyPreconditionSpec.groovy b/grails-data-hibernate7/dbmigration/src/test/groovy/org/grails/plugins/databasemigration/liquibase/GroovyPreconditionSpec.groovy
index 6118abadba..c339ae72a1 100644
--- a/grails-data-hibernate7/dbmigration/src/test/groovy/org/grails/plugins/databasemigration/liquibase/GroovyPreconditionSpec.groovy
+++ b/grails-data-hibernate7/dbmigration/src/test/groovy/org/grails/plugins/databasemigration/liquibase/GroovyPreconditionSpec.groovy
@@ -19,8 +19,8 @@
 package org.grails.plugins.databasemigration.liquibase
 
 import liquibase.exception.CommandExecutionException
-import org.grails.plugins.databasemigration.command.ApplicationContextDatabaseMigrationCommandSpec
-import org.grails.plugins.databasemigration.command.DbmUpdateCommand
+import org.apache.grails.data.hibernate7.dbmigration.cli.ApplicationContextDatabaseMigrationCommandSpec
+import org.apache.grails.data.hibernate7.dbmigration.cli.DbmUpdateCommand
 
 class GroovyPreconditionSpec extends ApplicationContextDatabaseMigrationCommandSpec {
 
diff --git a/grails-data-hibernate7/grails-plugin/build.gradle b/grails-data-hibernate7/grails-plugin/build.gradle
index 56e9b994d5..01e9a4df2e 100644
--- a/grails-data-hibernate7/grails-plugin/build.gradle
+++ b/grails-data-hibernate7/grails-plugin/build.gradle
@@ -21,6 +21,7 @@ plugins {
     id 'org.apache.grails.buildsrc.properties'
     id 'org.apache.grails.buildsrc.dependency-validator'
     id 'org.apache.grails.gradle.grails-plugin'
+    id 'org.apache.grails.gradle.grails-plugin-cli'
     id 'org.apache.grails.buildsrc.compile'
     id 'org.apache.grails.buildsrc.publish'
     id 'org.apache.grails.buildsrc.sbom'
@@ -31,6 +32,12 @@ plugins {
 version = projectVersion
 group = 'org.apache.grails'
 
+cliArtifact {
+    automaticModuleName = 'org.apache.grails.data.hibernate7.cli'
+    // this framework module wires its cli dependencies with project dependencies below
+    defaultDependencies = false
+}
+
 ext {
     gormApiDocs = true
     pomTitle = 'Grails GORM Hibernate 7 Plugin'
@@ -38,6 +45,17 @@ ext {
 }
 
 dependencies {
+    // the cli tier — published separately as org.apache.grails:grails-data-hibernate7-cli
+    cliImplementation platform(project(':grails-hibernate7-bom'))
+    cliApi project(project.path)
+    cliApi(project(':grails-core')) {
+        capabilities {
+            requireCapability('org.apache.grails:grails-core-cli')
+        }
+    }
+    // SchemaExport lives in hibernate-tools, which is implementation-scoped in the main tier
+    cliImplementation 'org.hibernate.tool:hibernate-tools-orm'
+
     implementation platform(project(':grails-hibernate7-bom'))
 
     api 'org.springframework.boot:spring-boot'
diff --git a/grails-data-hibernate7/grails-plugin/src/main/groovy/grails/plugin/hibernate/commands/SchemaExportCommand.groovy b/grails-data-hibernate7/grails-plugin/src/cli/groovy/org/apache/grails/data/hibernate7/cli/SchemaExportCommand.groovy
similarity index 95%
rename from grails-data-hibernate7/grails-plugin/src/main/groovy/grails/plugin/hibernate/commands/SchemaExportCommand.groovy
rename to grails-data-hibernate7/grails-plugin/src/cli/groovy/org/apache/grails/data/hibernate7/cli/SchemaExportCommand.groovy
index 5b6a06a7b9..69eacd0677 100644
--- a/grails-data-hibernate7/grails-plugin/src/main/groovy/grails/plugin/hibernate/commands/SchemaExportCommand.groovy
+++ b/grails-data-hibernate7/grails-plugin/src/cli/groovy/org/apache/grails/data/hibernate7/cli/SchemaExportCommand.groovy
@@ -16,7 +16,7 @@
  *  specific language governing permissions and limitations
  *  under the License.
  */
-package grails.plugin.hibernate.commands
+package org.apache.grails.data.hibernate7.cli
 
 import groovy.transform.CompileStatic
 
@@ -24,8 +24,8 @@ import org.hibernate.engine.spi.SessionFactoryImplementor
 import org.hibernate.tool.hbm2ddl.SchemaExport as HibernateSchemaExport
 import org.hibernate.tool.schema.TargetType
 
-import grails.dev.commands.ApplicationCommand
-import grails.dev.commands.ExecutionContext
+import org.apache.grails.core.cli.ApplicationCommand
+import org.apache.grails.core.cli.ExecutionContext
 import grails.util.Environment
 import org.grails.build.parsing.CommandLine
 import org.grails.datastore.mapping.core.connections.ConnectionSource
@@ -34,7 +34,6 @@ import org.grails.orm.hibernate.HibernateDatastore
 /**
  * Adds a schema-export command
  *
- * @author Graeme Rocher
  * @since 4.0
  */
 @CompileStatic
diff --git a/grails-doc/src/en/guide/commandLine/creatingCustomCommands.adoc b/grails-doc/src/en/guide/commandLine/creatingCustomCommands.adoc
index 61d704de67..8e18a8182c 100644
--- a/grails-doc/src/en/guide/commandLine/creatingCustomCommands.adoc
+++ b/grails-doc/src/en/guide/commandLine/creatingCustomCommands.adoc
@@ -31,14 +31,14 @@ Since Grails 3.2.0, commands have similar abilities as scripts in regards to ret
 
 If you created a command in a previous version of grails, you can update your command to have those abilities by changing which trait you are implementing.
 
-Commands created in Grails 3.1.x or lower implement the link:{api}grails/dev/commands/ApplicationCommand.html[ApplicationCommand] trait by default which requires your command to implement the following method:
+Commands created in Grails 3.1.x or lower implement the link:{api}org/apache/grails/core/cli/ApplicationCommand.html[ApplicationCommand] trait by default which requires your command to implement the following method:
 
 [source,groovy]
 ----
 boolean handle(ExecutionContext executionContext)
 ----
 
-Commands created in Grails 3.2.0 or higher implement the link:{api}grails/dev/commands/GrailsApplicationCommand.html[GrailsApplicationCommand] trait by default which requires your command to implement the following method:
+Commands created in Grails 3.2.0 or higher implement the link:{api}org/apache/grails/core/cli/GrailsApplicationCommand.html[GrailsApplicationCommand] trait by default which requires your command to implement the following method:
 
 [source,groovy]
 ----
@@ -82,7 +82,7 @@ There are several reasons why you might want to write a custom command for your
 * Integration: Custom commands can be used to integrate your Grails application with other systems or services. For example, you can create a command to synchronize data with an external API.
 * Customized Workflows: If your application has unique workflows or processes, custom commands provide a way to execute these workflows from the command line.
 
-In Grails, you can create custom commands by implementing the link:{api}grails/dev/commands/GrailsApplicationCommand.html[GrailsApplicationCommand] trait. By default, this trait requires your command to implement the handle() method as following:
+In Grails, you can create custom commands by implementing the link:{api}org/apache/grails/core/cli/GrailsApplicationCommand.html[GrailsApplicationCommand] trait. By default, this trait requires your command to implement the handle() method as following:
 
 [source,shell]
 ----
@@ -107,7 +107,7 @@ To create a custom command, you need to create a Groovy class that implements th
 // grails-app/commands/com/example/GreetCommand.groovy
 package com.example
 
-import grails.dev.commands.GrailsApplicationCommand
+import org.apache.grails.core.cli.GrailsApplicationCommand
 
 class GreetCommand implements GrailsApplicationCommand {
 
@@ -166,7 +166,7 @@ Grails also supports command-line arguments and options for custom commands. You
 // grails-app/commands/com/example/GreetCommand.groovy
 package com.example
 
-import grails.dev.commands.GrailsApplicationCommand
+import org.apache.grails.core.cli.GrailsApplicationCommand
 
 class GreetCommand implements GrailsApplicationCommand {
 
@@ -230,7 +230,7 @@ Here's an example of how you can create a custom command that uses the execution
 // grails-app/commands/com/example/BackupCommand.groovy
 package com.example
 
-import grails.dev.commands.GrailsApplicationCommand
+import org.apache.grails.core.cli.GrailsApplicationCommand
 
 class BackupCommand implements GrailsApplicationCommand {
 
@@ -272,69 +272,112 @@ When you run this custom command using `./gradlew runCommand -Pargs="backup"`, i
 
 **How to Create a Custom Command from a Grails Plugin**
 
-You can create custom commands not only within your Grails application but also from a Grails plugin. Here's how to do it:
-
-1. **Create a Grails Plugin:** If you don't already have a Grails plugin, you can create one using Grails' plugin generation commands. For example:
+Plugins publish their commands in a *companion cli artifact* (`<plugin-artifactId>-cli`) instead of
+the plugin's runtime jar, so command code and its CLI-only dependencies never reach an
+application's runtime classpath (`bootRun`, `bootJar`, `bootWar`). Here is the complete workflow:
 
+1. **Create a Grails Plugin:** If you don't already have a Grails plugin, create one:
 +
 [source,shell]
 ----
 grails create-plugin my-plugin
 ----
 
-2. **Define the Command:** Inside your Grails plugin, define the custom command by creating a Groovy class that implements the `GrailsApplicationCommand` trait or interface, providing the necessary methods like `getName()`, `getDescription()`, and `handle()`.
-
-3. **Build and Package the Plugin:** To publish the plugin, you should use the Gradle maven-publish plugin. Update your plugin's build.gradle file to include the following configuration:
-
+2. **Define the Command in a `cli` source set:** plugin commands live in `src/cli/groovy` (not
+`grails-app/commands`, which is compiled into the runtime jar). Give them a package that is unique
+to the cli artifact:
 +
 [source,groovy]
 ----
-publishing {
-    publications {
-        mavenJava(MavenPublication) {
-            from components.java
-        }
-    }
-    repositories {
-        maven {
-            url "file://path/to/your/local/repo" // Adjust the path accordingly
-        }
+// src/cli/groovy/com/example/myplugin/cli/AuditReportCommand.groovy
+package com.example.myplugin.cli
+
+import org.apache.grails.core.cli.GrailsApplicationCommand
+
+class AuditReportCommand implements GrailsApplicationCommand {
+
+    String description = 'Prints an audit report'
+
+    @Override
+    boolean handle() {
+        println 'Audit report...'
+        return true
     }
 }
-
 ----
 +
+When this source set compiles with `grails-core-cli` on its classpath, the command is registered
+automatically in `META-INF/grails-cli.factories` inside the cli jar — no manual registration file
+is needed.
+
+3. **Apply the Grails cli-artifact plugin in `build.gradle`:** it wires everything — the `cli`
+source set as a feature variant, the `grails-core-cli` contract and the plugin's own runtime
+classes on the cli compile classpath, the `Grails-Cli-Artifact` manifest advertisement on the
+runtime jar, and (when the Grails publish plugin is applied) the companion publication:
++
+[source,groovy]
+----
+plugins {
+    id 'org.apache.grails.gradle.grails-plugin'
+    id 'org.apache.grails.gradle.grails-plugin-cli'
+    id 'org.apache.grails.gradle.grails-publish'
+}
+
+cliArtifact {
+    // recommended: a unique, stable JPMS module name matching the cli package
+    automaticModuleName = 'com.example.myplugin.cli'
+}
 
-Then, you can publish the plugin to your local repository:
+dependencies {
+    // additional CLI-only dependencies of the commands, if any:
+    // cliImplementation 'org.example:some-cli-tool'
+}
+----
 
+4. **Publish both artifacts:** publishing the plugin publishes the companion alongside it, as its
+own coordinate with its own pom, sources, and javadoc:
 +
 [source,shell]
 ----
 ./gradlew publishToMavenLocal
+# com.example:my-plugin        (runtime — no command code)
+# com.example:my-plugin-cli    (the commands)
 ----
++
+NOTE: Without the Grails publish plugin, the cli feature is still built and advertised, but the
+companion publication must be configured manually from the `cli` software component.
 
-4. **Add the Plugin as a Dependency:** Instead of using the grails install-plugin command, you should add the plugin as a dependency in your Grails application's build.gradle file. Include the following dependency:
-
+5. **Consume the plugin from an application:** the application declares only the runtime plugin.
+The Grails Gradle plugin reads the `Grails-Cli-Artifact` manifest attribute from the plugin jar,
+adds `com.example:my-plugin-cli` to the application's `grailsCli` configuration, and registers the
+per-command Gradle task automatically:
 +
 [source,groovy]
 ----
 dependencies {
-    // ...
-    implementation 'com.example:my-plugin:1.0.0' // Replace with your plugin's group and version
-    // ...
+    implementation 'com.example:my-plugin:1.0.0'   // my-plugin-cli follows automatically
 }
 ----
-+
-Make sure to replace "com.example:my-plugin:1.0.0" with the appropriate group and version for your plugin
 
-5. **Run the Custom Command:** Now, you can run the custom command from your Grails application's root directory using the Gradle `runCommand` task, as previously explained:
+6. **Run the Command:**
 +
 [source,shell]
 ----
-./gradlew runCommand -Pargs="your-command-name"
+./gradlew runCommand -Pargs="audit-report"
+# or, via the automatically registered per-command task:
+./gradlew auditReport
 ----
-+
 
-Replace `"your-command-name"` with the name of the custom command you defined in your plugin.
+If an application disables the automatic discovery (`grails { cliAutoProvision = false }`), it
+declares the companion explicitly instead:
+
+[source,groovy]
+----
+dependencies {
+    implementation 'com.example:my-plugin:1.0.0'
+    grailsCli 'com.example:my-plugin-cli:1.0.0'
+}
+----
 
-By following these steps, you can create and run custom commands from a Grails plugin, extending the functionality of your Grails application as needed. This approach allows you to modularize your custom functionality and share it across multiple Grails projects if necessary.
+By packaging commands this way, the plugin's runtime jar stays free of command code and CLI-only
+libraries, while applications get the commands with no additional build configuration.
diff --git a/grails-doc/src/en/guide/commandLine/gradleBuild/gradlePlugins.adoc b/grails-doc/src/en/guide/commandLine/gradleBuild/gradlePlugins.adoc
index 8ee5c8672f..8a94c3f56e 100644
--- a/grails-doc/src/en/guide/commandLine/gradleBuild/gradlePlugins.adoc
+++ b/grails-doc/src/en/guide/commandLine/gradleBuild/gradlePlugins.adoc
@@ -56,6 +56,7 @@ Many of these are built-in plugins provided by Gradle or third-party plugins. Th
 * `org.apache.grails.gradle.grails-gson` - Adds support for compiling JSON Views (GSON)
 * `org.apache.grails.gradle.grails-markup` - Adds support for compiling Markup Views (XML)
 * `org.apache.grails.gradle.grails-plugin` - Marks the project as a Grails plugin
+* `org.apache.grails.gradle.grails-plugin-cli` - Publishes a Grails plugin's CLI commands as a companion `-cli` artifact, keeping command code off application runtime classpaths
 * `org.apache.grails.gradle.grails-web` - Adds the web URL mappings report to the Gradle project
 * `org.apache.grails.gradle.grails-publish` - Assists in publishing to Maven or Nexus repositories
 * `org.apache.grails.gradle.grails-profile` - Marks the project as a Grails profile
diff --git a/grails-doc/src/en/guide/introduction/whatsNew.adoc b/grails-doc/src/en/guide/introduction/whatsNew.adoc
index 482b962915..9e1af9e085 100644
--- a/grails-doc/src/en/guide/introduction/whatsNew.adoc
+++ b/grails-doc/src/en/guide/introduction/whatsNew.adoc
@@ -39,6 +39,53 @@ This brings the Spring Boot 4 modular artifact layout, Spring Framework 7 API re
 
 The Grails 8 upgrade guide calls out the major application-impacting changes and links to the Spring Boot 4.0 migration guide, Spring Boot 4.1 release notes and Spring Framework 7.0 release notes.
 
+==== CLI Commands Move to Companion `-cli` Artifacts
+
+Grails commands (`ApplicationCommand` implementations such as the `dbm-*` database-migration
+commands, the scaffolding `generate-*` commands, `url-mappings-report`, and `schema-export`) no
+longer ship inside the runtime plugin artifacts.
+Each command-bearing module now publishes a companion artifact under its own Maven coordinate with
+a `-cli` suffix — for example `org.apache.grails:grails-core-cli` and
+`org.apache.grails:grails-data-hibernate7-dbmigration-cli`.
+
+The command contract itself moved from `grails.dev.commands.*` to `org.apache.grails.core.cli.*`
+in the new `grails-core-cli` artifact.
+Applications consume cli artifacts through the new `grailsCli` Gradle configuration, which is
+compile-visible for `grails-app/commands` sources and on the command-runner classpath, but never on
+`runtimeClasspath` — commands and their CLI-only dependencies (such as `grails-shell-cli`) are
+excluded from `bootRun`, `bootJar`, and `bootWar` entirely.
+The Grails Gradle plugin provisions `grailsCli` automatically: it adds `grails-core-cli` and
+`grails-console`, and discovers every companion cli artifact advertised by the application's
+dependency graph — a command-bearing plugin advertises its companion through the
+`Grails-Cli-Artifact` manifest attribute of its runtime jar, and its commands are registered in a
+`META-INF/grails-cli.factories` file inside the companion jar. Declaring a plugin is therefore all
+that is needed; its commands (including the per-command Gradle tasks such as `dbmUpdate`) follow
+automatically, even when the plugin is only a transitive dependency:
+
+[source,groovy]
+.build.gradle
+----
+dependencies {
+    // the dbm-* commands are discovered automatically: the plugin jar advertises
+    // org.apache.grails:grails-data-hibernate7-dbmigration-cli, which is added to grailsCli
+    implementation 'org.apache.grails:grails-data-hibernate7-dbmigration'
+}
+----
+
+The auto-provisioning can be disabled with `grails { cliAutoProvision = false }`, in which case
+`grailsCli` dependencies are declared explicitly.
+
+Plugin authors get the whole publishing side from the new
+`org.apache.grails.gradle.grails-plugin-cli` Gradle plugin: it creates the `cli` source set as a
+feature variant, wires the command contract onto its compile classpath, advertises the companion
+from the runtime jar, and publishes it (via the Grails publish plugin) under the plugin's
+coordinate with the `-cli` suffix — the framework's own command-bearing modules are built with the
+same plugin.
+
+This removes CLI-only dependencies — and their side effects, such as the WAR-deployment failure
+caused by a CLI Spring Boot initializer on the runtime classpath — from packaged applications.
+See the xref:upgrading#upgrading80x[upgrade guide] for the migration steps.
+
 ==== GSP Tag Library Improvements
 
 Grails {grailsMajorVersion} continues the move toward method-based TagLib handlers while preserving compatibility with existing closure-based tags.
diff --git a/grails-doc/src/en/guide/plugins/providingBasicArtefacts.adoc b/grails-doc/src/en/guide/plugins/providingBasicArtefacts.adoc
index 1672ad3b39..d38201d633 100644
--- a/grails-doc/src/en/guide/plugins/providingBasicArtefacts.adoc
+++ b/grails-doc/src/en/guide/plugins/providingBasicArtefacts.adoc
@@ -41,11 +41,11 @@ If you want to create a new shell command that interacts with a loaded Grails ap
 $ grails create-command MyExampleCommand
 ----
 
-This will create a file called `grails-app/commands/PACKAGE_PATH/MyExampleCommand.groovy` that extends link:{api}grails/dev/commands/ApplicationCommand.html[ApplicationCommand]:
+This will create a file called `grails-app/commands/PACKAGE_PATH/MyExampleCommand.groovy` that extends link:{api}org/apache/grails/core/cli/ApplicationCommand.html[ApplicationCommand]:
 
 [source,groovy]
 ----
-import grails.dev.commands.*
+import org.apache.grails.core.cli.*
 
 class MyExampleCommand implements ApplicationCommand {
 
@@ -58,6 +58,48 @@ class MyExampleCommand implements ApplicationCommand {
 
 An `ApplicationCommand` has access to the `GrailsApplication` instance and is subject to autowiring like any other Spring bean.
 
+===== Ship plugin commands as a companion `-cli` artifact
+
+Commands are only ever executed by the CLI, so a plugin should keep them off the application
+runtime classpath. Publish them as a companion artifact under the plugin's coordinate with a `-cli`
+suffix by applying the `org.apache.grails.gradle.grails-plugin-cli` Gradle plugin:
+
+[source,groovy]
+.build.gradle
+----
+plugins {
+    id 'org.apache.grails.gradle.grails-plugin'
+    id 'org.apache.grails.gradle.grails-plugin-cli'
+}
+
+cliArtifact {
+    automaticModuleName = 'org.example.myplugin.cli'
+}
+----
+
+Place the command sources in `src/cli/groovy` (not `grails-app/commands`, which is compiled into
+the runtime plugin jar). The plugin creates the `cli` source set as a feature variant, puts the
+`grails-core-cli` command contract and the plugin's own runtime classes on its compile classpath,
+and registers compiled commands automatically in `META-INF/grails-cli.factories` inside the cli
+jar. It also advertises the companion coordinate through the `Grails-Cli-Artifact` manifest
+attribute of the runtime jar — the Grails Gradle plugin scans an application's dependency graph
+for this attribute and adds each advertised artifact to `grailsCli`, so applications only declare
+the runtime plugin:
+
+[source,groovy]
+.build.gradle
+----
+dependencies {
+    implementation 'org.example:my-plugin'   // org.example:my-plugin-cli follows automatically
+}
+----
+
+When the Grails publish plugin (`org.apache.grails.gradle.grails-publish`) is applied, the
+companion is published alongside the plugin as `org.example:my-plugin-cli` with its own pom,
+sources, and javadoc. See the
+xref:commandLine#creatingCustomCommands[Creating Custom Commands] section for the complete
+workflow.
+
 You can also inform Grails to skip the execution of `Bootstrap.groovy` files with a simple property in your command:
 
 [source,groovy]
diff --git a/grails-doc/src/en/guide/upgrading/upgrading80x.adoc b/grails-doc/src/en/guide/upgrading/upgrading80x.adoc
index 37e6b139e9..ee60a47193 100644
--- a/grails-doc/src/en/guide/upgrading/upgrading80x.adoc
+++ b/grails-doc/src/en/guide/upgrading/upgrading80x.adoc
@@ -1410,3 +1410,101 @@ Now the framework bean simply backs off.
 
 NOTE: The back-off applies to beans that are registered before auto-configuration conditions are evaluated — `@Bean` methods in application configuration classes.
 Beans contributed later, through a plugin's `doWithSpring` or the application's `resources.groovy`, continue to take effect through bean-definition overriding, exactly as in previous releases.
+
+==== 33. CLI Commands Move to Companion `-cli` Artifacts
+
+Grails commands (`ApplicationCommand` implementations) no longer ship inside runtime plugin
+artifacts. Each command-bearing module publishes a companion artifact under its own coordinate with
+a `-cli` suffix, and commands are registered in a dedicated `META-INF/grails-cli.factories` file
+instead of `META-INF/grails.factories`.
+
+**Package rename.** The command contract moved from `grails.dev.commands.*` (in `grails-core`) to
+`org.apache.grails.core.cli.*` (in the new `org.apache.grails:grails-core-cli` artifact). Update
+imports in your `grails-app/commands` classes:
+
+[source,groovy]
+----
+// Grails 7
+import grails.dev.commands.ApplicationCommand
+import grails.dev.commands.ExecutionContext
+
+// Grails 8
+import org.apache.grails.core.cli.ApplicationCommand
+import org.apache.grails.core.cli.ExecutionContext
+----
+
+**New `grailsCli` configuration.** The Grails Gradle plugin registers a `grailsCli` configuration
+that is compile-visible for `grails-app/commands` sources and on the command-runner classpath, but
+never on `runtimeClasspath` — so commands and their CLI-only dependencies are excluded from
+`bootRun`, `bootJar`, and `bootWar`.
+
+**CLI dependencies are discovered automatically.** The plugin adds
+`org.apache.grails:grails-core-cli` (the command contract) and `org.apache.grails:grails-console`
+(the command runner) to `grailsCli`, and walks the application's resolved dependency graph —
+including transitive plugins — for jars carrying the `Grails-Cli-Artifact` manifest attribute,
+adding each advertised companion automatically. The per-command Gradle tasks (e.g. `dbmUpdate`)
+are registered from those companions as well, so no `buildscript` classpath entry is required. In
+most applications, upgrading therefore requires **no build changes** to keep plugin commands
+working:
+
+[source,groovy]
+.build.gradle
+----
+dependencies {
+    // the dbm-* commands are discovered automatically: the plugin jar advertises
+    // org.apache.grails:grails-data-hibernate7-dbmigration-cli, which is added to grailsCli
+    implementation 'org.apache.grails:grails-data-hibernate7-dbmigration'
+}
+----
+
+Disable the discovery with `grails { cliAutoProvision = false }` and declare the cli tier
+explicitly when full control over the command classpath is preferred:
+
+[source,groovy]
+.build.gradle
+----
+grails {
+    cliAutoProvision = false
+}
+
+dependencies {
+    implementation 'org.apache.grails:grails-data-hibernate7-dbmigration'
+    grailsCli 'org.apache.grails:grails-core-cli'
+    grailsCli 'org.apache.grails:grails-console'
+    grailsCli 'org.apache.grails:grails-data-hibernate7-dbmigration-cli'
+}
+----
+
+The renamed framework command packages are:
+
+|===
+|Grails 7 | Grails 8 (`-cli` artifact)
+
+|`grails.dev.commands.*` (grails-core)
+|`org.apache.grails.core.cli.*` (grails-core-cli)
+
+|`org.grails.web.mapping.reporting.UrlMappingsReportCommand`
+|`org.apache.grails.web.mapping.cli.UrlMappingsReportCommand` (grails-web-url-mappings-cli)
+
+|`scaffolding.*` commands
+|`org.apache.grails.scaffolding.cli.*` (grails-scaffolding-cli)
+
+|`grails.plugin.hibernate.commands.SchemaExportCommand`
+|`org.apache.grails.data.hibernate5.cli` / `...hibernate7.cli` (grails-data-hibernate5-cli / -7-cli)
+
+|`org.grails.plugins.databasemigration.command.*`
+|`org.apache.grails.data.hibernate5.dbmigration.cli` / `...hibernate7.dbmigration.cli`
+
+|`grails.plugin.springsecurity` s2 commands
+|`org.apache.grails.security.cli.*` (grails-spring-security-cli)
+|===
+
+**Third-party plugins must be rebuilt against Grails 8.** Apply the new
+`org.apache.grails.gradle.grails-plugin-cli` Gradle plugin, move command sources from
+`grails-app/commands` to `src/cli/groovy`, and update the contract imports — recompiling then
+regenerates the `grails-cli.factories` registration automatically and the companion `-cli`
+artifact is published alongside the plugin (see
+xref:commandLine#creatingCustomCommands[Creating Custom Commands] for the complete workflow).
+Hand-authored command registrations must move from
+`src/main/resources/META-INF/grails.factories` to `.../grails-cli.factories`. A Grails 7 command
+plugin dropped onto a Grails 8 application unchanged will not have its commands discovered.
diff --git a/grails-doc/src/en/ref/Command Line/create-command.adoc b/grails-doc/src/en/ref/Command Line/create-command.adoc
index fd5d39320c..c9e0ac2c91 100644
--- a/grails-doc/src/en/ref/Command Line/create-command.adoc	
+++ b/grails-doc/src/en/ref/Command Line/create-command.adoc	
@@ -37,7 +37,7 @@ Creates a class called `grails-app/commands/PACKAGE_PATH/MyExampleCommand.groovy
 
 [source,groovy]
 ----
-import grails.dev.commands.*
+import org.apache.grails.core.cli.*
 
 class MyExampleCommand implements ApplicationCommand {
 
@@ -76,19 +76,14 @@ Or as a Gradle task:
 gradle myExample
 ----
 
-The plugin is required be on both the build classpath and the runtime classpath in `build.gradle` in order for the short form to work:
+Declaring the plugin as a regular dependency is all that is required for the short form to work —
+the plugin's companion `-cli` artifact (which carries its commands) is discovered from the
+dependency graph automatically and both the command and its Gradle task are registered:
 
 [source,groovy]
 ----
-buildscript {
-  ...
-  dependencies {
-    classpath "org.grails.plugins:myplugin:0.1-SNAPSHOT"
-  }
-  ...
-  dependencies {
-    runtime "org.grails.plugins:myplugin:0.1-SNAPSHOT"
-  }
+dependencies {
+    implementation "org.grails.plugins:myplugin:0.1-SNAPSHOT"
 }
 ----
 
@@ -96,4 +91,4 @@ buildscript {
 
 In order to separate the code generation and build layer, in Grails 3.x scripts created with `create-script` do not have access to the running application instance.
 
-Instead, Grails 3.x features a new concept called an link:{apiFromRef}grails/dev/commands/ApplicationCommand.html[ApplicationCommand] that is invoked via Gradle to perform tasks such as interact with classes in the runtime.
+Instead, Grails 3.x features a new concept called an link:{apiFromRef}org/apache/grails/core/cli/ApplicationCommand.html[ApplicationCommand] that is invoked via Gradle to perform tasks such as interact with classes in the runtime.
diff --git a/grails-forge/grails-forge-core/src/main/java/org/grails/forge/feature/migration/DatabaseMigrationPlugin.java b/grails-forge/grails-forge-core/src/main/java/org/grails/forge/feature/migration/DatabaseMigrationPlugin.java
index 413d849cba..6c8f450d81 100644
--- a/grails-forge/grails-forge-core/src/main/java/org/grails/forge/feature/migration/DatabaseMigrationPlugin.java
+++ b/grails-forge/grails-forge-core/src/main/java/org/grails/forge/feature/migration/DatabaseMigrationPlugin.java
@@ -57,16 +57,14 @@ public class DatabaseMigrationPlugin implements MigrationFeature {
     @Override
     public void apply(GeneratorContext generatorContext) {
         final String srcDirPath = getSrcDirPath();
-        generatorContext.addBuildscriptDependency(Dependency.builder()
-                .groupId("org.apache.grails")
-                .artifactId("grails-data-hibernate5-dbmigration")
-                .buildSrc()
-                .extension(new RockerWritable(dbMigrationGradle.template(srcDirPath))));
+        // the dbm-* commands ship in the companion -cli artifact, which the Grails Gradle plugin
+        // discovers automatically from the plugin jar's Grails-Cli-Artifact manifest attribute —
+        // no buildscript classpath or grailsCli entry is generated
         generatorContext.addDependency(Dependency.builder()
                 .groupId("org.apache.grails")
                 .artifactId("grails-data-hibernate5-dbmigration")
-                .implementation());
-
+                .implementation()
+                .extension(new RockerWritable(dbMigrationGradle.template(srcDirPath))));
         final ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
         generatorContext.addTemplate(srcDirPath, new URLTemplate(srcDirPath + "/.gitkeep", classLoader.getResource(".gitkeep")));
     }
diff --git a/grails-forge/grails-forge-core/src/test/groovy/org/grails/forge/feature/migration/DatabaseMigrationPluginSpec.groovy b/grails-forge/grails-forge-core/src/test/groovy/org/grails/forge/feature/migration/DatabaseMigrationPluginSpec.groovy
index b53ab1c501..83dbde3e30 100644
--- a/grails-forge/grails-forge-core/src/test/groovy/org/grails/forge/feature/migration/DatabaseMigrationPluginSpec.groovy
+++ b/grails-forge/grails-forge-core/src/test/groovy/org/grails/forge/feature/migration/DatabaseMigrationPluginSpec.groovy
@@ -36,29 +36,30 @@ class DatabaseMigrationPluginSpec extends ApplicationContextSpec implements Comm
                 .features(["database-migration"])
                 .render()
 
-        then:
-        template.contains('classpath "org.apache.grails:grails-data-hibernate5-dbmigration"')
+        then: 'only the runtime plugin is declared — its -cli companion is auto-discovered by the Grails Gradle plugin'
         template.contains('implementation "org.apache.grails:grails-data-hibernate5-dbmigration"')
+        !template.contains('grails-data-hibernate5-dbmigration-cli')
     }
 
-    void "test dependencies are present for buildSrc"() {
+    void "test the cli companion is not declared in buildSrc"() {
         when:
         final String template = new BuildBuilder(beanContext)
                 .features(["database-migration"])
                 .renderBuildSrc()
 
         then:
-        template.contains('implementation "org.apache.grails:grails-data-hibernate5-dbmigration"')
+        !template.contains('grails-data-hibernate5-dbmigration')
     }
 
-    void "test dependencies are present for buildscript "() {
+    void "test the generated application declares only the runtime plugin"() {
         given:
         final def output = generate(ApplicationType.WEB, new Options(DevelopmentReloading.DEVTOOLS), ['database-migration'])
         final def buildGradle = output["build.gradle"]
 
         expect:
         buildGradle != null
-        buildGradle.contains('classpath "org.apache.grails:grails-data-hibernate5-dbmigration"')
+        buildGradle.contains('implementation "org.apache.grails:grails-data-hibernate5-dbmigration"')
+        !buildGradle.contains('grails-data-hibernate5-dbmigration-cli')
     }
 
     @Unroll
diff --git a/grails-gradle/model/src/main/groovy/org/grails/io/support/FactoriesLoaderSupport.groovy b/grails-gradle/model/src/main/groovy/org/grails/io/support/FactoriesLoaderSupport.groovy
index b952f1d95d..8fe20c2f79 100644
--- a/grails-gradle/model/src/main/groovy/org/grails/io/support/FactoriesLoaderSupport.groovy
+++ b/grails-gradle/model/src/main/groovy/org/grails/io/support/FactoriesLoaderSupport.groovy
@@ -27,7 +27,6 @@ import groovy.transform.CompileStatic
 /**
  * Base functionality for loading grails.factories
  *
- * @author Graeme Rocher
  * @since 3.0
  */
 @CompileStatic
@@ -36,7 +35,10 @@ class FactoriesLoaderSupport {
     /** The location to look for the factories. Can be present in multiple JAR files. */
     static final String FACTORIES_RESOURCE_LOCATION = 'META-INF/grails.factories'
 
-    private static ConcurrentMap<Integer, Map<String,String[]>> loadedPropertiesForClassLoader = new ConcurrentHashMap<Integer, Map<String,String[]>>()
+    /** The location to look for CLI command registrations. Can be present in multiple JAR files. */
+    static final String CLI_FACTORIES_RESOURCE_LOCATION = 'META-INF/grails-cli.factories'
+
+    private static ConcurrentMap<String, Map<String,String[]>> loadedPropertiesForClassLoader = new ConcurrentHashMap<String, Map<String,String[]>>()
 
     /**
      * Loads the names of the classes from grails.factories without loading the classes themselves
@@ -46,9 +48,10 @@ class FactoriesLoaderSupport {
      *
      * @return An array of classes that implement the factory class
      */
-    static String[] loadFactoryNames(Class<?> factoryClass, ClassLoader classLoader = FactoriesLoaderSupport.classLoader) {
+    static String[] loadFactoryNames(Class<?> factoryClass, ClassLoader classLoader = FactoriesLoaderSupport.classLoader,
+                                     String resourceLocation = FACTORIES_RESOURCE_LOCATION) {
         String factoryClassName = factoryClass.getName()
-        return loadFactoryNames(factoryClassName, classLoader)
+        return loadFactoryNames(factoryClassName, classLoader, resourceLocation)
     }
 
     /**
@@ -59,12 +62,14 @@ class FactoriesLoaderSupport {
      *
      * @return An array of classes that implement the factory class
      */
-    static String[] loadFactoryNames(String factoryClassName, ClassLoader classLoader = FactoriesLoaderSupport.classLoader) {
+    static String[] loadFactoryNames(String factoryClassName, ClassLoader classLoader = FactoriesLoaderSupport.classLoader,
+                                     String resourceLocation = FACTORIES_RESOURCE_LOCATION) {
         try {
-            Map<String, String[]> loadedProperties = loadedPropertiesForClassLoader.get(System.identityHashCode(classLoader))
+            String cacheKey = "${System.identityHashCode(classLoader)}:${resourceLocation}"
+            Map<String, String[]> loadedProperties = loadedPropertiesForClassLoader.get(cacheKey)
             if (loadedProperties == null) {
                 Set<String> allKeys = [] as Set
-                def urls = classLoader.getResources(FACTORIES_RESOURCE_LOCATION)
+                def urls = classLoader.getResources(resourceLocation)
                 Collection<Properties> allProperties = []
                 urls.each { URL url ->
                     def properties = new Properties()
@@ -85,7 +90,7 @@ class FactoriesLoaderSupport {
                     }
                     mergedFactoryNames.put(propertyName, result as String[])
                 }
-                loadedProperties = loadedPropertiesForClassLoader.putIfAbsent(System.identityHashCode(classLoader), mergedFactoryNames)
+                loadedProperties = loadedPropertiesForClassLoader.putIfAbsent(cacheKey, mergedFactoryNames)
                 if (loadedProperties == null) {
                     loadedProperties = mergedFactoryNames
                 }
@@ -93,7 +98,7 @@ class FactoriesLoaderSupport {
             return loadedProperties.get(factoryClassName)
         }
         catch (IOException ex) {
-            throw new IllegalArgumentException("Unable to load [$factoryClassName] factories from location [$FACTORIES_RESOURCE_LOCATION]", ex)
+            throw new IllegalArgumentException("Unable to load [$factoryClassName] factories from location [$resourceLocation]", ex)
         }
     }
 }
diff --git a/grails-gradle/plugins/build.gradle b/grails-gradle/plugins/build.gradle
index f9c7cf3e7f..ae5645cde3 100644
--- a/grails-gradle/plugins/build.gradle
+++ b/grails-gradle/plugins/build.gradle
@@ -119,6 +119,12 @@ gradlePlugin {
             id = 'org.apache.grails.gradle.grails-plugin'
             implementationClass = 'org.grails.gradle.plugin.core.GrailsPluginGradlePlugin'
         }
+        grailsPluginCli {
+            displayName = 'Grails Plugin CLI Artifact Gradle Plugin'
+            description = 'Declares a Grails plugin\'s CLI commands as a companion -cli artifact, keeping command code off application runtime classpaths'
+            id = 'org.apache.grails.gradle.grails-plugin-cli'
+            implementationClass = 'org.grails.gradle.plugin.commands.GrailsCliArtifactGradlePlugin'
+        }
         grailsProfile {
             displayName = 'Grails Profile Gradle Plugin'
             description = 'A plugin that is capable of compiling a Grails profile into a JAR file for distribution'
diff --git a/grails-gradle/plugins/src/main/groovy/org/grails/gradle/plugin/commands/CliArtifactExtension.groovy b/grails-gradle/plugins/src/main/groovy/org/grails/gradle/plugin/commands/CliArtifactExtension.groovy
new file mode 100644
index 0000000000..cb14a912a8
--- /dev/null
+++ b/grails-gradle/plugins/src/main/groovy/org/grails/gradle/plugin/commands/CliArtifactExtension.groovy
@@ -0,0 +1,49 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you 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.grails.gradle.plugin.commands
+
+import org.gradle.api.provider.Property
+
+/**
+ * Configuration for {@link GrailsCliArtifactGradlePlugin}.
+ *
+ * @since 8.0
+ */
+abstract class CliArtifactExtension {
+
+    /**
+     * The artifactId of the companion cli artifact; defaults to {@code "${project.name}-cli"}
+     */
+    abstract Property<String> getArtifactId()
+
+    /**
+     * The optional {@code Automatic-Module-Name} of the companion cli jar. Recommended: a unique,
+     * stable JPMS module name matching the cli source set's package
+     * (e.g. {@code com.example.myplugin.cli}).
+     */
+    abstract Property<String> getAutomaticModuleName()
+
+    /**
+     * Whether the plugin adds the default cli dependencies — the plugin project's own runtime
+     * classes and the {@code org.apache.grails:grails-core-cli} command contract — to
+     * {@code cliApi}. Defaults to {@code true}; disable to wire the cli dependency graph manually
+     * (e.g. with project dependencies inside a composite build).
+     */
+    abstract Property<Boolean> getDefaultDependencies()
+}
diff --git a/grails-gradle/plugins/src/main/groovy/org/grails/gradle/plugin/commands/GrailsCliArtifactGradlePlugin.groovy b/grails-gradle/plugins/src/main/groovy/org/grails/gradle/plugin/commands/GrailsCliArtifactGradlePlugin.groovy
new file mode 100644
index 0000000000..fb2c0c8cca
--- /dev/null
+++ b/grails-gradle/plugins/src/main/groovy/org/grails/gradle/plugin/commands/GrailsCliArtifactGradlePlugin.groovy
@@ -0,0 +1,241 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you 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.grails.gradle.plugin.commands
+
+import groovy.transform.CompileDynamic
+import groovy.transform.CompileStatic
+
+import org.gradle.api.GradleException
+import org.gradle.api.Plugin
+import org.gradle.api.Project
+import org.gradle.api.artifacts.Configuration
+import org.gradle.api.artifacts.PublishArtifact
+import org.gradle.api.component.AdhocComponentWithVariants
+import org.gradle.api.component.ConfigurationVariantDetails
+import org.gradle.api.component.SoftwareComponentFactory
+import org.gradle.api.tasks.SourceSet
+import org.gradle.api.tasks.SourceSetContainer
+import org.gradle.api.tasks.bundling.Jar
+import org.gradle.api.plugins.JavaPluginExtension
+
+import javax.inject.Inject
+
+import org.apache.grails.gradle.publish.AdditionalPublication
+import org.apache.grails.gradle.publish.GrailsPublishExtension
+
+/**
+ * Configures a Grails plugin project to ship its CLI commands as a companion artifact under its
+ * own Maven coordinate ({@code <artifactId>-cli}), keeping command code and CLI-only dependencies
+ * off the runtime classpath of consuming applications.
+ *
+ * Applying the plugin:
+ * <ul>
+ *   <li>creates a {@code cli} source set ({@code src/cli/groovy}) exposed as a feature variant;</li>
+ *   <li>adds {@code org.apache.grails:grails-core-cli} (the command contract) and the plugin's own
+ *       runtime classes to the cli compile classpath, so commands compile with no additional
+ *       configuration and are registered automatically in {@code META-INF/grails-cli.factories};</li>
+ *   <li>keeps the cli variants out of the plugin's default publication and exposes them through a
+ *       dedicated {@code cli} software component;</li>
+ *   <li>stamps the runtime jar with the {@code Grails-Cli-Artifact} manifest attribute, so the
+ *       Grails Gradle plugin adds the companion to a consuming application's {@code grailsCli}
+ *       configuration automatically;</li>
+ *   <li>registers the companion publication with the Grails publish plugin
+ *       ({@code org.apache.grails.gradle.grails-publish}) when it is applied.</li>
+ * </ul>
+ *
+ * Configure through the {@code cliArtifact} extension:
+ * <pre>
+ * cliArtifact {
+ *     automaticModuleName = 'com.example.myplugin.cli'
+ * }
+ * </pre>
+ *
+ * @since 8.0
+ */
+@CompileStatic
+abstract class GrailsCliArtifactGradlePlugin implements Plugin<Project> {
+
+    public static final String CLI_SOURCE_SET_NAME = 'cli'
+    public static final String CLI_COMPONENT_NAME = 'cli'
+    public static final String CLI_PUBLICATION_NAME = 'cli'
+
+    /** The runtime-jar manifest attribute advertising the companion cli coordinate */
+    public static final String CLI_ARTIFACT_MANIFEST_ATTRIBUTE = 'Grails-Cli-Artifact'
+
+    @Inject
+    abstract SoftwareComponentFactory getSoftwareComponentFactory()
+
+    @Override
+    void apply(Project project) {
+        if (!project.pluginManager.hasPlugin('java')) {
+            throw new GradleException("The Grails cli-artifact plugin requires the `java` plugin (or a plugin that applies it, e.g. the Grails plugin plugin) to be applied to project `${project.name}` first.")
+        }
+
+        CliArtifactExtension extension = project.extensions.create('cliArtifact', CliArtifactExtension)
+        extension.artifactId.convention(project.provider { "${project.name}-cli" as String })
+        extension.defaultDependencies.convention(true)
+
+        SourceSetContainer sourceSets = project.extensions.getByType(SourceSetContainer)
+        SourceSet cliSourceSet = sourceSets.create(CLI_SOURCE_SET_NAME)
+
+        JavaPluginExtension java = project.extensions.getByType(JavaPluginExtension)
+        java.registerFeature(CLI_SOURCE_SET_NAME) { spec ->
+            // no explicit capability: the default (`${group}:${project.name}-cli:${version}`)
+            // is derived lazily from the project and matches the published coordinate
+            spec.usingSourceSet(cliSourceSet)
+        }
+
+        Configuration cliApiElements = project.configurations.getByName('cliApiElements')
+        Configuration cliRuntimeElements = project.configurations.getByName('cliRuntimeElements')
+        Configuration cliRuntimeClasspath = project.configurations.getByName('cliRuntimeClasspath')
+
+        // commands compile out of the box: the contract plus the plugin's own runtime classes
+        // (computed lazily so `cliArtifact { defaultDependencies = false }` can opt out)
+        project.configurations.named('cliApi').configure { Configuration cliApi ->
+            cliApi.withDependencies { dependencies ->
+                if (extension.defaultDependencies.get()) {
+                    dependencies.add(project.dependencies.create(project))
+                    dependencies.add(project.dependencies.create('org.apache.grails:grails-core-cli'))
+                }
+            }
+        }
+
+        // exported for tooling that maps a project to its companion coordinate (e.g. the Grails
+        // Gradle plugin's discovery inside composite builds)
+        project.afterEvaluate {
+            project.extensions.extraProperties.set('cliArtifactId', extension.artifactId.get())
+        }
+
+        // the plugin's default publication must carry no trace of the cli tier
+        AdhocComponentWithVariants javaComponent = (AdhocComponentWithVariants) project.components.getByName('java')
+        javaComponent.withVariantsFromConfiguration(cliApiElements) { ConfigurationVariantDetails details ->
+            details.skip()
+        }
+        javaComponent.withVariantsFromConfiguration(cliRuntimeElements) { ConfigurationVariantDetails details ->
+            details.skip()
+        }
+
+        // expose the cli variants as their own software component / coordinate; the secondary
+        // classes/resources variants are build-local and must not be published
+        AdhocComponentWithVariants cliComponent = softwareComponentFactory.adhoc(CLI_COMPONENT_NAME)
+        project.components.add(cliComponent)
+        cliComponent.addVariantsFromConfiguration(cliApiElements) { ConfigurationVariantDetails details ->
+            if (hasDirectoryArtifacts(details)) {
+                details.skip()
+                return
+            }
+            details.mapToMavenScope('compile')
+            configureDependencyMapping(project, details, cliRuntimeClasspath)
+        }
+        cliComponent.addVariantsFromConfiguration(cliRuntimeElements) { ConfigurationVariantDetails details ->
+            if (hasDirectoryArtifacts(details)) {
+                details.skip()
+                return
+            }
+            details.mapToMavenScope('runtime')
+            configureDependencyMapping(project, details, cliRuntimeClasspath)
+        }
+
+        // the plugin's tests exercise the cli classes through their public API
+        SourceSet testSourceSet = sourceSets.findByName('test')
+        if (testSourceSet != null) {
+            testSourceSet.compileClasspath += cliSourceSet.output
+            testSourceSet.runtimeClasspath += cliSourceSet.output
+            project.configurations.named('testImplementation').configure { Configuration it ->
+                it.extendsFrom(project.configurations.getByName('cliApi'), project.configurations.getByName('cliImplementation'))
+            }
+        }
+        SourceSet integrationTestSourceSet = sourceSets.findByName('integrationTest')
+        if (integrationTestSourceSet != null) {
+            integrationTestSourceSet.compileClasspath += cliSourceSet.output
+            integrationTestSourceSet.runtimeClasspath += cliSourceSet.output
+            project.configurations.named('integrationTestImplementation').configure { Configuration it ->
+                it.extendsFrom(project.configurations.getByName('cliApi'), project.configurations.getByName('cliImplementation'))
+            }
+        }
+
+        project.tasks.named(cliSourceSet.jarTaskName, Jar).configure { Jar jar ->
+            // the jar is the primary artifact of its own coordinate — publish it unclassified
+            // (a `cli` classifier would leave the publication with pom packaging and no jar for
+            // Maven consumers); the base name keeps the local file distinct from the main jar
+            jar.archiveBaseName.set(extension.artifactId)
+            jar.archiveClassifier.set('')
+            jar.manifest.attributes('Automatic-Module-Name': extension.automaticModuleName.orElse(''))
+            jar.doFirst {
+                if (!extension.automaticModuleName.present) {
+                    jar.manifest.attributes.remove('Automatic-Module-Name')
+                }
+            }
+        }
+
+        // consuming applications discover the companion through this runtime-jar attribute
+        project.tasks.named('jar', Jar).configure { Jar jar ->
+            jar.manifest.attributes((CLI_ARTIFACT_MANIFEST_ATTRIBUTE): project.provider {
+                "${project.group}:${extension.artifactId.get()}" as String
+            })
+        }
+
+        project.pluginManager.withPlugin('org.apache.grails.gradle.grails-publish') {
+            project.extensions.configure(GrailsPublishExtension) { GrailsPublishExtension gpe ->
+                gpe.additionalPublication(CLI_PUBLICATION_NAME) { AdditionalPublication publication ->
+                    publication.artifactId.set(extension.artifactId)
+                }
+            }
+        }
+        project.afterEvaluate {
+            if (!project.pluginManager.hasPlugin('org.apache.grails.gradle.grails-publish')
+                    && project.pluginManager.hasPlugin('maven-publish')) {
+                project.logger.warn('Project {} publishes a cli companion artifact but does not apply the Grails publish plugin (org.apache.grails.gradle.grails-publish). Apply it to publish `{}` automatically, or configure a publication for the `cli` component manually.',
+                        project.name, extension.artifactId.get())
+            }
+        }
+    }
+
+    /**
+     * Publish resolved variant-level coordinates for the cli variants so a dependency on another
+     * project's cli tier (declared with a capability inside a composite build) lands in the pom as
+     * the `-cli` coordinate rather than the primary one, which Maven consumers could not follow.
+     *
+     * Dependency mapping has not been promoted to Gradle's public API yet — it is only reachable
+     * via {@code ConfigurationVariantDetailsInternal}; fall back silently when the internal
+     * contract changes. Revisit when https://github.com/gradle/gradle/issues/26163 stabilizes.
+     */
+    @CompileDynamic
+    private static void configureDependencyMapping(Project project, ConfigurationVariantDetails details, Configuration cliRuntimeClasspath) {
+        try {
+            details.dependencyMapping {
+                it.publishResolvedCoordinates.set(true)
+                it.fromResolutionOf(cliRuntimeClasspath)
+            }
+        }
+        catch (Throwable e) {
+            project.logger.info('Dependency mapping is unavailable on this Gradle version; cli variant poms will record component-level coordinates.', e)
+        }
+    }
+
+    /**
+     * The secondary classes/resources variants of the elements configurations carry directory
+     * artifacts — they exist for local inter-project consumption only and must not be published.
+     */
+    private static boolean hasDirectoryArtifacts(ConfigurationVariantDetails details) {
+        details.configurationVariant.artifacts.any { PublishArtifact artifact ->
+            artifact.type in ['java-classes-directory', 'java-resources-directory', 'directory']
+        }
+    }
+}
diff --git a/grails-gradle/plugins/src/main/groovy/org/grails/gradle/plugin/core/GrailsExtension.groovy b/grails-gradle/plugins/src/main/groovy/org/grails/gradle/plugin/core/GrailsExtension.groovy
index 17364768d0..216f5bf83e 100644
--- a/grails-gradle/plugins/src/main/groovy/org/grails/gradle/plugin/core/GrailsExtension.groovy
+++ b/grails-gradle/plugins/src/main/groovy/org/grails/gradle/plugin/core/GrailsExtension.groovy
@@ -30,7 +30,6 @@ import grails.util.Environment
 /**
  * A extension to the Gradle plugin to configure Grails settings
  *
- * @author Graeme Rocher
  * @since 3.0
  */
 @CompileStatic
@@ -51,6 +50,10 @@ class GrailsExtension {
         this.indy = project.objects.property(Boolean).convention(false)
         this.preserveParameterNames = project.objects.property(Boolean).convention(true)
         this.compileStatic = project.objects.newInstance(GrailsCompileStaticOptions)
+        this.cliAutoProvision = project.objects.property(Boolean).convention(project.provider {
+            def fromProperty = project.findProperty('grailsCliAutoProvision')
+            fromProperty == null ? Boolean.TRUE : Boolean.parseBoolean(fromProperty as String)
+        })
         this.bom = project.objects.property(String)
         // Use set() rather than convention() so that clearing the value (bom = null,
         // or the deprecated springDependencyManagement = false) results in no BOM being
@@ -58,6 +61,19 @@ class GrailsExtension {
         this.bom.set(DEFAULT_BOM)
     }
 
+    /**
+     * Whether the plugin auto-provisions the CLI tier onto the {@code grailsCli} configuration.
+     * When enabled (the default), the plugin adds {@code org.apache.grails:grails-core-cli} (the
+     * command contract) and {@code org.apache.grails:grails-console} (the command runner), and
+     * discovers every companion {@code -cli} artifact advertised by the application's dependency
+     * graph — a plugin advertises its companion through the {@code Grails-Cli-Artifact} manifest
+     * attribute of its runtime jar. Plugin commands (e.g. the {@code dbm-*} or scaffolding
+     * commands) therefore work with no additional build configuration. Opt out with
+     * {@code grails { cliAutoProvision = false }} (or the {@code grailsCliAutoProvision} project
+     * property) and declare `grailsCli` dependencies explicitly.
+     */
+    final Property<Boolean> cliAutoProvision
+
     /**
      * Whether to invoke native2ascii on resource bundles
      */
diff --git a/grails-gradle/plugins/src/main/groovy/org/grails/gradle/plugin/core/GrailsGradlePlugin.groovy b/grails-gradle/plugins/src/main/groovy/org/grails/gradle/plugin/core/GrailsGradlePlugin.groovy
index 21f8d5e1de..d2ce2ccc33 100644
--- a/grails-gradle/plugins/src/main/groovy/org/grails/gradle/plugin/core/GrailsGradlePlugin.groovy
+++ b/grails-gradle/plugins/src/main/groovy/org/grails/gradle/plugin/core/GrailsGradlePlugin.groovy
@@ -18,6 +18,7 @@
  */
 package org.grails.gradle.plugin.core
 
+import java.util.jar.JarFile
 import java.util.zip.ZipFile
 
 import grails.util.BuildSettings
@@ -37,9 +38,12 @@ import org.gradle.api.Plugin
 import org.gradle.api.Project
 import org.gradle.api.Task
 import org.gradle.api.artifacts.Configuration
+import org.gradle.api.artifacts.ConfigurationContainer
 import org.gradle.api.artifacts.Dependency
 import org.gradle.api.artifacts.DependencyResolveDetails
 import org.gradle.api.artifacts.DependencySet
+import org.gradle.api.artifacts.result.ResolvedArtifactResult
+import org.gradle.api.artifacts.component.ProjectComponentIdentifier
 import org.gradle.api.artifacts.ModuleDependency
 import org.gradle.api.attributes.AttributeMatchingStrategy
 import org.gradle.api.attributes.Category
@@ -84,15 +88,35 @@ import javax.inject.Inject
  * The main Grails gradle plugin implementation
  *
  * @since 3.0
- * @author Graeme Rocher
  */
 @CompileStatic
 class GrailsGradlePlugin implements Plugin<Project> {
 
-    public static final String APPLICATION_CONTEXT_COMMAND_CLASS = 'grails.dev.commands.ApplicationCommand'
+    public static final String APPLICATION_CONTEXT_COMMAND_CLASS = 'org.apache.grails.core.cli.ApplicationCommand'
     private static final String CLI_PID_FILE_PROPERTY = 'grails.cli.pid.file'
     private static final String RUN_APP_PID_FILE_NAME = 'run-app.pid'
 
+    /**
+     * The dependency bucket carrying CLI-only dependencies (Grails commands and their libraries):
+     * compile-visible so `grails-app/commands` sources compile against the cli-only contract, on
+     * the command-runner classpath, but never on `runtimeClasspath`, `bootRun`, or packaged
+     * artifacts.
+     */
+    public static final String GRAILS_CLI_CONFIGURATION = 'grailsCli'
+
+    /** The resolvable view of {@link #GRAILS_CLI_CONFIGURATION} used by the command-runner tasks */
+    public static final String GRAILS_CLI_CLASSPATH_CONFIGURATION = 'grailsCliClasspath'
+
+    /**
+     * Set this project property to {@code false} to stop the plugin from auto-provisioning the
+     * CLI tier onto {@link #GRAILS_CLI_CONFIGURATION}; equivalent to
+     * {@code grails { cliAutoProvision = false }}.
+     */
+    public static final String GRAILS_CLI_AUTO_PROVISION_PROPERTY = 'grailsCliAutoProvision'
+
+    /** The internal probe configuration used to detect companion `-cli` modules */
+    public static final String GRAILS_CLI_DETECT_CONFIGURATION = 'grailsCliDetect'
+
     List<Class<Plugin>> basePluginClasses = [IntegrationTestGradlePlugin] as List<Class<Plugin>>
     List<String> excludedGrailsAppSourceDirs = ['migrations', 'assets']
     List<String> grailsAppResourceDirs = ['views', 'i18n', 'conf', 'migrations']
@@ -143,6 +167,8 @@ class GrailsGradlePlugin implements Plugin<Project> {
 
         configureConsoleTask(project)
 
+        configureGrailsCliConfiguration(project)
+
         configureForkSettings(project, grailsVersion)
 
         configureBootRunPidFile(project)
@@ -740,6 +766,133 @@ ${importStatements}
         }
     }
 
+    /**
+     * Registers the `grailsCli` dependency bucket and its resolvable `grailsCliClasspath` view.
+     * `grailsCli` carries the CLI tier — command companion artifacts (`<artifactId>-cli`) and the
+     * libraries they need. It extends the compile classpaths (the same wiring `compileOnly` uses)
+     * so `grails-app/commands` sources compile against the cli-only contract, while staying off
+     * `runtimeClasspath` — and therefore out of `bootRun`, `bootJar`, and `bootWar`.
+     */
+    protected void configureGrailsCliConfiguration(Project project) {
+        ConfigurationContainer configurations = project.configurations
+        if (configurations.names.contains(GRAILS_CLI_CONFIGURATION)) {
+            return
+        }
+
+        Configuration grailsCli = configurations.create(GRAILS_CLI_CONFIGURATION)
+        grailsCli.canBeResolved = false
+        grailsCli.canBeConsumed = false
+        grailsCli.description = 'CLI-only dependencies (Grails commands and the libraries they need); compile-visible and on the command-runner classpath, but never on runtimeClasspath, bootRun, or packaged artifacts.'
+
+        // compile visibility for grails-app/commands sources plus the TEST classpaths (tests
+        // exercise commands inside the test JVM), while the main runtimeClasspath — and therefore
+        // bootRun, bootJar, and bootWar — never sees the cli tier; matching configurations that
+        // appear later (e.g. the integrationTest pair) are included as they are created
+        configurations.matching { Configuration it ->
+            it.name in ['compileClasspath', 'testCompileClasspath', 'testRuntimeClasspath',
+                        'integrationTestCompileClasspath', 'integrationTestRuntimeClasspath']
+        }.configureEach { Configuration it ->
+            it.extendsFrom(grailsCli)
+        }
+
+        Configuration grailsCliClasspath = configurations.create(GRAILS_CLI_CLASSPATH_CONFIGURATION)
+        grailsCliClasspath.extendsFrom(grailsCli)
+        grailsCliClasspath.canBeResolved = true
+        grailsCliClasspath.canBeConsumed = false
+        grailsCliClasspath.description = 'Resolvable view of grailsCli used by the command-runner tasks.'
+
+        Configuration grailsCliDetect = configurations.create(GRAILS_CLI_DETECT_CONFIGURATION)
+        grailsCliDetect.canBeResolved = true
+        grailsCliDetect.canBeConsumed = false
+        grailsCliDetect.visible = false
+        grailsCliDetect.description = 'Internal probe used to discover companion -cli artifacts advertised by dependencies.'
+        for (String bucket : ['api', 'implementation', 'runtimeOnly']) {
+            configurations.matching { Configuration it -> it.name == bucket }.configureEach { Configuration it ->
+                grailsCliDetect.extendsFrom(it)
+            }
+        }
+
+        // computed when the configuration is first resolved, so every dependency (and the
+        // extension configuration) declared by the build script is visible
+        grailsCli.withDependencies { DependencySet dependencies ->
+            autoProvisionCliDependencies(project, dependencies)
+        }
+    }
+
+    /**
+     * Auto-provisions the CLI tier onto {@code grailsCli}: the command contract and runner, plus
+     * every companion {@code -cli} artifact advertised by a dependency of the application. A
+     * module advertises its companion through the {@code Grails-Cli-Artifact} manifest attribute
+     * of its runtime jar (stamped by the framework's cli-artifact build convention; third-party
+     * plugins set it on their jar task). Discovery walks the full dependency graph (including
+     * transitive plugins) through a lenient resolution of an internal probe configuration.
+     * Disable with {@code grails { cliAutoProvision = false }}.
+     */
+    @CompileDynamic
+    protected void autoProvisionCliDependencies(Project project, DependencySet dependencies) {
+        GrailsExtension grails = project.extensions.getByType(GrailsExtension)
+        if (!grails.cliAutoProvision.get()) {
+            return
+        }
+
+        // command authoring and execution work out of the box: the command contract + the runner
+        dependencies.add(project.dependencies.create('org.apache.grails:grails-core-cli'))
+        dependencies.add(project.dependencies.create('org.apache.grails:grails-console'))
+
+        Configuration probe = project.configurations.getByName(GRAILS_CLI_DETECT_CONFIGURATION)
+        Set<String> companions = [] as Set
+        def lenientArtifacts = probe.incoming.artifactView { it.lenient(true) }.artifacts
+        for (ResolvedArtifactResult artifact : lenientArtifacts.artifacts) {
+            String companion = findAdvertisedCliArtifact(project, artifact)
+            if (companion) {
+                companions.add(companion)
+            }
+        }
+
+        for (String companion : companions) {
+            List<String> coordinate = companion.tokenize(':')
+            if (coordinate.size() != 2) {
+                project.logger.warn('Ignoring malformed Grails-Cli-Artifact value [{}] found in the dependencies of project {}', companion, project.name)
+                continue
+            }
+            boolean alreadyDeclared = dependencies.any { Dependency existing ->
+                existing.group == coordinate[0] && existing.name == coordinate[1]
+            }
+            if (!alreadyDeclared) {
+                project.logger.info('Detected cli companion artifact {}, adding it to the {} configuration of project {}',
+                        companion, GRAILS_CLI_CONFIGURATION, project.name)
+                dependencies.add(project.dependencies.create(companion))
+            }
+        }
+    }
+
+    /**
+     * Returns the companion cli coordinate ({@code group:artifactId}) advertised by the given
+     * resolved artifact, or {@code null}. For artifacts produced by a project of the same build
+     * the (possibly not yet built) jar is not read — the coordinate comes from the project's
+     * {@code cliArtifactId} property exported by the cli-artifact convention.
+     */
+    @CompileDynamic
+    protected String findAdvertisedCliArtifact(Project project, ResolvedArtifactResult artifact) {
+        def componentIdentifier = artifact.id.componentIdentifier
+        if (componentIdentifier instanceof ProjectComponentIdentifier) {
+            Project target = project.rootProject.findProject(((ProjectComponentIdentifier) componentIdentifier).projectPath)
+            def cliArtifactId = target?.findProperty('cliArtifactId')
+            return cliArtifactId ? "${target.group}:${cliArtifactId}" as String : null
+        }
+
+        File file = artifact.file
+        if (file == null || !file.isFile() || !file.name.endsWith('.jar')) {
+            return null
+        }
+        try (JarFile jarFile = new JarFile(file)) {
+            return jarFile.manifest?.mainAttributes?.getValue('Grails-Cli-Artifact')
+        }
+        catch (IOException ignored) {
+            return null
+        }
+    }
+
     protected GrailsExtension registerGrailsExtension(Project project) {
         if (project.extensions.findByName('grails') == null) {
             project.extensions.create('grails', GrailsExtension, project)
@@ -748,10 +901,22 @@ ${importStatements}
 
     @CompileDynamic
     protected void configureApplicationCommands(Project project) {
-        def applicationContextCommands = FactoriesLoaderSupport.loadFactoryNames(APPLICATION_CONTEXT_COMMAND_CLASS)
+        def applicationContextCommands = FactoriesLoaderSupport.loadFactoryNames(APPLICATION_CONTEXT_COMMAND_CLASS,
+                FactoriesLoaderSupport.classLoader, FactoriesLoaderSupport.CLI_FACTORIES_RESOURCE_LOCATION)
         project.afterEvaluate {
-            FileCollection fileCollection = buildClasspath(project, project.configurations.runtimeClasspath, project.configurations.console)
-            for (ctxCommand in applicationContextCommands) {
+            FileCollection fileCollection = buildClasspath(project, project.configurations.runtimeClasspath, project.configurations.grailsCliClasspath)
+            // commands come from the buildscript classloader (legacy placement) and from the
+            // project's cli tier, so auto-provisioned command artifacts register their tasks
+            // without any buildscript classpath entry
+            Set<String> commandClassNames = new LinkedHashSet<String>()
+            if (applicationContextCommands) {
+                commandClassNames.addAll(applicationContextCommands as List)
+            }
+            GrailsExtension grails = project.extensions.getByType(GrailsExtension)
+            if (grails.cliAutoProvision.get()) {
+                commandClassNames.addAll(loadCommandNamesFromCliClasspath(project))
+            }
+            for (ctxCommand in commandClassNames) {
                 String taskName = GrailsNameUtils.getLogicalPropertyName(ctxCommand, 'Command')
                 String commandName = GrailsNameUtils.getScriptName(GrailsNameUtils.getLogicalName(ctxCommand, 'Command'))
                 if (!project.tasks.names.contains(taskName)) {
@@ -777,6 +942,45 @@ ${importStatements}
         }
     }
 
+    /**
+     * Loads command class names from the {@code META-INF/grails-cli.factories} files of the
+     * resolved {@code grailsCliClasspath} jars, so per-command Gradle tasks (e.g. {@code dbmUpdate})
+     * are registered for auto-provisioned cli artifacts. Resolution is lenient and jars that are
+     * not built yet (project dependencies within a composite) are skipped — the generic
+     * {@code runCommand} task can always execute those commands regardless.
+     */
+    @CompileDynamic
+    protected Collection<String> loadCommandNamesFromCliClasspath(Project project) {
+        Set<String> names = new LinkedHashSet<String>()
+        Configuration cliClasspath = project.configurations.findByName(GRAILS_CLI_CLASSPATH_CONFIGURATION)
+        if (cliClasspath == null) {
+            return names
+        }
+        for (File file : cliClasspath.incoming.artifactView { it.lenient(true) }.files) {
+            if (!file.isFile() || !file.name.endsWith('.jar')) {
+                continue
+            }
+            try (JarFile jarFile = new JarFile(file)) {
+                def entry = jarFile.getEntry(FactoriesLoaderSupport.CLI_FACTORIES_RESOURCE_LOCATION)
+                if (entry == null) {
+                    continue
+                }
+                Properties properties = new Properties()
+                jarFile.getInputStream(entry).withCloseable { input ->
+                    properties.load(input)
+                }
+                String factoryNames = properties.getProperty(APPLICATION_CONTEXT_COMMAND_CLASS)
+                if (factoryNames) {
+                    names.addAll(factoryNames.split(',').toList()*.trim())
+                }
+            }
+            catch (IOException ignored) {
+                // unreadable jar — skip
+            }
+        }
+        names
+    }
+
     @CompileDynamic
     protected void configureGrailsSourceDirs(Project project) {
         project.sourceSets {
@@ -1240,7 +1444,7 @@ ${importStatements}
             project.afterEvaluate {
                 runTask.configure {
                     SourceSet mainSourceSet = SourceSets.findMainSourceSet(project)
-                    it.classpath = mainSourceSet.runtimeClasspath + project.configurations.getByName('console')
+                    it.classpath = mainSourceSet.runtimeClasspath + project.configurations.getByName(GRAILS_CLI_CLASSPATH_CONFIGURATION)
                     it.systemProperty(Environment.KEY, System.getProperty(Environment.KEY, Environment.DEVELOPMENT.getName()))
 
                     // devtools' automatic restart mechanism uses a specialized classloader setup, which can interfere
@@ -1271,7 +1475,7 @@ ${importStatements}
             project.afterEvaluate {
                 runTask.configure {
                     SourceSet mainSourceSet = SourceSets.findMainSourceSet(project)
-                    it.classpath = mainSourceSet.runtimeClasspath + project.configurations.getByName('console')
+                    it.classpath = mainSourceSet.runtimeClasspath + project.configurations.getByName(GRAILS_CLI_CLASSPATH_CONFIGURATION)
                     it.systemProperty(Environment.KEY, System.getProperty(Environment.KEY, Environment.DEVELOPMENT.getName()))
 
                     // devtools' automatic restart mechanism uses a specialized classloader setup, which can interfere
diff --git a/grails-profiles/base/templates/artifacts/Command.groovy b/grails-profiles/base/templates/artifacts/Command.groovy
index 7ded69dc21..9a9b2d6af8 100644
--- a/grails-profiles/base/templates/artifacts/Command.groovy
+++ b/grails-profiles/base/templates/artifacts/Command.groovy
@@ -1,6 +1,6 @@
 @artifact.package@
 
-import grails.dev.commands.*
+import org.apache.grails.core.cli.*
 
 class @artifact.name@Command implements GrailsApplicationCommand {
 
diff --git a/grails-scaffolding/build.gradle b/grails-scaffolding/build.gradle
index c6e1a87c71..f05e3ff23e 100644
--- a/grails-scaffolding/build.gradle
+++ b/grails-scaffolding/build.gradle
@@ -22,6 +22,7 @@ plugins {
     id 'org.apache.grails.buildsrc.properties'
     id 'org.apache.grails.buildsrc.dependency-validator'
     id 'org.apache.grails.gradle.grails-plugin'
+    id 'org.apache.grails.gradle.grails-plugin-cli'
     id 'org.apache.grails.gradle.grails-gsp'
     id 'org.apache.grails.buildsrc.compile'
     id 'org.apache.grails.buildsrc.publish'
@@ -34,6 +35,13 @@ plugins {
 version = projectVersion
 group = 'org.apache.grails'
 
+cliArtifact {
+    automaticModuleName = 'org.apache.grails.scaffolding.cli'
+    // this framework module wires its cli dependencies with project dependencies below
+    defaultDependencies = false
+}
+
+
 ext {
     pomTitle = 'Grails Scaffolding Plugin'
     pomDescription = 'Provides scaffolding for Grails applications'
@@ -41,6 +49,18 @@ ext {
 
 dependencies {
     implementation platform(project(':grails-bom'))
+
+    // the cli tier — published separately as a companion -cli artifact
+    cliImplementation platform(project(':grails-bom'))
+    cliApi project(project.path)
+    cliApi(project(':grails-core')) {
+        capabilities {
+            requireCapability('org.apache.grails:grails-core-cli')
+        }
+    }
+    // GrailsConsole (used by the scaffolding commands) needs jline at compile time
+    cliImplementation 'org.jline:jline'
+    cliImplementation 'org.fusesource.jansi:jansi'
     api project(':grails-fields')
     api project(':grails-rest-transforms')
 
diff --git a/grails-scaffolding/src/main/groovy/grails/plugin/scaffolding/CommandLineHelper.groovy b/grails-scaffolding/src/cli/groovy/org/apache/grails/scaffolding/cli/CommandLineHelper.groovy
similarity index 94%
rename from grails-scaffolding/src/main/groovy/grails/plugin/scaffolding/CommandLineHelper.groovy
rename to grails-scaffolding/src/cli/groovy/org/apache/grails/scaffolding/cli/CommandLineHelper.groovy
index 9ace02ac0d..9d363c6baf 100644
--- a/grails-scaffolding/src/main/groovy/grails/plugin/scaffolding/CommandLineHelper.groovy
+++ b/grails-scaffolding/src/cli/groovy/org/apache/grails/scaffolding/cli/CommandLineHelper.groovy
@@ -17,9 +17,9 @@
  *  under the License.
  */
 
-package grails.plugin.scaffolding
+package org.apache.grails.scaffolding.cli
 
-import grails.dev.commands.ExecutionContext
+import org.apache.grails.core.cli.ExecutionContext
 import org.grails.build.parsing.CommandLine
 
 trait CommandLineHelper {
diff --git a/grails-scaffolding/grails-app/commands/scaffolding/CreateScaffoldControllerCommand.groovy b/grails-scaffolding/src/cli/groovy/org/apache/grails/scaffolding/cli/CreateScaffoldControllerCommand.groovy
similarity index 94%
rename from grails-scaffolding/grails-app/commands/scaffolding/CreateScaffoldControllerCommand.groovy
rename to grails-scaffolding/src/cli/groovy/org/apache/grails/scaffolding/cli/CreateScaffoldControllerCommand.groovy
index 6679d5c588..3f15abc85f 100644
--- a/grails-scaffolding/grails-app/commands/scaffolding/CreateScaffoldControllerCommand.groovy
+++ b/grails-scaffolding/src/cli/groovy/org/apache/grails/scaffolding/cli/CreateScaffoldControllerCommand.groovy
@@ -16,16 +16,14 @@
  *  specific language governing permissions and limitations
  *  under the License.
  */
-package scaffolding
+package org.apache.grails.scaffolding.cli
 
 import groovy.transform.CompileStatic
 
 import grails.build.logging.ConsoleLogger
 import grails.build.logging.GrailsConsole
 import grails.codegen.model.Model
-import grails.dev.commands.GrailsApplicationCommand
-import grails.plugin.scaffolding.CommandLineHelper
-import grails.plugin.scaffolding.SkipBootstrap
+import org.apache.grails.core.cli.GrailsApplicationCommand
 import org.grails.io.support.Resource
 
 /**
diff --git a/grails-scaffolding/grails-app/commands/scaffolding/CreateScaffoldServiceCommand.groovy b/grails-scaffolding/src/cli/groovy/org/apache/grails/scaffolding/cli/CreateScaffoldServiceCommand.groovy
similarity index 93%
rename from grails-scaffolding/grails-app/commands/scaffolding/CreateScaffoldServiceCommand.groovy
rename to grails-scaffolding/src/cli/groovy/org/apache/grails/scaffolding/cli/CreateScaffoldServiceCommand.groovy
index 62ba9f8226..f24e6c10cb 100644
--- a/grails-scaffolding/grails-app/commands/scaffolding/CreateScaffoldServiceCommand.groovy
+++ b/grails-scaffolding/src/cli/groovy/org/apache/grails/scaffolding/cli/CreateScaffoldServiceCommand.groovy
@@ -16,16 +16,14 @@
  *  specific language governing permissions and limitations
  *  under the License.
  */
-package scaffolding
+package org.apache.grails.scaffolding.cli
 
 import groovy.transform.CompileStatic
 
 import grails.build.logging.ConsoleLogger
 import grails.build.logging.GrailsConsole
 import grails.codegen.model.Model
-import grails.dev.commands.GrailsApplicationCommand
-import grails.plugin.scaffolding.CommandLineHelper
-import grails.plugin.scaffolding.SkipBootstrap
+import org.apache.grails.core.cli.GrailsApplicationCommand
 import org.grails.io.support.Resource
 
 /**
diff --git a/grails-scaffolding/grails-app/commands/scaffolding/GenerateAllCommand.groovy b/grails-scaffolding/src/cli/groovy/org/apache/grails/scaffolding/cli/GenerateAllCommand.groovy
similarity index 91%
rename from grails-scaffolding/grails-app/commands/scaffolding/GenerateAllCommand.groovy
rename to grails-scaffolding/src/cli/groovy/org/apache/grails/scaffolding/cli/GenerateAllCommand.groovy
index 8bcf0f2b28..37edc83088 100644
--- a/grails-scaffolding/grails-app/commands/scaffolding/GenerateAllCommand.groovy
+++ b/grails-scaffolding/src/cli/groovy/org/apache/grails/scaffolding/cli/GenerateAllCommand.groovy
@@ -16,15 +16,13 @@
  *  specific language governing permissions and limitations
  *  under the License.
  */
-package scaffolding
+package org.apache.grails.scaffolding.cli
 
 import groovy.transform.CompileStatic
 
 import grails.build.logging.ConsoleLogger
 import grails.build.logging.GrailsConsole
-import grails.dev.commands.GrailsApplicationCommand
-import grails.plugin.scaffolding.CommandLineHelper
-import grails.plugin.scaffolding.SkipBootstrap
+import org.apache.grails.core.cli.GrailsApplicationCommand
 
 /**
  * Generates a controller that performs CRUD operations and the associated views
diff --git a/grails-scaffolding/grails-app/commands/scaffolding/GenerateAsyncControllerCommand.groovy b/grails-scaffolding/src/cli/groovy/org/apache/grails/scaffolding/cli/GenerateAsyncControllerCommand.groovy
similarity index 94%
rename from grails-scaffolding/grails-app/commands/scaffolding/GenerateAsyncControllerCommand.groovy
rename to grails-scaffolding/src/cli/groovy/org/apache/grails/scaffolding/cli/GenerateAsyncControllerCommand.groovy
index 2ce5664297..6c92bb30d8 100644
--- a/grails-scaffolding/grails-app/commands/scaffolding/GenerateAsyncControllerCommand.groovy
+++ b/grails-scaffolding/src/cli/groovy/org/apache/grails/scaffolding/cli/GenerateAsyncControllerCommand.groovy
@@ -16,16 +16,14 @@
  *  specific language governing permissions and limitations
  *  under the License.
  */
-package scaffolding
+package org.apache.grails.scaffolding.cli
 
 import groovy.transform.CompileStatic
 
 import grails.build.logging.ConsoleLogger
 import grails.build.logging.GrailsConsole
 import grails.codegen.model.Model
-import grails.dev.commands.GrailsApplicationCommand
-import grails.plugin.scaffolding.CommandLineHelper
-import grails.plugin.scaffolding.SkipBootstrap
+import org.apache.grails.core.cli.GrailsApplicationCommand
 import org.grails.io.support.Resource
 
 /**
diff --git a/grails-scaffolding/grails-app/commands/scaffolding/GenerateControllerCommand.groovy b/grails-scaffolding/src/cli/groovy/org/apache/grails/scaffolding/cli/GenerateControllerCommand.groovy
similarity index 95%
rename from grails-scaffolding/grails-app/commands/scaffolding/GenerateControllerCommand.groovy
rename to grails-scaffolding/src/cli/groovy/org/apache/grails/scaffolding/cli/GenerateControllerCommand.groovy
index 6c4c3878f6..f9e16263ae 100644
--- a/grails-scaffolding/grails-app/commands/scaffolding/GenerateControllerCommand.groovy
+++ b/grails-scaffolding/src/cli/groovy/org/apache/grails/scaffolding/cli/GenerateControllerCommand.groovy
@@ -16,16 +16,14 @@
  *  specific language governing permissions and limitations
  *  under the License.
  */
-package scaffolding
+package org.apache.grails.scaffolding.cli
 
 import groovy.transform.CompileStatic
 
 import grails.build.logging.ConsoleLogger
 import grails.build.logging.GrailsConsole
 import grails.codegen.model.Model
-import grails.dev.commands.GrailsApplicationCommand
-import grails.plugin.scaffolding.CommandLineHelper
-import grails.plugin.scaffolding.SkipBootstrap
+import org.apache.grails.core.cli.GrailsApplicationCommand
 import org.grails.io.support.Resource
 
 /**
diff --git a/grails-scaffolding/grails-app/commands/scaffolding/GenerateScaffoldAllCommand.groovy b/grails-scaffolding/src/cli/groovy/org/apache/grails/scaffolding/cli/GenerateScaffoldAllCommand.groovy
similarity index 95%
rename from grails-scaffolding/grails-app/commands/scaffolding/GenerateScaffoldAllCommand.groovy
rename to grails-scaffolding/src/cli/groovy/org/apache/grails/scaffolding/cli/GenerateScaffoldAllCommand.groovy
index 53f2a6f504..38cc651a11 100644
--- a/grails-scaffolding/grails-app/commands/scaffolding/GenerateScaffoldAllCommand.groovy
+++ b/grails-scaffolding/src/cli/groovy/org/apache/grails/scaffolding/cli/GenerateScaffoldAllCommand.groovy
@@ -16,16 +16,14 @@
  *  specific language governing permissions and limitations
  *  under the License.
  */
-package scaffolding
+package org.apache.grails.scaffolding.cli
 
 import groovy.transform.CompileStatic
 
 import grails.build.logging.ConsoleLogger
 import grails.build.logging.GrailsConsole
 import grails.codegen.model.Model
-import grails.dev.commands.GrailsApplicationCommand
-import grails.plugin.scaffolding.CommandLineHelper
-import grails.plugin.scaffolding.SkipBootstrap
+import org.apache.grails.core.cli.GrailsApplicationCommand
 import org.grails.io.support.Resource
 
 /**
diff --git a/grails-scaffolding/grails-app/commands/scaffolding/GenerateServiceCommand.groovy b/grails-scaffolding/src/cli/groovy/org/apache/grails/scaffolding/cli/GenerateServiceCommand.groovy
similarity index 93%
rename from grails-scaffolding/grails-app/commands/scaffolding/GenerateServiceCommand.groovy
rename to grails-scaffolding/src/cli/groovy/org/apache/grails/scaffolding/cli/GenerateServiceCommand.groovy
index 7d662ae3b8..6c28cc714c 100644
--- a/grails-scaffolding/grails-app/commands/scaffolding/GenerateServiceCommand.groovy
+++ b/grails-scaffolding/src/cli/groovy/org/apache/grails/scaffolding/cli/GenerateServiceCommand.groovy
@@ -16,16 +16,14 @@
  *  specific language governing permissions and limitations
  *  under the License.
  */
-package scaffolding
+package org.apache.grails.scaffolding.cli
 
 import groovy.transform.CompileStatic
 
 import grails.build.logging.ConsoleLogger
 import grails.build.logging.GrailsConsole
 import grails.codegen.model.Model
-import grails.dev.commands.GrailsApplicationCommand
-import grails.plugin.scaffolding.CommandLineHelper
-import grails.plugin.scaffolding.SkipBootstrap
+import org.apache.grails.core.cli.GrailsApplicationCommand
 import org.grails.io.support.Resource
 
 /**
diff --git a/grails-scaffolding/grails-app/commands/scaffolding/GenerateViewsCommand.groovy b/grails-scaffolding/src/cli/groovy/org/apache/grails/scaffolding/cli/GenerateViewsCommand.groovy
similarity index 94%
rename from grails-scaffolding/grails-app/commands/scaffolding/GenerateViewsCommand.groovy
rename to grails-scaffolding/src/cli/groovy/org/apache/grails/scaffolding/cli/GenerateViewsCommand.groovy
index e9ef14cc02..3be3c1a5ab 100644
--- a/grails-scaffolding/grails-app/commands/scaffolding/GenerateViewsCommand.groovy
+++ b/grails-scaffolding/src/cli/groovy/org/apache/grails/scaffolding/cli/GenerateViewsCommand.groovy
@@ -16,16 +16,14 @@
  *  specific language governing permissions and limitations
  *  under the License.
  */
-package scaffolding
+package org.apache.grails.scaffolding.cli
 
 import groovy.transform.CompileStatic
 
 import grails.build.logging.ConsoleLogger
 import grails.build.logging.GrailsConsole
 import grails.codegen.model.Model
-import grails.dev.commands.GrailsApplicationCommand
-import grails.plugin.scaffolding.CommandLineHelper
-import grails.plugin.scaffolding.SkipBootstrap
+import org.apache.grails.core.cli.GrailsApplicationCommand
 import org.grails.io.support.Resource
 
 /**
diff --git a/grails-scaffolding/grails-app/commands/scaffolding/InstallTemplatesCommand.groovy b/grails-scaffolding/src/cli/groovy/org/apache/grails/scaffolding/cli/InstallTemplatesCommand.groovy
similarity index 93%
rename from grails-scaffolding/grails-app/commands/scaffolding/InstallTemplatesCommand.groovy
rename to grails-scaffolding/src/cli/groovy/org/apache/grails/scaffolding/cli/InstallTemplatesCommand.groovy
index b39aa9a72c..6fd2a9a836 100644
--- a/grails-scaffolding/grails-app/commands/scaffolding/InstallTemplatesCommand.groovy
+++ b/grails-scaffolding/src/cli/groovy/org/apache/grails/scaffolding/cli/InstallTemplatesCommand.groovy
@@ -16,15 +16,13 @@
  *  specific language governing permissions and limitations
  *  under the License.
  */
-package scaffolding
+package org.apache.grails.scaffolding.cli
 
 import groovy.transform.CompileStatic
 
 import grails.build.logging.ConsoleLogger
 import grails.build.logging.GrailsConsole
-import grails.dev.commands.GrailsApplicationCommand
-import grails.plugin.scaffolding.CommandLineHelper
-import grails.plugin.scaffolding.SkipBootstrap
+import org.apache.grails.core.cli.GrailsApplicationCommand
 import org.grails.io.support.Resource
 import org.grails.io.support.SpringIOUtils
 
diff --git a/grails-scaffolding/src/main/groovy/grails/plugin/scaffolding/SkipBootstrap.groovy b/grails-scaffolding/src/cli/groovy/org/apache/grails/scaffolding/cli/SkipBootstrap.groovy
similarity index 95%
rename from grails-scaffolding/src/main/groovy/grails/plugin/scaffolding/SkipBootstrap.groovy
rename to grails-scaffolding/src/cli/groovy/org/apache/grails/scaffolding/cli/SkipBootstrap.groovy
index 3c846d6087..edad644699 100644
--- a/grails-scaffolding/src/main/groovy/grails/plugin/scaffolding/SkipBootstrap.groovy
+++ b/grails-scaffolding/src/cli/groovy/org/apache/grails/scaffolding/cli/SkipBootstrap.groovy
@@ -17,7 +17,7 @@
  *  under the License.
  */
 
-package grails.plugin.scaffolding
+package org.apache.grails.scaffolding.cli
 
 trait SkipBootstrap {
 
diff --git a/grails-shell-cli/src/main/groovy/org/grails/cli/profile/commands/factory/ApplicationContextCommandFactory.groovy b/grails-shell-cli/src/main/groovy/org/grails/cli/profile/commands/factory/ApplicationContextCommandFactory.groovy
index a6dd5f964d..c709fd8577 100644
--- a/grails-shell-cli/src/main/groovy/org/grails/cli/profile/commands/factory/ApplicationContextCommandFactory.groovy
+++ b/grails-shell-cli/src/main/groovy/org/grails/cli/profile/commands/factory/ApplicationContextCommandFactory.groovy
@@ -38,10 +38,10 @@ class ApplicationContextCommandFactory implements CommandFactory {
             def classLoader = Thread.currentThread().contextClassLoader
             Class registry
             try {
-                registry = classLoader.loadClass('grails.dev.commands.ApplicationContextCommandRegistry')
+                registry = classLoader.loadClass('org.apache.grails.core.cli.ApplicationContextCommandRegistry')
             } catch (ClassNotFoundException cnf) {
                 try {
-                    registry = ApplicationContextCommandFactory.classLoader.loadClass('grails.dev.commands.ApplicationContextCommandRegistry')
+                    registry = ApplicationContextCommandFactory.classLoader.loadClass('org.apache.grails.core.cli.ApplicationContextCommandRegistry')
                 } catch (ClassNotFoundException ignored) {
                     return []
                 }
diff --git a/grails-spring-security/oauth2/plugin/build.gradle b/grails-spring-security/oauth2/plugin/build.gradle
index db6eccd030..96851866ff 100644
--- a/grails-spring-security/oauth2/plugin/build.gradle
+++ b/grails-spring-security/oauth2/plugin/build.gradle
@@ -28,16 +28,36 @@ plugins {
 	id 'org.apache.grails.buildsrc.sbom'
 	id 'org.apache.grails.gradle.grails-code-style'
 	id 'org.apache.grails.gradle.grails-plugin'
+	id 'org.apache.grails.gradle.grails-plugin-cli'
 	id 'org.apache.grails.gradle.grails-gsp'
 }
 
 version = projectVersion
 group = 'org.apache.grails'
 
+cliArtifact {
+	automaticModuleName = 'org.apache.grails.security.oauth2.cli'
+	// this framework module wires its cli dependencies with project dependencies below
+	defaultDependencies = false
+}
+
+
 dependencies {
 
 	implementation platform(project(':grails-bom'))
 
+	// the cli tier — published separately as a companion -cli artifact
+	cliImplementation platform(project(':grails-bom'))
+	cliApi project(project.path)
+	cliApi(project(':grails-core')) {
+		capabilities {
+			requireCapability('org.apache.grails:grails-core-cli')
+		}
+	}
+	// GrailsConsole (used by init-o-auth2) needs jline at compile time
+	cliImplementation 'org.jline:jline'
+	cliImplementation 'org.fusesource.jansi:jansi'
+
 	api project(':grails-spring-security'), {
 		// api: GrailsUserDetailsService, SpringSecurityService
 		// impl: GormUserDetailsService, GrailsUser, ReflectionUtils, @Secured(runtime), SecurityContextHolder,
diff --git a/grails-spring-security/oauth2/plugin/grails-app/commands/grails/plugin/springsecurity/oauth2/CommandLineHelper.groovy b/grails-spring-security/oauth2/plugin/src/cli/groovy/org/apache/grails/security/oauth2/cli/CommandLineHelper.groovy
similarity index 95%
rename from grails-spring-security/oauth2/plugin/grails-app/commands/grails/plugin/springsecurity/oauth2/CommandLineHelper.groovy
rename to grails-spring-security/oauth2/plugin/src/cli/groovy/org/apache/grails/security/oauth2/cli/CommandLineHelper.groovy
index b093fab8db..c229c71b99 100644
--- a/grails-spring-security/oauth2/plugin/grails-app/commands/grails/plugin/springsecurity/oauth2/CommandLineHelper.groovy
+++ b/grails-spring-security/oauth2/plugin/src/cli/groovy/org/apache/grails/security/oauth2/cli/CommandLineHelper.groovy
@@ -17,7 +17,7 @@
  *  under the License.
  */
 
-package grails.plugin.springsecurity.oauth2
+package org.apache.grails.security.oauth2.cli
 
 trait CommandLineHelper {
 
diff --git a/grails-spring-security/oauth2/plugin/grails-app/commands/grails/plugin/springsecurity/oauth2/InitOAuth2Command.groovy b/grails-spring-security/oauth2/plugin/src/cli/groovy/org/apache/grails/security/oauth2/cli/InitOAuth2Command.groovy
similarity index 97%
rename from grails-spring-security/oauth2/plugin/grails-app/commands/grails/plugin/springsecurity/oauth2/InitOAuth2Command.groovy
rename to grails-spring-security/oauth2/plugin/src/cli/groovy/org/apache/grails/security/oauth2/cli/InitOAuth2Command.groovy
index 54f8c6268a..7beb09d2f8 100644
--- a/grails-spring-security/oauth2/plugin/grails-app/commands/grails/plugin/springsecurity/oauth2/InitOAuth2Command.groovy
+++ b/grails-spring-security/oauth2/plugin/src/cli/groovy/org/apache/grails/security/oauth2/cli/InitOAuth2Command.groovy
@@ -13,14 +13,14 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package grails.plugin.springsecurity.oauth2
+package org.apache.grails.security.oauth2.cli
 
 import groovy.transform.CompileStatic
 
 import grails.build.logging.ConsoleLogger
 import grails.build.logging.GrailsConsole
 import grails.codegen.model.Model
-import grails.dev.commands.GrailsApplicationCommand
+import org.apache.grails.core.cli.GrailsApplicationCommand
 
 /**
  * Creates domain classes and updates config settings for the Spring Security OAuth2 plugin.
@@ -30,7 +30,6 @@ import grails.dev.commands.GrailsApplicationCommand
  * 1. <code>./gradlew runCommand "-Pargs=init-oauth2 com.yourapp User OAuthID"</code>
  * 2. <code>./gradlew runCommand "-Pargs=init-oauth2 com.yourapp com.yourapp.user.User OAuthID"</code>
  *
- * @author Puneet Behl
  * @since 3.0.0
  */
 @CompileStatic
diff --git a/grails-spring-security/plugin/build.gradle b/grails-spring-security/plugin/build.gradle
index 7ec19590b4..14453792e6 100644
--- a/grails-spring-security/plugin/build.gradle
+++ b/grails-spring-security/plugin/build.gradle
@@ -30,15 +30,35 @@ plugins {
 	id 'org.apache.grails.gradle.grails-code-style'
 	id 'org.apache.grails.gradle.grails-gsp'
 	id 'org.apache.grails.gradle.grails-plugin'
+	id 'org.apache.grails.gradle.grails-plugin-cli'
 }
 
 version = projectVersion
 group = 'org.apache.grails'
 
+cliArtifact {
+	automaticModuleName = 'org.apache.grails.security.cli'
+	// this framework module wires its cli dependencies with project dependencies below
+	defaultDependencies = false
+}
+
+
 dependencies {
 
 	implementation platform(project(':grails-bom'))
 
+	// the cli tier — published separately as a companion -cli artifact
+	cliImplementation platform(project(':grails-bom'))
+	cliApi project(project.path)
+	cliApi(project(':grails-core')) {
+		capabilities {
+			requireCapability('org.apache.grails:grails-core-cli')
+		}
+	}
+	// GrailsConsole (used by the s2-* commands) needs jline at compile time
+	cliImplementation 'org.jline:jline'
+	cliImplementation 'org.fusesource.jansi:jansi'
+
 	api project(':grails-spring-security-compat')
 	api project(':grails-async') // AsyncGrailsWebRequest is used in public API
 	api project(':grails-mimetypes')
diff --git a/grails-spring-security/plugin/grails-app/commands/grails.plugin.springsecurity/CommandLineHelper.groovy b/grails-spring-security/plugin/src/cli/groovy/org/apache/grails/security/cli/CommandLineHelper.groovy
similarity index 95%
rename from grails-spring-security/plugin/grails-app/commands/grails.plugin.springsecurity/CommandLineHelper.groovy
rename to grails-spring-security/plugin/src/cli/groovy/org/apache/grails/security/cli/CommandLineHelper.groovy
index 6d4a6604ec..9bfa2ea92b 100644
--- a/grails-spring-security/plugin/grails-app/commands/grails.plugin.springsecurity/CommandLineHelper.groovy
+++ b/grails-spring-security/plugin/src/cli/groovy/org/apache/grails/security/cli/CommandLineHelper.groovy
@@ -17,9 +17,9 @@
  *  under the License.
  */
 
-package grails.plugin.springsecurity
+package org.apache.grails.security.cli
 
-import grails.dev.commands.ExecutionContext
+import org.apache.grails.core.cli.ExecutionContext
 import org.grails.build.parsing.CommandLine
 
 trait CommandLineHelper {
diff --git a/grails-spring-security/plugin/grails-app/commands/grails.plugin.springsecurity/S2CreatePersistentTokenCommand.groovy b/grails-spring-security/plugin/src/cli/groovy/org/apache/grails/security/cli/S2CreatePersistentTokenCommand.groovy
similarity index 95%
rename from grails-spring-security/plugin/grails-app/commands/grails.plugin.springsecurity/S2CreatePersistentTokenCommand.groovy
rename to grails-spring-security/plugin/src/cli/groovy/org/apache/grails/security/cli/S2CreatePersistentTokenCommand.groovy
index 2fb604b289..615db6fc79 100644
--- a/grails-spring-security/plugin/grails-app/commands/grails.plugin.springsecurity/S2CreatePersistentTokenCommand.groovy
+++ b/grails-spring-security/plugin/src/cli/groovy/org/apache/grails/security/cli/S2CreatePersistentTokenCommand.groovy
@@ -13,12 +13,12 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package grails.plugin.springsecurity
+package org.apache.grails.security.cli
 
 import grails.build.logging.ConsoleLogger
 import grails.build.logging.GrailsConsole
 import grails.codegen.model.Model
-import grails.dev.commands.GrailsApplicationCommand
+import org.apache.grails.core.cli.GrailsApplicationCommand
 import groovy.transform.CompileStatic
 
 /**
@@ -27,7 +27,6 @@ import groovy.transform.CompileStatic
 *
  * For example: <code>./grailsw s2-create-persistent-token com.yourapp.PersistentLogin</code>
  *
- * @author Puneet Behl
  * @since 6.0.0
  */
 @CompileStatic
diff --git a/grails-spring-security/plugin/grails-app/commands/grails.plugin.springsecurity/S2CreateRoleHierarchyEntryCommand.groovy b/grails-spring-security/plugin/src/cli/groovy/org/apache/grails/security/cli/S2CreateRoleHierarchyEntryCommand.groovy
similarity index 95%
rename from grails-spring-security/plugin/grails-app/commands/grails.plugin.springsecurity/S2CreateRoleHierarchyEntryCommand.groovy
rename to grails-spring-security/plugin/src/cli/groovy/org/apache/grails/security/cli/S2CreateRoleHierarchyEntryCommand.groovy
index 4a9cba73a3..1411817642 100644
--- a/grails-spring-security/plugin/grails-app/commands/grails.plugin.springsecurity/S2CreateRoleHierarchyEntryCommand.groovy
+++ b/grails-spring-security/plugin/src/cli/groovy/org/apache/grails/security/cli/S2CreateRoleHierarchyEntryCommand.groovy
@@ -13,12 +13,12 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package grails.plugin.springsecurity
+package org.apache.grails.security.cli
 
 import grails.build.logging.ConsoleLogger
 import grails.build.logging.GrailsConsole
 import grails.codegen.model.Model
-import grails.dev.commands.GrailsApplicationCommand
+import org.apache.grails.core.cli.GrailsApplicationCommand
 import groovy.transform.CompileStatic
 
 /**
@@ -26,7 +26,6 @@ import groovy.transform.CompileStatic
  * Usage: <code>./grailsw s2-create-role-hierarchy-entry [DOMAIN CLASS NAME]
  * For example: <code>./grailsw s2-create-role-hierarchy-entry com.yourapp.RoleHierarchyEntry</code>
  *
- * @author Puneet Behl
  * @since 6.0.0
  */
 @CompileStatic
diff --git a/grails-spring-security/plugin/grails-app/commands/grails.plugin.springsecurity/S2QuickstartCommand.groovy b/grails-spring-security/plugin/src/cli/groovy/org/apache/grails/security/cli/S2QuickstartCommand.groovy
similarity index 99%
rename from grails-spring-security/plugin/grails-app/commands/grails.plugin.springsecurity/S2QuickstartCommand.groovy
rename to grails-spring-security/plugin/src/cli/groovy/org/apache/grails/security/cli/S2QuickstartCommand.groovy
index 20b150e5ef..9a7cab8684 100644
--- a/grails-spring-security/plugin/grails-app/commands/grails.plugin.springsecurity/S2QuickstartCommand.groovy
+++ b/grails-spring-security/plugin/src/cli/groovy/org/apache/grails/security/cli/S2QuickstartCommand.groovy
@@ -13,12 +13,12 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package grails.plugin.springsecurity
+package org.apache.grails.security.cli
 
 import grails.build.logging.ConsoleLogger
 import grails.build.logging.GrailsConsole
 import grails.codegen.model.Model
-import grails.dev.commands.GrailsApplicationCommand
+import org.apache.grails.core.cli.GrailsApplicationCommand
 import groovy.transform.CompileStatic
 
 /**
@@ -32,7 +32,6 @@ import groovy.transform.CompileStatic
  * 3. <code>./grailsw s2-quickstart --uiOnly</code>
  * 4. <code>./grailsw s2-quickstart com.yourapp User Role</code>
  *
- * @author Puneet Behl
  * @since 6.0.0
  */
 @CompileStatic
diff --git a/grails-spring-security/plugin/grails-app/commands/grails.plugin.springsecurity/SkipBootstrap.groovy b/grails-spring-security/plugin/src/cli/groovy/org/apache/grails/security/cli/SkipBootstrap.groovy
similarity index 95%
rename from grails-spring-security/plugin/grails-app/commands/grails.plugin.springsecurity/SkipBootstrap.groovy
rename to grails-spring-security/plugin/src/cli/groovy/org/apache/grails/security/cli/SkipBootstrap.groovy
index 4c7f158d17..0bf99ec1f9 100644
--- a/grails-spring-security/plugin/grails-app/commands/grails.plugin.springsecurity/SkipBootstrap.groovy
+++ b/grails-spring-security/plugin/src/cli/groovy/org/apache/grails/security/cli/SkipBootstrap.groovy
@@ -17,7 +17,7 @@
  *  under the License.
  */
 
-package grails.plugin.springsecurity
+package org.apache.grails.security.cli
 
 trait SkipBootstrap {
 
diff --git a/grails-test-examples/config-report/src/integration-test/groovy/configreport/ConfigReportCommandIntegrationSpec.groovy b/grails-test-examples/config-report/src/integration-test/groovy/configreport/ConfigReportCommandIntegrationSpec.groovy
index c8b347f3a6..1b497b60f1 100644
--- a/grails-test-examples/config-report/src/integration-test/groovy/configreport/ConfigReportCommandIntegrationSpec.groovy
+++ b/grails-test-examples/config-report/src/integration-test/groovy/configreport/ConfigReportCommandIntegrationSpec.groovy
@@ -21,8 +21,8 @@ package configreport
 import org.springframework.beans.factory.annotation.Autowired
 import org.springframework.context.ConfigurableApplicationContext
 
-import grails.dev.commands.ConfigReportCommand
-import grails.dev.commands.ExecutionContext
+import org.apache.grails.core.cli.ConfigReportCommand
+import org.apache.grails.core.cli.ExecutionContext
 import grails.testing.mixin.integration.Integration
 import org.grails.build.parsing.CommandLine
 import spock.lang.Narrative
diff --git a/grails-web-url-mappings/build.gradle b/grails-web-url-mappings/build.gradle
index e139c847b8..9e9e27762a 100644
--- a/grails-web-url-mappings/build.gradle
+++ b/grails-web-url-mappings/build.gradle
@@ -20,6 +20,7 @@
 plugins {
     id 'groovy'
     id 'java-library'
+    id 'org.apache.grails.gradle.grails-plugin-cli'
     id 'project-report'
     id 'org.apache.grails.buildsrc.properties'
     id 'org.apache.grails.buildsrc.dependency-validator'
@@ -34,10 +35,25 @@ plugins {
 version = projectVersion
 group = 'org.apache.grails.web'
 
+cliArtifact {
+    automaticModuleName = 'org.apache.grails.web.mapping.cli'
+    // this framework module wires its cli dependencies with project dependencies below
+    defaultDependencies = false
+}
+
 dependencies {
 
     implementation platform(project(':grails-bom'))
 
+    // the cli tier — published separately as a companion -cli artifact
+    cliImplementation platform(project(':grails-bom'))
+    cliApi project(project.path)
+    cliApi(project(':grails-core')) {
+        capabilities {
+            requireCapability('org.apache.grails:grails-core-cli')
+        }
+    }
+
     api project(':grails-web-common')
     implementation 'io.micrometer:micrometer-observation'
     compileOnly 'org.apache.grails.views:grails-gsp-core', {
diff --git a/grails-web-url-mappings/src/main/groovy/org/grails/web/mapping/reporting/UrlMappingsReportCommand.groovy b/grails-web-url-mappings/src/cli/groovy/org/apache/grails/web/mapping/cli/UrlMappingsReportCommand.groovy
similarity index 89%
rename from grails-web-url-mappings/src/main/groovy/org/grails/web/mapping/reporting/UrlMappingsReportCommand.groovy
rename to grails-web-url-mappings/src/cli/groovy/org/apache/grails/web/mapping/cli/UrlMappingsReportCommand.groovy
index cb581b95c9..caddcaecda 100644
--- a/grails-web-url-mappings/src/main/groovy/org/grails/web/mapping/reporting/UrlMappingsReportCommand.groovy
+++ b/grails-web-url-mappings/src/cli/groovy/org/apache/grails/web/mapping/cli/UrlMappingsReportCommand.groovy
@@ -16,14 +16,15 @@
  *  specific language governing permissions and limitations
  *  under the License.
  */
-package org.grails.web.mapping.reporting
+package org.apache.grails.web.mapping.cli
 
 import groovy.transform.CompileStatic
 import groovy.transform.EqualsAndHashCode
 import groovy.util.logging.Slf4j
 
-import grails.dev.commands.ApplicationCommand
-import grails.dev.commands.ExecutionContext
+import org.apache.grails.core.cli.ApplicationCommand
+import org.grails.web.mapping.reporting.AnsiConsoleUrlMappingsRenderer
+import org.apache.grails.core.cli.ExecutionContext
 import grails.web.mapping.UrlMappingsHolder
 
 /**