Skip to content

Instantly share code, notes, and snippets.

@saifsmailbox98
Last active April 14, 2026 15:21
Show Gist options
  • Select an option

  • Save saifsmailbox98/12f77b806e0823122fc6997b827e544b to your computer and use it in GitHub Desktop.

Select an option

Save saifsmailbox98/12f77b806e0823122fc6997b827e544b to your computer and use it in GitHub Desktop.

Enhanced Dev Environment Setup

Not responsible for melted desks, burnt thighs, or AppleCare claims.

This guide sets up an improved local development environment with:

  • just as a task runner (replacement for make)
  • portless for .test domain names instead of localhost:port
  • Git worktrees for working on multiple tasks in parallel, each with its own isolated Docker stack
  • mitmproxy for inspecting HTTP requests between frontend and backend
  • Mailpit as a standalone SMTP server shared across all stacks
  • tsgo (native TypeScript compiler) for 10x faster type checking

Prerequisites

brew install just
npm install -g portless

Just shell completions (zsh)

mkdir -p ~/.zsh/completions
just --completions zsh > ~/.zsh/completions/_just

Add to ~/.zshrc:

fpath=(~/.zsh/completions $fpath)
autoload -U compinit
compinit

Start portless proxy (one-time, persists in background)

portless proxy start --tld test

Docker Desktop settings (recommended)

  • Disk image size: 120 GB (Settings → Resources)
  • Memory: 16 GB (Settings → Resources)

Files to Create

All files are local to your clone — nothing gets committed. They are ignored via .git/info/exclude.

1. .git/info/exclude

Append these lines to your existing .git/info/exclude:

# Personal dev setup
docker-compose.dev.override.yml
docker-compose.worktree.yml
docker-compose.worktree.debug.yml
justfile
README.dev.md
nginx/default.dev.debug.conf

2. justfile (project root)

# Default project name is the current directory name
default_name := `basename "$PWD"`

# --- Main dev environment (existing workflow) ---

up-dev:
    #!/usr/bin/env bash
    set -euo pipefail
    # Update .env with the correct site URL
    grep -q '^SITE_URL=' .env && sed -i '' 's|^SITE_URL=.*|SITE_URL=https://infisical.test|' .env || echo 'SITE_URL=https://infisical.test' >> .env
    grep -q '^VITE_ALLOWED_HOSTS=' .env && sed -i '' 's|^VITE_ALLOWED_HOSTS=.*|VITE_ALLOWED_HOSTS=infisical.test|' .env || echo 'VITE_ALLOWED_HOSTS=infisical.test' >> .env
    docker compose -f docker-compose.dev.yml -f docker-compose.dev.override.yml up --build -d
    portless alias infisical 8080 --tld test --force 2>/dev/null || true
    portless alias db.infisical 5432 --tld test --force 2>/dev/null || true
    portless alias redis.infisical 6379 --tld test --force 2>/dev/null || true
    @echo ""
    @echo "App:      https://infisical.test"
    @echo "Postgres: db.infisical.test (port 5432)"
    @echo "Redis:    redis.infisical.test (port 6379)"
    @echo "psql:     psql -h db.infisical.test -U infisical -d infisical"

up-dev-ldap:
    docker compose -f docker-compose.dev.yml -f docker-compose.dev.override.yml --profile ldap up --build -d
    portless alias infisical 8080 --tld test --force 2>/dev/null || true
    portless alias db.infisical 5432 --tld test --force 2>/dev/null || true
    portless alias redis.infisical 6379 --tld test --force 2>/dev/null || true
    @echo ""
    @echo "App:      https://infisical.test"
    @echo "Postgres: db.infisical.test (port 5432)"
    @echo "Redis:    redis.infisical.test (port 6379)"

up-dev-metrics:
    docker compose -f docker-compose.dev.yml -f docker-compose.dev.override.yml --profile metrics up --build -d
    portless alias infisical 8080 --tld test --force 2>/dev/null || true
    portless alias db.infisical 5432 --tld test --force 2>/dev/null || true
    portless alias redis.infisical 6379 --tld test --force 2>/dev/null || true
    @echo ""
    @echo "App:      https://infisical.test"
    @echo "Postgres: db.infisical.test (port 5432)"
    @echo "Redis:    redis.infisical.test (port 6379)"

