QueryDeck Docs
Drift Mode

The Fix button

What runs when you click Fix, how the command is resolved per package manager, and what's logged.

For: developers.

When Drift Mode shows a difference, the Fix button on the card runs your ORM's migration command. QueryDeck does not invent SQL — it runs the same command you would run yourself in the terminal, with the right package manager detected for your project.

This page documents exactly what gets executed, the confirmation flow, and the audit log.

What "Fix" means per ORM

The command template depends on the ORM and on which direction the drift goes:

ORMDirectionCommand template
PrismaDB ahead of code (introspect from DB){runner} prisma db pull
PrismaCode ahead of DB (apply schema){runner} prisma migrate dev
DrizzleCode ahead of DB{runner} drizzle-kit push
DrizzleDB ahead of code{runner} drizzle-kit introspect
TypeORMCode ahead of DB{runner} typeorm migration:generate && {runner} typeorm migration:run
DjangoCode ahead of DBpython manage.py makemigrations && python manage.py migrate
DjangoDB ahead of codepython manage.py inspectdb
RailsCode ahead of DBrails db:migrate
RailsDB ahead of coderails db:schema:dump

The exact resolveCommand and pullCommand for the current ORM are visible at the top of the Drift screen.

The {runner} substitution

For JavaScript ORMs (Prisma, Drizzle, TypeORM), the command needs to run through your package manager so it picks up the locally-installed binary. {runner} is a placeholder that QueryDeck replaces based on what your project actually uses.

Package managerDetected fromRunner inserted
Bunbun.lockb or bun.lockbunx
pnpmpnpm-lock.yamlpnpm exec
Yarnyarn.lockyarn exec
npmpackage-lock.json or fallbacknpx

Detection walks up from your project root checking for lock files. If none are found, QueryDeck reads the packageManager field of package.json. If that's missing too, it falls back to npx.

Python and Ruby ORMs don't use {runner}python manage.py and rails are called directly.

The confirmation flow

Clicking Fix never runs anything immediately. The flow is:

  1. Card — click Fix on the drift card you want to address.

  2. Resolved command preview — a sheet appears showing the exact shell command that will run, the working directory, and the package manager used:

    Run this command?
    
      pnpm exec prisma migrate dev
    
    Working directory: /Users/you/code/myapp
    Package manager:   pnpm
    
    [Cancel]  [Run]
  3. Confirm — click Run to execute. Click Cancel to do nothing.

  4. Execution — the command runs in a login shell so your nvm, corepack, and PATH setup are respected. Output streams to a panel at the bottom of the Drift screen.

  5. Result — when the command exits, the panel shows the exit code, stdout, and stderr. If it succeeded, Drift Mode re-runs the diff and updates the cards.

There is no --yes mode in the GUI. Every Fix requires a confirm click. This is intentional — migrations are write operations and we want a deliberate gesture.

Fix All

When the hero banner says "Fix All", clicking it runs the same resolveCommand once for the whole batch. This is the common case for Prisma and Drizzle, where one prisma migrate dev brings everything in line.

For Django, "Fix All" runs makemigrations && migrate. For TypeORM, the migrations are generated and then run in one step.

How the command actually runs

Under the hood, QueryDeck uses the macOS Process API. The shell line is:

$SHELL -i -l -c "cd <project root> && <resolved command>"
  • -i makes the shell interactive so it reads ~/.zshrc (where nvm, corepack, project-specific aliases usually live).
  • -l makes it a login shell so it reads ~/.zprofile and /etc/zprofile.
  • The cd ensures the command runs in your project root.
  • $SHELL is whichever shell macOS reports — usually zsh, sometimes bash.

This is important because GUI apps on macOS get a minimal PATH (/usr/bin:/bin). Without -i -l, pnpm, bun, and Node.js installed via nvm would not be found.

Timeout

Each Fix command has a 120-second timeout. If the migration takes longer (a big schema change, slow migrations, a stuck lock), the command is killed and a timeout error is shown. The database state at that point is whatever the migration tool committed before being killed — often partial. Re-run from the terminal to see the full output.

The audit log

Every Fix execution is logged to:

~/.querydeck/fix-audit.log

Each entry is one line:

2026-05-28T14:32:11Z cmd="pnpm exec prisma migrate dev" cwd="/Users/you/code/myapp" exit=0 stdout="..." stderr="..."

stdout and stderr are truncated to 500 characters. The full output is only available in the panel during the session, not on disk.

When Fix isn't available

The Fix button is hidden for drift items that don't have a safe automated resolution:

  • Custom database objects (extensions, materialized views, custom types) — the ORM doesn't manage these, so its migration command wouldn't add them.
  • Drift in suppressed objects (those listed in .querydeck/drift-ignore.yml).
  • Read-only connections — Fix is disabled when the connection is read-only.

For these, the card still shows the diff and the generated SQL is copyable. You apply it manually in the SQL editor or via your migration tool.

Production safety

If the connection is colored red (production), clicking Fix shows an additional warning sheet before the confirmation:

You're about to run a migration on a production connection.

Are you sure you want to apply schema changes to:
  prod-db.example.com → myapp_production

Type the connection name to confirm: ____________

This is on by default. To disable, SettingsDriftConfirm production fixes (not recommended).

What's next