@graphit/cli 0.2.270 → 0.2.307

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 (38) hide show
  1. package/.claude-plugin/marketplace.json +3 -3
  2. package/.claude-plugin/plugin.json +1 -1
  3. package/.codex-plugin/plugin.json +1 -1
  4. package/bin/graphit +1 -1
  5. package/bin/graphit.ps1 +1 -1
  6. package/dist/commands/connector.js +4 -2
  7. package/dist/commands/connector.js.map +1 -1
  8. package/dist/commands/dashboard.js +24 -11
  9. package/dist/commands/dashboard.js.map +1 -1
  10. package/dist/commands/ds/refresh-history.js +2 -1
  11. package/dist/commands/ds/refresh-history.js.map +1 -1
  12. package/dist/commands/ds/ui-only.js +10 -4
  13. package/dist/commands/ds/ui-only.js.map +1 -1
  14. package/dist/commands/ds.js +8 -4
  15. package/dist/commands/ds.js.map +1 -1
  16. package/dist/commands/governance.js +2 -2
  17. package/dist/commands/governance.js.map +1 -1
  18. package/dist/commands/kb-create.js +8 -8
  19. package/dist/commands/kb-create.js.map +1 -1
  20. package/dist/commands/kb-delete.js +4 -1
  21. package/dist/commands/kb-delete.js.map +1 -1
  22. package/dist/commands/kb-read.js +22 -10
  23. package/dist/commands/kb-read.js.map +1 -1
  24. package/dist/commands/kb-shared.d.ts +3 -0
  25. package/dist/commands/kb-shared.js +12 -0
  26. package/dist/commands/kb-shared.js.map +1 -1
  27. package/dist/commands/kb-update.js +19 -10
  28. package/dist/commands/kb-update.js.map +1 -1
  29. package/dist/commands/query.js +2 -1
  30. package/dist/commands/query.js.map +1 -1
  31. package/package.json +4 -4
  32. package/scripts/commander-walk.mjs +154 -0
  33. package/scripts/generate-commands-doc.mjs +26 -95
  34. package/scripts/generate-tool-manifest.mjs +613 -0
  35. package/scripts/verb-policy-source.json +555 -0
  36. package/skills/graphit/SKILL.md +2 -2
  37. package/skills/graphit/VERSION.json +1 -1
  38. package/skills/graphit/references/onboarding.md +8 -0
