Repository: jetpack-io/devbox
Pull request #1690 (2023-12-21 00:47:42)

[refactor] Remove devbox interface
## Summary

Removes the devbox interface (`devbox.go` in root). I feel like it was making code harder to follow and not providing any value. 

Chatted with @loreto a few weeks ago about doing this. I was about to add a new function to interface and decided to remove instead.

A possible follow up could be to remove `devopt.Opts` to avoid some ducplication.

## How was it tested?

builds, CICD.



Patch:
diff --git a/.github/workflows/docker-image-release.yml b/.github/workflows/docker-image-release.yml
index 32f71010..115ec31e 100644
--- a/.github/workflows/docker-image-release.yml
+++ b/.github/workflows/docker-image-release.yml
@@ -20,16 +20,16 @@ jobs:
       - name: Build and push default
         uses: docker/build-push-action@v4
         with:
-          context: ./internal/impl/generate/tmpl/
-          file: ./internal/impl/generate/tmpl/DevboxImageDockerfile
+          context: ./internal/devbox/generate/tmpl/
+          file: ./internal/devbox/generate/tmpl/DevboxImageDockerfile
           push: true
           platforms: linux/amd64,linux/arm64
           tags: jetpackio/devbox:latest
       - name: Build and push root user
         uses: docker/build-push-action@v4
         with:
-          context: ./internal/impl/generate/tmpl/
-          file: ./internal/impl/generate/tmpl/DevboxImageDockerfileRootUser
+          context: ./internal/devbox/generate/tmpl/
+          file: ./internal/devbox/generate/tmpl/DevboxImageDockerfileRootUser
           push: true
           platforms: linux/amd64,linux/arm64
           tags: jetpackio/devbox-root-user:latest
diff --git a/devbox.go b/devbox.go
deleted file mode 100644
index 05371e40..00000000
--- a/devbox.go
+++ /dev/null
@@ -1,67 +0,0 @@
-// Copyright 2023 Jetpack Technologies Inc and contributors. All rights reserved.
-// Use of this source code is governed by the license in the LICENSE file.
-
-// Package devbox creates isolated development environments.
-package devbox
-
-import (
-	"context"
-	"io"
-
-	"go.jetpack.io/devbox/internal/devconfig"
-	"go.jetpack.io/devbox/internal/impl"
-	"go.jetpack.io/devbox/internal/impl/devopt"
-	"go.jetpack.io/devbox/internal/services"
-)
-
-// Devbox provides an isolated development environment.
-type Devbox interface {
-	Add(ctx context.Context, pkgs []string, opts devopt.AddOpts) error
-	Config() *devconfig.Config
-	EnvVars(ctx context.Context) ([]string, error)
-	Info(ctx context.Context, pkg string, markdown bool) (string, error)
-	Install(ctx context.Context) error
-	IsEnvEnabled() bool
-	ListScripts() []string
-	EnvExports(ctx context.Context, opts devopt.EnvExportsOpts) (string, error)
-	PackageNames() []string
-	ProjectDir() string
-	Pull(ctx context.Context, opts devopt.PullboxOpts) error
-	Push(ctx context.Context, opts devopt.PullboxOpts) error
-	Remove(ctx context.Context, pkgs ...string) error
-	RunScript(ctx context.Context, scriptName string, scriptArgs []string) error
-	Shell(ctx context.Context) error
-	Update(ctx context.Context, opts devopt.UpdateOpts) error
-
-	// Interact with services
-	ListServices(ctx context.Context, runInCurrentShell bool) error
-	RestartServices(ctx context.Context, runInCurrentShell bool, services ...string) error
-	Services() (services.Services, error)
-	StartProcessManager(ctx context.Context, runInCurrentShell bool, requestedServices []string, background bool, processComposeFileOrDir string) error
-	StartServices(ctx context.Context, runInCurrentShell bool, services ...string) error
-	StopServices(ctx context.Context, runInCurrentShell, allProjects bool, services ...string) error
-
-	// Generate files
-	Generate(ctx context.Context) error
-	GenerateDevcontainer(ctx context.Context, generateOpts devopt.GenerateOpts) error
-	GenerateDockerfile(ctx context.Context, generateOpts devopt.GenerateOpts) error
-	GenerateEnvrcFile(ctx context.Context, force bool, envFlags devopt.EnvFlags) error
-}
-
-// Open opens a devbox by reading the config file in dir.
-func Open(opts *devopt.Opts) (Devbox, error) {
-	return impl.Open(opts)
-}
-
-// InitConfig creates a default devbox config file if one doesn't already exist.
-func InitConfig(dir string, writer io.Writer) (bool, error) {
-	return devconfig.Init(dir, writer)
-}
-
-func GlobalDataPath() (string, error) {
-	return impl.GlobalDataPath()
-}
-
-func PrintEnvrcContent(w io.Writer, envFlags devopt.EnvFlags) error {
-	return impl.PrintEnvrcContent(w, envFlags)
-}
diff --git a/internal/boxcli/add.go b/internal/boxcli/add.go
index 6fcd2b2f..92aa84c6 100644
--- a/internal/boxcli/add.go
+++ b/internal/boxcli/add.go
@@ -9,9 +9,9 @@
 	"github.com/pkg/errors"
 	"github.com/spf13/cobra"
 
-	"go.jetpack.io/devbox"
 	"go.jetpack.io/devbox/internal/boxcli/usererr"
-	"go.jetpack.io/devbox/internal/impl/devopt"
+	"go.jetpack.io/devbox/internal/devbox"
+	"go.jetpack.io/devbox/internal/devbox/devopt"
 	"go.jetpack.io/devbox/internal/nix"
 )
 
diff --git a/internal/boxcli/cloud.go b/internal/boxcli/cloud.go
index 1bd022e2..ff4b3cab 100644
--- a/internal/boxcli/cloud.go
+++ b/internal/boxcli/cloud.go
@@ -10,11 +10,11 @@
 	"github.com/pkg/errors"
 	"github.com/spf13/cobra"
 
-	"go.jetpack.io/devbox"
 	"go.jetpack.io/devbox/internal/boxcli/usererr"
 	"go.jetpack.io/devbox/internal/cloud"
