diff --git a/README.md b/README.md
index 8b082058984c748a53d2f7ba913d003697475f1a..7bfc1dc662c7d506d573a80f3f66f621852baf85 100644
--- a/README.md
+++ b/README.md
@@ -66,3 +66,9 @@ Secret and/or public keys can always be passed using `--secret` and `--address`.
 Secret key format can be changed using `--secret-format` with the following values:
 * `substrate`: a Substrate secret address (optionally followed by a derivation path), or BIP39 mnemonic
 * `seed`: a 32-bytes seed in hexadecimal (Duniter v1 compatible)
+
+## TODO
+
+- [x] implement config formatter
+- [ ] add link/unlink account commands
+- [ ] migrate all xt to submit_call_and_look_event
\ No newline at end of file
diff --git a/src/conf.rs b/src/conf.rs
index 5b7976bdca743ac066a777139845350e307ef223..9801172134129417509ae5b240e2f87421f87da4 100644
--- a/src/conf.rs
+++ b/src/conf.rs
@@ -27,6 +27,25 @@ impl std::default::Default for Config {
 	}
 }
 
+impl std::fmt::Display for Config {
+	fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+		let secret = if self.secret.is_some() {
+			"(secret defined)"
+		} else {
+			"(no secret)"
+		};
+		let address = if let Some(address) = &self.address {
+			format!("{}", address)
+		} else {
+			"(no address)".to_string()
+		};
+		writeln!(f, "Äžcli config")?;
+		writeln!(f, "duniter endpoint {}", self.duniter_endpoint)?;
+		writeln!(f, "indexer endpoint {}", self.indexer_endpoint)?;
+		write!(f, "address {address} {secret}")
+	}
+}
+
 /// load config file and manage error if could not
 pub fn load_conf() -> Config {
 	match confy::load(APP_NAME, None) {
@@ -68,7 +87,7 @@ pub fn handle_command(data: Data, command: Subcommand) -> anyhow::Result<()> {
 			);
 		}
 		Subcommand::Show => {
-			println!("{:?}", data.cfg);
+			println!("{}", data.cfg);
 		}
 		Subcommand::Save => {
 			confy::store(APP_NAME, None, &data.cfg).expect("unable to write config");