diff --git a/rwm.py b/rwm.py
index 892464dfb31a711e4f04164dfd063c098c353854..d08c851e3da469ad8701ec997283d864b315720b 100755
--- a/rwm.py
+++ b/rwm.py
@@ -462,7 +462,7 @@ class StorageManager:
 
         return ret
 
-    def _bucket_state(self, bucket_name):
+    def storage_state(self, bucket_name):
         """dumps current bucket state into dict"""
 
         state = {
@@ -488,7 +488,7 @@ class StorageManager:
 
         # explicit error handling here, it's used during backup process
         try:
-            bucket_state = self._bucket_state(bucket_name)
+            bucket_state = self.storage_state(bucket_name)
             now = datetime.now().astimezone().isoformat()
             self.s3.Bucket(bucket_name).upload_fileobj(
                 BytesIO(gzip.compress(json.dumps(bucket_state, cls=RwmJSONEncoder).encode())),
@@ -741,6 +741,16 @@ class RWM:
 
         return 0
 
+    def storage_state(self, bucket_name) -> int:
+        """dump storage state in json"""
+
+        print(json.dumps(
+            self.storage_manager.storage_state(bucket_name),
+            indent=4,
+            cls=RwmJSONEncoder
+        ))
+        return 0
+
     def storage_drop_versions(self, bucket_name) -> int:
         """storage_drop_versions command"""
 
@@ -799,6 +809,9 @@ def parse_arguments(argv):
     storage_info_cmd_parser = subparsers.add_parser("storage-info", help="show detailed storage info")
     storage_info_cmd_parser.add_argument("bucket_name", help="bucket name")
 
+    storage_state_cmd_parser = subparsers.add_parser("storage-state", help="dump current storage state")
+    storage_state_cmd_parser.add_argument("bucket_name", help="bucket name")
+
     storage_drop_versions_cmd_parser = subparsers.add_parser(
         "storage-drop-versions",
         help="reclaim storage space; drop any old object versions from bucket"
@@ -873,6 +886,9 @@ def main(argv=None):  # pylint: disable=too-many-branches
     if args.command == "storage-info":
         ret = rwmi.storage_info(args.bucket_name)
 
+    if args.command == "storage-state":
+        ret = rwmi.storage_state(args.bucket_name)
+
     if args.command == "storage-drop-versions":
         ret = rwmi.storage_drop_versions(args.bucket_name)
 
diff --git a/tests/test_default.py b/tests/test_default.py
index 7b69848b9f706cfb24da1789a5e2281a181ff2de..2271626686d1f7fe624ae9c86429d4749a01d4a9 100644
--- a/tests/test_default.py
+++ b/tests/test_default.py
@@ -65,6 +65,9 @@ def test_main():
     with patch.object(rwm.RWM, "storage_info", mock_ok):
         assert _rwm_minconfig(["storage-info", "dummy"]) == 0
 
+    with patch.object(rwm.RWM, "storage_state", mock_ok):
+        assert _rwm_minconfig(["storage-state", "dummy"]) == 0
+
     with patch.object(rwm.RWM, "storage_drop_versions", mock_ok):
         assert _rwm_minconfig(["storage-drop-versions", "bucket"]) == 0
 
diff --git a/tests/test_rwm.py b/tests/test_rwm.py
index 6c22223fde51f496bfe27cab6a13d13d95cdb523..3a89a5b3f0bb1d27b561fe64e6d798f53831ff32 100644
--- a/tests/test_rwm.py
+++ b/tests/test_rwm.py
@@ -328,6 +328,19 @@ def test_storage_info(tmpworkdir: str, radosuser_admin: rwm.StorageManager):  #
     assert trwm.storage_info("dummy") == 0
 
 
+def test_storage_state(tmpworkdir: str, radosuser_admin: rwm.StorageManager):  # pylint: disable=unused-argument
+    """test storage_state"""
+
+    trwm = rwm.RWM({
+        "s3_endpoint_url": radosuser_admin.url,
+        "s3_access_key": radosuser_admin.access_key,
+        "s3_secret_key": radosuser_admin.secret_key,
+    })
+
+    trwm.storage_create("dummy", "dummy")
+    assert trwm.storage_state("dummy") == 0
+
+
 def test_storage_drop_versions(tmpworkdir: str):  # pylint: disable=unused-argument
     """test storage drop versions"""
 
diff --git a/tests/test_storage.py b/tests/test_storage.py
index da90b7f6645de2e0ebafabef5f2509fcda0b8445..96b594a67515e381d3ed15efd47fdf76b37a37d5 100644
--- a/tests/test_storage.py
+++ b/tests/test_storage.py
@@ -178,6 +178,25 @@ def test_storage_info(
     assert radosuser_admin.storage_info(bucket_name)["delete_markers"] == 1
 
 
+def test_storage_state(
+    tmpworkdir: str,
+    radosuser_admin: rwm.StorageManager,
+):  # pylint: disable=unused-argument
+    """test manager storage state"""
+
+    bucket_name = "rwmbackup-test1"
+    target_username = "test1"
+
+    bucket = radosuser_admin.storage_create(bucket_name, target_username)
+    bucket.upload_fileobj(BytesIO(b"dummydata1"), "dummykey")
+    bucket.upload_fileobj(BytesIO(b"dummydata1"), "dummykey1")
+    bucket.Object("dummykey1").delete()
+
+    state = radosuser_admin.storage_state(bucket_name)
+    assert len(state["versions"]) == 2
+    assert len(state["delete_markers"]) == 1
+
+
 def test_storage_drop_versions(tmpworkdir: str, radosuser_admin: rwm.StorageManager):  # pylint: disable=unused-argument
     """test manager storage_drop_versions"""
 
@@ -230,7 +249,7 @@ def test_storage_save_state_error_handling(tmpworkdir: str):  # pylint: disable=
     """test storage_save_state error handling"""
 
     mock = Mock(side_effect=TypeError("dummy"))
-    with patch.object(rwm.StorageManager, "_bucket_state", mock):
+    with patch.object(rwm.StorageManager, "storage_state", mock):
         assert rwm.StorageManager("http://localhost", "", "").storage_save_state("dummy") == 1