up-dev-sso:
    docker compose -f docker-compose.dev.yml -f docker-compose.dev.override.yml --profile sso up --build -d
    portless alias infisical 8080 --tld test --force 2>/dev/null || true
    portless alias db.infisical 5432 --tld test --force 2>/dev/null || true
    portless alias redis.infisical 6379 --tld test --force 2>/dev/null || true
    @echo ""
    @echo "App:      https://infisical.test"
    @echo "Postgres: db.infisical.test (port 5432)"
    @echo "Redis:    redis.infisical.test (port 6379)"

up-prod:
    docker compose -f docker-compose.prod.yml up --build

down-dev:
    docker compose -f docker-compose.dev.yml down

reviewable-ui:
    cd frontend && npm run lint:fix && npm run type:check

reviewable-api:
    cd backend && npm run lint:fix && npm run type:check

reviewable: reviewable-ui reviewable-api

# --- Worktree stacks ---

# Start a full isolated stack for the current worktree
# Usage: just up [name] [--no-fips]
up name=default_name *flags="":
    #!/usr/bin/env bash
    set -euo pipefail

    NAME="{{name}}"
    PG_SOURCE="infisical_postgres-data1"

    # Check for --no-fips flag
    for flag in {{flags}}; do
        if [ "$flag" = "--no-fips" ]; then
            PG_SOURCE="infisical_postgres-data"
        fi
    done

    PG_VOLUME="${NAME}_postgres-data"

    # Clone the postgres volume if this task doesn't have one yet
    if ! docker volume inspect "$PG_VOLUME" > /dev/null 2>&1; then
        echo "Cloning $PG_SOURCE → $PG_VOLUME..."
        docker volume create "$PG_VOLUME" > /dev/null
        docker run --rm \
            -v "$PG_SOURCE":/from:ro \
            -v "$PG_VOLUME":/to \
            alpine sh -c "cp -a /from/. /to/"
        echo "Done."
    else
        echo "Volume $PG_VOLUME already exists, reusing."
    fi

    # Update .env with the correct site URL
    if [ -f .env ]; then
        grep -q '^SITE_URL=' .env && sed -i '' "s|^SITE_URL=.*|SITE_URL=https://$NAME.test|" .env || echo "SITE_URL=https://$NAME.test" >> .env
        grep -q '^VITE_ALLOWED_HOSTS=' .env && sed -i '' "s|^VITE_ALLOWED_HOSTS=.*|VITE_ALLOWED_HOSTS=$NAME.test|" .env || echo "VITE_ALLOWED_HOSTS=$NAME.test" >> .env
    fi

    # Start the stack
    PG_VOLUME="$PG_VOLUME" docker compose \
        -p "$NAME" \
        -f docker-compose.worktree.yml \
        up --build -d

    # Wait a moment for containers to get ports assigned
    sleep 2

    # Get the nginx container's host port
    NGINX_CONTAINER="${NAME}-nginx-1"
    NGINX_PORT=$(docker port "$NGINX_CONTAINER" 80 2>/dev/null | head -1 | cut -d: -f2)

    # Get the postgres container's host port
    DB_CONTAINER="${NAME}-db-1"
    DB_PORT=$(docker port "$DB_CONTAINER" 5432 2>/dev/null | head -1 | cut -d: -f2)

    # Get the redis container's host port
    REDIS_CONTAINER="${NAME}-redis-1"
    REDIS_PORT=$(docker port "$REDIS_CONTAINER" 6379 2>/dev/null | head -1 | cut -d: -f2)

    # Register with portless
    portless alias "$NAME" "$NGINX_PORT" --tld test --force 2>/dev/null || true
    portless alias "db.$NAME" "$DB_PORT" --tld test --force 2>/dev/null || true
    portless alias "redis.$NAME" "$REDIS_PORT" --tld test --force 2>/dev/null || true

    echo ""
    echo "Stack '$NAME' is running:"
    echo "  App:      https://$NAME.test"
    echo "  Postgres: db.$NAME.test (port $DB_PORT)"
    echo "  Redis:    redis.$NAME.test (port $REDIS_PORT)"
    echo "  psql:     psql -h db.$NAME.test -U infisical -d infisical"

