In this post, I'm writing about one of my favorite projects out there, the CLI Assistant. As the name implies, it's a personal assistant that works in a terminal emulator window. It's inspired from the assistants made from corporations like Apple and Google, and it's an attempt to make a simple, free and open source assistant that functions in a similar manner, without the unwanted features proprietary software has.
Back in early September of 2020, I decided to mess with my hackintosh installation, and I decided to look at what the system and its preinstalled utilities could offer. One of the preinstalled applications is the voice assistant, Siri, which is used in all of Apple's operating systems, both on its phones and computers. So, I tested it and asked about various things, just for fun. Later, I decided to disable the voice input, just using my keyboard for input. While I was using the keyboard input, I had an idea.
"What if I tried to make a simple version of this program for Linux? I don't know many programs on Linux that do something similar to that."
Then, I booted back to Linux again and started experimenting with some code, which eventually would be the base for the program.
I started almost immediately to mess with code to make this idea possible. I decided to write it in C, because this is the language I'm most familiar with, and it's a simple language in general. Of course, a project like this can be a bit challenging, especially when you aren't experienced enough with the language.
Something I wanted to do, was to find a way to compare the input in a way that I would type something like "What time is it?", and the program would recognize
time as a keyword. After reading through C documentation (which is usually easy to find on a Linux system) I found that in order to make that possible, I had to use the
strstr() function. This function can locate a part of a string, from another one. That's exactly what I needed for my program.
To make it work as intended, for each command I had to compare two strings; the user input and the keyword of the command, which I wrote to have a constant value. Because of how
strstr() works, I had to create an empty string (which I named
cmdcmp, from the words "command compare") that's used as a pointer. By using the "if" statement, I added a couple of checks. The first one checks if the keyword value exists in the input (command) value, and the output would point to where the string starts if it's true. The second check is to see if
cmdcmp is equal to the keyword value that was set in the code. If both are true, then it runs the function for that command.
To make it seem less confusing, here's the line of the code for this, with the weather command as an example:
if ((*cmdcmp = strstr(command, weatherCommand)) && (*cmdcmp = weatherCommand))
Something that you may notice if you read the source code, is that I use the
system() function in most of the commands, as well as for the voice output, which works with
espeak-ng. The reason for using this function is to avoid writing unnecessary code and use the utilities that usually exist in the systems the program is targeted to work on.
The first public version of the program was uploaded on GitHub on the 8th of September 2020, as a proof of concept. After I finished the code, I wrote the documentation for it on the
README.md file, with compilation instructions and an explanation on how the program works. Good documentation is useful to make the program easier to understand for those who are interested to contribute to it, as well for the developer who wrote it, in order to fix any issues in the source code in the future.
On the 11th of April 2021, I updated the project. One of the changes was to include a makefile to make the program easier to install, changing the flags without editing the code manually. Some other changes was the rename of the C file from
assistant.c and some minor changes in the code.
Despite the slow updates of the project, it isn't dead. I have been working on an update for some time, but I need some time to finish it. I have limited free time, and I'm working on various things at the same time.
One of the changes I'm working on, is a better user interface. As it's made to run on a terminal, the best option for it is to make it with ncurses. I have been learning how work with the ncurses library for some time, and in my opinion, it's the least annoying graphical user interface to deal with. I plan to add support for some other GUI toolkit, like GTK or Qt in the future.
Something that I'm working on as well, is to improve the code. I want to make the program easier to extend and making it more customizable. Having a few hard-coded commands might not be an issue now, but this will become an issue in the future.
Of course, as a free and open source project, you can contribute to it if you want to. If you have any ideas, I would like to read your suggestions. The links for the git repositories can be found at the projects page.
Thanks to godcock for suggesting me to write this post.