diff --git a/src/rust/amadeus-rs/amadeus-macro/src/lib.rs b/src/rust/amadeus-rs/amadeus-macro/src/lib.rs
index 7e6a7e6107c33f1c24d0414d852f628a64e36443..3be4abf86039feae4d636763113449e2336d058e 100644
--- a/src/rust/amadeus-rs/amadeus-macro/src/lib.rs
+++ b/src/rust/amadeus-rs/amadeus-macro/src/lib.rs
@@ -1,5 +1,3 @@
-// https://doc.rust-lang.org/reference/macros-by-example.html
-
 #[macro_export]
 macro_rules! either {
     ($test:expr => $true_expr:expr; $false_expr:expr) => {
@@ -17,3 +15,14 @@ macro_rules! lkt_command_from_str {
         concat!($lit, '\n').to_owned()
     };
 }
+
+#[macro_export]
+macro_rules! then_some {
+    ($cond: expr => $some: expr) => {
+        if $cond {
+            Some($some)
+        } else {
+            None
+        }
+    };
+}
diff --git a/src/rust/amadeus-rs/amadeus/src/utils/deamon.rs b/src/rust/amadeus-rs/amadeus/src/utils/deamon.rs
index f7d312b3f251e366fd6dbb79a6184f27c990bb69..21317f21c7ef8abb5763d81ed0325b85eeacca83 100644
--- a/src/rust/amadeus-rs/amadeus/src/utils/deamon.rs
+++ b/src/rust/amadeus-rs/amadeus/src/utils/deamon.rs
@@ -153,14 +153,14 @@ impl Deamon for StatusDeamon {
             return_when_flagged!(quit_deamon, joined_deamon);
 
             let status = {
-                let mut res = match connexion.send_query(LektorQuery::PlaybackStatus) {
+                let res = match connexion.send_query(LektorQuery::PlaybackStatus) {
                     Ok(res) => res,
                     Err(e) => {
                         error!("failed to send the playback status command to lektor: {e}");
                         continue;
                     }
                 };
-                match LektorPlaybackStatusResponse::consume(&mut res) {
+                match LektorPlaybackStatusResponse::consume(res) {
                     Err(e) => {
                         error!("failed to build response from formated response: {e}");
                         continue;
@@ -170,14 +170,14 @@ impl Deamon for StatusDeamon {
             };
 
             let current = if status.state != LektorState::Stopped {
-                let mut res = match connexion.send_query(LektorQuery::CurrentKara) {
+                let res = match connexion.send_query(LektorQuery::CurrentKara) {
                     Ok(res) => res,
                     Err(e) => {
                         error!("failed to send the current kara command to lektor: {e}",);
                         continue;
                     }
                 };
-                match LektorCurrentKaraResponse::consume(&mut res) {
+                match LektorCurrentKaraResponse::consume(res) {
                     Ok(res) => Some(res),
                     Err(err) => {
                         error!("failed to build response from formated response: {err}");
diff --git a/src/rust/amadeus-rs/lkt-lib/src/connexion.rs b/src/rust/amadeus-rs/lkt-lib/src/connexion.rs
index 8d88132e6bedbf9c3fb73be29628b4ced6d9a5de..4a3edbc85c2fa40685e340a723bf12635efbc8f8 100644
--- a/src/rust/amadeus-rs/lkt-lib/src/connexion.rs
+++ b/src/rust/amadeus-rs/lkt-lib/src/connexion.rs
@@ -13,6 +13,7 @@ use std::{
 
 pub enum LektorQueryError {
     IO(io::Error),
+    Query(String),
     Other(String),
 }
 
@@ -20,6 +21,7 @@ impl std::fmt::Display for LektorQueryError {
     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
         use LektorQueryError::*;
         match self {
+            Query(err) => write!(f, "lektor query logic error: {err}"),
             IO(io) => write!(f, "lektor query error io: {io}"),
             Other(other) => write!(f, "lektor query error: {other}"),
         }
@@ -76,6 +78,7 @@ impl LektorConnexion {
         query: LektorQuery,
     ) -> Result<LektorFormatedResponse, LektorQueryError> {
         let mut res: Vec<String> = Vec::new();
+        query.verify().map_err(LektorQueryError::Query)?;
         self.send_query_inner(query, &mut res)
             .map_err(LektorQueryError::IO)?;
         LektorFormatedResponse::try_from(res).map_err(LektorQueryError::Other)
diff --git a/src/rust/amadeus-rs/lkt-lib/src/lib.rs b/src/rust/amadeus-rs/lkt-lib/src/lib.rs
index 4d272fafa663d56974da0b460962db7373390b05..331d354dd87a2a3762e3e6686bab89c9f66dcaaf 100644
--- a/src/rust/amadeus-rs/lkt-lib/src/lib.rs
+++ b/src/rust/amadeus-rs/lkt-lib/src/lib.rs
@@ -3,7 +3,6 @@
 
 mod connexion;
 mod constants;
-mod macros;
 mod query;
 mod response;
 mod types;
diff --git a/src/rust/amadeus-rs/lkt-lib/src/macros.rs b/src/rust/amadeus-rs/lkt-lib/src/macros.rs
deleted file mode 100644
index 88ba1211cb5124c4d0849feb6a66257b53a4473c..0000000000000000000000000000000000000000
--- a/src/rust/amadeus-rs/lkt-lib/src/macros.rs
+++ /dev/null
@@ -1,10 +0,0 @@
-#[macro_export]
-macro_rules! then_some {
-    ($cond: expr => $some: expr) => {
-        if $cond {
-            Some($some)
-        } else {
-            None
-        }
-    };
-}
diff --git a/src/rust/amadeus-rs/lkt-lib/src/query.rs b/src/rust/amadeus-rs/lkt-lib/src/query.rs
index 6bcf9b19d8847cc6377998482d322a09ea7e51bb..f0fe4dac1f6932d814857f68c5d10bdf020b70d7 100644
--- a/src/rust/amadeus-rs/lkt-lib/src/query.rs
+++ b/src/rust/amadeus-rs/lkt-lib/src/query.rs
@@ -2,7 +2,7 @@
 
 use crate::uri::LektorUri;
 use amadeus_macro::lkt_command_from_str;
-use std::string::ToString;
+use std::{borrow::Borrow, string::ToString};
 
 pub(crate) enum LektorQueryLineType {
     Ok,
@@ -16,7 +16,7 @@ pub enum LektorQuery {
     Ping,
     Close,
     KillServer,
-    ConnectAsUser(String),
+    ConnectAsUser(String, Box<LektorQuery>),
 
     CurrentKara,
     PlaybackStatus,
@@ -27,6 +27,7 @@ pub enum LektorQuery {
 
     ListAllPlaylists,
     ListPlaylist(String),
+    SearchKara(LektorUri),
 
     FindAddKara(LektorUri),
     InsertKara(LektorUri),
@@ -76,6 +77,32 @@ impl LektorQuery {
     pub fn create_continuation(query: Self, cont: usize) -> Self {
         Self::Continuation(cont, Box::new(query))
     }
+
+    pub fn verify(&self) -> Result<(), String> {
+        use LektorQuery::*;
+        match self {
+            // User commands
+            SearchKara(_) | FindAddKara(_) | InsertKara(_) | AddKara(_) | PlaybackStatus
+            | PlayNext | PlayPrevious | ShuffleQueue | ListAllPlaylists | ListPlaylist(_)
+            | CurrentKara | Ping => Ok(()),
+
+            // Should be admin commands
+            Close => Err("close is an admin command".to_string()),
+            KillServer => Err("kill server is an admin command".to_string()),
+
+            // Admin commands
+            ConnectAsUser(_, cmd) => match cmd.borrow() {
+                Close | KillServer => Ok(()),
+                _ => Err(format!("not an admin command: {cmd:?}")),
+            },
+
+            // Continuation commands
+            Continuation(_, cmd) => match cmd.borrow() {
+                ListAllPlaylists | FindAddKara(_) | SearchKara(_) | ListPlaylist(_) => Ok(()),
+                _ => Err(format!("not a continuable command: {cmd:?}")),
+            },
+        }
+    }
 }
 
 impl ToString for LektorQuery {
@@ -85,7 +112,16 @@ impl ToString for LektorQuery {
             Ping => lkt_command_from_str!("ping"),
             Close => lkt_command_from_str!("close"),
             KillServer => lkt_command_from_str!("kill"),
-            ConnectAsUser(password) => format!("password {}\n", password),
+            ConnectAsUser(password, cmd) => format!(
+                concat!(
+                    "command_list_begin\n",
+                    "password {}\n",
+                    "{}\n",
+                    "command_list_end\n",
+                ),
+                password,
+                cmd.to_string()
+            ),
 
             CurrentKara => lkt_command_from_str!("currentsong"),
             PlaybackStatus => lkt_command_from_str!("status"),
@@ -96,6 +132,7 @@ impl ToString for LektorQuery {
 
             ListAllPlaylists => lkt_command_from_str!("listplaylists"),
             ListPlaylist(plt_name) => format!("listplaylist {}\n", plt_name),
+            SearchKara(uri) => format!("find {}\n", uri.to_string()),
 
             FindAddKara(uri) => format!("findadd {}\n", uri.to_string()),
             InsertKara(uri) => format!("__insert {}\n", uri.to_string()),
diff --git a/src/rust/amadeus-rs/lkt-lib/src/response.rs b/src/rust/amadeus-rs/lkt-lib/src/response.rs
index 585ebdfa45f94980aff71b284c82f4378a246b1f..d80e662f86cc8e10743db422235e5c08a08f19cc 100644
--- a/src/rust/amadeus-rs/lkt-lib/src/response.rs
+++ b/src/rust/amadeus-rs/lkt-lib/src/response.rs
@@ -1,14 +1,19 @@
 //! Contains types for typed response.
 
-use crate::then_some;
 use crate::types::LektorState;
+use amadeus_macro::*;
 
+/// A formated response is just a list of key/pairs. We get every line that is
+/// not Ok/Ack/Continue (i.e. data lines) and split on the first ':' and trim
+/// spaces from the keys and the values. The keys are always in lowercase.
 #[derive(Debug)]
 pub struct LektorFormatedResponse {
     content: Vec<(String, String)>,
 }
 
 impl LektorFormatedResponse {
+    /// Pop the first key found in the response, get an error if the key is not
+    /// found. If multiple keys are found, only the first found is returned.
     pub fn pop(&mut self, key: &str) -> Result<String, String> {
         match self
             .content
@@ -20,6 +25,23 @@ impl LektorFormatedResponse {
             None => Err(format!("no key {key} was found in formated response")),
         }
     }
+
+    /// Pop all the entries with the said key. If no key is found then the empty
+    /// vector is returned. This function can't fail.
+    ///
+    /// FIXME: Get ride of the clone in this function...
+    pub fn pop_all(&mut self, key: &str) -> Vec<String> {
+        let mut ret = Vec::new();
+        self.content.retain(|(what, field)| {
+            if *what == key {
+                ret.push(field.clone());
+                false
+            } else {
+                true
+            }
+        });
+        ret
+    }
 }
 
 impl IntoIterator for LektorFormatedResponse {
@@ -54,6 +76,25 @@ impl TryFrom<Vec<String>> for LektorFormatedResponse {
 pub enum LektordResponse {
     PlaybackStatus(LektorPlaybackStatusResponse),
     CurrentKara(LektorCurrentKaraResponse),
+    PlaylistList(LektorPlaylistListResponse),
+}
+
+/// A trait for typed lektor responses. Such responses must be built by
+/// consuming a formated response. We also protect from implemeting this trait
+/// outside of this crate.
+pub trait FromLektorResponse: Sized + std::fmt::Debug + private::Sealed {
+    /// Consume a formated response to produce the correctly typed response. May
+    /// got an error as a string that describes the problem.
+    fn consume(response: LektorFormatedResponse) -> Result<Self, String>;
+}
+
+mod private {
+    use super::*;
+    pub trait Sealed {}
+    impl Sealed for LektorPlaybackStatusResponse {}
+    impl Sealed for LektorCurrentKaraResponse {}
+    impl Sealed for LektorPlaylistListResponse {}
+    impl Sealed for LektorEmptyResponse {}
 }
 
 #[derive(Debug)]
@@ -72,8 +113,59 @@ pub struct LektorPlaybackStatusResponse {
     pub repeat: bool,
 }
 
-impl LektorPlaybackStatusResponse {
-    pub fn consume(response: &mut LektorFormatedResponse) -> Result<Self, String> {
+#[derive(Debug)]
+pub struct LektorPlaylistListResponse {
+    pub playlists: Vec<String>,
+}
+
+#[derive(Debug)]
+pub struct LektorCurrentKaraInnerResponse {
+    pub title: String,
+    pub author: String,
+    pub source: String,
+    pub song_type: String,
+    pub song_number: Option<usize>,
+    pub category: String,
+    pub language: String,
+}
+
+#[derive(Debug)]
+pub struct LektorCurrentKaraResponse {
+    pub content: Option<LektorCurrentKaraInnerResponse>,
+}
+
+#[derive(Debug)]
+pub struct LektorEmptyResponse;
+
+impl LektorCurrentKaraInnerResponse {
+    /// If the response is partial we might want to return none (if we are not
+    /// playing anything for example...)
+    pub(self) fn is_partial(&self) -> bool {
+        self.title.is_empty()
+            || self.author.is_empty()
+            || self.source.is_empty()
+            || self.song_type.is_empty()
+            || self.category.is_empty()
+            || self.language.is_empty()
+    }
+}
+
+impl FromLektorResponse for LektorEmptyResponse {
+    fn consume(_: LektorFormatedResponse) -> Result<Self, String> {
+        Ok(Self {})
+    }
+}
+
+impl FromLektorResponse for LektorPlaylistListResponse {
+    fn consume(mut response: LektorFormatedResponse) -> Result<Self, String> {
+        Ok(Self {
+            playlists: response.pop_all("name"),
+        })
+    }
+}
+
+impl FromLektorResponse for LektorPlaybackStatusResponse {
+    fn consume(mut response: LektorFormatedResponse) -> Result<Self, String> {
         let mut ret = Self {
             elapsed: response.pop("elapsed")?.parse::<usize>().unwrap_or(0),
             songid: match response.pop("songid")?.parse::<isize>() {
@@ -108,19 +200,8 @@ impl LektorPlaybackStatusResponse {
     }
 }
 
-#[derive(Debug)]
-pub struct LektorCurrentKaraResponse {
-    pub title: String,
-    pub author: String,
-    pub source: String,
-    pub song_type: String,
-    pub song_number: Option<usize>,
-    pub category: String,
-    pub language: String,
-}
-
-impl LektorCurrentKaraResponse {
-    pub fn consume(response: &mut LektorFormatedResponse) -> Result<Self, String> {
+impl FromLektorResponse for LektorCurrentKaraResponse {
+    fn consume(mut response: LektorFormatedResponse) -> Result<Self, String> {
         let song_type_number = response.pop("type")?;
         let (song_type, song_number) = match song_type_number.find(char::is_numeric) {
             Some(index) => (
@@ -133,7 +214,7 @@ impl LektorCurrentKaraResponse {
             None => panic!("Oupsy"),
         };
 
-        Ok(Self {
+        let inner = LektorCurrentKaraInnerResponse {
             title: response.pop("title")?,
             author: response.pop("author")?,
             source: response.pop("source")?,
@@ -141,6 +222,10 @@ impl LektorCurrentKaraResponse {
             language: response.pop("language")?,
             song_type,
             song_number,
+        };
+
+        Ok(Self {
+            content: then_some!(!inner.is_partial() => inner),
         })
     }
 }
diff --git a/src/rust/amadeus-rs/lkt-rs/src/main.rs b/src/rust/amadeus-rs/lkt-rs/src/main.rs
index 01aea5fe5c8f1bb629914ac2f58f9e8a24b8863d..f7d6f81f7fd9f086c930e47ba414f1351b9e83cd 100644
--- a/src/rust/amadeus-rs/lkt-rs/src/main.rs
+++ b/src/rust/amadeus-rs/lkt-rs/src/main.rs
@@ -4,19 +4,18 @@ fn main() {
     let mut lektor = LektorConnexion::new("localhost".to_owned(), 6600).unwrap();
     if lektor.send_query(LektorQuery::Ping).is_ok() {}
 
-    if let Ok(mut response) = lektor.send_query(LektorQuery::CurrentKara) {
-        let current_kara = LektorCurrentKaraResponse::consume(&mut response);
+    if let Ok(response) = lektor.send_query(LektorQuery::CurrentKara) {
+        let current_kara = LektorCurrentKaraResponse::consume(response);
         println!("CURRENT {:?}", current_kara);
     }
 
-    if let Ok(mut response) = lektor.send_query(LektorQuery::PlaybackStatus) {
-        let playback_status = LektorPlaybackStatusResponse::consume(&mut response);
+    if let Ok(response) = lektor.send_query(LektorQuery::PlaybackStatus) {
+        let playback_status = LektorPlaybackStatusResponse::consume(response);
         println!("PLAYBACK-STATUS {:?}", playback_status);
     }
 
     if let Ok(response) = lektor.send_query(LektorQuery::ListAllPlaylists) {
-        for (what, item) in response.into_iter() {
-            println!("ALL PLAYLISTS {what}:{item}");
-        }
+        let plts_response = LektorPlaylistListResponse::consume(response);
+        println!("ALL-PLTS {:?}", plts_response);
     }
 }