Supabase CLI Local Setup on macOS, and Why `npm install -g supabase` Is the Wrong Move
A practical Supabase local development guide for macOS that covers CLI installation, local stack startup, project linking, migrations, and the common mistakes that come from treating Supabase like a normal JavaScript global package.
The mistake that starts the mess: developers assume every tool in a JavaScript-adjacent workflow should be installed with
npm install -g. Supabase is exactly the kind of tool where that assumption causes unnecessary confusion.
What the Supabase CLI is for
The Supabase CLI is not just a thin wrapper around an API. It helps with local development, database migrations, project linking, and function workflows. That means it belongs closer to infrastructure tooling than to a normal frontend package.
Install the CLI the supported way
On macOS, use Homebrew:
brew install supabase/tap/supabaseThen verify:
supabase --versionThis is cleaner than relying on a global npm install that was never the right mental model for the tool.
What else you need locally
Supabase local development depends on Docker. Before you try to start anything, confirm Docker is running:
docker psIf Docker is down, the CLI is not your first problem.
Start a local project
Inside your repository:
supabase initThat creates local project structure for config and migrations.
Then start the stack:
supabase startThis launches local services in containers. The first run can take longer because images need to be pulled.
Why people think supabase start is broken
Usually one of these is true:
- Docker is not running
- old containers or port conflicts are interfering
- the machine does not have enough free resources
- the developer expected an instant startup on the first image pull
That is not a Supabase-specific flaw. It is normal for local container stacks to feel heavier than pure app servers.
A basic migration workflow
Create a new migration:
supabase migration new add_profiles_tableThen update the SQL file and apply changes through your usual local flow.
The value here is not magic. It is repeatability. Schema changes become explicit files instead of fragile remembered steps.
Linking a remote project
If you need to connect the local repo to a hosted project:
supabase login
supabase link --project-ref your-project-refThat makes later commands more predictable because the CLI knows which project you mean.
The bigger lesson
Supabase is often introduced through frontend tutorials, so people start treating it like a normal client library first and an infrastructure stack second. That order is backwards for local setup work.
Once Docker, migrations, and project linking enter the picture, you need to think like an environment builder, not just a component author.
A safer macOS routine
When setting up a machine, use this order:
- install Docker
- install Supabase CLI with Homebrew
- initialize the project
- start the local stack
- only then begin app integration
That sequence is boring, but it prevents a lot of random-command thrashing.
Final recommendation
If Supabase local development feels heavier than expected, that is usually because it is doing more than a normal frontend tool. Treat it like local infrastructure. Install it the supported way, verify Docker early, and let migrations do the work of making state explicit.
Once you approach it that way, the tool becomes much more predictable. The frustration usually comes from using an infrastructure workflow while still expecting the ergonomics of a tiny global npm helper.