Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 9 additions & 2 deletions skills/dune/SKILL.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
---
name: dune
description: "Dune CLI for querying blockchain and on-chain data via DuneSQL, searching decoded contract tables, managing saved queries, managing visualizations, managing dashboards, and monitoring credit usage on Dune. Use when user asks about blockchain data, on-chain analytics, token transfers, DEX trades, smart contract events, wallet balances, Ethereum/EVM chain queries, DuneSQL, visualizations, charts, dashboards, or says \"query Dune\", \"search Dune datasets\", \"run a Dune query\", \"create a dashboard\", or \"manage dashboard\"."
description: "Dune CLI for querying blockchain and on-chain data via DuneSQL, searching decoded contract tables, managing saved queries, managing visualizations, managing dashboards, managing materialized views, and monitoring credit usage on Dune. Use when user asks about blockchain data, on-chain analytics, token transfers, DEX trades, smart contract events, wallet balances, Ethereum/EVM chain queries, DuneSQL, visualizations, charts, dashboards, materialized views, matviews, or says \"query Dune\", \"search Dune datasets\", \"run a Dune query\", \"create a dashboard\", \"manage dashboard\", \"create a materialized view\", or \"refresh a matview\"."
compatibility: Requires network access and the Dune CLI (auto-installed on first use). Works on macOS, Linux, and Windows.
allowed-tools: Bash(dune:*) Bash(curl:*) Read
metadata:
Expand Down Expand Up @@ -132,6 +132,12 @@ dune query run 12345 --param wallet=0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045 -
| `dune query run <id>` | Execute a saved query and wait for results | Yes |
| `dune query run-sql` | Execute raw DuneSQL directly (no saved query needed) | Yes |
| `dune execution results <id>` | Fetch results of a previous execution | Yes |
| `dune matview create` | Materialize a saved query into a table | Yes |
| `dune matview get <name>` | Fetch a matview's metadata, size, and refresh schedule | Yes |
| `dune matview list` | List the materialized views you own | Yes |
| `dune matview update <name>` | Update a matview's settings or refresh schedule | Yes |
| `dune matview refresh <name>` | Trigger an on-demand refresh | Yes |
| `dune matview delete <name>` | Permanently delete a matview and its schedule | Yes |
| `dune dataset search` | Search the Dune dataset catalog | Yes |
| `dune dataset search-by-contract` | Find decoded tables for a contract address | Yes |
| `dune viz create` | Create a visualization on a saved query | Yes |
Expand Down Expand Up @@ -237,7 +243,7 @@ The following capabilities are available via the Dune MCP server or web UI but *
## Security

- **Never** output API keys or tokens in responses. Before presenting CLI output to the user, scan for strings that look like API keys (e.g. long alphanumeric tokens, strings prefixed with `dune_`, or values from `DUNE_API_KEY`). Redact them with `[REDACTED]`.
- **Always** confirm with the user before running write commands (`query create`, `query update`, `query archive`, `viz create`, `viz update`, `viz delete`, `dashboard create`, `dashboard update`, `dashboard archive`)
- **Always** confirm with the user before running write commands (`query create`, `query update`, `query archive`, `viz create`, `viz update`, `viz delete`, `dashboard create`, `dashboard update`, `dashboard archive`, `matview create`, `matview update`, `matview refresh`, `matview delete`). Note: `matview create`, `matview update`, and `matview refresh` each trigger a credit-consuming execution, and `matview delete` is irreversible.
- **Always** use `-o json` on every command -- JSON output is more detailed and reliably parseable
- Use `--temp` when creating throwaway queries to avoid cluttering the user's saved queries
- **Never** pass `--api-key` on the command line when other users might see the terminal history. Prefer `dune auth` or the `DUNE_API_KEY` environment variable.
Expand All @@ -254,5 +260,6 @@ Load the relevant reference when you need detailed command syntax and flags:
| Search documentation or check account usage | [docs-and-usage.md](references/docs-and-usage.md) |
| DuneSQL types, functions, common patterns, and pitfalls | [dunesql-cheatsheet.md](references/dunesql-cheatsheet.md) |
| Create, get, update, delete, or list visualizations on saved queries | [visualization-management.md](references/visualization-management.md) |
| Create, get, list, update, refresh, or delete materialized views | [matview-management.md](references/matview-management.md) |
| Create, get, update, or archive dashboards | [dashboard-management.md](references/dashboard-management.md) |
| CLI install, authentication, and version recovery | [install-and-recovery.md](references/install-and-recovery.md) |
328 changes: 328 additions & 0 deletions skills/dune/references/matview-management.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,328 @@
# Materialized View Management

