👋 Hey all, the first release of the Leon CLI has landed a few days ago. I’d like to let Théo and Arthur share their experience building it, the problems they faced, how they solved them and whatever they would like to share with you!
If you are not familiar with Leon yet, Leon is an open-source personal assistant. He is based on Node.js for the core, and uses Python for his modules (skills). Therefore, several requirements need to be installed to start to fully enjoy the experience.
Installing these requirements can be a hassle, origins of several issues you reported were due to their setup. Knowing that we all come from different backgrounds, it may be troublesome to get through this. So we have thought of a CLI to get your own Leon running in 3 commands.
- Make the installation easy
- And the most important of all, do it well
You guess it, many discussions were needed to have a proper plan (come and join us on the discord server, it’s kinda cool there).
Split the tasks, a system to maintain good quality, creating automation, manage our time… So many choices and only one pair of brains.
Once upon a time a brainstorm, a really sweaty one!
How many features should we release? The minimum, we would not want to confuse our friendly Leon users with unnecessary steps.
Even with a few features, we had our whole package of difficulties. Fortunately, we had a well-structured task management system:
- Trello for the roadmap.
- Discord to communicate, do pair-programming and communicate with the community.
- GitHub to host our dear open-source CLI and discuss about implementation inside Pull Requests.
You asked for the tech stack? This one is tricky…
The next decision was the main library to build the CLI. A classic would be Commander but it had a big drawback for us: the structure. Our goal was to start small and progressively tend to a full-featured tool, the companion for our Leon journey. Commander would allow a nice start but leads us to a kind of messy project as most of the command parameters are inside a single file.
Let us introduce another alternative: Clipanion, a type-safe CLI library with no runtime dependencies, made with TypeScript.
A special thanks to Sindresorhus. Many of our struggles have been solved by his numerous packages, including:
execato execute commands.
chalkfor the tasty flavour in your command line interface (it adds color).
confto let the CLI persists some data (configuration files and logs).
We offer two ways to install Leon:
- A classic installation (directly installed on your machine).
- With Docker (an independent container).
Two options and two brains, a perfect match! Naturally, we divided the work:
- Théo started on the Docker install.
- And Arthur the classic one.
Let’s dive into some experience feedback:
Théo: The command
leon create birth was the hardest command to get it working as it’s completely cross-platform, so we needed to create Virtual Machines to test on multiple OSes. The Docker installation was a little bit easier, as Docker does the “heavy lifting” for us.
We both learned a lot building this first version of the CLI, but it’s only the beginning and we want to make it more and more useful to be the companion for your Leon journey.
Arthur: Leon’s CLI is a proof that nothing beats a challenge to learn and exceed your skills. I probably lost some hair managing the cross-platform side… So, I hope the community will appreciate my dedication. Jokes aside, it’s one of the most interesting project I worked on. Enjoy using it!
How to easily add features without breaking existing ones? With a stable and trusted architecture.
We started to talk about it before: Clipanion. But it’s not the answer to everything… We also needed to reuse features between commands. The object-oriented architecture and the services to isolate our functions per domains were a part of the answer.
To adapt to everyone and every architecture, each command has its set of options.
The next step for scalability is the testing system! For this v1, supporting Windows, Linux and macOS was the biggest challenge in terms of testing and scalability, by far.
We used a common strategy, a combination of unit testing and end-to-end testing. Knowing that the specificity of our project is to have the OS as the kernel, the end-to-end tests are the most important, they are the guardian of our stability.
Scenarios are the same on each OS and are executed on independent machines:
Retrieve the CLI
Make Leon alive by getting all its dependencies using
leon create birthcommand
Start Leon with
leon startand verify that the interface is available
To ensure that the code remains at the top quality and that new features never breaks older ones, we implemented Continuous Integration. It means that every time we (or you) push new lines of code to the CLI, all the tests are executed through GitHub Actions.
A lot of stuff is coming, our ideas never end. Not only our ideas, yours too. 🙂 Feel free to post any idea you have here.
A non-exhaustive list of incoming features:
leon infoto get information of our Leon instances
leon updateto obviously update Leon and see him evolve (get the latest features)
- A better developer experience for the creation of modules / packages
- Easily modify the configuration of Leon (text-to-speech, speech-to-text…)