duckhaven-cli 0.3.0__tar.gz → 0.5.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (34) hide show
  1. {duckhaven_cli-0.3.0 → duckhaven_cli-0.5.0}/CHANGELOG.md +48 -0
  2. duckhaven_cli-0.5.0/PKG-INFO +206 -0
  3. duckhaven_cli-0.5.0/README.md +177 -0
  4. {duckhaven_cli-0.3.0 → duckhaven_cli-0.5.0}/pyproject.toml +1 -1
  5. {duckhaven_cli-0.3.0 → duckhaven_cli-0.5.0}/src/dh/_version.py +2 -2
  6. duckhaven_cli-0.5.0/src/dh/commands/dashboard.py +907 -0
  7. {duckhaven_cli-0.3.0 → duckhaven_cli-0.5.0}/src/dh/commands/dbt.py +94 -11
  8. {duckhaven_cli-0.3.0 → duckhaven_cli-0.5.0}/src/dh/commands/query.py +1 -0
  9. {duckhaven_cli-0.3.0 → duckhaven_cli-0.5.0}/src/dh/execute.py +17 -4
  10. duckhaven_cli-0.5.0/src/dh/exposures.py +146 -0
  11. {duckhaven_cli-0.3.0 → duckhaven_cli-0.5.0}/src/dh/main.py +2 -0
  12. {duckhaven_cli-0.3.0 → duckhaven_cli-0.5.0}/src/dh/repl.py +1 -1
  13. {duckhaven_cli-0.3.0 → duckhaven_cli-0.5.0}/src/dh/rest.py +70 -13
  14. duckhaven_cli-0.3.0/PKG-INFO +0 -88
  15. duckhaven_cli-0.3.0/README.md +0 -59
  16. {duckhaven_cli-0.3.0 → duckhaven_cli-0.5.0}/.gitignore +0 -0
  17. {duckhaven_cli-0.3.0 → duckhaven_cli-0.5.0}/LICENSE +0 -0
  18. {duckhaven_cli-0.3.0 → duckhaven_cli-0.5.0}/src/dh/__init__.py +0 -0
  19. {duckhaven_cli-0.3.0 → duckhaven_cli-0.5.0}/src/dh/commands/__init__.py +0 -0
  20. {duckhaven_cli-0.3.0 → duckhaven_cli-0.5.0}/src/dh/commands/admin.py +0 -0
  21. {duckhaven_cli-0.3.0 → duckhaven_cli-0.5.0}/src/dh/commands/api.py +0 -0
  22. {duckhaven_cli-0.3.0 → duckhaven_cli-0.5.0}/src/dh/commands/auth.py +0 -0
  23. {duckhaven_cli-0.3.0 → duckhaven_cli-0.5.0}/src/dh/commands/catalog.py +0 -0
  24. {duckhaven_cli-0.3.0 → duckhaven_cli-0.5.0}/src/dh/commands/grant.py +0 -0
  25. {duckhaven_cli-0.3.0 → duckhaven_cli-0.5.0}/src/dh/commands/health.py +0 -0
  26. {duckhaven_cli-0.3.0 → duckhaven_cli-0.5.0}/src/dh/commands/profile.py +0 -0
  27. {duckhaven_cli-0.3.0 → duckhaven_cli-0.5.0}/src/dh/commands/saved.py +0 -0
  28. {duckhaven_cli-0.3.0 → duckhaven_cli-0.5.0}/src/dh/commands/session.py +0 -0
  29. {duckhaven_cli-0.3.0 → duckhaven_cli-0.5.0}/src/dh/config.py +0 -0
  30. {duckhaven_cli-0.3.0 → duckhaven_cli-0.5.0}/src/dh/context.py +0 -0
  31. {duckhaven_cli-0.3.0 → duckhaven_cli-0.5.0}/src/dh/errors.py +0 -0
  32. {duckhaven_cli-0.3.0 → duckhaven_cli-0.5.0}/src/dh/introspect.py +0 -0
  33. {duckhaven_cli-0.3.0 → duckhaven_cli-0.5.0}/src/dh/output/__init__.py +0 -0
  34. {duckhaven_cli-0.3.0 → duckhaven_cli-0.5.0}/src/dh/resolve.py +0 -0
@@ -6,6 +6,54 @@ All notable changes to `duckhaven-cli` are documented here. The format follows
6
6
 
7
7
  ## [Unreleased]
8
8
 
