@jskit-ai/agent-docs 0.1.1

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 (73) hide show
  1. package/DISTR_AGENT.md +25 -0
  2. package/guide/agent/app-extras/assistant.md +636 -0
  3. package/guide/agent/app-extras/realtime.md +223 -0
  4. package/guide/agent/app-setup/a-more-interesting-shell.md +643 -0
  5. package/guide/agent/app-setup/authentication.md +948 -0
  6. package/guide/agent/app-setup/console.md +316 -0
  7. package/guide/agent/app-setup/database-layer.md +775 -0
  8. package/guide/agent/app-setup/initial-scaffolding.md +714 -0
  9. package/guide/agent/app-setup/multi-homing.md +655 -0
  10. package/guide/agent/app-setup/users.md +355 -0
  11. package/guide/agent/app-setup/working-with-the-jskit-cli.md +983 -0
  12. package/guide/agent/generators/advanced-cruds.md +923 -0
  13. package/guide/agent/generators/crud-generators.md +556 -0
  14. package/guide/agent/generators/intro.md +63 -0
  15. package/guide/agent/generators/ui-generators.md +648 -0
  16. package/guide/agent/index.md +39 -0
  17. package/guide/human/app-extras/assistant.md +695 -0
  18. package/guide/human/app-extras/realtime.md +270 -0
  19. package/guide/human/app-setup/a-more-interesting-shell.md +734 -0
  20. package/guide/human/app-setup/authentication.md +963 -0
  21. package/guide/human/app-setup/console.md +352 -0
  22. package/guide/human/app-setup/database-layer.md +822 -0
  23. package/guide/human/app-setup/initial-scaffolding.md +738 -0
  24. package/guide/human/app-setup/multi-homing.md +795 -0
  25. package/guide/human/app-setup/users.md +404 -0
  26. package/guide/human/app-setup/working-with-the-jskit-cli.md +997 -0
  27. package/guide/human/generators/advanced-cruds.md +923 -0
  28. package/guide/human/generators/crud-generators.md +556 -0
  29. package/guide/human/generators/intro.md +109 -0
  30. package/guide/human/generators/ui-generators.md +665 -0
  31. package/guide/human/index.md +39 -0
  32. package/package.json +28 -0
  33. package/reference/autogen/KERNEL_MAP.md +536 -0
  34. package/reference/autogen/README.md +44 -0
  35. package/reference/autogen/packages/agent-docs.md +13 -0
  36. package/reference/autogen/packages/assistant-core.md +310 -0
  37. package/reference/autogen/packages/assistant-runtime.md +219 -0
  38. package/reference/autogen/packages/assistant.md +73 -0
  39. package/reference/autogen/packages/auth-core.md +352 -0
  40. package/reference/autogen/packages/auth-provider-supabase-core.md +223 -0
  41. package/reference/autogen/packages/auth-web.md +267 -0
  42. package/reference/autogen/packages/console-core.md +116 -0
  43. package/reference/autogen/packages/console-web.md +37 -0
  44. package/reference/autogen/packages/crud-core.md +283 -0
  45. package/reference/autogen/packages/crud-server-generator.md +220 -0
  46. package/reference/autogen/packages/crud-ui-generator.md +154 -0
  47. package/reference/autogen/packages/database-runtime-mysql.md +61 -0
  48. package/reference/autogen/packages/database-runtime-postgres.md +39 -0
  49. package/reference/autogen/packages/database-runtime.md +216 -0
  50. package/reference/autogen/packages/http-runtime.md +213 -0
  51. package/reference/autogen/packages/kernel.md +1350 -0
  52. package/reference/autogen/packages/realtime.md +95 -0
  53. package/reference/autogen/packages/shell-web.md +349 -0
  54. package/reference/autogen/packages/storage-runtime.md +39 -0
  55. package/reference/autogen/packages/ui-generator.md +101 -0
  56. package/reference/autogen/packages/uploads-image-web.md +76 -0
  57. package/reference/autogen/packages/uploads-runtime.md +85 -0
  58. package/reference/autogen/packages/users-core.md +307 -0
  59. package/reference/autogen/packages/users-web.md +473 -0
  60. package/reference/autogen/packages/workspaces-core.md +415 -0
  61. package/reference/autogen/packages/workspaces-web.md +372 -0
  62. package/reference/autogen/tooling/config-eslint.md +52 -0
  63. package/reference/autogen/tooling/create-app.md +194 -0
  64. package/reference/autogen/tooling/jskit-catalog.md +27 -0
  65. package/reference/autogen/tooling/jskit-cli.md +624 -0
  66. package/reference/autogen/tooling/test-support.md +27 -0
  67. package/reference/autogen/tooling/testUtils.md +31 -0
  68. package/templates/APP_BLUEPRINT.md +57 -0
  69. package/workflow/app-state.md +33 -0
  70. package/workflow/bootstrap.md +24 -0
  71. package/workflow/feature-delivery.md +21 -0
  72. package/workflow/review.md +22 -0
  73. package/workflow/scoping.md +26 -0
