Role: Developer laptop + coding agent  Β·  CLI: quemsi snapshot (--wait is the default)

This is not CI. Pipelines use Snapshot before deploy. Clicks in the console: Snapshot before a schema change. Any coding agent can run the same CLI; Cursor is the worked example below.

Before you start

Steps

1

Install the CLI

Download from /cli-releases/latest/. Put the binary on PATH. On Windows the file is quemsi.exe; the command is still quemsi.

Linux:

curl -fsSL -o quemsi https://quemsi.com/cli-releases/latest/quemsi && chmod +x quemsi && sudo mv quemsi /usr/local/bin/quemsi

Windows: download quemsi.exe and add it to PATH.

JAR (Java 21), either OS:

curl -fsSL -o quemsi.jar https://quemsi.com/cli-releases/latest/quemsi.jar
java -jar quemsi.jar snapshot --data … --agent …
2

Create a laptop token

Open Company Setup β†’ API tokens. Name it something like cursor-local. Bind it to your local agent. Scopes: snapshot and read only β€” not restore. See Create API tokens.

Put the secret in your shell profile or Cursor environment. Do not commit it.

export QUEMSI_TOKEN=qsk_...
# QUEMSI_URL defaults to https://quemsi.com
3

Snapshot before the schema changes

--wait is the default. Do not start the app, tests, or a migrate command until this exits 0.

quemsi snapshot --data YOUR_DATA --agent YOUR_LOCAL_AGENT \
  --tag work=baseline --tag purpose=pre-schema \
  --descript "pre-schema snapshot"

Use a distinct tag such as work=baseline. Restore lists the latest snapshot per tag combination. Do not reuse a nightly tag.

When to snapshot

Quemsi does not run your migration. Snapshot at the moment before the database schema changes. That moment depends on how you apply DDL.

Hibernate ddl-auto=update

There is no migrate CLI. Hibernate applies schema on the next app start (spring-boot:run, bootRun, tests that boot JPA, or Run/Debug in the IDE).

Snapshot after you edit entity / mapping files, before that boot. A hook that only watches Flyway or Liquibase will miss this.

Flyway, Liquibase, or SQL

Snapshot before the migrate command. Gate that command so it does not run if quemsi snapshot fails.

Cursor: rule plus hook

A rule tells the agent to snapshot first. The agent may skip it. A project hook is what actually fires. Commit the hook files; keep QUEMSI_TOKEN in user env.

Cursor’s afterFileEdit matcher is a tool type such as Write, not a file glob. Filter entity or migration paths in the script. afterFileEdit runs after the write; the snapshot still happens before the next boot. beforeShellExecution is what blocks migrate or bootRun if the snapshot fails. Matchers on that event are JavaScript-style regexes on the command string.

Rule (advisory)

Before applying a schema change β€” Hibernate auto-DDL on next boot, or a migrate command β€” run quemsi snapshot with work=baseline and purpose=pre-schema and wait for exit 0. Do not restore unless the person asks.

Project hook

Save as .cursor/hooks.json at the project root. Set failClosed so a failed snapshot (agent offline, missing token) blocks the edit or migrate.

{
  "version": 1,
  "hooks": {
    "afterFileEdit": [
      {
        "command": ".cursor/hooks/quemsi-snapshot.sh",
        "matcher": "Write|TabWrite",
        "failClosed": true
      }
    ],
    "beforeShellExecution": [
      {
        "command": ".cursor/hooks/quemsi-snapshot.sh",
        "matcher": "flyway|liquibase|migrate|spring-boot:run|bootRun",
        "failClosed": true
      }
    ]
  }
}

Save the script as .cursor/hooks/quemsi-snapshot.sh, make it executable, and replace YOUR_DATA / YOUR_LOCAL_AGENT. It needs quemsi and jq on PATH. It reads JSON on stdin. For file edits it snapshots only when the path looks like an entity or a migration. For shell it snapshots, then allows the command only if the snapshot exits 0.

#!/usr/bin/env bash
set -euo pipefail
input=$(cat)
file=$(printf '%s' "$input" | jq -r '.file_path // .path // empty')
command=$(printf '%s' "$input" | jq -r '.command // empty')

needs_snapshot=0
if [[ -n "$file" && "$file" =~ (entity|Entity\.java|/db/migration/|liquibase|flyway) ]]; then
  needs_snapshot=1
fi
if [[ -n "$command" && "$command" =~ (flyway|liquibase|migrate|spring-boot:run|bootRun) ]]; then
  needs_snapshot=1
fi

if [[ "$needs_snapshot" -eq 0 ]]; then
  if [[ -n "$command" ]]; then
    echo '{ "permission": "allow" }'
  fi
  exit 0
fi

quemsi snapshot --data YOUR_DATA --agent YOUR_LOCAL_AGENT \
  --tag work=baseline --tag purpose=pre-schema \
  --descript "pre-schema snapshot"

if [[ -n "$command" ]]; then
  echo '{ "permission": "allow" }'
fi
exit 0

Do not match every mvn test unless you want a snapshot on each test run. Do not put QUEMSI_TOKEN in the repo.

Restore is a person

If the schema change goes wrong, overwrite back from the UI: Restore a tagged snapshot, filter to work=baseline. Or run an explicit quemsi restore yourself. Do not auto-restore from the coding agent. Restore overwrites the target database.

Gaps

Not this page

Token, then snapshot

Bind a laptop token to your local agent, install quemsi, snapshot before Hibernate or a migration.

Open API tokens

Next