@@ -0,0 +1,555 @@
1
+ {
2
+ "$comment": [
3
+ "HAND-MAINTAINED. This is the only place a CLI verb's in-app behaviour is decided.",
4
+ "Project #275: the platform agent's tool surface is generated from the Commander tree,",
5
+ "but Commander knows nothing about approval, mutation class or whether a verb belongs",
6
+ "in the app at all. Those are product decisions and they live here.",
7
+ "",
8
+ "The generator fails when a Commander verb has no row here, and fails again when a row",
9
+ "here names a verb Commander no longer has. Absence is never silent (US-3.3): a verb",
10
+ "kept out of the app carries surface != 'both' AND a reason a human wrote.",
11
+ "",
12
+ "Fields per verb:",
13
+ " surface both | cli_only | app_only - where the verb is callable",
14
+ " is_read_only true when the verb cannot change stored state",
15
+ " mutation_class none | kb | canvas | dashboard | data_source | governance",
16
+ " (routes the validation-gateway pipeline and the loop guards)",
17
+ " requires_approval true when the turn must show an approval card before executing",
18
+ " silent_retry_exempt true when a failure must surface instead of being retried silently",
19
+ " reason REQUIRED when surface != 'both'",
20
+ " app_params parameters the app has and the CLI does not, each { type, required,",
21
+ " description, reason }. For verbs whose two surfaces differ in",
22
+ " MECHANICS rather than capability - the only case so far is canvas",
23
+ " HTML, which the CLI carries through --file/--stdin and an in-app",
24
+ " turn has no filesystem for. A reason is REQUIRED for the same",
25
+ " rule absence follows: an asymmetry nobody wrote down is one nobody",
26
+ " reviewed. Never a way to give the app capability the CLI lacks."
27
+ ],
28
+ "nouns": {
29
+ "kb_read": "Read the Knowledge Base - list, fetch, search and traverse metrics, dimensions, tables, rules, domains, topics, synonyms and relationships",
30
+ "kb_write": "Author the Knowledge Base - create, update, delete and verify metrics, dimensions, rules, domains, topics, synonyms, relationships and templates",
31
+ "ds": "Data sources - cached snapshots of warehouse queries and uploaded files",
32
+ "dashboard": "Custom dashboards - the HTML canvas, its entities, drafts and exports",
33
+ "query": "Run SQL against a cached data source or a live warehouse, through the governance gateway",
34
+ "metadata": "Warehouse metadata discovery - schemas, tables and columns",
35
+ "governance": "Governance conformance and the audit log",
36
+ "status": "The caller's effective permissions per domain"
37
+ },
38
+ "verbs": {
39
+ "auth login": {
40
+ "surface": "cli_only",
41
+ "is_read_only": false,
42
+ "mutation_class": "none",
43
+ "requires_approval": false,
44
+ "silent_retry_exempt": true,
45
+ "reason": "Browser OAuth that writes credentials to the caller's machine. An in-app turn is already inside an authenticated session, so there is nothing for the agent to log in to."
46
+ },
47
+ "auth status": {
48
+ "surface": "cli_only",
49
+ "is_read_only": true,
50
+ "mutation_class": "none",
51
+ "requires_approval": false,
52
+ "silent_retry_exempt": false,
53
+ "reason": "Reports the local credential file's state. In-app the session is the credential; `status` answers the question the agent actually has (what may I do?)."
54
+ },
55
+ "auth logout": {
56
+ "surface": "cli_only",
57
+ "is_read_only": false,
58
+ "mutation_class": "none",
59
+ "requires_approval": true,
60
+ "silent_retry_exempt": true,
61
+ "reason": "Clears credentials on the caller's machine. An agent that can log the user out of the app it is running inside is a footgun with no upside."
62
+ },
63
+ "status": {
64
+ "surface": "both",
65
+ "is_read_only": true,
66
+ "mutation_class": "none",
67
+ "requires_approval": false,
68
+ "silent_retry_exempt": false
69
+ },
70
+ "kb list": {
71
+ "surface": "both",
72
+ "noun": "kb_read",
73
+ "is_read_only": true,
74
+ "mutation_class": "none",
75
+ "requires_approval": false,
76
+ "silent_retry_exempt": false
77
+ },
78
+ "kb get": {
79
+ "surface": "both",
80
+ "noun": "kb_read",
81
+ "is_read_only": true,
82
+ "mutation_class": "none",
83
+ "requires_approval": false,
84
+ "silent_retry_exempt": false
85
+ },
86
+ "kb search": {
87
+ "surface": "both",
88
+ "noun": "kb_read",
89
+ "is_read_only": true,
90
+ "mutation_class": "none",
91
+ "requires_approval": false,
92
+ "silent_retry_exempt": false
93
+ },
94
+ "kb explore": {
95
+ "surface": "both",
96
+ "noun": "kb_read",
97
+ "is_read_only": true,
98
+ "mutation_class": "none",
99
+ "requires_approval": false,
100
+ "silent_retry_exempt": false
101
+ },
102
+ "kb usage": {
103
+ "surface": "both",
104
+ "noun": "kb_read",
105
+ "is_read_only": true,
106
+ "mutation_class": "none",
107
+ "requires_approval": false,
108
+ "silent_retry_exempt": false
109
+ },
110
+ "kb verify": {
111
+ "surface": "both",
112
+ "noun": "kb_write",
113
+ "is_read_only": false,
114
+ "mutation_class": "kb",
115
+ "requires_approval": true,
116
+ "silent_retry_exempt": false
117
+ },
118
+ "kb unverify": {
119
+ "surface": "both",
120
+ "noun": "kb_write",
121
+ "is_read_only": false,
122
+ "mutation_class": "kb",
123
+ "requires_approval": true,
124
+ "silent_retry_exempt": false
125
+ },
126
+ "kb create metric": {
127
+ "surface": "both",
128
+ "noun": "kb_write",
129
+ "is_read_only": false,
130
+ "mutation_class": "kb",
131
+ "requires_approval": true,
132
+ "silent_retry_exempt": false
133
+ },
134
+ "kb create dimension": {
135
+ "surface": "both",
136
+ "noun": "kb_write",
137
+ "is_read_only": false,
138
+ "mutation_class": "kb",
139
+ "requires_approval": true,
140
+ "silent_retry_exempt": false
141
+ },
142
+ "kb create rule": {
143
+ "surface": "both",
144
+ "noun": "kb_write",
145
+ "is_read_only": false,
146
+ "mutation_class": "kb",
147
+ "requires_approval": true,
148
+ "silent_retry_exempt": false
149
+ },
150
+ "kb create domain": {
151
+ "surface": "both",
152
+ "noun": "kb_write",
153
+ "is_read_only": false,
154
+ "mutation_class": "kb",
155
+ "requires_approval": true,
156
+ "silent_retry_exempt": false
157
+ },
158
+ "kb create synonym": {
159
+ "surface": "both",
160
+ "noun": "kb_write",
161
+ "is_read_only": false,
162
+ "mutation_class": "kb",
163
+ "requires_approval": true,
164
+ "silent_retry_exempt": false
165
+ },
166
+ "kb create relationship": {
167
+ "surface": "both",
168
+ "noun": "kb_write",
169
+ "is_read_only": false,
170
+ "mutation_class": "kb",
171
+ "requires_approval": true,
172
+ "silent_retry_exempt": false
173
+ },
174
+ "kb create topic": {
175
+ "surface": "both",
176
+ "noun": "kb_write",
177
+ "is_read_only": false,
178
+ "mutation_class": "kb",
179
+ "requires_approval": true,
180
+ "silent_retry_exempt": false
181
+ },
182
+ "kb create template": {
183
+ "surface": "both",
184
+ "noun": "kb_write",
185
+ "is_read_only": false,
186
+ "mutation_class": "kb",
187
+ "requires_approval": true,
188
+ "silent_retry_exempt": false
189
+ },
190
+ "kb update metric": {
191
+ "surface": "both",
192
+ "noun": "kb_write",
193
+ "is_read_only": false,
194
+ "mutation_class": "kb",
195
+ "requires_approval": true,
196
+ "silent_retry_exempt": false
197
+ },
198
+ "kb update dimension": {
199
+ "surface": "both",
200
+ "noun": "kb_write",
201
+ "is_read_only": false,
202
+ "mutation_class": "kb",
203
+ "requires_approval": true,
204
+ "silent_retry_exempt": false
205
+ },
206
+ "kb update rule": {
207
+ "surface": "both",
208
+ "noun": "kb_write",
209
+ "is_read_only": false,
210
+ "mutation_class": "kb",
211
+ "requires_approval": true,
212
+ "silent_retry_exempt": false
213
+ },
214
+ "kb update template": {
215
+ "surface": "both",
216
+ "noun": "kb_write",
217
+ "is_read_only": false,
218
+ "mutation_class": "kb",
219
+ "requires_approval": true,
220
+ "silent_retry_exempt": false
221
+ },
222
+ "kb update table": {
223
+ "surface": "both",
224
+ "noun": "kb_write",
225
+ "is_read_only": false,
226
+ "mutation_class": "kb",
227
+ "requires_approval": true,
228
+ "silent_retry_exempt": false
229
+ },
230
+ "kb update domain": {
231
+ "surface": "both",
232
+ "noun": "kb_write",
233
+ "is_read_only": false,
234
+ "mutation_class": "kb",
235
+ "requires_approval": true,
236
+ "silent_retry_exempt": false
237
+ },
238
+ "kb update synonym": {
239
+ "surface": "both",
240
+ "noun": "kb_write",
241
+ "is_read_only": false,
242
+ "mutation_class": "kb",
243
+ "requires_approval": true,
244
+ "silent_retry_exempt": false
245
+ },
246
+ "kb update relationship": {
247
+ "surface": "both",
248
+ "noun": "kb_write",
249
+ "is_read_only": false,
250
+ "mutation_class": "kb",
251
+ "requires_approval": true,
252
+ "silent_retry_exempt": false
253
+ },
254
+ "kb update topic": {
255
+ "surface": "both",
256
+ "noun": "kb_write",
257
+ "is_read_only": false,
258
+ "mutation_class": "kb",
259
+ "requires_approval": true,
260
+ "silent_retry_exempt": false
261
+ },
262
+ "kb delete": {
263
+ "surface": "both",
264
+ "noun": "kb_write",
265
+ "is_read_only": false,
266
+ "mutation_class": "kb",
267
+ "requires_approval": true,
268
+ "silent_retry_exempt": false
269
+ },
270
+ "query": {
271
+ "surface": "both",
272
+ "is_read_only": true,
273
+ "mutation_class": "none",
274
+ "requires_approval": false,
275
+ "silent_retry_exempt": false
276
+ },
277
+ "metadata schemas": {
278
+ "surface": "both",
279
+ "is_read_only": true,
280
+ "mutation_class": "none",
281
+ "requires_approval": false,
282
+ "silent_retry_exempt": false
283
+ },
284
+ "metadata tables": {
285
+ "surface": "both",
286
+ "is_read_only": true,
287
+ "mutation_class": "none",
288
+ "requires_approval": false,
289
+ "silent_retry_exempt": false
290
+ },
291
+ "metadata columns": {
292
+ "surface": "both",
293
+ "is_read_only": true,
294
+ "mutation_class": "none",
295
+ "requires_approval": false,
296
+ "silent_retry_exempt": false
297
+ },
298
+ "ds list": {
299
+ "surface": "both",
300
+ "is_read_only": true,
301
+ "mutation_class": "none",
302
+ "requires_approval": false,
303
+ "silent_retry_exempt": false
304
+ },
305
+ "ds refresh-history": {
306
+ "surface": "both",
307
+ "is_read_only": true,
308
+ "mutation_class": "none",
309
+ "requires_approval": false,
310
+ "silent_retry_exempt": false
311
+ },
312
+ "ds create": {
313
+ "surface": "both",
314
+ "is_read_only": false,
315
+ "mutation_class": "data_source",
316
+ "requires_approval": true,
317
+ "silent_retry_exempt": false
318
+ },
319
+ "ds refresh": {
320
+ "surface": "both",
321
+ "is_read_only": false,
322
+ "mutation_class": "data_source",
323
+ "requires_approval": true,
324
+ "silent_retry_exempt": true
325
+ },
326
+ "ds verify": {
327
+ "surface": "both",
328
+ "is_read_only": false,
329
+ "mutation_class": "data_source",
330
+ "requires_approval": true,
331
+ "silent_retry_exempt": false
332
+ },
333
+ "ds update": {
334
+ "surface": "both",
335
+ "is_read_only": false,
336
+ "mutation_class": "data_source",
337
+ "requires_approval": true,
338
+ "silent_retry_exempt": false
339
+ },
340
+ "ds refresh-config": {
341
+ "surface": "both",
342
+ "is_read_only": false,
343
+ "mutation_class": "data_source",
344
+ "requires_approval": true,
345
+ "silent_retry_exempt": false
346
+ },
347
+ "ds delete": {
348
+ "surface": "cli_only",
349
+ "is_read_only": false,
350
+ "mutation_class": "data_source",
351
+ "requires_approval": true,
352
+ "silent_retry_exempt": true,
353
+ "reason": "Not a working verb on either surface. The CLI registers it only to name the boundary - deletion cascades into dashboards, KB tables and cached snapshots, so it runs from the Sources Hub where the blast radius is shown first. Generating it in-app would advertise a capability that always errors."
354
+ },
355
+ "ds move": {
356
+ "surface": "cli_only",
357
+ "is_read_only": false,
358
+ "mutation_class": "data_source",
359
+ "requires_approval": true,
360
+ "silent_retry_exempt": true,
361
+ "reason": "Same as `ds delete` - a Sources Hub action the CLI names but does not perform. A domain move re-homes every asset bound to the source, which is a decision the UI shows before it commits."
362
+ },
363
+ "dashboard list": {
364
+ "surface": "both",
365
+ "is_read_only": true,
366
+ "mutation_class": "none",
367
+ "requires_approval": false,
368
+ "silent_retry_exempt": false
369
+ },
370
+ "dashboard get": {
371
+ "surface": "both",
372
+ "is_read_only": true,
373
+ "mutation_class": "none",
374
+ "requires_approval": false,
375
+ "silent_retry_exempt": false
376
+ },
377
+ "dashboard get-html": {
378
+ "surface": "both",
379
+ "is_read_only": true,
380
+ "mutation_class": "none",
381
+ "requires_approval": false,
382
+ "silent_retry_exempt": false
383
+ },
384
+ "dashboard list-entities": {
385
+ "surface": "both",
386
+ "is_read_only": true,
387
+ "mutation_class": "none",
388
+ "requires_approval": false,
389
+ "silent_retry_exempt": false
390
+ },
391
+ "dashboard get-entity": {
392
+ "surface": "both",
393
+ "is_read_only": true,
394
+ "mutation_class": "none",
395
+ "requires_approval": false,
396
+ "silent_retry_exempt": false
397
+ },
398
+ "dashboard export": {
399
+ "surface": "cli_only",
400
+ "is_read_only": true,
401
+ "mutation_class": "none",
402
+ "requires_approval": false,
403
+ "silent_retry_exempt": false,
404
+ "reason": "The export IS the file. The route renders the dashboard and returns PNG/PDF bytes as an HTTP download, and an in-app turn has nowhere to put bytes: returning them would flood the context, and returning only metadata would claim a success whose single artifact was discarded - complete with a bell notification saying an export exists when none does. The app's own export UI is the in-app path, and it hands the file to the browser that asked for it."
405
+ },
406
+ "dashboard create": {
407
+ "surface": "both",
408
+ "is_read_only": false,
409
+ "mutation_class": "dashboard",
410
+ "requires_approval": true,
411
+ "silent_retry_exempt": false
412
+ },
413
+ "dashboard update-html": {
414
+ "surface": "both",
415
+ "is_read_only": false,
416
+ "mutation_class": "canvas",
417
+ "requires_approval": false,
418
+ "silent_retry_exempt": true,
419
+ "app_params": {
420
+ "content": {
421
+ "type": "string",
422
+ "required": true,
423
+ "description": "The complete HTML document to write to the canvas - <!DOCTYPE html> through </html>, with all CSS and JS inline (the iframe blocks external resources).",
424
+ "reason": "The CLI carries the page through the filesystem (--file/--stdin), which is the right ergonomic for a shell and impossible in an in-app turn: there is no local disk and no pipe, so the document has to ride the call. Named `content` and not `html` because `dashboard get --html` already claims that name as a boolean, and the noun's schema is flat."
425
+ }
426
+ }
427
+ },
428
+ "dashboard update-entity": {
429
+ "surface": "both",
430
+ "is_read_only": false,
431
+ "mutation_class": "canvas",
432
+ "requires_approval": false,
433
+ "silent_retry_exempt": true,
434
+ "app_params": {
435
+ "content": {
436
+ "type": "string",
437
+ "required": true,
438
+ "description": "The entity's INNER HTML only - do not include the outer element carrying data-graphit-id, which already exists (a duplicate id breaks later updates).",
439
+ "reason": "Same as update-html: --file/--stdin are filesystem sources an in-app turn does not have. The description differs because this fragment is the entity's inner content rather than a whole document, and sending a whole document here is the mistake the CLI's own --file examples prevent by construction."
440
+ }
441
+ }
442
+ },
443
+ "dashboard edit": {
444
+ "surface": "both",
445
+ "is_read_only": false,
446
+ "mutation_class": "dashboard",
447
+ "requires_approval": true,
448
+ "silent_retry_exempt": true
449
+ },
450
+ "dashboard publish": {
451
+ "surface": "both",
452
+ "is_read_only": false,
453
+ "mutation_class": "dashboard",
454
+ "requires_approval": true,
455
+ "silent_retry_exempt": true
456
+ },
457
+ "dashboard release": {
458
+ "surface": "both",
459
+ "is_read_only": false,
460
+ "mutation_class": "dashboard",
461
+ "requires_approval": true,
462
+ "silent_retry_exempt": true
463
+ },
464
+ "dashboard delete": {
465
+ "surface": "both",
466
+ "is_read_only": false,
467
+ "mutation_class": "dashboard",
468
+ "requires_approval": true,
469
+ "silent_retry_exempt": true
470
+ },
471
+ "connector list": {
472
+ "surface": "cli_only",
473
+ "is_read_only": true,
474
+ "mutation_class": "none",
475
+ "requires_approval": false,
476
+ "silent_retry_exempt": false,
477
+ "reason": "Excluded with the rest of its group. No in-app agent action takes a connection id - `ds` and `query` resolve the connection server-side - so the read has no consumer, and an eighth noun for one unused list costs tool-window budget the seven earn."
478
+ },
479
+ "connector add snowflake-keypair": {
480
+ "surface": "cli_only",
481
+ "is_read_only": false,
482
+ "mutation_class": "none",
483
+ "requires_approval": true,
484
+ "silent_retry_exempt": true,
485
+ "reason": "Connection lifecycle. Adding a connection means handling the org's shared warehouse credential; that is an org-admin action performed in the web app, never something an agent turn assembles from chat."
486
+ },
487
+ "connector add bigquery-serviceaccount": {
488
+ "surface": "cli_only",
489
+ "is_read_only": false,
490
+ "mutation_class": "none",
491
+ "requires_approval": true,
492
+ "silent_retry_exempt": true,
493
+ "reason": "Connection lifecycle, and it takes a service-account key file. The agent must never be a path a credential travels along."
494
+ },
495
+ "connector test": {
496
+ "surface": "cli_only",
497
+ "is_read_only": true,
498
+ "mutation_class": "none",
499
+ "requires_approval": false,
500
+ "silent_retry_exempt": false,
501
+ "reason": "Connection lifecycle: `/test` exercises the org's shared credential and is org-admin gated for that reason. It belongs with the rest of its group in the web app."
502
+ },
503
+ "connector remove": {
504
+ "surface": "cli_only",
505
+ "is_read_only": false,
506
+ "mutation_class": "none",
507
+ "requires_approval": true,
508
+ "silent_retry_exempt": true,
509
+ "reason": "Connection lifecycle. Removing a connection breaks every data source built on it, org-wide."
510
+ },
511
+ "governance status": {
512
+ "surface": "both",
513
+ "is_read_only": true,
514
+ "mutation_class": "none",
515
+ "requires_approval": false,
516
+ "silent_retry_exempt": false
517
+ },
518
+ "governance audit": {
519
+ "surface": "both",
520
+ "is_read_only": true,
521
+ "mutation_class": "none",
522
+ "requires_approval": false,
523
+ "silent_retry_exempt": false
524
+ },
525
+ "team list": {
526
+ "surface": "cli_only",
527
+ "is_read_only": true,
528
+ "mutation_class": "none",
529
+ "requires_approval": false,
530
+ "silent_retry_exempt": false,
531
+ "reason": "Org-directory context, not analytics capability. Nothing in the in-app verb surface consumes a team id: dashboard sharing is done in the app's own UI, and `dashboard list --team` already covers the one analytics question teams answer. A noun for a single unconsumed read would spend tool-window budget for no capability."
532
+ },
533
+ "plugin status": {
534
+ "surface": "cli_only",
535
+ "is_read_only": true,
536
+ "mutation_class": "none",
537
+ "requires_approval": false,
538
+ "silent_retry_exempt": false,
539
+ "reason": "Reports the health of the plugin, npm package and skill files installed on the caller's machine. In-app there is no installation - the brain is composed from the image - so every field it returns is meaningless."
540
+ },
541
+ "setup": {
542
+ "surface": "cli_only",
543
+ "is_read_only": false,
544
+ "mutation_class": "none",
545
+ "requires_approval": true,
546
+ "silent_retry_exempt": true,
547
+ "reason": "Writes assistant files into the caller's filesystem for legacy editors. There is no filesystem to install into on the app surface."
548
+ }
549
+ },
550
+ "identity_param_exemptions": {
551
+ "governance audit": {
552
+ "user": "Not caller identity. The audit log is already scoped to the caller's own org and authorized before it is read; --user narrows the rows returned within that scope, so it can never widen who the call runs as. Reviewed 2026-08-10."
553
+ }
554
+ }
555
+ }
@@ -2,7 +2,7 @@
2
2
  name: graphit