@@ -0,0 +1,983 @@
1
+ <!-- Generated by `npm run agent-docs:build` from `docs/guide/app-setup/working-with-the-jskit-cli.md`. Do not edit manually. -->
2
+
3
+ # Working with the JSKIT CLI
4
+
5
+ In the first chapter, we used the JSKIT CLI, but only in passing. We created the app, installed dependencies, and moved on.
6
+
7
+ This chapter steps back and treats the CLI as a subject in its own right.
8
+
9
+ That matters because `jskit` is not just "the thing that installs packages". It is the tool that helps you:
10
+
11
+ - discover what JSKIT can do
12
+ - inspect bundles, packages, and generators before using them
13
+ - apply and re-apply JSKIT-managed mutations to your app
14
+ - keep managed files and lock state healthy
15
+ - create your own app-local runtime packages
16
+
17
+ If you understand this chapter early, the rest of the guide becomes much easier to follow.
18
+
19
+ ## What the CLI is actually managing
20
+
21
+ The easiest way to understand `jskit` is to separate it from the other tools in the app.
22
+
23
+ - `jskit` manages JSKIT-owned app mutations
24
+ - `npm install` downloads dependencies from `package.json`
25
+ - `npm run dev` and `npm run build` run Vite
26
+ - `npm run server` runs the backend
27
+ - `npm run db:migrate` runs Knex migrations against the database
28
+
29
+ That separation is crucial.
30
+
31
+ When you run a command such as `npx jskit add package shell-web`, JSKIT updates app-owned files and records what it changed. It does **not** replace npm, Vite, or Knex.
32
+
33
+ The most important record of that managed state lives here:
34
+
35
+ ```text
36
+ .jskit/lock.json
37
+ ```
38
+
39
+ That lock file is the source of truth for installed JSKIT-managed package state. It records things like:
40
+
41
+ - which JSKIT packages are installed
42
+ - which options were used when they were installed
43
+ - which package.json fields were added or changed
44
+ - which managed files or text mutations belong to each package
45
+
46
+ That is why commands such as `update`, `remove`, `position`, `migrations`, and `doctor` all care about `.jskit/lock.json`.
47
+
48
+ ## Discover first, change second
49
+
50
+ One of the best habits in JSKIT is to inspect the catalog before mutating the app.
51
+
52
+ ### Start with `help`
53
+
54
+ The top-level overview is:
55
+
56
+ ```bash
57
+ npx jskit help
58
+ ```
59
+
60
+ That shows the available commands such as:
61
+
62
+ - `list`
63
+ - `show`
64
+ - `add`
65
+ - `update`
66
+ - `remove`
67
+ - `position`
68
+ - `migrations`
69
+ - `create`
70
+ - `doctor`
71
+
72
+ Every command in the CLI also has its own help page. For example:
73
+
74
+ ```bash
75
+ npx jskit help add
76
+ npx jskit help migrations
77
+ ```
78
+
79
+ That is the fastest way to check current usage without leaving the terminal.
80
+
81
+ ### Use `list` for discovery
82
+
83
+ The broad catalog view is:
84
+
85
+ ```bash
86
+ npx jskit list
87
+ ```
88
+
89
+ By default, this prints three groups:
90
+
91
+ - bundles
92
+ - runtime packages
93
+ - generators
94
+
95
+ That distinction matters.
96
+
97
+ #### Bundles
98
+
99
+ A bundle is a curated install shortcut for several runtime packages that are meant to go together.
100
+
101
+ In the current catalog, `auth-base` is the obvious example. It is a single bundle id, but it expands to several real runtime packages.
102
+
103
+ #### Runtime packages
104
+
105
+ These are the actual packages that change how the app runs. Packages such as `shell-web`, `auth-web`, `users-web`, and `workspaces-web` belong here.
106
+
107
+ These are the things you install with:
108
+
109
+ ```bash
110
+ npx jskit add package ...
111
+ ```
112
+
113
+ #### Generators
114
+
115
+ Generators are tooling packages such as `ui-generator`, `crud-server-generator`, and `crud-ui-generator`.
116
+
117
+ They are **not** runtime installs.
118
+
119
+ You do **not** add them with `jskit add`. You run them with:
120
+
121
+ ```bash
122
+ npx jskit generate ...
123
+ ```
124
+
125
+ That distinction is easy to miss at first, and it is one of the main reasons this chapter exists.
126
+
127
+ If you only want one section of the catalog, use a mode:
128
+
129
+ ```bash
130
+ npx jskit list packages
131
+ npx jskit list generators
132
+ ```
133
+
134
+ Those two commands are especially useful later in the guide, once you already know roughly what kind of thing you are looking for.
135
+
136
+ If you want bundle members printed inline too, `npx jskit list --full` expands the bundle view. That is useful when you want a quick catalog scan without dropping straight into `show`.
137
+
138
+ One more detail is worth noticing. In repos that contain local package descriptors, `list packages` can also show app-local or repo-local packages in addition to the published catalog. So `list` is not only a remote catalog browser. It is also a view of what this app can currently see.
139
+
140
+ ### Use `show` before you install
141
+
142
+ Once `list` helps you find the right id, `show` is how you inspect it.
143
+
144
+ The basic form is:
145
+
146
+ ```bash
147
+ npx jskit show <id>
148
+ ```
149
+
150
+ And the more useful inspection form is:
151
+
152
+ ```bash
153
+ npx jskit show <id> --details
154
+ ```
155
+
156
+ This command is unusually valuable in JSKIT because packages and bundles do more than "add a dependency". They can:
157
+
158
+ - provide or require capabilities
159
+ - register runtime providers
160
+ - contribute placement entries
161
+ - write files into the app
162
+ - mutate `package.json`, scripts, and text blocks
163
+
164
+ So `show` is the command that answers:
165
+
166
+ - what does this thing actually install?
167
+ - what does it depend on?
168
+ - what runtime surfaces does it contribute?
169
+ - what app-owned files will it write or mutate?
170
+ - what container tokens or import surfaces does it expose?
171
+
172
+ The plain form is useful when you only want to identify something quickly. `--details` is what turns `show` into a real architecture-inspection command.
173
+
174
+ ### What `show` is good at
175
+
176
+ There are two especially common cases:
177
+
178
+ - you found a bundle or package in `jskit list` and want to know what it really does before you install it
179
+ - you already know a package changed the shell, the runtime graph, or the app tree, and you want to see *how*
180
+
181
+ That second case matters just as much as the first one. Later in the guide, chapters explain package behavior one feature at a time. `show --details` is the generic command that lets you inspect those same package contracts directly.
182
+
183
+ ### A first example: what does `auth-base` actually install?
184
+
185
+ Run:
186
+
187
+ ```bash
188
+ npx jskit show auth-base --details
189
+ ```
190
+
191
+ This output is short, but it already teaches something important:
192
+
193
+ - `auth-base` is a **bundle**
194
+ - it is not a runtime package by itself
195
+
196
+ It expands to two real runtime packages:
197
+
198
+ - `@jskit-ai/auth-core`
199
+ - `@jskit-ai/auth-web`
200
+
201
+ That is exactly the kind of thing you want to know before you mutate the app. For a bundle, this is often the main question:
202
+
203
+ - *what real packages am I about to get?*
204
+
205
+ `auth-base` is a good example because the bundle name is short and convenient, but the detailed view makes the underlying install explicit. It also helps you keep the mental model straight:
206
+
207
+ - bundles are install shortcuts
208
+ - runtime packages are the things that actually provide capabilities
209
+
210
+ ### A richer example: what does `workspaces-web` contribute?
211
+
212
+ Run:
213
+
214
+ ```bash
215
+ npx jskit show @jskit-ai/workspaces-web --details
216
+ ```
217
+
218
+ This is where `--details` becomes much more powerful.
219
+
220
+ The compact form of `show` is fine when you only want the package description. The detailed form can show things like:
221
+
222
+ - provided and required capabilities
223
+ - summary import surfaces / exported subpaths
224
+ - container tokens
225
+ - placement outlets
226
+ - default placement contributions
227
+ - dependency mutations
228
+ - script mutations
229
+ - text mutations
230
+ - file writes
231
+ - runtime providers
232
+
233
+ That makes `show --details` one of the best "read before you write" commands in the whole CLI.
234
+
235
+ ### Why `--details` matters
236
+
237
+ The plain form:
238
+
239
+ ```bash
240
+ npx jskit show @jskit-ai/workspaces-web
241
+ ```
242
+
243
+ is mainly for identifying the package at a glance.
244
+
245
+ The detailed form:
246
+
247
+ ```bash
248
+ npx jskit show @jskit-ai/workspaces-web --details
249
+ ```
250
+
251
+ is for understanding the package as part of the app architecture. It lets you answer concrete questions from one command instead of hunting across descriptors and generated files.
252
+
253
+ That is the version you should prefer when you are making a real install decision.
254
+
255
+ ### What `show --details` teaches you
256
+
257
+ The output is not one giant wall of metadata. It is answering several practical questions. You do not need to read every line. Read the sections that answer the question you currently have.
258
+
259
+ #### "What capabilities does this package participate in?"
260
+
261
+ The `Capabilities` section tells you:
262
+
263
+ - what the package provides
264
+ - what it requires from other packages
265
+
266
+ That helps you reason about dependency direction and why some packages bring others with them.
267
+
268
+ For `@jskit-ai/workspaces-web`, the detailed output shows:
269
+
270
+ - it **provides** `workspaces.web`
271
+ - it **requires** `users.web` and `workspaces.core`
272
+
273
+ That immediately tells you this package is not just some loose UI helper. It is the web layer of the workspace feature set, and it expects the users and workspace core layers underneath it.
274
+
275
+ #### "What UI does this package contribute?"
276
+
277
+ The placement sections are often the most useful part of `show --details`.
278
+
279
+ For `@jskit-ai/workspaces-web`, the detailed output shows placement contributions such as:
280
+
281
+ - the workspace selector in `shell-layout:top-left`
282
+ - the pending invites cue in `shell-layout:top-right`
283
+ - the workspace tools widget on the `admin` surface
284
+ - the `Members` and workspace settings menu entries
285
+
286
+ That lets you answer a very concrete question before installing anything:
287
+
288
+ - *what will change in the shell if I add this package?*
289
+
290
+ It also shows placement outlets, such as:
291
+
292
+ - `admin-settings:primary-menu`
293
+
294
+ which helps you understand where later app-owned pages or settings links can attach.
295
+
296
+ #### "What import paths, tokens, or providers does it register?"
297
+
298
+ The detailed output can also show:
299
+
300
+ - summary import surfaces / exported subpaths
301
+ - container tokens
302
+ - runtime providers
303
+
304
+ For `@jskit-ai/workspaces-web`, that includes client tokens such as:
305
+
306
+ - `workspaces.web.workspace.selector`
307
+ - `workspaces.web.workspace.tools.widget`
308
+ - `workspaces.web.members-admin.element`
309
+
310
+ It also shows a short `Summary` section with the main client import surfaces, such as:
311
+
312
+ - `@jskit-ai/workspaces-web/client`
313
+ - `@jskit-ai/workspaces-web/client/providers/WorkspacesWebClientProvider`
314
+ - `@jskit-ai/workspaces-web/client/composables/useWorkspaceRouteContext`
315
+
316
+ That gives you a quick view of the package's client integration surface without reading the source first.
317
+
318
+ This is especially useful when you are asking questions like:
319
+
320
+ - *does this package expose a client entrypoint I can import from?*
321
+ - *does it register a provider, or am I expected to wire components myself?*
322
+ - *what token name should I expect to see in placements or providers?*
323
+
324
+ #### "What app-owned files will it touch?"
325
+
326
+ The `File writes`, `Text mutations`, and `Script mutations` sections answer one of the most practical questions in JSKIT:
327
+
328
+ - *what will this package actually do to my app tree?*
329
+
330
+ For `@jskit-ai/workspaces-web`, the detailed view shows app-owned files such as:
331
+
332
+ - workspace surface route scaffolds
333
+ - workspace settings pages
334
+ - `WorkspaceNotFoundCard.vue`
335
+ - `useWorkspaceNotFoundState.js`
336
+
337
+ It also shows text mutations such as:
338
+
339
+ - appending placement entries to `src/placement.js`
340
+ - registering tokens in `packages/main/src/client/providers/MainClientProvider.js`
341
+
342
+ That matters because JSKIT packages are not only libraries. Many of them also write scaffold files into the app and extend app-owned provider files.
343
+
344
+ ### The kinds of questions this answers well
345
+
346
+ Once you get used to it, `show --details` is the fast answer to questions like:
347
+
348
+ - *what does this bundle really install?*
349
+ - *why did this package add a new shell widget?*
350
+ - *which capabilities does this package provide and require?*
351
+ - *which app-owned files will JSKIT write if I install this?*
352
+ - *where do later pages or placements plug into this package?*
353
+ - *what container tokens or client entrypoints does this package expose?*
354
+
355
+ ### How to read the output at a high level
356
+
357
+ Not every package shows every section, and that is normal. A good reading order is:
358
+
359
+ 1. `Information`
360
+ - what is this thing?
361
+ 2. `Summary`
362
+ - what are the main import paths or public entrypoints?
363
+ 3. `Depends on`
364
+ - what else does it need?
365
+ 4. `Capabilities`
366
+ - what role does it play in the runtime graph?
367
+ 5. `Placement contributions` / `Placement outlets`
368
+ - what UI surfaces does it add?
369
+ 6. `File writes` and `Text mutations`
370
+ - what app-owned files will change?
371
+ 7. `Runtime providers` and `Container tokens`
372
+ - what does it register internally?
373
+
374
+ That is enough to make `show --details` useful without treating it like a formal spec.
375
+
376
+ ### A simple rule of thumb
377
+
378
+ Use:
379
+
380
+ ```bash
381
+ npx jskit show <id>
382
+ ```
383
+
384
+ when you only want to identify a package or bundle quickly.
385
+
386
+ Use:
387
+
388
+ ```bash
389
+ npx jskit show <id> --details
390
+ ```
391
+
392
+ when you are seriously considering installing it, or when you need to understand why a package changed the shell, the config, or the runtime in a particular way.
393
+
394
+ ## Make the terminal nicer: `completion`
395
+
396
+ The CLI also ships with Bash completion:
397
+
398
+ ```bash
399
+ npx jskit completion bash
400
+ ```
401
+
402
+ That prints the completion script to stdout.
403
+
404
+ If you only want completion for the current shell session, run:
405
+
406
+ ```bash
407
+ source <(npx jskit completion bash)
408
+ ```
409
+
410
+ If you want JSKIT completion to keep working in future Bash sessions too, run:
411
+
412
+ ```bash
413
+ npx jskit completion bash --install
414
+ ```
415
+
416
+ This is not required, but it is genuinely useful once you start using commands such as `add`, `generate`, and `show` frequently.
417
+
418
+ ## Installing runtime capability: `add`
419
+
420
+ The install command comes in two main forms:
421
+
422
+ ```bash
423
+ npx jskit add package shell-web
424
+ npx jskit add bundle auth-base
425
+ ```
426
+
427
+ Those two examples look similar, but they do different things.
428
+
429
+ ### `add package`
430
+
431
+ Use this when you know the exact runtime package you want:
432
+
433
+ ```bash
434
+ npx jskit add package shell-web
435
+ ```
436
+
437
+ This is the command the next chapter uses.
438
+
439
+ Important defaults:
440
+
441
+ - short ids such as `shell-web` resolve to `@jskit-ai/shell-web` when available
442
+ - JSKIT records the install in `.jskit/lock.json`
443
+ - JSKIT rewrites app-owned managed files as needed
444
+ - npm install does **not** run unless you ask for it with `--run-npm-install`
445
+
446
+ That last point is why the normal guide flow is still:
447
+
448
+ ```bash
449
+ npx jskit add package shell-web
450
+ npm install
451
+ ```
452
+
453
+ `jskit add` changes the app. `npm install` downloads the dependencies that the changed app now requires.
454
+
455
+ ### `add bundle`
456
+
457
+ Use this when the catalog already offers a sensible grouped install:
458
+
459
+ ```bash
460
+ npx jskit add bundle auth-base
461
+ ```
462
+
463
+ Bundles are a convenience layer. They save you from having to remember and install several related runtime packages one by one.
464
+
465
+ This is why `show auth-base --details` is useful first: it lets you see what the bundle will actually install.
466
+
467
+ ### Generator packages are different
468
+
469
+ This is worth saying one more time because it causes confusion early on.
470
+
471
+ If `npx jskit list generators` shows a package such as `crud-ui-generator`, that does **not** mean you should run:
472
+
473
+ ```bash
474
+ npx jskit add package crud-ui-generator
475
+ ```
476
+
477
+ Generators are tooling packages. You use them through `jskit generate`, not `jskit add`.
478
+
479
+ ## Managed-file lifecycle: `update`, `remove`, and `position`
480
+
481
+ Once a package is installed, JSKIT treats it as managed app state, not just as "one more dependency".
482
+
483
+ That state lives in `.jskit/lock.json`, which is why lifecycle commands all start from the lock record for the installed package. In practice, that means JSKIT remembers:
484
+
485
+ - which package is installed
486
+ - which install options were used
487
+ - which files, text mutations, dependency entries, and migrations it owns
488
+
489
+ The easiest way to think about the lifecycle is:
490
+
491
+ 1. `jskit add package ...` creates managed state
492
+ 2. `jskit update package ...` reapplies that managed state
493
+ 3. `jskit position element ...` reapplies just the positioning layer
494
+ 4. `jskit remove package ...` removes the managed state
495
+
496
+ That is a better mental model than thinking of these as three unrelated commands.
497
+
498
+ ### `update` re-applies one installed package
499
+
500
+ The basic shape is:
501
+
502
+ ```bash
503
+ npx jskit update package workspaces-web
504
+ ```
505
+
506
+ This does **not** mean "fetch the newest npm version" in the way people often expect from other ecosystems.
507
+
508
+ In JSKIT, `update package ...` means:
509
+
510
+ - find the installed package in `.jskit/lock.json`
511
+ - reuse the saved lock options unless you override them inline
512
+ - run the normal package-application flow again with forced reapply
513
+
514
+ So `update` is for reapplying package-owned managed changes, not for generic dependency upgrades.
515
+
516
+ The best guide example is the tenancy-mode recovery path from the multi-homing chapter. If you installed `workspaces-core` or `workspaces-web` while the app was still on `tenancyMode = "none"`, then later changed the app to `personal`, the missing gated scaffold does not backfill automatically. The recovery path is:
517
+
518
+ ```bash
519
+ npx jskit update package workspaces-core
520
+ npx jskit update package workspaces-web
521
+ ```
522
+
523
+ That works because `update` reuses the saved install record and re-applies the package after the surrounding app state has changed.
524
+
525
+ This is the main kind of problem `update` solves:
526
+
527
+ - a package was installed correctly for the app state at the time
528
+ - the app state changed later
529
+ - the package's managed mutations need to be applied again
530
+
531
+ ### `position` re-applies only the placement/positioning layer
532
+
533
+ The positioning command is:
534
+
535
+ ```bash
536
+ npx jskit position element workspaces-web
537
+ ```
538
+
539
+ This is the focused version of reapply.
540
+
541
+ It reads the installed package from the lock file and reapplies only positioning mutations. That makes it especially useful for placement-heavy packages such as `shell-web` or `workspaces-web`, where a package contributes:
542
+
543
+ - shell placements
544
+ - menu entries
545
+ - outlet-targeted UI elements
546
+ - ordering-sensitive positioned elements
547
+
548
+ Use `position` when:
549
+
550
+ - the package itself is still installed
551
+ - you only need the placement layer refreshed
552
+ - you do **not** want a full package reapply
553
+
554
+ A realistic example is a workspace-heavy shell where the placement registry or surrounding shell files were edited, merged, or recovered and you want JSKIT to re-apply the `workspaces-web` positioned contributions without rerunning the whole install flow:
555
+
556
+ ```bash
557
+ npx jskit position element workspaces-web
558
+ ```
559
+
560
+ That is why the target word is `element` rather than `package`. This command is about positioned UI contributions, not general package installation.
561
+
562
+ It also does **not** run npm install. This is a focused managed-file repair command, not a dependency-install step.
563
+
564
+ ### `remove` removes managed state for one installed package
565
+
566
+ The removal form is:
567
+
568
+ ```bash
569
+ npx jskit remove package workspaces-web
570
+ ```
571
+
572
+ This is the inverse side of the lifecycle.
573
+
574
+ `remove` uses the lock record to tear out the managed state that package owns. In practice, that means it:
575
+
576
+ - removes the package's lock entry
577
+ - restores or removes the `package.json` fields JSKIT originally managed
578
+ - removes managed files only when they still match the version JSKIT owns
579
+
580
+ That last part is important. JSKIT is trying to remove package-owned managed state without blindly deleting user-owned edits.
581
+
582
+ Two practical things to remember:
583
+
584
+ - `remove` can refuse to run if other installed packages depend on the target package
585
+ - it does **not** automatically delete app-owned local package directories such as `packages/contacts/`
586
+
587
+ So if you created a local package yourself, `remove` cleans up the JSKIT-managed install state, but it does not assume it should delete the directory you own.
588
+
589
+ ### The practical rule of thumb
590
+
591
+ If a package is already installed and you are deciding which command to use, think like this:
592
+
593
+ - use `update` when the package's full managed install state needs to be applied again
594
+ - use `position` when only its placement/positioning contributions need to be refreshed
595
+ - use `remove` when you want JSKIT to cleanly remove the managed package state from the app
596
+
597
+ All three commands make more sense once you see them as one lifecycle around `.jskit/lock.json`, not as isolated CLI tricks.
598
+
599
+ ### `doctor` checks managed-state health
600
+
601
+ The health check is:
602
+
603
+ ```bash
604
+ npx jskit doctor
605
+ ```
606
+
607
+ This is JSKIT's normal app-health check for JSKIT-managed state.
608
+
609
+ It is not a linter, and it is not a test runner. It validates the things that only JSKIT itself can really verify.
610
+
611
+ In the current CLI, that includes checks such as:
612
+
613
+ - installed package entries in `.jskit/lock.json`
614
+ - whether managed files recorded in the lock still exist
615
+ - whether installed packages are still visible in the package registry
616
+ - certain JSKIT-specific app checks, such as invalid raw `mdi-*` icon literals in Vue templates when the app uses Vuetify's `mdi-svg` iconset
617
+
618
+ That last check is narrower than it sounds. `doctor` is looking for the broken case in direct Vue templates, such as:
619
+
620
+ ```vue
621
+ <v-icon icon="mdi-paw" />
622
+ ```
623
+
624
+ It does not flag the normal menu-metadata case in `src/placement.js`, where a shell menu link may still use:
625
+
626
+ ```js
627
+ icon: "mdi-cog-outline"
628
+ ```
629
+
630
+ because the shell runtime normalizes that metadata before Vuetify renders it. So if you see a `doctor` icon warning, the fix is usually "switch this Vue component to `@mdi/js`", not "remove every `mdi-*` string from the app."
631
+
632
+ In other words, `doctor` helps catch drift between:
633
+
634
+ - what JSKIT thinks it owns
635
+ - what is actually present on disk
636
+
637
+ That is a different job from:
638
+
639
+ - `npm run lint`, which checks source style and static code rules
640
+ - `npm run test`, which checks behavior
641
+ - `npm run build`, which checks whether the app can compile successfully
642
+
643
+ Those commands can all pass while JSKIT-managed state is still inconsistent. `doctor` is the command that checks that JSKIT's own view of the app still makes sense.
644
+
645
+ That is exactly why the starter scaffold already includes `npx jskit doctor` in `npm run verify`.
646
+
647
+ It belongs there because JSKIT apps are not only source trees. They also have:
648
+
649
+ - descriptor-driven runtime installs
650
+ - lock-file state under `.jskit/lock.json`
651
+ - JSKIT-managed files and mutations written into the app
652
+
653
+ `doctor` is the quick confirmation that those pieces still line up after all the normal quality checks pass.
654
+
655
+ This command belongs in your normal quality gate, not only in emergency debugging.
656
+
657
+ ### When to run it manually
658
+
659
+ The most common manual use is simply:
660
+
661
+ ```bash
662
+ npx jskit doctor
663
+ ```
664
+
665
+ after you have done something that changes JSKIT-managed state.
666
+
667
+ Good times to run it manually include:
668
+
669
+ - after `jskit add`, `update`, `remove`, `create package`, or generator commands
670
+ - after rebasing or resolving conflicts that touched `.jskit/lock.json`, `package.json`, or app-owned managed files
671
+ - after deleting, moving, or renaming files that may have been created by JSKIT
672
+ - when a package appears installed in the lock but starts behaving as if it is missing
673
+ - when you want a fast JSKIT-specific health check without waiting for a full test suite
674
+
675
+ One important nuance: `doctor` is checking for broken JSKIT ownership and visibility, not trying to stop you from editing app-owned files. For example, a managed file that still exists but whose contents changed is normally fine. The problem is when JSKIT expects a managed file to exist and it is gone, or when the installed package state no longer resolves cleanly.
676
+
677
+ ### Why `--json` exists
678
+
679
+ If you want machine-readable output, use:
680
+
681
+ ```bash
682
+ npx jskit doctor --json
683
+ ```
684
+
685
+ That prints a payload with:
686
+
687
+ - `appRoot`
688
+ - `lockVersion`
689
+ - `installedPackages`
690
+ - `issues`
691
+
692
+ This is useful in CI, editor tooling, or custom scripts where you want to parse the result instead of reading plain text. The exit code still does the simple job, but `--json` gives you the exact issue list in a form that other tools can consume.
693
+
694
+ ## Migrations: writing files is not the same as running the database
695
+
696
+ This distinction is one of the most important things to understand in JSKIT.
697
+
698
+ The explicit migration-materialization command is:
699
+
700
+ ```bash
701
+ npx jskit migrations changed
702
+ ```
703
+
704
+ This command does **not** run Knex against the database.
705
+
706
+ What it does is:
707
+
708
+ - look at installed packages in `.jskit/lock.json`
709
+ - decide which installed packages have managed migrations that need to be materialized
710
+ - write those migration files into your app
711
+
712
+ So this command is about **managed migration files on disk**.
713
+
714
+ In many normal `jskit add` flows, those migration files are already written as part of package application. `jskit migrations changed` is the explicit re-sync command when you want JSKIT to materialize the migration files again based on the current installed package state.
715
+
716
+ The database execution step is still:
717
+
718
+ ```bash
719
+ npm run db:migrate
720
+ ```
721
+
722
+ That step is about **running** the migration files that already exist.
723
+
724
+ The clean mental model is:
725
+
726
+ 1. JSKIT materializes managed migration files
727
+ 2. Knex executes them against the database
728
+
729
+ If you remember only one thing from this section, make it this:
730
+
731
+ - `jskit migrations ...` writes or refreshes managed migration files
732
+ - `npm run db:migrate` actually applies migrations to the database
733
+
734
+ Do not confuse those two steps.
735
+
736
+ Here is the practical version:
737
+
738
+ ```bash
739
+ # Common install flow for a schema-bearing package
740
+ npx jskit add package users-web
741
+ npm install
742
+ npm run db:migrate
743
+
744
+ # Refresh flow when JSKIT needs to re-materialize managed migration files
745
+ npx jskit migrations changed
746
+ npm run db:migrate
747
+ ```
748
+
749
+ In the first flow, package installation usually already wrote the managed migration files. In the second flow, you are explicitly asking JSKIT to write or refresh them again before Knex applies them.
750
+
751
+ ## Creating your own local package
752
+
753
+ JSKIT can also scaffold a brand-new app-local runtime package:
754
+
755
+ ```bash
756
+ npx jskit create package contacts
757
+ ```
758
+
759
+ If your app is named `exampleapp`, that command creates a package id like:
760
+
761
+ ```text
762
+ @exampleapp/contacts
763
+ ```
764
+
765
+ and scaffolds a real local package under:
766
+
767
+ ```text
768
+ packages/contacts/
769
+ ```
770
+
771
+ This is the direct CLI path for creating your own runtime package inside the app.
772
+
773
+ It is for the cases where you are authoring the package yourself:
774
+
775
+ - you want a new package boundary under `packages/`
776
+ - you want to define your own descriptor, providers, routes, or capabilities
777
+ - you are building app-specific runtime code, not installing something prebuilt from the catalog
778
+
779
+ That makes it different from both `add` and `generate`.
780
+
781
+ - `jskit add package ...` installs an existing runtime package from the catalog or from `node_modules`
782
+ - `jskit generate ...` runs a generator that writes app-owned scaffold files for a specific job such as CRUD
783
+ - `jskit create package ...` gives you a blank but valid app-local runtime package to grow yourself
784
+
785
+ ### What the command creates
786
+
787
+ The new package is intentionally small. For `contacts`, the scaffold looks like this:
788
+
789
+ ```text
790
+ packages/contacts/
791
+ README.md
792
+ package.json
793
+ package.descriptor.mjs
794
+ src/index.js
795
+ src/client/index.js
796
+ src/server/index.js
797
+ src/shared/index.js
798
+ ```
799
+
800
+ The command also updates two app-level files:
801
+
802
+ - `package.json`
803
+ - `.jskit/lock.json`
804
+
805
+ That means `create package` is not just "make a folder". It creates a real local JSKIT package and registers it with the app.
806
+
807
+ The important pieces are:
808
+
809
+ - `package.json`
810
+ defines a private local package with exports for `.`, `./client`, `./server`, and `./shared`
811
+ - `package.descriptor.mjs`
812
+ starts as a runtime descriptor with empty `dependsOn`, `capabilities`, `runtime`, `metadata`, and `mutations` sections ready for you to fill in
813
+ - `src/index.js`
814
+ gives the package a top-level module entrypoint, even before you decide what should be exported from it
815
+ - `src/client/index.js`
816
+ exports an empty `routeComponents` map and a no-op `bootClient()` so the package already has a valid client entrypoint
817
+ - `src/server/index.js` and `src/shared/index.js`
818
+ give you the server and shared entrypoints without assuming any implementation yet
819
+ - `README.md`
820
+ reminds you that the next step is to define runtime providers and real exports
821
+
822
+ This is a deliberate contrast with generated CRUD packages. A CRUD generator writes a much more opinionated scaffold: repository code, routes, actions, migrations, and resource definitions. `create package` does not guess any of that. It gives you the smallest valid runtime package boundary.
823
+
824
+ ### How the new package fits into the app
825
+
826
+ When you create `contacts`, JSKIT also adds a file dependency to the app root `package.json`:
827
+
828
+ ```json
829
+ "@exampleapp/contacts": "file:packages/contacts"
830
+ ```
831
+
832
+ and records the package in `.jskit/lock.json` as a `local-package`.
833
+
834
+ That has a few consequences:
835
+
836
+ - the package becomes part of the app's managed JSKIT state
837
+ - `jskit list packages` can see it alongside catalog packages
838
+ - later `update`, `remove`, and related lifecycle commands know this package exists
839
+ - the package is still app-owned, so JSKIT does not assume it can delete your directory just because managed state changes
840
+
841
+ This is the same idea you already saw in the starter app's `packages/main/` package. `create package` is how you make another package like that on purpose, instead of waiting for a generator to create one indirectly.
842
+
843
+ One practical point is easy to miss: the package exists immediately, but it does not do anything interesting until you give the descriptor real runtime hooks. In other words, after `create package`, you still need to add things such as:
844
+
845
+ - client providers
846
+ - server providers
847
+ - routes or UI metadata
848
+ - capabilities or dependency declarations
849
+
850
+ So think of `create package` as "establish the package boundary first, then implement the runtime behavior."
851
+
852
+ Because the command adds a file dependency, the normal follow-up is still:
853
+
854
+ ```bash
855
+ npm install
856
+ ```
857
+
858
+ or:
859
+
860
+ ```bash
861
+ npx jskit create package contacts --run-npm-install
862
+ ```
863
+
864
+ JSKIT updates the app files. npm refreshes dependency installation.
865
+
866
+ ### When to use it instead of a generator
867
+
868
+ Use `create package` when you are designing the package structure yourself.
869
+
870
+ Good fits include:
871
+
872
+ - a custom integration package that talks to one external API
873
+ - app-specific auth or policy behavior
874
+ - a local runtime package that owns both client and server behavior for one feature area
875
+ - a package that starts small now but may later grow providers, shared helpers, and routes
876
+
877
+ Use a generator when the problem is already understood well enough that JSKIT can scaffold the feature shape for you.
878
+
879
+ For example:
880
+
881
+ - `npx jskit create package contacts`
882
+ gives you an empty-but-valid `packages/contacts/` package boundary
883
+ - `npx jskit generate crud-server-generator scaffold contacts ...`
884
+ creates a CRUD-shaped package with repository, service, route, action, and migration files
885
+
886
+ Those commands can both result in a package under `packages/contacts/`, but they start from very different assumptions.
887
+
888
+ The other contrast is with catalog installs:
889
+
890
+ - `npx jskit add package workspaces-web`
891
+ installs a package someone else already authored
892
+ - `npx jskit create package contacts`
893
+ creates a package that your app will author and own
894
+
895
+ ### `--scope`, `--package-id`, and `--description` in practice
896
+
897
+ The three most important inline options are about naming and identity.
898
+
899
+ #### `--scope`
900
+
901
+ By default, JSKIT derives the scope from the app package name.
902
+
903
+ So if your app is `exampleapp`, this:
904
+
905
+ ```bash
906
+ npx jskit create package contacts
907
+ ```
908
+
909
+ produces:
910
+
911
+ ```text
912
+ package id: @exampleapp/contacts
913
+ directory: packages/contacts
914
+ ```
915
+
916
+ If you want a different scope, use `--scope`:
917
+
918
+ ```bash
919
+ npx jskit create package contacts --scope local
920
+ ```
921
+
922
+ which produces:
923
+
924
+ ```text
925
+ package id: @local/contacts
926
+ directory: packages/contacts
927
+ ```
928
+
929
+ Use this when you want the package id to follow a deliberate local naming convention instead of the app name.
930
+
931
+ #### `--package-id`
932
+
933
+ `--package-id` overrides the full package id directly:
934
+
935
+ ```bash
936
+ npx jskit create package contacts --package-id @acme/contacts
937
+ ```
938
+
939
+ This is the strongest naming override. Use it when you already know the exact package id you want.
940
+
941
+ In practice, this matters when:
942
+
943
+ - you want the package id to stay stable even if the app name changes
944
+ - you want a different scope than the default inference
945
+ - you are standardizing naming across several related local packages
946
+
947
+ The package directory is derived from the package name part of the package id, so `@acme/contacts` still creates `packages/contacts/`.
948
+
949
+ #### `--description`
950
+
951
+ `--description` fills the generated descriptor description:
952
+
953
+ ```bash
954
+ npx jskit create package contacts \
955
+ --description "App-local contact management runtime package."
956
+ ```
957
+
958
+ That is useful because the description is part of the package metadata JSKIT can show later when you inspect local packages. It is a small option, but it makes local packages easier to identify once an app has several of them.
959
+
960
+ So a practical mental model is:
961
+
962
+ - `--scope` chooses the default namespace for the generated package id
963
+ - `--package-id` sets the exact package id directly
964
+ - `--description` makes the generated descriptor self-describing
965
+
966
+ ## Summary
967
+
968
+ The JSKIT CLI is easiest to understand if you separate four jobs:
969
+
970
+ - `list`, `show`, and `help` are for discovery and inspection
971
+ - `add`, `update`, and `remove` manage installed JSKIT runtime packages
972
+ - `position`, `doctor`, and `migrations` maintain or repair JSKIT-managed state
973
+ - `create package` scaffolds a new app-local runtime package
974
+
975
+ And then keep one more distinction in your head:
976
+
977
+ - JSKIT manages app-owned package mutations and managed files
978
+ - npm installs dependencies
979
+ - Knex runs database migrations
980
+
981
+ That is the mental model the rest of the guide assumes.
982
+
983
+ The next chapter goes back to the normal hands-on flow and uses that model immediately by installing `shell-web`.