@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.
- package/README.md +282 -0
- package/dist/cli.mjs +6780 -0
- 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.
|