Install
$ agentstack add skill-bonnard-data-bonnard-cli-bonnard-get-started ✓ scanned · ✓ verified — works with Claude Code, Cursor, and more.
Security review
✓ PassedNo issues found. Passed automated security review. · v0.1.0 How review works →
- ✓ Prompt-injection patterns
- ✓ Secret / credential exfiltration
- ✓ Dangerous shell & filesystem operations
- ✓ Untrusted network calls
- ✓ Known-malicious package signatures
What it can access
- ✓ Network access No
- ✓ Filesystem access No
- ✓ Shell / process execution No
- ✓ Environment & secrets No
- ✓ Dynamic code execution No
From automated source analysis of v0.1.0. “Used” means the capability is present in the source — more access means more to trust, not that it’s unsafe.
About
Get Started with Bonnard
This skill guides you through building and deploying a semantic layer. The user has already run bon init.
IMPORTANT — pacing: Complete ONE phase at a time. Before starting a phase, briefly explain what it does and why. After completing it, show the user what happened and ask if they're ready to move on. Do NOT run through all phases in one go.
Phase 1: Connect a Data Source
Ask the user if they have a warehouse to connect, or want to try a demo dataset first:
# Option A: Use demo data (no warehouse needed)
bon datasource add --demo
# Option B: Import from dbt (if they use it)
bon datasource add --from-dbt
# Option C: Add manually, non-interactive (preferred for agents)
bon datasource add --name my_warehouse --type postgres \
--host db.example.com --port 5432 --database mydb --schema public \
--user myuser --password mypassword
# Option D: Add manually, interactive (in user's terminal)
bon datasource add
Supported types: postgres, redshift, snowflake, bigquery, databricks, duckdb.
The demo option adds a read-only Contoso retail dataset with tables like fact_sales, dim_product, dim_store, and dim_customer.
The connection will be tested automatically during bon deploy.
Phase 2: Explore the Data
Before creating cubes, understand what tables and columns are available in your warehouse.
Important: bon query is for querying the deployed semantic layer — it does NOT access your database directly. Use your warehouse's native tools to explore tables.
Options for exploring your data:
- Use your database CLI (e.g.,
psqlfor Postgres/Redshift,snowsqlfor Snowflake,bqfor BigQuery) to list tables and columns - Check your dbt docs or existing documentation for table schemas
- Ask the user for table names and column details if you don't have direct database access
- For the demo dataset, the tables are:
contoso.fact_sales,contoso.dim_product,contoso.dim_store,contoso.dim_customer
Note the table names, column names, and data types — you'll use these in Phase 3.
CHECKPOINT: Show the user the tables and columns you found. Ask which table they'd like to model first before proceeding.
Phase 3: Create Your First Cube
Based on what you found in Phase 2, create a file in bonnard/cubes/ for the most important table. A cube maps directly to a database table — define measures for the metrics you want to track and dimensions for the attributes you want to filter and group by. Use the actual table and column names from Phase 2, not placeholder names.
Example using demo data — bonnard/cubes/sales.yaml:
cubes:
- name: sales
sql_table: contoso.fact_sales
data_source: contoso_demo
measures:
- name: count
type: count
description: Total number of sales transactions
- name: total_revenue
type: sum
sql: sales_amount
description: Sum of sales revenue
- name: total_cost
type: sum
sql: total_cost
description: Sum of product costs
# Filtered measures — match what users actually see on dashboards
- name: return_count
type: count
description: >-
Sales transactions with returns only (return_quantity > 0).
For all transactions, use count.
filters:
- sql: "{CUBE}.return_quantity > 0"
dimensions:
- name: sales_key
type: number
sql: sales_key
primary_key: true
- name: date
type: time
sql: date_key
description: Sale date
- name: sales_quantity
type: number
sql: sales_quantity
description: Number of units sold
Key rules:
- Every cube needs a
primary_keydimension — it must be unique. If no column is naturally unique, usesqlwithROW_NUMBER()instead ofsql_tableand add a synthetic key. Non-unique PKs cause dimension queries to silently return empty results. - Every measure and dimension should have a
description— descriptions are how AI agents discover and choose metrics (see/bonnard-design-guide) - Add filtered measures for any metric users track with filters (e.g., "online revenue" vs "total revenue"). If a dashboard card has a WHERE clause beyond a date range, that filter should be a filtered measure.
- Measure descriptions should say what's included and excluded — e.g., "Online channel only. For all channels, use total_revenue."
- Dimension descriptions should include example values for categorical fields — e.g., "Sales channel (values: Online, Store, Reseller)"
- Set
data_sourceto match the datasource name from Phase 1 - Use
sql_tablewith the fullschema.tablepath - Use
sql_tablefor simple table references,sqlfor complex queries
Use bon docs cubes for the full reference, bon docs cubes.measures.types for all 12 measure types, bon docs cubes.dimensions.types for dimension types.
Phase 4: Design Views for Your Audience
Before creating view files, ask the user:
- Who will query this data? (e.g., sales managers, product analysts, executives, AI agents)
- What questions do they typically ask? (e.g., "what's revenue by store this month?", "which products are trending?")
Use the answers to decide view names, which measures/dimensions to include, and how to write descriptions. Each persona or use case may warrant its own view.
Views expose a curated subset of measures and dimensions for specific audiences. Name views by what they answer (e.g., sales_performance), not by what table they wrap (e.g., sales_view). A view can combine measures and dimensions from multiple cubes via join_path.
The view description is critical — it's how AI agents decide which view to query. It should answer: what's in here, when to use it, and when to use something else instead. Include key dimension values where helpful.
Example using demo data — bonnard/views/sales_performance.yaml:
views:
- name: sales_performance
description: >-
Retail sales metrics — revenue, cost, and transaction counts by product,
store, and date. Default view for sales questions. Includes return_count
for return analysis. For customer demographics, use customer_insights
instead.
cubes:
- join_path: sales
includes:
- count
- total_revenue
- return_count
- total_cost
- date
- sales_quantity
Use bon docs views for the full reference. See /bonnard-design-guide for principles on naming, descriptions, and view structure.
Phase 5: Validate
Check for errors:
bon validate
Fix any errors before proceeding. Common issues:
- Missing required fields (
name,type,sql) - Unknown measure/dimension types (e.g.,
textshould bestring) - Bad YAML indentation
Validate also warns about:
- Missing descriptions — descriptions help AI agents and analysts discover metrics
- Missing
data_source— cubes without an explicitdata_sourceuse the default warehouse, which can cause issues when multiple warehouses are configured
Phase 6: Deploy
CHECKPOINT: Before deploying, summarize what will be deployed — list the cubes, views, datasources, and any joins. Ask the user to confirm before running bon deploy.
Log in (if not already) and deploy:
bon login
bon deploy -m "Initial semantic layer with sales cube and overview view"
Deploy requires a -m message describing the changes. It validates, tests connections, uploads cubes/views, and syncs datasource credentials (encrypted) to Bonnard.
After deploying, the output shows what changed (added/modified/removed) and flags any breaking changes. Use bon deployments to see history and bon diff to review changes from any deployment.
Phase 7: Test with Queries
Verify the deployment works using the view name from Phase 4:
# Simple count
bon query '{"measures": ["sales_performance.count"]}'
# With a dimension
bon query '{"measures": ["sales_performance.total_revenue"], "dimensions": ["sales_performance.date"]}'
# SQL format
bon query --sql "SELECT MEASURE(total_revenue) FROM sales_performance"
Test with natural language too. If you've set up MCP (Phase 8), ask an AI agent questions like "what's our total revenue?" and check whether it picks the right view and measure. If it picks the wrong view, the issue is usually the view description — see /bonnard-design-guide Principle 4.
Phase 8: Connect AI Agents (Optional)
Set up MCP so AI agents can query the semantic layer:
bon mcp
This shows setup instructions for Claude Desktop, ChatGPT, Cursor, VS Code, and other MCP clients. The MCP URL is https://mcp.bonnard.dev/mcp.
Next Steps
After the first cube is working:
- Iterate on descriptions — test with real questions via MCP, fix agent mistakes by improving view descriptions and adding filtered measures (
/bonnard-design-guide) - Add more cubes for other tables
- Add joins between cubes (
bon docs cubes.joins) - Build audience-centric views that combine multiple cubes — e.g., a
managementview that pulls fromsales,users, andproductscubes - Add calculated measures (
bon docs cubes.measures.calculated) - Add segments for common filters (
bon docs cubes.segments)
Source & license
This open-source skill is cataloged on AgentStack and links to its original source — we do not rehost the code.
- Author: bonnard-data
- Source: bonnard-data/bonnard-cli
- License: MIT
- Homepage: https://www.bonnard.dev
Install and usage instructions live in the source repository linked above.
Reviews
No reviews yet — be the first.
Write a review
Versions
- v0.1.0 Imported from the upstream source.