This is an English translation of the original Japanese article published at: https://dev.classmethod.jp/articles/try-twb-to-omni-yaml-with-claude-code/
Please note that some images contain Japanese text, as they are from the original article.
When considering adopting a new BI tool like Omni, the biggest hurdle is usually "how to migrate from your existing BI tool."
However, with the recent advancement of AI technologies like Claude Code, migrating between code-based and text-based content is becoming surprisingly feasible.
With that in mind, I tried using Claude Code to automatically generate Omni's Semantic Layer YAML code from Tableau's .twb files, assuming a Tableau-to-Omni migration scenario. This article summarizes what I did and what I learned.
Note: This does not cover dashboard migration itself. The scope is limited to "generating Omni YAML code and creating Markdown instructions for how to build charts in Omni." If Omni dashboards become definable via code in the future, that could change things significantly.
Prerequisites
-
DWH: Snowflake (AWS Tokyo region, Enterprise edition)
- Starting from a
.twbfile connected to Snowflake via Tableau, I created a Connection and base Model in Omni, then attempted the migration.
- Starting from a
- Claude Code: 2.1.70 (Pro plan, using Opus 4.6)
-
Python environment: uv 0.10.9
- Python is required because the Skill I created uses Python scripts.
- Tableau Desktop: 2025.3.3
- Local environment: Ubuntu 24.04 LTS (via WSL2)
Preparation
First, I set things up on the Omni, Tableau, and Claude Code sides respectively.
Omni
For Omni preparation, I created a Connection to the same Snowflake instance used in Tableau, created a base Model, and set up Git integration so that Claude Code could easily edit the Model files.
Tableau
I prepared a .twb file with the following characteristics:
- Relationships defined across 4 tables, with a data source filter restricting to the last 180 days
- Custom dimensions, measures, and parameters added (the Japanese-labeled dimensions are the custom ones)
- Including LoD (Level of Detail) fields such as
地域別_平均フルフィル日数(Average Fulfillment Days by Region)
- Including LoD (Level of Detail) fields such as
- A dashboard created within the workbook
Installing model-local-editor
Since Omni is typically developed within its in-browser IDE, you need to install model-local-editor to validate locally developed content on the Omni instance.
This tool runs as a persistent process, and any files edited during that time are automatically synced to the Omni instance.
I've written a separate blog post on how to use it, so please refer to it for details:
Claude Code (Skill Implementation)
I created a Skill to generate Omni YAML from Tableau .twb files. The implementation approach was to have Claude Code's skill-creator Skill generate a base, then iterate through trial and error to refine it.
The Skill details are published in the following repository:
Note: This Skill does not guarantee perfect conversion of all .twb files to Omni's Semantic Layer. Please use it with that caveat in mind. Also, the Markdown descriptions within the linked Skill are written in Japanese.
https://github.com/SSchneider22/tableau-twb-to-omni-semantic-layer
Auto-Generating Omni YAML Files from .twb Files Using Claude Code
I cloned the Git-integrated Omni repository to my local environment and created a branch. Then I created a tableau folder.
Inside it, I placed the target Tableau workbook file (.twb file) for migration.
Next, I started model-local-editor so that local edits would be reflected on the Omni instance.
Then I launched Claude Code and ran /skills to verify that the Skill created during preparation was properly loaded. If it displays as shown below, everything is fine.
With that confirmed, I submitted the following prompt in Plan mode (adjust folder paths to match your setup):
Using the Skill "tableau-twb-to-omni-semantic-layer", generate all Omni migration files based on the .twb file in the develop/manufacturing_dataops_test/tableau folder.
Claude Code created a plan as shown below, and I then asked it to generate the code.
After code generation was complete, I reviewed the generated code. Here are some examples of what was produced:
- Dimensions/measures/filters definitions added to existing View files
- Topics generated per data source
- Markdown files with step-by-step instructions for reproducing each Tableau worksheet/dashboard in Omni
After this, I performed Git operations to update the main branch with the latest content.
Verifying on Omni
Since I was using model-local-editor, the code generated by Claude Code was already reflected in Omni on the specified branch.
From this state, I clicked Explore and followed the Markdown file created by Claude Code to see if I could reproduce the charts originally built in Tableau.
When reproducing each Query as a chart, I confirmed that Tableau's data source filters were applied as Topic default filters, and that the parameter for switching measures and LoD fields all worked as expected.
Finally, I also created a dashboard. While the positions of filters and legends differ, the functionality covers the same content as the Tableau dashboard.
Bonus: Examples of Issues Encountered During Testing
This article highlights the successful results, but during testing I encountered various issues and had to repeatedly feed error logs back to Claude Code to refine the Skill. (I went through this code generation → Skill refinement loop at least 10+ times...)
Here are some examples of actual issues I encountered:
- The generated Omni Semantic Layer code used non-existent parameters, causing error logs during model-local-editor sync
- Example 1: Specifying non-existent values for
aggregation_type - Example 2: Not creating LoD fields according to Omni's syntax
- Example 1: Specifying non-existent values for
- Even when sync succeeded, errors/warnings appeared on the Omni UI
- Example 1: Fields used in LoD calculations were not included in the Topic's field list
- Example 2: Filter fields already defined under
filters:were also duplicated underdimensions: - Example 3: A measure with
aggregate_type: count_distinctalso had COUNT DISTINCT in itssql:definition
Conclusion
I tried using Claude Code to automatically generate Omni Semantic Layer YAML code from Tableau .twb files.
While I haven't achieved automatic dashboard migration, being able to automate the generation of Semantic Layer definitions, Topics, and even Markdown instructions for reproducing charts in Omni gave me a strong sense that a significant portion of migration work can be streamlined.
In particular, the fact that complex Tableau definitions like data source filters, LoD fields, and parameters could be reproduced on the Omni side through iterative Skill improvements was a major win.
That said, perfect code isn't generated on the first try — the Skill required many rounds of refinement. While it worked well for the .twb file I tested, other .twb files may require additional adjustments.
Nevertheless, for BI tool migrations — which tend to be daunting undertakings — the advancement of AI technology is making "migration between code-based artifacts" an increasingly realistic option.
I hope this article helps anyone considering a BI tool migration.






















Top comments (0)
Some comments may only be visible to logged-in visitors. Sign in to view all comments.