9
+ ## [0.5.0] - 2026-11-15
10
+
11
+ ### Added
12
+
13
+ - **Dashboards in git.** `dh dashboard apply` applies `<name>.dashboard.yml` files, or every
14
+ one under a directory, to the dashboards they are named after, byte for byte. It takes
15
+ `--publish`, `--dry-run`, `--source-id`, `--source-ref`, `--expected-hash` and `--force`,
16
+ applies every file and reports each problem as `file:line:col`, and exits with the first
17
+ failure's status. `--prune` detaches and deletes the dashboards applied from
18
+ `--source-id` whose files are gone, after asking (or with `--yes`), and only when every
19
+ file applied.
20
+ - `dh dashboard validate`, `rename`, `adopt`, `detach`, `publish`, `delete`, `list` and
21
+ `get`. `dh dashboard export` prints a dashboard's YAML and `dh dashboard schema` its JSON
22
+ Schema, each as the file itself rather than the JSON envelope.
23
+ - `dh dashboard test` runs dashboard files without saving them and reports every widget as
24
+ `ok`, `empty`, `error` or `no_access`, with its time. It exits `6` when a widget fails or
25
+ cannot be read, and marks widgets slower than `--slow` seconds. It takes `--no-cache`.
26
+ - `dh dashboard preview FILE` holds a file as a preview, prints its page's address, and
27
+ sends the file again each time it is saved, starting a new preview when the last one has
28
+ ended. `--open` opens the page. `--once` runs the file once and prints each widget's state,
29
+ rows and SQL instead, which suits a coding agent checking its work.
30
+ - `dh dashboard impact REF` lists the dashboards that read a semantic model, metric or
31
+ dimension.
32
+ - `dh dashboard exposures MANIFEST` prints dbt exposures for the published dashboards that
33
+ read a dbt project's models, seeds, snapshots and sources, with `--owner-name` and
34
+ `--owner-email` for the owner dbt requires.
35
+ - `dh semantic import --dry-run` reports what an import would create, update and remove, and
36
+ the published dashboards it would break. `--allow-breaking` on `dh semantic import`,
37
+ `purge` and `deprecate` makes a change that breaks published dashboards; without it, the
38
+ change is refused and every dashboard it breaks is listed.
39
+ - The README has an `AGENTS.md` snippet for coding agents that write dashboard files.
40
+
41
+ ### Changed
42
+
43
+ - The pinned API contract is refreshed and covers the dashboard endpoints, including
44
+ previews and their runs.
45
+
46
+ ## [0.4.0] - 2026-10-15
47
+
48
+ ### Changed
49
+
50
+ - `dh sql` and the REPL ask the server to hold the submit for up to two seconds, so a quick
51
+ query finishes in one request instead of a submit and a poll. `--no-wait` still returns at
52
+ once. A server that predates the hold ignores it.
53
+ - Ready for DuckHaven `api_version` 3: `DECIMAL` and wide integers, which it sends as
54
+ strings, print as before in table and CSV output and stay exact strings with
55
+ `--format json`.
56
+
9
57
  ## [0.3.0] - 2026-10-13
10
58
 
11
59
  Brings the CLI up to date with the DuckHaven server's result cache, DuckLake catalogs,