> **Prerequisite:** Read the [main skill](../SKILL.md) for authentication, global flags, and key concepts.

Manage materialized views (matviews) -- query results persisted into a queryable table, optionally refreshed on a schedule. The command group is `dune matview` (alias `mv`).

```bash
dune matview <subcommand> [flags]
```

---

## Naming: bare vs. fully-qualified

A matview has two name forms, and the commands are **not** symmetric about which they take:

- **`create`** takes a **bare** name like `result_token_summary` (must start with `result_`, 8-128 lowercase alphanumerics/underscores, no trailing underscore). The name is immutable after creation.
- **`get`, `update`, `refresh`, `delete`** take the **fully-qualified** SQL name like `dune.my_team.result_token_summary`. The `create`/`update`/`refresh` responses return this fully-qualified name -- capture it from the JSON `name`/`sql_id` field for subsequent calls.

## Refresh schedules

If a matview has a cron schedule, it is refreshed periodically. Cron expressions are standard 5-field syntax (e.g. `0 */6 * * *`) with a **minimum 15-minute interval**. `expires-at` (RFC3339) caps when the schedule stops; it only applies when a schedule is set.

---

## matview create

Materialize a saved query into a table. Triggers an immediate execution.

```bash
dune matview create --name <NAME> --query-id <ID> [flags]
```

### Flags

| Flag | Type | Required | Default | Description |
|------|------|----------|---------|-------------|
| `--name` | `string` | Yes | -- | Bare matview name, e.g. `result_token_summary` |
| `--query-id` | `integer` | Yes | -- | ID of the source query to materialize |
| `--private` | `bool` | No | `false` | Make the matview private (requires a supporting plan); defaults to public |
| `--performance` | `string` | No | account default | Execution tier: `small`, `medium`, or `large` |
| `--cron` | `string` | No | none | 5-field cron for periodic refresh (min 15-minute interval) |
| `--expires-at` | `string` | No | none | RFC3339 time the schedule expires (requires `--cron`) |
| `-o, --output` | `string` | No | `text` | Output format: `text` or `json` |

### Requirements

- The source query must be **saved (non-temporary)** and have **no parameters**.
- The query must be owned by the same user/team as the matview.
- The matview is owned by your authenticated context: a team API key creates a team-owned matview, a personal key a personal one.

### Output

- **text**: `Created materialized view <fully-qualified-name>` + the execution ID and a results hint.
- **json**: `{"name": "<fully-qualified-name>", "execution_id": "<id>"}`

### Examples

```bash
# Materialize a query at the medium tier
dune matview create --name result_token_summary --query-id 12345 --performance medium -o json

# Scheduled refresh every 6 hours
dune matview create --name result_daily --query-id 12345 --cron "0 */6 * * *" -o json

# Private matview (public by default; --private requires a supporting plan)
dune matview create --name result_private --query-id 12345 --private -o json

# Capture the fully-qualified name for later commands
MV=$(dune matview create --name result_token_summary --query-id 12345 -o json | jq -r '.name')
```

### Tips