+	"go.jetpack.io/devbox/internal/devbox"
+	"go.jetpack.io/devbox/internal/devbox/devopt"
 	"go.jetpack.io/devbox/internal/envir"
-	"go.jetpack.io/devbox/internal/impl/devopt"
 )
 
 type cloudShellCmdFlags struct {
diff --git a/internal/boxcli/env.go b/internal/boxcli/env.go
index 9ef5b1c4..a1c2807c 100644
--- a/internal/boxcli/env.go
+++ b/internal/boxcli/env.go
@@ -9,7 +9,7 @@
 	"github.com/joho/godotenv"
 	"github.com/pkg/errors"
 	"github.com/spf13/cobra"
-	"go.jetpack.io/devbox/internal/impl/devopt"
+	"go.jetpack.io/devbox/internal/devbox/devopt"
 )
 
 // to be composed into xyzCmdFlags structs
diff --git a/internal/boxcli/envsec.go b/internal/boxcli/envsec.go
index e5cdf0c9..08e0fb99 100644
--- a/internal/boxcli/envsec.go
+++ b/internal/boxcli/envsec.go
@@ -6,9 +6,9 @@
 import (
 	"github.com/pkg/errors"
 	"github.com/spf13/cobra"
-	"go.jetpack.io/devbox"
 	"go.jetpack.io/devbox/internal/build"
-	"go.jetpack.io/devbox/internal/impl/devopt"
+	"go.jetpack.io/devbox/internal/devbox"
+	"go.jetpack.io/devbox/internal/devbox/devopt"
 	"go.jetpack.io/envsec/pkg/envsec"
 	"go.jetpack.io/pkg/envvar"
 )
diff --git a/internal/boxcli/generate.go b/internal/boxcli/generate.go
index b2411dfb..aa5d44f9 100644
--- a/internal/boxcli/generate.go
+++ b/internal/boxcli/generate.go
@@ -7,9 +7,9 @@
 	"github.com/pkg/errors"
 	"github.com/spf13/cobra"
 
-	"go.jetpack.io/devbox"
 	"go.jetpack.io/devbox/internal/cloud"
-	"go.jetpack.io/devbox/internal/impl/devopt"
+	"go.jetpack.io/devbox/internal/devbox"
+	"go.jetpack.io/devbox/internal/devbox/devopt"
 )
 
 type generateCmdFlags struct {
diff --git a/internal/boxcli/global.go b/internal/boxcli/global.go
index 3cfce8f7..d44208b5 100644
--- a/internal/boxcli/global.go
+++ b/internal/boxcli/global.go
@@ -9,8 +9,8 @@
 	"github.com/pkg/errors"
 	"github.com/spf13/cobra"
 
-	"go.jetpack.io/devbox"
-	"go.jetpack.io/devbox/internal/impl/devopt"
+	"go.jetpack.io/devbox/internal/devbox"
+	"go.jetpack.io/devbox/internal/devbox/devopt"
 	"go.jetpack.io/devbox/internal/ux"
 )
 
diff --git a/internal/boxcli/info.go b/internal/boxcli/info.go
index bfec6eb8..65873160 100644
--- a/internal/boxcli/info.go
+++ b/internal/boxcli/info.go
@@ -9,8 +9,8 @@
 	"github.com/pkg/errors"
 	"github.com/spf13/cobra"
 
-	"go.jetpack.io/devbox"
-	"go.jetpack.io/devbox/internal/impl/devopt"
+	"go.jetpack.io/devbox/internal/devbox"
+	"go.jetpack.io/devbox/internal/devbox/devopt"
 )
 
 type infoCmdFlags struct {
diff --git a/internal/boxcli/init.go b/internal/boxcli/init.go
index b5a9b5ad..7bf8aaf4 100644
--- a/internal/boxcli/init.go
+++ b/internal/boxcli/init.go
@@ -7,7 +7,7 @@
 	"github.com/pkg/errors"
 	"github.com/spf13/cobra"
 
-	"go.jetpack.io/devbox"
+	"go.jetpack.io/devbox/internal/devbox"
 )
 
 func initCmd() *cobra.Command {
diff --git a/internal/boxcli/install.go b/internal/boxcli/install.go
index fd57ae8a..aeb073ad 100644
--- a/internal/boxcli/install.go
+++ b/internal/boxcli/install.go
@@ -9,8 +9,8 @@
 	"github.com/pkg/errors"
 	"github.com/spf13/cobra"
 
-	"go.jetpack.io/devbox"
-	"go.jetpack.io/devbox/internal/impl/devopt"
+	"go.jetpack.io/devbox/internal/devbox"
+	"go.jetpack.io/devbox/internal/devbox/devopt"
 )
 
 func installCmd() *cobra.Command {
diff --git a/internal/boxcli/integrate.go b/internal/boxcli/integrate.go
index b7e180ce..4b87702f 100644
--- a/internal/boxcli/integrate.go
+++ b/internal/boxcli/integrate.go
@@ -12,9 +12,9 @@
 
 	"github.com/spf13/cobra"
 	"github.com/zealic/go2node"
-	"go.jetpack.io/devbox"
 	"go.jetpack.io/devbox/internal/debug"
-	"go.jetpack.io/devbox/internal/impl/devopt"
+	"go.jetpack.io/devbox/internal/devbox"
+	"go.jetpack.io/devbox/internal/devbox/devopt"
 )
 
 type integrateCmdFlags struct {
diff --git a/internal/boxcli/midcobra/telemetry.go b/internal/boxcli/midcobra/telemetry.go
index aefe6de9..d56fa9e6 100644
--- a/internal/boxcli/midcobra/telemetry.go
+++ b/internal/boxcli/midcobra/telemetry.go
@@ -11,11 +11,11 @@
 	"github.com/pkg/errors"
 	"github.com/spf13/cobra"
 	"github.com/spf13/pflag"
-	"go.jetpack.io/devbox"
 	"go.jetpack.io/devbox/internal/boxcli/featureflag"
 	"go.jetpack.io/devbox/internal/boxcli/usererr"
+	"go.jetpack.io/devbox/internal/devbox"
+	"go.jetpack.io/devbox/internal/devbox/devopt"
 	"go.jetpack.io/devbox/internal/envir"
-	"go.jetpack.io/devbox/internal/impl/devopt"
 	"go.jetpack.io/devbox/internal/telemetry"
 )
 