@@ -0,0 +1,206 @@
1
+ Metadata-Version: 2.5
2
+ Name: duckhaven-cli
3
+ Version: 0.5.0
4
+ Summary: dh — the command-line interface for DuckHaven
5
+ Project-URL: Homepage, https://github.com/tamasmrtn/duckhaven-clients
6
+ Project-URL: Source, https://github.com/tamasmrtn/duckhaven-clients
7
+ Author: DuckHaven
8
+ License-Expression: Apache-2.0
9
+ License-File: LICENSE
10
+ Keywords: cli,duckdb,duckhaven,iceberg,lakehouse
11
+ Classifier: Development Status :: 3 - Alpha
12
+ Classifier: Environment :: Console
13
+ Classifier: Intended Audience :: Developers
14
+ Classifier: Intended Audience :: System Administrators
15
+ Classifier: Programming Language :: Python :: 3
16
+ Classifier: Programming Language :: Python :: 3.11
17
+ Classifier: Programming Language :: Python :: 3.12
18
+ Classifier: Programming Language :: Python :: 3.13
19
+ Classifier: Programming Language :: Python :: 3.14
20
+ Classifier: Topic :: Database
21
+ Classifier: Topic :: Utilities
22
+ Classifier: Typing :: Typed
23
+ Requires-Python: >=3.11
24
+ Requires-Dist: click>=8.5.0
25
+ Requires-Dist: duckhaven-sql-connector>=0.4.1
26
+ Requires-Dist: httpx>=0.28
27
+ Requires-Dist: typer>=0.28.0
28
+ Description-Content-Type: text/markdown
29
+
30
+ # duckhaven-cli
31
+
32
+ `dh` — the command-line interface for [DuckHaven](https://github.com/tamasmrtn/duckhaven).
33
+
34
+ It gives analysts, CI pipelines and operators scriptable access to DuckHaven's REST API:
35
+ running SQL, browsing the catalog, publishing dbt lineage and semantic models, applying
36
+ dashboards from git, managing grants, and operating service accounts, users and agents.
37
+
38
+ Like every member of this repo it is a **pure HTTP client of DuckHaven's public REST
39
+ API**, authenticating with a Personal Access Token (`dh_pat_…`). The interactive REPL
40
+ holds a SQL session through
41
+ [`duckhaven-sql-connector`](../duckhaven-sql-connector/README.md); everything else,
42
+ including one-shot `dh sql`, goes over the REST API directly, because the one-shot query
43
+ route works on deployments where SQL sessions are switched off.
44
+
45
+ ## Install
46
+
47
+ ```sh
48
+ pip install duckhaven-cli
49
+ # or, to get an isolated tool install:
50
+ uv tool install duckhaven-cli
51
+ ```
52
+
53
+ ## Getting started
54
+
55
+ ```sh
56
+ dh auth login --host https://duckhaven.example.com
57
+ dh sql -q "select 1"
58
+ ```
59
+
60
+ ## The result cache
61
+
62
+ DuckHaven answers a repeated read from its result cache when nothing the query reads has
63
+ changed. `dh sql` says so on stderr when it happens; pass `--no-cache` to run the query
64
+ anyway (also on `dh session open` and `dh session exec`). An owner can switch the cache off
65
+ for a whole workspace with `dh workspace update --no-result-cache`. The interactive REPL
66
+ does not take `--no-cache`: it holds its session through the connector, which has its own
67
+ `use_cache` option, and the shell does not expose it yet.
68
+
69
+ ## Newer server features
70
+
71
+ A server that supports them offers: DuckLake catalogs (`dh catalog kinds`,
72
+ `dh catalog create --kind ducklake`, `dh catalog rotate-role`, `dh catalog export`), the
73
+ DuckDB runtimes agents run (`dh agent runtimes`, `--runtime` on
74
+ `dh admin agent elastic-create`), per-agent monitoring over a window or range and the
75
+ queries behind it (`dh admin agent monitoring`, `dh admin agent queries`), applying
76
+ maintenance recommendations (`dh admin maintenance recommendations|apply`), and your
77
+ private editor tabs (`dh worksheet`). Against an older server these commands answer with the
78
+ server's own not-found or validation error.
79
+
80
+ ## Dashboards in git
81
+
82
+ A DuckHaven dashboard is one YAML file. Keep each one in a repository as
83
+ `<name>.dashboard.yml`, named after the `name` inside it, review changes in pull
84
+ requests, and let CI apply them. `dh dashboard` is that CI step:
85
+
86
+ ```sh
87
+ # On a pull request: check every file as publishing would, and change nothing.
88
+ dh dashboard apply dashboards/ --dry-run --publish
89
+
90
+ # On main: apply and publish each file, and remove the dashboards whose files were deleted.
91
+ dh dashboard apply dashboards/ --publish --prune --yes \
92
+ --source-id "$GITHUB_REPOSITORY" --source-ref "$GITHUB_SHA"
93
+ ```
94
+
95
+ `apply` sends each file byte for byte, so DuckHaven keeps it as written, comments included,
96
+ and reports a problem at the line its author wrote: `dashboards/sales.dashboard.yml:12:16:
97
+ error: ...`. A dashboard applied this way is managed in git: DuckHaven refuses every other
98
+ change to it until it is detached. Without `--publish` a file becomes the dashboard's draft
99
+ and readers keep the published one; publishing needs a workspace `owner`, but a dry run
100
+ needs only `writer`, so a pull request's check can run with a token that cannot publish. Every
101
+ file is applied and every failure reported, not only the first, and the exit status is the
102
+ first failure's: `5` for a file the server refused, such as `source_changed` (another
103
+ repository manages that dashboard) or `managed_dashboard`.
104
+
105
+ Applying never deletes a dashboard. `--prune` does, for the dashboards applied from
106
+ `--source-id` that no file names any more: it lists them and asks before anything is applied
107
+ (or takes `--yes`), and it deletes nothing when any file failed to apply.
108
+
109
+ The other commands:
110
+
111
+ - `validate` checks files against the workspace without storing anything: a metric that
112
+ does not exist, or a model that is not published.
113
+ - `test PATH...` runs each file once without saving it, with your grants, and reports every
114
+ widget: `ok`, `empty`, `error`, or `no_access` when you may not read what it reads, with
115
+ how long it took to arrive. It exits `6` when a widget fails or cannot be read, so a pull
116
+ request catches a query that checks out but does not run. A widget slower than `--slow`
117
+ seconds (5 by default) is marked slow, which does not fail the run. `--no-cache` runs every
118
+ query rather than answering from the result cache.
119
+ - `impact REF` lists the dashboards that read a model, or a metric or dimension of one
120
+ (`orders.revenue`): what renaming or removing it would touch.
121
+ - `exposures MANIFEST` prints [dbt exposures](https://docs.getdbt.com/docs/build/exposures)
122
+ for the published dashboards that read your dbt project's tables, so dbt's lineage shows
123
+ which dashboards read each model. Keep the file in the project and write it again when
124
+ dashboards change:
125
+ `dh --output models/duckhaven_exposures.yml dashboard exposures target/manifest.json`. Each
126
+ exposure has the dashboard's title, description and link, and depends on the models, seeds,
127
+ snapshots and sources it reads, through its semantic models' datasets or its SQL. A table
128
+ matches a dbt relation when its catalog, schema and name are the relation's database,
129
+ schema and alias, as when DuckHaven imports from dbt. dbt requires an owner:
130
+ `--owner-name` (DuckHaven by default) and `--owner-email`.
131
+ - `rename OLD FILE` renames a dashboard whose file you renamed. Run it once before merging:
132
+ applying a renamed file as usual creates a second dashboard. The old name keeps working in
133
+ links.
134
+ - `adopt NAME DIR` takes over a dashboard made in DuckHaven: it saves the dashboard's file
135
+ into `DIR` and applies it, publishing nothing. Commit the file.
136
+ - `detach`, `publish`, `delete`, `list` and `get`, each one request.
137
+ - `export NAME` prints a dashboard's file and `schema` the JSON Schema for your editor. Both
138
+ print the file itself rather than the usual JSON envelope, so
139
+ `dh dashboard export sales > dashboards/sales.dashboard.yml` works.
140
+
141
+ `dh` does not read or rewrite the files; there is no formatter yet. These commands need a
142
+ DuckHaven that offers dashboards; an older one answers with its own not-found error.
143
+
144
+ Changes to the semantic layer are checked against dashboards too. An import,
145
+ `dh semantic purge` or `dh semantic deprecate` that removes something a published dashboard
146
+ reads is refused with exit `5`, listing every dashboard and what it reads, unless you pass
147
+ `--allow-breaking`. `dh semantic import --dry-run` reports what an import would create,
148
+ update and remove, and the dashboards it would break, and changes nothing.
149
+
150
+ ## Writing a dashboard
151
+
152
+ `dh dashboard preview FILE` shows a file in DuckHaven while you edit it, without saving it.
153
+ It prints the address of a page that only you can see; open it beside your editor, or pass
154
+ `--open`. Each time you save the file, `dh` sends it, and the page runs it again, with your
155
+ grants. A file that does not load is reported at its line, and the page keeps showing the
156
+ last file that did. A metric that does not exist shows on the page as that widget's error.
157
+ Stop with Ctrl+C.
158
+
159
+ A preview ends two hours after its file last changed or it last ran. A save after that
160
+ starts a new preview, at a new address, which `dh` prints. The page is new in DuckHaven:
161
+ against a server without it, use `--once`. If your browser is signed out, sign in, then open
162
+ the address again, as signing in does not bring you back to it.
163
+
164
+ `--once` runs the file in the terminal instead, once, and prints each widget with its state,
165
+ rows and SQL. It exits as `test` does.
166
+
167
+ ### For coding agents
168
+
169
+ An AI coding agent that writes dashboard files can check its own work the same way. Put
170
+ something like this in the repository's `AGENTS.md`, and give the agent a token with the
171
+ `writer` role, which `validate` and `preview` need:
172
+
173
+ ```markdown
174
+ ## Dashboards
175
+
176
+ Dashboards live in `dashboards/`, one `<name>.dashboard.yml` file each, named after the
177
+ `name` inside it. To write or change one:
178
+
179
+ 1. Read the file format: `dh dashboard schema`.
180
+ 2. Read what a widget can use: `dh semantic model get <model>` lists its metrics and
181
+ dimensions.
182
+ 3. Edit the file.
183
+ 4. `dh --format json dashboard validate <file>`, and fix every error at its line.
184
+ 5. `dh --format json dashboard preview --once <file>`, and fix every widget whose state is
185
+ `error`. Check that the rows answer what the widget's title says.
186
+ 6. Never run `dh dashboard apply` without `--dry-run`, and never publish. CI applies the
187
+ files once a person has reviewed them.
188
+ ```
189
+
190
+ ## Exact numbers
191
+
192
+ A DuckHaven with `api_version` 3 or later sends `DECIMAL` values and 64-bit-or-wider integers
193
+ (`BIGINT`, `HUGEINT`, `count(*)`) as strings, because JSON numbers lose precision past about
194
+ 16 digits. `dh` prints them exactly as before in table and CSV output. With `--format json`
195
+ they stay strings (`"12.50"`, `"9007199254740993"`), exact. Scripts reading `dh` JSON should
196
+ convert those columns themselves rather than expect JSON numbers.
197
+
198
+ ## Documentation
199
+
200
+ - [Command-line quickstart](https://tamasmrtn.github.io/duckhaven/getting-started/cli-quickstart/) — install, sign in,
201
+ run a query
202
+ - [CLI reference](https://tamasmrtn.github.io/duckhaven/reference/cli/) — every command and flag
203
+
204
+ ## Licence
205
+
206
+ Apache-2.0. See [LICENSE](LICENSE).
@@ -0,0 +1,177 @@
1
+ # duckhaven-cli
2
+
3
+ `dh` — the command-line interface for [DuckHaven](https://github.com/tamasmrtn/duckhaven).
4
+
5
+ It gives analysts, CI pipelines and operators scriptable access to DuckHaven's REST API:
6
+ running SQL, browsing the catalog, publishing dbt lineage and semantic models, applying
7
+ dashboards from git, managing grants, and operating service accounts, users and agents.
8
+
9
+ Like every member of this repo it is a **pure HTTP client of DuckHaven's public REST
10
+ API**, authenticating with a Personal Access Token (`dh_pat_…`). The interactive REPL
11
+ holds a SQL session through
12
+ [`duckhaven-sql-connector`](../duckhaven-sql-connector/README.md); everything else,
13
+ including one-shot `dh sql`, goes over the REST API directly, because the one-shot query
14
+ route works on deployments where SQL sessions are switched off.
15
+
16
+ ## Install
17
+
18
+ ```sh
19
+ pip install duckhaven-cli
20
+ # or, to get an isolated tool install:
21
+ uv tool install duckhaven-cli
22
+ ```
23
+
24
+ ## Getting started
25
+
26
+ ```sh
27
+ dh auth login --host https://duckhaven.example.com
28
+ dh sql -q "select 1"
29
+ ```
30
+
31
+ ## The result cache
32
+
33
+ DuckHaven answers a repeated read from its result cache when nothing the query reads has
34
+ changed. `dh sql` says so on stderr when it happens; pass `--no-cache` to run the query
35
+ anyway (also on `dh session open` and `dh session exec`). An owner can switch the cache off
36
+ for a whole workspace with `dh workspace update --no-result-cache`. The interactive REPL
37
+ does not take `--no-cache`: it holds its session through the connector, which has its own
38
+ `use_cache` option, and the shell does not expose it yet.
39
+
40
+ ## Newer server features
41
+
42
+ A server that supports them offers: DuckLake catalogs (`dh catalog kinds`,
43
+ `dh catalog create --kind ducklake`, `dh catalog rotate-role`, `dh catalog export`), the
44
+ DuckDB runtimes agents run (`dh agent runtimes`, `--runtime` on
45
+ `dh admin agent elastic-create`), per-agent monitoring over a window or range and the
46
+ queries behind it (`dh admin agent monitoring`, `dh admin agent queries`), applying
47
+ maintenance recommendations (`dh admin maintenance recommendations|apply`), and your
48
+ private editor tabs (`dh worksheet`). Against an older server these commands answer with the
49
+ server's own not-found or validation error.
50
+
51
+ ## Dashboards in git
52
+
53
+ A DuckHaven dashboard is one YAML file. Keep each one in a repository as
54
+ `<name>.dashboard.yml`, named after the `name` inside it, review changes in pull
55
+ requests, and let CI apply them. `dh dashboard` is that CI step:
56
+
57
+ ```sh
58
+ # On a pull request: check every file as publishing would, and change nothing.
59
+ dh dashboard apply dashboards/ --dry-run --publish
60
+
61
+ # On main: apply and publish each file, and remove the dashboards whose files were deleted.
62
+ dh dashboard apply dashboards/ --publish --prune --yes \
63
+ --source-id "$GITHUB_REPOSITORY" --source-ref "$GITHUB_SHA"
64
+ ```
65
+
66
+ `apply` sends each file byte for byte, so DuckHaven keeps it as written, comments included,
67
+ and reports a problem at the line its author wrote: `dashboards/sales.dashboard.yml:12:16:
68
+ error: ...`. A dashboard applied this way is managed in git: DuckHaven refuses every other
69
+ change to it until it is detached. Without `--publish` a file becomes the dashboard's draft
70
+ and readers keep the published one; publishing needs a workspace `owner`, but a dry run
71
+ needs only `writer`, so a pull request's check can run with a token that cannot publish. Every
72
+ file is applied and every failure reported, not only the first, and the exit status is the
73
+ first failure's: `5` for a file the server refused, such as `source_changed` (another
74
+ repository manages that dashboard) or `managed_dashboard`.
75
+
76
+ Applying never deletes a dashboard. `--prune` does, for the dashboards applied from
77
+ `--source-id` that no file names any more: it lists them and asks before anything is applied
78
+ (or takes `--yes`), and it deletes nothing when any file failed to apply.
79
+
80
+ The other commands:
81
+
82
+ - `validate` checks files against the workspace without storing anything: a metric that
83
+ does not exist, or a model that is not published.
84
+ - `test PATH...` runs each file once without saving it, with your grants, and reports every
85
+ widget: `ok`, `empty`, `error`, or `no_access` when you may not read what it reads, with
86
+ how long it took to arrive. It exits `6` when a widget fails or cannot be read, so a pull
87
+ request catches a query that checks out but does not run. A widget slower than `--slow`
88
+ seconds (5 by default) is marked slow, which does not fail the run. `--no-cache` runs every
89
+ query rather than answering from the result cache.
90
+ - `impact REF` lists the dashboards that read a model, or a metric or dimension of one
91
+ (`orders.revenue`): what renaming or removing it would touch.
92
+ - `exposures MANIFEST` prints [dbt exposures](https://docs.getdbt.com/docs/build/exposures)
93
+ for the published dashboards that read your dbt project's tables, so dbt's lineage shows
94
+ which dashboards read each model. Keep the file in the project and write it again when
95
+ dashboards change:
96
+ `dh --output models/duckhaven_exposures.yml dashboard exposures target/manifest.json`. Each
97
+ exposure has the dashboard's title, description and link, and depends on the models, seeds,
98
+ snapshots and sources it reads, through its semantic models' datasets or its SQL. A table
99
+ matches a dbt relation when its catalog, schema and name are the relation's database,
100
+ schema and alias, as when DuckHaven imports from dbt. dbt requires an owner:
101
+ `--owner-name` (DuckHaven by default) and `--owner-email`.
102
+ - `rename OLD FILE` renames a dashboard whose file you renamed. Run it once before merging:
103
+ applying a renamed file as usual creates a second dashboard. The old name keeps working in
104
+ links.
105
+ - `adopt NAME DIR` takes over a dashboard made in DuckHaven: it saves the dashboard's file
106
+ into `DIR` and applies it, publishing nothing. Commit the file.
107
+ - `detach`, `publish`, `delete`, `list` and `get`, each one request.
108
+ - `export NAME` prints a dashboard's file and `schema` the JSON Schema for your editor. Both
109
+ print the file itself rather than the usual JSON envelope, so
110
+ `dh dashboard export sales > dashboards/sales.dashboard.yml` works.
111
+
112
+ `dh` does not read or rewrite the files; there is no formatter yet. These commands need a
113
+ DuckHaven that offers dashboards; an older one answers with its own not-found error.
114
+
115
+ Changes to the semantic layer are checked against dashboards too. An import,
116
+ `dh semantic purge` or `dh semantic deprecate` that removes something a published dashboard
117
+ reads is refused with exit `5`, listing every dashboard and what it reads, unless you pass
118
+ `--allow-breaking`. `dh semantic import --dry-run` reports what an import would create,
119
+ update and remove, and the dashboards it would break, and changes nothing.
120
+
121
+ ## Writing a dashboard
122
+
123
+ `dh dashboard preview FILE` shows a file in DuckHaven while you edit it, without saving it.
124
+ It prints the address of a page that only you can see; open it beside your editor, or pass
125
+ `--open`. Each time you save the file, `dh` sends it, and the page runs it again, with your
126
+ grants. A file that does not load is reported at its line, and the page keeps showing the
127
+ last file that did. A metric that does not exist shows on the page as that widget's error.
128
+ Stop with Ctrl+C.
129
+
130
+ A preview ends two hours after its file last changed or it last ran. A save after that
131
+ starts a new preview, at a new address, which `dh` prints. The page is new in DuckHaven:
132
+ against a server without it, use `--once`. If your browser is signed out, sign in, then open
133
+ the address again, as signing in does not bring you back to it.
134
+
135
+ `--once` runs the file in the terminal instead, once, and prints each widget with its state,
136
+ rows and SQL. It exits as `test` does.
137
+
138
+ ### For coding agents
139
+
140
+ An AI coding agent that writes dashboard files can check its own work the same way. Put
141
+ something like this in the repository's `AGENTS.md`, and give the agent a token with the
142
+ `writer` role, which `validate` and `preview` need:
143
+
144
+ ```markdown
145
+ ## Dashboards
146
+
147
+ Dashboards live in `dashboards/`, one `<name>.dashboard.yml` file each, named after the
148
+ `name` inside it. To write or change one:
149
+
150
+ 1. Read the file format: `dh dashboard schema`.
151
+ 2. Read what a widget can use: `dh semantic model get <model>` lists its metrics and
152
+ dimensions.
153
+ 3. Edit the file.
154
+ 4. `dh --format json dashboard validate <file>`, and fix every error at its line.
155
+ 5. `dh --format json dashboard preview --once <file>`, and fix every widget whose state is
156
+ `error`. Check that the rows answer what the widget's title says.
157
+ 6. Never run `dh dashboard apply` without `--dry-run`, and never publish. CI applies the
158
+ files once a person has reviewed them.
159
+ ```
160
+
161
+ ## Exact numbers
162
+
163
+ A DuckHaven with `api_version` 3 or later sends `DECIMAL` values and 64-bit-or-wider integers
164
+ (`BIGINT`, `HUGEINT`, `count(*)`) as strings, because JSON numbers lose precision past about
165
+ 16 digits. `dh` prints them exactly as before in table and CSV output. With `--format json`
166
+ they stay strings (`"12.50"`, `"9007199254740993"`), exact. Scripts reading `dh` JSON should
167
+ convert those columns themselves rather than expect JSON numbers.
168
+
169
+ ## Documentation
170
+
171
+ - [Command-line quickstart](https://tamasmrtn.github.io/duckhaven/getting-started/cli-quickstart/) — install, sign in,
172
+ run a query
173
+ - [CLI reference](https://tamasmrtn.github.io/duckhaven/reference/cli/) — every command and flag
174
+
175
+ ## Licence
176
+
177
+ Apache-2.0. See [LICENSE](LICENSE).
@@ -22,7 +22,7 @@ classifiers = [
22
22
  "Typing :: Typed",
23
23
  ]
24
24
  dependencies = [
25
- "typer>=0.27.3",
25
+ "typer>=0.28.0",
26
26
  # click.Abort is caught directly (Ctrl-C/Ctrl-D handling); typer>=0.27 no longer
27
27
  # pulls click in as its own dependency, so it must be declared here too.
28
28
  "click>=8.5.0",
@@ -18,7 +18,7 @@ version_tuple: tuple[int | str, ...]
18
18
  commit_id: str | None
19
19
  __commit_id__: str | None
20
20
 
21
- __version__ = version = '0.3.0'
22
- __version_tuple__ = version_tuple = (0, 3, 0)
21
+ __version__ = version = '0.5.0'
22
+ __version_tuple__ = version_tuple = (0, 5, 0)
23
23
 
24
24
  __commit_id__ = commit_id = None