diff --git a/Cargo.lock b/Cargo.lock
index 34f452ed..c624f55d 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -19,6 +19,55 @@ dependencies = [
  "cpufeatures",
 ]
 
+[[package]]
+name = "anstream"
+version = "0.6.14"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "418c75fa768af9c03be99d17643f93f79bbba589895012a80e3452a19ddda15b"
+dependencies = [
+ "anstyle",
+ "anstyle-parse",
+ "anstyle-query",
+ "anstyle-wincon",
+ "colorchoice",
+ "is_terminal_polyfill",
+ "utf8parse",
+]
+
+[[package]]
+name = "anstyle"
+version = "1.0.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "038dfcf04a5feb68e9c60b21c9625a54c2c0616e79b72b0fd87075a056ae1d1b"
+
+[[package]]
+name = "anstyle-parse"
+version = "0.2.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c03a11a9034d92058ceb6ee011ce58af4a9bf61491aa7e1e59ecd24bd40d22d4"
+dependencies = [
+ "utf8parse",
+]
+
+[[package]]
+name = "anstyle-query"
+version = "1.0.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a64c907d4e79225ac72e2a354c9ce84d50ebb4586dee56c82b3ee73004f537f5"
+dependencies = [
+ "windows-sys 0.52.0",
+]
+
+[[package]]
+name = "anstyle-wincon"
+version = "3.0.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "61a38449feb7068f52bb06c12759005cf459ee52bb4adc1d5a7c4322d716fb19"
+dependencies = [
+ "anstyle",
+ "windows-sys 0.52.0",
+]
+
 [[package]]
 name = "autocfg"
 version = "1.3.0"
@@ -125,6 +174,52 @@ dependencies = [
  "inout",
 ]
 
+[[package]]
+name = "clap"
+version = "4.5.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "90bc066a67923782aa8515dbaea16946c5bcc5addbd668bb80af688e53e548a0"
+dependencies = [
+ "clap_builder",
+ "clap_derive",
+]
+
+[[package]]
+name = "clap_builder"
+version = "4.5.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ae129e2e766ae0ec03484e609954119f123cc1fe650337e155d03b022f24f7b4"
+dependencies = [
+ "anstream",
+ "anstyle",
+ "clap_lex",
+ "strsim",
+]
+
+[[package]]
+name = "clap_derive"
+version = "4.5.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "528131438037fd55894f62d6e9f068b8f45ac57ffa77517819645d10aed04f64"
+dependencies = [
+ "heck",
+ "proc-macro2",
+ "quote",
+ "syn",
+]
+
+[[package]]
+name = "clap_lex"
+version = "0.7.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "98cc8fbded0c607b7ba9dd60cd98df59af97e84d24e49c8557331cfc26d301ce"
+
+[[package]]
+name = "colorchoice"
+version = "1.0.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0b6a852b24ab71dffc585bcb46eaf7959d175cb865a7152e35b348d1b2960422"
+
 [[package]]
 name = "cpufeatures"
 version = "0.2.12"
@@ -593,6 +688,12 @@ dependencies = [
  "generic-array",
 ]
 
+[[package]]
+name = "is_terminal_polyfill"
+version = "1.70.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f8478577c03552c21db0e2724ffb8986a5ce7af88107e6be5d2ee6e158c12800"
+
 [[package]]
 name = "libc"
 version = "0.2.155"
