diff --git a/man/Makefile.am b/man/Makefile.am
index ffa94f9cc1a269ad0b89716faee4669bb59730ea..4699b3a78b65a5dbcd83d5e2969ab2304644b8f8 100644
--- a/man/Makefile.am
+++ b/man/Makefile.am
@@ -1,4 +1,4 @@
-lkt_manpages		   = lektor.man lektord.man lkt.man lkt.old.man
+lkt_manpages		   = lektor.man lektord.man lkt.man
 notrans_dist_man1_MANS = $(lkt_manpages)
 MAN                    = $(abs_top_srcdir)/scripts/manpage.bash
 CLEANFILES 			   = $(lkt_manpages)
diff --git a/man/Makefile.in b/man/Makefile.in
index 9f4e3af0fff28732aacddc411a35f3b25ac6f91d..e464bfa443983992fe300025f81a5378b2bf82e4 100644
--- a/man/Makefile.in
+++ b/man/Makefile.in
@@ -286,7 +286,7 @@ target_alias = @target_alias@
 top_build_prefix = @top_build_prefix@
 top_builddir = @top_builddir@
 top_srcdir = @top_srcdir@
-lkt_manpages = lektor.man lektord.man lkt.man lkt.old.man
+lkt_manpages = lektor.man lektord.man lkt.man
 notrans_dist_man1_MANS = $(lkt_manpages)
 CLEANFILES = $(lkt_manpages)
 all: all-am
diff --git a/man/footer b/man/footer
index 8301ba8d8697ee6da0f3d33069cc915a0216a4ca..3fd0a054894a397ddcfe73161fb159a9a061fa34 100644
--- a/man/footer
+++ b/man/footer
@@ -12,6 +12,5 @@
 \fIlektor\fP(1),
 \fIlektord\fP(1),
 \fIlkt\fP(1),
-\fIlkt.old\fP(1),
 \fImpc\fP(1),
 \fImpd\fP(1)
diff --git a/man/lektor.template b/man/lektor.template
index 49766112f26a0cae216017128fea6bc69c6cb969..b682cae63ee09fe0509fbfc8c11de0c9bca20d9f 100644
--- a/man/lektor.template
+++ b/man/lektor.template
@@ -15,8 +15,6 @@ You may be interested in other related programs like:
 \fIlektord\fP       The lektor daemon
 .TP
 \fIlkt\fP           A standard client for lektord
-.TP
-\fIlkt.old\fP       A standard client for lektord, the old and deprecated version
 .PD
 
 .SH "DESCRIPTION"
diff --git a/man/lkt.old.template b/man/lkt.old.template
deleted file mode 100644
index 8c4837fa4bfd82de4afdbfd0ed5b5551f858123d..0000000000000000000000000000000000000000
--- a/man/lkt.old.template
+++ /dev/null
@@ -1,274 +0,0 @@
-.\" vim: ft=groff
-.TH "LKT.OLD" "1" "___DATE___" "LEKTOR MK 7"
-.SH "NAME"
-
-lkt.old \- the old lektor command line client, kept for some back-compatibility issues
-
-.PP
-\fB/!\\ Deprecated /!\\\fP
-
-.SH "OVERVIEW"
-\fBlkt.old\fP is the old \fBlektord\fP client, much like \fBmpc\fP but with
-more functionnalities like \fIplaylists\fP and \fIstickers\fP management.
-.PP
-Because \fBlkt.old\fP is replaced by \fBlkt\fP, its usage is deprecated in
-favor of \fBlkt\fP. The differences are the following:
-.IP \[bu] 2
-Some types in queries are optional. Thus the type is infered from the regex
-part and it means that some \fIqueries\fP are no longer possible.
-.PP
-Commands can be used with the minimal name that permit them to be
-distinguished from others commands. Thus, it is possible to use the
-string \fIadm\fP as an alias for \fIadmin\fP. This is like cisco switch
-command line interface.
-.PP
-
-.SH "COMMANDS"
-Here are the \fBlkt.old\fP commands:
-
-.PP
-\fIBASE-COMMANDS\fP
-.PP
-.PD 0
-.TP
-.PD
-\fBcurrent\fP
-Prints informations about the currently playing kara. Can be used to
-display the current kara in a status bar like \fBxmobar\fP or in the
-\fBi3 panel\fP
-.TP
-\fBplay\fP [index]
-Toggle play/pause state. If the playback is stopped, start at a possibly
-specified index
-.TP
-\fBnext\fP
-Play next kara in the queue
-.TP
-\fBprevious\fP
-Play the previous kara in the queue
-.TP
-\fBshuffle\fP
-Shuffle the queue. If the state was stoppped, play from the first kara
-in the queue. If lektor was already playing a kara, it will play it
-from the begening. The current kara will be placed in first position
-in the queue.
-.TP
-\fBstatus\fP
-Prints information about the state of lektor and the currently playing kara
-.TP
-\fBstop\fP
-Stop the playback and reading the queue, the state is now \fIstopped\fP.
-.PP
-\fIPLAYLIST-COMMANDS\fP
-.PP
-.PD 0
-.TP
-.PD
-\fBplt create\fP <plt-name>
-Creates a playlist, do nothing if it was already present
-.TP
-\fBplt destroy\fP <plt-name>
-Delete a playlist with all its content, do nothing if the playlist didn't exists
-.TP
-\fBplt delete\fP <plt-name> <query>
-Deletes karas from a playlist with a valid \fIquery\fP
-.TP
-\fBplt add\fP <plt-name> <query>
-Adds karas to a playlist with a valid \fIquery\fP
-.TP
-\fBplt list\fP <plt-name>
-List the content of the playlist named <plt-name>
-.TP
-\fBplt list\fP
-List all the available playlists
-.PP
-
-\fIQUEUE-COMMANDS\fP
-.PP
-.PD 0
-.TP
-.PD
-\fBqueue\fP [count]
-Prints the names and ids of the next karas in the queue
-.TP
-\fBqueue pos\fP <pos | from:to>
-Prints the names and ids of karas in the queue. Karas can be designated by
-their position or with a range
-.TP
-\fBqueue pop\fP
-Delete the currently playing kara from the queue and pass to the next one.
-This can work only if the currently playong kara is not the last
-.TP
-\fBqueue add\fP <query>
-Add karas to the queue at the end of it with a valid query
-.TP
-\fBqueue insert\fP <query>
-Add karas to the queue just after the currently playing kara
-.TP
-\fBqueue seek\fP <id>
-Goto to the kara with the specified id in the queue
-.TP
-\fBqueue delete\fP <id>
-Delete karas from the playlist with their id. You can't delete the currently
-playing kara, for that use the \fBpop\fP queue command
-.TP
-\fBqueue clear\fP
-Clear the queue and set the state to \fIstopped\fP
-.TP
-\fBqueue crop\fP
-Crop the queue, delete every kara from it appart from the currently
-playing one
-.TP
-\fBqueue replace\fP <plt-name>
-Replace the queue with the content of a playlist. Keep the playling state
-.PP
-
-\fISEARCH-COMMANDS\fP
-.PP
-.PD 0
-.TP
-.PD
-\fBsearch database\fP <query>
-Search and prints the kara that correspond to the query in the database
-.TP
-\fBsearch plt\fP <plt-name> <query>
-Search, prints and add to an existing playlist the karas that match
-the query
-.TP
-\fBsearch plt\fP <plt-name>
-List the content of the playlist named <plt-name>
-.TP
-\fBsearch plt\fP
-List all the available playlists
-.TP
-\fBsearch count\fP <query>
-Search and prints the number of karas that match the query
-.TP
-\fBsearch get\fP <id>
-Get informations about a specific id
-.TP
-\fBsearch queue\fP <query>
-Search in the queue and prints the karas that match the query
-.PP
-
-\fISTICKERS-COMMANDS\fP
-.PP
-.PD 0
-.TP
-.PD
-\fBsticker create\fP <name>
-Create a sticker that can be used to tag \fIkara\fP and \fIplt\fP objects
-.TP
-\fBsticker get\fP <type> <uri> [ <name> [ <op> <value> ] ]
-List the stickers of an object \fIuri\fP. The object \fItype\fP can be
-\fIkara\fP or \fIplt\fP
-
-A condition can be defined on the value of the sticker with an operator
-\fIop\fP and an integer value \fIvalue\fP. Supported operators are \fIl\fP
-for 'less than', \fIe\fP for 'equal to' and \fIg\fP for 'greater than'.
-Operations are not strict
-.TP
-\fBsticker set\fP <type> <uri> <name> <value>
-Set the value of a sticker \fIname\fP to \fIvalue\fP for the object with the
-id \fIuri\fP
-.TP
-\fBsticker delete\fP <type> <uri> [name]
-Delete all the stickers or only one (specified by \fIname\fP) of the object
-with the id \fIuri\fP
-.PP
-
-\fIADMIN-COMMANDS\fP
-.PP
-.PD 0
-.TP
-.PD
-\fBadmin ping\fP
-Pings the lektord daemon, prints \fIOK\fP only if the ping succeeded
-.TP
-\fBadmin kill\fP
-Kill the lektord daemon
-.TP
-\fBadmin restart\fP
-Try to restart the lektord daemon
-.TP
-\fBadmin rescan\fP
-Rescan karas from the filesystem. New karas that are not in the database
-will be added to it. Don't synchronize from the repo
-.TP
-\fBadmin populate\fP
-Force a rescan (without taking into account the timestamp). Can be used
-to bootstrap the database from a filesystem
-.TP
-\fBadmin update\fP
-Update the base from the \fIKurisu\fP repo. Don't scan for new files in
-the filesystem
-.TP
-\fBadmin config\fP
-Prints to \fIstdout\fP the default configuration file
-.PP
-
-.SH "OPTIONS"
-Options can be passed to \fBlkt.old\fP before specifying the command in a
-\fIoption=value\fP format. This is done this way to allow one to make an alias
-of the \fBlkt.old\fP command.
-.PP
-The possible options are the following:
-.PP
-.PD 0
-.TP
-.PD
-\fBhost\fP
-The hostname or the IP of the machine where the \fBlektord\fP daemon
-is running
-.TP
-\fBport\fP
-The port on which the \fBlektord\fP daemon is listening
-.TP
-\fBpwd\fP
-The password to use for commands that require authentification. This is the
-case of most of the \fIadmin\fP commands
-.PP
-
-.SH "QUERIES"
-Queries are a way of listing karas in the database. They are composed of a
-type and the next of the line is the SQL regex that the kara must verify.
-In SQL regexes, the wildcard is the "%" character and the jocker the
-character "_". Queries are case insensitive.
-.PP
-Valid types for a query are the following: \fIid\fP, \fIlang\fP, \fItype\fP,
-\fIcategory\fP, \fIauthor\fP, \fIquery\fP and \fIplaylist\fP.
-.PP
-For the type \fItype\fP, the valid values are the following: \fIOP\fP,
-\fIED\fP, \fIIS\fP, \fIAMV\fP, \fIMV\fP, \fIPV\fP and \fILIVE\fP.
-.PP
-For the type \fIlang\fP, the valid values are the following: \fIjp\fP,
-\fIfr\fP, \fIsp\fP, \fIen\fP, \fIlatin\fP, \fIit\fP, \fIru\fP, \fImulti\fP
-and \fIundefined\fP.
-.PP
-For the \fIcategory\fP type, the valid values are the following:
-\fIvo\fP, \fIva\fP, \fIcdg\fP, \fIamv\fP, \fIvocaloid\fP and \fIautres\fP.
-.PP
-Here are some examples of queries:
-.PP
-.PD 0
-.TP
-.PD
-\fBtype OP\fP
-Select karas that are openings
-.TP
-\fBauthor kubat\fP
-Select karas where the author is "kubat"
-.PP
-
-.SH "EXAMPLES"
-Valid invocations of the \fBlkt.old\fP command are the following:
-.PP
-.PD 0
-.TP
-.PD
-\fBlkt.old host=sakura port=6601 pwd=toto admin restart\fP
-Restart the lektord daemon on the \fIsakura\fP PC. This daemon is listening on
-the port \fI6601\fP and the password of the admin user is \fItoto\fP
-.TP
-\fBlkt.old q a author krocoh\fP
-Add kara that Krocoh has done to the queue
diff --git a/man/lkt.template b/man/lkt.template
index b11343d4c2de761c01472b593c80325f15dadd49..3c3073f304c40b16837344931cf6ebcc26134035 100644
--- a/man/lkt.template
+++ b/man/lkt.template
@@ -196,6 +196,10 @@ to bootstrap the database from a filesystem
 Update the base from the \fIKurisu\fP repo. Don't scan for new files in
 the filesystem
 .TP
