Repository: GoogleContainerTools/kpt
Pull request #3540 (2022-09-07 20:27:09)

Move cobra commands from internal package into hierarchical structure under commands
This moves the kpt cobra commands from the flat structure under the `internal` package to a hierarchical structure in the `commands` package that reflects the way the commands are structured in the kpt cli. This makes it easier to navigate the commands and allows for simpler naming. 

I think of this as a first step towards better separation between the kpt cli and the kpt library as described in https://github.com/GoogleContainerTools/kpt/issues/3297

justinsb: I really like this - much more self-documenting and better architecturally.

I'm afraid I forced a conflict on you - sorry!  You probably want to get this in before #3541 (I can rebase that pretty easily!)

Patch:
diff --git a/commands/alphacmd.go b/commands/alpha/alphacmd.go
similarity index 67%
rename from commands/alphacmd.go
rename to commands/alpha/alphacmd.go
index f07f2ca2..fd0aa211 100644
--- a/commands/alphacmd.go
+++ b/commands/alpha/alphacmd.go
@@ -12,17 +12,23 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-package commands
+package alpha
 
 import (
 	"context"
 
+	"github.com/GoogleContainerTools/kpt/commands/alpha/live"
+	"github.com/GoogleContainerTools/kpt/commands/alpha/repo"
+	"github.com/GoogleContainerTools/kpt/commands/alpha/rpkg"
+	"github.com/GoogleContainerTools/kpt/commands/alpha/sync"
+	"github.com/GoogleContainerTools/kpt/commands/alpha/wasm"
+
 	"github.com/GoogleContainerTools/kpt/internal/docs/generated/alphadocs"
 	"github.com/GoogleContainerTools/kpt/internal/util/porch"
 	"github.com/spf13/cobra"
 )
 