diff --git a/internal/boxcli/multi/multi.go b/internal/boxcli/multi/multi.go
index 05ca3e9f..8af9a185 100644
--- a/internal/boxcli/multi/multi.go
+++ b/internal/boxcli/multi/multi.go
@@ -4,16 +4,16 @@
 	"io/fs"
 	"path/filepath"
 
-	"go.jetpack.io/devbox"
 	"go.jetpack.io/devbox/internal/debug"
+	"go.jetpack.io/devbox/internal/devbox"
+	"go.jetpack.io/devbox/internal/devbox/devopt"
 	"go.jetpack.io/devbox/internal/devconfig"
-	"go.jetpack.io/devbox/internal/impl/devopt"
 )
 
-func Open(opts *devopt.Opts) ([]devbox.Devbox, error) {
+func Open(opts *devopt.Opts) ([]*devbox.Devbox, error) {
 	defer debug.FunctionTimer().End()
 
-	var boxes []devbox.Devbox
+	var boxes []*devbox.Devbox
 	err := filepath.WalkDir(
 		".",
 		func(path string, dirEntry fs.DirEntry, err error) error {
diff --git a/internal/boxcli/pull.go b/internal/boxcli/pull.go
index 4bda512f..4a925e8e 100644
--- a/internal/boxcli/pull.go
+++ b/internal/boxcli/pull.go
@@ -12,10 +12,10 @@
 	"github.com/pkg/errors"
 	"github.com/spf13/cobra"
 
-	"go.jetpack.io/devbox"
 	"go.jetpack.io/devbox/internal/boxcli/usererr"
+	"go.jetpack.io/devbox/internal/devbox"
+	"go.jetpack.io/devbox/internal/devbox/devopt"
 	"go.jetpack.io/devbox/internal/goutil"
-	"go.jetpack.io/devbox/internal/impl/devopt"
 	"go.jetpack.io/devbox/internal/pullbox/s3"
 	"go.jetpack.io/pkg/auth"
 )
diff --git a/internal/boxcli/push.go b/internal/boxcli/push.go
index 73030a7e..d967b5f9 100644
--- a/internal/boxcli/push.go
+++ b/internal/boxcli/push.go
@@ -8,9 +8,9 @@
 	"github.com/spf13/cobra"
 	"go.jetpack.io/pkg/auth"
 
-	"go.jetpack.io/devbox"
+	"go.jetpack.io/devbox/internal/devbox"
+	"go.jetpack.io/devbox/internal/devbox/devopt"
 	"go.jetpack.io/devbox/internal/goutil"
-	"go.jetpack.io/devbox/internal/impl/devopt"
 )
 
 type pushCmdFlags struct {
diff --git a/internal/boxcli/rm.go b/internal/boxcli/rm.go
index 3fb6a12a..71d62df6 100644
--- a/internal/boxcli/rm.go
+++ b/internal/boxcli/rm.go
@@ -6,8 +6,8 @@
 import (
 	"github.com/pkg/errors"
 	"github.com/spf13/cobra"
-	"go.jetpack.io/devbox"
-	"go.jetpack.io/devbox/internal/impl/devopt"
+	"go.jetpack.io/devbox/internal/devbox"
+	"go.jetpack.io/devbox/internal/devbox/devopt"
 )
 
 type removeCmdFlags struct {
diff --git a/internal/boxcli/run.go b/internal/boxcli/run.go
index c399d451..ee0b328a 100644
--- a/internal/boxcli/run.go
+++ b/internal/boxcli/run.go
@@ -12,10 +12,10 @@
 	"github.com/spf13/cobra"
 	"github.com/spf13/pflag"
 
-	"go.jetpack.io/devbox"
 	"go.jetpack.io/devbox/internal/boxcli/usererr"
 	"go.jetpack.io/devbox/internal/debug"
-	"go.jetpack.io/devbox/internal/impl/devopt"
+	"go.jetpack.io/devbox/internal/devbox"
+	"go.jetpack.io/devbox/internal/devbox/devopt"
 	"go.jetpack.io/devbox/internal/redact"
 )
 
diff --git a/internal/boxcli/services.go b/internal/boxcli/services.go
index e78c8768..3fcf8c62 100644
--- a/internal/boxcli/services.go
+++ b/internal/boxcli/services.go
@@ -6,8 +6,8 @@
 import (
 	"github.com/pkg/errors"
 	"github.com/spf13/cobra"
-	"go.jetpack.io/devbox"
-	"go.jetpack.io/devbox/internal/impl/devopt"
+	"go.jetpack.io/devbox/internal/devbox"
+	"go.jetpack.io/devbox/internal/devbox/devopt"
 )
 
 type servicesCmdFlags struct {
diff --git a/internal/boxcli/shell.go b/internal/boxcli/shell.go
index a03c1c38..e9e77edb 100644
--- a/internal/boxcli/shell.go
+++ b/internal/boxcli/shell.go
@@ -9,10 +9,10 @@
 	"github.com/pkg/errors"
 	"github.com/spf13/cobra"
 
-	"go.jetpack.io/devbox"
 	"go.jetpack.io/devbox/internal/boxcli/usererr"
+	"go.jetpack.io/devbox/internal/devbox"
+	"go.jetpack.io/devbox/internal/devbox/devopt"
 	"go.jetpack.io/devbox/internal/envir"
-	"go.jetpack.io/devbox/internal/impl/devopt"
 )
 
 type shellCmdFlags struct {
diff --git a/internal/boxcli/shellenv.go b/internal/boxcli/shellenv.go
index 6197c8f1..619841fd 100644
--- a/internal/boxcli/shellenv.go
+++ b/internal/boxcli/shellenv.go
@@ -9,8 +9,8 @@
 	"strings"
 
 	"github.com/spf13/cobra"
-	"go.jetpack.io/devbox"
-	"go.jetpack.io/devbox/internal/impl/devopt"
+	"go.jetpack.io/devbox/internal/devbox"
+	"go.jetpack.io/devbox/internal/devbox/devopt"
 )
 
 type shellEnvCmdFlags struct {
diff --git a/internal/boxcli/update.go b/internal/boxcli/update.go
index 5cd5a329..ca1628b1 100644
--- a/internal/boxcli/update.go
+++ b/internal/boxcli/update.go
@@ -7,10 +7,10 @@
 	"github.com/pkg/errors"
 	"github.com/spf13/cobra"
 
-	"go.jetpack.io/devbox"
 	"go.jetpack.io/devbox/internal/boxcli/multi"
 	"go.jetpack.io/devbox/internal/boxcli/usererr"
-	"go.jetpack.io/devbox/internal/impl/devopt"
+	"go.jetpack.io/devbox/internal/devbox"
+	"go.jetpack.io/devbox/internal/devbox/devopt"
 )
 
 type updateCmdFlags struct {
diff --git a/internal/conf/doc.go b/internal/conf/doc.go
index 855d56a1..2e18f8fd 100644
--- a/internal/conf/doc.go
+++ b/internal/conf/doc.go
@@ -2,5 +2,5 @@
 // Use of this source code is governed by the license in the LICENSE file.
 
 // Package conf is future home of the config (devbox.json) management code.
-// it will merge exiting plugin and impl/config.go code.
+// it will merge exiting plugin and devbox/config.go code.
 package conf
diff --git a/internal/impl/devbox.go b/internal/devbox/devbox.go
similarity index 99%
rename from internal/impl/devbox.go
rename to internal/devbox/devbox.go
index 1a5ae329..3159bbd1 100644
--- a/internal/impl/devbox.go
+++ b/internal/devbox/devbox.go
@@ -1,8 +1,8 @@
 // Copyright 2023 Jetpack Technologies Inc and contributors. All rights reserved.
 // Use of this source code is governed by the license in the LICENSE file.
 
-// Package impl creates isolated development environments.
-package impl
+// Package devbox creates isolated development environments.
+package devbox
 
 import (
 	"bytes"
@@ -24,10 +24,10 @@
 	"github.com/pkg/errors"
 	"github.com/samber/lo"
 	"go.jetpack.io/devbox/internal/cachehash"
+	"go.jetpack.io/devbox/internal/devbox/envpath"
+	"go.jetpack.io/devbox/internal/devbox/generate"
 	"go.jetpack.io/devbox/internal/devpkg"
 	"go.jetpack.io/devbox/internal/devpkg/pkgtype"
-	"go.jetpack.io/devbox/internal/impl/envpath"
-	"go.jetpack.io/devbox/internal/impl/generate"
 	"go.jetpack.io/devbox/internal/searcher"
 	"go.jetpack.io/devbox/internal/shellgen"
 	"go.jetpack.io/devbox/internal/telemetry"
@@ -36,10 +36,10 @@
 	"go.jetpack.io/devbox/internal/cmdutil"
 	"go.jetpack.io/devbox/internal/conf"
 	"go.jetpack.io/devbox/internal/debug"
+	"go.jetpack.io/devbox/internal/devbox/devopt"
 	"go.jetpack.io/devbox/internal/devconfig"
 	"go.jetpack.io/devbox/internal/envir"
 	"go.jetpack.io/devbox/internal/fileutil"
-	"go.jetpack.io/devbox/internal/impl/devopt"
 	"go.jetpack.io/devbox/internal/lock"
 	"go.jetpack.io/devbox/internal/nix"
 	"go.jetpack.io/devbox/internal/plugin"
@@ -74,6 +74,10 @@ type Devbox struct {
 
 var legacyPackagesWarningHasBeenShown = false
 
+func InitConfig(dir string, writer io.Writer) (bool, error) {
+	return devconfig.Init(dir, writer)
+}
+
 func Open(opts *devopt.Opts) (*Devbox, error) {
 	projectDir, err := findProjectDir(opts.Dir)
 	if err != nil {
diff --git a/internal/impl/devopt/devboxopts.go b/internal/devbox/devopt/devboxopts.go
similarity index 100%
rename from internal/impl/devopt/devboxopts.go
rename to internal/devbox/devopt/devboxopts.go
diff --git a/internal/impl/dir.go b/internal/devbox/dir.go
similarity index 99%
rename from internal/impl/dir.go
rename to internal/devbox/dir.go
index d5a054ee..e30a063f 100644
--- a/internal/impl/dir.go
+++ b/internal/devbox/dir.go
@@ -1,7 +1,7 @@
 // Copyright 2023 Jetpack Technologies Inc and contributors. All rights reserved.
 // Use of this source code is governed by the license in the LICENSE file.
 
-package impl
+package devbox
 
 import (
 	"os"
diff --git a/internal/impl/envpath/pathlists.go b/internal/devbox/envpath/pathlists.go
similarity index 100%
rename from internal/impl/envpath/pathlists.go
rename to internal/devbox/envpath/pathlists.go
diff --git a/internal/impl/envpath/pathlists_test.go b/internal/devbox/envpath/pathlists_test.go
similarity index 100%
rename from internal/impl/envpath/pathlists_test.go
rename to internal/devbox/envpath/pathlists_test.go
diff --git a/internal/impl/envpath/stack.go b/internal/devbox/envpath/stack.go
similarity index 100%
rename from internal/impl/envpath/stack.go
rename to internal/devbox/envpath/stack.go
diff --git a/internal/impl/envpath/stack_test.go b/internal/devbox/envpath/stack_test.go
similarity index 100%
rename from internal/impl/envpath/stack_test.go
rename to internal/devbox/envpath/stack_test.go
diff --git a/internal/impl/envvars.go b/internal/devbox/envvars.go
similarity index 97%
rename from internal/impl/envvars.go
rename to internal/devbox/envvars.go
index 2013a05e..06a37b30 100644
--- a/internal/impl/envvars.go
+++ b/internal/devbox/envvars.go
@@ -1,15 +1,15 @@
 // Copyright 2023 Jetpack Technologies Inc and contributors. All rights reserved.
 // Use of this source code is governed by the license in the LICENSE file.
 
-package impl
+package devbox
 
 import (
 	"os"
 	"slices"
 	"strings"
 
+	"go.jetpack.io/devbox/internal/devbox/envpath"
 	"go.jetpack.io/devbox/internal/envir"
-	"go.jetpack.io/devbox/internal/impl/envpath"
 )
 
 const devboxSetPrefix = "__DEVBOX_SET_"
diff --git a/internal/impl/flakes.go b/internal/devbox/flakes.go
similarity index 98%
rename from internal/impl/flakes.go
rename to internal/devbox/flakes.go
index 7ff667ee..d37e03cf 100644
--- a/internal/impl/flakes.go
+++ b/internal/devbox/flakes.go
@@ -1,7 +1,7 @@
 // Copyright 2023 Jetpack Technologies Inc and contributors. All rights reserved.
 // Use of this source code is governed by the license in the LICENSE file.
 
-package impl
+package devbox
 
 import (
 	"strings"
diff --git a/internal/impl/generate/devcontainer_util.go b/internal/devbox/generate/devcontainer_util.go
similarity index 99%
rename from internal/impl/generate/devcontainer_util.go
rename to internal/devbox/generate/devcontainer_util.go
index 23afb3b2..daf338e4 100644
--- a/internal/impl/generate/devcontainer_util.go
+++ b/internal/devbox/generate/devcontainer_util.go
@@ -19,7 +19,7 @@
 	"strings"
 
 	"go.jetpack.io/devbox/internal/debug"
-	"go.jetpack.io/devbox/internal/impl/devopt"
+	"go.jetpack.io/devbox/internal/devbox/devopt"
 )
 
 //go:embed tmpl/*
diff --git a/internal/impl/generate/tmpl/DevboxImageDockerfile b/internal/devbox/generate/tmpl/DevboxImageDockerfile
similarity index 100%
rename from internal/impl/generate/tmpl/DevboxImageDockerfile
rename to internal/devbox/generate/tmpl/DevboxImageDockerfile
diff --git a/internal/impl/generate/tmpl/DevboxImageDockerfileRootUser b/internal/devbox/generate/tmpl/DevboxImageDockerfileRootUser
similarity index 100%
rename from internal/impl/generate/tmpl/DevboxImageDockerfileRootUser
rename to internal/devbox/generate/tmpl/DevboxImageDockerfileRootUser
diff --git a/internal/impl/generate/tmpl/Dockerfile.dockerignore.tmpl b/internal/devbox/generate/tmpl/Dockerfile.dockerignore.tmpl
similarity index 100%
rename from internal/impl/generate/tmpl/Dockerfile.dockerignore.tmpl
rename to internal/devbox/generate/tmpl/Dockerfile.dockerignore.tmpl
diff --git a/internal/impl/generate/tmpl/devcontainerDockerfile.tmpl b/internal/devbox/generate/tmpl/devcontainerDockerfile.tmpl
similarity index 100%
rename from internal/impl/generate/tmpl/devcontainerDockerfile.tmpl
rename to internal/devbox/generate/tmpl/devcontainerDockerfile.tmpl
diff --git a/internal/impl/generate/tmpl/envrc.tmpl b/internal/devbox/generate/tmpl/envrc.tmpl
similarity index 100%
rename from internal/impl/generate/tmpl/envrc.tmpl
rename to internal/devbox/generate/tmpl/envrc.tmpl
diff --git a/internal/impl/generate/tmpl/envrcContent.tmpl b/internal/devbox/generate/tmpl/envrcContent.tmpl
similarity index 100%
rename from internal/impl/generate/tmpl/envrcContent.tmpl
rename to internal/devbox/generate/tmpl/envrcContent.tmpl
diff --git a/internal/impl/global.go b/internal/devbox/global.go
similarity index 98%
rename from internal/impl/global.go
rename to internal/devbox/global.go
index 2fd5ca46..7809cb53 100644
--- a/internal/impl/global.go
+++ b/internal/devbox/global.go
@@ -1,7 +1,7 @@
 // Copyright 2023 Jetpack Technologies Inc and contributors. All rights reserved.
 // Use of this source code is governed by the license in the LICENSE file.
 
-package impl
+package devbox
 
 import (
 	"io/fs"
diff --git a/internal/impl/packages.go b/internal/devbox/packages.go
similarity index 99%
rename from internal/impl/packages.go
rename to internal/devbox/packages.go
index a2770f46..c750f4d0 100644
--- a/internal/impl/packages.go
+++ b/internal/devbox/packages.go
@@ -1,7 +1,7 @@
 // Copyright 2023 Jetpack Technologies Inc and contributors. All rights reserved.
 // Use of this source code is governed by the license in the LICENSE file.
 
-package impl
+package devbox
 
 import (
 	"context"
@@ -15,9 +15,9 @@
 
 	"github.com/pkg/errors"
 	"github.com/samber/lo"
+	"go.jetpack.io/devbox/internal/devbox/devopt"
 	"go.jetpack.io/devbox/internal/devpkg"
 	"go.jetpack.io/devbox/internal/devpkg/pkgtype"
-	"go.jetpack.io/devbox/internal/impl/devopt"
 	"go.jetpack.io/devbox/internal/nix/nixprofile"
 	"go.jetpack.io/devbox/internal/shellgen"
 
diff --git a/internal/impl/pure_shell.go b/internal/devbox/pure_shell.go
similarity index 99%
rename from internal/impl/pure_shell.go
rename to internal/devbox/pure_shell.go
index 5f84e7d4..7136428f 100644
--- a/internal/impl/pure_shell.go
+++ b/internal/devbox/pure_shell.go
@@ -1,7 +1,7 @@
 // Copyright 2023 Jetpack Technologies Inc and contributors. All rights reserved.
 // Use of this source code is governed by the license in the LICENSE file.
 
-package impl
+package devbox
 
 import (
 	"fmt"
diff --git a/internal/impl/pushpull.go b/internal/devbox/pushpull.go
similarity index 90%
rename from internal/impl/pushpull.go
rename to internal/devbox/pushpull.go
index 5d20d857..ce79fa96 100644
--- a/internal/impl/pushpull.go
+++ b/internal/devbox/pushpull.go
@@ -1,13 +1,13 @@
 // Copyright 2023 Jetpack Technologies Inc and contributors. All rights reserved.
 // Use of this source code is governed by the license in the LICENSE file.
 
-package impl
+package devbox
 
 import (
 	"context"
 	"runtime/trace"
 
-	"go.jetpack.io/devbox/internal/impl/devopt"
+	"go.jetpack.io/devbox/internal/devbox/devopt"
 	"go.jetpack.io/devbox/internal/pullbox"
 )
 
diff --git a/internal/impl/refresh.go b/internal/devbox/refresh.go
similarity index 99%
rename from internal/impl/refresh.go
rename to internal/devbox/refresh.go
index 9aeb2b5a..6439b9a2 100644
--- a/internal/impl/refresh.go
+++ b/internal/devbox/refresh.go
@@ -1,4 +1,4 @@
-package impl
+package devbox
 
 import (
 	"fmt"
diff --git a/internal/impl/shell.go b/internal/devbox/shell.go
similarity index 99%
rename from internal/impl/shell.go
rename to internal/devbox/shell.go
index 05f24288..84af307d 100644
--- a/internal/impl/shell.go
+++ b/internal/devbox/shell.go
@@ -1,7 +1,7 @@
 // Copyright 2023 Jetpack Technologies Inc and contributors. All rights reserved.
 // Use of this source code is governed by the license in the LICENSE file.
 
-package impl
+package devbox
 
 import (
 	"bytes"
diff --git a/internal/impl/shellcmd/command.go b/internal/devbox/shellcmd/command.go
similarity index 100%
rename from internal/impl/shellcmd/command.go
rename to internal/devbox/shellcmd/command.go
diff --git a/internal/impl/shellcmd/command_test.go b/internal/devbox/shellcmd/command_test.go
similarity index 100%
rename from internal/impl/shellcmd/command_test.go
rename to internal/devbox/shellcmd/command_test.go
diff --git a/internal/impl/shellrc.tmpl b/internal/devbox/shellrc.tmpl
similarity index 100%
rename from internal/impl/shellrc.tmpl
rename to internal/devbox/shellrc.tmpl
diff --git a/internal/impl/shellrc_fish.tmpl b/internal/devbox/shellrc_fish.tmpl
similarity index 100%
rename from internal/impl/shellrc_fish.tmpl
rename to internal/devbox/shellrc_fish.tmpl
diff --git a/internal/impl/testdata/shellrc/basic/env b/internal/devbox/testdata/shellrc/basic/env
similarity index 100%
rename from internal/impl/testdata/shellrc/basic/env
rename to internal/devbox/testdata/shellrc/basic/env
diff --git a/internal/impl/testdata/shellrc/basic/shellrc b/internal/devbox/testdata/shellrc/basic/shellrc
similarity index 100%
rename from internal/impl/testdata/shellrc/basic/shellrc
rename to internal/devbox/testdata/shellrc/basic/shellrc
diff --git a/internal/impl/testdata/shellrc/basic/shellrc.golden b/internal/devbox/testdata/shellrc/basic/shellrc.golden
similarity index 100%
rename from internal/impl/testdata/shellrc/basic/shellrc.golden
rename to internal/devbox/testdata/shellrc/basic/shellrc.golden
diff --git a/internal/impl/testdata/shellrc/noshellrc/shellrc.golden b/internal/devbox/testdata/shellrc/noshellrc/shellrc.golden
similarity index 100%
rename from internal/impl/testdata/shellrc/noshellrc/shellrc.golden
rename to internal/devbox/testdata/shellrc/noshellrc/shellrc.golden
diff --git a/internal/impl/update.go b/internal/devbox/update.go
similarity index 98%
rename from internal/impl/update.go
rename to internal/devbox/update.go
index 9aff31ba..76487730 100644
--- a/internal/impl/update.go
+++ b/internal/devbox/update.go
@@ -1,7 +1,7 @@
 // Copyright 2023 Jetpack Technologies Inc and contributors. All rights reserved.
 // Use of this source code is governed by the license in the LICENSE file.
 
-package impl
+package devbox
 
 import (
 	"context"
@@ -9,8 +9,8 @@
 
 	"github.com/pkg/errors"
 	"go.jetpack.io/devbox/internal/boxcli/featureflag"
+	"go.jetpack.io/devbox/internal/devbox/devopt"
 	"go.jetpack.io/devbox/internal/devpkg"
-	"go.jetpack.io/devbox/internal/impl/devopt"
 	"go.jetpack.io/devbox/internal/lock"
 	"go.jetpack.io/devbox/internal/nix"
 	"go.jetpack.io/devbox/internal/nix/nixprofile"
diff --git a/internal/impl/util.go b/internal/devbox/util.go
similarity index 99%
rename from internal/impl/util.go
rename to internal/devbox/util.go
index 17f688d5..4691f6cc 100644
--- a/internal/impl/util.go
+++ b/internal/devbox/util.go
@@ -1,7 +1,7 @@
 // Copyright 2023 Jetpack Technologies Inc and contributors. All rights reserved.
 // Use of this source code is governed by the license in the LICENSE file.
 
-package impl
+package devbox
 
 import (
 	"context"
diff --git a/internal/devconfig/config.go b/internal/devconfig/config.go
index 91a8b3bd..1f29526f 100644
--- a/internal/devconfig/config.go
+++ b/internal/devconfig/config.go
@@ -19,7 +19,7 @@
 	"go.jetpack.io/devbox/internal/boxcli/featureflag"
 	"go.jetpack.io/devbox/internal/boxcli/usererr"
 	"go.jetpack.io/devbox/internal/cachehash"
-	"go.jetpack.io/devbox/internal/impl/shellcmd"
+	"go.jetpack.io/devbox/internal/devbox/shellcmd"
 )
 
 const (
diff --git a/internal/devpkg/package.go b/internal/devpkg/package.go
index 2bfcc3bb..4a6153a5 100644
--- a/internal/devpkg/package.go
+++ b/internal/devpkg/package.go
@@ -16,9 +16,9 @@
 	"github.com/samber/lo"
 	"go.jetpack.io/devbox/internal/boxcli/usererr"
 	"go.jetpack.io/devbox/internal/cachehash"
+	"go.jetpack.io/devbox/internal/devbox/devopt"
 	"go.jetpack.io/devbox/internal/devconfig"
 	"go.jetpack.io/devbox/internal/devpkg/pkgtype"
-	"go.jetpack.io/devbox/internal/impl/devopt"
 	"go.jetpack.io/devbox/internal/lock"
 	"go.jetpack.io/devbox/internal/nix"
 	"go.jetpack.io/devbox/plugins"
diff --git a/internal/plugin/info.go b/internal/plugin/info.go
index f0ba02a8..dd13bbf7 100644
--- a/internal/plugin/info.go
+++ b/internal/plugin/info.go
@@ -13,6 +13,7 @@
 	"github.com/pkg/errors"
 	"github.com/samber/lo"
 	"go.jetpack.io/devbox/internal/devpkg"
+	"go.jetpack.io/devbox/internal/services"
 )
 
 func Readme(ctx context.Context,
@@ -39,7 +40,7 @@ func Readme(ctx context.Context,
 		return "", err
 	}
 
-	if err = printServices(cfg, buf, markdown); err != nil {
+	if err = printServices(cfg, pkg, buf, markdown); err != nil {
 		return "", err
 	}
 
@@ -72,17 +73,25 @@ func printReadme(cfg *config, w io.Writer, markdown bool) error {
 	return errors.WithStack(err)
 }
 
-func printServices(cfg *config, w io.Writer, markdown bool) error {
-	svcs, err := cfg.Services()
+func printServices(cfg *config, pkg *devpkg.Package, w io.Writer, markdown bool) error {
+	_, contentPath := cfg.ProcessComposeYaml()
+	if contentPath == "" {
+		return nil
+	}
+	content, err := pkg.FileContent(contentPath)
+	if err != nil {
+		return errors.WithStack(err)
+	}
+	serviceNames, err := services.NamesFromProcessCompose(content)
 	if err != nil {
 		return errors.WithStack(err)
 	}
-	if len(svcs) == 0 {
+	if len(serviceNames) == 0 {
 		return nil
 	}
 	services := ""
-	for _, service := range svcs {
-		services += fmt.Sprintf("* %[1]s\n", service.Name)
+	for _, serviceName := range serviceNames {
+		services += fmt.Sprintf("* %[1]s\n", serviceName)
 	}
 
 	_, err = fmt.Fprintf(
diff --git a/internal/plugin/plugin.go b/internal/plugin/plugin.go
index 0720397b..a600320c 100644
--- a/internal/plugin/plugin.go
+++ b/internal/plugin/plugin.go
@@ -17,7 +17,7 @@
 
 	"go.jetpack.io/devbox/internal/conf"
 	"go.jetpack.io/devbox/internal/debug"
-	"go.jetpack.io/devbox/internal/impl/shellcmd"
+	"go.jetpack.io/devbox/internal/devbox/shellcmd"
 	"go.jetpack.io/devbox/internal/lock"
 	"go.jetpack.io/devbox/internal/nix"
 	"go.jetpack.io/devbox/internal/services"
@@ -50,17 +50,17 @@ type config struct {
 	} `json:"shell,omitempty"`
 }
 
-func (c *config) ProcessComposeYaml() (string, bool) {
-	for file := range c.CreateFiles {
+func (c *config) ProcessComposeYaml() (string, string) {
+	for file, contentPath := range c.CreateFiles {
 		if strings.HasSuffix(file, "process-compose.yaml") || strings.HasSuffix(file, "process-compose.yml") {
-			return file, true
+			return file, contentPath
 		}
 	}
-	return "", false
+	return "", ""
 }
 
 func (c *config) Services() (services.Services, error) {
-	if file, ok := c.ProcessComposeYaml(); ok {
+	if file, _ := c.ProcessComposeYaml(); file != "" {
 		return services.FromProcessCompose(file)
 	}
 	return nil, nil
diff --git a/internal/pullbox/pullbox.go b/internal/pullbox/pullbox.go
index bd9a5aca..96d41b8f 100644
--- a/internal/pullbox/pullbox.go
+++ b/internal/pullbox/pullbox.go
@@ -13,7 +13,7 @@
 	"github.com/pkg/errors"
 
 	"go.jetpack.io/devbox/internal/boxcli/usererr"
-	"go.jetpack.io/devbox/internal/impl/devopt"
+	"go.jetpack.io/devbox/internal/devbox/devopt"
 	"go.jetpack.io/devbox/internal/pullbox/git"
 	"go.jetpack.io/devbox/internal/pullbox/s3"
 	"go.jetpack.io/devbox/internal/pullbox/tar"
diff --git a/internal/pullbox/s3/config.go b/internal/pullbox/s3/config.go
index fd39f089..72c6b0a6 100644
--- a/internal/pullbox/s3/config.go
+++ b/internal/pullbox/s3/config.go
@@ -8,7 +8,7 @@
 	"github.com/aws/aws-sdk-go-v2/credentials"
 	"github.com/aws/aws-sdk-go-v2/service/sts"
 	"github.com/pkg/errors"
-	"go.jetpack.io/devbox/internal/impl/devopt"
+	"go.jetpack.io/devbox/internal/devbox/devopt"
 )
 
 // TODO(landau): We could make these customizable so folks can use their own
diff --git a/internal/pullbox/s3/pull.go b/internal/pullbox/s3/pull.go
index 06c5a2c5..04b8dc9d 100644
--- a/internal/pullbox/s3/pull.go
+++ b/internal/pullbox/s3/pull.go
@@ -13,7 +13,7 @@
 	"github.com/aws/aws-sdk-go-v2/feature/s3/manager"
 	"github.com/aws/aws-sdk-go-v2/service/s3"
 	"github.com/pkg/errors"
-	"go.jetpack.io/devbox/internal/impl/devopt"
+	"go.jetpack.io/devbox/internal/devbox/devopt"
 	"go.jetpack.io/devbox/internal/pullbox/tar"
 	"go.jetpack.io/devbox/internal/ux"
 )
diff --git a/internal/pullbox/s3/push.go b/internal/pullbox/s3/push.go
index e3b55d82..020db8be 100644
--- a/internal/pullbox/s3/push.go
+++ b/internal/pullbox/s3/push.go
@@ -12,7 +12,7 @@
 	"github.com/aws/aws-sdk-go-v2/aws"
 	"github.com/aws/aws-sdk-go-v2/feature/s3/manager"
 	"github.com/aws/aws-sdk-go-v2/service/s3"
-	"go.jetpack.io/devbox/internal/impl/devopt"
+	"go.jetpack.io/devbox/internal/devbox/devopt"
 	"go.jetpack.io/devbox/internal/pullbox/tar"
 	"go.jetpack.io/devbox/internal/ux"
 )
diff --git a/internal/services/config.go b/internal/services/config.go
index b35bc702..39d70d92 100644
--- a/internal/services/config.go
+++ b/internal/services/config.go
@@ -10,6 +10,7 @@
 
 	"github.com/f1bonacc1/process-compose/src/types"
 	"github.com/pkg/errors"
+	"gopkg.in/yaml.v3"
 
 	"go.jetpack.io/devbox/internal/cuecfg"
 )
@@ -47,6 +48,18 @@ func FromProcessCompose(path string) (Services, error) {
 	return services, nil
 }
 
+func NamesFromProcessCompose(content []byte) ([]string, error) {
+	var processCompose types.Project
+	if err := yaml.Unmarshal(content, &processCompose); err != nil {
+		return nil, err
+	}
+	names := []string{}
+	for name := range processCompose.Processes {
+		names = append(names, name)
+	}
+	return names, nil
+}
+
 func lookupProcessCompose(projectDir, path string) string {
 	if path == "" {
 		path = projectDir
diff --git a/internal/telemetry/sentry.go b/internal/telemetry/sentry.go
index 5b1420a1..91c1d0ac 100644
--- a/internal/telemetry/sentry.go
+++ b/internal/telemetry/sentry.go
@@ -169,17 +169,17 @@ func exportedErrType(err error) string {
 // package path and base name components.
 func splitPkgFunc(name string) (pkgPath, funcName string) {
 	// Using the following fully-qualified function name as an example:
-	// go.jetpack.io/devbox/internal/impl.(*Devbox).RunScript
+	// go.jetpack.io/devbox/internal/devbox.(*Devbox).RunScript
 
 	// dir = go.jetpack.io/devbox/internal/
-	// base = impl.(*Devbox).RunScript
+	// base = devbox.(*Devbox).RunScript
 	dir, base := path.Split(name)
 
-	// pkgName = impl
+	// pkgName = devbox
 	// fn = (*Devbox).RunScript
 	pkgName, fn, _ := strings.Cut(base, ".")
 
-	// pkgPath = go.jetpack.io/devbox/internal/impl
+	// pkgPath = go.jetpack.io/devbox/internal/devbox
 	// funcName = (*Devbox).RunScript
 	return dir + pkgName, fn
 }


Test patch:
diff --git a/internal/impl/devbox_test.go b/internal/devbox/devbox_test.go
similarity index 97%
rename from internal/impl/devbox_test.go
rename to internal/devbox/devbox_test.go
index 7655d697..df3e1c6b 100644
--- a/internal/impl/devbox_test.go
+++ b/internal/devbox/devbox_test.go
@@ -1,7 +1,7 @@
 // Copyright 2023 Jetpack Technologies Inc and contributors. All rights reserved.
 // Use of this source code is governed by the license in the LICENSE file.
 
-package impl
+package devbox
 
 import (
 	"context"
@@ -14,11 +14,11 @@
 	"github.com/bmatcuk/doublestar/v4"
 	"github.com/stretchr/testify/assert"
 	"github.com/stretchr/testify/require"
-	"go.jetpack.io/devbox/internal/impl/envpath"
+	"go.jetpack.io/devbox/internal/devbox/envpath"
 
+	"go.jetpack.io/devbox/internal/devbox/devopt"
 	"go.jetpack.io/devbox/internal/devconfig"
 	"go.jetpack.io/devbox/internal/envir"
-	"go.jetpack.io/devbox/internal/impl/devopt"
 	"go.jetpack.io/devbox/internal/nix"
 )
 
diff --git a/internal/impl/dir_test.go b/internal/devbox/dir_test.go
similarity index 99%
rename from internal/impl/dir_test.go
rename to internal/devbox/dir_test.go
index 940718be..fe5c05a1 100644
--- a/internal/impl/dir_test.go
+++ b/internal/devbox/dir_test.go
@@ -1,7 +1,7 @@
 // Copyright 2023 Jetpack Technologies Inc and contributors. All rights reserved.
 // Use of this source code is governed by the license in the LICENSE file.
 
-package impl
+package devbox
 
 import (
 	"os"
diff --git a/internal/impl/shell_test.go b/internal/devbox/shell_test.go
similarity index 99%
rename from internal/impl/shell_test.go
rename to internal/devbox/shell_test.go
index a91d0db6..a931123b 100644
--- a/internal/impl/shell_test.go
+++ b/internal/devbox/shell_test.go
@@ -1,7 +1,7 @@
 // Copyright 2023 Jetpack Technologies Inc and contributors. All rights reserved.
 // Use of this source code is governed by the license in the LICENSE file.
 
-package impl
+package devbox
 
 import (
 	"errors"
diff --git a/internal/impl/update_test.go b/internal/devbox/update_test.go
similarity index 99%
rename from internal/impl/update_test.go
rename to internal/devbox/update_test.go
index d26707f5..bdb2ed95 100644
--- a/internal/impl/update_test.go
+++ b/internal/devbox/update_test.go
@@ -1,4 +1,4 @@
-package impl
+package devbox
 
 import (
 	"testing"