3
3
  description: >-
4
4
  Use Graphit for ANY question about the user's business or product data: metrics, KPIs, revenue, retention, spend, users, cohorts, funnels, trends, comparisons, "why did X change", "how are we doing on Y", analysis, reports, or dashboards. Activate even when the user does not say "Graphit" or name any tool: if someone wants to understand their numbers, this is the tool. Graphit answers through a governed semantic layer (computed the team's way, reusable and safe to share) and delivers the answer as a fast cached-data query or a hand-authored interactive HTML dashboard, and can create the metrics, dimensions, and rules an answer needs. Prefer Graphit over hand-rolled one-off analysis whenever the data is, or could be, the user's business data. Skip only for pure software tasks (code, logs, config, infra) or data with nothing to do with the user's business.
5
- skill_version: "0.2.270"
5
+ skill_version: "0.2.307"
6
6
  ---
7
7
 
8
8
  <!-- SIZE EXEMPTION (SKILL.md): standard hard limit 12,288 chars, exempted ceiling 30,592. Always-loaded: the collaboration/pace spine, hard constraints + scope gate, the loop, and the generated command table (COMMANDS markers, scripts/generate-commands-doc.mjs) - needed every turn, cannot defer to a reference. Marker sits after the frontmatter so the loader and sync-plugin-version.mjs parse it. Reviewed 2026-08-02. Raised from 29,952 on 2026-08-07 (founder-directed): a domain is now an access boundary, so loop step 2 must say that picking one decides who ever sees the work - load-bearing before any reference load can be relied on. SIZING.md rules raises pay only for command-table growth; deliberate exception. -->