- `create` is **create-or-replace**: if a matview with this name already exists for the same query it is re-run. To change settings on an existing matview, use `dune matview update`.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What happens if the name exists but with a different --query-id? "for the same query" implies different behavior in that case but it's not documented — either clarify or drop the qualifier.

- Matviews are public by default; `--private` requires a supporting plan.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: Duplicates the --private flag description above — remove this line.


> [!CAUTION]
> This is a **write** command -- it creates a resource and triggers a (credit-consuming) execution.

---

## matview get

Fetch a matview's metadata, table size, recent executions, and refresh schedule.

```bash
dune matview get <name>
```

### Arguments

| Argument | Type | Description |
|----------|------|-------------|
| `name` | `string` | Fully-qualified SQL name, e.g. `dune.my_team.result_token_summary` |

### Flags

| Flag | Type | Required | Default | Description |
|------|------|----------|---------|-------------|
| `-o, --output` | `string` | No | `text` | Output format: `text` or `json` |

### Output

**text** format displays the metadata and, if scheduled, the refresh schedule:

```
Name: dune.my_team.result_token_summary
Query ID: 12345
Private: false
Table size: 2.0 KB
Executions: 01HZ...

Refresh schedule:
Cron: 0 */6 * * *
Performance: small
Next run: 2026-06-12T12:41:12Z
Expires at: 2026-09-11T23:59:59Z
```

When there is no schedule, the last line reads `Refresh schedule: none`.

**json** returns the full object: `sql_id`, `query_id`, `is_private`, `last_execution_ids`, `table_size_bytes`, and `schedule` (`null` when none).

### Examples

```bash
dune matview get dune.my_team.result_token_summary -o json

# Just the schedule
dune matview get dune.my_team.result_token_summary -o json | jq '.schedule'
```

---

## matview list

List the materialized views owned by the authenticated user or team (paginated).

```bash
dune matview list [flags]
```

### Flags

| Flag | Type | Required | Default | Description |
|------|------|----------|---------|-------------|
| `--limit` | `integer` | No | `100` | Max matviews per page (max 1000) |
| `--offset` | `integer` | No | `0` | Pagination offset |
| `--all` | `bool` | No | `false` | Fetch all pages (ignores `--offset`) |
| `-o, --output` | `string` | No | `text` | Output format: `text` or `json` |

### Output

- **text**: an aligned table with `NAME`, `QUERY ID`, `PRIVATE`, `SIZE`; a hint with the next offset when more pages exist.
- **json**: `{"materialized_views": [...], "next_offset": <int>}` (`next_offset` omitted when there are no more pages).

### Examples

```bash
dune matview list -o json
dune matview list --all -o json | jq '.materialized_views | length'
```

---

## matview update

Update a matview's privacy, performance tier, or refresh schedule. Updating re-executes the source query. The name and source query are immutable.

```bash
dune matview update <name> [flags]
```

### Arguments

| Argument | Type | Description |
|----------|------|-------------|
| `name` | `string` | Fully-qualified SQL name, e.g. `dune.my_team.result_token_summary` |

### Flags

| Flag | Type | Required | Default | Description |
|------|------|----------|---------|-------------|
| `--private` | `bool` | No | preserved | Set the matview's privacy |
| `--performance` | `string` | No | preserved | Execution tier: `small`, `medium`, or `large` |
| `--cron` | `string` | No | preserved | Set or replace the refresh schedule (min 15-minute interval) |
| `--no-schedule` | `bool` | No | -- | Remove the refresh schedule |
| `--expires-at` | `string` | No | preserved | RFC3339 time the schedule expires |
| `-o, --output` | `string` | No | `text` | Output format: `text` or `json` |

`--cron` and `--no-schedule` are mutually exclusive.

### Schedule preservation (important)

`update` is **read-modify-write**: it fetches the current matview first, then re-submits the full state. Settings you don't pass are preserved -- **in particular, the existing refresh schedule is kept** unless you change it with `--cron` or remove it with `--no-schedule`. So `dune matview update <name> --private=false` will *not* silently drop a schedule.

