 Hi, I'm Corey Butler. I'm going to be talking about CLI First Development. The CLI First Strategy is a thought framework for managing development projects. The main activity is prioritizing the design and evolution of a command line interpreter throughout the software development lifecycle. In simple terms, I'm going to show you how to develop a CLI tool that serves as the core of your app, both back end and front end, and your workflow. The CLI First Strategy is similar to the traditional software development lifecycle. It shares the same goals, but differs in how they're achieved. Unlike the traditional approach, CLI First encourages coding at every stage. Both strategies rely on a team's ability to agree about what is going to be made. This means teams must convert intangible concepts and ideas into something tangible. The CLI First Strategy strikes a balance by replacing or augmenting the specification with a shared command line utility. I'll show you how to do this, but first, let's review the tools we're going to use. I'll be demonstrating the strategy with the Author Shell Library. It's a lightweight shell framework for creating CLI experiences in any modern JavaScript runtime. On the left, we have Node.js, and the right shows the browser code. You can see the functional code is the same for both runtimes. It only differs in the import source and how user input is collected and passed to the shell. I'll also be using a CLI DevTools extension for browsers, which mimics a terminal experience with auto-completion, hints, suggestions, and more. To illustrate the planning stage of the CLI First Strategy, let's consider building a team communication app. An application like this is going to have a couple of different core features, maybe a member directory, wall or discussion feature, profile management where you can manage your avatar, email, name, so forth, and some sort of notification feature that's going to notify you when you have a new message or when you've received a reply. Now, like any system, there's a number of different concerns or disciplines that are going to be required to actually implement such a system, like the user interface, an API, database or data store, DevOps process, quality assurance. This is just a short list. Obviously, there are more in most applications, but you get the idea. Remember that in the traditional software development lifecycle, the requirements gathering process ends with a specification, whereas the CLI First approach ends with software. The reason this is important is because in the traditional approach, it's a sequential process, meaning that the features are defined first. Then you worry about the implementation concerns. With the CLI First approach, we're combining those, where we're thinking about features and concerns at the same time. Now, the way to address this is fairly simple. We just need to align on what those features and concerns are. To do this with a CLI tool, it's actually pretty straightforward. We need a dictionary of some sort, and what better way to do that than with a help screen? On the right side of the screen, you can see a configuration for a shell. This is designed specifically for the author shell library, and we're providing a couple of configuration options. First, we're going to call this application team. We've got our description and a version, and then we've identified several different commands. You may notice that these commands are loosely related to the features that we have. There's the user and directory wall notification with a small description of each of these. To implement this, we're importing this configuration into our shell library. This happens to be the node version. Similarly, we're doing the same thing in the browser. Let's take a look at the results of this. Switch over to a terminal here, and we immediately have a help environment with everything defined. Now, let's take a look at this in the browser. I'll open DevTools here and follow the instructions. It just tells us to type team help. You can see we have the exact same information accessible in both the browser and in the terminal. I mentioned that we were going to be using the command line extension for this. Let's take a look at that. That's installed here. I'm going to clear this out so that you can see the same thing. This, by default, has the help feature. You could type it in like that, or it simply hit enter, and it provides you the information the same way that you would do if you were executing this as a command through the console. This is a little bit easier, and you'll see that more throughout the rest of this presentation. At this stage, we have created a very simplistic command line tool that documents our system and the features within it that is accessible on a desktop, on a server, and in the browser. In a matter of minutes, the project momentum just increased. By creating a basic CLI help screen, groups are forced to trim the fat in an almost surgical manner. The incredibly direct nature of the command line enforces ruthless simplicity. Command serves as standard terminology to define the systems and applications being built. My favorite benefit of this stage is the fact there is working software. It's software that doesn't do anything, but the ideas are baked into the core. This serves as inspiration, and it's an excellent onboarding tool. We also have a strong sense of confidence in our project trajectory. The prototyping stage is a proving ground. It's kind of like the entrepreneur's equivalent of a proof of concept. It's time to prove that each area of concern, like the user interface and APIs, can work in an aligned manner while maintaining independence and how they each choose to implement their part of the project. At this stage, we're pretty much just mocking up functionality at a finer level of detail. I'm going to add a sub-command to serve as a placeholder for authenticating a user. To do this, we add a command like this, and let's give it a description. This will just be retrieving an access code or access token. You know what? Let's make an alias for that. We'll just call it A for now, and then we need to actually handle this. In this case, for the time being, since this is just a prototype, just a placeholder, we're just going to say console.log not implemented yet. Let's save this, but let's take a look at the team user. Now, you can see the new help has been updated. Let's go ahead and run that. You can see here that it just says not implemented yet. Let's take a brief look at that in the browser as well. Here, we can see the exact same command provides the exact same output. Again, if we put in user help, we'll be able to see the same help command as well. Everything that we did in the planning stage immediately transfers into the prototyping stage, and we also have just a small, tiny bit of functionality. Again, it doesn't really do much, but it serves as a placeholder, and this is something that we can use to build upon in the future. The beautiful part about this is that teams can still work independently. Regardless of the pace that you go at, by providing some placeholders, you're able to then start incrementally adding functionality into your application and into your system. Hopefully, it's obvious how rapid the transition is between the phases of the strategy. By inheriting the progress of the planning phase, prototyping can be very quick and super flexible. So far, the CLI tool has a user authenticate command. I'd like to see this working from a terminal and the browser. So I'm going to start by creating a basic working API. Then we'll build an API client into the CLI tool. I pre-built a simple node API skeleton using the common API library. This library provides many features for rapidly creating backends. I've added several endpoints representing the features of the application that we care about, along with basic auth security. You can also see I've launched the server in the top terminal. I've also updated the CLI's user authenticate command with an HTTP request for an access token. You can see both runtimes retrieve the same token using the same command. So as you can see, this process is still inheriting the progress from the stages before. It allows for us to work independently in our own area of expertise, UI, API, data, and anywhere else. Yet we remain unified in our approach. The software systems are always changing. The CLI-first approach can't prevent this from happening, but it can provide a predictable way for responding to change. Think of it like having a go-to battle plan for any situation. To illustrate, let's pretend the group communication system has been in use for a while and has proven to be a reliable way to communicate with the entire workforce. In an effort to boost morale, the system needs to provide a new inspirational quote of the day. There are a few challenges with this. First, it involves a new unproven third-party service to provide quotes. It also means the implementation of the user experience may differ between run times. At this point, we can restart the CLI-first process for this portion of the system. Think about this. In a real production system, this can be a huge benefit because it reduces the price of fixing technical debt. In other words, it won't cost you as much time or stress to change your system. Since a command line tool is flexible, it can be introduced to the development workforce incrementally the same way the original features and functionality were introduced. This buys time, reduces stress, and keeps the system clean. Instead of avoiding change, people start to embrace it. If this common challenge is one you face, the CLI-first strategy is likely to offer you significant relief. So let's embrace this quote of the day change in our app. At this point, we have the user directory, wall, and notification. Now, I've already preconfigured this to add a new command called quote. We're using quotes.rest here for our quote of the day. So we don't actually know what we're going to get back from this right now. But what we do know is that their API documentation shows us that we get back contents with some quote. It's basically a JSON object that comes back. Now, we need to present this in different ways depending on the runtime that we're running in. So you can see here that we're leveraging the new global this feature of ECMAScript to determine whether or not the window object exists. That's unique to the browser. So we know that if the window object exists, we're in the browser. Otherwise, we're assuming that we're in Node.js or another runtime. So all we're doing here is providing a block of text. We're saying we're going to insert this block quote into the web app with the quote and the author. In Node, we're going to be doing the same thing, but we're going to be logging this out to the standard out. So we're providing the quote and then we're providing the author. So let's take a look at this and actually run this command here now. So I'm going to say team, I'll clear this out, team quote. You can see the quote here. Let's go take this into the browser as well and run the same thing. This time, you'll notice that the browser changed. So earlier, we were talking about how we could emit an event or trigger some sort of action depending on which runtime we're in. In this case, we simply made a change to the web page. So you can see here a kind of interesting concept where you can come in to the CLI depth tools extension or into the console, type in a command and it's going to update the UI. Now that doesn't work the same way in the terminal, but think about the power behind this. If you are an API developer and your UI developer comes to you and says, I'm not getting the data back that you're saying I should be getting back. As the API developer, you can say, well, please provide me the command that you use to capture that data. So the UI developer can provide that command. The API developer can go in to the browser and run the exact same command, see the error, take that offline and use that in their own development environment, however they see fit, because they have the same command line tool. So now you can start troubleshooting. So not only is it troubleshooting that way, but you can take this concept significantly further if you wanted to think about unit testing, integration testing, all kinds of things that you could potentially automate with a command line tool that's the same across run times or at least the input and output is the same, even if the implementation is different as it is here. If you need to integrate this with other things such as an approval process, you could. You don't have to release this quote command. You don't even have to use this quote command in all run times until you're competent in it. So it's a very light amount of overhead to give you a significant amount of flexibility in your development process. As you can see, the process of pivoting is very adaptable and it provides predictability in how you adapt to change. A flexible approach like this has a wonderful effect on tech teams. It enables behaviors that create organic growth, which fundamentally change your development culture. We've already seen how the tooling and the process can adapt to changing plans, new features, heavier development and complete pivots. The final phase is maintenance. The word maintenance is often thought of as work done in the aftermath of a new feature. The CLI first way of thinking views it more as growth activities. It's both the end of a cycle and seeds of the next cycle. For example, pretend the organization introduces a new JavaScript runtime to your standard stack, like Deno. Perhaps the runtime has some characteristics that require some modification to your code. In Deno, there is a global window object just like the browser. With the existing command code for our quote of the day feature, it'll misinterpret the runtime mistaking Deno for the browser, producing HTML when it should be writing to standard output. This is a minor maintenance task. We'll use optional chaining to solve this. We'll be leveraging the navigator object, which Deno does not have on its window object. We'll also be mindful to update the version. With the updates in place, a new version of the CLI tool can be released with the modified functionality. Let's see how this looks. First, we'll refresh this page and notice that there is now a version 1.0.1. In our terminal, to do the same thing, we'll see we're also at version 1.0.1. When we run the quote command, we get a quote, likewise in the console. Now, the important thing to note here is that the app didn't break, despite the fact that we made some changes. Now, if it had broken, we could roll back to a prior version of the tool. So you can see that the maintenance process is still inheriting progress from all of the phases before it. You can also start to see that the process itself can be version controlled, simply because you can maintain multiple versions of your CLI, such as a fork or another feature branch, anything that you really want. So you have point-in-time understanding of your process. This whole project is a lot easier with the CLI tool simply because the help is documenting the system as we go. So as we make changes, we're only changing that documentation when something important changes, such as a new feature or a change to the way that something is accomplished. Remember, the CLI-first strategy is ultimately a thought framework or best practice of sorts. You can use it to ease into planning with a tool that provides help. Prove your stack works by wireframing placeholders together with actual code. Develop your part of a system with confidence knowing the work you do will be understood by others. You'll be prepared with a battle plan for addressing change. Maintain your applications with repeatable practices. All this can be done well with the assistant of code at every stage. This flexible strategy can be used for testing, onboarding, documentation, DevOps, applications, and even tooling. Whether you choose to use it for one purpose or many, you'll benefit from the speed, simplicity, and standardization a command line utility provides. For teams, it provides a more streamlined approach for collaboration and automating workflows. Many organizations already have their own homegrown CLI tools. If this describes your organization, you already have a set of standards to build upon and integrate into your systems. If you've never considered using a CLI concept in the browser before, I recommend trying it out. In my personal experience, browser CLIs have increased our productivity by an order of magnitude. Testing and debugging alone is far simpler when we don't have to point and click through every user journey. We just run a command. Troubleshooting apps is often easier when an error can be recreated just by issuing a command. When we first started using the CLI first strategy, it was for speed. Today, I find the documentation aspect to be just as, if not more valuable. CLI help menus act like a Cliff's Notes guide, giving all developers the ability to read about the parts of the system they care about without getting bogged down with too much unnecessary detail. If you are interested in trying out the CLI first strategy, you can use the same tools you've seen today. I'll be posting more information about the CLI first strategy on the GitHub repo listed here, and I can be reached on Twitter and Quora if you have questions about it. I will most likely make follow-up videos as well in the near future. Thanks for joining me today, and have a great conference.