# Stop a worktree stack (keeps volumes)
down name=default_name:
    #!/usr/bin/env bash
    set -euo pipefail

    NAME="{{name}}"

    docker compose \
        -p "$NAME" \
        -f docker-compose.worktree.yml \
        -f docker-compose.worktree.debug.yml \
        down 2>/dev/null || \
    docker compose \
        -p "$NAME" \
        -f docker-compose.worktree.yml \
        down

    # Remove portless aliases
    portless alias --remove "$NAME" 2>/dev/null || true
    portless alias --remove "debug.$NAME" 2>/dev/null || true
    portless alias --remove "db.$NAME" 2>/dev/null || true
    portless alias --remove "redis.$NAME" 2>/dev/null || true

    echo "Stack '$NAME' stopped. Volumes preserved."

# Remove a worktree stack's containers AND volumes
rm name=default_name:
    #!/usr/bin/env bash
    set -euo pipefail

    NAME="{{name}}"

    docker compose \
        -p "$NAME" \
        -f docker-compose.worktree.yml \
        -f docker-compose.worktree.debug.yml \
        down -v 2>/dev/null || \
    docker compose \
        -p "$NAME" \
        -f docker-compose.worktree.yml \
        down -v

    # Remove the cloned postgres volume
    docker volume rm "${NAME}_postgres-data" 2>/dev/null || true

    # Remove portless aliases
    portless alias --remove "$NAME" 2>/dev/null || true
    portless alias --remove "debug.$NAME" 2>/dev/null || true
    portless alias --remove "db.$NAME" 2>/dev/null || true
    portless alias --remove "redis.$NAME" 2>/dev/null || true

    echo "Stack '$NAME' removed (containers + volumes)."

# Start a worktree stack with mitmproxy (request inspector)
up-debug name=default_name *flags="":
    #!/usr/bin/env bash
    set -euo pipefail

    NAME="{{name}}"
    PG_SOURCE="infisical_postgres-data1"

    # Check for --no-fips flag
    for flag in {{flags}}; do
        if [ "$flag" = "--no-fips" ]; then
            PG_SOURCE="infisical_postgres-data"
        fi
    done

    PG_VOLUME="${NAME}_postgres-data"

    # Clone the postgres volume if this task doesn't have one yet
    if ! docker volume inspect "$PG_VOLUME" > /dev/null 2>&1; then
        echo "Cloning $PG_SOURCE → $PG_VOLUME..."
        docker volume create "$PG_VOLUME" > /dev/null
        docker run --rm \
            -v "$PG_SOURCE":/from:ro \
            -v "$PG_VOLUME":/to \
            alpine sh -c "cp -a /from/. /to/"
        echo "Done."
    else
        echo "Volume $PG_VOLUME already exists, reusing."
    fi

    # Update .env with the correct site URL
    if [ -f .env ]; then
        grep -q '^SITE_URL=' .env && sed -i '' "s|^SITE_URL=.*|SITE_URL=https://$NAME.test|" .env || echo "SITE_URL=https://$NAME.test" >> .env
        grep -q '^VITE_ALLOWED_HOSTS=' .env && sed -i '' "s|^VITE_ALLOWED_HOSTS=.*|VITE_ALLOWED_HOSTS=$NAME.test|" .env || echo "VITE_ALLOWED_HOSTS=$NAME.test" >> .env
    fi

    # Start the stack with mitmproxy
    PG_VOLUME="$PG_VOLUME" docker compose \
        -p "$NAME" \
        -f docker-compose.worktree.yml \
        -f docker-compose.worktree.debug.yml \
        up --build -d

    # Wait a moment for containers to get ports assigned
    sleep 2

    # Get the nginx container's host port
    NGINX_CONTAINER="${NAME}-nginx-1"
    NGINX_PORT=$(docker port "$NGINX_CONTAINER" 80 2>/dev/null | head -1 | cut -d: -f2)

    # Get the mitmweb UI port
    MITM_CONTAINER="${NAME}-mitmproxy-1"
    MITM_PORT=$(docker port "$MITM_CONTAINER" 8081 2>/dev/null | head -1 | cut -d: -f2)

    # Get the postgres container's host port
    DB_CONTAINER="${NAME}-db-1"
    DB_PORT=$(docker port "$DB_CONTAINER" 5432 2>/dev/null | head -1 | cut -d: -f2)

    # Get the redis container's host port
    REDIS_CONTAINER="${NAME}-redis-1"
    REDIS_PORT=$(docker port "$REDIS_CONTAINER" 6379 2>/dev/null | head -1 | cut -d: -f2)

    # Register with portless
    portless alias "$NAME" "$NGINX_PORT" --tld test --force 2>/dev/null || true
    portless alias "debug.$NAME" "$MITM_PORT" --tld test --force 2>/dev/null || true
    portless alias "db.$NAME" "$DB_PORT" --tld test --force 2>/dev/null || true
    portless alias "redis.$NAME" "$REDIS_PORT" --tld test --force 2>/dev/null || true

    echo ""
    echo "Stack '$NAME' is running with mitmproxy:"
    echo "  App:      https://$NAME.test"
    echo "  mitmweb:  https://debug.$NAME.test (request inspector, password: password)"
    echo "  Postgres: db.$NAME.test (port $DB_PORT)"
    echo "  Redis:    redis.$NAME.test (port $REDIS_PORT)"
    echo "  psql:     psql -h db.$NAME.test -U infisical -d infisical"

