diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml
index 384e1d6fcdd1d88bd547d0215a76f13ada177bb3..e8a9a1cec75bb04c084c9ecb6acd004cfd63d99d 100644
--- a/.github/workflows/main.yml
+++ b/.github/workflows/main.yml
@@ -50,7 +50,7 @@ jobs:
         with:
           args: ./...
       - name: Ensure no files were modified as a result of the build
-        run: git update-index --refresh && git diff-index --quiet HEAD --
+        run: git update-index --refresh && git diff-index --quiet HEAD -- || git diff
   e2e:
     # The type of runner that the job will run on
     runs-on: ubuntu-latest
diff --git a/cmd/cli/app/format/wrap.go b/cmd/cli/app/format/wrap.go
index ba820ecc6645ae7e320aca826acb048d41c52d9e..4239388bb09bb2f0d27507f4889910e4c99755ef 100644
--- a/cmd/cli/app/format/wrap.go
+++ b/cmd/cli/app/format/wrap.go
@@ -6,6 +6,7 @@ import (
 	"log"
 
 	"github.com/spf13/cobra"
+	"github.com/spf13/viper"
 )
 
 type cobraCmd func(cmd *cobra.Command, args []string)
@@ -20,14 +21,24 @@ func WrapCmd(f formatCmd) cobraCmd {
 		}
 
 		// TODO: add flags to control output formatting (JSON, plaintext, etc.)
-		if s, ok := obj.(fmt.Stringer); ok {
-			fmt.Print(s.String())
-		} else {
-			b, err := json.Marshal(obj)
-			if err != nil {
-				log.Fatal(err)
+		format := viper.GetString("format")
+		switch format {
+		case "default":
+			if s, ok := obj.(fmt.Stringer); ok {
+				fmt.Print(s.String())
+			} else {
+				fmt.Println(toJson(s))
 			}
-			fmt.Println(string(b))
+		case "json":
+			fmt.Println(toJson(obj))
 		}
 	}
 }
+
+func toJson(i interface{}) string {
+	b, err := json.Marshal(i)
+	if err != nil {
+		log.Fatal(err)
+	}
+	return string(b)
+}
diff --git a/cmd/cli/app/root.go b/cmd/cli/app/root.go
index 2e495908dc22e7062337d8a12b019fa2486bcffa..682595e20a5096cb95501489fbc7eb086bbed704 100644
--- a/cmd/cli/app/root.go
+++ b/cmd/cli/app/root.go
@@ -55,6 +55,7 @@ func init() {
 	rootCmd.PersistentFlags().StringVar(&cfgFile, "config", "", "config file (default is $HOME/.rekor.yaml)")
 
 	rootCmd.PersistentFlags().Var(&urlFlag{url: "http://localhost:3000"}, "rekor_server", "Server address:port")
+	rootCmd.PersistentFlags().Var(&formatFlag{format: "default"}, "format", "Command output format")
 
 	// these are bound here and not in PreRun so that all child commands can use them
 	if err := viper.BindPFlags(rootCmd.PersistentFlags()); err != nil {
@@ -130,3 +131,28 @@ func (u *urlFlag) Set(s string) error {
 func (u *urlFlag) Type() string {
 	return "url"
 }
+
+type formatFlag struct {
+	format string
+}
+
+func (f *formatFlag) String() string {
+	return f.format
+}
+
+func (f *formatFlag) Set(s string) error {
+	choices := map[string]struct{}{"default": {}, "json": {}}
+	if s == "" {
+		f.format = "default"
+		return nil
+	}
+	if _, ok := choices[s]; ok {
+		f.format = s
+		return nil
+	}
+	return fmt.Errorf("invalid flag value: %s, valid values are [default, json]", s)
+}
+
+func (u *formatFlag) Type() string {
+	return "format"
+}