+\fBadmin import\fP
+Import favorites from the \fIKurisu\fP repo. Favorites will create playlists on
+the lektor side begening with the @ character
+.TP
 \fBadmin config\fP
 Prints to \fIstdout\fP the default configuration file
 .PP
diff --git a/src/Makefile.am b/src/Makefile.am
index eac0e4cbee317428865ae8093a201f975783beb1..b95770d7d3c592a42eadd389e0c620708c12b9d9 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -84,10 +84,9 @@ EXTRA_DIST = database/disk.sql database/memory.sql
 ## MAIN FILES ##
 ################
 
-bin_PROGRAMS = lektord lkt.old lkt
+bin_PROGRAMS = lektord lkt
 
 ## The lkt client
-lkt_old_SOURCES = main/lkt-old.c base/cmd.c base/common.c
 lkt_SOURCES = main/lkt.c base/cmd.c base/common.c
 
 ## The lektord server
diff --git a/src/Makefile.in b/src/Makefile.in
index 0c7d8c290652282b4d1e4483e64548e4662b3e77..d824d34b88da889e9d0336697d3320b003268696 100644
--- a/src/Makefile.in
+++ b/src/Makefile.in
@@ -99,7 +99,7 @@ host_triplet = @host@
 
 # TODO pour le Kubat du futur: c'est pas beau, trouver un truc pour que ça se fasse tout seul
 @LKT_STATIC_MODULE_TRUE@am__append_8 = module/thread.c
-bin_PROGRAMS = lektord$(EXEEXT) lkt.old$(EXEEXT) lkt$(EXEEXT)
+bin_PROGRAMS = lektord$(EXEEXT) lkt$(EXEEXT)
 subdir = src
 ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
 am__aclocal_m4_deps = $(top_srcdir)/config/m4/libtool.m4 \
@@ -212,10 +212,6 @@ am_lkt_OBJECTS = main/lkt.$(OBJEXT) base/cmd.$(OBJEXT) \
 	base/common.$(OBJEXT)
 lkt_OBJECTS = $(am_lkt_OBJECTS)
 lkt_LDADD = $(LDADD)
-am_lkt_old_OBJECTS = main/lkt-old.$(OBJEXT) base/cmd.$(OBJEXT) \
-	base/common.$(OBJEXT)
-lkt_old_OBJECTS = $(am_lkt_old_OBJECTS)
-lkt_old_LDADD = $(LDADD)
 AM_V_P = $(am__v_P_@AM_V@)
 am__v_P_ = $(am__v_P_@AM_DEFAULT_V@)
 am__v_P_0 = false
@@ -249,8 +245,7 @@ am__depfiles_remade = base/$(DEPDIR)/cmd.Po base/$(DEPDIR)/common.Po \
 	database/$(DEPDIR)/liblektor_la-queue.Plo \
 	database/$(DEPDIR)/liblektor_la-stickers.Plo \
 	database/$(DEPDIR)/liblektor_la-update.Plo \
-	database/$(DEPDIR)/liblektor_la-user.Plo \
-	main/$(DEPDIR)/lkt-old.Po main/$(DEPDIR)/lkt.Po \
+	database/$(DEPDIR)/liblektor_la-user.Plo main/$(DEPDIR)/lkt.Po \
 	main/$(DEPDIR)/server.Po mkv/$(DEPDIR)/liblektor_la-mkv.Plo \
 	mkv/$(DEPDIR)/liblektor_la-utils.Plo \
 	mkv/$(DEPDIR)/liblektor_la-write.Plo \