-func GetAlphaCommand(ctx context.Context, name, version string) *cobra.Command {
+func GetCommand(ctx context.Context, name, version string) *cobra.Command {
 	alpha := &cobra.Command{
 		Use:   "alpha",
 		Short: alphadocs.AlphaShort,
@@ -41,11 +47,11 @@ func GetAlphaCommand(ctx context.Context, name, version string) *cobra.Command {
 	}
 
 	alpha.AddCommand(
-		NewRepoCommand(ctx, version),
-		NewRpkgCommand(ctx, version),
-		NewSyncCommand(ctx, version),
-		NewWasmCommand(ctx, version),
-		GetAlphaLiveCommand(ctx, "", version),
+		repo.NewCommand(ctx, version),
+		rpkg.NewCommand(ctx, version),
+		sync.NewCommand(ctx, version),
+		wasm.NewCommand(ctx, version),
+		live.GetCommand(ctx, "", version),
 	)
 
 	return alpha
diff --git a/commands/alphalivecmd.go b/commands/alpha/live/livecmd.go
similarity index 73%
rename from commands/alphalivecmd.go
rename to commands/alpha/live/livecmd.go
index 3c7ea50a..eac8005c 100644
--- a/commands/alphalivecmd.go
+++ b/commands/alpha/live/livecmd.go
@@ -12,20 +12,21 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-package commands
+package live
 
 import (
 	"context"
 	"os"
 
-	"github.com/GoogleContainerTools/kpt/internal/cmdapply"
-	"github.com/GoogleContainerTools/kpt/internal/cmdplan"
+	"github.com/GoogleContainerTools/kpt/commands/alpha/live/plan"
+	"github.com/GoogleContainerTools/kpt/commands/live/apply"
+	"github.com/GoogleContainerTools/kpt/commands/util"
 	"github.com/GoogleContainerTools/kpt/internal/docs/generated/livedocs"
 	"github.com/spf13/cobra"
 	"k8s.io/cli-runtime/pkg/genericclioptions"
 )
 
-func GetAlphaLiveCommand(ctx context.Context, _, version string) *cobra.Command {
+func GetCommand(ctx context.Context, _, version string) *cobra.Command {
 	liveCmd := &cobra.Command{
 		Use:   "live",
 		Short: "[Alpha] " + livedocs.LiveShort,
@@ -38,12 +39,12 @@ func GetAlphaLiveCommand(ctx context.Context, _, version string) *cobra.Command
 		ErrOut: os.Stderr,
 	}
 
-	f := newFactory(liveCmd, version)
+	f := util.NewFactory(liveCmd, version)
 
-	applyCmd := cmdapply.NewCommand(ctx, f, ioStreams, true)
+	applyCmd := apply.NewCommand(ctx, f, ioStreams, true)
 	liveCmd.AddCommand(applyCmd)
 
-	planCmd := cmdplan.NewCommand(ctx, f, ioStreams)
+	planCmd := plan.NewCommand(ctx, f, ioStreams)
 	liveCmd.AddCommand(planCmd)
 
 	return liveCmd
diff --git a/internal/cmdplan/command.go b/commands/alpha/live/plan/command.go
similarity index 99%
rename from internal/cmdplan/command.go
rename to commands/alpha/live/plan/command.go
index 1e8ac795..d7b980f6 100644
--- a/internal/cmdplan/command.go
+++ b/commands/alpha/live/plan/command.go
@@ -12,7 +12,7 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-package cmdplan
+package plan
 
 import (
 	"bufio"
diff --git a/internal/cmdplan/diff.go b/commands/alpha/live/plan/diff.go
similarity index 99%
rename from internal/cmdplan/diff.go
rename to commands/alpha/live/plan/diff.go
index f4ddc2a5..ca99b723 100644
--- a/internal/cmdplan/diff.go
+++ b/commands/alpha/live/plan/diff.go
@@ -12,7 +12,7 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-package cmdplan
+package plan
 
 import (
 	"reflect"
diff --git a/internal/cmdrepoget/command.go b/commands/alpha/repo/get/command.go
similarity index 99%
rename from internal/cmdrepoget/command.go
rename to commands/alpha/repo/get/command.go
index 0c48f967..9ef3bc61 100644
--- a/internal/cmdrepoget/command.go
+++ b/commands/alpha/repo/get/command.go
@@ -12,7 +12,7 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-package cmdrepoget
+package get
 
 import (
 	"context"
diff --git a/internal/cmdreporeg/command.go b/commands/alpha/repo/reg/command.go
similarity index 99%
rename from internal/cmdreporeg/command.go
rename to commands/alpha/repo/reg/command.go
index 2d908007..53c7c72a 100644
--- a/internal/cmdreporeg/command.go
+++ b/commands/alpha/repo/reg/command.go
@@ -12,7 +12,7 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-package cmdreporeg
+package reg
 
 import (
 	"context"
diff --git a/internal/cmdreporeg/testdata/auth-repository.yaml b/commands/alpha/repo/reg/testdata/auth-repository.yaml
similarity index 100%
rename from internal/cmdreporeg/testdata/auth-repository.yaml
rename to commands/alpha/repo/reg/testdata/auth-repository.yaml
diff --git a/internal/cmdreporeg/testdata/auth-secret.yaml b/commands/alpha/repo/reg/testdata/auth-secret.yaml
similarity index 100%
rename from internal/cmdreporeg/testdata/auth-secret.yaml
rename to commands/alpha/repo/reg/testdata/auth-secret.yaml
diff --git a/internal/cmdreporeg/testdata/full-repository.yaml b/commands/alpha/repo/reg/testdata/full-repository.yaml
similarity index 100%
rename from internal/cmdreporeg/testdata/full-repository.yaml
rename to commands/alpha/repo/reg/testdata/full-repository.yaml
diff --git a/internal/cmdreporeg/testdata/simple-repository.yaml b/commands/alpha/repo/reg/testdata/simple-repository.yaml
similarity index 100%
rename from internal/cmdreporeg/testdata/simple-repository.yaml
rename to commands/alpha/repo/reg/testdata/simple-repository.yaml
diff --git a/commands/repocmd.go b/commands/alpha/repo/repocmd.go
similarity index 79%
rename from commands/repocmd.go
rename to commands/alpha/repo/repocmd.go
index a0db4c48..d878b5a6 100644
--- a/commands/repocmd.go
+++ b/commands/alpha/repo/repocmd.go
@@ -12,16 +12,16 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-package commands
+package repo
 
 import (
 	"context"
 	"flag"
 	"fmt"
 
-	"github.com/GoogleContainerTools/kpt/internal/cmdrepoget"
-	"github.com/GoogleContainerTools/kpt/internal/cmdreporeg"
-	"github.com/GoogleContainerTools/kpt/internal/cmdrepounreg"
+	"github.com/GoogleContainerTools/kpt/commands/alpha/repo/get"
+	"github.com/GoogleContainerTools/kpt/commands/alpha/repo/reg"
+	"github.com/GoogleContainerTools/kpt/commands/alpha/repo/unreg"
 	"github.com/GoogleContainerTools/kpt/internal/docs/generated/repodocs"
 	"github.com/GoogleContainerTools/kpt/internal/util/porch"
 	"github.com/spf13/cobra"
@@ -29,7 +29,7 @@ import (
 	"k8s.io/client-go/rest"
 )
 
-func NewRepoCommand(ctx context.Context, version string) *cobra.Command {
+func NewCommand(ctx context.Context, version string) *cobra.Command {
 	repo := &cobra.Command{
 		Use:     "repo",
 		Aliases: []string{"repository"},
@@ -61,9 +61,9 @@ func NewRepoCommand(ctx context.Context, version string) *cobra.Command {
 	pf.AddGoFlagSet(flag.CommandLine)
 
 	repo.AddCommand(
-		cmdreporeg.NewCommand(ctx, kubeflags),
-		cmdrepoget.NewCommand(ctx, kubeflags),
-		cmdrepounreg.NewCommand(ctx, kubeflags),
+		reg.NewCommand(ctx, kubeflags),
+		get.NewCommand(ctx, kubeflags),
+		unreg.NewCommand(ctx, kubeflags),
 	)
 
 	return repo
diff --git a/internal/cmdrepounreg/command.go b/commands/alpha/repo/unreg/command.go
similarity index 99%
rename from internal/cmdrepounreg/command.go
rename to commands/alpha/repo/unreg/command.go
index 4d16a118..c235e004 100644
--- a/internal/cmdrepounreg/command.go
+++ b/commands/alpha/repo/unreg/command.go
@@ -12,7 +12,7 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-package cmdrepounreg
+package unreg
 
 import (
 	"context"
diff --git a/internal/cmdrpkgapprove/command.go b/commands/alpha/rpkg/approve/command.go
similarity index 99%
rename from internal/cmdrpkgapprove/command.go
rename to commands/alpha/rpkg/approve/command.go
index 0a0cf04a..4f2a8522 100644
--- a/internal/cmdrpkgapprove/command.go
+++ b/commands/alpha/rpkg/approve/command.go
@@ -12,7 +12,7 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-package cmdrpkgapprove
+package approve
 
 import (
 	"context"
diff --git a/internal/cmdrpkgclone/command.go b/commands/alpha/rpkg/clone/command.go
similarity index 99%
rename from internal/cmdrpkgclone/command.go
rename to commands/alpha/rpkg/clone/command.go
index 55c88e2e..db797452 100644
--- a/internal/cmdrpkgclone/command.go
+++ b/commands/alpha/rpkg/clone/command.go
@@ -12,7 +12,7 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-package cmdrpkgclone
+package clone
 
 import (
 	"context"
diff --git a/internal/cmdrpkgcopy/command.go b/commands/alpha/rpkg/copy/command.go
similarity index 99%
rename from internal/cmdrpkgcopy/command.go
rename to commands/alpha/rpkg/copy/command.go
index e382ae7e..82a80f07 100644
--- a/internal/cmdrpkgcopy/command.go
+++ b/commands/alpha/rpkg/copy/command.go
@@ -12,7 +12,7 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-package cmdrpkgcopy
+package copy
 
 import (
 	"context"
diff --git a/internal/cmdrpkgdel/command.go b/commands/alpha/rpkg/del/command.go
similarity index 99%
rename from internal/cmdrpkgdel/command.go
rename to commands/alpha/rpkg/del/command.go
index 5e5219b4..2318a2f5 100644
--- a/internal/cmdrpkgdel/command.go
+++ b/commands/alpha/rpkg/del/command.go
@@ -12,7 +12,7 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-package cmdrpkgdel
+package del
 
 import (
 	"context"
diff --git a/internal/cmdrpkgget/command.go b/commands/alpha/rpkg/get/command.go
similarity index 99%
rename from internal/cmdrpkgget/command.go
rename to commands/alpha/rpkg/get/command.go
index 73c57d00..f242efca 100644
--- a/internal/cmdrpkgget/command.go
+++ b/commands/alpha/rpkg/get/command.go
@@ -12,7 +12,7 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-package cmdrpkgget
+package get
 
 import (
 	"context"
diff --git a/internal/cmdrpkginit/command.go b/commands/alpha/rpkg/init/command.go
similarity index 99%
rename from internal/cmdrpkginit/command.go
rename to commands/alpha/rpkg/init/command.go
index ae1f1078..06174ca0 100644
--- a/internal/cmdrpkginit/command.go
+++ b/commands/alpha/rpkg/init/command.go
@@ -12,7 +12,7 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-package cmdrpkginit
+package init
 
 import (
 	"context"
diff --git a/internal/cmdrpkgpropose/command.go b/commands/alpha/rpkg/propose/command.go
similarity index 99%
rename from internal/cmdrpkgpropose/command.go
rename to commands/alpha/rpkg/propose/command.go
index 9ddcbe60..45e36148 100644
--- a/internal/cmdrpkgpropose/command.go
+++ b/commands/alpha/rpkg/propose/command.go
@@ -12,7 +12,7 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-package cmdrpkgpropose
+package propose
 
 import (
 	"context"
diff --git a/internal/cmdrpkgpull/command.go b/commands/alpha/rpkg/pull/command.go
similarity index 99%
rename from internal/cmdrpkgpull/command.go
rename to commands/alpha/rpkg/pull/command.go
index bffb34ee..bd6adadc 100644
--- a/internal/cmdrpkgpull/command.go
+++ b/commands/alpha/rpkg/pull/command.go
@@ -12,7 +12,7 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-package cmdrpkgpull
+package pull
 
 import (
 	"context"
diff --git a/internal/cmdrpkgpush/command.go b/commands/alpha/rpkg/push/command.go
similarity index 99%
rename from internal/cmdrpkgpush/command.go
rename to commands/alpha/rpkg/push/command.go
index 65ca797b..c7be0abe 100644
--- a/internal/cmdrpkgpush/command.go
+++ b/commands/alpha/rpkg/push/command.go
@@ -12,7 +12,7 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-package cmdrpkgpush
+package push
 
 import (
 	"bytes"
diff --git a/internal/cmdrpkgreject/command.go b/commands/alpha/rpkg/reject/command.go
similarity index 99%
rename from internal/cmdrpkgreject/command.go
rename to commands/alpha/rpkg/reject/command.go
index ba0d7e06..89f7d5ee 100644
--- a/internal/cmdrpkgreject/command.go
+++ b/commands/alpha/rpkg/reject/command.go
@@ -12,7 +12,7 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-package cmdrpkgreject
+package reject
 
 import (
 	"context"
diff --git a/commands/rpkgcmd.go b/commands/alpha/rpkg/rpkgcmd.go
similarity index 56%
rename from commands/rpkgcmd.go
rename to commands/alpha/rpkg/rpkgcmd.go
index c919d04f..72006bec 100644
--- a/commands/rpkgcmd.go
+++ b/commands/alpha/rpkg/rpkgcmd.go
@@ -12,24 +12,24 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-package commands
+package rpkg
 
 import (
 	"context"
 	"flag"
 	"fmt"
 
-	"github.com/GoogleContainerTools/kpt/internal/cmdrpkgapprove"
-	"github.com/GoogleContainerTools/kpt/internal/cmdrpkgclone"
-	"github.com/GoogleContainerTools/kpt/internal/cmdrpkgcopy"
-	"github.com/GoogleContainerTools/kpt/internal/cmdrpkgdel"
-	"github.com/GoogleContainerTools/kpt/internal/cmdrpkgget"
-	"github.com/GoogleContainerTools/kpt/internal/cmdrpkginit"
-	"github.com/GoogleContainerTools/kpt/internal/cmdrpkgpropose"
-	"github.com/GoogleContainerTools/kpt/internal/cmdrpkgpull"
-	"github.com/GoogleContainerTools/kpt/internal/cmdrpkgpush"
-	"github.com/GoogleContainerTools/kpt/internal/cmdrpkgreject"
-	"github.com/GoogleContainerTools/kpt/internal/cmdrpkgupdate"
+	"github.com/GoogleContainerTools/kpt/commands/alpha/rpkg/approve"
+	"github.com/GoogleContainerTools/kpt/commands/alpha/rpkg/clone"
+	"github.com/GoogleContainerTools/kpt/commands/alpha/rpkg/copy"
+	"github.com/GoogleContainerTools/kpt/commands/alpha/rpkg/del"
+	"github.com/GoogleContainerTools/kpt/commands/alpha/rpkg/get"
+	initialization "github.com/GoogleContainerTools/kpt/commands/alpha/rpkg/init"
+	"github.com/GoogleContainerTools/kpt/commands/alpha/rpkg/propose"
+	"github.com/GoogleContainerTools/kpt/commands/alpha/rpkg/pull"
+	"github.com/GoogleContainerTools/kpt/commands/alpha/rpkg/push"
+	"github.com/GoogleContainerTools/kpt/commands/alpha/rpkg/reject"
+	"github.com/GoogleContainerTools/kpt/commands/alpha/rpkg/update"
 	"github.com/GoogleContainerTools/kpt/internal/docs/generated/rpkgdocs"
 	"github.com/GoogleContainerTools/kpt/internal/util/porch"
 	"github.com/spf13/cobra"
@@ -37,7 +37,7 @@ import (
 	"k8s.io/client-go/rest"
 )
 
-func NewRpkgCommand(ctx context.Context, version string) *cobra.Command {
+func NewCommand(ctx context.Context, version string) *cobra.Command {
 	repo := &cobra.Command{
 		Use:     "rpkg",
 		Aliases: []string{"rpackage"},
@@ -69,17 +69,17 @@ func NewRpkgCommand(ctx context.Context, version string) *cobra.Command {
 	pf.AddGoFlagSet(flag.CommandLine)
 
 	repo.AddCommand(
-		cmdrpkgget.NewCommand(ctx, kubeflags),
-		cmdrpkgpull.NewCommand(ctx, kubeflags),
-		cmdrpkgpush.NewCommand(ctx, kubeflags),
-		cmdrpkgclone.NewCommand(ctx, kubeflags),
-		cmdrpkginit.NewCommand(ctx, kubeflags),
-		cmdrpkgpropose.NewCommand(ctx, kubeflags),
-		cmdrpkgapprove.NewCommand(ctx, kubeflags),
-		cmdrpkgreject.NewCommand(ctx, kubeflags),
-		cmdrpkgdel.NewCommand(ctx, kubeflags),
-		cmdrpkgcopy.NewCommand(ctx, kubeflags),
-		cmdrpkgupdate.NewCommand(ctx, kubeflags),
+		get.NewCommand(ctx, kubeflags),
+		pull.NewCommand(ctx, kubeflags),
+		push.NewCommand(ctx, kubeflags),
+		clone.NewCommand(ctx, kubeflags),
+		initialization.NewCommand(ctx, kubeflags),
+		propose.NewCommand(ctx, kubeflags),
+		approve.NewCommand(ctx, kubeflags),
+		reject.NewCommand(ctx, kubeflags),
+		del.NewCommand(ctx, kubeflags),
+		copy.NewCommand(ctx, kubeflags),
+		update.NewCommand(ctx, kubeflags),
 	)
 
 	return repo
diff --git a/internal/cmdrpkgupdate/command.go b/commands/alpha/rpkg/update/command.go
similarity index 99%
rename from internal/cmdrpkgupdate/command.go
rename to commands/alpha/rpkg/update/command.go
index 759d21ba..1e5cca06 100644
--- a/internal/cmdrpkgupdate/command.go
+++ b/commands/alpha/rpkg/update/command.go
@@ -12,7 +12,7 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-package cmdrpkgupdate
+package update
 
 import (
 	"context"
diff --git a/internal/cmdrpkgupdate/discover.go b/commands/alpha/rpkg/update/discover.go
similarity index 99%
rename from internal/cmdrpkgupdate/discover.go
rename to commands/alpha/rpkg/update/discover.go
index 95055415..2a4734d8 100644
--- a/internal/cmdrpkgupdate/discover.go
+++ b/commands/alpha/rpkg/update/discover.go
@@ -12,7 +12,7 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-package cmdrpkgupdate
+package update
 
 import (
 	"fmt"
diff --git a/internal/cmdsync/create/command.go b/commands/alpha/sync/create/command.go
similarity index 97%
rename from internal/cmdsync/create/command.go
rename to commands/alpha/sync/create/command.go
index 3374ccd6..bc992850 100644
--- a/internal/cmdsync/create/command.go
+++ b/commands/alpha/sync/create/command.go
@@ -18,7 +18,7 @@ import (
 	"context"
 	"fmt"
 
-	"github.com/GoogleContainerTools/kpt/internal/cmdsync"
+	"github.com/GoogleContainerTools/kpt/commands/util"
 	"github.com/GoogleContainerTools/kpt/internal/docs/generated/syncdocs"
 	"github.com/GoogleContainerTools/kpt/internal/errors"
 	"github.com/GoogleContainerTools/kpt/internal/util/porch"
@@ -135,7 +135,7 @@ func (r *runner) runE(cmd *cobra.Command, args []string) error {
 			},
 			ObjectMeta: metav1.ObjectMeta{
 				Name:      fmt.Sprintf("%s-auth", syncName),
-				Namespace: cmdsync.RootSyncNamespace,
+				Namespace: util.RootSyncNamespace,
 			},
 			Data: map[string][]byte{
 				"username": repositorySecret.Data["username"],
@@ -168,7 +168,7 @@ func (r *runner) runE(cmd *cobra.Command, args []string) error {
 			"kind":       "RootSync",
 			"metadata": map[string]interface{}{
 				"name":      syncName,
-				"namespace": cmdsync.RootSyncNamespace,
+				"namespace": util.RootSyncNamespace,
 			},
 			"spec": map[string]interface{}{
 				"sourceFormat": "unstructured",
diff --git a/internal/cmdsync/delete/command.go b/commands/alpha/sync/delete/command.go
similarity index 98%
rename from internal/cmdsync/delete/command.go
rename to commands/alpha/sync/delete/command.go
index 7a6f2d79..06888254 100644
--- a/internal/cmdsync/delete/command.go
+++ b/commands/alpha/sync/delete/command.go
@@ -19,7 +19,7 @@ import (
 	"fmt"
 	"time"
 
-	"github.com/GoogleContainerTools/kpt/internal/cmdsync"
+	"github.com/GoogleContainerTools/kpt/commands/util"
 	"github.com/GoogleContainerTools/kpt/internal/docs/generated/syncdocs"
 	"github.com/GoogleContainerTools/kpt/internal/errors"
 	"github.com/GoogleContainerTools/kpt/internal/util/porch"
@@ -109,7 +109,7 @@ func (r *runner) runE(cmd *cobra.Command, args []string) error {
 	}
 
 	name := args[0]
-	namespace := cmdsync.RootSyncNamespace
+	namespace := util.RootSyncNamespace
 	if *r.cfg.Namespace != "" {
 		namespace = *r.cfg.Namespace
 	}
diff --git a/internal/cmdsync/get/command.go b/commands/alpha/sync/get/command.go
similarity index 96%
rename from internal/cmdsync/get/command.go
rename to commands/alpha/sync/get/command.go
index 769c4cb4..fb81bc4f 100644
--- a/internal/cmdsync/get/command.go
+++ b/commands/alpha/sync/get/command.go
@@ -18,7 +18,7 @@ import (
 	"context"
 	"fmt"
 
-	"github.com/GoogleContainerTools/kpt/internal/cmdsync"
+	"github.com/GoogleContainerTools/kpt/commands/util"
 	"github.com/GoogleContainerTools/kpt/internal/docs/generated/syncdocs"
 	"github.com/GoogleContainerTools/kpt/internal/errors"
 	"github.com/GoogleContainerTools/kpt/internal/util/porch"
@@ -89,7 +89,7 @@ func (r *runner) runE(cmd *cobra.Command, args []string) error {
 	}
 
 	name := args[0]
-	namespace := cmdsync.RootSyncNamespace
+	namespace := util.RootSyncNamespace
 	if *r.cfg.Namespace != "" {
 		namespace = *r.cfg.Namespace
 	}
diff --git a/commands/synccmd.go b/commands/alpha/sync/synccmd.go
similarity index 85%
rename from commands/synccmd.go
rename to commands/alpha/sync/synccmd.go
index d317415a..762da724 100644
--- a/commands/synccmd.go
+++ b/commands/alpha/sync/synccmd.go
@@ -12,16 +12,16 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-package commands
+package sync
 
 import (
 	"context"
 	"flag"
 	"fmt"
 
-	"github.com/GoogleContainerTools/kpt/internal/cmdsync/create"
-	"github.com/GoogleContainerTools/kpt/internal/cmdsync/delete"
-	"github.com/GoogleContainerTools/kpt/internal/cmdsync/get"
+	"github.com/GoogleContainerTools/kpt/commands/alpha/sync/create"
+	"github.com/GoogleContainerTools/kpt/commands/alpha/sync/delete"
+	"github.com/GoogleContainerTools/kpt/commands/alpha/sync/get"
 	"github.com/GoogleContainerTools/kpt/internal/docs/generated/syncdocs"
 	"github.com/GoogleContainerTools/kpt/internal/util/porch"
 	"github.com/spf13/cobra"
@@ -29,7 +29,7 @@ import (
 	"k8s.io/client-go/rest"
 )
 
-func NewSyncCommand(ctx context.Context, version string) *cobra.Command {
+func NewCommand(ctx context.Context, version string) *cobra.Command {
 	sync := &cobra.Command{
 		Use:   "sync",
 		Short: "[Alpha] " + syncdocs.SyncShort,
diff --git a/internal/cmdwasmpull/command.go b/commands/alpha/wasm/pull/command.go
similarity index 99%
rename from internal/cmdwasmpull/command.go
rename to commands/alpha/wasm/pull/command.go
index 1a1e1383..1e5efc87 100644
--- a/internal/cmdwasmpull/command.go
+++ b/commands/alpha/wasm/pull/command.go
@@ -12,7 +12,7 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-package cmdwasmpull
+package pull
 
 import (
 	"context"
diff --git a/internal/cmdwasmpush/command.go b/commands/alpha/wasm/push/command.go
similarity index 98%
rename from internal/cmdwasmpush/command.go
rename to commands/alpha/wasm/push/command.go
index 1f9a0e62..88f9fc6b 100644
--- a/internal/cmdwasmpush/command.go
+++ b/commands/alpha/wasm/push/command.go
@@ -12,7 +12,7 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-package cmdwasmpush
+package push
 
 import (
 	"context"
diff --git a/commands/wasmcmd.go b/commands/alpha/wasm/wasmcmd.go
similarity index 76%
rename from commands/wasmcmd.go
rename to commands/alpha/wasm/wasmcmd.go
index c3f1cd58..6d539142 100644
--- a/commands/wasmcmd.go
+++ b/commands/alpha/wasm/wasmcmd.go
@@ -12,18 +12,18 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-package commands
+package wasm
 
 import (
 	"context"
 
-	"github.com/GoogleContainerTools/kpt/internal/cmdwasmpull"
-	"github.com/GoogleContainerTools/kpt/internal/cmdwasmpush"
+	"github.com/GoogleContainerTools/kpt/commands/alpha/wasm/pull"
+	"github.com/GoogleContainerTools/kpt/commands/alpha/wasm/push"
 	"github.com/GoogleContainerTools/kpt/internal/docs/generated/wasmdocs"
 	"github.com/spf13/cobra"
 )
 
-func NewWasmCommand(ctx context.Context, version string) *cobra.Command {
+func NewCommand(ctx context.Context, version string) *cobra.Command {
 	wasmcmd := &cobra.Command{
 		Use:   "wasm",
 		Short: "[Alpha] " + wasmdocs.WasmShort,
@@ -31,8 +31,8 @@ func NewWasmCommand(ctx context.Context, version string) *cobra.Command {
 	}
 
 	wasmcmd.AddCommand(
-		cmdwasmpull.NewCommand(ctx),
-		cmdwasmpush.NewCommand(ctx),
+		pull.NewCommand(ctx),
+		push.NewCommand(ctx),
 	)
 
 	return wasmcmd
diff --git a/commands/commands.go b/commands/commands.go
index bed62630..20818211 100644
--- a/commands/commands.go
+++ b/commands/commands.go
@@ -18,6 +18,10 @@ import (
 	"context"
 	"strings"
 
+	"github.com/GoogleContainerTools/kpt/commands/alpha"
+	"github.com/GoogleContainerTools/kpt/commands/fn"
+	"github.com/GoogleContainerTools/kpt/commands/live"
+	"github.com/GoogleContainerTools/kpt/commands/pkg"
 	"github.com/spf13/cobra"
 )
 
@@ -32,10 +36,10 @@ func NormalizeCommand(c ...*cobra.Command) {
 // GetKptCommands returns the set of kpt commands to be registered
 func GetKptCommands(ctx context.Context, name, version string) []*cobra.Command {
 	var c []*cobra.Command
-	fnCmd := GetFnCommand(ctx, name)
-	pkgCmd := GetPkgCommand(ctx, name)
-	liveCmd := GetLiveCommand(ctx, name, version)
-	alphaCmd := GetAlphaCommand(ctx, name, version)
+	fnCmd := fn.GetCommand(ctx, name)
+	pkgCmd := pkg.GetCommand(ctx, name)
+	liveCmd := live.GetCommand(ctx, name, version)
+	alphaCmd := alpha.GetCommand(ctx, name, version)
 
 	c = append(c, pkgCmd, fnCmd, liveCmd, alphaCmd)
 
diff --git a/internal/cmdfndoc/cmdfndoc.go b/commands/fn/doc/cmdfndoc.go
similarity index 97%
rename from internal/cmdfndoc/cmdfndoc.go
rename to commands/fn/doc/cmdfndoc.go
index 7f98c0d4..581c79bf 100644
--- a/internal/cmdfndoc/cmdfndoc.go
+++ b/commands/fn/doc/cmdfndoc.go
@@ -12,8 +12,7 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-// Package cmdfndoc contains the fndoc command
-package cmdfndoc
+package doc
 
 import (
 	"bytes"
diff --git a/commands/fncmd.go b/commands/fn/fncmd.go
similarity index 84%
rename from commands/fncmd.go
rename to commands/fn/fncmd.go
index 20c235a2..7a4668eb 100644
--- a/commands/fncmd.go
+++ b/commands/fn/fncmd.go
@@ -12,13 +12,13 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-package commands
+package fn
 
 import (
 	"context"
 
-	"github.com/GoogleContainerTools/kpt/internal/cmdfndoc"
-	"github.com/GoogleContainerTools/kpt/internal/cmdrender"
+	"github.com/GoogleContainerTools/kpt/commands/fn/doc"
+	"github.com/GoogleContainerTools/kpt/commands/fn/render"
 	"github.com/GoogleContainerTools/kpt/internal/docs/generated/fndocs"
 	"github.com/GoogleContainerTools/kpt/thirdparty/cmdconfig/commands/cmdeval"
 	"github.com/GoogleContainerTools/kpt/thirdparty/cmdconfig/commands/cmdsink"
@@ -26,7 +26,7 @@ import (
 	"github.com/spf13/cobra"
 )
 
-func GetFnCommand(ctx context.Context, name string) *cobra.Command {
+func GetCommand(ctx context.Context, name string) *cobra.Command {
 	functions := &cobra.Command{
 		Use:     "fn",
 		Short:   fndocs.FnShort,
@@ -46,8 +46,8 @@ func GetFnCommand(ctx context.Context, name string) *cobra.Command {
 
 	functions.AddCommand(
 		cmdeval.EvalCommand(ctx, name),
-		cmdrender.NewCommand(ctx, name),
-		cmdfndoc.NewCommand(ctx, name),
+		render.NewCommand(ctx, name),
+		doc.NewCommand(ctx, name),
 		cmdsource.NewCommand(ctx, name),
 		cmdsink.NewCommand(ctx, name),
 	)
diff --git a/internal/cmdrender/cmdrender.go b/commands/fn/render/cmdrender.go
similarity index 99%
rename from internal/cmdrender/cmdrender.go
rename to commands/fn/render/cmdrender.go
index 2627741a..0f1ed18b 100644
--- a/internal/cmdrender/cmdrender.go
+++ b/commands/fn/render/cmdrender.go
@@ -13,7 +13,7 @@
 // limitations under the License.
 
 // Package cmdrender contains the render command
-package cmdrender
+package render
 
 import (
 	"bytes"
diff --git a/internal/cmdapply/cmdapply.go b/commands/live/apply/cmdapply.go
similarity index 99%
rename from internal/cmdapply/cmdapply.go
rename to commands/live/apply/cmdapply.go
index 1b293fb7..2f24cc9c 100644
--- a/internal/cmdapply/cmdapply.go
+++ b/commands/live/apply/cmdapply.go
@@ -12,7 +12,7 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-package cmdapply
+package apply
 
 import (
 	"context"
diff --git a/internal/cmddestroy/cmddestroy.go b/commands/live/destroy/cmddestroy.go
similarity index 99%
rename from internal/cmddestroy/cmddestroy.go
rename to commands/live/destroy/cmddestroy.go
index 3fee25d7..189d4681 100644
--- a/internal/cmddestroy/cmddestroy.go
+++ b/commands/live/destroy/cmddestroy.go
@@ -12,7 +12,7 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-package cmddestroy
+package destroy
 
 import (
 	"context"
diff --git a/internal/cmdliveinit/cmdliveinit.go b/commands/live/init/cmdliveinit.go
similarity index 99%
rename from internal/cmdliveinit/cmdliveinit.go
rename to commands/live/init/cmdliveinit.go
index bdb86c66..2a4e14e5 100644
--- a/internal/cmdliveinit/cmdliveinit.go
+++ b/commands/live/init/cmdliveinit.go
@@ -1,7 +1,7 @@
 // Copyright 2020 Google LLC.
 // SPDX-License-Identifier: Apache-2.0
 
-package cmdliveinit
+package init
 
 import (
 	"context"
diff --git a/internal/cmdinstallrg/cmdinstallrg.go b/commands/live/installrg/cmdinstallrg.go
similarity index 99%
rename from internal/cmdinstallrg/cmdinstallrg.go
rename to commands/live/installrg/cmdinstallrg.go
index bff3f5da..a7afb671 100644
--- a/internal/cmdinstallrg/cmdinstallrg.go
+++ b/commands/live/installrg/cmdinstallrg.go
@@ -12,7 +12,7 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-package cmdinstallrg
+package installrg
 
 import (
 	"context"
diff --git a/commands/livecmd.go b/commands/live/livecmd.go
similarity index 64%
rename from commands/livecmd.go
rename to commands/live/livecmd.go
index 2c43cc2e..d26ea129 100644
--- a/commands/livecmd.go
+++ b/commands/live/livecmd.go
@@ -12,18 +12,19 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-package commands
+package live
 
 import (
 	"context"
 	"os"
 
-	"github.com/GoogleContainerTools/kpt/internal/cmdapply"
-	"github.com/GoogleContainerTools/kpt/internal/cmddestroy"
-	"github.com/GoogleContainerTools/kpt/internal/cmdinstallrg"
-	"github.com/GoogleContainerTools/kpt/internal/cmdliveinit"
-	"github.com/GoogleContainerTools/kpt/internal/cmdmigrate"
-	"github.com/GoogleContainerTools/kpt/internal/cmdstatus"
+	"github.com/GoogleContainerTools/kpt/commands/live/apply"
+	"github.com/GoogleContainerTools/kpt/commands/live/destroy"
+	initialization "github.com/GoogleContainerTools/kpt/commands/live/init"
+	"github.com/GoogleContainerTools/kpt/commands/live/installrg"
+	"github.com/GoogleContainerTools/kpt/commands/live/migrate"
+	"github.com/GoogleContainerTools/kpt/commands/live/status"
+	"github.com/GoogleContainerTools/kpt/commands/util"
 	"github.com/GoogleContainerTools/kpt/internal/docs/generated/livedocs"
 	"github.com/GoogleContainerTools/kpt/pkg/live"
 	"github.com/spf13/cobra"
@@ -32,7 +33,7 @@ import (
 	"sigs.k8s.io/cli-utils/pkg/manifestreader"
 )
 
-func GetLiveCommand(ctx context.Context, _, version string) *cobra.Command {
+func GetCommand(ctx context.Context, _, version string) *cobra.Command {
 	liveCmd := &cobra.Command{
 		Use:   "live",
 		Short: livedocs.LiveShort,
@@ -45,17 +46,17 @@ func GetLiveCommand(ctx context.Context, _, version string) *cobra.Command {
 		ErrOut: os.Stderr,
 	}
 
-	f := newFactory(liveCmd, version)
+	f := util.NewFactory(liveCmd, version)
 	invFactory := live.NewClusterClientFactory()
-	loader := cmdstatus.NewRGInventoryLoader(ctx, f)
+	loader := status.NewRGInventoryLoader(ctx, f)
 
 	// Init command which updates a Kptfile for the ResourceGroup inventory object.
 	klog.V(2).Infoln("init command updates Kptfile for ResourceGroup inventory")
-	initCmd := cmdliveinit.NewCommand(ctx, f, ioStreams)
-	applyCmd := cmdapply.NewCommand(ctx, f, ioStreams, false)
-	destroyCmd := cmddestroy.NewCommand(ctx, f, ioStreams)
-	statusCmd := cmdstatus.NewCommand(ctx, f, invFactory, loader)
-	installRGCmd := cmdinstallrg.NewCommand(ctx, f, ioStreams)
+	initCmd := initialization.NewCommand(ctx, f, ioStreams)
+	applyCmd := apply.NewCommand(ctx, f, ioStreams, false)
+	destroyCmd := destroy.NewCommand(ctx, f, ioStreams)
+	statusCmd := status.NewCommand(ctx, f, invFactory, loader)
+	installRGCmd := installrg.NewCommand(ctx, f, ioStreams)
 	liveCmd.AddCommand(initCmd, applyCmd, destroyCmd, statusCmd, installRGCmd)
 
 	// Add the migrate command to change from ConfigMap to ResourceGroup inventory
@@ -64,7 +65,7 @@ func GetLiveCommand(ctx context.Context, _, version string) *cobra.Command {
 	// TODO: Remove the loader implementation for ConfigMap once we remove the
 	// migrate command.
 	cmLoader := manifestreader.NewManifestLoader(f)
-	migrateCmd := cmdmigrate.NewCommand(ctx, f, cmLoader, ioStreams)
+	migrateCmd := migrate.NewCommand(ctx, f, cmLoader, ioStreams)
 
 	liveCmd.AddCommand(migrateCmd)
 
diff --git a/internal/cmdmigrate/migratecmd.go b/commands/live/migrate/migratecmd.go
similarity index 92%
rename from internal/cmdmigrate/migratecmd.go
rename to commands/live/migrate/migratecmd.go
index 85f2dd28..316dbee8 100644
--- a/internal/cmdmigrate/migratecmd.go
+++ b/commands/live/migrate/migratecmd.go
@@ -1,7 +1,7 @@
 // Copyright 2020 Google LLC.
 // SPDX-License-Identifier: Apache-2.0
 
-package cmdmigrate
+package migrate
 
 import (
 	"bytes"
@@ -12,7 +12,7 @@ import (
 	"os"
 	"path/filepath"
 
-	"github.com/GoogleContainerTools/kpt/internal/cmdliveinit"
+	initialization "github.com/GoogleContainerTools/kpt/commands/live/init"
 	"github.com/GoogleContainerTools/kpt/internal/docs/generated/livedocs"
 	"github.com/GoogleContainerTools/kpt/internal/errors"
 	"github.com/GoogleContainerTools/kpt/internal/pkg"
@@ -36,7 +36,7 @@ import (
 )
 
 // MigrateRunner encapsulates fields for the kpt migrate command.
-type MigrateRunner struct {
+type Runner struct {
 	ctx       context.Context
 	Command   *cobra.Command
 	ioStreams genericclioptions.IOStreams
@@ -59,8 +59,8 @@ func NewRunner(
 	factory util.Factory,
 	cmLoader manifestreader.ManifestLoader,
 	ioStreams genericclioptions.IOStreams,
-) *MigrateRunner {
-	r := &MigrateRunner{
+) *Runner {
+	r := &Runner{
 		ctx:             ctx,
 		factory:         factory,
 		ioStreams:       ioStreams,
@@ -107,7 +107,7 @@ func NewCommand(ctx context.Context, f util.Factory, cmLoader manifestreader.Man
 
 // Run executes the migration from the ConfigMap based inventory to the ResourceGroup
 // based inventory.
-func (mr *MigrateRunner) Run(reader io.Reader, args []string) error {
+func (mr *Runner) Run(reader io.Reader, args []string) error {
 	// Validate the number of arguments.
 	if len(args) > 1 {
 		return fmt.Errorf("too many arguments; migrate requires one directory argument (or stdin)")
@@ -154,7 +154,7 @@ func (mr *MigrateRunner) Run(reader io.Reader, args []string) error {
 // applyCRD applies the ResourceGroup custom resource definition, returning an
 // error if one occurred. Ignores "AlreadyExists" error. Uses the definition
 // stored in the "rgCrd" variable.
-func (mr *MigrateRunner) applyCRD() error {
+func (mr *Runner) applyCRD() error {
 	fmt.Fprint(mr.ioStreams.Out, "  ensuring ResourceGroup CRD exists in cluster...")
 	// Simply return early if this is a dry run
 	if mr.dryRun {
@@ -176,7 +176,7 @@ func (mr *MigrateRunner) applyCRD() error {
 
 // retrieveConfigMapInv retrieves the ConfigMap inventory object or
 // an error if one occurred.
-func (mr *MigrateRunner) retrieveConfigMapInv(reader io.Reader, args []string) (inventory.Info, error) {
+func (mr *Runner) retrieveConfigMapInv(reader io.Reader, args []string) (inventory.Info, error) {
 	fmt.Fprint(mr.ioStreams.Out, "  retrieve the current ConfigMap inventory...")
 	cmReader, err := mr.cmLoader.ManifestReader(reader, args[0])
 	if err != nil {
@@ -208,7 +208,7 @@ func (mr *MigrateRunner) retrieveConfigMapInv(reader io.Reader, args []string) (
 // retrieveInvObjs returns the object references from the passed
 // inventory object by querying the inventory object in the cluster,
 // or an error if one occurred.
-func (mr *MigrateRunner) retrieveInvObjs(cmInvClient inventory.Client,
+func (mr *Runner) retrieveInvObjs(cmInvClient inventory.Client,
 	invObj inventory.Info) ([]object.ObjMetadata, error) {
 	fmt.Fprint(mr.ioStreams.Out, "  retrieve ConfigMap inventory objs...")
 	cmObjs, err := cmInvClient.GetClusterObjs(invObj)
@@ -222,7 +222,7 @@ func (mr *MigrateRunner) retrieveInvObjs(cmInvClient inventory.Client,
 // migrateObjs stores the passed objects in the ResourceGroup inventory
 // object and applies the inventory object to the cluster. Returns
 // an error if one occurred.
-func (mr *MigrateRunner) migrateObjs(rgInvClient inventory.Client,
+func (mr *Runner) migrateObjs(rgInvClient inventory.Client,
 	cmObjs []object.ObjMetadata, reader io.Reader, args []string) error {
 	if err := validateParams(reader, args); err != nil {
 		return err
@@ -266,7 +266,7 @@ func (mr *MigrateRunner) migrateObjs(rgInvClient inventory.Client,
 
 // deleteConfigMapInv removes the passed inventory object from the
 // cluster. Returns an error if one occurred.
-func (mr *MigrateRunner) deleteConfigMapInv(cmInvClient inventory.Client,
+func (mr *Runner) deleteConfigMapInv(cmInvClient inventory.Client,
 	invObj inventory.Info) error {
 	fmt.Fprint(mr.ioStreams.Out, "  deleting old ConfigMap inventory object...")
 	if err := cmInvClient.DeleteInventoryObj(invObj, mr.dryRunStrategy()); err != nil {
@@ -281,7 +281,7 @@ func (mr *MigrateRunner) deleteConfigMapInv(cmInvClient inventory.Client,
 // the input was a directory argument (otherwise there is nothing to delete).
 // Returns an error if one occurs while deleting the file. Does NOT return an
 // error if the inventory template file is missing.
-func (mr *MigrateRunner) deleteConfigMapFile() error {
+func (mr *Runner) deleteConfigMapFile() error {
 	// Only delete the file if the input was a directory argument.
 	if len(mr.dir) > 0 {
 		cmFilename, _, err := common.ExpandDir(mr.dir)
@@ -304,7 +304,7 @@ func (mr *MigrateRunner) deleteConfigMapFile() error {
 }
 
 // dryRunStrategy returns the strategy to use based on user config
-func (mr *MigrateRunner) dryRunStrategy() common.DryRunStrategy {
+func (mr *Runner) dryRunStrategy() common.DryRunStrategy {
 	if mr.dryRun {
 		return common.DryRunClient
 	}
@@ -347,7 +347,7 @@ func cmInvClient(factory util.Factory) (inventory.Client, error) {
 
 // migrateKptfileToRG extracts inventory information from a package's Kptfile
 // into an external resourcegroup file.
-func (mr *MigrateRunner) migrateKptfileToRG(args []string) error {
+func (mr *Runner) migrateKptfileToRG(args []string) error {
 	const op errors.Op = "migratecmd.migrateKptfileToRG"
 	klog.V(4).Infoln("attempting to migrate from Kptfile inventory")
 	fmt.Fprint(mr.ioStreams.Out, "  reading existing Kptfile...")
@@ -379,7 +379,7 @@ func (mr *MigrateRunner) migrateKptfileToRG(args []string) error {
 			return errors.E(op, errors.IO, types.UniquePath(dir), err)
 		}
 
-		err = (&cmdliveinit.ConfigureInventoryInfo{
+		err = (&initialization.ConfigureInventoryInfo{
 			Pkg:         p,
 			Factory:     mr.factory,
 			Quiet:       true,
@@ -398,7 +398,7 @@ func (mr *MigrateRunner) migrateKptfileToRG(args []string) error {
 }
 
 // migrateCMToRG migrates from ConfigMap to resourcegroup object.
-func (mr *MigrateRunner) migrateCMToRG(stdinBytes []byte, args []string) error {
+func (mr *Runner) migrateCMToRG(stdinBytes []byte, args []string) error {
 	// Create the inventory clients for reading inventories based on RG and
 	// ConfigMap.
 	rgInvClient, err := mr.rgInvClientFunc(mr.factory)
@@ -445,7 +445,7 @@ func (mr *MigrateRunner) migrateCMToRG(stdinBytes []byte, args []string) error {
 }
 
 // createRGfile writes the inventory information into the resourcegroup object.
-func (mr *MigrateRunner) createRGfile(ctx context.Context, args []string, prevID string) error {
+func (mr *Runner) createRGfile(ctx context.Context, args []string, prevID string) error {
 	fmt.Fprint(mr.ioStreams.Out, "  creating ResourceGroup object file...")
 	if !mr.dryRun {
 		dir, _, err := pathutil.ResolveAbsAndRelPaths(args[0])
@@ -456,7 +456,7 @@ func (mr *MigrateRunner) createRGfile(ctx context.Context, args []string, prevID
 		if err != nil {
 			return err
 		}
-		err = (&cmdliveinit.ConfigureInventoryInfo{
+		err = (&initialization.ConfigureInventoryInfo{
 			Pkg:         p,
 			Factory:     mr.factory,
 			Quiet:       true,
@@ -466,7 +466,7 @@ func (mr *MigrateRunner) createRGfile(ctx context.Context, args []string, prevID
 		}).Run(ctx)
 
 		if err != nil {
-			var invExistsError *cmdliveinit.InvExistsError
+			var invExistsError *initialization.InvExistsError
 			if errors.As(err, &invExistsError) {
 				fmt.Fprint(mr.ioStreams.Out, "values already exist...")
 			} else {
diff --git a/internal/cmdstatus/cmdstatus.go b/commands/live/status/cmdstatus.go
similarity index 97%
rename from internal/cmdstatus/cmdstatus.go
rename to commands/live/status/cmdstatus.go
index 18c4054d..1fa4be30 100644
--- a/internal/cmdstatus/cmdstatus.go
+++ b/commands/live/status/cmdstatus.go
@@ -1,7 +1,7 @@
-// Copyright 2020 The Kubernetes Authors.
+// Copyright 2022 Google LLC.
 // SPDX-License-Identifier: Apache-2.0
 
-package cmdstatus
+package status
 
 import (
 	"context"
diff --git a/internal/cmdstatus/fake-loader.go b/commands/live/status/fake-loader.go
similarity index 93%
rename from internal/cmdstatus/fake-loader.go
rename to commands/live/status/fake-loader.go
index 6aff107c..48d53279 100644
--- a/internal/cmdstatus/fake-loader.go
+++ b/commands/live/status/fake-loader.go
@@ -1,4 +1,7 @@
-package cmdstatus
+// Copyright 2022 Google LLC.
+// SPDX-License-Identifier: Apache-2.0
+
+package status
 
 import (
 	"context"
diff --git a/internal/cmddiff/cmddiff.go b/commands/pkg/diff/cmddiff.go
similarity index 98%
rename from internal/cmddiff/cmddiff.go
rename to commands/pkg/diff/cmddiff.go
index d33f2f47..2af9877c 100644
--- a/internal/cmddiff/cmddiff.go
+++ b/commands/pkg/diff/cmddiff.go
@@ -12,8 +12,7 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-// Package cmddiff contains the diff command
-package cmddiff
+package diff
 
 import (
 	"context"
diff --git a/internal/cmdget/cmdget.go b/commands/pkg/get/cmdget.go
similarity index 98%
rename from internal/cmdget/cmdget.go
rename to commands/pkg/get/cmdget.go
index 7ec13939..6e1fa1df 100644
--- a/internal/cmdget/cmdget.go
+++ b/commands/pkg/get/cmdget.go
@@ -12,8 +12,7 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-// Package cmdget contains the get command
-package cmdget
+package get
 
 import (
 	"context"
diff --git a/internal/cmdinit/cmdinit.go b/commands/pkg/init/cmdinit.go
similarity index 97%
rename from internal/cmdinit/cmdinit.go
rename to commands/pkg/init/cmdinit.go
index e1d7e8a9..0720c4b7 100644
--- a/internal/cmdinit/cmdinit.go
+++ b/commands/pkg/init/cmdinit.go
@@ -12,8 +12,7 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-// Package cmdinit contains the init command
-package cmdinit
+package init
 
 import (
 	"context"
diff --git a/commands/pkgcmd.go b/commands/pkg/pkgcmd.go
similarity index 72%
rename from commands/pkgcmd.go
rename to commands/pkg/pkgcmd.go
index eb6cd75b..c7666ea1 100644
--- a/commands/pkgcmd.go
+++ b/commands/pkg/pkgcmd.go
@@ -12,21 +12,21 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-package commands
+package pkg
 
 import (
 	"context"
 
-	"github.com/GoogleContainerTools/kpt/internal/cmddiff"
-	"github.com/GoogleContainerTools/kpt/internal/cmdget"
-	"github.com/GoogleContainerTools/kpt/internal/cmdinit"
-	"github.com/GoogleContainerTools/kpt/internal/cmdupdate"
+	"github.com/GoogleContainerTools/kpt/commands/pkg/diff"
+	"github.com/GoogleContainerTools/kpt/commands/pkg/get"
+	initialization "github.com/GoogleContainerTools/kpt/commands/pkg/init"
+	"github.com/GoogleContainerTools/kpt/commands/pkg/update"
 	"github.com/GoogleContainerTools/kpt/internal/docs/generated/pkgdocs"
 	"github.com/GoogleContainerTools/kpt/thirdparty/cmdconfig/commands/cmdtree"
 	"github.com/spf13/cobra"
 )
 
-func GetPkgCommand(ctx context.Context, name string) *cobra.Command {
+func GetCommand(ctx context.Context, name string) *cobra.Command {
 	pkg := &cobra.Command{
 		Use:     "pkg",
 		Short:   pkgdocs.PkgShort,
@@ -45,8 +45,8 @@ func GetPkgCommand(ctx context.Context, name string) *cobra.Command {
 	}
 
 	pkg.AddCommand(
-		cmdget.NewCommand(ctx, name), cmdinit.NewCommand(ctx, name),
-		cmdupdate.NewCommand(ctx, name), cmddiff.NewCommand(ctx, name),
+		get.NewCommand(ctx, name), initialization.NewCommand(ctx, name),
+		update.NewCommand(ctx, name), diff.NewCommand(ctx, name),
 		cmdtree.NewCommand(ctx, name),
 	)
 	return pkg
diff --git a/internal/cmdupdate/cmdupdate.go b/commands/pkg/update/cmdupdate.go
similarity index 98%
rename from internal/cmdupdate/cmdupdate.go
rename to commands/pkg/update/cmdupdate.go
index 938e5786..12a6b1d2 100644
--- a/internal/cmdupdate/cmdupdate.go
+++ b/commands/pkg/update/cmdupdate.go
@@ -12,8 +12,7 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-// Package cmdupdate contains the update command
-package cmdupdate
+package update
 
 import (
 	"context"
diff --git a/internal/cmdsync/common.go b/commands/util/common.go
similarity index 97%
rename from internal/cmdsync/common.go
rename to commands/util/common.go
index 87ea9c91..027834aa 100644
--- a/internal/cmdsync/common.go
+++ b/commands/util/common.go
@@ -12,7 +12,7 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-package cmdsync
+package util
 
 const (
 	RootSyncNamespace = "config-management-system"
diff --git a/commands/factory.go b/commands/util/factory.go
similarity index 97%
rename from commands/factory.go
rename to commands/util/factory.go
index 5a531f14..cb04ca6f 100644
--- a/commands/factory.go
+++ b/commands/util/factory.go
@@ -12,7 +12,7 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-package commands
+package util
 
 import (
 	"context"
@@ -29,7 +29,7 @@ import (
 	"sigs.k8s.io/cli-utils/pkg/flowcontrol"
 )
 
-func newFactory(cmd *cobra.Command, version string) cluster.Factory {
+func NewFactory(cmd *cobra.Command, version string) cluster.Factory {
 	flags := cmd.PersistentFlags()
 	kubeConfigFlags := genericclioptions.NewConfigFlags(true).
 		WithDeprecatedPasswordFlag()
diff --git a/internal/errors/resolver/live.go b/internal/errors/resolver/live.go
index 6086601a..ce70321c 100644
--- a/internal/errors/resolver/live.go
+++ b/internal/errors/resolver/live.go
@@ -15,7 +15,7 @@
 package resolver
 
 import (
-	"github.com/GoogleContainerTools/kpt/internal/cmdliveinit"
+	initialization "github.com/GoogleContainerTools/kpt/commands/live/init"
 	"github.com/GoogleContainerTools/kpt/internal/cmdutil"
 	"github.com/GoogleContainerTools/kpt/internal/errors"
 	"github.com/GoogleContainerTools/kpt/internal/pkg"
@@ -138,7 +138,7 @@ func (*liveErrorResolver) Resolve(err error) (ResolvedResult, bool) {
 		}, true
 	}
 
-	var invExistsError *cmdliveinit.InvExistsError
+	var invExistsError *initialization.InvExistsError
 	if errors.As(err, &invExistsError) {
 		return ResolvedResult{
 			Message: ExecuteTemplate(invInfoAlreadyExistsMsg, map[string]interface{}{
@@ -147,7 +147,7 @@ func (*liveErrorResolver) Resolve(err error) (ResolvedResult, bool) {
 		}, true
 	}
 
-	var invInfoInRGAlreadyExistsError *cmdliveinit.InvInRGExistsError
+	var invInfoInRGAlreadyExistsError *initialization.InvInRGExistsError
 	if errors.As(err, &invInfoInRGAlreadyExistsError) {
 		return ResolvedResult{
 			Message: ExecuteTemplate(invInfoInRGAlreadyExistsMsg, map[string]interface{}{
@@ -156,7 +156,7 @@ func (*liveErrorResolver) Resolve(err error) (ResolvedResult, bool) {
 		}, true
 	}
 
-	var invInKfExistsError *cmdliveinit.InvInKfExistsError
+	var invInKfExistsError *initialization.InvInKfExistsError
 	if errors.As(err, &invInKfExistsError) {
 		return ResolvedResult{
 			Message: ExecuteTemplate(invInfoInKfAlreadyExistsMsg, map[string]interface{}{


Test patch:
diff --git a/internal/cmdreporeg/command_test.go b/commands/alpha/repo/reg/command_test.go
similarity index 99%
rename from internal/cmdreporeg/command_test.go
rename to commands/alpha/repo/reg/command_test.go
index 67e28c82..a8038128 100644
--- a/internal/cmdreporeg/command_test.go
+++ b/commands/alpha/repo/reg/command_test.go
@@ -12,7 +12,7 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-package cmdreporeg
+package reg
 
 import (
 	"encoding/json"
diff --git a/internal/cmdrpkgcopy/command_test.go b/commands/alpha/rpkg/copy/command_test.go
similarity index 98%
rename from internal/cmdrpkgcopy/command_test.go
rename to commands/alpha/rpkg/copy/command_test.go
index 2a42987b..a89542f3 100644
--- a/internal/cmdrpkgcopy/command_test.go
+++ b/commands/alpha/rpkg/copy/command_test.go
@@ -12,7 +12,7 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-package cmdrpkgcopy
+package copy
 
 import (
 	"testing"
diff --git a/internal/cmdfndoc/cmdfndoc_test.go b/commands/fn/doc/cmdfndoc_test.go
similarity index 90%
rename from internal/cmdfndoc/cmdfndoc_test.go
rename to commands/fn/doc/cmdfndoc_test.go
index e764b086..59677535 100644
--- a/internal/cmdfndoc/cmdfndoc_test.go
+++ b/commands/fn/doc/cmdfndoc_test.go
@@ -12,13 +12,13 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-package cmdfndoc_test
+package doc_test
 
 import (
 	"bytes"
 	"testing"
 
-	"github.com/GoogleContainerTools/kpt/internal/cmdfndoc"
+	"github.com/GoogleContainerTools/kpt/commands/fn/doc"
 	"github.com/GoogleContainerTools/kpt/internal/printer/fake"
 	"sigs.k8s.io/kustomize/kyaml/testutil"
 )
@@ -45,7 +45,7 @@ func TestFnDoc(t *testing.T) {
 
 	for _, tc := range testcases {
 		b := &bytes.Buffer{}
-		runner := cmdfndoc.NewRunner(fake.CtxWithPrinter(b, b), "kpt")
+		runner := doc.NewRunner(fake.CtxWithPrinter(b, b), "kpt")
 		runner.Image = tc.image
 		err := runner.Command.Execute()
 		if tc.expectErr == "" {
diff --git a/internal/cmdrender/cmdrender_test.go b/commands/fn/render/cmdrender_test.go
similarity index 98%
rename from internal/cmdrender/cmdrender_test.go
rename to commands/fn/render/cmdrender_test.go
index 3dd4b6d2..7a2c7684 100644
--- a/internal/cmdrender/cmdrender_test.go
+++ b/commands/fn/render/cmdrender_test.go
@@ -12,7 +12,7 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-package cmdrender
+package render
 
 import (
 	"os"
diff --git a/internal/cmdapply/cmdapply_test.go b/commands/live/apply/cmdapply_test.go
similarity index 99%
rename from internal/cmdapply/cmdapply_test.go
rename to commands/live/apply/cmdapply_test.go
index a19da430..003a4072 100644
--- a/internal/cmdapply/cmdapply_test.go
+++ b/commands/live/apply/cmdapply_test.go
@@ -12,7 +12,7 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-package cmdapply
+package apply
 
 import (
 	"path/filepath"
diff --git a/internal/cmddestroy/cmddestroy_test.go b/commands/live/destroy/cmddestroy_test.go
similarity index 99%
rename from internal/cmddestroy/cmddestroy_test.go
rename to commands/live/destroy/cmddestroy_test.go
index a50ad051..f1ae9622 100644
--- a/internal/cmddestroy/cmddestroy_test.go
+++ b/commands/live/destroy/cmddestroy_test.go
@@ -12,7 +12,7 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-package cmddestroy
+package destroy
 
 import (
 	"path/filepath"
diff --git a/internal/cmdliveinit/cmdliveinit_test.go b/commands/live/init/cmdliveinit_test.go
similarity index 99%
rename from internal/cmdliveinit/cmdliveinit_test.go
rename to commands/live/init/cmdliveinit_test.go
index 71296d7d..0f7a8388 100644
--- a/internal/cmdliveinit/cmdliveinit_test.go
+++ b/commands/live/init/cmdliveinit_test.go
@@ -1,7 +1,7 @@
 // Copyright 2020 Google LLC.
 // SPDX-License-Identifier: Apache-2.0
 
-package cmdliveinit
+package init
 
 import (
 	"os"
diff --git a/internal/cmdmigrate/migratecmd_test.go b/commands/live/migrate/migratecmd_test.go
similarity index 99%
rename from internal/cmdmigrate/migratecmd_test.go
rename to commands/live/migrate/migratecmd_test.go
index 850fb263..9c326a7e 100644
--- a/internal/cmdmigrate/migratecmd_test.go
+++ b/commands/live/migrate/migratecmd_test.go
@@ -1,7 +1,7 @@
 // Copyright 2020 Google LLC.
 // SPDX-License-Identifier: Apache-2.0
 
-package cmdmigrate
+package migrate
 
 import (
 	"os"
diff --git a/internal/cmdstatus/cmdstatus_test.go b/commands/live/status/cmdstatus_test.go
similarity index 99%
rename from internal/cmdstatus/cmdstatus_test.go
rename to commands/live/status/cmdstatus_test.go
index f961e570..1f369179 100644
--- a/internal/cmdstatus/cmdstatus_test.go
+++ b/commands/live/status/cmdstatus_test.go
@@ -1,7 +1,7 @@
-// Copyright 2020 The Kubernetes Authors.
+// Copyright 2022 Google LLC.
 // SPDX-License-Identifier: Apache-2.0
 
-package cmdstatus
+package status
 
 import (
 	"bytes"
diff --git a/internal/cmddiff/cmddiff_test.go b/commands/pkg/diff/cmddiff_test.go
similarity index 85%
rename from internal/cmddiff/cmddiff_test.go
rename to commands/pkg/diff/cmddiff_test.go
index f70db5bb..645579e4 100644
--- a/internal/cmddiff/cmddiff_test.go
+++ b/commands/pkg/diff/cmddiff_test.go
@@ -12,15 +12,15 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-package cmddiff_test
+package diff_test
 
 import (
 	"os"
 	"path/filepath"
 	"testing"
 
-	"github.com/GoogleContainerTools/kpt/internal/cmddiff"
-	"github.com/GoogleContainerTools/kpt/internal/cmdget"
+	"github.com/GoogleContainerTools/kpt/commands/pkg/diff"
+	"github.com/GoogleContainerTools/kpt/commands/pkg/get"
 	"github.com/GoogleContainerTools/kpt/internal/printer/fake"
 	"github.com/GoogleContainerTools/kpt/internal/testutil"
 	"github.com/spf13/cobra"
@@ -32,7 +32,7 @@ func TestMain(m *testing.M) {
 }
 
 func TestCmdInvalidDiffType(t *testing.T) {
-	runner := cmddiff.NewRunner(fake.CtxWithDefaultPrinter(), "")
+	runner := diff.NewRunner(fake.CtxWithDefaultPrinter(), "")
 	runner.C.SetArgs([]string{"--diff-type", "invalid"})
 	err := runner.C.Execute()
 	assert.EqualError(t,
@@ -41,7 +41,7 @@ func TestCmdInvalidDiffType(t *testing.T) {
 }
 
 func TestCmdInvalidDiffTool(t *testing.T) {
-	runner := cmddiff.NewRunner(fake.CtxWithDefaultPrinter(), "")
+	runner := diff.NewRunner(fake.CtxWithDefaultPrinter(), "")
 	runner.C.SetArgs([]string{"--diff-tool", "nodiff"})
 	err := runner.C.Execute()
 	assert.EqualError(t,
@@ -60,12 +60,12 @@ func TestCmdExecute(t *testing.T) {
 
 	dest := filepath.Join(w.WorkspaceDirectory, g.RepoName)
 
-	getRunner := cmdget.NewRunner(fake.CtxWithDefaultPrinter(), "")
+	getRunner := get.NewRunner(fake.CtxWithDefaultPrinter(), "")
 	getRunner.Command.SetArgs([]string{"file://" + g.RepoDirectory + ".git/", "./"})
 	err := getRunner.Command.Execute()
 	assert.NoError(t, err)
 
-	runner := cmddiff.NewRunner(fake.CtxWithDefaultPrinter(), "")
+	runner := diff.NewRunner(fake.CtxWithDefaultPrinter(), "")
 	runner.C.SetArgs([]string{dest, "--diff-type", "local"})
 	err = runner.C.Execute()
 	assert.NoError(t, err)
@@ -81,7 +81,7 @@ func TestCmd_flagAndArgParsing_Symlink(t *testing.T) {
 	assert.NoError(t, err)
 
 	// verify the branch ref is set to the correct value
-	r := cmddiff.NewRunner(fake.CtxWithDefaultPrinter(), "kpt")
+	r := diff.NewRunner(fake.CtxWithDefaultPrinter(), "kpt")
 	r.C.RunE = NoOpRunE
 	r.C.SetArgs([]string{"foo" + "@refs/heads/foo"})
 	err = r.C.Execute()
diff --git a/internal/cmdget/cmdget_test.go b/commands/pkg/get/cmdget_test.go
similarity index 89%
rename from internal/cmdget/cmdget_test.go
rename to commands/pkg/get/cmdget_test.go
index 4fcfb883..31afaa6d 100644
--- a/internal/cmdget/cmdget_test.go
+++ b/commands/pkg/get/cmdget_test.go
@@ -12,7 +12,7 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-package cmdget_test
+package get_test
 
 import (
 	"fmt"
@@ -21,7 +21,7 @@ import (
 	"runtime"
 	"testing"
 
-	"github.com/GoogleContainerTools/kpt/internal/cmdget"
+	"github.com/GoogleContainerTools/kpt/commands/pkg/get"
 	"github.com/GoogleContainerTools/kpt/internal/printer/fake"
 	"github.com/GoogleContainerTools/kpt/internal/testutil"
 	kptfilev1 "github.com/GoogleContainerTools/kpt/pkg/api/kptfile/v1"
@@ -46,7 +46,7 @@ func TestCmd_execute(t *testing.T) {
 
 	dest := filepath.Join(w.WorkspaceDirectory, g.RepoName)
 
-	r := cmdget.NewRunner(fake.CtxWithDefaultPrinter(), "kpt")
+	r := get.NewRunner(fake.CtxWithDefaultPrinter(), "kpt")
 	// defaults LOCAL_DEST_DIR to current working directory
 	r.Command.SetArgs([]string{"file://" + g.RepoDirectory + ".git/"})
 	err := r.Command.Execute()
@@ -107,7 +107,7 @@ func TestCmdMainBranch_execute(t *testing.T) {
 		t.FailNow()
 	}
 
-	r := cmdget.NewRunner(fake.CtxWithDefaultPrinter(), "kpt")
+	r := get.NewRunner(fake.CtxWithDefaultPrinter(), "kpt")
 	r.Command.SetArgs([]string{"file://" + g.RepoDirectory + ".git/", "./"})
 	err = r.Command.Execute()
 
@@ -152,7 +152,7 @@ func TestCmdMainBranch_execute(t *testing.T) {
 
 // TestCmd_fail verifies that that command returns an error rather than exiting the process
 func TestCmd_fail(t *testing.T) {
-	r := cmdget.NewRunner(fake.CtxWithDefaultPrinter(), "kpt")
+	r := get.NewRunner(fake.CtxWithDefaultPrinter(), "kpt")
 	r.Command.SilenceErrors = true
 	r.Command.SilenceUsage = true
 	r.Command.SetArgs([]string{"file://" + filepath.Join("not", "real", "dir") + ".git/@master", "./"})
@@ -200,14 +200,14 @@ func TestCmd_Execute_flagAndArgParsing(t *testing.T) {
 	testCases := map[string]struct {
 		argsFunc    func(repo, dir string) []string
 		runE        func(*cobra.Command, []string) error
-		validations func(repo, dir string, r *cmdget.Runner, err error)
+		validations func(repo, dir string, r *get.Runner, err error)
 	}{
 		"must have at least 1 arg": {
 			argsFunc: func(repo, _ string) []string {
 				return []string{}
 			},
 			runE: failRun,
-			validations: func(_, _ string, r *cmdget.Runner, err error) {
+			validations: func(_, _ string, r *get.Runner, err error) {
 				assert.EqualError(t, err, "requires at least 1 arg(s), only received 0")
 			},
 		},
@@ -216,7 +216,7 @@ func TestCmd_Execute_flagAndArgParsing(t *testing.T) {
 				return []string{"foo", "bar", "baz"}
 			},
 			runE: failRun,
-			validations: func(_, _ string, r *cmdget.Runner, err error) {
+			validations: func(_, _ string, r *get.Runner, err error) {
 				assert.Error(t, err)
 				assert.Contains(t, err.Error(), "ambiguous repo/dir@version specify '.git' in argument")
 			},
@@ -226,7 +226,7 @@ func TestCmd_Execute_flagAndArgParsing(t *testing.T) {
 				return []string{"something://foo.git/@master", "./"}
 			},
 			runE: NoOpRunE,
-			validations: func(_, _ string, r *cmdget.Runner, err error) {
+			validations: func(_, _ string, r *get.Runner, err error) {
 				assert.NoError(t, err)
 				assert.Equal(t, "master", r.Get.Git.Ref)
 				assert.Equal(t, "something://foo", r.Get.Git.Repo)
@@ -238,7 +238,7 @@ func TestCmd_Execute_flagAndArgParsing(t *testing.T) {
 				return []string{fmt.Sprintf("file://%s.git/blueprints/java", repo), "."}
 			},
 			runE: NoOpRunE,
-			validations: func(repo, _ string, r *cmdget.Runner, err error) {
+			validations: func(repo, _ string, r *get.Runner, err error) {
 				assert.NoError(t, err)
 				assert.Equal(t, fmt.Sprintf("file://%s", repo), r.Get.Git.Repo)
 				assert.Equal(t, "master", r.Get.Git.Ref)
@@ -251,7 +251,7 @@ func TestCmd_Execute_flagAndArgParsing(t *testing.T) {
 				return []string{fmt.Sprintf("file://%s.git/blueprints/java", repo), "foo/../bar/../"}
 			},
 			runE: NoOpRunE,
-			validations: func(repo, _ string, r *cmdget.Runner, err error) {
+			validations: func(repo, _ string, r *get.Runner, err error) {
 				assert.NoError(t, err)
 				assert.Equal(t, fmt.Sprintf("file://%s", repo), r.Get.Git.Repo)
 				assert.Equal(t, "master", r.Get.Git.Ref)
@@ -264,7 +264,7 @@ func TestCmd_Execute_flagAndArgParsing(t *testing.T) {
 				return []string{fmt.Sprintf("file://%s.git/blueprints/java", repo), "./foo/../bar/../baz"}
 			},
 			runE: NoOpRunE,
-			validations: func(repo, _ string, r *cmdget.Runner, err error) {
+			validations: func(repo, _ string, r *get.Runner, err error) {
 				assert.NoError(t, err)
 				assert.Equal(t, fmt.Sprintf("file://%s", repo), r.Get.Git.Repo)
 				assert.Equal(t, "master", r.Get.Git.Ref)
@@ -277,7 +277,7 @@ func TestCmd_Execute_flagAndArgParsing(t *testing.T) {
 				return []string{fmt.Sprintf("file://%s.git/blueprints/java", repo), "/foo/../bar/../baz"}
 			},
 			runE: NoOpRunE,
-			validations: func(repo, _ string, r *cmdget.Runner, err error) {
+			validations: func(repo, _ string, r *get.Runner, err error) {
 				assert.NoError(t, err)
 				assert.Equal(t, fmt.Sprintf("file://%s", repo), r.Get.Git.Repo)
 				assert.Equal(t, "master", r.Get.Git.Ref)
@@ -290,7 +290,7 @@ func TestCmd_Execute_flagAndArgParsing(t *testing.T) {
 				return []string{fmt.Sprintf("file://%s.git", repo), filepath.Join(dir, "my-app")}
 			},
 			runE: NoOpRunE,
-			validations: func(repo, dir string, r *cmdget.Runner, err error) {
+			validations: func(repo, dir string, r *get.Runner, err error) {
 				assert.NoError(t, err)
 				assert.Equal(t, fmt.Sprintf("file://%s", repo), r.Get.Git.Repo)
 				assert.Equal(t, "master", r.Get.Git.Ref)
@@ -302,7 +302,7 @@ func TestCmd_Execute_flagAndArgParsing(t *testing.T) {
 				return []string{fmt.Sprintf("file://%s.git/baz", repo), filepath.Join(dir, "my-app")}
 			},
 			runE: NoOpRunE,
-			validations: func(repo, dir string, r *cmdget.Runner, err error) {
+			validations: func(repo, dir string, r *get.Runner, err error) {
 				assert.NoError(t, err)
 				assert.Equal(t, fmt.Sprintf("file://%s", repo), r.Get.Git.Repo)
 				assert.Equal(t, "/baz", r.Get.Git.Directory)
@@ -315,7 +315,7 @@ func TestCmd_Execute_flagAndArgParsing(t *testing.T) {
 				return []string{fmt.Sprintf("file://%s.git/baz@v1", repo), filepath.Join(dir, "my-app")}
 			},
 			runE: NoOpRunE,
-			validations: func(repo, dir string, r *cmdget.Runner, err error) {
+			validations: func(repo, dir string, r *get.Runner, err error) {
 				assert.NoError(t, err)
 				assert.Equal(t, fmt.Sprintf("file://%s", repo), r.Get.Git.Repo)
 				assert.Equal(t, "/baz", r.Get.Git.Directory)
@@ -328,7 +328,7 @@ func TestCmd_Execute_flagAndArgParsing(t *testing.T) {
 				return []string{fmt.Sprintf("file://%s.git", repo), filepath.Join(dir, "package")}
 			},
 			runE: NoOpRunE,
-			validations: func(repo, dir string, r *cmdget.Runner, err error) {
+			validations: func(repo, dir string, r *get.Runner, err error) {
 				assert.NoError(t, err)
 				assert.Equal(t, fmt.Sprintf("file://%s", repo), r.Get.Git.Repo)
 				assert.Equal(t, "master", r.Get.Git.Ref)
@@ -340,7 +340,7 @@ func TestCmd_Execute_flagAndArgParsing(t *testing.T) {
 				return []string{"/", filepath.Join(dir, "package", "my-app")}
 			},
 			runE: failRun,
-			validations: func(repo, dir string, r *cmdget.Runner, err error) {
+			validations: func(repo, dir string, r *get.Runner, err error) {
 				assert.Error(t, err)
 				assert.Contains(t, err.Error(), "specify '.git'")
 			},
@@ -350,7 +350,7 @@ func TestCmd_Execute_flagAndArgParsing(t *testing.T) {
 				return []string{fmt.Sprintf("file://%s.git", repo), filepath.Join(dir, "package"), "--strategy=fast-forward"}
 			},
 			runE: NoOpRunE,
-			validations: func(repo, dir string, r *cmdget.Runner, err error) {
+			validations: func(repo, dir string, r *get.Runner, err error) {
 				assert.NoError(t, err)
 				assert.Equal(t, fmt.Sprintf("file://%s", repo), r.Get.Git.Repo)
 				assert.Equal(t, "master", r.Get.Git.Ref)
@@ -363,7 +363,7 @@ func TestCmd_Execute_flagAndArgParsing(t *testing.T) {
 				return []string{fmt.Sprintf("file://%s.git", repo), filepath.Join(dir, "package"), "--strategy=does-not-exist"}
 			},
 			runE: failRun,
-			validations: func(repo, dir string, r *cmdget.Runner, err error) {
+			validations: func(repo, dir string, r *get.Runner, err error) {
 				assert.Error(t, err)
 				assert.Contains(t, err.Error(), "unknown update strategy \"does-not-exist\"")
 			},
@@ -378,7 +378,7 @@ func TestCmd_Execute_flagAndArgParsing(t *testing.T) {
 			})
 			defer clean()
 
-			r := cmdget.NewRunner(fake.CtxWithDefaultPrinter(), "kpt")
+			r := get.NewRunner(fake.CtxWithDefaultPrinter(), "kpt")
 			r.Command.SilenceErrors = true
 			r.Command.SilenceUsage = true
 			r.Command.RunE = tc.runE
@@ -398,7 +398,7 @@ func TestCmd_flagAndArgParsing_Symlink(t *testing.T) {
 	err = os.Symlink(filepath.Join("path", "to", "pkg", "dir"), "link")
 	assert.NoError(t, err)
 
-	r := cmdget.NewRunner(fake.CtxWithDefaultPrinter(), "kpt")
+	r := get.NewRunner(fake.CtxWithDefaultPrinter(), "kpt")
 	r.Command.RunE = NoOpRunE
 	r.Command.SetArgs([]string{"file://foo.git" + "@refs/heads/foo", "link"})
 	err = r.Command.Execute()
@@ -410,7 +410,7 @@ func TestCmd_flagAndArgParsing_Symlink(t *testing.T) {
 	// make the link broken by deleting the dir
 	err = os.RemoveAll(filepath.Join("path", "to", "pkg", "dir"))
 	assert.NoError(t, err)
-	r = cmdget.NewRunner(fake.CtxWithDefaultPrinter(), "kpt")
+	r = get.NewRunner(fake.CtxWithDefaultPrinter(), "kpt")
 	r.Command.RunE = NoOpRunE
 	r.Command.SetArgs([]string{"file://foo.git" + "@refs/heads/foo", "link"})
 	err = r.Command.Execute()
diff --git a/internal/cmdinit/cmdinit_test.go b/commands/pkg/init/cmdinit_test.go
similarity index 92%
rename from internal/cmdinit/cmdinit_test.go
rename to commands/pkg/init/cmdinit_test.go
index 6748d8c8..b013fc1a 100644
--- a/internal/cmdinit/cmdinit_test.go
+++ b/commands/pkg/init/cmdinit_test.go
@@ -12,7 +12,7 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-package cmdinit_test
+package init_test
 
 import (
 	"os"
@@ -20,8 +20,8 @@ import (
 	"strings"
 	"testing"
 
+	initialization "github.com/GoogleContainerTools/kpt/commands/pkg/init"
 	"github.com/GoogleContainerTools/kpt/internal/builtins"
-	"github.com/GoogleContainerTools/kpt/internal/cmdinit"
 	"github.com/GoogleContainerTools/kpt/internal/printer/fake"
 	"github.com/GoogleContainerTools/kpt/internal/testutil"
 	"github.com/GoogleContainerTools/kpt/internal/util/man"
@@ -37,7 +37,7 @@ func TestCmd(t *testing.T) {
 	d := t.TempDir()
 	assert.NoError(t, os.Mkdir(filepath.Join(d, "my-pkg"), 0700))
 
-	r := cmdinit.NewRunner(fake.CtxWithDefaultPrinter(), "kpt")
+	r := initialization.NewRunner(fake.CtxWithDefaultPrinter(), "kpt")
 	r.Command.SetArgs([]string{filepath.Join(d, "my-pkg"), "--description", "my description"})
 	err := r.Command.Execute()
 	assert.NoError(t, err)
@@ -103,7 +103,7 @@ func TestCmd_currentDir(t *testing.T) {
 			}
 		}()
 
-		r := cmdinit.NewRunner(fake.CtxWithDefaultPrinter(), "kpt")
+		r := initialization.NewRunner(fake.CtxWithDefaultPrinter(), "kpt")
 		r.Command.SetArgs([]string{".", "--description", "my description"})
 		return r.Command.Execute()
 	}()
@@ -141,7 +141,7 @@ func TestCmd_DefaultToCurrentDir(t *testing.T) {
 			}
 		}()
 
-		r := cmdinit.NewRunner(fake.CtxWithDefaultPrinter(), "kpt")
+		r := initialization.NewRunner(fake.CtxWithDefaultPrinter(), "kpt")
 		r.Command.SetArgs([]string{"--description", "my description"})
 		return r.Command.Execute()
 	}()
@@ -164,7 +164,7 @@ info:
 // TestCmd_failExists verifies the command throws and error if the directory exists
 func TestCmd_failNotExists(t *testing.T) {
 	d := t.TempDir()
-	r := cmdinit.NewRunner(fake.CtxWithDefaultPrinter(), "kpt")
+	r := initialization.NewRunner(fake.CtxWithDefaultPrinter(), "kpt")
 	r.Command.SetArgs([]string{filepath.Join(d, "my-pkg"), "--description", "my description"})
 	err := r.Command.Execute()
 	if assert.Error(t, err) {
diff --git a/internal/cmdupdate/cmdupdate_test.go b/commands/pkg/update/cmdupdate_test.go
similarity index 94%
rename from internal/cmdupdate/cmdupdate_test.go
rename to commands/pkg/update/cmdupdate_test.go
index 1d264c54..3c264453 100644
--- a/internal/cmdupdate/cmdupdate_test.go
+++ b/commands/pkg/update/cmdupdate_test.go
@@ -12,7 +12,7 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-package cmdupdate_test
+package update_test
 
 import (
 	"bytes"
@@ -24,8 +24,8 @@ import (
 	"testing"
 	"text/template"
 
-	"github.com/GoogleContainerTools/kpt/internal/cmdget"
-	"github.com/GoogleContainerTools/kpt/internal/cmdupdate"
+	"github.com/GoogleContainerTools/kpt/commands/pkg/get"
+	"github.com/GoogleContainerTools/kpt/commands/pkg/update"
 	"github.com/GoogleContainerTools/kpt/internal/gitutil"
 	"github.com/GoogleContainerTools/kpt/internal/printer/fake"
 	"github.com/GoogleContainerTools/kpt/internal/testutil"
@@ -53,7 +53,7 @@ func TestCmd_execute(t *testing.T) {
 	dest := filepath.Join(w.WorkspaceDirectory, g.RepoName)
 
 	// clone the repo
-	getCmd := cmdget.NewRunner(fake.CtxWithDefaultPrinter(), "kpt")
+	getCmd := get.NewRunner(fake.CtxWithDefaultPrinter(), "kpt")
 	getCmd.Command.SetArgs([]string{"file://" + g.RepoDirectory + ".git", w.WorkspaceDirectory})
 	err := getCmd.Command.Execute()
 	if !assert.NoError(t, err) {
@@ -85,7 +85,7 @@ func TestCmd_execute(t *testing.T) {
 	}
 
 	// update the cloned package
-	updateCmd := cmdupdate.NewRunner(fake.CtxWithDefaultPrinter(), "kpt")
+	updateCmd := update.NewRunner(fake.CtxWithDefaultPrinter(), "kpt")
 	updateCmd.Command.SetArgs([]string{g.RepoName, "--strategy", "fast-forward"})
 	if !assert.NoError(t, updateCmd.Command.Execute()) {
 		return
@@ -144,7 +144,7 @@ func TestCmd_successUnCommitted(t *testing.T) {
 	dest := filepath.Join(w.WorkspaceDirectory, g.RepoName)
 
 	// clone the repo
-	getCmd := cmdget.NewRunner(fake.CtxWithDefaultPrinter(), "kpt")
+	getCmd := get.NewRunner(fake.CtxWithDefaultPrinter(), "kpt")
 	getCmd.Command.SetArgs([]string{"file://" + g.RepoDirectory + ".git", w.WorkspaceDirectory})
 	err := getCmd.Command.Execute()
 	if !assert.NoError(t, err) {
@@ -166,7 +166,7 @@ func TestCmd_successUnCommitted(t *testing.T) {
 	}
 
 	// update the cloned package
-	updateCmd := cmdupdate.NewRunner(fake.CtxWithDefaultPrinter(), "kpt")
+	updateCmd := update.NewRunner(fake.CtxWithDefaultPrinter(), "kpt")
 	updateCmd.Command.SetArgs([]string{g.RepoName})
 	err = updateCmd.Command.Execute()
 	if !assert.NoError(t, err) {
@@ -194,7 +194,7 @@ func TestCmd_successNoGit(t *testing.T) {
 	dest := filepath.Join(w.WorkspaceDirectory, g.RepoName)
 
 	// clone the repo
-	getCmd := cmdget.NewRunner(fake.CtxWithDefaultPrinter(), "kpt")
+	getCmd := get.NewRunner(fake.CtxWithDefaultPrinter(), "kpt")
 	getCmd.Command.SetArgs([]string{"file://" + g.RepoDirectory + ".git", w.WorkspaceDirectory})
 	err = getCmd.Command.Execute()
 	if !assert.NoError(t, err) {
@@ -216,7 +216,7 @@ func TestCmd_successNoGit(t *testing.T) {
 	}
 
 	// update the cloned package
-	updateCmd := cmdupdate.NewRunner(fake.CtxWithDefaultPrinter(), "kpt")
+	updateCmd := update.NewRunner(fake.CtxWithDefaultPrinter(), "kpt")
 	updateCmd.Command.SetArgs([]string{g.RepoName})
 	err = updateCmd.Command.Execute()
 	if !assert.NoError(t, err) {
@@ -242,7 +242,7 @@ func TestCmd_onlyVersionAsInput(t *testing.T) {
 	dest := filepath.Join(w.WorkspaceDirectory, g.RepoName)
 
 	// clone the repo
-	getCmd := cmdget.NewRunner(fake.CtxWithDefaultPrinter(), "kpt")
+	getCmd := get.NewRunner(fake.CtxWithDefaultPrinter(), "kpt")
 	getCmd.Command.SetArgs([]string{"file://" + g.RepoDirectory + ".git", w.WorkspaceDirectory})
 	err = getCmd.Command.Execute()
 	if !assert.NoError(t, err) {
@@ -264,7 +264,7 @@ func TestCmd_onlyVersionAsInput(t *testing.T) {
 	}
 
 	// update the cloned package
-	updateCmd := cmdupdate.NewRunner(fake.CtxWithDefaultPrinter(), "kpt")
+	updateCmd := update.NewRunner(fake.CtxWithDefaultPrinter(), "kpt")
 	defer testutil.Chdir(t, dest)()
 	updateCmd.Command.SetArgs([]string{"@master"})
 	err = updateCmd.Command.Execute()
@@ -299,7 +299,7 @@ func TestCmd_Execute_flagAndArgParsing(t *testing.T) {
 	defer testutil.Chdir(t, filepath.Dir(dir))()
 
 	// verify the current working directory is used if no path is specified
-	r := cmdupdate.NewRunner(fake.CtxWithDefaultPrinter(), "kpt")
+	r := update.NewRunner(fake.CtxWithDefaultPrinter(), "kpt")
 	r.Command.RunE = NoOpRunE
 	r.Command.SetArgs([]string{})
 	err := r.Command.Execute()
@@ -308,7 +308,7 @@ func TestCmd_Execute_flagAndArgParsing(t *testing.T) {
 	assert.Equal(t, kptfilev1.ResourceMerge, r.Update.Strategy)
 
 	// verify an error is thrown if multiple paths are specified
-	r = cmdupdate.NewRunner(fake.CtxWithDefaultPrinter(), "kpt")
+	r = update.NewRunner(fake.CtxWithDefaultPrinter(), "kpt")
 	r.Command.SilenceErrors = true
 	r.Command.RunE = failRun
 	r.Command.SetArgs([]string{"foo", "bar"})
@@ -318,7 +318,7 @@ func TestCmd_Execute_flagAndArgParsing(t *testing.T) {
 	assert.Equal(t, kptfilev1.UpdateStrategyType(""), r.Update.Strategy)
 
 	// verify the branch ref is set to the correct value
-	r = cmdupdate.NewRunner(fake.CtxWithDefaultPrinter(), "kpt")
+	r = update.NewRunner(fake.CtxWithDefaultPrinter(), "kpt")
 	r.Command.RunE = NoOpRunE
 	r.Command.SetArgs([]string{dir + "@refs/heads/foo"})
 	err = r.Command.Execute()
@@ -327,7 +327,7 @@ func TestCmd_Execute_flagAndArgParsing(t *testing.T) {
 	assert.Equal(t, kptfilev1.ResourceMerge, r.Update.Strategy)
 
 	// verify the branch ref is set to the correct value
-	r = cmdupdate.NewRunner(fake.CtxWithDefaultPrinter(), "kpt")
+	r = update.NewRunner(fake.CtxWithDefaultPrinter(), "kpt")
 	r.Command.RunE = NoOpRunE
 	r.Command.SetArgs([]string{dir, "--strategy", "force-delete-replace"})
 	err = r.Command.Execute()
@@ -335,7 +335,7 @@ func TestCmd_Execute_flagAndArgParsing(t *testing.T) {
 	assert.Equal(t, kptfilev1.ForceDeleteReplace, r.Update.Strategy)
 	assert.Equal(t, "", r.Update.Ref)
 
-	r = cmdupdate.NewRunner(fake.CtxWithDefaultPrinter(), "kpt")
+	r = update.NewRunner(fake.CtxWithDefaultPrinter(), "kpt")
 	r.Command.RunE = NoOpRunE
 	r.Command.SetArgs([]string{dir, "--strategy", "resource-merge"})
 	err = r.Command.Execute()
@@ -354,7 +354,7 @@ func TestCmd_flagAndArgParsing_Symlink(t *testing.T) {
 	assert.NoError(t, err)
 
 	// verify the branch ref is set to the correct value
-	r := cmdupdate.NewRunner(fake.CtxWithDefaultPrinter(), "kpt")
+	r := update.NewRunner(fake.CtxWithDefaultPrinter(), "kpt")
 	r.Command.RunE = NoOpRunE
 	r.Command.SetArgs([]string{"foo" + "@refs/heads/foo"})
 	err = r.Command.Execute()
@@ -368,7 +368,7 @@ func TestCmd_flagAndArgParsing_Symlink(t *testing.T) {
 
 // TestCmd_fail verifies that that command returns an error when it fails rather than exiting the process
 func TestCmd_fail(t *testing.T) {
-	r := cmdupdate.NewRunner(fake.CtxWithDefaultPrinter(), "kpt")
+	r := update.NewRunner(fake.CtxWithDefaultPrinter(), "kpt")
 	r.Command.SilenceErrors = true
 	r.Command.SilenceUsage = true
 	r.Command.SetArgs([]string{filepath.Join("not", "real", "dir")})
@@ -428,7 +428,7 @@ func TestCmd_path(t *testing.T) {
 		t.Run(test.name, func(t *testing.T) {
 			defer testutil.Chdir(t, test.currentWD)()
 
-			r := cmdupdate.NewRunner(fake.CtxWithDefaultPrinter(), "kpt")
+			r := update.NewRunner(fake.CtxWithDefaultPrinter(), "kpt")
 			r.Command.RunE = func(cmd *cobra.Command, args []string) error {
 				if !assert.Equal(t, test.expectedFullPackagePath, r.Update.Pkg.UniquePath.String()) {
 					t.FailNow()
@@ -776,7 +776,7 @@ Updated 2 package(s).
 			var errBuf bytes.Buffer
 
 			ctx := fake.CtxWithPrinter(&outBuf, &errBuf)
-			r := cmdupdate.NewRunner(ctx, "kpt")
+			r := update.NewRunner(ctx, "kpt")
 			r.Command.SetArgs([]string{})
 			err := r.Command.Execute()
 			if !assert.NoError(t, err) {