# List all running worktree stacks
ls:
    @docker ps --filter "label=com.docker.compose.project" --format "table {{{{.Names}}}}\t{{{{.Status}}}}\t{{{{.Ports}}}}" | head -50

# --- Standalone tools ---

mailpit:
    docker run -d --name mailpit -p 1025:1025 -p 8025:8025 --restart unless-stopped axllent/mailpit

mailpit-stop:
    docker stop mailpit && docker rm mailpit

# --- TypeScript native compiler (tsgo) ---

tsgo-fe:
    cd frontend && npm install --save-dev @typescript/native-preview@latest

tsgo-be:
    cd backend && npm install --save-dev @typescript/native-preview@latest

tsgo: tsgo-fe tsgo-be

3. docker-compose.dev.override.yml (project root)

Profiles out pgAdmin, redis-commander, and smtp-server from the default dev stack so they only start with --profile tools.

services:
  pgadmin:
    profiles: [tools]
  redis-commander:
    profiles: [tools]
  smtp-server:
    profiles: [tools]

4. docker-compose.worktree.yml (project root)

Full isolated stack for worktrees. All host ports are random (0:port) to avoid conflicts when running multiple stacks.

services:
  nginx:
    image: nginx
    restart: "always"
    ports:
      - "0:80"
    volumes:
      - ./nginx/default.dev.conf:/etc/nginx/conf.d/default.conf:ro
    depends_on:
      - backend
      - frontend

  db:
    image: postgres:14-alpine
    ports:
      - "0:5432"
    volumes:
      - postgres_data:/var/lib/postgresql/data
    environment:
      POSTGRES_PASSWORD: infisical
      POSTGRES_USER: infisical
      POSTGRES_DB: infisical

  redis:
    image: redis
    environment:
      - ALLOW_EMPTY_PASSWORD=yes
    ports:
      - "0:6379"
    volumes:
      - redis_data:/data

  clickhouse:
    image: clickhouse/clickhouse-server:25.12.5
    restart: unless-stopped
    ports:
      - "0:8123"
      - "0:9000"
    volumes:
      - clickhouse_data:/var/lib/clickhouse
      - clickhouse_logs:/var/log/clickhouse-server
    environment:
      - CLICKHOUSE_DB=infisical
      - CLICKHOUSE_USER=infisical
      - CLICKHOUSE_PASSWORD=infisical
      - CLICKHOUSE_DEFAULT_ACCESS_MANAGEMENT=1
    ulimits:
      nofile:
        soft: 262144
        hard: 262144

  backend:
    image: infisical-dev-backend:latest
    build:
      context: ./backend
      dockerfile: Dockerfile.dev.fips
    depends_on:
      db:
        condition: service_started
      redis:
        condition: service_started
      clickhouse:
        condition: service_started
    env_file:
      - .env
    ports:
      - "0:4000"
    environment:
      - NODE_ENV=development
      - DB_CONNECTION_URI=postgres://infisical:infisical@db/infisical?sslmode=disable
      - TELEMETRY_ENABLED=false
    volumes:
      - ./backend/src:/app/src
      - softhsm_tokens:/etc/softhsm2/tokens
    extra_hosts:
      - "host.docker.internal:host-gateway"

  frontend:
    image: infisical-dev-frontend:latest
    restart: unless-stopped
    depends_on:
      - backend
    build:
      context: ./frontend
      dockerfile: Dockerfile.dev
    volumes:
      - ./frontend/src:/app/src/
      - ./frontend/public:/app/public
    env_file: .env

