Skip to content

Look at a SQL Yodeler project

llms.txtlists every page for an agent
Optional: hand this page to your coding agentThe steps work by hand too.
Show the whole prompt
Read https://intentius.io/behold/using/sql-yodeler/.
Serve this SQL Yodeler project with `npx @intentius/behold serve .` and tell me the URL.
List the environments the Releases tab shows.
For each gate that waits, show me the `yodel approve` line to run myself.
Never deploy with the Deploy button, `POST /api/apply` or `POST /api/ci/dispatch`. Gate approvals stay mine as well (`/api/ops/:name/signal/:gate`, `/api/workspace/gates/approve`, `/api/operator/approve/:op/:gate`). Op runs (`/api/ops/:name/run`) and rollbacks (`/api/rollback`) are mine too. Leave `--auto-sync` off, and keep a `behold preview` or `--public` serve read-only.

SQL Yodeler plans and applies database migrations through chant, one environment at a time. behold draws the project’s declared schema and reads what yodel and chant already wrote about each environment. It never writes to the repository, its chant/lifecycle branch or a database.

behold serve . in a SQL Yodeler project draws what src/ declares: Postgres schemas, tables, indexes and the rest, or ClickHouse databases and tables, each card named by its kind (“Postgres table”) and its qualified name, with the column and foreign key count. A table that REFERENCES another has an edge to it. The migrations ops in ops/ draw as Chant::Op cards.

The Pipeline tab reads the gates SQL Yodeler and chant write on chant/lifecycle: the apply pipeline’s waves (_gates/yodel-apply.jsonl, one gate yodel-apply-wave-<k> per environment) and each environment’s migrations op (_gates/migrate-<env>.jsonl, gate approve-migrate-<env>). Environments are listed in the order yodel-waves.json applies them.

Each gate says whether it waits, was approved, applied, or was refused, the plan digest it is bound to, who approved it and how (signed, through a pull request’s review), and which commit of chant/lifecycle it was read from and how old that is. A waiting gate shows the line to approve it:

Terminal window
npx yodel approve prod --plan <digest>

Copy it and run it yourself; behold has no approve button for SQL Yodeler.

When the waves in yodel-waves.json at the base commit name different approval modes (say pr-review for staging and sealed for prod), each wave is decided under its own mode. A wave’s request records the mode it asked under, and its card shows it; a request written by an older chant records none, and then the card says the mode was read at base. A wave that names none takes chant’s rule. A wave held on another gate names the hook that holds it. Under pr-review, a waiting wave also lists the pull request heads whose recorded plans (_wave-plans/yodel-apply/<head>.json) name its digest: a writer’s approving review of that head, once merged, approves it when the wave runs again. behold does not read the forge, so it cannot say whether that review exists.

A project that is a member of a chant workspace keeps all of this under _members/<member>/ on chant/lifecycle. behold asks chant which member owns the served directory and reads the gates, the head plans and the releases there; the legend names the member.

Under the tab, the gate ledgers’ history lists every request, approval and apply in the order they were committed.

The history table that records which migrations ran lives in the database, which behold does not connect to; the report files below and the release ledger cover that ground.

After every apply SQL Yodeler appends a release record to <env>/releases.jsonl on the repository’s chant/lifecycle branch, keyed by the digest of the schema the environment now holds.

When the served directory has a yodel.config.ts or a yodel-waves.json, behold adds a Releases tab: one column per environment, one row per component or tenant (<component>/<tenant>). Each cell is that environment’s newest release, with its digest, when it was recorded, who ran it and who approved it, and the chant/lifecycle commit it was read from.

Columns follow the wave order in yodel-waves.json. A cell whose digest the environment before it does not hold is marked “differs from <env>”, and its hover gives both digests and says whether that environment ever recorded this one. It answers the same question as chant components status prod --compare-to staging.

behold fetches chant/lifecycle from the checkout’s origin into a cache of its own and reads it with chant’s release-ledger reader. If the fetch fails it reads the checkout’s origin/chant/lifecycle instead and says so. It never writes to the repository, the branch or a database. behold export carries the strip as a snapshot of the moment it ran.

Terminal window
yodel report --json > out/report.json
yodel drift prod --json > out/drift-prod.json
behold serve . --yodel-report out/

--yodel-report takes the report file, or the directory holding it. Any drift JSON in the same directory is read too. behold never runs yodel and never connects to the database: it reads the files you or your pipeline wrote.

  • The SQL Yodeler tab lists each environment’s applied migrations, the ones not applied with their state, and the gaps the report found, dated by the report’s generatedAt.
  • A table or other object a drift file names as changed or missing gets a corner tag on its card, such as drift prod · 4h. Drift JSON has no time of its own, so the age is when its file was written. Hover the card or open it for the properties that differ.
  • Objects no card is are listed in the tab, not dropped.
  • The report’s audit entries are listed under their environment, oldest first, each with its own time and where SQL Yodeler read it: a gate ledger on chant/lifecycle, or a row of the environment’s history table.

behold export . --yodel-report out/ carries the report and drift as a snapshot of the moment it ran, and fails if the files cannot be read. A SQL Yodeler repo’s Pipeline lane is captured the same way.

Every file is checked against SQL Yodeler’s own JSON Schemas, from @intentius/sql-yodeler when it is installed and from a copy pinned in behold otherwise. A file that does not match is refused by name with code: "yodel-report", and nothing from that read is drawn.

behold