Skip to main content
This guide covers how to migrate Looker dashboards to Omni using a scripted API approach — a Python builder script, the Omni CLI, omni-sync, and Claude Code with custom agent skills. Rather than rebuilding dashboards by hand, the toolset lets you inspect source dashboards programmatically, translate fields and filters, and create Omni dashboards via the API in a workflow that gets faster with every dashboard you migrate. This is especially relevant if you:
  • Are migrating multiple Looker dashboards and want a repeatable, scriptable approach
  • Are comfortable working in Claude Code or Cursor and want to run most of the migration autonomously with agent skills
  • Need to handle complex Looker patterns — dynamic fields, pivots, parameter fields — that don’t map directly to Omni

How the tools fit together

The migration involves six tools. Knowing what each one does before you start saves a lot of back-and-forth later.

Looker API

The Looker API is the starting point for every dashboard. The dashboard_dashboard_elements and dashboard_dashboard_filters endpoints return everything you need: fields, filters, sorts, pivots, dynamic fields, layout position, and filter-listen wiring. You can call these directly using the inspect script below, or let the agent skill handle it.

Omni CLI

The Omni CLI (@omni-co/cli) handles branching, field management, model validation, and more. It’s what the omni-model-builder agent skill calls under the hood. You can also use it directly for one-off operations.

omni-sync (@omni-co/model-local-editor)

The omni-sync (@omni-co/model-local-editor) package is your live feedback loop for model changes. It watches local YAML files, pushes every save to your Omni branch, and streams validation errors back to the terminal in real time.Keep it running in a background terminal throughout the migration — it’s what lets you (or Claude Code) iterate on the model without leaving the terminal.

omni-model-builder agent skill

The omni-model-builder agent skill is a Claude Code / Cursor task definition from the Omni agent skills repo.Give it an instruction like “add this missing dimension to the orders view” and it handles the YAML edits, pushes via the CLI, reads the omni-sync validation output, and iterates until the model is clean.

omni_dashboard_builder.py Python script

The omni_dashboard_builder.py file is the Python script that creates Omni dashboards via the API. You write a build_<name>() function per dashboard that assembles tiles from queries, register it in a DASHBOARDS dict, and run the script. It handles the API mechanics that would otherwise be tedious: layout via the export/import cycle, filter wiring, and visualization configs that the direct create API drops.See the Appendix for the full file contents.

looker-to-omni-dashboard agent skill

The looker-to-omni-dashboard agent skill orchestrates the full migration workflow in Claude Code. You give it a Looker dashboard ID and then it:
  • Calls the Looker API
  • Maps fields to Omni equivalents
  • Writes the build_<name>() function
  • Wires filters and layout
  • Runs the builder script
  • Opens the result URL for you to inspect
See the Appendix for the full file contents.

Part 1: Get set up

The first step is to install the required packages and configure your tooling. You’ll need to complete all of the steps in this section to follow the remaining sections in this guide.
1

Install Python 3.9+

You’ll need Python 3.9 or later to follow the steps in this guide. See the official Python downloads to download the correct version for your operating system.You can check what version of Python is installed, if any, by running:
If the first command returns an error or a legacy version, try python3. Some systems explicitly require python3.
2

Install the Looker SDK

Install the Looker SDK by running:
3

Install Omni Agent Skills

  1. Use the Omni agent skills installation guide to install the official plugin for Claude Code.
  2. Copy the looker-to-omni-dashboard-skill.md file from this guide’s appendix into .claude/agents/ in your repo.
    The migration skill is distinct from the official plugin and needs to be placed there manually.
  3. Save the file as looker-to-omni-dashboard.md.
4

Install the Omni CLI

  1. Use the CLI installation guide to install the CLI.
  2. After installing, run omni config init once to configure your profile and set up authentication.
5

Install the model editor CLI (omni-sync)

See the Local development with the model editor CLI guide for more information about this CLI.
Install the @omni-co/model-local-editor package globally:
6

Set environment variables

Set the following in the shell you’ll run the migration scripts from:
looker_dashboard_inspect.py and omni_dashboard_builder.py (both in the Appendix) read these directly — set them before running either script.
7

Start omni-sync

Before making any model changes, start a migration branch and keep the watcher running in a dedicated terminal throughout:

Part 2: Configure Omni Git settings

  1. Open your model in Omni by navigating to the model IDE.
  2. Click Model > Git Settings.
  3. Verify the following settings are enabled:
    • Pull request required — Prevents direct promotion of branch changes to the shared model
    • Always create branches — Ensures PRs created outside Omni automatically create a corresponding Omni branch
