add-malli-schemas
Efficiently add Malli schemas to API endpoints in the Metabase codebase with proper patterns, validation timing, and error…
Add, test, run and roll back application-database (Liquibase) migrations. Use when adding a changeset, changing a table or column in the Metabase app DB, writing a custom (Clojure) migration, or rolling migrations back in development.
$ npx -y skills add metabase/metabase --skill app-db-migrations --agent claude-codeHow it fires
How this skill gets triggered: by you, by Claude, or both.
/app-db-migrationsContext preview
The summary Claude sees to decide when to auto-load this skill.
Add, test, run and roll back application-database (Liquibase) migrations. Use when adding a changeset, changing a table or column in the Metabase app DB, writing a custom (Clojure) migration, or rolling migrations back in development.
name: app-db-migrations description: Add, test, run and roll back application-database (Liquibase) migrations. Use when adding a changeset, changing a table or column in the Metabase app DB, writing a custom (Clojure) migration, or rolling migrations back in development.
Schema changes to the Metabase application database are Liquibase changesets in YAML under `resources/migrations/`. Every changeset in the repository is linted by `./bin/lint-migrations-file.sh` (`mage lint-migrations`); run it before pushing.
New changesets are **version-less** and live in a year directory. Create one with `./bin/mage new-migration <snake_case_name>`, which writes:
resources/migrations/2026/20261012_short_snake_case_name.yaml # changeset id: a random one, e.g. k3x9qa
digits and underscores only). One file per change or per closely related group of changes; several changesets in one file are fine.
first changeset, checking it is unused in `resources/migrations`. For more changesets in the same file, make up another the same way and grep to confirm it is unused. The lint accepts lower-case letters, digits and underscores with at least one letter -- not an ISO date or timestamp like the old ids carried (`2026-09-18T12:00:00`), not `v66.…`, not all digits, and no leading `v`: releases from before version-less support read the schema's version from the highest `id LIKE 'v%'`.
Do **not** start new work in the versioned files (`migrations/0NN/…` with `vNN.` ids, or `0NN_update_migrations.yaml`). The lint still accepts `vNN.` ids up to v66, so changesets already in flight for 66 can land, and refuses them from v67 on. Don't add versioned changesets on release branches either: changelog order puts every versioned file before the year directories, so a versioned changeset added after a version-less one would run before it on a fresh install but after it on an upgraded one.
Version-less support is backported to patch releases of every supported major back to v58, so a version-less changeset is backported like any other change: cherry-pick the **same file** onto each release branch. Liquibase identifies a changeset by file path, id and author, so the upgraded customer's database already has it as run. A few rules follow from the same changeset meeting different histories:
another branch fails checksum validation when a customer upgrades onto it. Fix a mistake with a new changeset.
major to any later one.
major's `vNN.` changesets; on a database upgraded from an older major's patch it already ran before them. Make sure none of the later majors' changesets conflict with it either way round, e.g. by both creating the same object.
changelog rows they don't know, and Metabase keeps a marker row last in `databasechangelog` so they read the schema's version correctly (see `metabase.app-db.liquibase.versions/record-legacy-version-tracking!`).
databaseChangeLog:
- changeSet:
id: k3x9qa
author: yourgithubhandle
comment: Add entity_id to glossary
changes:
- addColumn:
tableName: glossary
columns:
- column:
name: entity_id
type: varchar(21)
remarks: NanoID for serialization
rollback:
- dropColumn:
tableName: glossary
columnName: entity_idRules the lint enforces (and reviewers expect):
`boolean`, `text`, `blob`, `datetime` or `timestamp without time zone`.
`addColumn`, `createIndex`, `addForeignKeyConstraint`, `renameColumn`, …). `sql`, `dropColumn`, `dropTable`, `modifyDataType` and the like need an explicit rollback (an empty `rollback:` is allowed when there is genuinely nothing to undo).
`uniqueConstraintExists` need `tableName`, `foreignKeyConstraintExists` needs `foreignKeyTableName`), or Liquibase snapshots the whole schema to answer them. Preconditions are rarely needed at all: rely on Liquibase's changeset tracking.
contains. `runOnChange: true` changesets (views) are the one exception and may be edited in place.
Never j
Metabase is the easy, open-source way for everyone in your company to ask questions and learn from data.
Efficiently add Malli schemas to API endpoints in the Metabase codebase with proper patterns, validation timing, and error…
Add OpenTelemetry tracing spans to Clojure code following Metabase tracing conventions. Use when instrumenting backend code with…
Add product analytics events to track user interactions in the Metabase frontend
Draft or audit the REST API changelog (docs/developers-guide/api-changelog.md) by semantically diffing the checked-in OpenAPI…
Where Metabase backend code goes and how it reaches the app DB. Covers module layout, the `<module>.db` rule, `[:auto/param]`…
Evaluate Clojure code via nREPL using clj-nrepl-eval. Use this when you need to test code, check if edited files compile, verify…