# Quick and Easy Supabase CLI Local Setup Guide

Yes, Supabase is powerful, but hitting production for every tweak? That’s a recipe for slow dev, wasted free-tier limits, and possible oops moments.

Instead, set up Supabase locally with the CLI. It’s faster, safer, and perfect for version control. Your teammates (and future self) will thank you when everything’s reproducible and just works.  
  
with tiny bit of setup and understanding of how things work you can make your setup solid from day one.

## Install Supabase using node

I’m going to keep things simple and install it with node using NPM. if you want install it differently you can check the Supabase CLI [install guide](https://supabase.com/docs/guides/local-development/cli/getting-started?queryGroups=platform&platform=npm&queryGroups=access-method&access-method=analytics).

```bash
npm install supabase --save-dev
```

## Initialize Supabase

```bash
npx supabase init
```

## Start Supabase

<div data-node-type="callout">
<div data-node-type="callout-emoji">💡</div>
<div data-node-type="callout-text">You need to have <a target="_self" rel="noopener noreferrer nofollow" href="https://www.docker.com/products/docker-desktop/" style="pointer-events: none">docker desktop</a> installed on your system for this to work</div>
</div>

```bash
npx supabase start
```

this will download all the docker images and start your Supabase stack locally. You would see output like this *(obviously they are not my real secrets)* you would get your own.

```plaintext
Started supabase local development setup.

         API URL: http://127.0.0.1:54321
     GraphQL URL: http://127.0.0.1:54321/graphql/v1
  S3 Storage URL: http://127.0.0.1:54321/storage/v1/s3
          DB URL: postgresql://postgres:postgres@127.0.0.1:54322/postgres
      Studio URL: http://127.0.0.1:54323
    Inbucket URL: http://127.0.0.1:54324
      JWT secret: super-secret-jwt-token-with-at-least-32-characters-long
        anon key: eujnsdfnjkafwfnIkpXVCJ9.eyJpc3MiOiJzinjsfjnsfub24iLCJleHAiOjE5ODM4MTI5OTZ9.CRXP1A7WkjnadsfonjdsfonigdDMblYTn_I0
service_role key: eyafsKJsfIgsbks80hinjoUbonCJ9.eyJpc3MiOiJzdXBhYmFzZS1kZW1vIiwichabjfjsa8oIJJnnjnlUHJk5Nn0.EGIM96ajhbjifaoiHIs81IU
   S3 Access Key: 62sdf729ahbsiouhfff351asa23cf
   S3 Secret Key: 85ojsnfosoijwfiowefvs742isdfjnfweu907
       S3 Region: local
```

Now we can go on **Studio URL** to get started

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1749451981095/adda4db6-b684-45ad-aef0-2e475cc96e76.png align="center")

<div data-node-type="callout">
<div data-node-type="callout-emoji">💡</div>
<div data-node-type="callout-text">I would recommend to <a target="_self" rel="noopener noreferrer" class="notion-link-token notion-focusable-token notion-enable-hover" href="https://docs.deno.com/runtime/getting_started/installation/" style="pointer-events: none">install deno</a> when you are running Supabase locally as Supabase uses deno runtimes to execute edge functions and installing deno and its <strong>IntelliSence </strong>extension would help you.</div>
</div>

## Connect to your production env

