Resources

Air: A blazingly fast R code formatter - Davis Vaughan, Lionel Henry

In Python, Rust, Go, and many other languages, code formatters are widely loved. They run on every save, on every pull request, and in git pre-commit hooks to ensure code consistently looks its best at all times. In this talk, you'll learn about Air, a new R code formatter. Air is extremely fast, capable of formatting individual files so fast that you'll question if its even running, and of formatting entire projects in under a second. Air integrates directly with your favorite IDEs, like Positron, RStudio, and VS Code, and is available on the command line, making it easy to standardize on one tool even for teams using various IDEs. Once you start using Air, you'll never worry about code style ever again! https://www.tidyverse.org/blog/2025/02/air/ https://github.com/posit-dev/air

Oct 28, 2025
14 min

image: thumbnail.jpg

Transcript#

This transcript was generated automatically and may contain errors.

Hi everyone, my name is Davis Vaughan, I'm here with my colleague Lionel Henry and we're here to talk to you about a new tool we've created called Air. Actually the warm-up music there was also a band called Air. It's a French band, which is also where we got these t-shirts from. When you choose a generic name you can co-op swag from other people, which is quite nice.

So what I want to start with is to have you just look at this kind of prose here on the left. Besides it being in Latin, what you should understand is that it's just kind of hard to read because there's no white space. Compare that to this on the right. We have a lot of white space, we have a lot of indentation, bolding. It just makes the prose a lot easier to read, a lot more pleasant.

And code is kind of the same way. Here's a for loop. It's compressed. We've all seen code like this, right? If I were to ask you on a glance, what does this do, you don't necessarily know. There might be hidden bugs, it's hard to find it out. Compare that to rewriting this for loop with some good indentation, some good spacing, lots of new lines, and now it's really easy to see that this just prints out. It's even or it's odd.

Now I think we can all agree this looks better than what we just saw on the previous slide. The hard part is that sometimes it's just manual or a tedious process to make your code pretty, to get it in this form. For example, watch me kind of struggle through formatting this pipeline. It extends off the right-hand side of the screen. So what I'll first do is just kind of reflow the pipes manually, and then I'll go through and expand this pivot longer call.

I think we can agree, again, that this looks better in the end. You can actually read the code now. But this kind of sucks. It's a manual process, it's tedious, and at the end of a long workday, like, I'm just going to stop doing this at some point.

Introducing Air

So let's reset. Wouldn't it be cool if there was a tool where you could just snap your fingers and it would reflow the pipes? Or you could snap your fingers again and it would expand your function calls. If that sounds interesting to you, then you are really going to like Air.

Air is an R code formatter. If you're not familiar with formatters, they do what you saw on the previous slide. They take messy code and they automatically turn it into pretty styled code. Now I like to think of it as giving you a whole bunch of formatting superpowers. You saw a couple on the previous slide. We'll explore more over the next following slides. And if it seems cool to you, but you're thinking, like, God, is this one more tool that I have to learn? Is this going to have a big setup curve? Am I going to have to worry about a whole bunch of things that I have to read? Well, know that we've made Air extremely simple to get going with. There's really only two steps. You configure your project to use Air, and then you format all of your existing files.

Getting started in Positron

And it's actually so easy to get started, we're just going to show you real quick what it looks like. So if we jump over into Positron, the thing to know is that Positron comes batteries included with Air. There's actually nothing else you need to install. It's already there.

So we've got a project here with a couple files. We need to configure this project to use Air, and then we'll format those files. That's our goal for today. So the first thing we do is run this command, Air initialize workspace folder. What this will do is create those setup files that I was talking about. All this really does is tell your IDE, hey, go please use Air when you format. We'll commit those. That's step one, already done.

Step two is to then go through and actually format all of the individual files, but you don't have to do that manually. We help you out. There's a button here in the bottom right-hand corner. Just click to format the whole workspace folder. That easy.

So now if you use Git, and you don't have to, but if you do, and we encourage it, now you can look at the diffs of what Air has actually done to your files. It's kind of cleaned up some messy code. If you like that, then you go ahead and commit all of those, and that's step two, done. This project is now set up to work well with Air.

Format on save

Setting up is really easy, but again, like, okay, that's just the setup stage. What do we do on a day-to-day basis? Again, is this a tool that I have to learn a whole bunch of crap to know how to use? Well, no. We say that if you know how to save a file, you already know how to use Air. We're going to take a look at that.

So we'll create a new file here in our project called visualize.r. I've already started working on some visualization code for the scripts we have here. So if I were to continue this out, I would add maybe geomline and theme minimal, and I'm not really thinking about the style of this code at this point, but it's getting pretty long. Now, I've finished my thought here, so I might take a breath and save the file. And on save, Air kicks in, and it reflows your pipes.

Or I might say, well, actually, I'm not ready to do the plot yet. I need to create a couple extra columns first, so I might do a mutate call. And again, as I'm typing this, I'm not really thinking about what it looks like. I don't care at the moment. I'm just trying to get what's in my head onto the screen here. But when I finish, I take a breath, and I save, and Air kicks in, nicely reformatting this mutate call, adding white space, reflowing the pipes, and so on.

And you might be thinking, like, OK, format on save, that sounds cool, but, like, every single time, like, I save hundreds or thousands of times a day, right? Like, is this going to slow me down in any way in a large file? Well, we've designed Air to be imperceptible with format on save. It is actually so fast that we want you to question whether it even ran.

