@metabase/rde 0.1.0

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 (3) hide show
  1. package/README.md +282 -0
  2. package/dist/cli.mjs +6780 -0
  3. package/package.json +53 -0
package/README.md ADDED
@@ -0,0 +1,282 @@
1
+ # @metabase/rde
2
+
3
+ `rde` prepares a Mac or Linux machine for data-engineering work with Metabase and coding agents. One command, `rde init`, walks through everything a working setup needs: the `mb` CLI, the `rde` skill for your coding agents, a running Metabase Enterprise instance in Docker, an admin user, an API key wired into `mb`, your license, the databases you want to work with, and a git repository connected through Metabase's remote sync. Every step checks whether it is already done, so the wizard can be interrupted at any prompt and picked up again with the same command.
4
+
5
+ After `init`, the rest is lifecycle: `rde start`, `rde stop`, `rde status`, `rde logs`, `rde open`, and `rde db add` when another database comes along. The instance lives under `~/.rde`, listens on `127.0.0.1` only, and is used through `mb` and through the agent skill.
6
+
7
+ ## Requirements
8
+
9
+ - macOS or Linux
10
+ - Node 20.19 or newer
11
+ - git
12
+ - Docker: Docker Desktop, OrbStack, or colima on a Mac; the `docker` package on Linux, with your user in the `docker` group
13
+
14
+ `rde init` checks all four first and prints what is missing with the install hint for your platform.
15
+
16
+ ## Install
17
+
18
+ ```sh
19
+ npm install -g @metabase/rde
20
+ rde init
21
+ ```
22
+
23
+ ## What `rde init` does
24
+
25
+ The wizard shows its checklist first (`✓` done, `○` to do, `–` not applicable), runs the steps still to do in order, and ends with a summary of your environment. A first run on a machine that has Docker but not yet `mb` starts like this:
26
+
27
+ ```
28
+ ┌ rde init
29
+ ✓ Check this machine
30
+ ○ Install the Metabase CLI
31
+ ○ Install the rde skill for your coding agents
32
+ ○ Install Metabase
33
+ ○ Start Metabase
34
+ ○ Create the admin user
35
+ ○ Connect the Metabase CLI
36
+ ○ Activate your license
37
+ ○ Connect your databases
38
+ – Connect a git repository
39
+ ○ Summary
40
+ │
41
+ ◆ Install @metabase/cli globally with npm?
42
+ ```
43
+
44
+ The git step reads `–` until a license with remote sync is active; it is checked again when its turn comes, so a run that activates a license connects the repository in the same pass.
45
+
46
+ | Step | What it does |
47
+ | --- | --- |
48
+ | Check this machine | Platform, Node version, git, and a reachable Docker daemon |
49
+ | Install the Metabase CLI | `@metabase/cli` (`mb`) with the package manager that installed `rde` |
50
+ | Install the rde skill | The `rde` skill from `metabase/agent-skills` for the agents you pick (Claude Code, Codex, Cursor, Gemini CLI, OpenCode, Windsurf) |
51
+ | Install Metabase | Pulls `metabase/metabase-enterprise:latest` (or `--image`) and creates the container on port 13000 (or the first free port above it, or `--port`) |
52
+ | Start Metabase | Starts the container and waits for `/api/health`, showing Metabase's own progress |
53
+ | Create the admin user | Default credentials or your own, see below |
54
+ | Connect the Metabase CLI | Creates an API key named `rde` and logs `mb` in with it under the profile `default`, so plain `mb …` uses the instance; if `default` already points at another Metabase, offers the named profile `rde` instead |
55
+ | Activate your license | Optional. Paste a token, or press Enter to skip; remote sync needs one with the `remote-sync` feature |
56
+ | Connect your databases | Paste a connection string (or fill the fields one by one), review, test, add; repeat |
57
+ | Connect a git repository | Only with a license. Initializes or reuses a repository and points Metabase's remote sync at it |
58
+ | Summary | URL, login, `mb` profile, databases, repository, and the command that opens each detected agent |
59
+
60
+ The second run on the same machine detects every step as done and prints the summary only:
61
+
62
+ ```
63
+ ┌ rde init
64
+ ✓ Check this machine
65
+ ✓ Install the Metabase CLI
66
+ ✓ Install the rde skill for your coding agents
67
+ ✓ Install Metabase
68
+ ✓ Start Metabase
69
+ ✓ Create the admin user
70
+ ✓ Connect the Metabase CLI
71
+ – Activate your license
72
+ ✓ Connect your databases
73
+ – Connect a git repository
74
+ ○ Summary
75
+ │
76
+ ◇ Your environment ────────────────────────────────────────────────────╮
77
+ │ │
78
+ │ Metabase: http://localhost:13000 │
79
+ │ Login: admin@metabase.com / metabase123 │
80
+ │ Metabase CLI: mb <command> │
81
+ │ Databases: │
82
+ │ Sample Database (sqlite, sync complete) │
83
+ │ warehouse (postgres, sync complete) │
84
+ │ Remote sync: not configured (no license) │
85
+ │ rde skill: installed for Claude Code │
86
+ │ Start working: │
87
+ │ claude (Claude Code) │
88
+ │ Lifecycle: rde status, rde stop, rde start │
89
+ │ │
90
+ ├───────────────────────────────────────────────────────────────────────╯
91
+ │
92
+ └ rde init finished
93
+ ```
94
+
95
+ Ctrl-C at any prompt stops the run; `rde init` again continues from the first step that is not done. `rde init --from license` re-runs from a step on, `rde init --only databases` runs one step.
96
+
97
+ ## Credentials
98
+
99
+ The admin-user step offers two variants:
100
+
101
+ - **Use default credentials**: `admin@metabase.com` / `metabase123`. Both are written to `~/.rde` and shown in the summary and in `rde status`, so agents and scripts can log in without asking you. Pick this for a local instance nobody else can reach.
102
+ - **Enter my own**: email and password are asked once, sent to Metabase, and never written anywhere by `rde`.
103
+
104
+ In both variants `rde` creates an API key named `rde` in the Administrators group and stores it in the instance's state file with mode `0600`. That key is what `mb` and `rde` itself use afterwards.
105
+
106
+ ## What lands in `~/.rde`, and what never does
107
+
108
+ ```
109
+ ~/.rde/
110
+ config.json { schemaVersion, defaultInstance }
111
+ instances/default/
112
+ state.json mode 0600: runtime, url, admin credentials variant, API key, license
113
+ features, databases, git remote, step records
114
+ data/ mounted into the container as /rde
115
+ metabase.db/metabase.db.mv.db the H2 application database
116
+ plugins/ driver jars (Oracle, Vertica) go here
117
+ content.git/ the bare repository behind a local git remote
118
+ ```
119
+
120
+ Three things are never written to disk or to a log by `rde`: the license token (it goes to Metabase, which keeps it in its own application database), a password you typed in the "Enter my own" variant, and a git access token for a hosted remote (Metabase encrypts it on its side). The `mb` profile `rde` lives where `mb` keeps its profiles, under `$XDG_CONFIG_HOME` or `~/.config`.
121
+
122
+ The Metabase container publishes its port on `127.0.0.1` only, so the instance is reachable from this machine and from nothing else on the network.
123
+
124
+ ## Everyday commands
125
+
126
+ | Command | What it does |
127
+ | --- | --- |
128
+ | `rde start` | Starts the instance and waits until it is healthy |
129
+ | `rde stop` | Stops it; the data stays |
130
+ | `rde status` | The init checklist, container state, health, databases with their sync state, remote sync state; `--json` for scripts |
131
+ | `rde logs` | The container's log; `-f` keeps streaming |
132
+ | `rde open` | Opens the instance in the browser |
133
+ | `rde db add` | The same database wizard as in `init` |
134
+ | `rde db list` | The connected databases; `--json` for scripts |
135
+ | `rde doctor` | One table of checks with a fix hint per failure; `--fix` re-runs the init steps behind them; `--json` for scripts; exit 1 while anything fails |
136
+ | `rde uninstall` | Removes the instance, its data, and the `mb` profile; see [Resetting](#resetting) |
137
+
138
+ Everything else goes through the Metabase CLI, logged in as the profile `default`, so plain `mb …` talks to the instance:
139
+
140
+ ```sh
141
+ mb db list
142
+ mb git-sync status
143
+ ```
144
+
145
+ If your `default` profile already pointed at another Metabase when `init` ran, it was left alone and the instance was connected as the profile `rde` (`init` asks; `--mb-profile default|rde` answers without a terminal). Then it is `mb --profile rde …`, or `export MB_PROFILE=rde` once per shell; the summary and `rde status` say which.
146
+
147
+ ## The git repository
148
+
149
+ With a license that includes remote sync, the last step connects a git repository. You choose where the working directory lives (here, a new directory, or an existing repository) and where Metabase pushes:
150
+
151
+ - **Local remote inside `~/.rde`** (default): a bare repository at `instances/default/data/content.git`, mounted into the container and reached as `file:///rde/content.git`. No account, no token. Your working directory gets it as `origin` (or as `rde-remote` when `origin` already points elsewhere).
152
+ - **Hosted remote**: a GitHub, GitLab, or Bitbucket `https://` URL plus a token with read and write access. `rde` tests the connection through Metabase before saving anything.
153
+
154
+ A repository that already holds Metabase content is imported on the spot. Afterwards:
155
+
156
+ ```sh
157
+ cd <your working directory>
158
+ mb git-sync status
159
+ mb git-sync export -m "what changed"
160
+ git pull # after an export, to see the YAML files
161
+ ```
162
+
163
+ ## Running `init` without a terminal
164
+
165
+ Every prompt can be answered ahead of time, by a flag or by a JSON answers file, so an agent or a CI job can run `rde init` unattended. When stdin is not a terminal, the first prompt nothing answers fails with exit code 2 and a message naming the step, the prompt, and the flag or answers key that would have answered it; nothing hangs. A text prompt with a default (image, port, display name) takes its default, as Enter would.
166
+
167
+ ### Flags
168
+
169
+ ```sh
170
+ rde init --agents claude-code,codex --admin default --skip-license \
171
+ --database "postgres=postgres://user:pass@localhost:5432/app" \
172
+ --git-dir ~/analytics --git-remote local
173
+ ```
174
+
175
+ | Flag | Answers |
176
+ | --- | --- |
177
+ | `--agents claude-code,codex` / `--skip-agents` | Which agents get the skill |
178
+ | `--image`, `--port` | The Docker image and host port |
179
+ | `--admin default\|prompted`, `--admin-email`, `--admin-password` | The admin user; an email or password implies `prompted` |
180
+ | `--license-token` / `--skip-license` | The license |
181
+ | `--database <engine>=<connection string>` (repeatable) / `--skip-databases` | The warehouses |
182
+ | `--git-dir`, `--git-remote local\|hosted`, `--git-url`, `--git-token` / `--skip-git` | The content repository; a remote or URL without `--git-dir` means the current directory |
183
+ | `--yes` | Every confirmation (installing `mb`, skipping databases) |
184
+
185
+ A secret flag (`--admin-password`, `--license-token`, `--git-token`) takes `-` to read one line from stdin, the way `mb auth login` takes its key, or a literal `$VAR` (single-quoted, so the shell leaves it alone) to read the environment; either keeps the value out of your shell history and process listings. Only one flag can read stdin.
186
+
187
+ ```sh
188
+ echo "$PASSWORD" | rde init --admin-email me@example.com --admin-password - …
189
+ rde init --license-token '$RDE_LICENSE_TOKEN' …
190
+ ```
191
+
192
+ ### Answers file
193
+
194
+ `rde init --answers <file>` reads a JSON file with one section per step; flags win over the file, key by key. A `$VAR` string is read from the environment, and an unset variable is an error rather than an empty answer.
195
+
196
+ ```json
197
+ {
198
+ "install-mb": { "package-manager": "npm" },
199
+ "agents-skills": { "agents": ["claude-code"] },
200
+ "runtime": { "image": "metabase/metabase-enterprise:latest", "port": 13000 },
201
+ "admin-user": { "variant": "prompted", "email": "me@example.com", "password": "$RDE_ADMIN_PASSWORD" },
202
+ "license": { "token": "$RDE_LICENSE_TOKEN" },
203
+ "databases": [
204
+ { "engine": "postgres", "uri": "$RDE_DATABASE_1_URI" },
205
+ { "engine": "bigquery-cloud-sdk", "fields": { "project-id": "acme", "service-account-json": "/keys/acme.json" }, "name": "Warehouse" }
206
+ ],
207
+ "git-sync": { "location": "new", "path": "~/analytics", "remote": "local-bare" }
208
+ }
209
+ ```
210
+
211
+ `"license": { "token": null }` skips the license, `"databases": []` connects none, `"git-sync": { "location": "skip" }` leaves the repository for later. A database is pasted as a `uri` or entered with `fields`, keyed by the driver's field names as the admin form shows them; a file field takes a path. Anything a `fields` entry leaves out is asked in the terminal, or named in the error without one.
212
+
213
+ ### Recording a run
214
+
215
+ `rde init --print-answers <file>` writes, once an interactive run finishes, the answers file that reproduces it. Secrets are written as references, never as values: `$RDE_ADMIN_PASSWORD`, `$RDE_LICENSE_TOKEN`, `$RDE_GIT_TOKEN`, `$RDE_DATABASE_<n>_URI` for a connection string carrying a password, and `$RDE_DATABASE_<n>_<FIELD>` for a secret field. Set those variables and run `rde init --answers <file>` on the next machine.
216
+
217
+ ## Resetting
218
+
219
+ `rde uninstall` returns the machine to the state before `rde init`: it stops and removes the container, forgets the `mb` profile it logged in (`default`, or `rde`; never a profile pointing at another Metabase), and deletes `~/.rde/instances/default` along with the `config.json` entry. It shows the list first and asks once; `--yes` skips the question. Your working directory and its git history are never touched, nor are the `mb` CLI and Docker itself.
220
+
221
+ ```sh
222
+ rde uninstall # container, mb profile, ~/.rde/instances/default
223
+ rde uninstall --keep-data # container and profile only; `rde init` reinstalls from the kept data
224
+ rde uninstall --remove-skill # also the rde skill from your coding agents
225
+ rde uninstall --remove-image # also the Docker image (otherwise it stays for the next init)
226
+ ```
227
+
228
+ Running it twice is a no-op. It also works with no `~/.rde` at all, so a leftover `rde-metabase-default` container or `mb` profile from a half-finished run is cleaned up the same way. Anything it could not remove is listed at the end and the command exits with 1.
229
+
230
+ ## Troubleshooting
231
+
232
+ Start with `rde doctor`. It checks the machine (platform, Node, git, Docker, `mb`), the instance (container, port, health, admin user, API key, `mb` profile, license, databases, remote sync), and the skill for each detected coding agent, one row each with ✓, ✗, or – and a hint under every ✗:
233
+
234
+ ```
235
+ ✓ container rde-metabase-default stopped (metabase/metabase-enterprise:latest)
236
+ ✓ port 13000 is free
237
+ ✗ health unreachable
238
+ → `rde start`
239
+ – admin user Metabase is not healthy
240
+ ```
241
+
242
+ `rde doctor --fix` lists the init steps that repair the failed rows, asks once (`--yes` skips the question), re-runs them, and prints the table again. A failure with no automatic fix, such as a port held by another program, keeps its hint and the exit code stays 1 until it is resolved.
243
+
244
+ **Docker is not running.** The first step prints the check that failed, with what Docker said and what to do, and exits with code 2:
245
+
246
+ ```
247
+ ◇ This machine ──────────────────────────────────────────────────────────────────────────────────╮
248
+ │ │
249
+ │ ✓ macOS │
250
+ │ ✓ Node v22.13.1 │
251
+ │ ✓ git version 2.50.1 │
252
+ │ ✗ Docker: Cannot connect to the Docker daemon at unix:///var/run/docker.sock. Is the docker │
253
+ │ daemon running? │
254
+ │ Install Docker Desktop (https://www.docker.com/products/docker-desktop/), OrbStack, or │
255
+ │ colima, and start it │
256
+ │ │
257
+ ├─────────────────────────────────────────────────────────────────────────────────────────────────╯
258
+ Fix the items above and run rde init again
259
+ ```
260
+
261
+ Start Docker (or `colima start`) and run `rde init` again. `rde start` and `rde status` report the same condition on an existing instance.
262
+
263
+ **The port is in use.** Port 13000 is the default because 3000 is usually taken by a Metabase checkout's dev server. When 13000 is busy too, the runtime step says so and offers the next free port: `Port 13000 is in use by another program; 13001 is free`. Accept it, type another, or pass `--port`. A container that exists with a different port or image is reported with the `docker rm -f` command that clears it.
264
+
265
+ **The license token is rejected.** Activation ends with `Metabase reports the token as invalid` (or another status Metabase returned). Check the token, and check that the container can reach `token-check.metabase.com`: activation needs outbound network access. Run `rde init --from license` to try again; press Enter at the prompt to skip the license and carry on without remote sync.
266
+
267
+ ## Development
268
+
269
+ ```sh
270
+ bun install
271
+ bun run check # tsc, oxlint + boundary linter, oxfmt, unit tests
272
+ bin/rde-dev init # runs from source with RDE_HOME and the mb config under .dev-state/
273
+ ```
274
+
275
+ The end-to-end lane runs the built binary against real Docker: a seeded Postgres 16 sidecar on `127.0.0.1:15432` (`RDE_E2E_PG_PORT` to change it) and a fresh instance under `.e2e-state/`, with a fake `HOME` so the skill installer never touches your agents. `bun run build` must precede `bun run test:e2e`.
276
+
277
+ ```sh
278
+ bun run build && bun run e2e:up && bun run test:e2e
279
+ bun run e2e:down
280
+ ```
281
+
282
+ With `MB_PREMIUM_EMBEDDING_TOKEN` in the environment the lane also activates the license and connects a local git remote; without it that test is reported as skipped.