A handed over project runs two tools on your code, and only one of them can find a bug.
Linting and formatting a handed over project means dealing with two tools that get mistaken for one. ESLint reads your code and reports problems. Prettier throws your formatting away and reprints it. The project you inherited most likely has the first one configured and the second one absent, because that is what the Expo setup does. So the useful question is not how to configure them. It is which of the two you have to care about, what it costs you to leave the other alone, and which file in your own project root tells you what you already have. Every file name, default and command below comes from ESLint, Prettier and Expo documentation, read on 17 October 2026. If the project is still new to you, start with getting started with Expo.
What follows is the check on your own project root, what each tool decides, what Expo installs for you and what it leaves out, and the one place where Expo and Prettier give opposite advice. Both are first party. Neither is wrong. You still have to pick.
Start hereThe short version
Keep the half that finds bugs. The other half is a preference.
Lint and format are one habit and two tools. The linter decides whether your code is a problem. The formatter decides what it looks like. Only the first can tell you something true about behaviour, and only the second produces a commit that touches every file in the project. Treating them as one thing is how people end up afraid of a command that was never going to break anything.
On an inherited project, do three things in this order. Find out what the project already has, which takes about thirty seconds and is the check below. Read the lint script in package.json, because that one line is what any build pipeline will run. Then decide once whether a formatter belongs in the repo, write the decision into the repo rather than into your head, and do the first sweep as its own commit with nothing else in it.
Do you have to care about this on a project you did not write?
Yes, for one reason, and it is not code quality. The lint step is usually wired into something. Expo documents that running npx expo lint runs the lint script from package.json, so whatever that single line says is what actually runs. If a build or a deploy step calls it, then a rule nobody has looked at in months gets a vote on whether your release goes out. That is the version of this problem that costs you an evening, and it costs you the evening you can least afford it.
The second reason is diffs, and it matters more than it sounds. If you and an agent both edit the same files and nothing normalises the formatting, every real change arrives mixed in with noise. After a few rounds of that you stop reading diffs properly, and on a project you did not type the diff is the main control you have. A formatter is not about taste. It is about being able to see what changed.
What you can safely leave alone is most of the output. ESLint documentation says the problems it reports can be anything from potential runtime bugs, to not following best practices, to styling issues. That is three very different piles sharing one label and one colour in your terminal. A warning about a hook dependency is telling you something about behaviour. A warning about where a brace sits is telling you about a preference somebody encoded in 2021. Read the first kind. Ignore the second kind until you have a reason.
And the honest limit, because it keeps people chasing the wrong thing. None of this finds the faults that actually take an app down. A linter does not know your API returns null on the first of the month, or that a screen leaks a listener on the fourth visit. For those you are debugging a crash, and no config file helps. A clean lint run is a tidy house, not a working app.
What is ESLint doing, and what is Prettier doing?
ESLint documentation describes it as a configurable JavaScript linter that helps you find and fix problems in your JavaScript code, and says rules are the core building block, where a rule validates whether your code meets a certain expectation and what to do if it does not. The rules index sorts them into four groups: Possible Problems, Suggestions, Layout and Formatting, and Deprecated. The Layout and Formatting group is described as rules that care about how the code looks rather than how it executes, and it is nearly empty now. Almost all of its rules sit under Deprecated, each one pointing at a replacement in a separate stylistic plugin. ESLint handed the formatting job back.
Prettier documents the split from the other side, and more plainly. Its comparison page says linters have two categories of rules: formatting rules, of the maximum line length and comma style kind, and code quality rules, of the no unused variables kind. It says the code quality rules are likely to catch real bugs with your code. Prettier removes the need for the first category by reprinting the entire program from scratch in a consistent way, so it is no longer possible for the programmer to make a mistake there. It says it is not a rule-based tool and has no individual formatting rules you can enable or disable, which is the part people fight before they accept it. On the other category it is equally blunt: Prettier does nothing to help with those kinds of rules. Its own conclusion is one sentence, use Prettier for formatting and linters for catching bugs.
One word trap is worth knowing before you read any ESLint output. ESLint has a thing it calls a formatter, and it is not a code formatter. Its documentation says an ESLint formatter controls the appearance of the linting results in the command line interface. It formats the report. It does not touch your source. People read that word, conclude the linter already formats their code, and then spend an hour wondering why nothing is being reprinted.
Prettier, Prettier vs. Linters, read 17 October 2026
Thirty second check
What is actually in your project root
Open the top level of the project and tick what you find. These are the file names each tool looks for.
Nothing ticked yet. If none of these are there, nothing is checking or reprinting your code, and no command will fail because of formatting.
What does Expo set up for you, and what does it leave out?
Expo has one guide for this, called Using ESLint and Prettier, and it carries a modification date of 25 September 2026. The first time you run npx expo lint it installs and configures ESLint for you and writes an eslint.config.js that extends configuration from eslint-config-expo. Run the command again and it lints, by running the lint script from package.json. So the setup and the daily command are the same command, which is tidy, and also means the first run on an inherited project may write files rather than only report on them.
Which config format you get is decided by how old the project is. Expo documents that from SDK 53 onwards the default config file uses the Flat config format, and that for SDK 52 and earlier the default uses legacy config and does not support Flat config. That is why two Expo projects on the same machine can have different file names for the same job. Neither is broken. If yours is the legacy one, moving across is a migration Expo documents, not an emergency.
What the setup leaves out is Prettier. Expo documents it as a separate step with its own install of prettier, eslint-config-prettier and eslint-plugin-prettier as dev dependencies, and a .prettierrc at the project root if you want to change its defaults. So a project with a linter and no formatter is the ordinary result of the Expo setup, not a gap somebody left behind. That is the single most useful thing to know before you go looking for a missing config file that was never there.
Two rough edges on that page are worth knowing before you copy from it, and both are visible on the page itself. Its Flat config example uses a Node globals value without importing the package that provides it, so pasting the snippet exactly as written gives you an error rather than a config. And its troubleshooting section, the one for when ESLint is slow, tells you to add a .eslintignore file containing the Expo cache directory and node_modules, while its own Flat config examples exclude paths with an ignores entry instead. The page does not say which of the two your project should use. Check which one your config actually reads before you trust either.
Expo, Using ESLint and Prettier, modification date 25 September 2026, read 17 October 2026
Should Prettier run inside ESLint or on its own?
This is the one place in the whole subject where two first party sources give opposite advice, and you should know that before you pick, because both camps will quote documentation at you. Expo documents one route and only one: install eslint-plugin-prettier, add its recommended config, and from then on anything that is not aligned with Prettier formatting is caught as an error when you run npx expo lint. Expo also notes you can set the rule to warn instead if you would rather have formatting reported without failing. One command, one report, and formatting cannot be quietly skipped, because it fails the same check as everything else.
Prettier documentation, on its page about integrating with linters, is cool on exactly that arrangement. It says plugins that run Prettier as a linter rule are generally not recommended, though they can be useful in certain circumstances, and that they were especially useful when Prettier was new. It gives three reasons: you end up with a lot of red squiggly lines in your editor, they are slower than running Prettier directly, and they are one more layer of indirection where things may break. It points instead at running Prettier with its own check flag, at editor support, and at eslint-config-prettier to switch off the lint rules that conflict with a formatter.
How to pick without spending a week on it. If you want one command and you want formatting enforced whether or not anyone remembers, take the Expo route, because it is the path of least resistance inside an Expo project and the failure is impossible to miss. If the project is large and lint already feels slow, run Prettier on its own and keep eslint-config-prettier so the two never argue over the same line. The genuinely bad answer is the third one: leaving ESLint formatting rules switched on at the same time as a formatter. Then two tools rewrite the same line in two directions, and a lint run that never comes back clean is a lint run everybody learns to ignore.
Whichever you choose, do the first full sweep as its own commit with nothing else in it. A formatting pass does not change what the code does, and it touches JavaScript rather than anything native, which puts it in the cheap category of change, the same category as over the air updates rather than a fresh native build. The expensive part was never the run. It is the review, and you can only honestly skip that review if the commit contains formatting and nothing else.
The same file, read by two tools
| The question | ESLint | Prettier | Same for both |
|---|---|---|---|
| What it decides | Whether the code is a problem | What the code looks like | No |
| Can catch a real bug | Yes | No | No |
| Rules you turn on and off | Yes | No | No |
| Installed by npx expo lint | Yes | No | No |
| Config file in an Expo project | eslint.config.js, Flat config from SDK 53 | .prettierrc at the project root | No |
| Changes what the code does | No | No | Yes |
| A full run on an inherited project gives you | A list to read | A commit that touches every file | No |
Where this lands if a builder generated your app
Nothing about the division of labour changes because an agent typed the first version. The rules live in a file in your repository, and both tools read that file whoever wrote it. The only difference is that you did not choose it, so the first job is reading it rather than arguing with it.
Newly is an AI app builder. You describe an app in plain English and it writes a real React Native and Expo project you own. It uploads iOS builds to TestFlight, publishes to Google Play internal testing and builds a standalone Android APK. It is $25 a month, with no free plan. If the premise is new to you, the longer version is building React Native apps without coding.
The part that matters for this page is the two way GitHub sync. The project sits in a repository you control, which means the lint config is a file you can open, change and review, and a formatting sweep is an ordinary commit you can see the whole of before it lands. That is the practical difference between inheriting a codebase and inheriting a black box. A generated project you can read is a project where this page is a thirty minute decision rather than a mystery.
The honest limit: generating an app does not decide your formatting policy, and no tool can decide it for you, because it is a taste question with real consequences only for how readable your diffs are. Run the check further up this page on your own root, decide once whether a formatter belongs in the project, and write the decision into the repo rather than keeping it in your head. An agent editing those files later will follow whatever the config says, and will follow nothing at all if there is no config.
Questions people ask about lint and formatting on an inherited project
They do two different jobs that share one reputation. ESLint documentation describes it as a configurable JavaScript linter that helps you find and fix problems in your code, built out of rules, where each rule validates whether your code meets an expectation. Prettier documentation says linters have two categories of rules, formatting rules and code quality rules, and that Prettier removes the need for the first category by reprinting the entire program from scratch in a consistent way. It also says Prettier does nothing to help with code quality rules. Prettier states its own conclusion in one sentence: use Prettier for formatting and linters for catching bugs.
Describe the app, then make two decisions once
Keep the rules that point at behaviour. Decide whether a formatter is in the project or not, and commit that decision on its own. After that, lint stops being a thing you are afraid to run.
Start building