there are two different ways to connect to the prod environment. either you use a PAT token which you can generate from this [link](https://supabase.com/dashboard/account/tokens) and use the token to login or use browser login.

1. **Browser login**
    
    run the following command
    
    ```plaintext
    npx supabase login
    ```
    
    **Output**
    
    ```plaintext
    Hello from Supabase! Press Enter to open browser and login automatically.
    ```
    
    If you are logged into Supabase in your browser you should see this screen on the browser.
    
    ![](https://cdn.hashnode.com/res/hashnode/image/upload/v1749452307397/43c9d8bf-2567-4684-bfa1-893fa5d03b81.png align="center")
    
    now go back to your command line and enter the code. This would automatically create PAT token for you and set it in your local env.
    
2. **Manually generating PAT (Personal Access Token)**
    
    * generate from this [link](https://supabase.com/dashboard/account/tokens)
        
    * run the following command
        
        ```plaintext
        $env:SUPABASE_ACCESS_TOKEN="sbp_a6cc1610147"; npx supabase link
        ```
        
        <div data-node-type="callout">
        <div data-node-type="callout-emoji">💡</div>
        <div data-node-type="callout-text">replace the token with your token.</div>
        </div>
        

## Link project

```bash
npx supabase link
```

1. select the project.
    
2. enter the Database password
    
    1. you can find the password under. `Project Settings` &gt; `Configuration` &gt; `Database`
        
    2. hit reset password and generate a new password
        
    3. copy that password
        

and you are done. now you can sync the database to production database using the following commands.

1. pull configs. this would pull migrations and configs from the production
    
    ```bash
    npx supabase db pull
    ```
    
2. push configs
    
    ```bash
    npx supabase db push
    ```
    

<div data-node-type="callout">
<div data-node-type="callout-emoji">💡</div>
<div data-node-type="callout-text">You need to enter Database password if you have not already in the beginning.</div>
</div>

next you run the command.

```bash
npx supabase db reset
```

this will reset the local database and apply all the migrations

for more details check: [Supabase CLI reference](https://supabase.com/docs/reference/cli/supabase-db-reset)

<div data-node-type="callout">
<div data-node-type="callout-emoji">💡</div>
<div data-node-type="callout-text"><strong>Note:</strong> If you’ve made changes to protected schemas like <code>auth</code> in production, <strong>Supabase won’t pull those by default</strong> when running <code>db pull</code> — and that’s usually for good reason. Pulling Supabase-managed migrations can cause serious headaches if you're not careful.</div>
</div>

If you need to add something custom (like a trigger on `auth.users` post-signup), it’s better to **create a local migration** (will see how to do this next), push it to Git, and let your teammates pick it up. Since the base `auth` schema already exists in production, make sure your migration includes proper checks — e.g., `IF NOT EXISTS` — to avoid blowing things up.

<div data-node-type="callout">
<div data-node-type="callout-emoji">💡</div>
<div data-node-type="callout-text"><strong>Heads up: </strong>when i did the process for the first time my migrations did not get applied. I stopped all the containers using the command <code>npx supabase stop</code> and than I started them again using <code>npx supabase start</code> and redid the process of pulling the data and resetting the database and it worked. it may have caused because when i ran the <code>npx supabase db reset</code> command for the first time it started pulling docker images. even though I have ran the command <code>npx supabase start</code> beforehand.</div>
</div>

## Migrations

In Supabase we need to create migrations to keep things in sync with local and prod. When we make changes locally we need to create migrations for version control so other devs working on the project are on the same page and also when other people make changes we can get those changes and push it to the production.

  
There are two ways to create migrations.

1. **Create migration file manually**
    
    1. **Run the command**
        
        ```bash
        npx supabase migration new <file name>
        ```
        
        example:
        
        ```bash
        npx supabase migration new new_migration
        ```
        
    2. A**dd content in the migration file**
        
        for example lets say we want to add a trigger, this could be anything. such as creating a table
        
        ```sql
        -- Add trigger to populate `profiles` when a new `auth.users` is created
        do $$
        begin
          if not exists (
            select 1 from pg_trigger where tgname = 'on_auth_user_created'
          ) then
            create trigger on_auth_user_created
              after insert on auth.users
              for each row
              execute function public.handle_new_user();
          end if;
        end
        $$;
        ```
        
    3. **Apply changes to local Database**
        
        ```sql
        npx supabase db reset
        ```
        
    4. **Push to git for version control**
        
        this helps other people working on the project get the changes
        
        ```bash
        git add .
        git commit -m "Add safe trigger on auth.users to populate profiles"
        git push origin main
        ```
        
    5. Push to Supabase production
        
        ```sql
        npx supabase db push
        ```
        
    6. **Make changes from the dashboard and generate migration**
        
        You can make changes from the dashboard. like creating tables, adding or altering columns, creating functions etc.
        
        <div data-node-type="callout">
        <div data-node-type="callout-emoji">💡</div>
        <div data-node-type="callout-text">There are limitation to this though. you cant run alter schema from auth and other protected schemas which are managed by Supabase from the Supabase dashboard directly. in that case you either use the SQL editor in Supabase dashboard or use the first method.</div>
        </div>
        
        1. **Generate migration content**
            
            ```bash
            npx supabase db diff
            ```
            
            if you have made changes related to protected schemas you need to add the schema flag and mention the schemas as Supabase don’t do it by default.
            
            ```bash
            npx supabase db diff --schema public,auth
            ```
            
            this will auto generate the migration based on the changes and give the output in `stdout` on the terminal. like the following.
            
            ![](https://cdn.hashnode.com/res/hashnode/image/upload/v1749453970890/efe02c37-6e53-4562-91dc-4edfa2cacb02.png align="center")
            
            just copy this content
            
            you can use this to create a new migration by creating a new migration file
            
        
        2\. **Create migration file**
        
        ```bash
        supabase migration new <migration_name>
        ```
        
        e:g
        
        ```bash
        supabase migration new schema_test
        ```
        
        and now copy the migration content into the generated file. the generate file should be inside the migrations folder with name something like this `20250609062017_schema_test`
        
        or you can simply use the following command to write the content directly to the file.
        
        ```bash
        npx supabase db diff --schema public,auth --file migrations/20250609_add_trigger.sql
        ```
        
        <div data-node-type="callout">
        <div data-node-type="callout-emoji">💡</div>
        <div data-node-type="callout-text">I would recommend generating the file using the command as it generates accurate timestamp.</div>
        </div>
        
        once this is done you can follow the same process as method one to apply changes changes, push to production and version control  
        

Resources: [Supabase docs](https://supabase.com/docs/guides/local-development?queryGroups=package-manager&package-manager=npm)