@@ -282,11 +277,10 @@ am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@)
 am__v_CCLD_0 = @echo "  CCLD    " $@;
 am__v_CCLD_1 = 
 SOURCES = $(liblektor_la_SOURCES) $(liblktmodrepo_la_SOURCES) \
-	$(liblktmodsdl_la_SOURCES) $(lektord_SOURCES) $(lkt_SOURCES) \
-	$(lkt_old_SOURCES)
+	$(liblktmodsdl_la_SOURCES) $(lektord_SOURCES) $(lkt_SOURCES)
 DIST_SOURCES = $(am__liblektor_la_SOURCES_DIST) \
 	$(liblktmodrepo_la_SOURCES) $(liblktmodsdl_la_SOURCES) \
-	$(lektord_SOURCES) $(lkt_SOURCES) $(lkt_old_SOURCES)
+	$(lektord_SOURCES) $(lkt_SOURCES)
 am__can_run_installinfo = \
   case $$AM_UPDATE_INFO_DIR in \
     n|no|NO) false;; \
@@ -483,7 +477,6 @@ liblektor_la_LDFLAGS = -avoid-version -pthread -lsqlite3 \
 @LKT_STATIC_MODULE_TRUE@liblektor_la_LIBADD = liblktmodsdl.la liblktmodrepo.la
 CLEANFILES = database/disk.c database/memory.c
 EXTRA_DIST = database/disk.sql database/memory.sql
-lkt_old_SOURCES = main/lkt-old.c base/cmd.c base/common.c
 lkt_SOURCES = main/lkt.c base/cmd.c base/common.c
 lektord_SOURCES = main/server.c
 lektord_LDADD = liblektor.la
@@ -751,12 +744,6 @@ base/common.$(OBJEXT): base/$(am__dirstamp) \
 lkt$(EXEEXT): $(lkt_OBJECTS) $(lkt_DEPENDENCIES) $(EXTRA_lkt_DEPENDENCIES) 
 	@rm -f lkt$(EXEEXT)
 	$(AM_V_CCLD)$(LINK) $(lkt_OBJECTS) $(lkt_LDADD) $(LIBS)
-main/lkt-old.$(OBJEXT): main/$(am__dirstamp) \
-	main/$(DEPDIR)/$(am__dirstamp)
-
-lkt.old$(EXEEXT): $(lkt_old_OBJECTS) $(lkt_old_DEPENDENCIES) $(EXTRA_lkt_old_DEPENDENCIES) 
-	@rm -f lkt.old$(EXEEXT)
-	$(AM_V_CCLD)$(LINK) $(lkt_old_OBJECTS) $(lkt_old_LDADD) $(LIBS)
 
 mostlyclean-compile:
 	-rm -f *.$(OBJEXT)
@@ -795,7 +782,6 @@ distclean-compile:
 @AMDEP_TRUE@@am__include@ @am__quote@database/$(DEPDIR)/liblektor_la-stickers.Plo@am__quote@ # am--include-marker
 @AMDEP_TRUE@@am__include@ @am__quote@database/$(DEPDIR)/liblektor_la-update.Plo@am__quote@ # am--include-marker
 @AMDEP_TRUE@@am__include@ @am__quote@database/$(DEPDIR)/liblektor_la-user.Plo@am__quote@ # am--include-marker
-@AMDEP_TRUE@@am__include@ @am__quote@main/$(DEPDIR)/lkt-old.Po@am__quote@ # am--include-marker
 @AMDEP_TRUE@@am__include@ @am__quote@main/$(DEPDIR)/lkt.Po@am__quote@ # am--include-marker
 @AMDEP_TRUE@@am__include@ @am__quote@main/$(DEPDIR)/server.Po@am__quote@ # am--include-marker
 @AMDEP_TRUE@@am__include@ @am__quote@mkv/$(DEPDIR)/liblektor_la-mkv.Plo@am__quote@ # am--include-marker
@@ -1217,7 +1203,6 @@ distclean: distclean-am
 	-rm -f database/$(DEPDIR)/liblektor_la-stickers.Plo
 	-rm -f database/$(DEPDIR)/liblektor_la-update.Plo
 	-rm -f database/$(DEPDIR)/liblektor_la-user.Plo
-	-rm -f main/$(DEPDIR)/lkt-old.Po
 	-rm -f main/$(DEPDIR)/lkt.Po
 	-rm -f main/$(DEPDIR)/server.Po
 	-rm -f mkv/$(DEPDIR)/liblektor_la-mkv.Plo
@@ -1296,7 +1281,6 @@ maintainer-clean: maintainer-clean-am
 	-rm -f database/$(DEPDIR)/liblektor_la-stickers.Plo
 	-rm -f database/$(DEPDIR)/liblektor_la-update.Plo
 	-rm -f database/$(DEPDIR)/liblektor_la-user.Plo
-	-rm -f main/$(DEPDIR)/lkt-old.Po
 	-rm -f main/$(DEPDIR)/lkt.Po
 	-rm -f main/$(DEPDIR)/server.Po
 	-rm -f mkv/$(DEPDIR)/liblektor_la-mkv.Plo