It is actually so fast that we want you to question whether it even ran.

To put some numbers behind that, we'll look at dplyr's across.r. It has over 1,000 lines in it. It's a fairly large R file. This takes 20 seconds, or 20 milliseconds, sorry, to format with Air. That would not be fast, would it? By comparison, to just give you some relative numbers, when you blink your eye, it takes 200 milliseconds. So it's very fast. Let's scale up. What if we were to format all of dplyr all at once, 150 files? That takes Air 200 milliseconds. You can format the whole project of dplyr in the blink of an eye.

Adoption and collaborative friction

If that sounds cool to you, and you're considering adopting Air, know that you will be in good company. We have already transitioned most of our packages over to using it, including a number of community packages like Nanier and iGraph. At this point, Air has been run over hundreds of thousands of lines of R code. We feel pretty good about the formatting. It feels pretty stable, and we're confident about it at this point. And it's truly a great time to adopt this tool.

So our goal with the formatter is that once you start using it, it will be hard for you to go back to your previous formatter-less life. And that's something that we have managed to achieve with Hadley, because now, when he saves a file and he doesn't reformat, it feels broken. So we knew that Hadley would be an easy win, because he cares a lot about style. And actually, many of us in the organization do. And I want to talk about what happens when you have a room full of programmers who all care a lot about style.

Something like this happens. So these are excerpts from pull request reviews in our organization. And in all these instances, the reviewer is focused on the style of the contribution that comes in. So of course, we would prefer to focus on the content of the contribution. And we call this collaborative friction. And we think that Air can help you with collaborative friction in two ways. The first is enforcement, and the second is configuration, and we'll start with enforcement.

So if you are a GitHub user, we have a GitHub action called setupAir. And once you've set up your project with this, a robot will come in and check the style for you, according to what Air expects. And so the robot provides suggestions. When the style doesn't match, the contributor can commit the suggestions themselves. And hopefully, with all the style comments out of the way, it will be easier and faster to get the contribution accepted in the project.

Configuration philosophy

So that was enforcement. Let's talk about configuration. So here we have a configuration file for a formatter called clang-format, which is for C code. And this particular formatter is extremely configurable. Here you have a small sample of the configuration options that you have to describe how you want your code to be formatted. So that's a lot of complexity and a lot of knobs to turn.

Now some of you might like this flexibility, but we'd like to argue that there is a hidden cost to it. So to give you an example, here is Davis and I trying to configure a formatter for REST code, because we write a lot of REST code these days. And here I'm suggesting to use a particular option to format the REST code. And I come in as the well-actually Felice and say, I don't like this option, actually. I think it actually makes the code worse, and blah, blah, blah. And we just end up back in the same scenario before with... So that's, like, we're going back to collaborative friction again.

So that's why we made the formatter more like a light switch than a sound mixer. So it's either on or off. You're either using the formatter rules that we have, or you're not. So that's how a configuration file looks like with our formatter. You have how wide you want your code to be. You have a couple of options about indentation style, whether you use spaces or tabs, and how wide an indentation is. And that's it.

So that's why we made the formatter more like a light switch than a sound mixer. So it's either on or off. You're either using the formatter rules that we have, or you're not.

We hope that will make it straightforward to set up your project and agree with your collaborator how to set up the project with R.

Flexibility: persistent line breaks and magic commands

So does that mean that with this trick, a formatter, you have absolutely no say into how to format your code? Well, not quite. Because one of our design goals was to make it easy to still have some flexibility. And that happens in two ways. First, persistent line breaks and magic commands. And to give you an example for persistent line breaks, here we have a couple of R expressions, a list call and a ggplot pipeline. And the idea is that if you insert a line break in the first element of a list call, for instance, that will be taken as an instruction for the formatter to go from the flat layout to the expanded layout, which is more vertical. You can do the same with the ggplot pipeline. So you find the first element. You add a line break. You save. It reformats to the expanded layout. That works in the opposite direction as well. You can remove the line break, save, go back to flat. And same for the list call. Remove the line break, and it goes back to flat.

So that's one of our favorite features with the formatter, because it really gives you a grip on your code. It's super fun to use, and we hope you will like it, too.

Now another way we provide you some flexibility is magic commands. So here you have an example from igraph, which is a package for specifying graphs. And it uses operators, the minus and plus operators, to do that. So here you have a graph specification. And if you try to format this with air, there's no way that it's going to know how to do a good job with this operator. So that will not look like a proper graph anymore. So what you can do is use a magic command. In this case, it's a skip command. And that's like an instruction to ignore the next line of code and to leave it as is. So of course, if you use igraph a lot, you're not going to want to insert magic commands everywhere. So we also have a configuration option to specify which functions should be skipped by the formatter.

IDE support and closing thoughts

So as we wrap up here, there's one more thing that we wanted to show you. Now all of the examples and videos so far have been in Positron. But air is an external tool. What that means is that it also works in RStudio. And in fact, air works in any IDE. If that IDE supports the language server protocol or allows for external formatters, you can use it with air. That includes NeoVim, Emacs, Elix, Zed, VS Code, Positron, RStudio, and the list goes on.

You see, we want air to be a tool for the whole community. And this means providing great support for all IDEs, not just Positron and RStudio. We have guides for most or if not all of these on our website. And at the end of the day, air is for everyone, no matter where you write your R code. Thank you very much.