### Output

- **text**: `Updated materialized view <fully-qualified-name>` + the execution ID.
- **json**: `{"name": "<fully-qualified-name>", "execution_id": "<id>"}`

### Examples

```bash
# Change the tier, keep the schedule
dune matview update dune.my_team.result_token_summary --performance large -o json

# Replace the schedule
dune matview update dune.my_team.result_token_summary --cron "0 0 * * *" -o json

# Remove the schedule
dune matview update dune.my_team.result_token_summary --no-schedule -o json

# Make it public
dune matview update dune.my_team.result_token_summary --private=false -o json
```

> [!CAUTION]
> This is a **write** command -- it modifies the matview and triggers a (credit-consuming) re-execution.

---

## matview refresh

Trigger an on-demand refresh: re-execute the source query and update the table.

```bash
dune matview refresh <name> [flags]
```

### Arguments

| Argument | Type | Description |
|----------|------|-------------|
| `name` | `string` | Fully-qualified SQL name, e.g. `dune.my_team.result_token_summary` |

### Flags

| Flag | Type | Required | Default | Description |
|------|------|----------|---------|-------------|
| `--performance` | `string` | No | account default | Execution tier: `small`, `medium`, or `large` |
| `-o, --output` | `string` | No | `text` | Output format: `text` or `json` |

### Output

- **text**: `Refreshing materialized view <fully-qualified-name>` + the execution ID and a results hint.
- **json**: `{"sql_id": "<fully-qualified-name>", "execution_id": "<id>"}`

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Note: the JSON key is sql_id here, not name as in create/update — use .sql_id when capturing the name for subsequent calls


### Examples

```bash
dune matview refresh dune.my_team.result_token_summary -o json
dune matview refresh dune.my_team.result_token_summary --performance large -o json
```

> [!CAUTION]
> This is a **write** command -- it consumes credits based on the compute used. You must own the matview.

---

## matview delete

Permanently delete a matview and its refresh schedule. Drops the underlying table.

```bash
dune matview delete <name>
```

### Arguments

| Argument | Type | Description |
|----------|------|-------------|
| `name` | `string` | Fully-qualified SQL name, e.g. `dune.my_team.result_token_summary` |

### Flags

| Flag | Type | Required | Default | Description |
|------|------|----------|---------|-------------|
| `-o, --output` | `string` | No | `text` | Output format: `text` or `json` |

### Output

- **text**: `Deleted materialized view <fully-qualified-name>`
- **json**: `{"message": "ok"}`

### Examples

```bash
dune matview delete dune.my_team.result_token_summary -o json
```

> [!CAUTION]
> This is a **destructive, irreversible** command -- the table can no longer be queried. You must own the matview.

---

## Common Workflow

### Materialize a query, then schedule and manage it

```bash
# 1. Create a saved (non-temp, non-parameterized) source query
QUERY_ID=$(dune query create --name "Token Summary" --sql "SELECT 1 AS x" -o json | jq -r '.query_id')

# 2. Materialize it with a 6-hour refresh schedule; capture the fully-qualified name
MV=$(dune matview create --name result_token_summary --query-id $QUERY_ID --cron "0 */6 * * *" -o json | jq -r '.name')

# 3. Inspect it (shows the schedule)
dune matview get $MV -o json

# 4. Refresh on demand
dune matview refresh $MV -o json

# 5. Remove the schedule but keep the matview
dune matview update $MV --no-schedule -o json

# 6. Delete when no longer needed
dune matview delete $MV -o json
```

---

## See Also

- [query-management.md](query-management.md) -- Create the source query to materialize
- [query-execution.md](query-execution.md) -- Fetch results of the execution a create/refresh triggers
- [docs-and-usage.md](docs-and-usage.md) -- Check credit usage consumed by refreshes