volumes:
  postgres_data:
    external: true
    name: ${PG_VOLUME}
  redis_data:
    driver: local
  clickhouse_data:
    driver: local
  clickhouse_logs:
    driver: local
  softhsm_tokens:
    driver: local

5. docker-compose.worktree.debug.yml (project root)

Compose override that adds mitmproxy between nginx and backend for request inspection.

services:
  mitmproxy:
    image: mitmproxy/mitmproxy
    command: mitmweb --mode reverse:http://backend:4000 --web-host 0.0.0.0 --listen-port 4000 --no-web-open-browser --set web_password=password
    restart: unless-stopped
    ports:
      - "0:8081"
    depends_on:
      - backend

  nginx:
    volumes:
      - ./nginx/default.dev.debug.conf:/etc/nginx/conf.d/default.conf:ro

6. nginx/default.dev.debug.conf

Same as nginx/default.dev.conf but routes API traffic through mitmproxy instead of directly to backend. Only difference is line 2:

upstream api {
    server mitmproxy:4000;
}

server {
    listen 80;

    large_client_header_buffers 8 128k;
    client_header_buffer_size 128k;

    # WebSocket endpoint for PAM web access
    location ~ ^/api/v1/pam/accounts/[^/]+/web-access$ {
        proxy_set_header X-Real-RIP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;

        proxy_set_header Host $http_host;
        proxy_set_header X-NginX-Proxy true;

        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";

        proxy_buffering off;
        proxy_cache off;

        proxy_read_timeout 4200s;
        proxy_send_timeout 4200s;

        proxy_pass http://api;
        proxy_redirect off;

        proxy_cookie_path / "/; SameSite=strict";
    }

    location ~ ^/(api|secret-scanning/webhooks) {
        proxy_set_header X-Real-RIP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;

        proxy_set_header Host $http_host;
        proxy_set_header X-NginX-Proxy true;

        proxy_pass http://api;
        proxy_redirect off;

        proxy_cookie_path / "/; SameSite=strict";
    }

    location /runtime-ui-env.js {
        proxy_set_header X-Real-RIP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;

        proxy_set_header Host $http_host;
        proxy_set_header X-NginX-Proxy true;

        proxy_pass http://api;
        proxy_redirect off;

        proxy_cookie_path / "/; HttpOnly; SameSite=strict";
    }

    location /api/v3/migrate {
        client_max_body_size 25M;

        proxy_set_header X-Real-RIP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;

        proxy_set_header Host $http_host;
        proxy_set_header X-NginX-Proxy true;

        proxy_pass http://api;
        proxy_redirect off;

        proxy_cookie_path / "/; HttpOnly; SameSite=strict";
    }

    location /scep {
        proxy_set_header X-Real-RIP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;

        proxy_set_header Host $http_host;
        proxy_set_header X-NginX-Proxy true;

        proxy_pass http://api;
        proxy_redirect off;

        proxy_cookie_path / "/; HttpOnly; SameSite=strict";
    }

    location ~ /\.well-known {
        proxy_set_header X-Real-RIP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;

        proxy_set_header Host $http_host;
        proxy_set_header X-NginX-Proxy true;

        proxy_set_header X-SSL-Client-Cert $ssl_client_escaped_cert;

        proxy_pass http://api;
        proxy_redirect off;

        proxy_cookie_path / "/; HttpOnly; SameSite=strict";
    }

    location / {
        include /etc/nginx/mime.types;

        proxy_set_header X-Real-RIP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;

        proxy_set_header Host $http_host;
        proxy_set_header X-NginX-Proxy true;

        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";

        proxy_pass http://frontend:3000;
        proxy_redirect off;
    }
}