diff --git a/src/main/lkt-old.c b/src/main/lkt-old.c
deleted file mode 100644
index f6c0987ca2c0b8398f4edb2abee19296cb914196..0000000000000000000000000000000000000000
--- a/src/main/lkt-old.c
+++ /dev/null
@@ -1,1154 +0,0 @@
-#define _POSIX_C_SOURCE 200809L
-
-#include <lektor/common.h>
-#include <lektor/net.h>
-#include <lektor/cmd.h>
-#include <lektor/config.h>
-
-#include <arpa/inet.h>
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <netinet/in.h>
-#include <errno.h>
-#include <fcntl.h>
-#include <netdb.h>
-#include <stdint.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <strings.h>
-#include <unistd.h>
-#include <signal.h>
-#include <locale.h>
-#include <stdnoreturn.h>
-#include <stdbool.h>
-#include <stdarg.h>
-#include <limits.h>
-
-#define LKT_KEY_VALUE_SEP               ": \n\t\0"
-#define fail_if(cond, msg)              { if (cond) { LOG_ERROR("LKT", "%s", msg); exit(EXIT_FAILURE); } }
-#define fail(msg)                       { LOG_ERROR("LKT", "%s", msg); exit(EXIT_FAILURE); }
-
-#define exit_with_status(sock, buff) {                \
-    read_socket(sock, buff, 2);                       \
-    fail_if(buff[0] != 'O' && buff[1] != 'K', "ACK"); \
-    exit(EXIT_SUCCESS);                               \
-}
-
-/* Type definition. */
-
-typedef struct {
-    const char *host;   /* Serveur host, may be resolved.               */
-    const char *port;   /* Serveur port.                                */
-    const char *pwd;    /* The password for the user.                   */
-    const char **argv;  /* Pointer to the argv from the main function.  */
-    int argc;           /* Argument count of the args.                  */
-} args_t;
-
-/* Global variables. */
-
-static const char *host;
-static const char *port;
-static const char *password;
-static const char *LKT_QUEUE_DEFAULT[] = { "10" };
-
-/* Communication functions and fonction that interact with lektor stuff. */
-
-static int
-lkt_valid_type(const char *type)
-{
-    return (STR_MATCH(type, "query")    ||
-            STR_MATCH(type, "category") ||
-            STR_MATCH(type, "author")   ||
-            STR_MATCH(type, "lang")     ||
-            STR_MATCH(type, "id")       ||
-            STR_MATCH(type, "type")     ||
-            STR_MATCH(type, "playlist"));
-}
-
-static int
-read_socket(FILE *sock, char *buff, size_t max_len)
-{
-    size_t i, len;
-    for (i = 0; i < max_len; ++i) {
-        len = fread(buff + i, sizeof(char), 1, sock);
-        if (buff[i] == '\n' || len != 1)
-            break;
-    }
-    fail_if(len == 0, "Connexion error");
-    return i;
-}
-
-static FILE *
-create_socket(const char *host, const char *port)
-{
-    FILE *socket_desc;
-    struct addrinfo hints, *found;
-    socklen_t sock_len;
-    struct sockaddr sock;
-
-    memset(&hints, 0, sizeof(struct addrinfo));
-    hints.ai_flags = 0;
-    hints.ai_family = AF_INET;
-    hints.ai_socktype = SOCK_STREAM;
-
-    getaddrinfo(host, port, &hints, &found); //  <---- Another assert yeeted because it makes php panic
-
-    sock = *found->ai_addr;
-    sock_len = found->ai_addrlen;
-    freeaddrinfo(found);
-
-    int cx = socket(AF_INET, SOCK_STREAM, 0);
-
-    if (cx <= 0 || connect(cx, &sock, sock_len))
-        exit(EXIT_FAILURE);
-
-    socket_desc = fdopen(cx, "r+");
-    fail_if(!socket_desc, "Failed to connect to lektord");
-    return socket_desc;
-}
-
-static FILE *
-lkt_connect(void)
-{
-    char buff[LKT_MESSAGE_MAX];
-    FILE *sock = create_socket(host, port);
-    read_socket(sock, buff, LKT_MESSAGE_MAX);
-    return sock;
-}
-
-static void
-write_socket(FILE *sock, const char *format, ...)
-{
-    int size;
-    char buff[LKT_MESSAGE_MAX];
-    va_list ap;
-
-    va_start(ap, format);
-    size = vsnprintf(buff, LKT_MESSAGE_MAX - 1, format, ap);
-    buff[LKT_MESSAGE_MAX - 1] = 0;
-
-    if (size < 0)
-        fail("Connexion error");
-
-    if (fwrite(buff, sizeof(char), size, sock) < (unsigned int) size)
-        fail("Connexion error");
-
-    va_end(ap);
-}
-
-noreturn static inline void
-lkt_send_and_exit(const char *buffer, size_t len)
-{
-    write_socket(lkt_connect(), buffer, len);
-    exit(EXIT_SUCCESS);
-}
-
-static char *
-lkt_skip_key(char *buffer)
-{
-    size_t len = strcspn(buffer, LKT_KEY_VALUE_SEP);
-    char *ret = &buffer[len + 1];
-    len = strspn(ret, ": ");
-    return ret + len;
-}
-
-static inline void
-send_cmd_with_uri(FILE *sock, char *cmd, int argc, const char **argv)
-{
-    int i;
-    char buf[LKT_MESSAGE_MAX] = {0};
-    for (i = 1; i < argc - 1; ++i) {
-        strncat(buf, argv[i], LKT_MESSAGE_MAX - 1);
-        strncat(buf, " ", LKT_MESSAGE_MAX - 1);
-    }
-    strncat(buf, argv[i], LKT_MESSAGE_MAX - 1);
-    strncat(buf, "\n", LKT_MESSAGE_MAX - 1);
-    write_socket(sock, "%s %s://%s", cmd, argv[0], buf);
-}
-
-/* Functions implementing options. */
-
-#define just_send_one_arg(func, cmd)                \
-noreturn void func (struct cmd_args *args) {        \
-    fail_if(args->argc != 1, "Invalid argument");   \
-    FILE *sock = lkt_connect();                     \
-    char buff[2];                                   \
-    write_socket(sock, cmd " %s\n", args->argv[0]); \
-    exit_with_status(sock, buff);                   \
-}
-just_send_one_arg(stickers_create__,  "sticker __create")
-just_send_one_arg(stickers_destroy__, "sticker __destroy")
-just_send_one_arg(plt_destroy__,      "rm")
-just_send_one_arg(plt_create__,       "playlistadd")
-just_send_one_arg(queue_dump__,       "__dump")
-#undef just_send_one_arg
-
-#define just_send(func, msg) /* Just send a simple string functions */  \
-    noreturn void func (struct cmd_args *args) {                        \
-        fail_if(args->argc, "This command takes no arguments");         \
-        lkt_send_and_exit(msg, sizeof(msg));                            \
-    }
-just_send(queue_clear__, "clear\n")
-just_send(queue_crop__,  "crop\n")
-just_send(next__,        "next\n")
-just_send(prev__,        "previous\n")
-just_send(stop__,        "stop\n")
-just_send(shuffle__,     "shuffle\nplay\n")
-#undef just_send
-
-noreturn void
-simple_send_with_password__(const char *cmd)
-{
-    if (!password)
-        fail("Password not provided");
-    FILE *sock = lkt_connect();
-    write_socket(sock, "command_list_begin\n");
-    write_socket(sock, "password %s\n", password);
-    write_socket(sock, "%s\n", cmd);
-    write_socket(sock, "command_list_end\n");
-    exit(EXIT_SUCCESS);
-}
-
-noreturn void
-restart__(struct cmd_args *args)
-{
-    if (args->argc != 0)
-        fail("Invalid argument, the previous command takes no arguments");
-    simple_send_with_password__("__restart");
-}
-
-noreturn void
-kill__(struct cmd_args *args)
-{
-    if (args->argc != 0)
-        fail("Invalid argument, the previous command takes no arguments");
-    simple_send_with_password__("kill");
-}
-
-noreturn void
-rescan_or_update__(struct cmd_args *args, const char *cmd)
-{
-    if (!password)
-        fail("Password not provided");
-    FILE *sock = lkt_connect();
-    char buff[LKT_MESSAGE_MAX];
-    int i;
-
-    /* All the db */
-    if (args->argc == 0) {
-        write_socket(sock, "command_list_begin\n");
-        write_socket(sock, "password %s\n", password);
-        write_socket(sock, "%s\n", cmd);
-        write_socket(sock, "command_list_end\n");
-    }
-
-    /* With a query */
-    else {
-        memset(buff, 0, LKT_MESSAGE_MAX * sizeof(char));
-        for (i = 0; i < args->argc; ++i)
-            strncat(buff, args->argv[i], LKT_MESSAGE_MAX - 1);
-        write_socket(sock, "command_list_begin\n");
-        write_socket(sock, "password %s\n", password);
-        write_socket(sock, "%s %s\n", cmd, buff);
-        write_socket(sock, "command_list_end\n");
-    }
-
-    exit(EXIT_SUCCESS);
-}
-
-noreturn void
-rescan__(struct cmd_args *args)
-{
-    rescan_or_update__(args, "rescan");
-}
-
-noreturn void
-update__(struct cmd_args *args)
-{
-    rescan_or_update__(args, "update");
-}
-
-noreturn void
-populate__(struct cmd_args *args)
-{
-    rescan_or_update__(args, "__rescan");
-}
-
-noreturn void
-queue_replace__(struct cmd_args *args)
-{
-    if (args->argc != 1)
-        fail("Invalid argument");
-    bool play = false;
-    char buff[LKT_MESSAGE_MAX];
-    FILE *sock = lkt_connect();
-
-    for (;;) {
-        memset(buff, 0, LKT_MESSAGE_MAX * sizeof(char));
-        read_socket(sock, buff, LKT_MESSAGE_MAX - 1);
-        size_t len = strcspn(buff, LKT_KEY_VALUE_SEP);
-
-        if (STR_NMATCH(buff, "state", len)) {
-            char *it = lkt_skip_key(buff);
-            play = STR_NMATCH(it, "play", 4);
-            break;
-        }
-
-        if (STR_NMATCH(buff, "OK", 2))
-            break;
-        else if (STR_NMATCH(buff, "ACK", 3))
-            fail("ACK");
-    }
-
-    fclose(sock);
-    sock = lkt_connect();
-    write_socket(sock, "command_list_begin\n");
-    write_socket(sock, "clear\n");
-    write_socket(sock, "add playlist://%s\n", args->argv[0]);
-    if (play)
-        write_socket(sock, "play\n");
-    write_socket(sock, "command_list_end\n");
-    exit_with_status(sock, buff);
-}
-
-noreturn void
-config__(struct cmd_args *args)
-{
-    int ret = EXIT_SUCCESS;
-    if (args->argc == 0)
-        fwrite(lkt_default_config_file, sizeof(char),
-               strlen(lkt_default_config_file), stdout);
-    exit(ret);
-}
-
-noreturn void
-play__(struct cmd_args *args)
-{
-    if (args->argc > 1)
-        fail("Invalid argument");
-
-    int pos = 0;
-    if (args->argc != 0)
-        pos = atoi(args->argv[0]);
-
-    static const char status__[]        = "status\n";
-    static const char cmd_play__[]      = "play\n";
-    static const char cmd_play_from__[] = "play %d\n";
-    static const char cmd_pause__[]     = "pause\n";
-
-    char buff[LKT_MESSAGE_MAX];
-    FILE *sock = lkt_connect();
-    write_socket(sock, status__);
-
-    for (;;) {
-        memset(buff, 0, LKT_MESSAGE_MAX * sizeof(char));
-        read_socket(sock, buff, LKT_MESSAGE_MAX - 1);
-        size_t len = strcspn(buff, LKT_KEY_VALUE_SEP);
-
-        if (STR_NMATCH(buff, "state", len)) {
-            fclose(sock);
-
-            if (STR_NMATCH(lkt_skip_key(buff), "stop", 4)) {
-                if (!pos)
-                    lkt_send_and_exit(cmd_play__, sizeof(cmd_play__));  /* In bytes. */
-                else {
-                    write_socket(lkt_connect(), cmd_play_from__, pos);
-                    exit(EXIT_SUCCESS);
-                }
-            }
-
-            else
-                lkt_send_and_exit(cmd_pause__, sizeof(cmd_pause__));    /* In bytes. */
-
-            exit(EXIT_FAILURE);
-        }
-    }
-}
-
-noreturn void
-ping__(struct cmd_args *args)
-{
-    if (args->argc != 0)
-        fail("Invalid argument, the ping command takes no arguments");
-    char buff[6] = {0};
-    FILE *sock = lkt_connect();
-    write_socket(sock, "ping\n");
-    read_socket(sock, buff, 6 * sizeof(char));
-    if (!STR_NMATCH(buff, "OK", 2))
-        fail("ACK");
-    exit(write(1, "OK\n", sizeof("OK\n")) == 0);
-}
-
-noreturn void
-current__(struct cmd_args *args)
-{
-    if (args->argc != 0)
-        fail("Invalid argument, the current command takes no arguments");
-
-    static const char current_song__[] = "currentsong\n";
-    char buff[LKT_MESSAGE_MAX];
-
-    char *mem = NULL;
-    FILE *sock = lkt_connect();
-
-    write_socket(sock, current_song__);
-    assert(mem = calloc(6 * LKT_MESSAGE_MAX, sizeof(char)));
-    assert(memset(mem, 0, 6 * LKT_MESSAGE_MAX * sizeof(char)));
-
-    char *const title    = &mem[0];
-    char *const author   = &mem[LKT_MESSAGE_MAX];
-    char *const source   = &mem[2 * LKT_MESSAGE_MAX];
-    char *const type     = &mem[3 * LKT_MESSAGE_MAX];
-    char *const category = &mem[4 * LKT_MESSAGE_MAX];
-    char *const language = &mem[5 * LKT_MESSAGE_MAX];
-
-    for (;;) {
-        memset(buff, 0, LKT_MESSAGE_MAX * sizeof(char));
-        read_socket(sock, buff, LKT_MESSAGE_MAX - 1);
-
-        const size_t len = strcspn(buff, LKT_KEY_VALUE_SEP);
-        char *value = lkt_skip_key(buff);
-        const size_t value_size = strcspn(value, "\n\0") * sizeof(char);
-
-        if (STR_NMATCH("title", buff, len))
-            assert(memcpy(title, value, value_size));
-
-        if (STR_NMATCH("author", buff, len))
-            assert(memcpy(author, value, value_size));
-
-        if (STR_NMATCH("source", buff, len))
-            assert(memcpy(source, value, value_size));
-
-        if (STR_NMATCH("type", buff, len))
-            assert(memcpy(type, value, value_size));
-
-        if (STR_NMATCH("language", buff, len))
-            assert(memcpy(language, value, value_size));
-
-        if (STR_NMATCH("category", buff, len))
-            assert(memcpy(category, value, value_size));
-
-        /* At this point every key has been parsed. */
-        if (STR_NMATCH(buff, "OK", 2))
-            goto ok;
-        else if (STR_NMATCH(buff, "ACK", 3))
-            exit(EXIT_FAILURE);
-    }
-
-ok:
-    if (language[0])
-        printf("%s - %s / %s - %s - %s [ %s ]\n",
-               category, language, source, type, title, author);
-    else
-        printf("%s / %s - %s - %s [ %s ]\n",
-               category, source, type, title, author);
-
-    exit(EXIT_SUCCESS);
-}
-
-noreturn void
-queue_pop__(struct cmd_args *args)
-{
-    fail_if(args->argc, "Invalid argument");
-    int songid = 0;
-    char buff[LKT_MESSAGE_MAX];
-    FILE *sock = lkt_connect();
-
-    /* Get lektor's status. */
-    write_socket(sock, "status\n");
-
-#define assign_int(str, var) if (STR_NMATCH(buff, str, len)) { var = (atoi(lkt_skip_key(buff))); continue; }
-    for (;;) {
-        memset(buff, 0, LKT_MESSAGE_MAX * sizeof(char));
-        read_socket(sock, buff, LKT_MESSAGE_MAX - 1);
-        size_t len = strcspn(buff, LKT_KEY_VALUE_SEP);
-        assign_int("songid", songid)
-
-        /* At this point every key has been parsed. */
-        if (STR_NMATCH(buff, "OK", 2))
-            break;
-        else if (STR_NMATCH(buff, "ACK", 3))
-            exit(EXIT_FAILURE);
-    }
-#undef assign_int
-
-    fclose(sock);
-    sock = lkt_connect();
-    if (!songid)
-        exit(EXIT_FAILURE);
-    write_socket(sock, "next\ndeleteid %d\n", songid);
-    exit_with_status(sock, buff);
-}
-
-noreturn void
-status__(struct cmd_args *args)
-{
-    if (args->argc != 0)
-        fail("Invalid argument, the status command takes no arguments");
-
-    static const char *const status_str__ = "status\n";
-    static const char *const stats_str__  = "stats\n";
-
-    char buff[LKT_MESSAGE_MAX];
-    char flags[24];
-
-    bool play = false, stopped = true, is_updating = false;
-    int time_pos = 0, time_duration = 0, song_index = 0, plt_len = 0, ret = EXIT_FAILURE, it = 0;
-    size_t len;
-    time_t update_ts = 0;
-
-    memset(flags, 0, 24 * sizeof(char));
-    FILE *sock = lkt_connect();
-
-#define assign_flag(str, f)  if (STR_NMATCH(buff, str, len) && (atoi(lkt_skip_key(buff)) == 1)) { flags[it++] = f; continue; }
-#define assign_int(str, var) if (STR_NMATCH(buff, str, len)) { var = (strtoll(lkt_skip_key(buff), NULL, 0)); continue; }
-#define check_end()                                     \
-    if (STR_NMATCH(buff, "OK", 2)) break;               \
-    else if (STR_NMATCH(buff, "ACK", 3)) goto error;
-
-    /* Get lektor's status */
-    write_socket(sock, status_str__);
-    for (;;) {
-        len       = read_socket(sock, buff, LKT_MESSAGE_MAX - 1);
-        buff[len] = '\0';
-        len       = strcspn(buff, LKT_KEY_VALUE_SEP);
-
-        if (STR_NMATCH(buff, "state", len)) {
-            char *it = lkt_skip_key(buff);
-            play     = STR_NMATCH(it, "play", 4);
-            stopped  = STR_NMATCH(it, "stop", 4);
-            continue;
-        }
-
-        assign_flag("random",  'r')
-        assign_flag("repeat",  'l')
-        assign_flag("single",  's')
-        assign_flag("consume", 'c')
-
-        assign_int("elapsed",        time_pos)
-        assign_int("duration",       time_duration)
-        assign_int("song",           song_index)
-        assign_int("playlistlength", plt_len)
-
-        check_end()
-    }
-
-    /* Get lektor's stats */
-    write_socket(sock, stats_str__);
-    for (;;) {
-        len       = read_socket(sock, buff, LKT_MESSAGE_MAX - 1);
-        buff[len] = '\0';
-        len       = strcspn(buff, LKT_KEY_VALUE_SEP);
-
-        assign_int("__is_updating", is_updating)
-        assign_int("db_update",     update_ts)
-
-        check_end()
-    }
-
-    /* End of communication */
-    fclose(sock);
-
-#undef assign_flag
-#undef assign_int
-#undef check_end
-
-    struct tm *p_tm = localtime(&update_ts);
-    len = strftime(buff, LKT_MESSAGE_MAX - 1, "%F %H:%M:%S", p_tm);
-    buff[len] = '\0';
-
-    int  pla_m = time_pos / 60;
-    char pla_s = time_pos % 60;
-    int  dur_m = time_duration / 60;
-    char dur_s = time_duration % 60;
-
-    printf("Lektor: %s\n"
-           "Queue: #%d/%d\n"
-           "Playback: %d:%d/%d:%d\n"
-           "Flags: %s\n"
-           "%s: %s\n",
-           play ? "play" : "stopped",
-           song_index + 1, plt_len,
-           pla_m, pla_s, dur_m, dur_s,
-           flags[0] ? flags : "(none)",
-           is_updating ? "Updating" : "Last update", buff);
-
-    /* If there is a kara loaded in mpv, get this kara. */
-    if (!stopped) {
-        printf("Kara: ");
-        current__(args);
-    }
-
-    ret = EXIT_SUCCESS;
-error:
-    exit(ret);
-}
-
-noreturn void
-queue_delete__(struct cmd_args *args)
-{
-    if (args->argc != 1)
-        fail("Invalid argument, need onlt one argument: queue delete <id>");
-
-    static const char *cmd_id__ = "deleteid %d\n";
-    int dumy = 0;
-    FILE *sock = lkt_connect();
-    char buff[3];
-
-    sscanf(args->argv[0], "%d", &dumy);
-    if (dumy != 0) {
-        write_socket(sock, cmd_id__, dumy);
-        exit_with_status(sock, buff);
-    }
-
-    fail("Invalid argument");
-}
-
-noreturn void
-queue_add__(struct cmd_args *args)
-{
-    char buff[3];
-    fail_if(args->argc < 1, "Invalid arguments");
-    fail_if(!lkt_valid_type(args->argv[0]), "Invalid query type");
-    FILE *sock = lkt_connect();
-    send_cmd_with_uri(sock, "add", args->argc, args->argv);
-    exit_with_status(sock, buff);
-}
-
-noreturn void
-queue_insert__(struct cmd_args *args)
-{
-    char buff[3];
-    fail_if(args->argc < 1, "Invalid arguments");
-    fail_if(!lkt_valid_type(args->argv[0]), "Invalid query type");
-    FILE *sock = lkt_connect();
-    send_cmd_with_uri(sock, "__insert", args->argc, args->argv);
-    exit_with_status(sock, buff);
-}
-
-noreturn void
-queue_seek__(struct cmd_args *args)
-{
-    fail_if(args->argc != 1, "The seek command needs one argument: queue seek <id>");
-
-    char *endptr, buf[3];
-    long id = strtol(args->argv[0], &endptr, 0);
-
-    if ((errno == ERANGE && (id == LONG_MAX || id == LONG_MIN)) ||
-        (errno != 0 && id == 0)                                 ||
-        (endptr == args->argv[0]))
-        fail("Invalid argument, not an integer");
-
-    if (*endptr != '\0')
-        fail("Invalid argument, must be only one integer");
-
-    FILE *sock = lkt_connect();
-    write_socket(sock, "playid %ld\n", id);
-    exit_with_status(sock, buf);
-}
-
-noreturn void
-queue_pos__(struct cmd_args *args)
-{
-    char buff[LKT_MESSAGE_MAX], *endptr;
-
-    if (args->argc != 1)
-        fail("Invalid argument for the pos command: queue pos <arg> where arg is a position or a range");
-
-    long continuation = 0, up = 0;
-
-    continuation = strtol(args->argv[0], &endptr, 0);
-    if ((errno == ERANGE && (continuation == LONG_MAX || continuation == LONG_MIN)) || (errno != 0
-            && continuation == 0) || (endptr == args->argv[0]))
-        fail("Invalid argument, not an integer: queue pos <arg> where arg is a position or a range");
-
-    if (*endptr != '\0') {
-        /* A range */
-        if (*(++endptr) == '\0')
-            fail("Invalid argument, a range is two integers");
-        up = atoi(endptr);
-    }
-
-
-    FILE *sock = NULL;
-redo:
-    sock = lkt_connect();
-    if (up != 0)
-        write_socket(sock, "playlist %d:%d\n", continuation, up);
-    else
-        write_socket(sock, "playlist %d\n", continuation);
-
-    for (;;) {
-        memset(buff, 0, LKT_MESSAGE_MAX * sizeof(char));
-        read_socket(sock, buff, LKT_MESSAGE_MAX - 1);
-
-        if (STR_NMATCH(buff, "continue:", strlen("continue:"))) {
-            continuation = atoi(lkt_skip_key(buff));
-            if (continuation > 0) {
-                fclose(sock);
-                goto redo;
-            }
-        }
-
-        if (STR_NMATCH(buff, "OK", 2))
-            exit(EXIT_SUCCESS);
-        else if (STR_NMATCH(buff, "ACK", 3))
-            exit(EXIT_FAILURE);
-
-        fprintf(stdout, "%s", buff);
-    }
-}
-
-noreturn void
-queue_list__(struct cmd_args *args)
-{
-    char buff[LKT_MESSAGE_MAX], *endptr;
-    FILE *sock = NULL;
-    long continuation = 0, song_index = 1;
-
-    /* Arguments stuff. */
-
-    if (args->argc == 0)
-        args->argv = LKT_QUEUE_DEFAULT;
-    else if (args->argc != 1)
-        fail("Invalid argument: queue <count?>");
-
-    continuation = strtol(args->argv[0], &endptr, 0);
-    if ((errno == ERANGE && (continuation == LONG_MAX || continuation == LONG_MIN)) || (errno != 0
-            && continuation == 0) || (endptr == args->argv[0]))
-        fail("Invalid argument, not an integer");
-
-    if (*endptr != '\0')
-        fail("Invalid argument");
-
-    /* Get the current pos to get limits for the playlist command. */
-
-    sock = lkt_connect();
-    write_socket(sock, "status\n");
-
-#define assign_int(str, var) if (STR_NMATCH(buff, str, len)) { var = (atoi(lkt_skip_key(buff))); continue; }
-    for (;;) {
-        memset(buff, 0, LKT_MESSAGE_MAX * sizeof(char));
-        read_socket(sock, buff, LKT_MESSAGE_MAX - 1);
-        size_t len = strcspn(buff, LKT_KEY_VALUE_SEP);
-        assign_int("song", song_index);
-
-        /* At this point every key has been parsed. */
-        if (STR_NMATCH(buff, "OK", 2))
-            break;
-        else if (STR_NMATCH(buff, "ACK", 3))
-            exit(EXIT_FAILURE);
-    }
-#undef assign_int
-    fclose(sock);
-
-    /* Get the content of the queue. */
-
-    continuation = labs(continuation);
-    song_index = MAX(song_index + 1, 1);
-    safe_snprintf(buff, LKT_MESSAGE_MAX, "%ld:%ld", song_index, song_index + continuation - 1);
-    args->argc = 1;
-    args->argv[0] = buff;
-    queue_pos__(args);
-}
-
-/* Functions implementing options, but for for playlists. */
-
-noreturn void
-plt_add__(struct cmd_args *args)
-{
-    char buff[2];
-    FILE *sock = lkt_connect();
-    fail_if(args->argc < 3,
-            "Invalid argument, need at least three arguments: plt add <plt> <query>");
-    fail_if(!lkt_valid_type(args->argv[1]), "Invalid argument, type for the query is invalid");
-
-    int i;
-    char buf[LKT_MESSAGE_MAX] = {0};
-    for (i = 2; i < args->argc - 1; ++i) {
-        strncat(buf, args->argv[i], LKT_MESSAGE_MAX - 1);
-        strncat(buf, " ", LKT_MESSAGE_MAX - 1);
-    }
-    strncat(buf, args->argv[i], LKT_MESSAGE_MAX - 1);
-    strncat(buf, "\n", LKT_MESSAGE_MAX - 1);
-    write_socket(sock, "playlistadd %s %s://%s", args->argv[0], args->argv[1], buf);
-
-    exit_with_status(sock, buff);
-}
-
-noreturn void
-plt_delete__(struct cmd_args *args)
-{
-    FILE *sock = lkt_connect();
-    char buff[2];
-    char cmd[128];
-    fail_if(args->argc < 3, "Invalid argument");
-    snprintf(cmd, 128 - 1, "playlistdelete %s", args->argv[0]);
-    cmd[127] = '\0';
-    send_cmd_with_uri(sock, cmd, args->argc - 1, &args->argv[1]);
-    exit_with_status(sock, buff);
-}
-
-noreturn void
-stickers_get__(struct cmd_args *args)
-{
-    char buff[LKT_MESSAGE_MAX];
-    FILE *sock;
-    if (args->argc == 2)
-        write_socket(sock = lkt_connect(), "sticker get %s %s\n", args->argv[0], args->argv[1]);
-    else if (args->argc == 3)
-        write_socket(sock = lkt_connect(), "sticker get %s %s %s\n", args->argv[0], args->argv[1],
-                     args->argv[2]);
-    else if (args->argc == 5) {
-        const char *op = args->argv[3];
-        op = op[0] == 'e' ? "=" : op[0] == 'l' ? "<" : op[0] == 'g' ? ">" : NULL;
-        fail_if(!op, "Invalid argument");
-        write_socket(sock = lkt_connect(), "sticker get %s %s %s %s %s\n", args->argv[0],
-                     args->argv[1], args->argv[2], op, args->argv[4]);
-    } else
-        fail("Invalid argument");
-
-    for (;;) {
-        memset(buff, 0, LKT_MESSAGE_MAX * sizeof(char));
-        read_socket(sock, buff, LKT_MESSAGE_MAX - 1);
-        if (STR_NMATCH(buff, "OK", 2))
-            exit(EXIT_SUCCESS);
-        else if (STR_NMATCH(buff, "ACK", 3))
-            exit(EXIT_FAILURE);
-        fprintf(stdout, "%s", buff);
-    }
-}
-
-noreturn void
-stickers_set__(struct cmd_args *args)
-{
-    fail_if(args->argc != 4, "Invalid argument");
-    FILE *sock = lkt_connect();
-    char buff[2];
-    write_socket(sock, "sticker set %s %s %s %s\n", args->argv[0],
-                 args->argv[1], args->argv[2], args->argv[3]);
-    exit_with_status(sock, buff);
-}
-
-noreturn void
-stickers_delete__(struct cmd_args *args)
-{
-    FILE *sock;
-    char buff[2];
-    if (args->argc == 2)
-        write_socket(sock = lkt_connect(), "sticker delete %s %s",
-                     args->argv[0], args->argv[1]);
-    else if (args->argc == 3)
-        write_socket(sock = lkt_connect(), "sticker delete %s %s %s",
-                     args->argv[0], args->argv[1], args->argv[2]);
-    else
-        fail("Invalid argument");
-    exit_with_status(sock, buff);
-}
-
-/* Search functions. */
-
-noreturn void
-__continuation_calls(const char *cmd)
-{
-    char buff[LKT_MESSAGE_MAX];
-    int continuation = 0;
-    FILE *sock = NULL;
-redo:
-    sock = lkt_connect();
-
-    write_socket(sock, "%d %s\n", continuation, cmd);
-    for (;;) {
-        memset(buff, 0, LKT_MESSAGE_MAX * sizeof(char));
-        read_socket(sock, buff, LKT_MESSAGE_MAX - 1);
-
-        if (STR_NMATCH(buff, "continue:", strlen("continue:"))) {
-            continuation = atoi(lkt_skip_key(buff));
-            fclose(sock);
-            goto redo;
-        }
-
-        if (STR_NMATCH(buff, "OK", 2))
-            exit(EXIT_SUCCESS);
-        else if (STR_NMATCH(buff, "ACK", 3))
-            exit(EXIT_FAILURE);
-
-        fprintf(stdout, "%s", buff);
-    }
-}
-
-noreturn void
-list_plt__(struct cmd_args *args)
-{
-    fail_if(args->argc != 0, "Invalid argument number");
-    __continuation_calls("listplaylists");
-}
-
-noreturn void
-list_plt_content__(struct cmd_args *args)
-{
-    fail_if(args->argc != 1, "Invalid argument number");
-    char buff[LKT_MESSAGE_MAX];
-    safe_snprintf(buff, LKT_MESSAGE_MAX, "listplaylist %s", args->argv[0]);
-    __continuation_calls(buff);
-    exit(EXIT_FAILURE);
-}
-
-noreturn void
-search_with_cmd__(struct cmd_args *args, const char *cmd)
-{
-    fail_if(args->argc < 2,                 "Invalid number of arguments");
-    fail_if(!lkt_valid_type(args->argv[0]), "Invalid type for the query");
-
-    char buff[LKT_MESSAGE_MAX];
-    int continuation = 0, i;
-    FILE *sock = NULL;
-redo:
-    sock = lkt_connect();
-
-    write_socket(sock, "%d %s %s://", continuation, cmd, args->argv[0]);
-    for (i = 1; i < args->argc - 1; ++i)
-        write_socket(sock, "%s ", args->argv[i]);
-    write_socket(sock, "%s\n", args->argv[i]);
-
-    for (;;) {
-        memset(buff, 0, LKT_MESSAGE_MAX * sizeof(char));
-        read_socket(sock, buff, LKT_MESSAGE_MAX - 1);
-
-        if (STR_NMATCH(buff, "continue:", strlen("continue:"))) {
-            continuation = atoi(lkt_skip_key(buff));
-            fclose(sock);
-            goto redo;
-        }
-
-        if (STR_NMATCH(buff, "OK", 2))
-            exit(EXIT_SUCCESS);
-        else if (STR_NMATCH(buff, "ACK", 3))
-            exit(EXIT_FAILURE);
-
-        fprintf(stdout, "%s", buff);
-    }
-}
-
-noreturn void
-search_get__(struct cmd_args *args)
-{
-    fail_if(args->argc != 1, "Invalid number of arguments");
-    fail_if(!strtol(args->argv[0], NULL, 0), "Invalid id");
-    char buff[LKT_MESSAGE_MAX];
-    FILE *sock = lkt_connect();
-
-    write_socket(sock, "find %s\n", args->argv[0]);
-    for (;;) {
-        memset(buff, 0, LKT_MESSAGE_MAX * sizeof(char));
-        read_socket(sock, buff, LKT_MESSAGE_MAX - 1);
-        if (STR_NMATCH(buff, "OK", 2))
-            exit(EXIT_SUCCESS);
-        else if (STR_NMATCH(buff, "ACK", 3))
-            exit(EXIT_FAILURE);
-        (void) write(1, buff, strlen(buff));
-    }
-}
-
-noreturn void
-search_plt__(struct cmd_args *args)
-{
-    if (args->argc == 0)
-        list_plt__(args);
-    if (args->argc == 1)
-        list_plt_content__(args);
-
-    fail_if(args->argc < 3, "Invalid number of arguments");
-    fail_if(!lkt_valid_type(args->argv[1]), "Invalid type for query");
-    char buff[LKT_MESSAGE_MAX];
-    int continuation = 0, i;
-    FILE *sock = NULL;
-redo:
-    sock = lkt_connect();
-
-    write_socket(sock, "%d listplaylistinfo %s %s://", continuation,
-                 args->argv[0], args->argv[1]);
-    for (i = 2; i < args->argc - 1; ++i)
-        write_socket(sock, "%s ", args->argv[i]);
-    write_socket(sock, "%s\n", args->argv[i]);
-
-    for (;;) {
-        memset(buff, 0, LKT_MESSAGE_MAX * sizeof(char));
-        read_socket(sock, buff, LKT_MESSAGE_MAX - 1);
-
-        if (STR_NMATCH(buff, "continue:", strlen("continue:"))) {
-            continuation = atoi(lkt_skip_key(buff));
-            fclose(sock);
-            goto redo;
-        }
-
-        if (STR_NMATCH(buff, "OK", 2))
-            exit(EXIT_SUCCESS);
-        else if (STR_NMATCH(buff, "ACK", 3))
-            exit(EXIT_FAILURE);
-
-        fprintf(stdout, "%s", buff);
-    }
-}
-
-#define search_with_cmd(func, cmd) /* I don't want to write always the same things */ \
-    noreturn void func (struct cmd_args *args) { search_with_cmd__(args, #cmd); }
-search_with_cmd(search_db__,     search)
-search_with_cmd(search_count__,  count)
-search_with_cmd(search_queue__,  playlistfind)
-#undef search_with_cmd
-
-/* Parsing stuff. */
-
-static struct cmd_opt options_queue[] = {
-    { .name = "insert",     .call = queue_insert__  },
-    { .name = "pos",        .call = queue_pos__     },
-    { .name = "pop",        .call = queue_pop__     },
-    { .name = "add",        .call = queue_add__     },
-    { .name = "seek",       .call = queue_seek__    },
-    { .name = "delete",     .call = queue_delete__  },
-    { .name = "clear",      .call = queue_clear__   },
-    { .name = "crop",       .call = queue_crop__    },
-    { .name = "replace",    .call = queue_replace__ },
-    { .name = "dump",       .call = queue_dump__    },
-    CMD_OPT_DEFAULT(queue_list__),
-};
-
-static struct cmd_opt options_plt[] = {
-    { .name = "add",        .call = plt_add__     },
-    { .name = "delete",     .call = plt_delete__  },
-    { .name = "destroy",    .call = plt_destroy__ },
-    { .name = "create",     .call = plt_create__  },
-    { .name = "list",       .call = search_plt__  },
-    CMD_OPT_NULL,
-};
-
-static struct cmd_opt options_search[] = {
-    { .name = "database",   .call = search_db__     },
-    { .name = "get",        .call = search_get__    },
-    { .name = "plt",        .call = search_plt__    },
-    { .name = "count",      .call = search_count__  },
-    { .name = "queue",      .call = search_queue__  },
-    CMD_OPT_NULL,
-};
-
-static struct cmd_opt options_admin[] = {
-    { .name = "ping",       .call = ping__     },
-    { .name = "kill",       .call = kill__     },
-    { .name = "restart",    .call = restart__  },
-    { .name = "rescan",     .call = rescan__   },
-    { .name = "update",     .call = update__   },
-    { .name = "populate",   .call = populate__ },
-    { .name = "config",     .call = config__   },
-    CMD_OPT_NULL,
-};
-
-static struct cmd_opt options_stickers[] = {
-    { .name = "get",        .call = stickers_get__      },
-    { .name = "set",        .call = stickers_set__      },
-    { .name = "delete",     .call = stickers_delete__   },
-    { .name = "create",     .call = stickers_create__   },
-    { .name = "destroy",    .call = stickers_destroy__  },
-    CMD_OPT_NULL,
-};
-
-#define sub_command(name) /* Create sub-commands here */                            \
-    noreturn void name ## __(struct cmd_args *args) {                               \
-        fail_if(!args->argc, "Invalid command, specify a sub command for " #name);  \
-        cmd_parse(options_ ## name, args->argc, args->argv);                        \
-    }
-sub_command(stickers)
-sub_command(search)
-sub_command(plt)
-sub_command(admin)
-
-noreturn void
-queue__(struct cmd_args *args)
-{
-    if (args->argc == 0)
-        queue_list__(args);
-    cmd_parse(options_queue, args->argc, args->argv);
-}
-#undef sub_command
-
-static struct cmd_opt options_[] = {
-    { .name = "current",  .call = current__  },
-    { .name = "play",     .call = play__     },
-    { .name = "next",     .call = next__     },
-    { .name = "previous", .call = prev__     },
-    { .name = "queue",    .call = queue__    },
-    { .name = "shuffle",  .call = shuffle__  },
-    { .name = "status",   .call = status__   },
-    { .name = "stop",     .call = stop__     },
-    { .name = "plt",      .call = plt__      },
-    { .name = "search",   .call = search__   },
-    { .name = "admin",    .call = admin__    },
-    { .name = "stickers", .call = stickers__ },
-    CMD_OPT_NULL,
-};
-
-/* The sigpipe function, if SIGPIPE signal is sent. */
-
-static void
-sigpipe__(int sig)
-{
-    LOG_ERROR("GENERAL", "Exit because of signal sigpipe (%d)", sig);
-    exit(EXIT_FAILURE);
-}
-
-/* Functions declarations. */
-
-static void
-parse_args(args_t *args, int argc, const char **argv)
-{
-    int i, got = 0;
-    size_t len;
-
-    for (i = 1; i < argc && i < 3; ++i) {
-        len = strcspn(argv[i], "=");
-
-        if (STR_NMATCH("host", argv[i], len)) {
-            args->host = (argv[i] + len + 1);
-            ++got;
-        }
-
-        else if (STR_NMATCH("port", argv[i], len)) {
-            args->port = (argv[i] + len + 1);
-            ++got;
-        }
-
-        else if (STR_NMATCH("pwd", argv[i], len)) {
-            args->pwd = (argv[i] + len + 1);
-            ++got;
-        }
-    }
-
-    args->argv = &argv[got + 1];
-    args->argc = argc - (got + 1);
-}
-
-int
-main(int argc, const char **argv)
-{
-    __log_level = ERROR;
-    executable_name = "lkt";
-    assert(NULL != setlocale(LC_ALL, "en_US.UTF-8"));   /* BECAUSE! */
-    if (signal(SIGPIPE, sigpipe__)) {
-        // LOG_ERROR("SYS", "%s", "Failed to install handler for SIGPIPE signal");
-    }
-
-    args_t args = {
-        .host = "localhost",
-        .port = "6600",
-    };
-
-    parse_args(&args, argc, argv);
-
-    host     = args.host;
-    port     = args.port;
-    password = args.pwd;
-
-    /* Communication with lektor. */
-    cmd_parse(options_, args.argc, args.argv);
-}
diff --git a/src/main/lkt.c b/src/main/lkt.c
index ccb02b2ae7f3c800883e8e6d6393323efa0c646b..5edcc32dfb5c191d7dd241627abb2ba340827105 100644
--- a/src/main/lkt.c
+++ b/src/main/lkt.c
@@ -355,6 +355,12 @@ update__(struct cmd_args *args)
     rescan_or_update__(args, "update");
 }
 
+noreturn void
+import__(struct cmd_args *args)
+{
+    rescan_or_update__(args, "import");
+}
+
 noreturn void
 populate__(struct cmd_args *args)
 {
@@ -1120,6 +1126,7 @@ static struct cmd_opt options_admin[] = {
     { .name = "update",     .call = update__   },
     { .name = "populate",   .call = populate__ },
     { .name = "config",     .call = config__   },
+    { .name = "import",     .call = import__   },
     CMD_OPT_NULL,
 };