refactor: rename pkgs (#408)

Ayman Bagabas created

Change summary

cmd/cmd.go                                          |  71 ++
cmd/soft/admin/admin.go                             |  34 
cmd/soft/browse/browse.go                           |  14 
cmd/soft/hook/hook.go                               |  72 -
cmd/soft/main.go                                    |  82 +-
cmd/soft/man.go                                     |  27 
cmd/soft/migrate_config.go                          | 434 ---------------
cmd/soft/serve/serve.go                             |  87 ++-
cmd/soft/serve/server.go                            |  20 
pkg/access/access.go                                |   0 
pkg/access/access_test.go                           |   0 
pkg/access/context.go                               |   0 
pkg/backend/access_token.go                         |   4 
pkg/backend/auth.go                                 |   0 
pkg/backend/auth_test.go                            |   0 
pkg/backend/backend.go                              |   8 
pkg/backend/cache.go                                |   0 
pkg/backend/collab.go                               |  12 
pkg/backend/context.go                              |   0 
pkg/backend/hooks.go                                |   8 
pkg/backend/lfs.go                                  |  12 
pkg/backend/repo.go                                 |  18 
pkg/backend/settings.go                             |   4 
pkg/backend/user.go                                 |  12 
pkg/backend/utils.go                                |   2 
pkg/backend/webhooks.go                             |  10 
pkg/config/config.go                                |   2 
pkg/config/config_test.go                           |   0 
pkg/config/context.go                               |   0 
pkg/config/file.go                                  |   0 
pkg/config/ssh.go                                   |   0 
pkg/config/testdata/k1.pub                          |   0 
pkg/cron/cron.go                                    |   0 
pkg/daemon/conn.go                                  |   0 
pkg/daemon/daemon.go                                |  10 
pkg/daemon/daemon_test.go                           |  16 
pkg/db/context.go                                   |   0 
pkg/db/db.go                                        |   2 
pkg/db/errors.go                                    |   0 
pkg/db/handler.go                                   |   0 
pkg/db/logger.go                                    |   0 
pkg/db/migrate/0001_create_tables.go                |   8 
pkg/db/migrate/0001_create_tables_postgres.down.sql |   0 
pkg/db/migrate/0001_create_tables_postgres.up.sql   |   0 
pkg/db/migrate/0001_create_tables_sqlite.down.sql   |   0 
pkg/db/migrate/0001_create_tables_sqlite.up.sql     |   0 
pkg/db/migrate/0002_webhooks.go                     |   2 
pkg/db/migrate/0002_webhooks_postgres.down.sql      |   0 
pkg/db/migrate/0002_webhooks_postgres.up.sql        |   0 
pkg/db/migrate/0002_webhooks_sqlite.down.sql        |   0 
pkg/db/migrate/0002_webhooks_sqlite.up.sql          |   0 
pkg/db/migrate/migrate.go                           |   2 
pkg/db/migrate/migrations.go                        |   2 
pkg/db/models/access_token.go                       |   0 
pkg/db/models/collab.go                             |   2 
pkg/db/models/lfs.go                                |   0 
pkg/db/models/public_key.go                         |   0 
pkg/db/models/repo.go                               |   0 
pkg/db/models/settings.go                           |   0 
pkg/db/models/user.go                               |   0 
pkg/db/models/webhook.go                            |   0 
pkg/git/errors.go                                   |   0 
pkg/git/git.go                                      |   0 
pkg/git/git_test.go                                 |   0 
pkg/git/lfs.go                                      |  14 
pkg/git/lfs_auth.go                                 |   8 
pkg/git/service.go                                  |   0 
pkg/hooks/gen.go                                    |   4 
pkg/hooks/hooks.go                                  |   0 
pkg/jobs/jobs.go                                    |   0 
pkg/jobs/mirror.go                                  |  12 
pkg/jwk/jwk.go                                      |   2 
pkg/lfs/basic_transfer.go                           |   0 
pkg/lfs/client.go                                   |   0 
pkg/lfs/common.go                                   |   0 
pkg/lfs/endpoint.go                                 |   0 
pkg/lfs/http_client.go                              |   0 
pkg/lfs/pointer.go                                  |   0 
pkg/lfs/pointer_test.go                             |   0 
pkg/lfs/scanner.go                                  |   0 
pkg/lfs/ssh_client.go                               |   0 
pkg/lfs/transfer.go                                 |   0 
pkg/log/log.go                                      |   2 
pkg/proto/access_token.go                           |   0 
pkg/proto/context.go                                |   0 
pkg/proto/errors.go                                 |   0 
pkg/proto/repo.go                                   |   0 
pkg/proto/user.go                                   |   0 
pkg/ssh/cmd/blob.go                                 |   6 
pkg/ssh/cmd/branch.go                               |   6 
pkg/ssh/cmd/cmd.go                                  |  12 
pkg/ssh/cmd/collab.go                               |   4 
pkg/ssh/cmd/commit.go                               |   6 
pkg/ssh/cmd/create.go                               |   6 
pkg/ssh/cmd/delete.go                               |   2 
pkg/ssh/cmd/description.go                          |   2 
pkg/ssh/cmd/git.go                                  |  16 
pkg/ssh/cmd/hidden.go                               |   2 
pkg/ssh/cmd/import.go                               |   6 
pkg/ssh/cmd/info.go                                 |   4 
pkg/ssh/cmd/jwt.go                                  |   6 
pkg/ssh/cmd/list.go                                 |   6 
pkg/ssh/cmd/mirror.go                               |   2 
pkg/ssh/cmd/private.go                              |   2 
pkg/ssh/cmd/project_name.go                         |   2 
pkg/ssh/cmd/pubkey.go                               |   4 
pkg/ssh/cmd/rename.go                               |   2 
pkg/ssh/cmd/repo.go                                 |   4 
pkg/ssh/cmd/set_username.go                         |   4 
pkg/ssh/cmd/settings.go                             |   4 
pkg/ssh/cmd/tag.go                                  |   6 
pkg/ssh/cmd/token.go                                |   4 
pkg/ssh/cmd/tree.go                                 |   4 
pkg/ssh/cmd/user.go                                 |   6 
pkg/ssh/cmd/webhooks.go                             |   4 
pkg/ssh/middleware.go                               |  14 
pkg/ssh/session.go                                  |  10 
pkg/ssh/session_test.go                             |  14 
pkg/ssh/ssh.go                                      |  10 
pkg/ssh/ui.go                                       |  14 
pkg/sshutils/utils.go                               |   0 
pkg/sshutils/utils_test.go                          |   0 
pkg/stats/stats.go                                  |   2 
pkg/storage/local.go                                |   0 
pkg/storage/storage.go                              |   0 
pkg/store/access_token.go                           |   4 
pkg/store/collab.go                                 |   6 
pkg/store/context.go                                |   0 
pkg/store/database/access_token.go                  |   6 
pkg/store/database/collab.go                        |  10 
pkg/store/database/database.go                      |   6 
pkg/store/database/lfs.go                           |   6 
pkg/store/database/repo.go                          |   8 
pkg/store/database/settings.go                      |   6 
pkg/store/database/user.go                          |  10 
pkg/store/database/webhooks.go                      |   6 
pkg/store/lfs.go                                    |   4 
pkg/store/repo.go                                   |   4 
pkg/store/settings.go                               |   4 
pkg/store/store.go                                  |   0 
pkg/store/user.go                                   |   4 
pkg/store/webhooks.go                               |   4 
pkg/sync/workqueue.go                               |   0 
pkg/sync/workqueue_test.go                          |   0 
pkg/task/manager.go                                 |   0 
pkg/test/test.go                                    |   0 
pkg/ui/common/common.go                             |   8 
pkg/ui/common/component.go                          |   0 
pkg/ui/common/error.go                              |   0 
pkg/ui/common/format.go                             |   2 
pkg/ui/common/style.go                              |   0 
pkg/ui/common/utils.go                              |   2 
pkg/ui/components/code/code.go                      |   4 
pkg/ui/components/footer/footer.go                  |   2 
pkg/ui/components/header/header.go                  |   2 
pkg/ui/components/selector/selector.go              |   2 
pkg/ui/components/statusbar/statusbar.go            |   2 
pkg/ui/components/tabs/tabs.go                      |   2 
pkg/ui/components/viewport/viewport.go              |   2 
pkg/ui/keymap/keymap.go                             |   0 
pkg/ui/pages/repo/empty.go                          |   4 
pkg/ui/pages/repo/files.go                          |   8 
pkg/ui/pages/repo/filesitem.go                      |   2 
pkg/ui/pages/repo/log.go                            |  12 
pkg/ui/pages/repo/logitem.go                        |   2 
pkg/ui/pages/repo/readme.go                         |   8 
pkg/ui/pages/repo/refs.go                           |   6 
pkg/ui/pages/repo/refsitem.go                       |   2 
pkg/ui/pages/repo/repo.go                           |  12 
pkg/ui/pages/repo/stash.go                          |   8 
pkg/ui/pages/repo/stashitem.go                      |   2 
pkg/ui/pages/selection/item.go                      |   6 
pkg/ui/pages/selection/selection.go                 |  12 
pkg/ui/styles/styles.go                             |   0 
pkg/utils/utils.go                                  |   0 
pkg/utils/utils_test.go                             |   0 
pkg/version/version.go                              |   0 
pkg/web/auth.go                                     |   6 
pkg/web/context.go                                  |   8 
pkg/web/git.go                                      |  14 
pkg/web/git_lfs.go                                  |  18 
pkg/web/goget.go                                    |   6 
pkg/web/http.go                                     |   2 
pkg/web/logging.go                                  |   0 
pkg/web/server.go                                   |   0 
pkg/web/util.go                                     |   0 
pkg/webhook/branch_tag.go                           |   8 
pkg/webhook/collaborator.go                         |   8 
pkg/webhook/common.go                               |   0 
pkg/webhook/content_type.go                         |   0 
pkg/webhook/event.go                                |   0 
pkg/webhook/push.go                                 |   8 
pkg/webhook/repository.go                           |   8 
pkg/webhook/webhook.go                              |  10 
testscript/script_test.go                           |  20 
195 files changed, 556 insertions(+), 975 deletions(-)

Detailed changes

cmd/cmd.go 🔗

@@ -0,0 +1,71 @@
+package cmd
+
+import (
+	"context"
+	"errors"
+	"fmt"
+	"io/fs"
+	"os"
+
+	"github.com/charmbracelet/soft-serve/pkg/backend"
+	"github.com/charmbracelet/soft-serve/pkg/config"
+	"github.com/charmbracelet/soft-serve/pkg/db"
+	"github.com/charmbracelet/soft-serve/pkg/hooks"
+	"github.com/charmbracelet/soft-serve/pkg/store"
+	"github.com/charmbracelet/soft-serve/pkg/store/database"
+	"github.com/spf13/cobra"
+)
+
+// InitBackendContext initializes the backend context.
+func InitBackendContext(cmd *cobra.Command, _ []string) error {
+	ctx := cmd.Context()
+	cfg := config.FromContext(ctx)
+	if _, err := os.Stat(cfg.DataPath); errors.Is(err, fs.ErrNotExist) {
+		if err := os.MkdirAll(cfg.DataPath, os.ModePerm); err != nil {
+			return fmt.Errorf("create data directory: %w", err)
+		}
+	}
+	dbx, err := db.Open(ctx, cfg.DB.Driver, cfg.DB.DataSource)
+	if err != nil {
+		return fmt.Errorf("open database: %w", err)
+	}
+
+	ctx = db.WithContext(ctx, dbx)
+	dbstore := database.New(ctx, dbx)
+	ctx = store.WithContext(ctx, dbstore)
+	be := backend.New(ctx, cfg, dbx)
+	ctx = backend.WithContext(ctx, be)
+
+	cmd.SetContext(ctx)
+
+	return nil
+}
+
+// CloseDBContext closes the database context.
+func CloseDBContext(cmd *cobra.Command, _ []string) error {
+	ctx := cmd.Context()
+	dbx := db.FromContext(ctx)
+	if dbx != nil {
+		if err := dbx.Close(); err != nil {
+			return fmt.Errorf("close database: %w", err)
+		}
+	}
+
+	return nil
+}
+
+// InitializeHooks initializes the hooks.
+func InitializeHooks(ctx context.Context, cfg *config.Config, be *backend.Backend) error {
+	repos, err := be.Repositories(ctx)
+	if err != nil {
+		return err
+	}
+
+	for _, repo := range repos {
+		if err := hooks.GenerateHooks(ctx, cfg, repo.Name()); err != nil {
+			return err
+		}
+	}
+
+	return nil
+}

cmd/soft/admin.go → cmd/soft/admin/admin.go 🔗

@@ -1,17 +1,19 @@
-package main
+package admin
 
 import (
 	"fmt"
 
-	"github.com/charmbracelet/soft-serve/server/backend"
-	"github.com/charmbracelet/soft-serve/server/config"
-	"github.com/charmbracelet/soft-serve/server/db"
-	"github.com/charmbracelet/soft-serve/server/db/migrate"
+	"github.com/charmbracelet/soft-serve/cmd"
+	"github.com/charmbracelet/soft-serve/pkg/backend"
+	"github.com/charmbracelet/soft-serve/pkg/config"
+	"github.com/charmbracelet/soft-serve/pkg/db"
+	"github.com/charmbracelet/soft-serve/pkg/db/migrate"
 	"github.com/spf13/cobra"
 )
 
 var (
-	adminCmd = &cobra.Command{
+	// Command is the admin command.
+	Command = &cobra.Command{
 		Use:   "admin",
 		Short: "Administrate the server",
 	}
@@ -19,8 +21,8 @@ var (
 	migrateCmd = &cobra.Command{
 		Use:                "migrate",
 		Short:              "Migrate the database to the latest version",
-		PersistentPreRunE:  initBackendContext,
-		PersistentPostRunE: closeDBContext,
+		PersistentPreRunE:  cmd.InitBackendContext,
+		PersistentPostRunE: cmd.CloseDBContext,
 		RunE: func(cmd *cobra.Command, _ []string) error {
 			ctx := cmd.Context()
 			db := db.FromContext(ctx)
@@ -35,8 +37,8 @@ var (
 	rollbackCmd = &cobra.Command{
 		Use:                "rollback",
 		Short:              "Rollback the database to the previous version",
-		PersistentPreRunE:  initBackendContext,
-		PersistentPostRunE: closeDBContext,
+		PersistentPreRunE:  cmd.InitBackendContext,
+		PersistentPostRunE: cmd.CloseDBContext,
 		RunE: func(cmd *cobra.Command, _ []string) error {
 			ctx := cmd.Context()
 			db := db.FromContext(ctx)
@@ -51,13 +53,13 @@ var (
 	syncHooksCmd = &cobra.Command{
 		Use:                "sync-hooks",
 		Short:              "Update repository hooks",
-		PersistentPreRunE:  initBackendContext,
-		PersistentPostRunE: closeDBContext,
-		RunE: func(cmd *cobra.Command, _ []string) error {
-			ctx := cmd.Context()
+		PersistentPreRunE:  cmd.InitBackendContext,
+		PersistentPostRunE: cmd.CloseDBContext,
+		RunE: func(c *cobra.Command, _ []string) error {
+			ctx := c.Context()
 			cfg := config.FromContext(ctx)
 			be := backend.FromContext(ctx)
-			if err := initializeHooks(ctx, cfg, be); err != nil {
+			if err := cmd.InitializeHooks(ctx, cfg, be); err != nil {
 				return fmt.Errorf("initialize hooks: %w", err)
 			}
 
@@ -67,7 +69,7 @@ var (
 )
 
 func init() {
-	adminCmd.AddCommand(
+	Command.AddCommand(
 		syncHooksCmd,
 		migrateCmd,
 		rollbackCmd,

cmd/soft/browse.go → cmd/soft/browse/browse.go 🔗

@@ -1,4 +1,4 @@
-package main
+package browse
 
 import (
 	"fmt"
@@ -9,15 +9,16 @@ import (
 	tea "github.com/charmbracelet/bubbletea"
 	"github.com/charmbracelet/lipgloss"
 	"github.com/charmbracelet/soft-serve/git"
-	"github.com/charmbracelet/soft-serve/server/proto"
-	"github.com/charmbracelet/soft-serve/server/ui/common"
-	"github.com/charmbracelet/soft-serve/server/ui/components/footer"
-	"github.com/charmbracelet/soft-serve/server/ui/pages/repo"
+	"github.com/charmbracelet/soft-serve/pkg/proto"
+	"github.com/charmbracelet/soft-serve/pkg/ui/common"
+	"github.com/charmbracelet/soft-serve/pkg/ui/components/footer"
+	"github.com/charmbracelet/soft-serve/pkg/ui/pages/repo"
 	"github.com/muesli/termenv"
 	"github.com/spf13/cobra"
 )
 
-var browseCmd = &cobra.Command{
+// Command is the browse command.
+var Command = &cobra.Command{
 	Use:   "browse PATH",
 	Short: "Browse a repository",
 	Args:  cobra.MaximumNArgs(1),
@@ -72,7 +73,6 @@ func init() {
 	// HACK: This is a hack to hide the clone url
 	// TODO: Make this configurable
 	common.CloneCmd = func(publicURL, name string) string { return "" }
-	rootCmd.AddCommand(browseCmd)
 }
 
 type state int

cmd/soft/hook.go → cmd/soft/hook/hook.go 🔗

@@ -1,4 +1,4 @@
-package main
+package hook
 
 import (
 	"bufio"
@@ -13,9 +13,10 @@ import (
 	"strings"
 
 	"github.com/charmbracelet/log"
-	"github.com/charmbracelet/soft-serve/server/backend"
-	"github.com/charmbracelet/soft-serve/server/config"
-	"github.com/charmbracelet/soft-serve/server/hooks"
+	"github.com/charmbracelet/soft-serve/cmd"
+	"github.com/charmbracelet/soft-serve/pkg/backend"
+	"github.com/charmbracelet/soft-serve/pkg/config"
+	"github.com/charmbracelet/soft-serve/pkg/hooks"
 	"github.com/spf13/cobra"
 )
 
@@ -26,23 +27,24 @@ var (
 	// Deprecated: this flag is ignored.
 	configPath string
 
-	hookCmd = &cobra.Command{
+	// Command is the hook command.
+	Command = &cobra.Command{
 		Use:    "hook",
 		Short:  "Run git server hooks",
 		Long:   "Handles Soft Serve git server hooks.",
 		Hidden: true,
-		PersistentPreRunE: func(cmd *cobra.Command, args []string) error {
-			logger := log.FromContext(cmd.Context())
-			if err := initBackendContext(cmd, args); err != nil {
+		PersistentPreRunE: func(c *cobra.Command, args []string) error {
+			logger := log.FromContext(c.Context())
+			if err := cmd.InitBackendContext(c, args); err != nil {
 				logger.Error("failed to initialize backend context", "err", err)
 				return ErrInternalServerError
 			}
 
 			return nil
 		},
-		PersistentPostRunE: func(cmd *cobra.Command, args []string) error {
-			logger := log.FromContext(cmd.Context())
-			if err := closeDBContext(cmd, args); err != nil {
+		PersistentPostRunE: func(c *cobra.Command, args []string) error {
+			logger := log.FromContext(c.Context())
+			if err := cmd.CloseDBContext(c, args); err != nil {
 				logger.Error("failed to close backend", "err", err)
 				return ErrInternalServerError
 			}
@@ -147,8 +149,8 @@ var (
 )
 
 func init() {
-	hookCmd.PersistentFlags().StringVar(&configPath, "config", "", "path to config file (deprecated)")
-	hookCmd.AddCommand(
+	Command.PersistentFlags().StringVar(&configPath, "config", "", "path to config file (deprecated)")
+	Command.AddCommand(
 		preReceiveCmd,
 		updateCmd,
 		postReceiveCmd,
@@ -163,47 +165,3 @@ func runCommand(ctx context.Context, in io.Reader, out io.Writer, err io.Writer,
 	cmd.Stderr = err
 	return cmd.Run()
 }
-
-const updateHookExample = `#!/bin/sh
-#
-# An example hook script to echo information about the push
-# and send it to the client.
-#
-# To enable this hook, rename this file to "update" and make it executable.
-
-refname="$1"
-oldrev="$2"
-newrev="$3"
-
-# Safety check
-if [ -z "$GIT_DIR" ]; then
-        echo "Don't run this script from the command line." >&2
-        echo " (if you want, you could supply GIT_DIR then run" >&2
-        echo "  $0 <ref> <oldrev> <newrev>)" >&2
-        exit 1
-fi
-
-if [ -z "$refname" -o -z "$oldrev" -o -z "$newrev" ]; then
-        echo "usage: $0 <ref> <oldrev> <newrev>" >&2
-        exit 1
-fi
-
-# Check types
-# if $newrev is 0000...0000, it's a commit to delete a ref.
-zero=$(git hash-object --stdin </dev/null | tr '[0-9a-f]' '0')
-if [ "$newrev" = "$zero" ]; then
-        newrev_type=delete
-else
-        newrev_type=$(git cat-file -t $newrev)
-fi
-
-echo "Hi from Soft Serve update hook!"
-echo
-echo "Repository: $SOFT_SERVE_REPO_NAME"
-echo "RefName: $refname"
-echo "Change Type: $newrev_type"
-echo "Old SHA1: $oldrev"
-echo "New SHA1: $newrev"
-
-exit 0
-`

cmd/soft/root.go → cmd/soft/main.go 🔗

@@ -2,20 +2,20 @@ package main
 
 import (
 	"context"
-	"errors"
 	"fmt"
-	"io/fs"
 	"os"
 	"runtime/debug"
 
 	"github.com/charmbracelet/log"
-	"github.com/charmbracelet/soft-serve/server/backend"
-	"github.com/charmbracelet/soft-serve/server/config"
-	"github.com/charmbracelet/soft-serve/server/db"
-	logr "github.com/charmbracelet/soft-serve/server/log"
-	"github.com/charmbracelet/soft-serve/server/store"
-	"github.com/charmbracelet/soft-serve/server/store/database"
-	"github.com/charmbracelet/soft-serve/server/version"
+	"github.com/charmbracelet/soft-serve/cmd/soft/admin"
+	"github.com/charmbracelet/soft-serve/cmd/soft/browse"
+	"github.com/charmbracelet/soft-serve/cmd/soft/hook"
+	"github.com/charmbracelet/soft-serve/cmd/soft/serve"
+	"github.com/charmbracelet/soft-serve/pkg/config"
+	logr "github.com/charmbracelet/soft-serve/pkg/log"
+	"github.com/charmbracelet/soft-serve/pkg/version"
+	mcobra "github.com/muesli/mango-cobra"
+	"github.com/muesli/roff"
 	"github.com/spf13/cobra"
 	"go.uber.org/automaxprocs/maxprocs"
 )
@@ -39,18 +39,36 @@ var (
 		Long:         "Soft Serve is a self-hostable Git server for the command line.",
 		SilenceUsage: true,
 		RunE: func(cmd *cobra.Command, args []string) error {
-			return browseCmd.RunE(cmd, args)
+			return browse.Command.RunE(cmd, args)
+		},
+	}
+
+	manCmd = &cobra.Command{
+		Use:    "man",
+		Short:  "Generate man pages",
+		Args:   cobra.NoArgs,
+		Hidden: true,
+		RunE: func(_ *cobra.Command, _ []string) error {
+			manPage, err := mcobra.NewManPage(1, rootCmd) //.
+			if err != nil {
+				return err
+			}
+
+			manPage = manPage.WithSection("Copyright", "(C) 2021-2023 Charmbracelet, Inc.\n"+
+				"Released under MIT license.")
+			fmt.Println(manPage.Build(roff.NewDocument()))
+			return nil
 		},
 	}
 )
 
 func init() {
 	rootCmd.AddCommand(
-		serveCmd,
 		manCmd,
-		hookCmd,
-		migrateConfig,
-		adminCmd,
+		serve.Command,
+		hook.Command,
+		admin.Command,
+		browse.Command,
 	)
 	rootCmd.CompletionOptions.HiddenDefaultCmd = true
 
@@ -114,39 +132,3 @@ func main() {
 		os.Exit(1)
 	}
 }
-
-func initBackendContext(cmd *cobra.Command, _ []string) error {
-	ctx := cmd.Context()
-	cfg := config.FromContext(ctx)
-	if _, err := os.Stat(cfg.DataPath); errors.Is(err, fs.ErrNotExist) {
-		if err := os.MkdirAll(cfg.DataPath, os.ModePerm); err != nil {
-			return fmt.Errorf("create data directory: %w", err)
-		}
-	}
-	dbx, err := db.Open(ctx, cfg.DB.Driver, cfg.DB.DataSource)
-	if err != nil {
-		return fmt.Errorf("open database: %w", err)
-	}
-
-	ctx = db.WithContext(ctx, dbx)
-	dbstore := database.New(ctx, dbx)
-	ctx = store.WithContext(ctx, dbstore)
-	be := backend.New(ctx, cfg, dbx)
-	ctx = backend.WithContext(ctx, be)
-
-	cmd.SetContext(ctx)
-
-	return nil
-}
-
-func closeDBContext(cmd *cobra.Command, _ []string) error {
-	ctx := cmd.Context()
-	dbx := db.FromContext(ctx)
-	if dbx != nil {
-		if err := dbx.Close(); err != nil {
-			return fmt.Errorf("close database: %w", err)
-		}
-	}
-
-	return nil
-}

cmd/soft/man.go 🔗

@@ -1,27 +0,0 @@
-package main
-
-import (
-	"fmt"
-
-	mcobra "github.com/muesli/mango-cobra"
-	"github.com/muesli/roff"
-	"github.com/spf13/cobra"
-)
-
-var manCmd = &cobra.Command{
-	Use:    "man",
-	Short:  "Generate man pages",
-	Args:   cobra.NoArgs,
-	Hidden: true,
-	RunE: func(_ *cobra.Command, _ []string) error {
-		manPage, err := mcobra.NewManPage(1, rootCmd) //.
-		if err != nil {
-			return err
-		}
-
-		manPage = manPage.WithSection("Copyright", "(C) 2021-2023 Charmbracelet, Inc.\n"+
-			"Released under MIT license.")
-		fmt.Println(manPage.Build(roff.NewDocument()))
-		return nil
-	},
-}

cmd/soft/migrate_config.go 🔗

@@ -1,434 +0,0 @@
-package main
-
-import (
-	"encoding/json"
-	"errors"
-	"fmt"
-	"io"
-	"os"
-	"path/filepath"
-	"strings"
-	"time"
-
-	"github.com/charmbracelet/log"
-	"github.com/charmbracelet/soft-serve/git"
-	"github.com/charmbracelet/soft-serve/server/access"
-	"github.com/charmbracelet/soft-serve/server/backend"
-	"github.com/charmbracelet/soft-serve/server/config"
-	"github.com/charmbracelet/soft-serve/server/db"
-	"github.com/charmbracelet/soft-serve/server/proto"
-	"github.com/charmbracelet/soft-serve/server/sshutils"
-	"github.com/charmbracelet/soft-serve/server/utils"
-	gitm "github.com/gogs/git-module"
-	"github.com/spf13/cobra"
-	"golang.org/x/crypto/ssh"
-	"gopkg.in/yaml.v3"
-)
-
-// Deprecated: will be removed in a future release.
-var migrateConfig = &cobra.Command{
-	Use:    "migrate-config",
-	Short:  "Migrate config to new format",
-	Hidden: true,
-	RunE: func(cmd *cobra.Command, _ []string) error {
-		ctx := cmd.Context()
-
-		logger := log.FromContext(ctx)
-		// Disable logging timestamp
-		logger.SetReportTimestamp(false)
-
-		keyPath := os.Getenv("SOFT_SERVE_KEY_PATH")
-		reposPath := os.Getenv("SOFT_SERVE_REPO_PATH")
-		bindAddr := os.Getenv("SOFT_SERVE_BIND_ADDRESS")
-		cfg := config.DefaultConfig()
-		if err := cfg.ParseEnv(); err != nil {
-			return fmt.Errorf("parse env: %w", err)
-		}
-
-		ctx = config.WithContext(ctx, cfg)
-		db, err := db.Open(ctx, cfg.DB.Driver, cfg.DB.DataSource)
-		if err != nil {
-			return fmt.Errorf("open database: %w", err)
-		}
-
-		defer db.Close() // nolint: errcheck
-		sb := backend.New(ctx, cfg, db)
-
-		// FIXME: Admin user gets created when the database is created.
-		sb.DeleteUser(ctx, "admin") // nolint: errcheck
-
-		// Set SSH listen address
-		logger.Info("Setting SSH listen address...")
-		if bindAddr != "" {
-			cfg.SSH.ListenAddr = bindAddr
-		}
-
-		// Copy SSH host key
-		logger.Info("Copying SSH host key...")
-		if keyPath != "" {
-			if err := os.MkdirAll(filepath.Join(cfg.DataPath, "ssh"), os.ModePerm); err != nil {
-				return fmt.Errorf("failed to create ssh directory: %w", err)
-			}
-
-			if err := copyFile(keyPath, filepath.Join(cfg.DataPath, "ssh", filepath.Base(keyPath))); err != nil {
-				return fmt.Errorf("failed to copy ssh key: %w", err)
-			}
-
-			if err := copyFile(keyPath+".pub", filepath.Join(cfg.DataPath, "ssh", filepath.Base(keyPath))+".pub"); err != nil {
-				logger.Errorf("failed to copy ssh key: %s", err)
-			}
-
-			cfg.SSH.KeyPath = filepath.Join(cfg.DataPath, "ssh", filepath.Base(keyPath))
-		}
-
-		// Read config
-		logger.Info("Reading config repository...")
-		r, err := git.Open(filepath.Join(reposPath, "config"))
-		if err != nil {
-			return fmt.Errorf("failed to open config repo: %w", err)
-		}
-
-		head, err := r.HEAD()
-		if err != nil {
-			return fmt.Errorf("failed to get head: %w", err)
-		}
-
-		tree, err := r.TreePath(head, "")
-		if err != nil {
-			return fmt.Errorf("failed to get tree: %w", err)
-		}
-
-		isJson := false // nolint: revive
-		te, err := tree.TreeEntry("config.yaml")
-		if err != nil {
-			te, err = tree.TreeEntry("config.json")
-			if err != nil {
-				return fmt.Errorf("failed to get config file: %w", err)
-			}
-			isJson = true
-		}
-
-		cc, err := te.Contents()
-		if err != nil {
-			return fmt.Errorf("failed to get config contents: %w", err)
-		}
-
-		var ocfg Config
-		if isJson {
-			if err := json.Unmarshal(cc, &ocfg); err != nil {
-				return fmt.Errorf("failed to unmarshal config: %w", err)
-			}
-		} else {
-			if err := yaml.Unmarshal(cc, &ocfg); err != nil {
-				return fmt.Errorf("failed to unmarshal config: %w", err)
-			}
-		}
-
-		readme, readmePath, err := git.LatestFile(r, nil, "README*")
-		hasReadme := err == nil
-
-		// Set server name
-		cfg.Name = ocfg.Name
-
-		// Set server public url
-		cfg.SSH.PublicURL = fmt.Sprintf("ssh://%s:%d", ocfg.Host, ocfg.Port)
-
-		// Set server settings
-		logger.Info("Setting server settings...")
-		if sb.SetAllowKeyless(ctx, ocfg.AllowKeyless) != nil {
-			fmt.Fprintf(os.Stderr, "failed to set allow keyless\n")
-		}
-		anon := access.ParseAccessLevel(ocfg.AnonAccess)
-		if anon >= 0 {
-			if err := sb.SetAnonAccess(ctx, anon); err != nil {
-				fmt.Fprintf(os.Stderr, "failed to set anon access: %s\n", err)
-			}
-		}
-
-		// Copy repos
-		if reposPath != "" {
-			logger.Info("Copying repos...")
-			if err := os.MkdirAll(filepath.Join(cfg.DataPath, "repos"), os.ModePerm); err != nil {
-				return fmt.Errorf("failed to create repos directory: %w", err)
-			}
-
-			dirs, err := os.ReadDir(reposPath)
-			if err != nil {
-				return fmt.Errorf("failed to read repos directory: %w", err)
-			}
-
-			for _, dir := range dirs {
-				if !dir.IsDir() || dir.Name() == "config" {
-					continue
-				}
-
-				if !isGitDir(filepath.Join(reposPath, dir.Name())) {
-					continue
-				}
-
-				logger.Infof("  Copying repo %s", dir.Name())
-				src := filepath.Join(reposPath, utils.SanitizeRepo(dir.Name()))
-				dst := filepath.Join(cfg.DataPath, "repos", utils.SanitizeRepo(dir.Name())) + ".git"
-				if err := os.MkdirAll(dst, os.ModePerm); err != nil {
-					return fmt.Errorf("failed to create repo directory: %w", err)
-				}
-
-				if err := copyDir(src, dst); err != nil {
-					return fmt.Errorf("failed to copy repo: %w", err)
-				}
-
-				if _, err := sb.CreateRepository(ctx, dir.Name(), nil, proto.RepositoryOptions{}); err != nil {
-					fmt.Fprintf(os.Stderr, "failed to create repository: %s\n", err)
-				}
-			}
-
-			if hasReadme {
-				logger.Infof("  Copying readme from \"config\" to \".soft-serve\"")
-
-				// Switch to main branch
-				bcmd := git.NewCommand("branch", "-M", "main")
-
-				rp := filepath.Join(cfg.DataPath, "repos", ".soft-serve.git")
-				nr, err := git.Init(rp, true)
-				if err != nil {
-					return fmt.Errorf("failed to init repo: %w", err)
-				}
-
-				if _, err := nr.SymbolicRef("HEAD", gitm.RefsHeads+"main"); err != nil {
-					return fmt.Errorf("failed to set HEAD: %w", err)
-				}
-
-				tmpDir, err := os.MkdirTemp("", "soft-serve")
-				if err != nil {
-					return fmt.Errorf("failed to create temp dir: %w", err)
-				}
-
-				r, err := git.Init(tmpDir, false)
-				if err != nil {
-					return fmt.Errorf("failed to clone repo: %w", err)
-				}
-
-				if _, err := bcmd.RunInDir(tmpDir); err != nil {
-					return fmt.Errorf("failed to create main branch: %w", err)
-				}
-
-				if err := os.WriteFile(filepath.Join(tmpDir, readmePath), []byte(readme), 0o644); err != nil { // nolint: gosec
-					return fmt.Errorf("failed to write readme: %w", err)
-				}
-
-				if err := r.Add(gitm.AddOptions{
-					All: true,
-				}); err != nil {
-					return fmt.Errorf("failed to add readme: %w", err)
-				}
-
-				if err := r.Commit(&gitm.Signature{
-					Name:  "Soft Serve",
-					Email: "vt100@charm.sh",
-					When:  time.Now(),
-				}, "Add readme"); err != nil {
-					return fmt.Errorf("failed to commit readme: %w", err)
-				}
-
-				if err := r.RemoteAdd("origin", "file://"+rp); err != nil {
-					return fmt.Errorf("failed to add remote: %w", err)
-				}
-
-				if err := r.Push("origin", "main"); err != nil {
-					return fmt.Errorf("failed to push readme: %w", err)
-				}
-
-				// Create `.soft-serve` repository and add readme
-				if _, err := sb.CreateRepository(ctx, ".soft-serve", nil, proto.RepositoryOptions{
-					ProjectName: "Home",
-					Description: "Soft Serve home repository",
-					Hidden:      true,
-					Private:     false,
-				}); err != nil {
-					fmt.Fprintf(os.Stderr, "failed to create repository: %s\n", err)
-				}
-			}
-		}
-
-		// Set repos metadata & collabs
-		logger.Info("Setting repos metadata & collabs...")
-		for _, r := range ocfg.Repos {
-			repo, name := r.Repo, r.Name
-			// Special case for config repo
-			if repo == "config" {
-				repo = ".soft-serve"
-				r.Private = false
-			}
-
-			if err := sb.SetProjectName(ctx, repo, name); err != nil {
-				logger.Errorf("failed to set repo name to %s: %s", repo, err)
-			}
-
-			if err := sb.SetDescription(ctx, repo, r.Note); err != nil {
-				logger.Errorf("failed to set repo description to %s: %s", repo, err)
-			}
-
-			if err := sb.SetPrivate(ctx, repo, r.Private); err != nil {
-				logger.Errorf("failed to set repo private to %s: %s", repo, err)
-			}
-
-			for _, collab := range r.Collabs {
-				if err := sb.AddCollaborator(ctx, repo, collab, access.ReadWriteAccess); err != nil {
-					logger.Errorf("failed to add repo collab to %s: %s", repo, err)
-				}
-			}
-		}
-
-		// Create users & collabs
-		logger.Info("Creating users & collabs...")
-		for _, user := range ocfg.Users {
-			keys := make(map[string]ssh.PublicKey)
-			for _, key := range user.PublicKeys {
-				pk, _, err := sshutils.ParseAuthorizedKey(key)
-				if err != nil {
-					continue
-				}
-				ak := sshutils.MarshalAuthorizedKey(pk)
-				keys[ak] = pk
-			}
-
-			pubkeys := make([]ssh.PublicKey, 0)
-			for _, pk := range keys {
-				pubkeys = append(pubkeys, pk)
-			}
-
-			username := strings.ToLower(user.Name)
-			username = strings.ReplaceAll(username, " ", "-")
-			logger.Infof("Creating user %q", username)
-			if _, err := sb.CreateUser(ctx, username, proto.UserOptions{
-				Admin:      user.Admin,
-				PublicKeys: pubkeys,
-			}); err != nil {
-				logger.Errorf("failed to create user: %s", err)
-			}
-
-			for _, repo := range user.CollabRepos {
-				if err := sb.AddCollaborator(ctx, repo, username, access.ReadWriteAccess); err != nil {
-					logger.Errorf("failed to add user collab to %s: %s\n", repo, err)
-				}
-			}
-		}
-
-		logger.Info("Writing config...")
-		defer logger.Info("Done!")
-		return cfg.WriteConfig()
-	},
-}
-
-// Returns true if path is a directory containing an `objects` directory and a
-// `HEAD` file.
-func isGitDir(path string) bool {
-	stat, err := os.Stat(filepath.Join(path, "objects"))
-	if err != nil {
-		return false
-	}
-	if !stat.IsDir() {
-		return false
-	}
-
-	stat, err = os.Stat(filepath.Join(path, "HEAD"))
-	if err != nil {
-		return false
-	}
-	if stat.IsDir() {
-		return false
-	}
-
-	return true
-}
-
-// copyFile copies a single file from src to dst.
-func copyFile(src, dst string) error {
-	var err error
-	var srcfd *os.File
-	var dstfd *os.File
-	var srcinfo os.FileInfo
-
-	if srcfd, err = os.Open(src); err != nil {
-		return err
-	}
-	defer srcfd.Close() // nolint: errcheck
-
-	if dstfd, err = os.Create(dst); err != nil {
-		return err
-	}
-	defer dstfd.Close() // nolint: errcheck
-
-	if _, err = io.Copy(dstfd, srcfd); err != nil {
-		return err
-	}
-	if srcinfo, err = os.Stat(src); err != nil {
-		return err
-	}
-	return os.Chmod(dst, srcinfo.Mode())
-}
-
-// copyDir copies a whole directory recursively.
-func copyDir(src string, dst string) error {
-	var err error
-	var fds []os.DirEntry
-	var srcinfo os.FileInfo
-
-	if srcinfo, err = os.Stat(src); err != nil {
-		return err
-	}
-
-	if err = os.MkdirAll(dst, srcinfo.Mode()); err != nil {
-		return err
-	}
-
-	if fds, err = os.ReadDir(src); err != nil {
-		return err
-	}
-
-	for _, fd := range fds {
-		srcfp := filepath.Join(src, fd.Name())
-		dstfp := filepath.Join(dst, fd.Name())
-
-		if fd.IsDir() {
-			if err = copyDir(srcfp, dstfp); err != nil {
-				err = errors.Join(err, err)
-			}
-		} else {
-			if err = copyFile(srcfp, dstfp); err != nil {
-				err = errors.Join(err, err)
-			}
-		}
-	}
-
-	return err
-}
-
-// Config is the configuration for the server.
-type Config struct {
-	Name         string       `yaml:"name" json:"name"`
-	Host         string       `yaml:"host" json:"host"`
-	Port         int          `yaml:"port" json:"port"`
-	AnonAccess   string       `yaml:"anon-access" json:"anon-access"`
-	AllowKeyless bool         `yaml:"allow-keyless" json:"allow-keyless"`
-	Users        []User       `yaml:"users" json:"users"`
-	Repos        []RepoConfig `yaml:"repos" json:"repos"`
-}
-
-// User contains user-level configuration for a repository.
-type User struct {
-	Name        string   `yaml:"name" json:"name"`
-	Admin       bool     `yaml:"admin" json:"admin"`
-	PublicKeys  []string `yaml:"public-keys" json:"public-keys"`
-	CollabRepos []string `yaml:"collab-repos" json:"collab-repos"`
-}
-
-// RepoConfig is a repository configuration.
-type RepoConfig struct {
-	Name    string   `yaml:"name" json:"name"`
-	Repo    string   `yaml:"repo" json:"repo"`
-	Note    string   `yaml:"note" json:"note"`
-	Private bool     `yaml:"private" json:"private"`
-	Readme  string   `yaml:"readme" json:"readme"`
-	Collabs []string `yaml:"collabs" json:"collabs"`
-}

cmd/soft/serve.go → cmd/soft/serve/serve.go 🔗

@@ -1,4 +1,4 @@
-package main
+package serve
 
 import (
 	"context"
@@ -9,26 +9,26 @@ import (
 	"syscall"
 	"time"
 
-	"github.com/charmbracelet/soft-serve/server"
-	"github.com/charmbracelet/soft-serve/server/backend"
-	"github.com/charmbracelet/soft-serve/server/config"
-	"github.com/charmbracelet/soft-serve/server/db"
-	"github.com/charmbracelet/soft-serve/server/db/migrate"
-	"github.com/charmbracelet/soft-serve/server/hooks"
+	"github.com/charmbracelet/soft-serve/cmd"
+	"github.com/charmbracelet/soft-serve/pkg/backend"
+	"github.com/charmbracelet/soft-serve/pkg/config"
+	"github.com/charmbracelet/soft-serve/pkg/db"
+	"github.com/charmbracelet/soft-serve/pkg/db/migrate"
 	"github.com/spf13/cobra"
 )
 
 var (
 	syncHooks bool
 
-	serveCmd = &cobra.Command{
+	// Command is the serve command.
+	Command = &cobra.Command{
 		Use:                "serve",
 		Short:              "Start the server",
 		Args:               cobra.NoArgs,
-		PersistentPreRunE:  initBackendContext,
-		PersistentPostRunE: closeDBContext,
-		RunE: func(cmd *cobra.Command, _ []string) error {
-			ctx := cmd.Context()
+		PersistentPreRunE:  cmd.InitBackendContext,
+		PersistentPostRunE: cmd.CloseDBContext,
+		RunE: func(c *cobra.Command, _ []string) error {
+			ctx := c.Context()
 			cfg := config.DefaultConfig()
 			if cfg.Exist() {
 				if err := cfg.ParseFile(); err != nil {
@@ -67,14 +67,14 @@ var (
 				return fmt.Errorf("migration error: %w", err)
 			}
 
-			s, err := server.NewServer(ctx)
+			s, err := NewServer(ctx)
 			if err != nil {
 				return fmt.Errorf("start server: %w", err)
 			}
 
 			if syncHooks {
 				be := backend.FromContext(ctx)
-				if err := initializeHooks(ctx, cfg, be); err != nil {
+				if err := cmd.InitializeHooks(ctx, cfg, be); err != nil {
 					return fmt.Errorf("initialize hooks: %w", err)
 				}
 			}
@@ -103,20 +103,49 @@ var (
 )
 
 func init() {
-	serveCmd.Flags().BoolVarP(&syncHooks, "sync-hooks", "", false, "synchronize hooks for all repositories before running the server")
+	Command.Flags().BoolVarP(&syncHooks, "sync-hooks", "", false, "synchronize hooks for all repositories before running the server")
 }
 
-func initializeHooks(ctx context.Context, cfg *config.Config, be *backend.Backend) error {
-	repos, err := be.Repositories(ctx)
-	if err != nil {
-		return err
-	}
-
-	for _, repo := range repos {
-		if err := hooks.GenerateHooks(ctx, cfg, repo.Name()); err != nil {
-			return err
-		}
-	}
-
-	return nil
-}
+const updateHookExample = `#!/bin/sh
+#
+# An example hook script to echo information about the push
+# and send it to the client.
+#
+# To enable this hook, rename this file to "update" and make it executable.
+
+refname="$1"
+oldrev="$2"
+newrev="$3"
+
+# Safety check
+if [ -z "$GIT_DIR" ]; then
+        echo "Don't run this script from the command line." >&2
+        echo " (if you want, you could supply GIT_DIR then run" >&2
+        echo "  $0 <ref> <oldrev> <newrev>)" >&2
+        exit 1
+fi
+
+if [ -z "$refname" -o -z "$oldrev" -o -z "$newrev" ]; then
+        echo "usage: $0 <ref> <oldrev> <newrev>" >&2
+        exit 1
+fi
+
+# Check types
+# if $newrev is 0000...0000, it's a commit to delete a ref.
+zero=$(git hash-object --stdin </dev/null | tr '[0-9a-f]' '0')
+if [ "$newrev" = "$zero" ]; then
+        newrev_type=delete
+else
+        newrev_type=$(git cat-file -t $newrev)
+fi
+
+echo "Hi from Soft Serve update hook!"
+echo
+echo "Repository: $SOFT_SERVE_REPO_NAME"
+echo "RefName: $refname"
+echo "Change Type: $newrev_type"
+echo "Old SHA1: $oldrev"
+echo "New SHA1: $newrev"
+
+exit 0
+`

server/server.go → cmd/soft/serve/server.go 🔗

@@ -1,4 +1,4 @@
-package server
+package serve
 
 import (
 	"context"
@@ -8,15 +8,15 @@ import (
 
 	"github.com/charmbracelet/log"
 
-	"github.com/charmbracelet/soft-serve/server/backend"
-	"github.com/charmbracelet/soft-serve/server/config"
-	"github.com/charmbracelet/soft-serve/server/cron"
-	"github.com/charmbracelet/soft-serve/server/daemon"
-	"github.com/charmbracelet/soft-serve/server/db"
-	"github.com/charmbracelet/soft-serve/server/jobs"
-	sshsrv "github.com/charmbracelet/soft-serve/server/ssh"
-	"github.com/charmbracelet/soft-serve/server/stats"
-	"github.com/charmbracelet/soft-serve/server/web"
+	"github.com/charmbracelet/soft-serve/pkg/backend"
+	"github.com/charmbracelet/soft-serve/pkg/config"
+	"github.com/charmbracelet/soft-serve/pkg/cron"
+	"github.com/charmbracelet/soft-serve/pkg/daemon"
+	"github.com/charmbracelet/soft-serve/pkg/db"
+	"github.com/charmbracelet/soft-serve/pkg/jobs"
+	sshsrv "github.com/charmbracelet/soft-serve/pkg/ssh"
+	"github.com/charmbracelet/soft-serve/pkg/stats"
+	"github.com/charmbracelet/soft-serve/pkg/web"
 	"github.com/charmbracelet/ssh"
 	"golang.org/x/sync/errgroup"
 )

server/backend/access_token.go → pkg/backend/access_token.go 🔗

@@ -5,8 +5,8 @@ import (
 	"errors"
 	"time"
 
-	"github.com/charmbracelet/soft-serve/server/db"
-	"github.com/charmbracelet/soft-serve/server/proto"
+	"github.com/charmbracelet/soft-serve/pkg/db"
+	"github.com/charmbracelet/soft-serve/pkg/proto"
 )
 
 // CreateAccessToken creates an access token for user.

server/backend/backend.go → pkg/backend/backend.go 🔗

@@ -4,10 +4,10 @@ import (
 	"context"
 
 	"github.com/charmbracelet/log"
-	"github.com/charmbracelet/soft-serve/server/config"
-	"github.com/charmbracelet/soft-serve/server/db"
-	"github.com/charmbracelet/soft-serve/server/store"
-	"github.com/charmbracelet/soft-serve/server/task"
+	"github.com/charmbracelet/soft-serve/pkg/config"
+	"github.com/charmbracelet/soft-serve/pkg/db"
+	"github.com/charmbracelet/soft-serve/pkg/store"
+	"github.com/charmbracelet/soft-serve/pkg/task"
 )
 
 // Backend is the Soft Serve backend that handles users, repositories, and

server/backend/collab.go → pkg/backend/collab.go 🔗

@@ -5,12 +5,12 @@ import (
 	"errors"
 	"strings"
 
-	"github.com/charmbracelet/soft-serve/server/access"
-	"github.com/charmbracelet/soft-serve/server/db"
-	"github.com/charmbracelet/soft-serve/server/db/models"
-	"github.com/charmbracelet/soft-serve/server/proto"
-	"github.com/charmbracelet/soft-serve/server/utils"
-	"github.com/charmbracelet/soft-serve/server/webhook"
+	"github.com/charmbracelet/soft-serve/pkg/access"
+	"github.com/charmbracelet/soft-serve/pkg/db"
+	"github.com/charmbracelet/soft-serve/pkg/db/models"
+	"github.com/charmbracelet/soft-serve/pkg/proto"
+	"github.com/charmbracelet/soft-serve/pkg/utils"
+	"github.com/charmbracelet/soft-serve/pkg/webhook"
 )
 
 // AddCollaborator adds a collaborator to a repository.

server/backend/hooks.go → pkg/backend/hooks.go 🔗

@@ -7,10 +7,10 @@ import (
 	"sync"
 
 	"github.com/charmbracelet/soft-serve/git"
-	"github.com/charmbracelet/soft-serve/server/hooks"
-	"github.com/charmbracelet/soft-serve/server/proto"
-	"github.com/charmbracelet/soft-serve/server/sshutils"
-	"github.com/charmbracelet/soft-serve/server/webhook"
+	"github.com/charmbracelet/soft-serve/pkg/hooks"
+	"github.com/charmbracelet/soft-serve/pkg/proto"
+	"github.com/charmbracelet/soft-serve/pkg/sshutils"
+	"github.com/charmbracelet/soft-serve/pkg/webhook"
 )
 
 var _ hooks.Hooks = (*Backend)(nil)

server/backend/lfs.go → pkg/backend/lfs.go 🔗

@@ -8,12 +8,12 @@ import (
 	"path/filepath"
 	"strconv"
 
-	"github.com/charmbracelet/soft-serve/server/config"
-	"github.com/charmbracelet/soft-serve/server/db"
-	"github.com/charmbracelet/soft-serve/server/lfs"
-	"github.com/charmbracelet/soft-serve/server/proto"
-	"github.com/charmbracelet/soft-serve/server/storage"
-	"github.com/charmbracelet/soft-serve/server/store"
+	"github.com/charmbracelet/soft-serve/pkg/config"
+	"github.com/charmbracelet/soft-serve/pkg/db"
+	"github.com/charmbracelet/soft-serve/pkg/lfs"
+	"github.com/charmbracelet/soft-serve/pkg/proto"
+	"github.com/charmbracelet/soft-serve/pkg/storage"
+	"github.com/charmbracelet/soft-serve/pkg/store"
 )
 
 // StoreRepoMissingLFSObjects stores missing LFS objects for a repository.

server/backend/repo.go → pkg/backend/repo.go 🔗

@@ -13,15 +13,15 @@ import (
 	"time"
 
 	"github.com/charmbracelet/soft-serve/git"
-	"github.com/charmbracelet/soft-serve/server/db"
-	"github.com/charmbracelet/soft-serve/server/db/models"
-	"github.com/charmbracelet/soft-serve/server/hooks"
-	"github.com/charmbracelet/soft-serve/server/lfs"
-	"github.com/charmbracelet/soft-serve/server/proto"
-	"github.com/charmbracelet/soft-serve/server/storage"
-	"github.com/charmbracelet/soft-serve/server/task"
-	"github.com/charmbracelet/soft-serve/server/utils"
-	"github.com/charmbracelet/soft-serve/server/webhook"
+	"github.com/charmbracelet/soft-serve/pkg/db"
+	"github.com/charmbracelet/soft-serve/pkg/db/models"
+	"github.com/charmbracelet/soft-serve/pkg/hooks"
+	"github.com/charmbracelet/soft-serve/pkg/lfs"
+	"github.com/charmbracelet/soft-serve/pkg/proto"
+	"github.com/charmbracelet/soft-serve/pkg/storage"
+	"github.com/charmbracelet/soft-serve/pkg/task"
+	"github.com/charmbracelet/soft-serve/pkg/utils"
+	"github.com/charmbracelet/soft-serve/pkg/webhook"
 )
 
 func (d *Backend) reposPath() string {

server/backend/settings.go → pkg/backend/settings.go 🔗

@@ -3,8 +3,8 @@ package backend
 import (
 	"context"
 
-	"github.com/charmbracelet/soft-serve/server/access"
-	"github.com/charmbracelet/soft-serve/server/db"
+	"github.com/charmbracelet/soft-serve/pkg/access"
+	"github.com/charmbracelet/soft-serve/pkg/db"
 )
 
 // AllowKeyless returns whether or not keyless access is allowed.

server/backend/user.go → pkg/backend/user.go 🔗

@@ -6,12 +6,12 @@ import (
 	"strings"
 	"time"
 
-	"github.com/charmbracelet/soft-serve/server/access"
-	"github.com/charmbracelet/soft-serve/server/db"
-	"github.com/charmbracelet/soft-serve/server/db/models"
-	"github.com/charmbracelet/soft-serve/server/proto"
-	"github.com/charmbracelet/soft-serve/server/sshutils"
-	"github.com/charmbracelet/soft-serve/server/utils"
+	"github.com/charmbracelet/soft-serve/pkg/access"
+	"github.com/charmbracelet/soft-serve/pkg/db"
+	"github.com/charmbracelet/soft-serve/pkg/db/models"
+	"github.com/charmbracelet/soft-serve/pkg/proto"
+	"github.com/charmbracelet/soft-serve/pkg/sshutils"
+	"github.com/charmbracelet/soft-serve/pkg/utils"
 	"golang.org/x/crypto/ssh"
 )
 

server/backend/utils.go → pkg/backend/utils.go 🔗

@@ -2,7 +2,7 @@ package backend
 
 import (
 	"github.com/charmbracelet/soft-serve/git"
-	"github.com/charmbracelet/soft-serve/server/proto"
+	"github.com/charmbracelet/soft-serve/pkg/proto"
 )
 
 // LatestFile returns the contents of the latest file at the specified path in

server/backend/webhooks.go → pkg/backend/webhooks.go 🔗

@@ -5,11 +5,11 @@ import (
 	"encoding/json"
 
 	"github.com/charmbracelet/log"
-	"github.com/charmbracelet/soft-serve/server/db"
-	"github.com/charmbracelet/soft-serve/server/db/models"
-	"github.com/charmbracelet/soft-serve/server/proto"
-	"github.com/charmbracelet/soft-serve/server/store"
-	"github.com/charmbracelet/soft-serve/server/webhook"
+	"github.com/charmbracelet/soft-serve/pkg/db"
+	"github.com/charmbracelet/soft-serve/pkg/db/models"
+	"github.com/charmbracelet/soft-serve/pkg/proto"
+	"github.com/charmbracelet/soft-serve/pkg/store"
+	"github.com/charmbracelet/soft-serve/pkg/webhook"
 	"github.com/google/uuid"
 )
 

server/config/config.go → pkg/config/config.go 🔗

@@ -9,7 +9,7 @@ import (
 	"time"
 
 	"github.com/caarlos0/env/v8"
-	"github.com/charmbracelet/soft-serve/server/sshutils"
+	"github.com/charmbracelet/soft-serve/pkg/sshutils"
 	"golang.org/x/crypto/ssh"
 	"gopkg.in/yaml.v3"
 )

server/daemon/daemon.go → pkg/daemon/daemon.go 🔗

@@ -11,11 +11,11 @@ import (
 	"time"
 
 	"github.com/charmbracelet/log"
-	"github.com/charmbracelet/soft-serve/server/access"
-	"github.com/charmbracelet/soft-serve/server/backend"
-	"github.com/charmbracelet/soft-serve/server/config"
-	"github.com/charmbracelet/soft-serve/server/git"
-	"github.com/charmbracelet/soft-serve/server/utils"
+	"github.com/charmbracelet/soft-serve/pkg/access"
+	"github.com/charmbracelet/soft-serve/pkg/backend"
+	"github.com/charmbracelet/soft-serve/pkg/config"
+	"github.com/charmbracelet/soft-serve/pkg/git"
+	"github.com/charmbracelet/soft-serve/pkg/utils"
 	"github.com/go-git/go-git/v5/plumbing/format/pktline"
 	"github.com/prometheus/client_golang/prometheus"
 	"github.com/prometheus/client_golang/prometheus/promauto"

server/daemon/daemon_test.go → pkg/daemon/daemon_test.go 🔗

@@ -12,14 +12,14 @@ import (
 	"strings"
 	"testing"
 
-	"github.com/charmbracelet/soft-serve/server/backend"
-	"github.com/charmbracelet/soft-serve/server/config"
-	"github.com/charmbracelet/soft-serve/server/db"
-	"github.com/charmbracelet/soft-serve/server/db/migrate"
-	"github.com/charmbracelet/soft-serve/server/git"
-	"github.com/charmbracelet/soft-serve/server/store"
-	"github.com/charmbracelet/soft-serve/server/store/database"
-	"github.com/charmbracelet/soft-serve/server/test"
+	"github.com/charmbracelet/soft-serve/pkg/backend"
+	"github.com/charmbracelet/soft-serve/pkg/config"
+	"github.com/charmbracelet/soft-serve/pkg/db"
+	"github.com/charmbracelet/soft-serve/pkg/db/migrate"
+	"github.com/charmbracelet/soft-serve/pkg/git"
+	"github.com/charmbracelet/soft-serve/pkg/store"
+	"github.com/charmbracelet/soft-serve/pkg/store/database"
+	"github.com/charmbracelet/soft-serve/pkg/test"
 	"github.com/go-git/go-git/v5/plumbing/format/pktline"
 	_ "modernc.org/sqlite" // sqlite driver
 )

server/db/db.go → pkg/db/db.go 🔗

@@ -7,7 +7,7 @@ import (
 	"fmt"
 
 	"github.com/charmbracelet/log"
-	"github.com/charmbracelet/soft-serve/server/config"
+	"github.com/charmbracelet/soft-serve/pkg/config"
 	"github.com/jmoiron/sqlx"
 	_ "github.com/lib/pq"  // postgres driver
 	_ "modernc.org/sqlite" // sqlite driver

server/db/migrate/0001_create_tables.go → pkg/db/migrate/0001_create_tables.go 🔗

@@ -6,10 +6,10 @@ import (
 	"fmt"
 	"strconv"
 
-	"github.com/charmbracelet/soft-serve/server/access"
-	"github.com/charmbracelet/soft-serve/server/config"
-	"github.com/charmbracelet/soft-serve/server/db"
-	"github.com/charmbracelet/soft-serve/server/sshutils"
+	"github.com/charmbracelet/soft-serve/pkg/access"
+	"github.com/charmbracelet/soft-serve/pkg/config"
+	"github.com/charmbracelet/soft-serve/pkg/db"
+	"github.com/charmbracelet/soft-serve/pkg/sshutils"
 )
 
 const (

server/db/migrate/0002_webhooks.go → pkg/db/migrate/0002_webhooks.go 🔗

@@ -3,7 +3,7 @@ package migrate
 import (
 	"context"
 
-	"github.com/charmbracelet/soft-serve/server/db"
+	"github.com/charmbracelet/soft-serve/pkg/db"
 )
 
 const (

server/db/migrate/migrate.go → pkg/db/migrate/migrate.go 🔗

@@ -7,7 +7,7 @@ import (
 	"fmt"
 
 	"github.com/charmbracelet/log"
-	"github.com/charmbracelet/soft-serve/server/db"
+	"github.com/charmbracelet/soft-serve/pkg/db"
 )
 
 // MigrateFunc is a function that executes a migration.

server/db/migrate/migrations.go → pkg/db/migrate/migrations.go 🔗

@@ -7,7 +7,7 @@ import (
 	"regexp"
 	"strings"
 
-	"github.com/charmbracelet/soft-serve/server/db"
+	"github.com/charmbracelet/soft-serve/pkg/db"
 )
 
 //go:embed *.sql

server/db/models/collab.go → pkg/db/models/collab.go 🔗

@@ -3,7 +3,7 @@ package models
 import (
 	"time"
 
-	"github.com/charmbracelet/soft-serve/server/access"
+	"github.com/charmbracelet/soft-serve/pkg/access"
 )
 
 // Collab represents a repository collaborator.

server/git/lfs.go → pkg/git/lfs.go 🔗

@@ -15,13 +15,13 @@ import (
 
 	"github.com/charmbracelet/git-lfs-transfer/transfer"
 	"github.com/charmbracelet/log"
-	"github.com/charmbracelet/soft-serve/server/config"
-	"github.com/charmbracelet/soft-serve/server/db"
-	"github.com/charmbracelet/soft-serve/server/db/models"
-	"github.com/charmbracelet/soft-serve/server/lfs"
-	"github.com/charmbracelet/soft-serve/server/proto"
-	"github.com/charmbracelet/soft-serve/server/storage"
-	"github.com/charmbracelet/soft-serve/server/store"
+	"github.com/charmbracelet/soft-serve/pkg/config"
+	"github.com/charmbracelet/soft-serve/pkg/db"
+	"github.com/charmbracelet/soft-serve/pkg/db/models"
+	"github.com/charmbracelet/soft-serve/pkg/lfs"
+	"github.com/charmbracelet/soft-serve/pkg/proto"
+	"github.com/charmbracelet/soft-serve/pkg/storage"
+	"github.com/charmbracelet/soft-serve/pkg/store"
 	"github.com/rubyist/tracerx"
 )
 

server/git/lfs_auth.go → pkg/git/lfs_auth.go 🔗

@@ -8,10 +8,10 @@ import (
 	"time"
 
 	"github.com/charmbracelet/log"
-	"github.com/charmbracelet/soft-serve/server/config"
-	"github.com/charmbracelet/soft-serve/server/jwk"
-	"github.com/charmbracelet/soft-serve/server/lfs"
-	"github.com/charmbracelet/soft-serve/server/proto"
+	"github.com/charmbracelet/soft-serve/pkg/config"
+	"github.com/charmbracelet/soft-serve/pkg/jwk"
+	"github.com/charmbracelet/soft-serve/pkg/lfs"
+	"github.com/charmbracelet/soft-serve/pkg/proto"
 	"github.com/golang-jwt/jwt/v5"
 )
 

server/hooks/gen.go → pkg/hooks/gen.go 🔗

@@ -9,8 +9,8 @@ import (
 	"text/template"
 
 	"github.com/charmbracelet/log"
-	"github.com/charmbracelet/soft-serve/server/config"
-	"github.com/charmbracelet/soft-serve/server/utils"
+	"github.com/charmbracelet/soft-serve/pkg/config"
+	"github.com/charmbracelet/soft-serve/pkg/utils"
 )
 
 // The names of git server-side hooks.

server/jobs/mirror.go → pkg/jobs/mirror.go 🔗

@@ -8,12 +8,12 @@ import (
 
 	"github.com/charmbracelet/log"
 	"github.com/charmbracelet/soft-serve/git"
-	"github.com/charmbracelet/soft-serve/server/backend"
-	"github.com/charmbracelet/soft-serve/server/config"
-	"github.com/charmbracelet/soft-serve/server/db"
-	"github.com/charmbracelet/soft-serve/server/lfs"
-	"github.com/charmbracelet/soft-serve/server/store"
-	"github.com/charmbracelet/soft-serve/server/sync"
+	"github.com/charmbracelet/soft-serve/pkg/backend"
+	"github.com/charmbracelet/soft-serve/pkg/config"
+	"github.com/charmbracelet/soft-serve/pkg/db"
+	"github.com/charmbracelet/soft-serve/pkg/lfs"
+	"github.com/charmbracelet/soft-serve/pkg/store"
+	"github.com/charmbracelet/soft-serve/pkg/sync"
 )
 
 func init() {

server/jwk/jwk.go → pkg/jwk/jwk.go 🔗

@@ -5,7 +5,7 @@ import (
 	"crypto/sha256"
 	"fmt"
 
-	"github.com/charmbracelet/soft-serve/server/config"
+	"github.com/charmbracelet/soft-serve/pkg/config"
 	"github.com/go-jose/go-jose/v3"
 	"github.com/golang-jwt/jwt/v5"
 )

server/log/log.go → pkg/log/log.go 🔗

@@ -6,7 +6,7 @@ import (
 	"time"
 
 	"github.com/charmbracelet/log"
-	"github.com/charmbracelet/soft-serve/server/config"
+	"github.com/charmbracelet/soft-serve/pkg/config"
 )
 
 // NewLogger returns a new logger with default settings.

server/ssh/cmd/blob.go → pkg/ssh/cmd/blob.go 🔗

@@ -4,9 +4,9 @@ import (
 	"fmt"
 
 	"github.com/charmbracelet/soft-serve/git"
-	"github.com/charmbracelet/soft-serve/server/backend"
-	"github.com/charmbracelet/soft-serve/server/ui/common"
-	"github.com/charmbracelet/soft-serve/server/ui/styles"
+	"github.com/charmbracelet/soft-serve/pkg/backend"
+	"github.com/charmbracelet/soft-serve/pkg/ui/common"
+	"github.com/charmbracelet/soft-serve/pkg/ui/styles"
 	"github.com/spf13/cobra"
 )
 

server/ssh/cmd/branch.go → pkg/ssh/cmd/branch.go 🔗

@@ -5,9 +5,9 @@ import (
 	"strings"
 
 	"github.com/charmbracelet/soft-serve/git"
-	"github.com/charmbracelet/soft-serve/server/backend"
-	"github.com/charmbracelet/soft-serve/server/proto"
-	"github.com/charmbracelet/soft-serve/server/webhook"
+	"github.com/charmbracelet/soft-serve/pkg/backend"
+	"github.com/charmbracelet/soft-serve/pkg/proto"
+	"github.com/charmbracelet/soft-serve/pkg/webhook"
 	gitm "github.com/gogs/git-module"
 	"github.com/spf13/cobra"
 )

server/ssh/cmd/cmd.go → pkg/ssh/cmd/cmd.go 🔗

@@ -7,12 +7,12 @@ import (
 	"text/template"
 	"unicode"
 
-	"github.com/charmbracelet/soft-serve/server/access"
-	"github.com/charmbracelet/soft-serve/server/backend"
-	"github.com/charmbracelet/soft-serve/server/config"
-	"github.com/charmbracelet/soft-serve/server/proto"
-	"github.com/charmbracelet/soft-serve/server/sshutils"
-	"github.com/charmbracelet/soft-serve/server/utils"
+	"github.com/charmbracelet/soft-serve/pkg/access"
+	"github.com/charmbracelet/soft-serve/pkg/backend"
+	"github.com/charmbracelet/soft-serve/pkg/config"
+	"github.com/charmbracelet/soft-serve/pkg/proto"
+	"github.com/charmbracelet/soft-serve/pkg/sshutils"
+	"github.com/charmbracelet/soft-serve/pkg/utils"
 	"github.com/charmbracelet/ssh"
 	"github.com/spf13/cobra"
 )

server/ssh/cmd/collab.go → pkg/ssh/cmd/collab.go 🔗

@@ -1,8 +1,8 @@
 package cmd
 
 import (
-	"github.com/charmbracelet/soft-serve/server/access"
-	"github.com/charmbracelet/soft-serve/server/backend"
+	"github.com/charmbracelet/soft-serve/pkg/access"
+	"github.com/charmbracelet/soft-serve/pkg/backend"
 	"github.com/spf13/cobra"
 )
 

server/ssh/cmd/commit.go → pkg/ssh/cmd/commit.go 🔗

@@ -7,9 +7,9 @@ import (
 
 	gansi "github.com/charmbracelet/glamour/ansi"
 	"github.com/charmbracelet/soft-serve/git"
-	"github.com/charmbracelet/soft-serve/server/backend"
-	"github.com/charmbracelet/soft-serve/server/ui/common"
-	"github.com/charmbracelet/soft-serve/server/ui/styles"
+	"github.com/charmbracelet/soft-serve/pkg/backend"
+	"github.com/charmbracelet/soft-serve/pkg/ui/common"
+	"github.com/charmbracelet/soft-serve/pkg/ui/styles"
 	"github.com/muesli/termenv"
 	"github.com/spf13/cobra"
 )

server/ssh/cmd/create.go → pkg/ssh/cmd/create.go 🔗

@@ -3,9 +3,9 @@ package cmd
 import (
 	"fmt"
 
-	"github.com/charmbracelet/soft-serve/server/backend"
-	"github.com/charmbracelet/soft-serve/server/config"
-	"github.com/charmbracelet/soft-serve/server/proto"
+	"github.com/charmbracelet/soft-serve/pkg/backend"
+	"github.com/charmbracelet/soft-serve/pkg/config"
+	"github.com/charmbracelet/soft-serve/pkg/proto"
 	"github.com/spf13/cobra"
 )
 

server/ssh/cmd/delete.go → pkg/ssh/cmd/delete.go 🔗

@@ -1,7 +1,7 @@
 package cmd
 
 import (
-	"github.com/charmbracelet/soft-serve/server/backend"
+	"github.com/charmbracelet/soft-serve/pkg/backend"
 	"github.com/spf13/cobra"
 )
 

server/ssh/cmd/description.go → pkg/ssh/cmd/description.go 🔗

@@ -3,7 +3,7 @@ package cmd
 import (
 	"strings"
 
-	"github.com/charmbracelet/soft-serve/server/backend"
+	"github.com/charmbracelet/soft-serve/pkg/backend"
 	"github.com/spf13/cobra"
 )
 

server/ssh/cmd/git.go → pkg/ssh/cmd/git.go 🔗

@@ -6,14 +6,14 @@ import (
 	"time"
 
 	"github.com/charmbracelet/log"
-	"github.com/charmbracelet/soft-serve/server/access"
-	"github.com/charmbracelet/soft-serve/server/backend"
-	"github.com/charmbracelet/soft-serve/server/config"
-	"github.com/charmbracelet/soft-serve/server/git"
-	"github.com/charmbracelet/soft-serve/server/lfs"
-	"github.com/charmbracelet/soft-serve/server/proto"
-	"github.com/charmbracelet/soft-serve/server/sshutils"
-	"github.com/charmbracelet/soft-serve/server/utils"
+	"github.com/charmbracelet/soft-serve/pkg/access"
+	"github.com/charmbracelet/soft-serve/pkg/backend"
+	"github.com/charmbracelet/soft-serve/pkg/config"
+	"github.com/charmbracelet/soft-serve/pkg/git"
+	"github.com/charmbracelet/soft-serve/pkg/lfs"
+	"github.com/charmbracelet/soft-serve/pkg/proto"
+	"github.com/charmbracelet/soft-serve/pkg/sshutils"
+	"github.com/charmbracelet/soft-serve/pkg/utils"
 	"github.com/prometheus/client_golang/prometheus"
 	"github.com/prometheus/client_golang/prometheus/promauto"
 	"github.com/spf13/cobra"

server/ssh/cmd/hidden.go → pkg/ssh/cmd/hidden.go 🔗

@@ -1,7 +1,7 @@
 package cmd
 
 import (
-	"github.com/charmbracelet/soft-serve/server/backend"
+	"github.com/charmbracelet/soft-serve/pkg/backend"
 	"github.com/spf13/cobra"
 )
 

server/ssh/cmd/import.go → pkg/ssh/cmd/import.go 🔗

@@ -3,9 +3,9 @@ package cmd
 import (
 	"errors"
 
-	"github.com/charmbracelet/soft-serve/server/backend"
-	"github.com/charmbracelet/soft-serve/server/proto"
-	"github.com/charmbracelet/soft-serve/server/task"
+	"github.com/charmbracelet/soft-serve/pkg/backend"
+	"github.com/charmbracelet/soft-serve/pkg/proto"
+	"github.com/charmbracelet/soft-serve/pkg/task"
 	"github.com/spf13/cobra"
 )
 

server/ssh/cmd/info.go → pkg/ssh/cmd/info.go 🔗

@@ -1,8 +1,8 @@
 package cmd
 
 import (
-	"github.com/charmbracelet/soft-serve/server/backend"
-	"github.com/charmbracelet/soft-serve/server/sshutils"
+	"github.com/charmbracelet/soft-serve/pkg/backend"
+	"github.com/charmbracelet/soft-serve/pkg/sshutils"
 	"github.com/spf13/cobra"
 )
 

server/ssh/cmd/jwt.go → pkg/ssh/cmd/jwt.go 🔗

@@ -4,9 +4,9 @@ import (
 	"fmt"
 	"time"
 
-	"github.com/charmbracelet/soft-serve/server/config"
-	"github.com/charmbracelet/soft-serve/server/jwk"
-	"github.com/charmbracelet/soft-serve/server/proto"
+	"github.com/charmbracelet/soft-serve/pkg/config"
+	"github.com/charmbracelet/soft-serve/pkg/jwk"
+	"github.com/charmbracelet/soft-serve/pkg/proto"
 	"github.com/golang-jwt/jwt/v5"
 	"github.com/spf13/cobra"
 )

server/ssh/cmd/list.go → pkg/ssh/cmd/list.go 🔗

@@ -1,9 +1,9 @@
 package cmd
 
 import (
-	"github.com/charmbracelet/soft-serve/server/access"
-	"github.com/charmbracelet/soft-serve/server/backend"
-	"github.com/charmbracelet/soft-serve/server/sshutils"
+	"github.com/charmbracelet/soft-serve/pkg/access"
+	"github.com/charmbracelet/soft-serve/pkg/backend"
+	"github.com/charmbracelet/soft-serve/pkg/sshutils"
 	"github.com/spf13/cobra"
 )
 

server/ssh/cmd/mirror.go → pkg/ssh/cmd/mirror.go 🔗

@@ -1,7 +1,7 @@
 package cmd
 
 import (
-	"github.com/charmbracelet/soft-serve/server/backend"
+	"github.com/charmbracelet/soft-serve/pkg/backend"
 	"github.com/spf13/cobra"
 )
 

server/ssh/cmd/private.go → pkg/ssh/cmd/private.go 🔗

@@ -4,7 +4,7 @@ import (
 	"strconv"
 	"strings"
 
-	"github.com/charmbracelet/soft-serve/server/backend"
+	"github.com/charmbracelet/soft-serve/pkg/backend"
 	"github.com/spf13/cobra"
 )
 

server/ssh/cmd/project_name.go → pkg/ssh/cmd/project_name.go 🔗

@@ -3,7 +3,7 @@ package cmd
 import (
 	"strings"
 
-	"github.com/charmbracelet/soft-serve/server/backend"
+	"github.com/charmbracelet/soft-serve/pkg/backend"
 	"github.com/spf13/cobra"
 )
 

server/ssh/cmd/pubkey.go → pkg/ssh/cmd/pubkey.go 🔗

@@ -3,8 +3,8 @@ package cmd
 import (
 	"strings"
 
-	"github.com/charmbracelet/soft-serve/server/backend"
-	"github.com/charmbracelet/soft-serve/server/sshutils"
+	"github.com/charmbracelet/soft-serve/pkg/backend"
+	"github.com/charmbracelet/soft-serve/pkg/sshutils"
 	"github.com/spf13/cobra"
 )
 

server/ssh/cmd/rename.go → pkg/ssh/cmd/rename.go 🔗

@@ -1,7 +1,7 @@
 package cmd
 
 import (
-	"github.com/charmbracelet/soft-serve/server/backend"
+	"github.com/charmbracelet/soft-serve/pkg/backend"
 	"github.com/spf13/cobra"
 )
 

server/ssh/cmd/repo.go → pkg/ssh/cmd/repo.go 🔗

@@ -4,8 +4,8 @@ import (
 	"fmt"
 	"strings"
 
-	"github.com/charmbracelet/soft-serve/server/backend"
-	"github.com/charmbracelet/soft-serve/server/proto"
+	"github.com/charmbracelet/soft-serve/pkg/backend"
+	"github.com/charmbracelet/soft-serve/pkg/proto"
 	"github.com/spf13/cobra"
 )
 

server/ssh/cmd/set_username.go → pkg/ssh/cmd/set_username.go 🔗

@@ -1,8 +1,8 @@
 package cmd
 
 import (
-	"github.com/charmbracelet/soft-serve/server/backend"
-	"github.com/charmbracelet/soft-serve/server/sshutils"
+	"github.com/charmbracelet/soft-serve/pkg/backend"
+	"github.com/charmbracelet/soft-serve/pkg/sshutils"
 	"github.com/spf13/cobra"
 )
 

server/ssh/cmd/settings.go → pkg/ssh/cmd/settings.go 🔗

@@ -4,8 +4,8 @@ import (
 	"fmt"
 	"strconv"
 
-	"github.com/charmbracelet/soft-serve/server/access"
-	"github.com/charmbracelet/soft-serve/server/backend"
+	"github.com/charmbracelet/soft-serve/pkg/access"
+	"github.com/charmbracelet/soft-serve/pkg/backend"
 	"github.com/spf13/cobra"
 )
 

server/ssh/cmd/tag.go → pkg/ssh/cmd/tag.go 🔗

@@ -5,9 +5,9 @@ import (
 
 	"github.com/charmbracelet/log"
 	"github.com/charmbracelet/soft-serve/git"
-	"github.com/charmbracelet/soft-serve/server/backend"
-	"github.com/charmbracelet/soft-serve/server/proto"
-	"github.com/charmbracelet/soft-serve/server/webhook"
+	"github.com/charmbracelet/soft-serve/pkg/backend"
+	"github.com/charmbracelet/soft-serve/pkg/proto"
+	"github.com/charmbracelet/soft-serve/pkg/webhook"
 	"github.com/spf13/cobra"
 )
 

server/ssh/cmd/token.go → pkg/ssh/cmd/token.go 🔗

@@ -7,8 +7,8 @@ import (
 
 	"github.com/caarlos0/duration"
 	"github.com/caarlos0/tablewriter"
-	"github.com/charmbracelet/soft-serve/server/backend"
-	"github.com/charmbracelet/soft-serve/server/proto"
+	"github.com/charmbracelet/soft-serve/pkg/backend"
+	"github.com/charmbracelet/soft-serve/pkg/proto"
 	"github.com/dustin/go-humanize"
 	"github.com/spf13/cobra"
 )

server/ssh/cmd/tree.go → pkg/ssh/cmd/tree.go 🔗

@@ -4,8 +4,8 @@ import (
 	"fmt"
 
 	"github.com/charmbracelet/soft-serve/git"
-	"github.com/charmbracelet/soft-serve/server/backend"
-	"github.com/charmbracelet/soft-serve/server/proto"
+	"github.com/charmbracelet/soft-serve/pkg/backend"
+	"github.com/charmbracelet/soft-serve/pkg/proto"
 	"github.com/dustin/go-humanize"
 	"github.com/spf13/cobra"
 )

server/ssh/cmd/user.go → pkg/ssh/cmd/user.go 🔗

@@ -4,9 +4,9 @@ import (
 	"sort"
 	"strings"
 
-	"github.com/charmbracelet/soft-serve/server/backend"
-	"github.com/charmbracelet/soft-serve/server/proto"
-	"github.com/charmbracelet/soft-serve/server/sshutils"
+	"github.com/charmbracelet/soft-serve/pkg/backend"
+	"github.com/charmbracelet/soft-serve/pkg/proto"
+	"github.com/charmbracelet/soft-serve/pkg/sshutils"
 	"github.com/spf13/cobra"
 	"golang.org/x/crypto/ssh"
 )

server/ssh/cmd/webhooks.go → pkg/ssh/cmd/webhooks.go 🔗

@@ -6,8 +6,8 @@ import (
 	"strings"
 
 	"github.com/caarlos0/tablewriter"
-	"github.com/charmbracelet/soft-serve/server/backend"
-	"github.com/charmbracelet/soft-serve/server/webhook"
+	"github.com/charmbracelet/soft-serve/pkg/backend"
+	"github.com/charmbracelet/soft-serve/pkg/webhook"
 	"github.com/dustin/go-humanize"
 	"github.com/google/uuid"
 	"github.com/spf13/cobra"

server/ssh/middleware.go → pkg/ssh/middleware.go 🔗

@@ -5,13 +5,13 @@ import (
 	"time"
 
 	"github.com/charmbracelet/log"
-	"github.com/charmbracelet/soft-serve/server/backend"
-	"github.com/charmbracelet/soft-serve/server/config"
-	"github.com/charmbracelet/soft-serve/server/db"
-	"github.com/charmbracelet/soft-serve/server/proto"
-	"github.com/charmbracelet/soft-serve/server/ssh/cmd"
-	"github.com/charmbracelet/soft-serve/server/sshutils"
-	"github.com/charmbracelet/soft-serve/server/store"
+	"github.com/charmbracelet/soft-serve/pkg/backend"
+	"github.com/charmbracelet/soft-serve/pkg/config"
+	"github.com/charmbracelet/soft-serve/pkg/db"
+	"github.com/charmbracelet/soft-serve/pkg/proto"
+	"github.com/charmbracelet/soft-serve/pkg/ssh/cmd"
+	"github.com/charmbracelet/soft-serve/pkg/sshutils"
+	"github.com/charmbracelet/soft-serve/pkg/store"
 	"github.com/charmbracelet/ssh"
 	"github.com/charmbracelet/wish"
 	"github.com/prometheus/client_golang/prometheus"

server/ssh/session.go → pkg/ssh/session.go 🔗

@@ -5,11 +5,11 @@ import (
 	"time"
 
 	tea "github.com/charmbracelet/bubbletea"
-	"github.com/charmbracelet/soft-serve/server/access"
-	"github.com/charmbracelet/soft-serve/server/backend"
-	"github.com/charmbracelet/soft-serve/server/config"
-	"github.com/charmbracelet/soft-serve/server/proto"
-	"github.com/charmbracelet/soft-serve/server/ui/common"
+	"github.com/charmbracelet/soft-serve/pkg/access"
+	"github.com/charmbracelet/soft-serve/pkg/backend"
+	"github.com/charmbracelet/soft-serve/pkg/config"
+	"github.com/charmbracelet/soft-serve/pkg/proto"
+	"github.com/charmbracelet/soft-serve/pkg/ui/common"
 	"github.com/charmbracelet/ssh"
 	"github.com/charmbracelet/wish"
 	"github.com/muesli/termenv"

server/ssh/session_test.go → pkg/ssh/session_test.go 🔗

@@ -9,13 +9,13 @@ import (
 	"time"
 
 	"github.com/charmbracelet/log"
-	"github.com/charmbracelet/soft-serve/server/backend"
-	"github.com/charmbracelet/soft-serve/server/config"
-	"github.com/charmbracelet/soft-serve/server/db"
-	"github.com/charmbracelet/soft-serve/server/db/migrate"
-	"github.com/charmbracelet/soft-serve/server/store"
-	"github.com/charmbracelet/soft-serve/server/store/database"
-	"github.com/charmbracelet/soft-serve/server/test"
+	"github.com/charmbracelet/soft-serve/pkg/backend"
+	"github.com/charmbracelet/soft-serve/pkg/config"
+	"github.com/charmbracelet/soft-serve/pkg/db"
+	"github.com/charmbracelet/soft-serve/pkg/db/migrate"
+	"github.com/charmbracelet/soft-serve/pkg/store"
+	"github.com/charmbracelet/soft-serve/pkg/store/database"
+	"github.com/charmbracelet/soft-serve/pkg/test"
 	"github.com/charmbracelet/ssh"
 	bm "github.com/charmbracelet/wish/bubbletea"
 	"github.com/charmbracelet/wish/testsession"

server/ssh/ssh.go → pkg/ssh/ssh.go 🔗

@@ -10,11 +10,11 @@ import (
 
 	"github.com/charmbracelet/keygen"
 	"github.com/charmbracelet/log"
-	"github.com/charmbracelet/soft-serve/server/backend"
-	"github.com/charmbracelet/soft-serve/server/config"
-	"github.com/charmbracelet/soft-serve/server/db"
-	"github.com/charmbracelet/soft-serve/server/proto"
-	"github.com/charmbracelet/soft-serve/server/store"
+	"github.com/charmbracelet/soft-serve/pkg/backend"
+	"github.com/charmbracelet/soft-serve/pkg/config"
+	"github.com/charmbracelet/soft-serve/pkg/db"
+	"github.com/charmbracelet/soft-serve/pkg/proto"
+	"github.com/charmbracelet/soft-serve/pkg/store"
 	"github.com/charmbracelet/ssh"
 	"github.com/charmbracelet/wish"
 	bm "github.com/charmbracelet/wish/bubbletea"

server/ssh/ui.go → pkg/ssh/ui.go 🔗

@@ -8,13 +8,13 @@ import (
 	tea "github.com/charmbracelet/bubbletea"
 	"github.com/charmbracelet/lipgloss"
 	"github.com/charmbracelet/soft-serve/git"
-	"github.com/charmbracelet/soft-serve/server/proto"
-	"github.com/charmbracelet/soft-serve/server/ui/common"
-	"github.com/charmbracelet/soft-serve/server/ui/components/footer"
-	"github.com/charmbracelet/soft-serve/server/ui/components/header"
-	"github.com/charmbracelet/soft-serve/server/ui/components/selector"
-	"github.com/charmbracelet/soft-serve/server/ui/pages/repo"
-	"github.com/charmbracelet/soft-serve/server/ui/pages/selection"
+	"github.com/charmbracelet/soft-serve/pkg/proto"
+	"github.com/charmbracelet/soft-serve/pkg/ui/common"
+	"github.com/charmbracelet/soft-serve/pkg/ui/components/footer"
+	"github.com/charmbracelet/soft-serve/pkg/ui/components/header"
+	"github.com/charmbracelet/soft-serve/pkg/ui/components/selector"
+	"github.com/charmbracelet/soft-serve/pkg/ui/pages/repo"
+	"github.com/charmbracelet/soft-serve/pkg/ui/pages/selection"
 )
 
 type page int

server/stats/stats.go → pkg/stats/stats.go 🔗

@@ -5,7 +5,7 @@ import (
 	"net/http"
 	"time"
 
-	"github.com/charmbracelet/soft-serve/server/config"
+	"github.com/charmbracelet/soft-serve/pkg/config"
 	"github.com/prometheus/client_golang/prometheus/promhttp"
 )
 

server/store/access_token.go → pkg/store/access_token.go 🔗

@@ -4,8 +4,8 @@ import (
 	"context"
 	"time"
 
-	"github.com/charmbracelet/soft-serve/server/db"
-	"github.com/charmbracelet/soft-serve/server/db/models"
+	"github.com/charmbracelet/soft-serve/pkg/db"
+	"github.com/charmbracelet/soft-serve/pkg/db/models"
 )
 
 // AccessTokenStore is an interface for managing access tokens.

server/store/collab.go → pkg/store/collab.go 🔗

@@ -3,9 +3,9 @@ package store
 import (
 	"context"
 
-	"github.com/charmbracelet/soft-serve/server/access"
-	"github.com/charmbracelet/soft-serve/server/db"
-	"github.com/charmbracelet/soft-serve/server/db/models"
+	"github.com/charmbracelet/soft-serve/pkg/access"
+	"github.com/charmbracelet/soft-serve/pkg/db"
+	"github.com/charmbracelet/soft-serve/pkg/db/models"
 )
 
 // CollaboratorStore is an interface for managing collaborators.

server/store/database/access_token.go → pkg/store/database/access_token.go 🔗

@@ -4,9 +4,9 @@ import (
 	"context"
 	"time"
 
-	"github.com/charmbracelet/soft-serve/server/db"
-	"github.com/charmbracelet/soft-serve/server/db/models"
-	"github.com/charmbracelet/soft-serve/server/store"
+	"github.com/charmbracelet/soft-serve/pkg/db"
+	"github.com/charmbracelet/soft-serve/pkg/db/models"
+	"github.com/charmbracelet/soft-serve/pkg/store"
 )
 
 type accessTokenStore struct{}

server/store/database/collab.go → pkg/store/database/collab.go 🔗

@@ -4,11 +4,11 @@ import (
 	"context"
 	"strings"
 
-	"github.com/charmbracelet/soft-serve/server/access"
-	"github.com/charmbracelet/soft-serve/server/db"
-	"github.com/charmbracelet/soft-serve/server/db/models"
-	"github.com/charmbracelet/soft-serve/server/store"
-	"github.com/charmbracelet/soft-serve/server/utils"
+	"github.com/charmbracelet/soft-serve/pkg/access"
+	"github.com/charmbracelet/soft-serve/pkg/db"
+	"github.com/charmbracelet/soft-serve/pkg/db/models"
+	"github.com/charmbracelet/soft-serve/pkg/store"
+	"github.com/charmbracelet/soft-serve/pkg/utils"
 )
 
 type collabStore struct{}

server/store/database/database.go → pkg/store/database/database.go 🔗

@@ -4,9 +4,9 @@ import (
 	"context"
 
 	"github.com/charmbracelet/log"
-	"github.com/charmbracelet/soft-serve/server/config"
-	"github.com/charmbracelet/soft-serve/server/db"
-	"github.com/charmbracelet/soft-serve/server/store"
+	"github.com/charmbracelet/soft-serve/pkg/config"
+	"github.com/charmbracelet/soft-serve/pkg/db"
+	"github.com/charmbracelet/soft-serve/pkg/store"
 )
 
 type datastore struct {

server/store/database/lfs.go → pkg/store/database/lfs.go 🔗

@@ -4,9 +4,9 @@ import (
 	"context"
 	"strings"
 
-	"github.com/charmbracelet/soft-serve/server/db"
-	"github.com/charmbracelet/soft-serve/server/db/models"
-	"github.com/charmbracelet/soft-serve/server/store"
+	"github.com/charmbracelet/soft-serve/pkg/db"
+	"github.com/charmbracelet/soft-serve/pkg/db/models"
+	"github.com/charmbracelet/soft-serve/pkg/store"
 )
 
 type lfsStore struct{}

server/store/database/repo.go → pkg/store/database/repo.go 🔗

@@ -3,10 +3,10 @@ package database
 import (
 	"context"
 
-	"github.com/charmbracelet/soft-serve/server/db"
-	"github.com/charmbracelet/soft-serve/server/db/models"
-	"github.com/charmbracelet/soft-serve/server/store"
-	"github.com/charmbracelet/soft-serve/server/utils"
+	"github.com/charmbracelet/soft-serve/pkg/db"
+	"github.com/charmbracelet/soft-serve/pkg/db/models"
+	"github.com/charmbracelet/soft-serve/pkg/store"
+	"github.com/charmbracelet/soft-serve/pkg/utils"
 )
 
 type repoStore struct{}

server/store/database/settings.go → pkg/store/database/settings.go 🔗

@@ -3,9 +3,9 @@ package database
 import (
 	"context"
 
-	"github.com/charmbracelet/soft-serve/server/access"
-	"github.com/charmbracelet/soft-serve/server/db"
-	"github.com/charmbracelet/soft-serve/server/store"
+	"github.com/charmbracelet/soft-serve/pkg/access"
+	"github.com/charmbracelet/soft-serve/pkg/db"
+	"github.com/charmbracelet/soft-serve/pkg/store"
 )
 
 type settingsStore struct{}

server/store/database/user.go → pkg/store/database/user.go 🔗

@@ -4,11 +4,11 @@ import (
 	"context"
 	"strings"
 
-	"github.com/charmbracelet/soft-serve/server/db"
-	"github.com/charmbracelet/soft-serve/server/db/models"
-	"github.com/charmbracelet/soft-serve/server/sshutils"
-	"github.com/charmbracelet/soft-serve/server/store"
-	"github.com/charmbracelet/soft-serve/server/utils"
+	"github.com/charmbracelet/soft-serve/pkg/db"
+	"github.com/charmbracelet/soft-serve/pkg/db/models"
+	"github.com/charmbracelet/soft-serve/pkg/sshutils"
+	"github.com/charmbracelet/soft-serve/pkg/store"
+	"github.com/charmbracelet/soft-serve/pkg/utils"
 	"golang.org/x/crypto/ssh"
 )
 

server/store/database/webhooks.go → pkg/store/database/webhooks.go 🔗

@@ -3,9 +3,9 @@ package database
 import (
 	"context"
 
-	"github.com/charmbracelet/soft-serve/server/db"
-	"github.com/charmbracelet/soft-serve/server/db/models"
-	"github.com/charmbracelet/soft-serve/server/store"
+	"github.com/charmbracelet/soft-serve/pkg/db"
+	"github.com/charmbracelet/soft-serve/pkg/db/models"
+	"github.com/charmbracelet/soft-serve/pkg/store"
 	"github.com/google/uuid"
 	"github.com/jmoiron/sqlx"
 )

server/store/lfs.go → pkg/store/lfs.go 🔗

@@ -3,8 +3,8 @@ package store
 import (
 	"context"
 
-	"github.com/charmbracelet/soft-serve/server/db"
-	"github.com/charmbracelet/soft-serve/server/db/models"
+	"github.com/charmbracelet/soft-serve/pkg/db"
+	"github.com/charmbracelet/soft-serve/pkg/db/models"
 )
 
 // LFSStore is the interface for the LFS store.

server/store/repo.go → pkg/store/repo.go 🔗

@@ -3,8 +3,8 @@ package store
 import (
 	"context"
 
-	"github.com/charmbracelet/soft-serve/server/db"
-	"github.com/charmbracelet/soft-serve/server/db/models"
+	"github.com/charmbracelet/soft-serve/pkg/db"
+	"github.com/charmbracelet/soft-serve/pkg/db/models"
 )
 
 // RepositoryStore is an interface for managing repositories.

server/store/settings.go → pkg/store/settings.go 🔗

@@ -3,8 +3,8 @@ package store
 import (
 	"context"
 
-	"github.com/charmbracelet/soft-serve/server/access"
-	"github.com/charmbracelet/soft-serve/server/db"
+	"github.com/charmbracelet/soft-serve/pkg/access"
+	"github.com/charmbracelet/soft-serve/pkg/db"
 )
 
 // SettingStore is an interface for managing settings.

server/store/user.go → pkg/store/user.go 🔗

@@ -3,8 +3,8 @@ package store
 import (
 	"context"
 
-	"github.com/charmbracelet/soft-serve/server/db"
-	"github.com/charmbracelet/soft-serve/server/db/models"
+	"github.com/charmbracelet/soft-serve/pkg/db"
+	"github.com/charmbracelet/soft-serve/pkg/db/models"
 	"golang.org/x/crypto/ssh"
 )
 

server/store/webhooks.go → pkg/store/webhooks.go 🔗

@@ -3,8 +3,8 @@ package store
 import (
 	"context"
 
-	"github.com/charmbracelet/soft-serve/server/db"
-	"github.com/charmbracelet/soft-serve/server/db/models"
+	"github.com/charmbracelet/soft-serve/pkg/db"
+	"github.com/charmbracelet/soft-serve/pkg/db/models"
 	"github.com/google/uuid"
 )
 

server/ui/common/common.go → pkg/ui/common/common.go 🔗

@@ -5,10 +5,10 @@ import (
 
 	"github.com/charmbracelet/log"
 	"github.com/charmbracelet/soft-serve/git"
-	"github.com/charmbracelet/soft-serve/server/backend"
-	"github.com/charmbracelet/soft-serve/server/config"
-	"github.com/charmbracelet/soft-serve/server/ui/keymap"
-	"github.com/charmbracelet/soft-serve/server/ui/styles"
+	"github.com/charmbracelet/soft-serve/pkg/backend"
+	"github.com/charmbracelet/soft-serve/pkg/config"
+	"github.com/charmbracelet/soft-serve/pkg/ui/keymap"
+	"github.com/charmbracelet/soft-serve/pkg/ui/styles"
 	"github.com/charmbracelet/ssh"
 	zone "github.com/lrstanley/bubblezone"
 	"github.com/muesli/termenv"

server/ui/common/format.go → pkg/ui/common/format.go 🔗

@@ -6,7 +6,7 @@ import (
 
 	"github.com/alecthomas/chroma/lexers"
 	gansi "github.com/charmbracelet/glamour/ansi"
-	"github.com/charmbracelet/soft-serve/server/ui/styles"
+	"github.com/charmbracelet/soft-serve/pkg/ui/styles"
 	"github.com/muesli/termenv"
 )
 

server/ui/common/utils.go → pkg/ui/common/utils.go 🔗

@@ -4,7 +4,7 @@ import (
 	"fmt"
 	"net/url"
 
-	"github.com/charmbracelet/soft-serve/server/utils"
+	"github.com/charmbracelet/soft-serve/pkg/utils"
 	"github.com/muesli/reflow/truncate"
 )
 

server/ui/components/code/code.go → pkg/ui/components/code/code.go 🔗

@@ -10,8 +10,8 @@ import (
 	"github.com/charmbracelet/glamour"
 	gansi "github.com/charmbracelet/glamour/ansi"
 	"github.com/charmbracelet/lipgloss"
-	"github.com/charmbracelet/soft-serve/server/ui/common"
-	vp "github.com/charmbracelet/soft-serve/server/ui/components/viewport"
+	"github.com/charmbracelet/soft-serve/pkg/ui/common"
+	vp "github.com/charmbracelet/soft-serve/pkg/ui/components/viewport"
 	"github.com/muesli/termenv"
 )
 

server/ui/components/footer/footer.go → pkg/ui/components/footer/footer.go 🔗

@@ -5,7 +5,7 @@ import (
 	"github.com/charmbracelet/bubbles/key"
 	tea "github.com/charmbracelet/bubbletea"
 	"github.com/charmbracelet/lipgloss"
-	"github.com/charmbracelet/soft-serve/server/ui/common"
+	"github.com/charmbracelet/soft-serve/pkg/ui/common"
 )
 
 // ToggleFooterMsg is a message sent to show/hide the footer.

server/ui/components/header/header.go → pkg/ui/components/header/header.go 🔗

@@ -4,7 +4,7 @@ import (
 	"strings"
 
 	tea "github.com/charmbracelet/bubbletea"
-	"github.com/charmbracelet/soft-serve/server/ui/common"
+	"github.com/charmbracelet/soft-serve/pkg/ui/common"
 )
 
 // Header represents a header component.

server/ui/components/selector/selector.go → pkg/ui/components/selector/selector.go 🔗

@@ -6,7 +6,7 @@ import (
 	"github.com/charmbracelet/bubbles/key"
 	"github.com/charmbracelet/bubbles/list"
 	tea "github.com/charmbracelet/bubbletea"
-	"github.com/charmbracelet/soft-serve/server/ui/common"
+	"github.com/charmbracelet/soft-serve/pkg/ui/common"
 )
 
 // Selector is a list of items that can be selected.

server/ui/components/statusbar/statusbar.go → pkg/ui/components/statusbar/statusbar.go 🔗

@@ -3,7 +3,7 @@ package statusbar
 import (
 	tea "github.com/charmbracelet/bubbletea"
 	"github.com/charmbracelet/lipgloss"
-	"github.com/charmbracelet/soft-serve/server/ui/common"
+	"github.com/charmbracelet/soft-serve/pkg/ui/common"
 	"github.com/muesli/reflow/truncate"
 )
 

server/ui/components/tabs/tabs.go → pkg/ui/components/tabs/tabs.go 🔗

@@ -5,7 +5,7 @@ import (
 
 	tea "github.com/charmbracelet/bubbletea"
 	"github.com/charmbracelet/lipgloss"
-	"github.com/charmbracelet/soft-serve/server/ui/common"
+	"github.com/charmbracelet/soft-serve/pkg/ui/common"
 )
 
 // SelectTabMsg is a message that contains the index of the tab to select.

server/ui/components/viewport/viewport.go → pkg/ui/components/viewport/viewport.go 🔗

@@ -4,7 +4,7 @@ import (
 	"github.com/charmbracelet/bubbles/key"
 	"github.com/charmbracelet/bubbles/viewport"
 	tea "github.com/charmbracelet/bubbletea"
-	"github.com/charmbracelet/soft-serve/server/ui/common"
+	"github.com/charmbracelet/soft-serve/pkg/ui/common"
 )
 
 // Viewport represents a viewport component.

server/ui/pages/repo/empty.go → pkg/ui/pages/repo/empty.go 🔗

@@ -3,8 +3,8 @@ package repo
 import (
 	"fmt"
 
-	"github.com/charmbracelet/soft-serve/server/config"
-	"github.com/charmbracelet/soft-serve/server/ui/common"
+	"github.com/charmbracelet/soft-serve/pkg/config"
+	"github.com/charmbracelet/soft-serve/pkg/ui/common"
 )
 
 func defaultEmptyRepoMsg(cfg *config.Config, repo string) string {

server/ui/pages/repo/files.go → pkg/ui/pages/repo/files.go 🔗

@@ -11,10 +11,10 @@ import (
 	"github.com/charmbracelet/bubbles/spinner"
 	tea "github.com/charmbracelet/bubbletea"
 	"github.com/charmbracelet/soft-serve/git"
-	"github.com/charmbracelet/soft-serve/server/proto"
-	"github.com/charmbracelet/soft-serve/server/ui/common"
-	"github.com/charmbracelet/soft-serve/server/ui/components/code"
-	"github.com/charmbracelet/soft-serve/server/ui/components/selector"
+	"github.com/charmbracelet/soft-serve/pkg/proto"
+	"github.com/charmbracelet/soft-serve/pkg/ui/common"
+	"github.com/charmbracelet/soft-serve/pkg/ui/components/code"
+	"github.com/charmbracelet/soft-serve/pkg/ui/components/selector"
 	gitm "github.com/gogs/git-module"
 )
 

server/ui/pages/repo/filesitem.go → pkg/ui/pages/repo/filesitem.go 🔗

@@ -11,7 +11,7 @@ import (
 	tea "github.com/charmbracelet/bubbletea"
 	"github.com/charmbracelet/lipgloss"
 	"github.com/charmbracelet/soft-serve/git"
-	"github.com/charmbracelet/soft-serve/server/ui/common"
+	"github.com/charmbracelet/soft-serve/pkg/ui/common"
 	"github.com/dustin/go-humanize"
 )
 

server/ui/pages/repo/log.go → pkg/ui/pages/repo/log.go 🔗

@@ -11,12 +11,12 @@ import (
 	gansi "github.com/charmbracelet/glamour/ansi"
 	"github.com/charmbracelet/lipgloss"
 	"github.com/charmbracelet/soft-serve/git"
-	"github.com/charmbracelet/soft-serve/server/proto"
-	"github.com/charmbracelet/soft-serve/server/ui/common"
-	"github.com/charmbracelet/soft-serve/server/ui/components/footer"
-	"github.com/charmbracelet/soft-serve/server/ui/components/selector"
-	"github.com/charmbracelet/soft-serve/server/ui/components/viewport"
-	"github.com/charmbracelet/soft-serve/server/ui/styles"
+	"github.com/charmbracelet/soft-serve/pkg/proto"
+	"github.com/charmbracelet/soft-serve/pkg/ui/common"
+	"github.com/charmbracelet/soft-serve/pkg/ui/components/footer"
+	"github.com/charmbracelet/soft-serve/pkg/ui/components/selector"
+	"github.com/charmbracelet/soft-serve/pkg/ui/components/viewport"
+	"github.com/charmbracelet/soft-serve/pkg/ui/styles"
 	"github.com/muesli/reflow/wrap"
 	"github.com/muesli/termenv"
 )

server/ui/pages/repo/logitem.go → pkg/ui/pages/repo/logitem.go 🔗

@@ -11,7 +11,7 @@ import (
 	tea "github.com/charmbracelet/bubbletea"
 	"github.com/charmbracelet/lipgloss"
 	"github.com/charmbracelet/soft-serve/git"
-	"github.com/charmbracelet/soft-serve/server/ui/common"
+	"github.com/charmbracelet/soft-serve/pkg/ui/common"
 	"github.com/muesli/reflow/truncate"
 )
 

server/ui/pages/repo/readme.go → pkg/ui/pages/repo/readme.go 🔗

@@ -7,10 +7,10 @@ import (
 	"github.com/charmbracelet/bubbles/key"
 	"github.com/charmbracelet/bubbles/spinner"
 	tea "github.com/charmbracelet/bubbletea"
-	"github.com/charmbracelet/soft-serve/server/backend"
-	"github.com/charmbracelet/soft-serve/server/proto"
-	"github.com/charmbracelet/soft-serve/server/ui/common"
-	"github.com/charmbracelet/soft-serve/server/ui/components/code"
+	"github.com/charmbracelet/soft-serve/pkg/backend"
+	"github.com/charmbracelet/soft-serve/pkg/proto"
+	"github.com/charmbracelet/soft-serve/pkg/ui/common"
+	"github.com/charmbracelet/soft-serve/pkg/ui/components/code"
 )
 
 // ReadmeMsg is a message sent when the readme is loaded.

server/ui/pages/repo/refs.go → pkg/ui/pages/repo/refs.go 🔗

@@ -9,9 +9,9 @@ import (
 	"github.com/charmbracelet/bubbles/spinner"
 	tea "github.com/charmbracelet/bubbletea"
 	"github.com/charmbracelet/soft-serve/git"
-	"github.com/charmbracelet/soft-serve/server/proto"
-	"github.com/charmbracelet/soft-serve/server/ui/common"
-	"github.com/charmbracelet/soft-serve/server/ui/components/selector"
+	"github.com/charmbracelet/soft-serve/pkg/proto"
+	"github.com/charmbracelet/soft-serve/pkg/ui/common"
+	"github.com/charmbracelet/soft-serve/pkg/ui/components/selector"
 )
 
 // RefMsg is a message that contains a git.Reference.

server/ui/pages/repo/refsitem.go → pkg/ui/pages/repo/refsitem.go 🔗

@@ -11,7 +11,7 @@ import (
 	tea "github.com/charmbracelet/bubbletea"
 	"github.com/charmbracelet/lipgloss"
 	"github.com/charmbracelet/soft-serve/git"
-	"github.com/charmbracelet/soft-serve/server/ui/common"
+	"github.com/charmbracelet/soft-serve/pkg/ui/common"
 	"github.com/dustin/go-humanize"
 	"github.com/muesli/reflow/truncate"
 )

server/ui/pages/repo/repo.go → pkg/ui/pages/repo/repo.go 🔗

@@ -10,12 +10,12 @@ import (
 	tea "github.com/charmbracelet/bubbletea"
 	"github.com/charmbracelet/lipgloss"
 	"github.com/charmbracelet/soft-serve/git"
-	"github.com/charmbracelet/soft-serve/server/proto"
-	"github.com/charmbracelet/soft-serve/server/ui/common"
-	"github.com/charmbracelet/soft-serve/server/ui/components/footer"
-	"github.com/charmbracelet/soft-serve/server/ui/components/selector"
-	"github.com/charmbracelet/soft-serve/server/ui/components/statusbar"
-	"github.com/charmbracelet/soft-serve/server/ui/components/tabs"
+	"github.com/charmbracelet/soft-serve/pkg/proto"
+	"github.com/charmbracelet/soft-serve/pkg/ui/common"
+	"github.com/charmbracelet/soft-serve/pkg/ui/components/footer"
+	"github.com/charmbracelet/soft-serve/pkg/ui/components/selector"
+	"github.com/charmbracelet/soft-serve/pkg/ui/components/statusbar"
+	"github.com/charmbracelet/soft-serve/pkg/ui/components/tabs"
 )
 
 type state int

server/ui/pages/repo/stash.go → pkg/ui/pages/repo/stash.go 🔗

@@ -8,10 +8,10 @@ import (
 	tea "github.com/charmbracelet/bubbletea"
 	"github.com/charmbracelet/lipgloss"
 	"github.com/charmbracelet/soft-serve/git"
-	"github.com/charmbracelet/soft-serve/server/proto"
-	"github.com/charmbracelet/soft-serve/server/ui/common"
-	"github.com/charmbracelet/soft-serve/server/ui/components/code"
-	"github.com/charmbracelet/soft-serve/server/ui/components/selector"
+	"github.com/charmbracelet/soft-serve/pkg/proto"
+	"github.com/charmbracelet/soft-serve/pkg/ui/common"
+	"github.com/charmbracelet/soft-serve/pkg/ui/components/code"
+	"github.com/charmbracelet/soft-serve/pkg/ui/components/selector"
 	gitm "github.com/gogs/git-module"
 )
 

server/ui/pages/repo/stashitem.go → pkg/ui/pages/repo/stashitem.go 🔗

@@ -7,7 +7,7 @@ import (
 	"github.com/charmbracelet/bubbles/key"
 	"github.com/charmbracelet/bubbles/list"
 	tea "github.com/charmbracelet/bubbletea"
-	"github.com/charmbracelet/soft-serve/server/ui/common"
+	"github.com/charmbracelet/soft-serve/pkg/ui/common"
 	gitm "github.com/gogs/git-module"
 )
 

server/ui/pages/selection/item.go → pkg/ui/pages/selection/item.go 🔗

@@ -11,9 +11,9 @@ import (
 	"github.com/charmbracelet/bubbles/list"
 	tea "github.com/charmbracelet/bubbletea"
 	"github.com/charmbracelet/lipgloss"
-	"github.com/charmbracelet/soft-serve/server/config"
-	"github.com/charmbracelet/soft-serve/server/proto"
-	"github.com/charmbracelet/soft-serve/server/ui/common"
+	"github.com/charmbracelet/soft-serve/pkg/config"
+	"github.com/charmbracelet/soft-serve/pkg/proto"
+	"github.com/charmbracelet/soft-serve/pkg/ui/common"
 	"github.com/dustin/go-humanize"
 )
 

server/ui/pages/selection/selection.go → pkg/ui/pages/selection/selection.go 🔗

@@ -8,12 +8,12 @@ import (
 	"github.com/charmbracelet/bubbles/list"
 	tea "github.com/charmbracelet/bubbletea"
 	"github.com/charmbracelet/lipgloss"
-	"github.com/charmbracelet/soft-serve/server/access"
-	"github.com/charmbracelet/soft-serve/server/backend"
-	"github.com/charmbracelet/soft-serve/server/ui/common"
-	"github.com/charmbracelet/soft-serve/server/ui/components/code"
-	"github.com/charmbracelet/soft-serve/server/ui/components/selector"
-	"github.com/charmbracelet/soft-serve/server/ui/components/tabs"
+	"github.com/charmbracelet/soft-serve/pkg/access"
+	"github.com/charmbracelet/soft-serve/pkg/backend"
+	"github.com/charmbracelet/soft-serve/pkg/ui/common"
+	"github.com/charmbracelet/soft-serve/pkg/ui/components/code"
+	"github.com/charmbracelet/soft-serve/pkg/ui/components/selector"
+	"github.com/charmbracelet/soft-serve/pkg/ui/components/tabs"
 )
 
 const (

server/web/auth.go → pkg/web/auth.go 🔗

@@ -8,9 +8,9 @@ import (
 	"strings"
 
 	"github.com/charmbracelet/log"
-	"github.com/charmbracelet/soft-serve/server/backend"
-	"github.com/charmbracelet/soft-serve/server/config"
-	"github.com/charmbracelet/soft-serve/server/proto"
+	"github.com/charmbracelet/soft-serve/pkg/backend"
+	"github.com/charmbracelet/soft-serve/pkg/config"
+	"github.com/charmbracelet/soft-serve/pkg/proto"
 	"github.com/golang-jwt/jwt/v5"
 )
 

server/web/context.go → pkg/web/context.go 🔗

@@ -5,10 +5,10 @@ import (
 	"net/http"
 
 	"github.com/charmbracelet/log"
-	"github.com/charmbracelet/soft-serve/server/backend"
-	"github.com/charmbracelet/soft-serve/server/config"
-	"github.com/charmbracelet/soft-serve/server/db"
-	"github.com/charmbracelet/soft-serve/server/store"
+	"github.com/charmbracelet/soft-serve/pkg/backend"
+	"github.com/charmbracelet/soft-serve/pkg/config"
+	"github.com/charmbracelet/soft-serve/pkg/db"
+	"github.com/charmbracelet/soft-serve/pkg/store"
 )
 
 // NewContextHandler returns a new context middleware.

server/web/git.go → pkg/web/git.go 🔗

@@ -15,13 +15,13 @@ import (
 
 	"github.com/charmbracelet/log"
 	gitb "github.com/charmbracelet/soft-serve/git"
-	"github.com/charmbracelet/soft-serve/server/access"
-	"github.com/charmbracelet/soft-serve/server/backend"
-	"github.com/charmbracelet/soft-serve/server/config"
-	"github.com/charmbracelet/soft-serve/server/git"
-	"github.com/charmbracelet/soft-serve/server/lfs"
-	"github.com/charmbracelet/soft-serve/server/proto"
-	"github.com/charmbracelet/soft-serve/server/utils"
+	"github.com/charmbracelet/soft-serve/pkg/access"
+	"github.com/charmbracelet/soft-serve/pkg/backend"
+	"github.com/charmbracelet/soft-serve/pkg/config"
+	"github.com/charmbracelet/soft-serve/pkg/git"
+	"github.com/charmbracelet/soft-serve/pkg/lfs"
+	"github.com/charmbracelet/soft-serve/pkg/proto"
+	"github.com/charmbracelet/soft-serve/pkg/utils"
 	"github.com/gorilla/mux"
 	"github.com/prometheus/client_golang/prometheus"
 	"github.com/prometheus/client_golang/prometheus/promauto"

server/web/git_lfs.go → pkg/web/git_lfs.go 🔗

@@ -14,15 +14,15 @@ import (
 	"strings"
 
 	"github.com/charmbracelet/log"
-	"github.com/charmbracelet/soft-serve/server/access"
-	"github.com/charmbracelet/soft-serve/server/backend"
-	"github.com/charmbracelet/soft-serve/server/config"
-	"github.com/charmbracelet/soft-serve/server/db"
-	"github.com/charmbracelet/soft-serve/server/db/models"
-	"github.com/charmbracelet/soft-serve/server/lfs"
-	"github.com/charmbracelet/soft-serve/server/proto"
-	"github.com/charmbracelet/soft-serve/server/storage"
-	"github.com/charmbracelet/soft-serve/server/store"
+	"github.com/charmbracelet/soft-serve/pkg/access"
+	"github.com/charmbracelet/soft-serve/pkg/backend"
+	"github.com/charmbracelet/soft-serve/pkg/config"
+	"github.com/charmbracelet/soft-serve/pkg/db"
+	"github.com/charmbracelet/soft-serve/pkg/db/models"
+	"github.com/charmbracelet/soft-serve/pkg/lfs"
+	"github.com/charmbracelet/soft-serve/pkg/proto"
+	"github.com/charmbracelet/soft-serve/pkg/storage"
+	"github.com/charmbracelet/soft-serve/pkg/store"
 	"github.com/gorilla/mux"
 )
 

server/web/goget.go → pkg/web/goget.go 🔗

@@ -7,9 +7,9 @@ import (
 	"text/template"
 
 	"github.com/charmbracelet/log"
-	"github.com/charmbracelet/soft-serve/server/backend"
-	"github.com/charmbracelet/soft-serve/server/config"
-	"github.com/charmbracelet/soft-serve/server/utils"
+	"github.com/charmbracelet/soft-serve/pkg/backend"
+	"github.com/charmbracelet/soft-serve/pkg/config"
+	"github.com/charmbracelet/soft-serve/pkg/utils"
 	"github.com/gorilla/mux"
 	"github.com/prometheus/client_golang/prometheus"
 	"github.com/prometheus/client_golang/prometheus/promauto"

server/web/http.go → pkg/web/http.go 🔗

@@ -6,7 +6,7 @@ import (
 	"time"
 
 	"github.com/charmbracelet/log"
-	"github.com/charmbracelet/soft-serve/server/config"
+	"github.com/charmbracelet/soft-serve/pkg/config"
 )
 
 // HTTPServer is an http server.

server/webhook/branch_tag.go → pkg/webhook/branch_tag.go 🔗

@@ -5,10 +5,10 @@ import (
 	"fmt"
 
 	"github.com/charmbracelet/soft-serve/git"
-	"github.com/charmbracelet/soft-serve/server/config"
-	"github.com/charmbracelet/soft-serve/server/db"
-	"github.com/charmbracelet/soft-serve/server/proto"
-	"github.com/charmbracelet/soft-serve/server/store"
+	"github.com/charmbracelet/soft-serve/pkg/config"
+	"github.com/charmbracelet/soft-serve/pkg/db"
+	"github.com/charmbracelet/soft-serve/pkg/proto"
+	"github.com/charmbracelet/soft-serve/pkg/store"
 )
 
 // BranchTagEvent is a branch or tag event.

server/webhook/collaborator.go → pkg/webhook/collaborator.go 🔗

@@ -3,10 +3,10 @@ package webhook
 import (
 	"context"
 
-	"github.com/charmbracelet/soft-serve/server/access"
-	"github.com/charmbracelet/soft-serve/server/db"
-	"github.com/charmbracelet/soft-serve/server/proto"
-	"github.com/charmbracelet/soft-serve/server/store"
+	"github.com/charmbracelet/soft-serve/pkg/access"
+	"github.com/charmbracelet/soft-serve/pkg/db"
+	"github.com/charmbracelet/soft-serve/pkg/proto"
+	"github.com/charmbracelet/soft-serve/pkg/store"
 )
 
 // CollaboratorEvent is a collaborator event.

server/webhook/push.go → pkg/webhook/push.go 🔗

@@ -5,10 +5,10 @@ import (
 	"fmt"
 
 	"github.com/charmbracelet/soft-serve/git"
-	"github.com/charmbracelet/soft-serve/server/config"
-	"github.com/charmbracelet/soft-serve/server/db"
-	"github.com/charmbracelet/soft-serve/server/proto"
-	"github.com/charmbracelet/soft-serve/server/store"
+	"github.com/charmbracelet/soft-serve/pkg/config"
+	"github.com/charmbracelet/soft-serve/pkg/db"
+	"github.com/charmbracelet/soft-serve/pkg/proto"
+	"github.com/charmbracelet/soft-serve/pkg/store"
 	gitm "github.com/gogs/git-module"
 )
 

server/webhook/repository.go → pkg/webhook/repository.go 🔗

@@ -3,10 +3,10 @@ package webhook
 import (
 	"context"
 
-	"github.com/charmbracelet/soft-serve/server/config"
-	"github.com/charmbracelet/soft-serve/server/db"
-	"github.com/charmbracelet/soft-serve/server/proto"
-	"github.com/charmbracelet/soft-serve/server/store"
+	"github.com/charmbracelet/soft-serve/pkg/config"
+	"github.com/charmbracelet/soft-serve/pkg/db"
+	"github.com/charmbracelet/soft-serve/pkg/proto"
+	"github.com/charmbracelet/soft-serve/pkg/store"
 )
 
 // RepositoryEvent is a repository payload.

server/webhook/webhook.go → pkg/webhook/webhook.go 🔗

@@ -11,11 +11,11 @@ import (
 	"io"
 	"net/http"
 
-	"github.com/charmbracelet/soft-serve/server/db"
-	"github.com/charmbracelet/soft-serve/server/db/models"
-	"github.com/charmbracelet/soft-serve/server/store"
-	"github.com/charmbracelet/soft-serve/server/utils"
-	"github.com/charmbracelet/soft-serve/server/version"
+	"github.com/charmbracelet/soft-serve/pkg/db"
+	"github.com/charmbracelet/soft-serve/pkg/db/models"
+	"github.com/charmbracelet/soft-serve/pkg/store"
+	"github.com/charmbracelet/soft-serve/pkg/utils"
+	"github.com/charmbracelet/soft-serve/pkg/version"
 	"github.com/google/go-querystring/query"
 	"github.com/google/uuid"
 )

testscript/script_test.go 🔗

@@ -19,15 +19,15 @@ import (
 
 	"github.com/charmbracelet/keygen"
 	"github.com/charmbracelet/log"
-	"github.com/charmbracelet/soft-serve/server"
-	"github.com/charmbracelet/soft-serve/server/backend"
-	"github.com/charmbracelet/soft-serve/server/config"
-	"github.com/charmbracelet/soft-serve/server/db"
-	"github.com/charmbracelet/soft-serve/server/db/migrate"
-	logr "github.com/charmbracelet/soft-serve/server/log"
-	"github.com/charmbracelet/soft-serve/server/store"
-	"github.com/charmbracelet/soft-serve/server/store/database"
-	"github.com/charmbracelet/soft-serve/server/test"
+	"github.com/charmbracelet/soft-serve/cmd/soft/serve"
+	"github.com/charmbracelet/soft-serve/pkg/backend"
+	"github.com/charmbracelet/soft-serve/pkg/config"
+	"github.com/charmbracelet/soft-serve/pkg/db"
+	"github.com/charmbracelet/soft-serve/pkg/db/migrate"
+	logr "github.com/charmbracelet/soft-serve/pkg/log"
+	"github.com/charmbracelet/soft-serve/pkg/store"
+	"github.com/charmbracelet/soft-serve/pkg/store/database"
+	"github.com/charmbracelet/soft-serve/pkg/test"
 	"github.com/rogpeppe/go-internal/testscript"
 	"github.com/spf13/cobra"
 	"golang.org/x/crypto/ssh"
@@ -153,7 +153,7 @@ func TestScript(t *testing.T) {
 			ctx = backend.WithContext(ctx, be)
 
 			lock.Lock()
-			srv, err := server.NewServer(ctx)
+			srv, err := serve.NewServer(ctx)
 			if err != nil {
 				lock.Unlock()
 				return err