7. .git/local-hooks/post-checkout

Git hook that automatically copies all dev files into new worktrees. Must be executable (chmod +x).

#!/bin/bash
OLD_REF=$1

# Only run for new worktrees (old ref is all zeros)
if [ "$OLD_REF" = "0000000000000000000000000000000000000000" ]; then
    MAIN_REPO="$(git rev-parse --git-common-dir)/.."
    WORKTREE="$(git rev-parse --show-toplevel)"

    cp "$MAIN_REPO/justfile" "$WORKTREE/" 2>/dev/null
    cp "$MAIN_REPO/docker-compose.worktree.yml" "$WORKTREE/" 2>/dev/null
    cp "$MAIN_REPO/docker-compose.worktree.debug.yml" "$WORKTREE/" 2>/dev/null
    cp "$MAIN_REPO/docker-compose.dev.override.yml" "$WORKTREE/" 2>/dev/null
    cp "$MAIN_REPO/README.dev.md" "$WORKTREE/" 2>/dev/null
    cp "$MAIN_REPO/.env" "$WORKTREE/" 2>/dev/null
    mkdir -p "$WORKTREE/nginx"
    cp "$MAIN_REPO/nginx/default.dev.debug.conf" "$WORKTREE/nginx/" 2>/dev/null
    echo "Dev files copied into worktree: $WORKTREE"
fi

8. Git hooks path config

Husky overrides the default hooks directory. To use our custom hook alongside Husky's pre-commit:

# Create local hooks directory
mkdir -p .git/local-hooks/_

# Copy Husky's pre-commit hook and helper
cp .husky/pre-commit .git/local-hooks/
cp .husky/_/husky.sh .git/local-hooks/_/

# Copy the post-checkout hook (from step 7 above)
# Make it executable
chmod +x .git/local-hooks/post-checkout
chmod +x .git/local-hooks/pre-commit

# Point git to the local hooks directory
git config --local core.hooksPath .git/local-hooks

Workflow

Main repo (day-to-day)

just up-dev                   # → https://infisical.test
just down-dev                 # stop

New task in a worktree

# Create worktree (hook auto-copies dev files + .env)
git fetch origin
git worktree add ../my-feature -b feat/my-feature origin/main
cd ../my-feature

# Optional: enable fast TS compiler
just tsgo

# Start isolated stack
just up                       # → https://my-feature.test

Review a PR

git fetch origin
git worktree add ../review-pr origin/feat/some-feature
cd ../review-pr
just up                       # → https://review-pr.test

Multiple stacks simultaneously

Both run at the same time on different domains:

  • https://my-feature.test
  • https://review-pr.test

Inspect API requests

just up-debug                 # → app at https://my-feature.test
                              # → mitmweb UI at https://debug.my-feature.test (password: password)

Stop / clean up

just down                     # stop containers, keep volumes (resume later)
just up                       # resume with same DB state

just rm                       # remove containers + volumes (permanent)

# Remove the worktree
cd ~/infi/repos/infisical
git worktree remove ../review-pr

Standalone mailpit (shared SMTP)

just mailpit                  # start — SMTP on 1025, UI on http://localhost:8025
just mailpit-stop             # stop

All Commands

Command What it does
just up-dev Start main dev stack → https://infisical.test
just up-dev-ldap Start with LDAP profile
just up-dev-sso Start with SSO profile
just up-dev-metrics Start with metrics profile
just down-dev Stop main dev stack
just up Start worktree stack (uses directory name)
just up my-name Start with custom name
just up --no-fips Clone non-FIPS postgres volume
just up-debug Start with mitmproxy request inspector
just down Stop worktree stack, keep volumes
just rm Remove worktree stack + volumes
just ls List all running stacks
just mailpit Start standalone mailpit
just mailpit-stop Stop mailpit
just tsgo Install latest tsgo in both frontend and backend
just tsgo-fe Install latest tsgo in frontend only
just tsgo-be Install latest tsgo in backend only
just reviewable Lint + typecheck both frontend and backend
just reviewable-ui Lint + typecheck frontend
just reviewable-api Lint + typecheck backend
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment