diff --git a/cmd/cli/app/log_info.go b/cmd/cli/app/log_info.go
index 3c3a30de40fbc81f39d83b2969aa6f5f488dd2ba..5b9c2e49254f3b40a9a5df04686f50e1e7c4118d 100644
--- a/cmd/cli/app/log_info.go
+++ b/cmd/cli/app/log_info.go
@@ -19,16 +19,22 @@ import (
 	"crypto"
 	"crypto/x509"
 	"encoding/base64"
+	"encoding/hex"
 	"encoding/pem"
 	"errors"
 	"fmt"
 
+	"github.com/projectrekor/rekor/cmd/cli/app/state"
+
 	"github.com/google/trillian"
 	tclient "github.com/google/trillian/client"
 	tcrypto "github.com/google/trillian/crypto"
+	"github.com/google/trillian/merkle"
 	"github.com/google/trillian/merkle/rfc6962"
 
 	"github.com/projectrekor/rekor/cmd/cli/app/format"
+	"github.com/projectrekor/rekor/pkg/generated/client/tlog"
+	"github.com/projectrekor/rekor/pkg/log"
 	"github.com/spf13/cobra"
 	"github.com/spf13/viper"
 )
@@ -104,9 +110,42 @@ var logInfoCmd = &cobra.Command{
 		}
 
 		verifier := tclient.NewLogVerifier(rfc6962.DefaultHasher, pub, crypto.SHA256)
-		if _, err := tcrypto.VerifySignedLogRoot(verifier.PubKey, verifier.SigHash, &sth); err != nil {
+		lr, err := tcrypto.VerifySignedLogRoot(verifier.PubKey, verifier.SigHash, &sth)
+		if err != nil {
 			return nil, err
 		}
+
+		oldState := state.Load()
+		if oldState != nil {
+			log.CliLogger.Infof("Found previous log state, proving consistency between %d and %d", oldState.TreeSize, lr.TreeSize)
+			params := tlog.NewGetLogProofParams()
+			firstSize := int64(oldState.TreeSize)
+			params.FirstSize = &firstSize
+			params.LastSize = int64(lr.TreeSize)
+			proof, err := rekorClient.Tlog.GetLogProof(params)
+			if err != nil {
+				return nil, err
+			}
+			hashes := [][]byte{}
+			for _, h := range proof.Payload.Hashes {
+				b, _ := hex.DecodeString(h)
+				hashes = append(hashes, b)
+			}
+			v := merkle.NewLogVerifier(rfc6962.DefaultHasher)
+			if err := v.VerifyConsistencyProof(firstSize, int64(lr.TreeSize), oldState.RootHash,
+				lr.RootHash, hashes); err != nil {
+				return nil, err
+			}
+			log.CliLogger.Infof("Consistency proof valid!")
+		} else {
+			log.CliLogger.Infof("No previous log state stored, unable to prove consistency")
+		}
+
+		if viper.GetBool("store_tree_state") {
+			if err := state.Dump(lr); err != nil {
+				log.CliLogger.Infof("Unable to store previous state: %v", err)
+			}
+		}
 		return cmdOutput, nil
 	}),
 }
diff --git a/cmd/cli/app/root.go b/cmd/cli/app/root.go
index 086880b5e98e5b514fda9fe17e2a150e73c5ae53..68cb7a1a4f1a6927a7a6207ad8b7a1bb40adc89d 100644
--- a/cmd/cli/app/root.go
+++ b/cmd/cli/app/root.go
@@ -34,6 +34,7 @@ import (
 )
 
 var cfgFile string
+var storeState bool
 
 var rootCmd = &cobra.Command{
 	Use:   "rekor",
@@ -53,6 +54,7 @@ func init() {
 	cobra.OnInitialize(initConfig)
 
 	rootCmd.PersistentFlags().StringVar(&cfgFile, "config", "", "config file (default is $HOME/.rekor.yaml)")
+	rootCmd.PersistentFlags().BoolVar(&storeState, "store_tree_state", true, "whether to store tree state in between invocations for additional verification")
 
 	rootCmd.PersistentFlags().Var(&urlFlag{url: "https://api.rekor.dev"}, "rekor_server", "Server address:port")
 	rootCmd.PersistentFlags().Var(&formatFlag{format: "default"}, "format", "Command output format")
diff --git a/cmd/cli/app/state/state.go b/cmd/cli/app/state/state.go
new file mode 100644
index 0000000000000000000000000000000000000000..82cf24ce394f830d706d0c005042314c097df1a3
--- /dev/null
+++ b/cmd/cli/app/state/state.go
@@ -0,0 +1,75 @@
+/*
+Copyright © 2021 Dan Lorenc <lorenc.d@gmail.com>
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+package state
+
+import (
+	"encoding/json"
+	"io/ioutil"
+	"os"
+	"path/filepath"
+
+	"github.com/google/trillian/types"
+	"github.com/mitchellh/go-homedir"
+)
+
+func Dump(lr *types.LogRootV1) error {
+	rekorDir, err := getRekorDir()
+	if err != nil {
+		return err
+	}
+	statePath := filepath.Join(rekorDir, "state.json")
+
+	b, err := json.Marshal(lr)
+	if err != nil {
+		return err
+	}
+	if err := ioutil.WriteFile(statePath, b, 0600); err != nil {
+		return err
+	}
+	return nil
+}
+
+func Load() *types.LogRootV1 {
+	rekorDir, err := getRekorDir()
+	if err != nil {
+		return nil
+	}
+	fp := filepath.Join(rekorDir, "state.json")
+	b, err := ioutil.ReadFile(filepath.Clean(fp))
+	if err != nil {
+		return nil
+	}
+	result := &types.LogRootV1{}
+	if err := json.Unmarshal(b, result); err != nil {
+		return nil
+	}
+	return result
+}
+
+func getRekorDir() (string, error) {
+	home, err := homedir.Dir()
+	if err != nil {
+		return "", err
+	}
+	rekorDir := filepath.Join(home, ".rekor")
+	if _, err := os.Stat(rekorDir); os.IsNotExist(err) {
+		if err := os.MkdirAll(rekorDir, 0644); err != nil {
+			return "", err
+		}
+	}
+	return rekorDir, nil
+}
diff --git a/pkg/log/log.go b/pkg/log/log.go
index 839c53434f1d2b9cb12b55cceeaee5c7cd8004a6..7551ac4bbc822fc7168ad6a6fcc3ce826dc315cd 100644
--- a/pkg/log/log.go
+++ b/pkg/log/log.go
@@ -32,6 +32,21 @@ func ConfigureLogger(logType string) {
 	Logger = logger.Sugar()
 }
 
+var CliLogger = createCliLogger()
+
+func createCliLogger() *zap.SugaredLogger {
+	cfg := zap.NewDevelopmentConfig()
+	cfg.EncoderConfig.TimeKey = ""
+	cfg.EncoderConfig.LevelKey = ""
+	cfg.DisableCaller = true
+	logger, err := cfg.Build()
+	if err != nil {
+		log.Fatalln("createLogger", err)
+	}
+
+	return logger.Sugar()
+}
+
 func WithRequestID(ctx context.Context, id string) context.Context {
 	return context.WithValue(ctx, middleware.RequestIDKey, id)
 }