Open pull requests through the Omni web UI, not directly in GitHub. In the Omni IDE, click Open Pull Request in the branch selector.
Don’t push branches or pull requests directly to GitHub. Changes pushed outside of Omni won’t be properly validated and may break the model.

Part 3: The migration workflow

This approach works best when you start with your simplest dashboards. The first few teach you the failure modes specific to your Looker model, such as field prefix conventions, which dynamic fields translate cleanly, and how your filter patterns map to Omni. By the time you get to complex dashboards with 50+ tiles and intricate filter wiring, you’ll have the playbook down and they’ll go much faster.
1

Inspect the source dashboard

Run the Looker inspect script against your Looker dashboard ID:
This calls dashboard_dashboard_elements and dashboard_dashboard_filters and prints a structured summary of every tile in visual order — fields, filters, sorts, pivots, dynamic fields, hidden fields, and filter-listen mappings — plus a ready-to-copy tile_order list at the end.If you’re using Claude Code with the looker-to-omni-dashboard skill, this step runs automatically when you give it the dashboard ID. Read the output carefully before writing anything.See the Appendix for the full Python script contents.
2

Verify and build missing model fields

Compare what the Looker dashboard requires against what’s in your Omni model. For each tile, you need the topic to exist, every field to be present in the view YAML, and any joins to be in relationships.yaml. If anything’s missing, add it before writing the build function.With omni-sync running, every YAML save validates immediately. With the omni-model-builder skill active in Claude Code, you can describe what’s missing and let the agent handle the edits and validation cycle.
3

Write the build function and run the script

Add a build_<name>() function to omni_dashboard_builder.py using the query(), tile(), and visualization config helpers in the script, register it in DASHBOARDS, and run:
main() builds every dashboard registered in DASHBOARDS. To build a subset, comment out the others. The script prints the dashboard URL when it finishes — open it immediately and check visually. Broken charts, missing filters, and wrong tile order are all obvious at a glance.See the Appendix for the script file, which includes all the details needed for writing build functions, translating visualizations, wiring filters, and handling edge cases.
The script calls delete_existing_by_name() before every create, which deletes every document accessible to your API token with that exact name across all folders. Use unique, script-managed names for dashboards built with this script and avoid reusing those names for anything built by hand.
Layout, filter wiring, and visualization configs are applied via an export/import cycle using /api/unstable/ endpoints — confirmed still in beta as of this writing, per Omni’s API docs. This is a field-tested workaround for limitations in the stable create API.Omni’s newer v2 Documents API (/v2/documents) supports layout and dashboard filters natively via containers and controls. This script will be updated to the v2 create/patch/publish flow instead of the export/import round-trip. Until then, it’s worth regression-testing after Omni upgrades if dashboard creation starts breaking.
4

Iterate

Fix what’s wrong, rebuild, repeat. The script deletes and recreates cleanly on every run, so there’s no stale state to manage.If you’re in Claude Code, feed errors back to the agent and ask it to update the skill file, as that learning carries forward to every subsequent dashboard automatically.
5

Merge your migration branch

Once you’ve built and verified all the dashboards you’re migrating, merge the branch you started in Part 1:
If Pull request required is enabled in your git settings (see Part 2), open the pull request through the Omni web UI first, then run the command above once it’s merged to delete the local branch reference.If your environment doesn’t require pull requests, skip the PR and merge directly with --force-override-git-settings:

Part 4: Finish the cleanup in Omni

A few things can’t be set programmatically and require manual work in the Omni UI after each dashboard is created:
  • KPI tile styling — Font sizes and alignment must be set in the UI. The field and label persist through rebuilds, but visual styling does not.
  • Markdown and text tiles — Not migratable; recreate manually
  • Chart color themes — Must be applied in the UI after creation
Visualization configuration — axis assignment, series colors, chart formatting — has limited API coverage when building dashboards programmatically. Chart type hints set via the API may be overridden by Omni’s automatic visualization logic, and detailed axis configs set through the UI won’t be reproduced by the builder script.For the visual layer, use Omni’s built-in AI assistant, accessible from the sidebar in any dashboard, to refine chart formatting after the dashboard structure is in place. Describe what each tile should look like and the Omni Agent will execute the changes.

Next steps

Appendix: Companion files

The following files contain everything needed to run the migration. Click to open and copy the contents.
Run this first against your Looker dashboard ID to get a structured summary of every tile before writing any build functions.
Copy the full contents into .claude/agents/looker-to-omni-dashboard.md in your repo.
Add your build_<name>() functions and register them in DASHBOARDS, then run with python3 scripts/omni_dashboard_builder.py.