@@ -155,7 +155,7 @@ Read the one that matches what you are doing now. Do not preload them. Exact com
155
155
 
156
156
  ## Commands
157
157
 
158
- Graphit is one CLI, but how you invoke it depends on your environment. On Claude Code the plugin provides a `graphit` wrapper, so `graphit <command>` runs the current CLI. On Codex, Cursor, a terminal, or CI there is no `graphit` wrapper - invoke the CLI explicitly with `npx -y @graphit/cli@0.2.270 <command>` (a stamped version, kept current by the build; pin an exact version for a reproducible run). The table below is generated from the CLI itself. For exact flags, run `graphit <command> --help` - never guess a flag.
158
+ Graphit is one CLI, but how you invoke it depends on your environment. On Claude Code the plugin provides a `graphit` wrapper, so `graphit <command>` runs the current CLI. On Codex, Cursor, a terminal, or CI there is no `graphit` wrapper - invoke the CLI explicitly with `npx -y @graphit/cli@0.2.307 <command>` (a stamped version, kept current by the build; pin an exact version for a reproducible run). The table below is generated from the CLI itself. For exact flags, run `graphit <command> --help` - never guess a flag.
159
159
 
160
160
  <!-- COMMANDS:START -->
161
161
 
@@ -1,5 +1,5 @@
1
1
  {
2
2
  "package": "@graphit/cli",
3
- "version": "0.2.270",
3
+ "version": "0.2.307",
4
4
  "source": "cli/package.json"
5
5
  }
@@ -42,6 +42,14 @@ graphit kb list domains
42
42
  graphit kb create domain --name MARKETING --description "Acquisition and spend"
43
43
  ```
44
44
 
45
+ **Read the table before you write its SQL.** You cannot author a source SELECT without knowing the columns, and guessing them wastes a round trip. Read them straight off the warehouse:
46
+
47
+ ```bash
48
+ graphit metadata columns --connection <id> --schema <name> --table <name>
49
+ ```
50
+
51
+ This needs no governed reference. An aggregate or `GROUP BY` against a warehouse table that is not yet in the knowledge base is a different matter, so use it for shape rather than probing with a query.
52
+
45
53
  Then create the source and activate it:
46
54
 
47
55
  ```bash