nimblybase 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 +222 -0
  2. package/dist/index.js +4165 -0
  3. package/package.json +41 -0
package/README.md ADDED
@@ -0,0 +1,222 @@
1
+ # nimblybase
2
+
3
+ The NimblyBase command line. Projects, keys and backends from a terminal.
4
+
5
+ ```bash
6
+ npx nimblybase login
7
+ npx nimblybase create "My App"
8
+ npx nimblybase keys create "local dev"
9
+ ```
10
+
11
+ Install it properly if you use it often:
12
+
13
+ ```bash
14
+ npm install -g nimblybase
15
+ nimbly --help
16
+ ```
17
+
18
+ ## Signing in
19
+
20
+ Run:
21
+
22
+ ```bash
23
+ nimbly login
24
+ ```
25
+
26
+ The CLI opens your browser, where you choose the organization and approve
27
+ the requested permissions. The resulting grant is stored in your login
28
+ keychain on macOS, and otherwise in
29
+ `~/.config/nimblybase/credentials.json` with permissions `0600`. `nimbly
30
+ login` always says which one it used.
31
+
32
+ For a machine without a browser, create an access token in the dashboard
33
+ under **Access tokens** and run `nimbly login --token <token>`. Omitting the
34
+ value prompts without echoing it.
35
+
36
+ In CI, set `NIMBLYBASE_TOKEN` instead. It takes precedence over anything
37
+ stored and is never written to disk.
38
+
39
+ ## Linking a directory
40
+
41
+ ```bash
42
+ nimbly link my-app
43
+ ```
44
+
45
+ Writes `nimblybase.json`, which records the project id and slug and **no
46
+ credentials**. Commit it: a teammate cloning the repo gets the same target
47
+ without being told a UUID. Commands run anywhere beneath it use that project
48
+ unless you name another with `-p`.
49
+
50
+ ## Scripting
51
+
52
+ Every command takes `--json`. In JSON mode stdout carries the document and
53
+ nothing else — progress, warnings and errors all go to stderr, including a
54
+ machine-readable error document.
55
+
56
+ Exit codes are stable:
57
+
58
+ | code | meaning |
59
+ |---|---|
60
+ | 0 | success |
61
+ | 1 | failed |
62
+ | 2 | bad arguments |
63
+ | 3 | not signed in, or the token is no longer valid |
64
+ | 4 | not found |
65
+ | 5 | refused by permissions |
66
+ | 6 | the API could not be reached |
67
+
68
+ ```bash
69
+ nimbly projects --json | jq -r '.projects[] | select(.status == "active") | .slug'
70
+ ```
71
+
72
+ ## Opening a table to your app
73
+
74
+ The key that ships in a browser — the anon key — can do **nothing** until a
75
+ policy says otherwise. That is the design, not a gap: the alternative is a
76
+ public key that runs arbitrary SQL.
77
+
78
+ ```bash
79
+ nimbly policies # what is open, and to whom
80
+ nimbly policies allow posts select --using true # let anyone read posts
81
+ nimbly policies allow posts select --using '{"col":"published","eq":true}'
82
+ nimbly policies revoke 3
83
+ ```
84
+
85
+ A table absent from `nimbly policies` is closed entirely — which is almost
86
+ always the answer to "why does my app get nothing back".
87
+
88
+ An expression is data, not SQL. `{"col":"published","eq":true}` means
89
+ published rows; `{"and":[…]}` and `{"or":[…]}` combine them; and
90
+ `{"col":"owner_id","eq":{"ctx":"userId"}}` means rows belonging to the
91
+ signed-in end user — which matches **nothing** for an anonymous caller, so it
92
+ fails closed rather than open.
93
+
94
+ `select`, `update` and `delete` need `--using` (which rows may be touched).
95
+ `insert` and `update` need `--check` (which rows may be written).
96
+
97
+ ## Edge functions
98
+
99
+ ```bash
100
+ nimbly functions deploy ./webhook.js
101
+ nimbly functions
102
+ nimbly functions delete webhook
103
+ ```
104
+
105
+ A function is a standard Worker module — `export default { async fetch(request, env) { … } }` —
106
+ published to `https://<ref>.<host>/fn/<name>`.
107
+
108
+ **The URL is public.** No NimblyBase key is required to call it, because a
109
+ webhook handler that demanded one could not receive a webhook. Check a
110
+ signature or a shared secret inside your own code.
111
+
112
+ It receives **this project's own resources** and nothing else: `env.DB`,
113
+ `env.FILES`, `env.KV`, and `env.VECTORS` / `env.AI` where the project has
114
+ them. It cannot reach another project's anything, and it does not receive
115
+ the platform-wide bindings our own Worker carries.
116
+
117
+ ## When something is broken
118
+
119
+ ```bash
120
+ nimbly diagnose
121
+ ```
122
+
123
+ Checks, in the order things actually break: is the project serving, does it
124
+ have keys, does the database have tables, does any row policy exist, and what
125
+ has actually been failing in the last day. Prints one sentence, then the
126
+ findings that earned it. Key use is inferred from request logs rather than a
127
+ control-plane timestamp that the edge cannot update.
128
+
129
+ The commonest answer by a distance is that a table has no policy — which
130
+ makes an anon key get a 403 rather than an empty list.
131
+
132
+ ## Reading as your app reads
133
+
134
+ `nimbly sql` uses a service key and bypasses policies. `nimbly rows` goes
135
+ through the row API, so it sees what an app sees — which is the only way to
136
+ check a policy actually works.
137
+
138
+ ```bash
139
+ nimbly rows posts --as anon
140
+ nimbly rows posts --as anon --where published=eq.true --order created_at.desc
141
+ nimbly rows posts --as authenticated --as-user u-42
142
+ ```
143
+
144
+ Rows back means the app works. A policy error means it is locked out, and the
145
+ message says which role and which operation.
146
+
147
+ `--where` is repeatable and takes `<column>=<op>.<value>` — `eq`, `neq`, `gt`,
148
+ `gte`, `lt`, `lte`, `like`, `in`, `is`. Values never go into a string you have
149
+ to quote.
150
+
151
+ ## Logs
152
+
153
+ ```bash
154
+ nimbly logs # the last hour
155
+ nimbly logs --level error # only failures
156
+ nimbly logs --since 24h --route /v1/sql
157
+ ```
158
+
159
+ One line per request: status, method, route, duration, rows read. A failed
160
+ SQL statement is printed underneath its own line, because when it is there it
161
+ is the only thing you want to read.
162
+
163
+ Newest **last**, so the thing you just did ends up next to your prompt.
164
+
165
+ Logs are readable while a project is paused — "why did it stop working" is a
166
+ question asked about things that stopped working. They are kept for three
167
+ months, and under heavy load rows are sampled per project; when that happens
168
+ the CLI says so rather than quietly under-reporting.
169
+
170
+ Never recorded: bound parameters, request or response bodies, credentials, or
171
+ a storage object key in the route column. The SQL statement is recorded only
172
+ when it **failed** — a working application should not accumulate a
173
+ three-month copy of its own query history.
174
+
175
+ ## Connecting an agent
176
+
177
+ ```bash
178
+ nimbly mcp claude --with-token
179
+ ```
180
+
181
+ Prints the exact command or config block for Claude Code, Cursor, VS Code, or
182
+ raw MCP JSON. Without `--with-token` it emits a placeholder, because this
183
+ output is the kind of thing people paste into issues.
184
+
185
+ ## Environment
186
+
187
+ | variable | effect |
188
+ |---|---|
189
+ | `NIMBLYBASE_TOKEN` | Use this token instead of the stored one |
190
+ | `NIMBLYBASE_API_URL` | Point at a different API |
191
+ | `NIMBLYBASE_NO_KEYCHAIN` | Set to `1` to always use the credentials file |
192
+ | `NO_COLOR` | Disable colour |
193
+
194
+ ## The database
195
+
196
+ The schema is **declared**, not migrated by hand. You write the shape you
197
+ want; the difference is computed and only the difference runs — which is what
198
+ makes `db push` safe to run twice.
199
+
200
+ ```bash
201
+ nimbly db pull # write the live schema to schema.json
202
+ $EDITOR schema.json
203
+ nimbly db status # what push would change, changing nothing
204
+ nimbly db push # plans, prints the statements, asks, then applies
205
+ ```
206
+
207
+ `db push` **always plans first**, even with `--yes`. Nothing is applied that
208
+ has not been printed. A change that drops a table or column additionally
209
+ needs `--allow-destructive`; `--yes` on its own is consent to run the
210
+ migration, not consent to lose data.
211
+
212
+ A plan that cannot be carried out completely is refused whole — never applied
213
+ half way.
214
+
215
+ ```bash
216
+ nimbly sql "select * from notes where id = ?" --param 7
217
+ ```
218
+
219
+ `--param` is repeatable and fills the `?` placeholders in order. Values never
220
+ go into the statement string: a CLI whose only option is to paste them in
221
+ teaches everybody — and every agent reading a shell history — to write
222
+ injectable SQL.