lenso-cli 0.2.9

Lenso command-line interface for scaffolding and operating Lenso backend projects.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
# lenso-cli

Command-line interface for the Lenso backend framework.

## Install

```sh
npm install -g @lenso/cli
# or
cargo install lenso-cli
```

## Scaffold a host application

```sh
lenso host init my-app
cd my-app
cp .env.example .env
lenso console update
lenso serve
```

The package name defaults to the target directory name and can be overridden with
`--name`. Pass `--force` to scaffold into a non-empty directory.
Install or update the hosted Runtime Console with:

```sh
lenso console update
```

The command downloads the latest `lenso-runtime-console` release artifact and
installs it under `.lenso/console`, so the host API can serve `/console`
without requiring Node.js or pnpm in the host application. For local builds,
pass `--artifact <dir-or-tar.gz>`. For a pinned release, pass
`--console-version vX.Y.Z`.

After creating a password user, grant the first Runtime Console admin:

```sh
lenso console bootstrap-admin --identifier admin@example.com
# or
lenso console bootstrap-admin --user-id usr_...
```

`console.admin` is always added. Pass extra `--scope <name>` flags when the
user should also see scoped module data, then restart the API/worker.

The generated host depends on the crates.io `lenso` crate with the `host`
feature, which is the current narrow host API for booting API, worker, and
migration entrypoints. See
[`docs/architecture/framework-public-surface.md`](https://github.com/LioRael/lenso/blob/main/docs/architecture/framework-public-surface.md)
for the host-facade roadmap.

`lenso serve` is a local development wrapper for the generated host. It starts
the template Postgres service, runs migrations, then keeps the API and worker
running until Ctrl-C. New hosts run them in one local process; pass
`--separate-worker` when you want two child processes. Use `--skip-db` or
`--skip-migrate` when you already have those steps covered.

## Scaffold a module

```sh
lenso module create billing
```

Add `--with-console` when the linked module should also get a Runtime Console
workspace package:

```sh
lenso module create billing --with-console
```

For a standalone service provider:

```sh
lenso service create support-suite-provider --lang ts --output-dir ../services
lenso service create support-suite-provider --lang rust --output-dir ../services --port 4110
```

The generated provider includes a `lenso.service.json` manifest and a minimal
service process. A service name ending in `-provider` or `-service` provides a
module named without that suffix, so `support-suite-provider` provides
`support-suite`.
`service create` also updates `lenso.workspace.json` unless `--no-workspace` is
set. That workspace file is the local service plane for development:

```sh
lenso service workspace list
lenso service dev
```

`lenso service dev` starts workspace services first, then starts declared
installed services from `.lenso/module-services.json`, then runs the host.
Workspace reads prefer `lenso.workspace.json` and also accept the older
`.lenso/services.json` path for compatibility.

For a System v2 graph containing multiple Autonomous Services, use the
clusterless System Sandbox on macOS or Linux:

```sh
lenso system dev --dry-run --json
lenso system dev
lenso system dev --scenario deadline-timeout --json
lenso system dev --cleanup
```

The System graph remains in `lenso.system.json`. Local-only executable details
live beside it in `lenso.system-sandbox.json`:

```json
{
  "protocol": "lenso.system-sandbox.v1",
  "services": [{
    "serviceId": "support",
    "workloads": [{
      "workloadId": "support-migrate",
      "command": ["cargo", "run", "--bin", "support-migrate"]
    }, {
      "workloadId": "support-api",
      "command": ["cargo", "run", "--bin", "support-api"],
      "scenarioCommand": ["cargo", "run", "--bin", "support-scenario-driver"],
      "endpoint": "http://127.0.0.1:4110",
      "healthUrl": "http://127.0.0.1:4110/health/ready"
    }, {
      "workloadId": "support-worker",
      "command": ["cargo", "run", "--bin", "support-worker"]
    }]
  }],
  "scenarios": [{
    "scenarioId": "deadline-timeout",
    "fault": {
      "kind": "timeout",
      "serviceId": "support",
      "workloadId": "support-api",
      "delayMs": 100
    },
    "callPolicy": {
      "deadlineMs": 100,
      "maxAttempts": 2,
      "idempotent": true
    }
  }]
}
```

Failure controls are inert during ordinary startup and dry-run. They are read
only from the local System Sandbox definition and activated only when an
explicit `--scenario <scenarioId>` is supplied. Supported fault kinds are
`timeout`, `slow_dependency`, `workload_crash`, `overload`, and
`partial_unavailability`. Timeout and slow-dependency decisions use controlled
scenario time; overload uses declared `capacity` and `demand`, never machine
pressure.

Timeout, slow-dependency, and overload scenarios require the affected
Workload's `scenarioCommand`. The Sandbox invokes that Workload-owned adapter
only for an explicit scenario, supplies `LENSO_SANDBOX_*` controlled-time,
fault, capacity, and Call Policy inputs, and accepts one
`lenso.sandbox-workload-observation.v1` JSON result. The adapter exercises the
Service's real local call or dependency path; normal Workload startup never
receives those failure-control inputs.

Each run emits `lenso.failure-scenario-result.v1` JSON, performs Sandbox-owned
process and state cleanup, and writes the equivalent durable Story Segment to
`.lenso/system-sandbox-results/<systemId>/<scenarioId>/story-segment.json`.
Results include the injected fault, affected Service and Workload, attempt and
retry evidence, Call Policy and health transitions, outcome, cleanup, and next
actions. Repeating the same declared scenario overwrites that evidence with an
equivalent result.

Dry-run performs the same definition, cwd, executable, URL, graph, and
dependency validation as launch without creating Store directories, state, or
processes. Launch assigns each Workload an explicit `local-dev://` identity,
allocates one sandbox-owned Store path per Service, waits for declared health,
and records correlated endpoint and process state under
`.lenso/system-sandbox/<systemId>`. This identity is development-only and
does not claim production authentication. Ctrl-C and `--cleanup` terminate
only token-proven sandbox processes or their process groups, and remove state
only when its ownership marker
matches; Kubernetes, a Host, service mesh, external broker, System Plane, and a
production identity provider are not required.
Host and Provider declarations may remain in the System graph for topology
validation, but the sandbox neither starts nor contacts them.

## Assess linked Module extraction

Report whether one Host-owned linked Module is ready to move behind an
Autonomous Service boundary:

```sh
lenso module extraction readiness support-ticket \
  --module-manifest modules/support-ticket/lenso.module.json \
  --system-file lenso.system.json \
  --evidence-file support-ticket.extraction-evidence.json \
  --json
```

The CLI scans Rust Module Cargo dependencies, imports, and fully qualified
in-process calls under `modules/`. The evidence file supplies authoritative
Service/Event Contract mappings and active Consumer compatibility results;
omitting or supplying ambiguous evidence produces a blocked report. Human and
JSON output come from the same `lenso.extraction-readiness-report.v1` artifact.
Blocked reports exit non-zero so the command can gate CI.

Readiness analysis is read-only: it does not write repository files, start
Workloads, move data, or change authority. Use `--repo-root` and
`--modules-root` when the Module sources are not under the current repository's
default `modules/` directory.

Generated TS and Rust services also support `--check-release` to print the
development module release descriptor before packaging.
Before handing a service to another app or deployment pipeline, package-check
the project and then emit a local service artifact:

```sh
cd ../services/support-suite-provider
lenso service package --check
lenso service package --output-dir dist/lenso-service
```

The package artifact contains the canonical `lenso.service.json`,
`lenso.service-package.json`, and one
`modules/<module>/lenso.module.json` plus
`modules/<module>/lenso.module-release.json` file for each provided module.
The service package records the provider name, version, and provided module
names; each module release is the business-module install entrypoint.
Operators can install a provider directly. For a local package artifact, still
pass the runtime service base URL:

```sh
lenso service install dist/lenso-service/support-suite-provider/lenso.service-package.json \
  --base-url http://127.0.0.1:4100/lenso/service/v1
```

Install a packaged module release with the module command:

```sh
lenso module release inspect dist/lenso-service/support-suite-provider/modules/support-ticket/lenso.module-release.json
lenso module release check dist/lenso-service/support-suite-provider/modules/support-ticket/lenso.module-release.json \
  --base-url http://127.0.0.1:4100/lenso/service/v1
lenso module install dist/lenso-service/support-suite-provider/modules/support-ticket/lenso.module-release.json \
  --base-url http://127.0.0.1:4100/lenso/service/v1
lenso module enable support-ticket
lenso module disable support-ticket
```

`lenso.module-release.v1` is the module release channel. It records the module
name, version, capabilities, source, and optional provider pointer. V11 keeps
`lenso module install` as the unified business-capability entrypoint:

- `source: service` resolves to a provider service package or service manifest.
- `source: linked` enables linked Rust code in the host.
- `source: bundled` enables a host-bundled module.

`lenso service install` remains the lower-level provider/process command. It
connects a service, but it does not mean every module inside that service is
the user-facing install target.

When this command runs from a framework checkout with sibling `lenso` and
`lenso-runtime-console` repositories, the scaffold uses local path/file
dependencies so `cargo check` or `pnpm install` can run before the packages are
published. Outside that checkout it keeps the future-publish version
dependencies and prints a note to replace them with local paths until
`lenso-service` and `@lenso/service-kit` are published.

The older standalone module package generator is still available as:

```sh
lenso module create billing --remote --output-dir ../module-packages
```

The Runtime Console package generator is available directly as:

```sh
lenso console package create billing
```

### Runtime Console package development

Preview a console package while editing it:

```sh
lenso console dev --package packages/auth-console
```

From a module repository root, discover every local console package:

```sh
lenso module dev --console
```

Both commands default to standalone mock mode. Add `--host` to proxy real Lenso
host APIs while still loading the local package bundle:

```sh
lenso module dev --console --host http://localhost:3000
```

Set `LENSO_RUNTIME_CONSOLE_ROOT=/path/to/lenso-runtime-console` when the Runtime
Console checkout is not a sibling of the current repository.

## Install a module

```sh
lenso module install auth
lenso module install auth-password
lenso module install auth-oidc
lenso module install auth-device
```

`module install` reads `source` from the module descriptor when one is present.
When the reference is a module name, the CLI resolves it from the official
catalog at `https://catalog.lenso.dev/v1/modules.json` unless `--catalog-url`
points at another registry. If the primary official catalog endpoint is
temporarily blocked by edge security, the CLI falls back to the official
workers.dev mirror at `https://lenso-catalog.lenso.workers.dev/v1/modules.json`.
For V5 service-backed modules, `module install <name>` is the business-capability
entrypoint: the catalog resolves the provider service, installs it when needed,
then enables the requested module.
For module releases, `module install <module-release.json>` resolves the
release by source, then records `moduleRelease` provenance in
`.lenso/module-installs.json` where the source supports a receipt.

Install a service directly when you have a workspace service name or manifest
reference:

```sh
lenso service install support-suite-provider
lenso service install https://example.com/lenso/service/v1/manifest
lenso service install ./lenso.service.json --repo-root ../my-lenso-host
```

When the first argument matches a service in `lenso.workspace.json` or
`.lenso/services.json`, the CLI resolves its manifest and infers `--base-url`
from the service `readyUrl`. Local source manifests registered in the workspace
also infer `--base-url`; package artifacts outside that workspace still need
`--base-url` so the host records the runtime service endpoint rather than the
file path.

Service installs update `REMOTE_MODULES`, copy declared Runtime Console bundles to
`.lenso/console/extensions`, update `.lenso/console/extensions/registry.json`,
and record `.lenso/module-installs.json` in one step. Linked modules update the
host `Cargo.toml`, `src/lib.rs`, `.env` toggle, and the same install receipt
from the descriptor's `linked` section. `module add` remains a compatibility
alias for service installs.

Legacy `lenso module install <manifest-url>` still works for one compatibility
window, but prints a deprecation warning. Use `lenso service install <manifest>`
for process manifests and `lenso module install <module-name>` for business
modules.

Install descriptor profiles let a module expose optional setup without baking
module-specific choices into the CLI. For Redis-backed auth sessions:

```sh
lenso module install auth --profile redis-session-cache
```

The `auth` descriptor applies that profile by enabling the
`lenso-module-auth` dependency's `redis` Cargo feature, writing
`REDIS_URL=redis://localhost:6379/0` to `.env`, and recording
`auth.session_cache=redis` in `.lenso/runtime-config-defaults.json`. Provide a
Redis service separately; the starter Docker Compose file only starts Postgres
by default.

Reapply an installed module from `.lenso/module-installs.json` with:

```sh
lenso module update auth
lenso module update billing --base-url https://example.com/lenso/module/v1
```

`module update` reuses the recorded `manifestReference` and source. Remote
updates refresh `REMOTE_MODULES`, service state, install receipts, and copied
Runtime Console bundles. Linked updates reapply the recorded descriptor or
builtin module entry.

Use `--no-console-extension` when you want to skip Runtime Console extension
registration.

Service module manifests may also declare `install.env` values and
`install.commands`. Env values are written to `.env`; commands are run only when
you pass:

```sh
lenso service install https://example.com/lenso/service/v1/manifest --run-install-commands
```

For long-running service backends, declare `install.services`. These are
stored in `.lenso/module-services.json` and started before the host loads
service-provided modules on API/worker startup. Services started by the host are tracked with
`.lock`/`.pid` files and stopped when the owning API/worker process exits;
services that are already ready before startup are treated as external and are
not stopped by the host.

During local development, start declared service providers and then the host
with:

```sh
lenso service dev
lenso service dev --skip-db --skip-migrate
lenso service dev --workspace-file lenso.workspace.json
```

After the service processes are running, check the workspace from another shell:

```sh
lenso service workspace check
lenso service workspace check support-suite-provider --json
lenso service verify
lenso service verify support-suite-provider --json
lenso service verify ./lenso.service.json --env-file .env --json
```

Use `lenso service dev --no-workspace` when only installed
`.lenso/module-services.json` providers should start.

`lenso service workspace check` verifies that each declared service directory
exists, its manifest is reachable, and its `readyUrl` is responding before the
host tries to load the provider.

`lenso service verify` is the release-readiness entrypoint. With no argument it
checks `./lenso.service.json`; with a provider name it reuses the installed
service doctor checks. Pass `--env-file` to include required/missing service env
in the verification report.

Preview service upgrade impact before writing host-local state:

```sh
lenso service upgrade-plan billing ./lenso.service.json --json
lenso service upgrade billing ./lenso.service.json --dry-run
```

Export workspace services into the host service-start state format when a script
or deployment handoff should consume the same service declarations:

```sh
lenso service workspace export --output .lenso/module-services.json
```

Diagnose installed service state with:

```sh
lenso service doctor
lenso service doctor billing
lenso service doctor billing --json
lenso service check billing --json
```

The doctor reads `REMOTE_MODULES`, `.lenso/module-installs.json`, and
`.lenso/module-services.json`. It reports whether the service is
installed, configured, whether an HTTP manifest is reachable, whether managed
service `readyUrl` endpoints are ready, and which stale `.lock`/`.pid` files
may be blocking a host-started service.

Export declared service processes as a Compose fragment when handing the
service to deployment tooling:

```sh
lenso service export --module billing --format compose
```

If a manifest declares incompatible `compatibility` metadata, install stops
before writing host-local state. Use `--allow-incompatible` only when an
operator deliberately accepts that override.

Remove the local service source, install receipt, service state, Runtime
Console extension registry entry, and copied bundle files with:

```sh
lenso service uninstall billing-service
```

Use `--source linked` only when you need to force the loading source. Prefer
descriptors with a `source` field for new installs.

```sh
lenso module install auth --source linked
lenso module uninstall auth --source linked
```

## M6 GA support operations

The GA commands consume exact versioned evidence and never infer compatibility
from nearby semantic versions:

```sh
lenso ga support-check --manifest lenso.ga-support-manifest.v1.json \
  --component cli:@lenso/cli@0.1.30 \
  --component runtime:lenso-service@0.1.4 \
  --state-version service-store.v1 --json

lenso ga manifest-migrate --manifest lenso.ga-support-manifest.v1.json \
  --source lenso.system.json --target-format lenso.system.v2 \
  --identity-pointer /systemId --dry-run --json

lenso ga service-upgrade --manifest lenso.ga-support-manifest.v1.json \
  --input service-upgrade-input.json --json

lenso ga contract-retire --input contract-retirement-input.json --json
lenso ga failure-evaluate --input failure-scenario.json --json
```

Manifest migration and Service upgrade are non-mutating plans by default.
Contract Retirement does not apply without an exact human approval bound to
the current plan digest. Unknown combinations, stale inputs, active Consumers,
incomplete deprecation windows, incompatible state, and unexpected failure
behavior stop with stable issue codes and next actions.