Introducing Fauna Shell

Back in April, our team got together with the goal of assessing the current status of FaunaDB to try to see which areas we wanted to improve next. This group was a mix of people who had been at Fauna since the beginning, and people like me who had just joined the company.

As a new user, I struggled with how to get started using FaunaDB, so I raised the issue to the team. During our brainstorming sessions, we concluded that we needed to improve a couple of areas to provide the user with a blissful experience. One of them was overall documentation: information was usually there, somewhere, but it was hard to find for a new user. Since then, our team has been working hard on improving FaunaDB’s documentation. At the same time, we wanted to give the user a straightforward path to running their first FaunaDB query. The team knew we had great technology built into the database, but we needed to help users start experimenting with it as fast as possible.

An interactive shell was the answer to that, a tool where users could issue their FaunaDB queries while getting results from the database right away. And so the project Fauna Shell was born.

After you install the Fauna Shell, you can login from there to your Fauna Cloud account directly from the command line:

First, install the shell. If you're on a PC, you can install it with npm:

$ npm install -g fauna-shell

Alternatively, if you're on a Mac, you can install it with homebrew:

$ brew install fauna-shell

Second, log in with your Fauna credentials:

$ fauna cloud-login

Password: **********

After those two steps, you are ready to start using your FaunaDB instance, for example by creating a database:

$ fauna create-database my_app

And then start playing with it from the interactive shell:

$ fauna shell my_app
Starting shell for database my_app
Connected to
Type Ctrl+D or .exit to exit the shell

Once in the shell, you will be able to start typing queries and receiving feedback right away:

my_app> CreateClass({ name: "posts" })
{ ref: Class("posts"),
 ts: 1533753878043481,
 history_days: 30,
 name: "posts" }

User-centered design

This might seem like a small thing, but it's great when a user wants to get their feet wet with FaunaDB as fast as possible. The shell brings up an environment where instant feedback can guide the user while learning how to use FaunaDB.

Another important advantage of the Fauna Shell is that users don't need to setup a whole development environment to start using FaunaDB. In the past, there was the need to pick a programming language that had a FaunaDB client. Then, the user would have to install that client and learn the proper import directives that would let them use that client. From then on, they would have to write a query, compile or execute the program, see the results, and try again. With the Fauna Shell, we removed all those steps: The user writes queries and sees their results immediately.

Removing Obstacles

Something I enjoyed from the process of developing the Fauna Shell was how it was driven with a focus on providing the user with a pleasant experience. We wanted to remove obstacles. As mentioned above, one of them was the need for setting up a development environment just to use FaunaDB.

After discussions with Matt our CTO, and Summer our UX Lead, we came to the conclusion that Javascript would be the language that would host the shell. On one side, it provided an interactive environment, and on the other side, due to the web's popularity, almost every developer has worked with Javascript at least once during their professional lives.

Using our Javascript in plain node.js, we would write queries like this: query(q.CreateClass({ name: "posts" })). Basically a CreateClass directive would be passed to the query method, and that method would execute the query for the user. During the prototyping stages of the Fauna Shell, we used to write queries that way, but the more we typed those queries, the more we saw something was out. Every time we wanted to execute a query, we had to wrap it inside a query() function call. That sounded less than ideal. We decided to bring into scope the whole query module, removing that requirement.

By removing the need to wrap queries all the time and the need to scope function calls to the q. module,  we left the user with a more ergonomic experience where they could focus on typing FQL expressions directly. The code shown above just became CreateClass({ name: "posts" }), letting the user focus on what’s important to them, for example, creating a class called posts.

Small Details Matter

Another thing we noticed as we worked with the shell was that the output we were receiving after sending queries to the database was far from ideal. For example, if you submitted the query CreateClass({ name: "posts" }), you would receive something like this:

{ ref: Ref(id=posts, class=Ref(id=classes)),
 ts: 1527349751848648,
 history_days: 30,
 name: 'posts' }

As we kept seeing those results, and we tried to use them in future queries, we noticed that they couldn't be copy-pasted right back into the shell to be used in future queries. Our colleague Marrony worked on improving our faunadb-js driver so results would be pretty printed in a way that would allow for easy copy-paste:

{ ref: Class("posts"),
 ts: 1532624109799742,
 history_days: 30,
 name: 'posts' }

While these examples all seem like small details, they help users have a nicer and more natural experience while using the Fauna Shell to learn how FaunaDB works. It's all about removing obstacles.

Finally, once we were ready to launch, we noticed that the shell provided no information to the user about to which server they were connected to, nor about which database they were using.

$ fauna shell my_app
Starting shell for database my_app
Connected to
Ctrl+D or .exit to exit the shell


Again, just a small detail that greatly improves the usability of the shell, providing users with the right context about where their queries are being sent. Nobody wants to suddenly delete all their information in the production database!


In this article, we not only wanted to give you a quick intro to the Fauna Shell, but also to provide you with some insight into how we develop products here at Fauna. We try to put ourselves in the shoes of our users and from that point try to see where our tools need to improve.

Also, even though in this case I was the lead for the Fauna Shell project, the whole work was a team effort: Our sales engineers helped us identify where the Fauna Shell was falling short. This feedback was looped between our UX lead, our CTO, and me so we could retrofit it into the project. Also, other colleagues stepped in and helped by improving other aspects of the product, like our JS driver, so at the end we could deliver a polished experience for our users while organically improving other areas of the system.

Of course, this is just the start of the road for the Fauna Shell project. We’re improving it further every day, and can't wait to hear from you about features you would like to see next.