@@ -655,6 +756,7 @@ dependencies = [
  "awesome-glib",
  "awesome-gtk",
  "cbc",
+ "clap",
  "deflate",
  "embed-resource",
  "futures",
@@ -817,6 +919,12 @@ version = "1.13.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67"
 
+[[package]]
+name = "strsim"
+version = "0.11.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f"
+
 [[package]]
 name = "syn"
 version = "2.0.66"
@@ -924,6 +1032,12 @@ version = "1.0.12"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b"
 
+[[package]]
+name = "utf8parse"
+version = "0.2.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "711b9620af191e0cdc7468a8d14e709c3dcdb115b36f838e601583af800a370a"
+
 [[package]]
 name = "version-compare"
 version = "0.2.0"
diff --git a/Cargo.toml b/Cargo.toml
index 338eb4b7..eedde872 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -7,6 +7,7 @@ edition = "2021"
 license = "LGPL-3.0-or-later"
 description = "Password storing program"
 readme = "README.md"
+default-run = "password-storage"
 
 [dependencies]
 futures = "0.3"
@@ -26,6 +27,8 @@ gtk = { package = "gtk4", version = "0.8", features = ["v4_12"] }
 awesome-glib = "0.4"
 awesome-gtk = "0.4"
 
+clap = { version = "4.5.4", features = ["derive"] }
+
 [build-dependencies]
 glib-build-tools = "0.19"
 
diff --git a/src/bin/revelation-decode.rs b/src/bin/revelation-decode.rs
new file mode 100644
index 00000000..09331d70
--- /dev/null
+++ b/src/bin/revelation-decode.rs
@@ -0,0 +1,41 @@
+use clap::Parser;
+use password_storage::format::revelation;
+use std::error::Error;
+use std::fs;
+use std::io::{stdin, stdout, BufReader, Write};
+use std::path::PathBuf;
+
+#[derive(Parser)]
+struct Opts {
+    /// Input file
+    input: PathBuf,
+
+    /// Input file
+    output: PathBuf,
+}
+
+fn main() -> Result<(), Box<dyn Error>> {
+    let opts = Opts::parse();
+
+    print!("Enter a password for a file {}: ", opts.input.display());
+    stdout().flush()?;
+
+    let mut password = String::new();
+    stdin().read_line(&mut password)?;
+    println!("");
+
+    let file = fs::OpenOptions::new().read(true).open(&opts.input)?;
+    let mut buffer = BufReader::new(file);
+
+    let data = revelation::decrypt_revelation_file(&mut buffer, &password.trim())?;
+
+    fs::write(&opts.output, data.content)?;
+
+    println!(
+        "Output file: {}\nData format: {:?}\nDone",
+        opts.output.display(),
+        data.format
+    );
+
+    Ok(())
+}
diff --git a/src/format/revelation/mod.rs b/src/format/revelation/mod.rs
index ed08aa34..78d029a8 100644
--- a/src/format/revelation/mod.rs
+++ b/src/format/revelation/mod.rs
@@ -26,7 +26,8 @@ impl CryptoContainer {
     }
 }
 
-enum SerializationFormat {
+#[derive(Debug)]
+pub enum SerializationFormat {
     Xml,
 }
 
@@ -51,7 +52,12 @@ fn version_impl(version: u8) -> Option<(CryptoContainer, SerializationFormat)> {
     }
 }
 
-pub fn load_revelation_file(source: &mut dyn Read, password: &str) -> Result<RecordTree> {
+pub struct Decrypted {
+    pub format: SerializationFormat,
+    pub content: Vec<u8>,
+}
+
+pub fn decrypt_revelation_file(source: &mut dyn Read, password: &str) -> Result<Decrypted> {
     let header = file_header::FileHeader::read(source)?;
     let (container, format) = version_impl(header.data_version).ok_or_else(|| {
         format!(
@@ -59,8 +65,13 @@ pub fn load_revelation_file(source: &mut dyn Read, password: &str) -> Result<Rec
             header.data_version, header.app_version
         )
     })?;
-    let decrypted = container.decrypt(source, password)?;
-    let tree = format.deserialize(&decrypted)?;
+    let content = container.decrypt(source, password)?;
+    Ok(Decrypted { format, content })
+}
+
+pub fn load_revelation_file(source: &mut dyn Read, password: &str) -> Result<RecordTree> {
+    let Decrypted { format, content } = decrypt_revelation_file(source, password)?;
+    let tree = format.deserialize(&content)?;
     Ok(tree)
 }