nylorun 0.4.0-beta → 0.5.0-beta

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,27 @@
1
1
  # nylorun
2
2
 
3
+ ## 0.5.0-beta
4
+
5
+ ### Minor Changes
6
+
7
+ - f96fe32: **Studio reports anonymous page views, unless you opt out.** Studio sends page views to Google Analytics with every Tenant, agent and session id replaced by `:id` and the query dropped; nothing sent to agents is collected. `nylorun start` says so once, and passes the measurement id to the Studio container as `NYLORUN_STUDIO_ANALYTICS_ID`. Turn it off with `nylorun telemetry disable`, `NYLORUN_TELEMETRY_DISABLED=1` or `DO_NOT_TRACK=1`; it is always off in CI, inside an embedding app, and when the browser sends Do Not Track or Global Privacy Control.
8
+ - 4b9906f: **Breaking: "Tenant" replaces "stack", and `nylorun start` works anywhere.** Each local installation holds one Tenant, and its name is the Tenant's name, so help, output, errors and docs say Tenant. See MIGRATION.md.
9
+
10
+ - **Breaking (`nylorun`): selection.** Every command acts on the Tenant `--tenant <name>` names (replaces `--name`, which is removed), else `NYLORUN_TENANT` (replaces `NYLORUN_STACK`), else the Project link's `tenant`; `start` in a project names a new one after the project directory. Outside a project, or with `start --no-link`, commands act on the Tenant `default`. In a project without a link, commands other than `start` exit 2 and list the machine's Tenants. A name starting with `tn_` (a Tenant id) is refused.
11
+ - **Breaking (`nylorun`): files.** Host roots are under `~/.nylorun/tenants/<name>/` (was `~/.nylorun/stacks/<name>/`) with `tenant.json` (was `stack.json`); the `.env` key is `NYLORUN_TENANT_NAME` (was `NYLORUN_STACK_NAME`); `NYLORUN_COMPOSE_PROJECT` replaces `NYLORUN_STACK_PROJECT`. Compose projects stay `nylorun-<name>`. Every command first moves 0.4 Host roots from `~/.nylorun/stacks/` to `~/.nylorun/tenants/` (renaming `stack.json` and the `.env` key), so they keep their volumes and keys. `nylorun ls` lists only directories with `tenant.json`.
12
+ - **Breaking (`nylorun`): removed.** `nylorun legacy` and all handling of the single stack of releases before 0.4; the hidden `nylorun stack <cmd>` alias; `nylorun doctor stack|runtime`. Output says Tenant: `ls` prints `TENANT` and JSON `{ "tenants": [...] }`, `status` prints the Tenant id on its own line, and `doctor`'s row is `tenant`.
13
+ - **Breaking: Project link format 3.** `.nylorun/link.json` is `{ "format": 3, "tenant", "tenantId", "hostUrl", "hostId" }`; `tenant` replaces `stack`. `@nylorun/agents`, `@nylorun/cli` and `@nylorun/admin` refuse an older link and name `npx nylorun start`, which rewrites it. `@nylorun/core`'s `ProjectLinkFileSchema` parses formats 0–3 with `tenant`.
14
+ - **Breaking (`@nylorun/admin`):** `createAdmin({ tenant })` replaces `{ stack }`, `tenantHostRoot(name)` replaces `stackHostRoot(name)`, and local resolution reads `NYLORUN_TENANT` and the link's `tenant`.
15
+ - `@nylorun/cli`: `status` and `endpoints` drop the `stack` line and JSON key; messages say Tenant. `@nylorun/agents`: a Runtime too old for the client says "update the Runtime (npx nylorun@latest start)". `@nylorun/studio`: setup hints say Tenant. `@nylorun/create-agent`: the next steps describe `npx nylorun@beta start` as this project's Tenant and its link.
16
+
17
+ ### Patch Changes
18
+
19
+ - Pin core to the tested release.
20
+ - Pin runtime to the tested release.
21
+ - Pin studio to the tested release.
22
+ - Updated dependencies [4b9906f]
23
+ - @nylorun/core@0.11.0-beta
24
+
3
25
  ## 0.4.0-beta
4
26
 
5
27
  ### Major Changes
package/README.md CHANGED
@@ -1,23 +1,23 @@
1
1
  # nylorun
2
2
 
3
- Sets up and runs local Nylorun stacks: the Runtime and Studio, as Docker
4
- Compose stacks, one per project. It needs nothing in your project; run it with
3
+ Sets up and runs local Nylorun Tenants: the Runtime and Studio, in Docker
4
+ Compose, one Tenant per project. It needs nothing in your project; run it with
5
5
  `npx` in the project's directory:
6
6
 
7
7
  ```sh
8
- npx nylorun start # create (first run) and start this project's stack, its Tenant and the Project link
8
+ npx nylorun start # create (first run) and start this project's Tenant, and the Project link
9
9
  npx nylorun stop # stop it; volumes (and the Tenant's data) are kept
10
10
  ```
11
11
 
12
- A stack is one installation: one Runtime with its own Postgres, Restate and
13
- S2, serving exactly one Tenant. `nylorun start` in a project creates the
14
- project's stack, the Runtime creates the stack's Tenant on its first start,
15
- and `nylorun start` links the project to it. There are no Tenant commands:
16
- projects that must not share agents, credentials or history run separate
17
- stacks. Agents, sessions and model providers belong to the Runtime client,
18
- [`@nylorun/cli`](../cli/README.md) (command `nylo`). Depends on `@nylorun/core`
19
- only among Nylorun packages and never imports `@nylorun/runtime`. Vocabulary:
20
- [runtime/src/CONTEXT.md](../runtime/src/CONTEXT.md).
12
+ A local Tenant is one installation: one Runtime with its own Postgres, Restate
13
+ and S2, serving exactly that Tenant, and its name is the Tenant's name.
14
+ `nylorun start` in a project creates the project's Tenant (the Runtime creates
15
+ it on its first start) and links the project to it; anywhere else, it starts
16
+ the Tenant `default`. Projects that must not share agents, credentials or
17
+ history run separate Tenants. Agents, sessions and model providers belong to
18
+ the Runtime client, [`@nylorun/cli`](../cli/README.md) (command `nylo`).
19
+ Depends on `@nylorun/core` only among Nylorun packages and never imports
20
+ `@nylorun/runtime`. Vocabulary: [runtime/src/CONTEXT.md](../runtime/src/CONTEXT.md).
21
21
 
22
22
  Prerequisites, installed by the developer (nylorun never downloads them): Node
23
23
  24 or newer, and Docker with Compose v2 ([Docker
@@ -28,53 +28,57 @@ another engine). On Windows, install them inside
28
28
  supported.
29
29
 
30
30
  ```sh
31
- npx nylorun doctor # Node 24+, Docker, Compose v2, and the stack's health
31
+ npx nylorun doctor # Node 24+, Docker, Compose v2, and the Tenant's health
32
32
  ```
33
33
 
34
34
  ## Commands
35
35
 
36
36
  ```sh
37
- nylorun up|start [--name <stack>] [--no-link] [--no-studio] [--no-open] [--allow-downgrade] [--studio-embed-origin <origin>]... [--studio-embed-origin-reset]
38
- # create (first run) and start the stack; link the project; print the URLs; open Studio signed in
39
- nylorun down|stop [--name <stack>] # stop the containers; keep volumes
40
- nylorun status [--name <stack>] [--json] # the stack, its Host root and Tenant, services, endpoints, Runtime health
41
- nylorun logs [service] [--name <stack>] [-f] [--tail <n>] # postgres, restate, s2, gateway, runtime, studio
42
- nylorun studio [--name <stack>] [--no-open] # sign a browser in to Studio on the stack's Tenant; starts the stack if needed
43
- nylorun reset [--name <stack>] [--yes] # delete the stack's volumes and Tenant directory; the next start creates a new Tenant
44
- nylorun ls [--json] # the stacks on this machine
45
- nylorun delete <stack> --yes # remove a stack: containers, volumes, Host root and vault key
46
- nylorun legacy stop|delete [--yes] # the single stack of older releases
47
- nylorun doctor [--json] # prerequisites and stack health
37
+ nylorun up|start [--tenant <name>] [--no-link] [--no-studio] [--no-open] [--allow-downgrade] [--studio-embed-origin <origin>]... [--studio-embed-origin-reset]
38
+ # create (first run) and start the Tenant; link the project; print the URLs; open Studio signed in
39
+ nylorun down|stop [--tenant <name>] # stop the containers; keep volumes
40
+ nylorun status [--tenant <name>] [--json] # the Tenant, its Host root and id, services, endpoints, Runtime health
41
+ nylorun logs [service] [--tenant <name>] [-f] [--tail <n>] # postgres, restate, s2, gateway, runtime, studio
42
+ nylorun studio [--tenant <name>] [--no-open] # sign a browser in to Studio on the Tenant; starts it if needed
43
+ nylorun reset [--tenant <name>] [--yes] # delete the Tenant's volumes, Tenant directory and vault key; the next start creates it anew
44
+ nylorun ls [--json] # the Tenants on this machine
45
+ nylorun delete <tenant> --yes # remove a Tenant: containers, volumes, Host root and vault key
46
+ nylorun doctor [--json] # prerequisites and the Tenant's health
47
+ nylorun telemetry [status|enable|disable] # Studio's anonymous usage analytics
48
48
  ```
49
49
 
50
50
  `up` and `down` are the Docker Compose spellings of `start` and `stop`: `down`
51
- stops the containers and keeps the volumes, so no Tenant data is lost.
52
- `nylorun stack <command>` still works as a hidden alias. Removed commands exit
53
- 2 naming the replacement: `nylorun tenant …` (`nylorun start` creates the
54
- Tenant; `nylorun status|reset`, or `nylo status|reset|endpoints`), `nylorun
55
- dev`, `nylorun configure`, `nylorun status --env` and `nylorun doctor sandbox`.
51
+ stops the containers and keeps the volumes, so no Tenant data is lost. Removed
52
+ commands exit 2 naming the replacement: `nylorun dev`, `nylorun configure`,
53
+ `nylorun status --env` and `nylorun doctor sandbox`.
56
54
 
57
- ## Stacks
55
+ ## Tenants
58
56
 
59
- Every command acts on one stack, chosen in this order:
57
+ Every command acts on one Tenant, chosen in this order:
60
58
 
61
- 1. `--name <stack>`;
62
- 2. `NYLORUN_STACK`;
63
- 3. the stack in the project's link (`.nylorun/link.json`, found from the
59
+ 1. `--tenant <name>`;
60
+ 2. `NYLORUN_TENANT`;
61
+ 3. the Tenant in the project's link (`.nylorun/link.json`, found from the
64
62
  working directory upwards);
65
- 4. for `start` in a project only: the project directory's name, lowercased,
66
- with characters outside `[a-z0-9_-]` as `-`, and a suffix (`-2`, `-3`, …)
67
- when a stack of that name was created for another project directory.
68
-
69
- Outside a project, `start` needs `--name`, and the other commands need
70
- `--name`, `NYLORUN_STACK` or a linked project. `nylorun ls` lists the stacks.
71
-
72
- Each stack has its own Host root `~/.nylorun/stacks/<name>/`, Compose project
73
- `nylorun-<name>` (`NYLORUN_STACK_PROJECT` overrides it), volumes, network and
74
- ports. `NYLORUN_HOME` replaces the whole Host root (the stack's name then comes
75
- from its `stack.json`, the project directory or the Host root's own name).
76
-
77
- A stack refuses only a Runtime older than its own database: `start` records
63
+ 4. for `start` in a project: the project directory's name, lowercased, with
64
+ characters outside `[a-z0-9_-]` as `-`, and a suffix (`-2`, `-3`, …) when a
65
+ Tenant of that name was created for another project directory;
66
+ 5. outside a project, or `start --no-link`: the Tenant `default`.
67
+
68
+ In a project without a link, the commands other than `start` exit 2 and list
69
+ the Tenants on this machine. A name is lowercase letters, digits, `-` and `_`;
70
+ a Tenant id (`tn_…`) is refused: pass the Tenant's name (`nylorun ls` lists
71
+ them).
72
+
73
+ Each Tenant has its own Host root `~/.nylorun/tenants/<name>/`, Compose project
74
+ `nylorun-<name>` (`NYLORUN_COMPOSE_PROJECT` overrides it), volumes, network and
75
+ ports. `NYLORUN_HOME` replaces the whole Host root (the Tenant's name then
76
+ comes from its `tenant.json`, the project directory or the Host root's own
77
+ name). nylorun 0.4 kept Host roots in `~/.nylorun/stacks/`: the first command
78
+ of this release moves them to `~/.nylorun/tenants/`, keeping their Compose
79
+ projects and volumes.
80
+
81
+ A Tenant refuses only a Runtime older than its own database: `start` records
78
82
  the pinned Runtime version in `host.json` (`runtimeVersion`) and exits 5 when
79
83
  this nylorun pins an older one. Update nylorun, or pass `--allow-downgrade`
80
84
  when both versions use the same database schema (otherwise the Runtime reports
@@ -84,51 +88,51 @@ recorded version.
84
88
 
85
89
  ## The Project link
86
90
 
87
- `nylorun start` in a project waits until the stack's Tenant is open
91
+ `nylorun start` in a project waits until the Tenant is open
88
92
  (`/v1/admin/status`), then writes, in a `.nylorun/` directory (mode 0700, with
89
93
  its own `.gitignore` of `*`):
90
94
 
91
- - `link.json`: `{ "format": 2, "stack", "hostUrl", "hostId", "tenantId" }`.
92
- The Tenant id is information only: nothing in a request selects a Tenant.
95
+ - `link.json`: `{ "format": 3, "tenant", "tenantId", "hostUrl", "hostId" }`.
96
+ `tenant` is the local Tenant's name; the Tenant id is information only:
97
+ nothing in a request selects a Tenant.
93
98
  - `credentials.json` (mode 0600): the key of the derived principal `project`,
94
- derived from the stack's admin key, and its id.
99
+ derived from the Tenant's admin key, and its id.
95
100
 
96
- Later starts reuse the stack and rewrite the link only when the stack, its URL,
97
- Host or Tenant changed (after `nylorun reset`, for example). When it writes a
101
+ Later starts reuse the Tenant and rewrite the link only when the Tenant's name,
102
+ URL, Host or id changed (after `nylorun reset`, for example). When it writes a
98
103
  new link, `start` seeds the Tenant from the project's `.env`: the sandbox
99
104
  backend (`NYLORUN_SANDBOX=auto|virtual`) and the model credential
100
105
  (`MODEL_PROVIDER`, `MODEL`, `MODEL_PROVIDER_API_KEY`, `MODEL_PROVIDER_BASE_URL`,
101
106
  or `.nylorun/auth.json`), unless the Tenant has a model or
102
- `NYLORUN_DEV_MODEL=fixture`. `.env` never configures the stack itself.
107
+ `NYLORUN_DEV_MODEL=fixture`. `.env` never configures the containers.
103
108
 
104
109
  A fresh clone or a second worktree has no link: `nylorun start` there creates a
105
- new stack, or `nylorun start --name <stack>` attaches it to an existing one so
106
- both share the stack's Tenant. `--no-link` starts a stack without linking the
107
- working directory (scripts). A link of format 0 or 1 named a Tenant on the
108
- shared stack of an older Runtime: `start` says so, creates the project's own
109
- stack and replaces the link.
110
+ new Tenant, or `nylorun start --tenant <name>` attaches it to an existing one so
111
+ both share it. `--no-link` starts a Tenant without linking the working
112
+ directory (scripts). A link of an older nylorun (format 0 to 2) counts as no
113
+ link: `start` replaces it.
110
114
 
111
115
  The Runtime registers the derived principals of `NYLORUN_DERIVED_PRINCIPALS`
112
- (comma-separated, from the environment of `nylorun start`, kept in the stack's
116
+ (comma-separated, from the environment of `nylorun start`, kept in the Tenant's
113
117
  `.env`) when it creates the Tenant; `project` is always among them.
114
118
 
115
- ## The stack
119
+ ## The containers
116
120
 
117
121
  `nylorun start` writes `compose.yaml` and `.env` (mode 0600) under
118
- `~/.nylorun/stacks/<name>/docker/` on the first run and reuses them after that: `postgres`,
122
+ `~/.nylorun/tenants/<name>/docker/` on the first run and reuses them after that: `postgres`,
119
123
  `restate`, `s2`, `gateway`, `runtime` and `studio`. Postgres initialises the
120
- stack's database with C collation. The Runtime and Studio images are pinned by
124
+ Tenant's database with C collation. The Runtime and Studio images are pinned by
121
125
  this release (`package.json` `nylorun.runtime` and `nylorun.studio`);
122
126
  `NYLORUN_RUNTIME_IMAGE` and `NYLORUN_STUDIO_IMAGE` override them (local builds,
123
127
  CI). Ports publish on loopback only: the Runtime on `8787`, its operator
124
128
  listener (Admin API) on `8788`, Studio on `4161` and the Restate UI on `9070`,
125
- or free ports chosen on the stack's first start, avoiding the ports other
126
- stacks keep, and kept in its `.env`.
129
+ or free ports chosen on the Tenant's first start, avoiding the ports other
130
+ Tenants keep, and kept in its `.env`.
127
131
 
128
132
  `start` prints Studio as `http://localhost:<port>`. Studio has no password: in a
129
133
  terminal (not in CI, and not with `--no-open`), `start` asks the Studio container
130
134
  for a single-use login token with the admin key (`POST /_studio/login-tokens`)
131
- and opens `http://localhost:<port>/login?token=…` on the stack's Tenant in the
135
+ and opens `http://localhost:<port>/login?token=…` on the Tenant's page in the
132
136
  browser. That sets a session cookie for 30 days, which survives Studio
133
137
  restarts, so the printed URL keeps working in that browser. The token itself is
134
138
  never printed unless no browser starts. Otherwise `start` says to run `nylorun
@@ -140,49 +144,55 @@ prints the login URL (it works once, for two minutes) instead.
140
144
  A desktop app such as Babai Desktop can show Studio inside its own window, in
141
145
  an iframe loaded from Studio's URL (`studio.url` in `nylorun status --json`).
142
146
  Only exact origins listed in `NYLORUN_STUDIO_FRAME_ANCESTORS` (in
143
- `~/.nylorun/stacks/<name>/docker/.env`) may frame it. The default is Babai's
147
+ `~/.nylorun/tenants/<name>/docker/.env`) may frame it. The default is Babai's
144
148
  `nylorun://localhost http://nylorun.localhost`; `nylorun status` lists them
145
149
  under `Embeds`. While building such an app, add its dev server once with
146
150
  `nylorun start --studio-embed-origin http://localhost:1420`; the list is kept
147
151
  across starts until `--studio-embed-origin-reset`. Wildcards are refused.
148
152
 
149
- The app's backend mints a single-use login token for the stack's Tenant with
153
+ The app's backend mints a single-use login token for the Tenant with
150
154
  `mintStudioLoginToken` from `@nylorun/admin` (it needs the admin key), and its
151
155
  page passes the token to Studio by `postMessage`. The message contract is
152
156
  `@nylorun/agents/studio-embed`.
153
157
 
158
+ ### Telemetry
159
+
160
+ Studio reports anonymous page views to Google Analytics, so we can see which
161
+ parts of it are used. A page view carries the route's shape only: every Tenant,
162
+ agent and session id becomes `:id` (`/tenants/:id/agents/:id/sessions/:id`)
163
+ and the query is dropped. Nothing you send to agents, no names, keys or
164
+ responses, and no Google signals or ad personalization are collected. Studio
165
+ loads no analytics inside an embedding app, or when the browser sends Do Not
166
+ Track or Global Privacy Control.
167
+
168
+ It is on by default, and `nylorun start` says so the first time. Turn it off on
169
+ this machine with `nylorun telemetry disable` (kept in
170
+ `~/.nylorun/telemetry.json`), or for one start with `NYLORUN_TELEMETRY_DISABLED=1`
171
+ or `DO_NOT_TRACK=1`. It is always off when `CI` is set. `nylorun start` decides
172
+ on every start and writes the result to `NYLORUN_STUDIO_ANALYTICS_ID` in
173
+ `docker/.env` (empty when off); `nylorun telemetry` reports the current choice.
174
+
154
175
  ## Sandboxes
155
176
 
156
177
  A session gets a sandbox when it is opened with one, or when the Tenant's
157
- default names one (`PUT /v1/tenant/sandbox`). The stack runs them on the
178
+ default names one (`PUT /v1/tenant/sandbox`). A local Tenant runs them on the
158
179
  Runtime's **virtual** backend: an emulated shell in the Runtime process, with no
159
180
  extra containers. It is not a VM or container boundary.
160
181
 
161
182
  ## Host root
162
183
 
163
- The **Host root** is `~/.nylorun/stacks/<name>/`, or `NYLORUN_HOME`. It is
164
- bind-mounted into the Runtime and Studio containers, and holds `stack.json`
165
- (the stack's name and the project it was created for), `host.json` (the
166
- client-facing host and port), `host-credentials.json` (the admin key, mode
167
- 0600), the Docker Compose files in `docker/`, the Tenant directory `tenant/` (homes, logs) and
168
- `keys/vault-kek`, the Tenant's vault key, which only the gateway container
169
- mounts. The Tenant's data lives in the stack's Postgres, Restate and S2
170
- volumes.
171
-
172
- `nylorun reset` deletes the selected stack's volumes, `tenant/` and `keys/`, and keeps
173
- its files and ports; the next start creates a new Tenant and relinks the
174
- project. `nylorun delete <stack> --yes` removes the stack's containers,
175
- volumes and Host root: the vault key (KEK) and all the Tenant's data go with it.
176
-
177
- ## Upgrading from a shared stack
178
-
179
- Older releases ran one stack per machine (Compose project `nylorun`, Host root
180
- `~/.nylorun`) with a Tenant per project. This release starts fresh and leaves
181
- that stack as it is: `nylorun start` mentions it once, and `nylorun ls` shows
182
- it. `nylorun legacy stop` stops it; `nylorun legacy delete --yes` removes its
183
- containers, volumes and files under `~/.nylorun` (never `~/.nylorun/stacks`).
184
- Model credentials come from each project's `.env` (or Studio), and agents
185
- register again (`npm run dev`). See [MIGRATION.md](../MIGRATION.md).
184
+ The **Host root** is `~/.nylorun/tenants/<name>/`, or `NYLORUN_HOME`. It is
185
+ bind-mounted into the Runtime and Studio containers, and holds `tenant.json`
186
+ (`{ "format": 1, "name", "project"? }`: the Tenant's name and the project it
187
+ was created for), `host.json` (the client-facing host and port),
188
+ `host-credentials.json` (the admin key, mode 0600), the Docker Compose files in
189
+ `docker/`, the Tenant directory `tenant/` (homes, logs) and `keys/vault-kek`,
190
+ the Tenant's vault key, which only the gateway container mounts. The Tenant's data lives in its Postgres, Restate and S2 volumes.
191
+
192
+ `nylorun reset` deletes the selected Tenant's volumes, `tenant/` and `keys/`, and keeps
193
+ its files and ports; the next start creates the Tenant anew (with a new id) and
194
+ relinks the project. `nylorun delete <tenant> --yes` removes the Tenant's
195
+ containers, volumes and Host root: the vault key (KEK) and all its data go with it.
186
196
 
187
197
  ## Exit codes
188
198
 
@@ -190,11 +200,11 @@ register again (`npm run dev`). See [MIGRATION.md](../MIGRATION.md).
190
200
  | --- | --- |
191
201
  | 0 | Success |
192
202
  | 1 | Generic failure, including a missing Docker or Compose v2 |
193
- | 2 | Usage error (including no stack selected, or `delete` without `--yes`), or a removed or moved command |
194
- | 3 | `status`: the Runtime is not answering; `stop`/`logs`: no stack yet; `delete`: no such stack |
203
+ | 2 | Usage error (including no Tenant selected, or `delete` without `--yes`), or a removed or moved command |
204
+ | 3 | `status`: the Runtime is not answering; `stop`/`logs`: no Tenant yet; `delete`: no such Tenant |
195
205
  | 4 | The Runtime port is held by another Host |
196
- | 5 | `up`/`start`/`studio`: this nylorun pins a Runtime older than the one that last ran the stack; update nylorun, or `start --allow-downgrade` |
197
- | 7 | The stack, its Tenant or Studio did not become ready (an unavailable Tenant's cause is printed) |
206
+ | 5 | `up`/`start`/`studio`: this nylorun pins a Runtime older than the one that last ran the Tenant; update nylorun, or `start --allow-downgrade` |
207
+ | 7 | The containers, the Tenant or Studio did not become ready (an unavailable Tenant's cause is printed) |
198
208
  | 130 / 143 | SIGINT / SIGTERM |
199
209
 
200
210
  ## Troubleshooting
@@ -204,8 +214,8 @@ register again (`npm run dev`). See [MIGRATION.md](../MIGRATION.md).
204
214
  | Docker missing or not running | Install or start Docker Desktop, OrbStack or Colima; `nylorun doctor` checks |
205
215
  | `426` from the Runtime | Upgrade nylorun (`npx nylorun@latest start`), or pin a matching older set |
206
216
  | `Refusing to start Runtime …` (exit 5) | Upgrade nylorun (`npx nylorun@latest start`); `--allow-downgrade` only when both Runtimes share the database schema |
207
- | `The Tenant of stack … is unavailable` (exit 7) | Follow the repair it names; `nylorun logs runtime` |
208
- | Port conflict | Change `NYLORUN_PORT` / `NYLORUN_STUDIO_PORT` in `~/.nylorun/stacks/<name>/docker/.env` |
217
+ | `Tenant … is unavailable` (exit 7) | Follow the repair it names; `nylorun logs runtime` |
218
+ | Port conflict | Change `NYLORUN_PORT` / `NYLORUN_STUDIO_PORT` in `~/.nylorun/tenants/<name>/docker/.env` |
209
219
  | Logs | `nylorun logs runtime -f` |
210
220
  | Studio login expired | `nylorun studio` |
211
221
 
package/dist/cli.js CHANGED
@@ -3,28 +3,30 @@ import "./baseline.js";
3
3
  import { baselineEnv } from "./baseline.js";
4
4
  import { CliError } from "./errors.js";
5
5
  import { isStackCommand, stackCommand, stackUsage, studioCommand, } from "./stack/index.js";
6
- const usage = `nylorun <up|down|start|stop|status|logs|studio|reset|ls|delete|legacy|doctor>
6
+ const usage = `nylorun <up|down|start|stop|status|logs|studio|reset|ls|delete|doctor|telemetry>
7
7
 
8
- Local stacks (Docker Compose), one per project:
8
+ Local Tenants (Docker Compose), one per project:
9
9
  ${stackUsage}
10
- doctor [--json] check Node, Docker and Compose v2, and the stack's health
10
+ doctor [--json] check Node, Docker and Compose v2, and the Tenant's health
11
+ telemetry [status|enable|disable] Studio's anonymous usage analytics (on unless disabled,
12
+ NYLORUN_TELEMETRY_DISABLED=1, DO_NOT_TRACK=1 or CI)
11
13
 
12
- A command acts on the stack --name or NYLORUN_STACK names, else the linked project's;
13
- NYLORUN_HOME sets its Host root (default ~/.nylorun/stacks/<name>).
14
+ A command acts on the Tenant --tenant or NYLORUN_TENANT names, else the linked project's,
15
+ else (outside a project) the default Tenant; NYLORUN_HOME sets its Host root
16
+ (default ~/.nylorun/tenants/<name>).
14
17
 
15
- nylorun sets up and runs local stacks. "nylorun start" in a project creates the
16
- project's stack, its one Tenant and the Project link. Agents, sessions and model
17
- providers belong to the Runtime client: npx @nylorun/cli --help`;
18
+ nylorun sets up and runs local Tenants. "nylorun start" in a project creates the
19
+ project's Tenant and the Project link; anywhere else, it starts the default Tenant.
20
+ Agents, sessions and model providers belong to the Runtime client: npx @nylorun/cli --help`;
18
21
  const CLIENT = "npx @nylorun/cli";
19
22
  /** Commands that were removed, or moved to the Runtime client (`@nylorun/cli`, command `nylo`). */
20
23
  const MOVED_TO_CLIENT = {
21
- dev: "nylorun dev was removed: run `npx nylorun start` in your project (it creates the project's stack, its Tenant and the Project link), then your project's `npm run dev`.",
22
- tenant: `Tenant commands were removed: a stack serves one Tenant, which \`npx nylorun start\` in a project creates with the stack and the Project link. Use nylorun status|reset, or ${CLIENT} status|reset|endpoints.`,
24
+ dev: "nylorun dev was removed: run `npx nylorun start` in your project (it creates the project's Tenant and the Project link), then your project's `npm run dev`.",
23
25
  configure: `nylorun configure moved to the Runtime client: ${CLIENT} configure`,
24
26
  serve: "nylorun serve was removed. Use node dist/src/main.js with NYLORUN_RUNTIME_URL and NYLORUN_SERVER_KEY.",
25
- runtime: "nylorun runtime was removed: the local Runtime runs in the Docker Compose stack. Use nylorun up|down|status|logs.",
27
+ runtime: "nylorun runtime was removed: the local Runtime runs in Docker Compose. Use nylorun up|down|status|logs.",
26
28
  };
27
- const LOCAL_UI_REMOVED = "--local-ui was removed: Studio runs in the stack's studio container. Run nylorun studio.";
29
+ const LOCAL_UI_REMOVED = "--local-ui was removed: Studio runs in its own container. Run nylorun studio.";
28
30
  const usageError = (message) => new CliError(message, 2);
29
31
  async function main() {
30
32
  const [command, ...args] = process.argv.slice(2);
@@ -47,23 +49,23 @@ async function main() {
47
49
  process.exitCode = await stackCommand(command, args, baselineEnv());
48
50
  return;
49
51
  }
50
- // `nylorun stack <command>`: the Wave 1 spelling, kept as a hidden alias.
51
- if (command === "stack") {
52
- const [name, ...rest] = args;
53
- if (!isStackCommand(name))
54
- throw usageError(usage);
55
- process.exitCode = await stackCommand(name, rest, baselineEnv());
52
+ if (command === "telemetry") {
53
+ const { telemetryCommand } = await import("./telemetry.js");
54
+ const { defaultNylorunRoot } = await import("./stack/stacks.js");
55
+ process.exitCode = await telemetryCommand(args, {
56
+ nylorunRoot: defaultNylorunRoot(),
57
+ env: baselineEnv(),
58
+ out: (line) => console.log(line),
59
+ });
56
60
  return;
57
61
  }
58
62
  if (command === "doctor") {
59
- // `doctor stack` and `doctor runtime` are older spellings of `doctor`.
60
- const options = args[0] === "stack" || args[0] === "runtime" ? args.slice(1) : args;
61
63
  if (args[0] === "sandbox")
62
64
  throw usageError(`nylorun doctor sandbox moved to the Runtime client: ${CLIENT} doctor sandbox`);
63
- if (options.some((option) => option !== "--json"))
65
+ if (args.some((option) => option !== "--json"))
64
66
  throw usageError("Usage: nylorun doctor [--json]");
65
67
  const { doctorStack } = await import("./doctor.js");
66
- process.exitCode = await doctorStack({ json: options.includes("--json"), env: baselineEnv() });
68
+ process.exitCode = await doctorStack({ json: args.includes("--json"), env: baselineEnv() });
67
69
  return;
68
70
  }
69
71
  throw usageError(usage);
package/dist/doctor.d.ts CHANGED
@@ -6,20 +6,20 @@ export interface StackDoctorReport {
6
6
  };
7
7
  docker: Check;
8
8
  compose?: Check;
9
- stack?: Pick<StackStatus, "name" | "project" | "home" | "state" | "runtime" | "tenant" | "studio" | "gateway">;
10
- /** Why no stack was checked: none is selected here (no link, NYLORUN_STACK or NYLORUN_HOME). */
11
- noStack?: string;
9
+ tenant?: Pick<StackStatus, "name" | "project" | "home" | "state" | "runtime" | "tenant" | "studio" | "gateway">;
10
+ /** Why no Tenant was checked: none is selected here (a project without a link). */
11
+ noTenant?: string;
12
12
  }
13
13
  /**
14
- * `nylorun doctor`: check the prerequisites of the local stack (Node 24+,
15
- * Docker, Compose v2) and, when they pass, the stack's health. Prints the fix
14
+ * `nylorun doctor`: check the prerequisites of a local Tenant (Node 24+,
15
+ * Docker, Compose v2) and, when they pass, the Tenant's health. Prints the fix
16
16
  * for each problem and returns 1 when a prerequisite is missing or a running
17
- * stack is unhealthy; installs and starts nothing.
17
+ * Tenant is unhealthy; installs and starts nothing.
18
18
  */
19
19
  export declare function doctorStack(options: {
20
20
  json: boolean;
21
21
  env?: Readonly<Record<string, string | undefined>>;
22
- /** Stack dependencies (tests). */
22
+ /** Command dependencies (tests). */
23
23
  deps?: StackDeps;
24
24
  log?: (line: string) => void;
25
25
  }): Promise<number>;
package/dist/doctor.js CHANGED
@@ -1,12 +1,12 @@
1
1
  import { CliError } from "./errors.js";
2
2
  import { checkDocker, defaultStackDeps, readStackStatus, } from "./stack/index.js";
3
- /** Oldest Node the stack's tooling and the developer's application run on. */
3
+ /** Oldest Node nylorun and the developer's application run on. */
4
4
  const MIN_NODE_MAJOR = 24;
5
5
  /**
6
- * `nylorun doctor`: check the prerequisites of the local stack (Node 24+,
7
- * Docker, Compose v2) and, when they pass, the stack's health. Prints the fix
6
+ * `nylorun doctor`: check the prerequisites of a local Tenant (Node 24+,
7
+ * Docker, Compose v2) and, when they pass, the Tenant's health. Prints the fix
8
8
  * for each problem and returns 1 when a prerequisite is missing or a running
9
- * stack is unhealthy; installs and starts nothing.
9
+ * Tenant is unhealthy; installs and starts nothing.
10
10
  */
11
11
  export async function doctorStack(options) {
12
12
  const log = options.log ?? ((line) => console.log(line));
@@ -20,7 +20,7 @@ export async function doctorStack(options) {
20
20
  if (checks.docker.ok && checks.compose?.ok) {
21
21
  try {
22
22
  const status = await readStackStatus(deps);
23
- report.stack = {
23
+ report.tenant = {
24
24
  name: status.name,
25
25
  project: status.project,
26
26
  home: status.home,
@@ -34,14 +34,14 @@ export async function doctorStack(options) {
34
34
  catch (error) {
35
35
  if (!(error instanceof CliError) || error.exitCode !== 2)
36
36
  throw error;
37
- report.noStack = error.message;
37
+ report.noTenant = error.message;
38
38
  }
39
39
  }
40
- const stackBroken = report.stack?.state === "running" &&
41
- (!report.stack.runtime.healthy ||
42
- !report.stack.gateway.healthy ||
43
- report.stack.tenant?.cause !== undefined);
44
- const failed = !nodeOk || !checks.docker.ok || checks.compose?.ok === false || stackBroken;
40
+ const broken = report.tenant?.state === "running" &&
41
+ (!report.tenant.runtime.healthy ||
42
+ !report.tenant.gateway.healthy ||
43
+ report.tenant.tenant?.cause !== undefined);
44
+ const failed = !nodeOk || !checks.docker.ok || checks.compose?.ok === false || broken;
45
45
  if (options.json) {
46
46
  log(JSON.stringify(report, null, 2));
47
47
  return failed ? 1 : 0;
@@ -61,41 +61,41 @@ export async function doctorStack(options) {
61
61
  ["docker", line(checks.docker)],
62
62
  ["compose", line(checks.compose)],
63
63
  ];
64
- const stack = report.stack;
65
- if (report.noStack)
66
- rows.push(["stack", `- ${report.noStack}`]);
67
- if (stack) {
64
+ const local = report.tenant;
65
+ if (report.noTenant)
66
+ rows.push(["tenant", `- ${report.noTenant}`]);
67
+ if (local) {
68
68
  rows.push([
69
- "stack",
70
- stack.state === "absent"
71
- ? `- ${stack.name} not created under ${stack.home}: run nylorun up`
72
- : stack.state === "stopped"
73
- ? `- ${stack.name} stopped (Compose project ${stack.project}): run nylorun up`
74
- : stack.runtime.healthy
75
- ? `✓ ${stack.name} running (Compose project ${stack.project})`
76
- : `✗ ${stack.name} running, but the Runtime does not answer: see nylorun status and nylorun logs runtime`,
69
+ "tenant",
70
+ local.state === "absent"
71
+ ? `- ${local.name} not created under ${local.home}: run nylorun up`
72
+ : local.state === "stopped"
73
+ ? `- ${local.name} stopped (Compose project ${local.project}): run nylorun up`
74
+ : local.runtime.healthy
75
+ ? `✓ ${local.name} running (Compose project ${local.project})`
76
+ : `✗ ${local.name} running, but the Runtime does not answer: see nylorun status and nylorun logs runtime`,
77
77
  ]);
78
- if (stack.state === "running") {
78
+ if (local.state === "running") {
79
79
  rows.push([
80
80
  "runtime",
81
- stack.runtime.healthy
82
- ? `✓ ${stack.runtime.url ?? "?"} · ${stack.runtime.version ?? "?"}`
83
- : `✗ ${stack.runtime.url ?? "?"} not answering`,
81
+ local.runtime.healthy
82
+ ? `✓ ${local.runtime.url ?? "?"} · ${local.runtime.version ?? "?"}`
83
+ : `✗ ${local.runtime.url ?? "?"} not answering`,
84
84
  ]);
85
85
  rows.push([
86
86
  "gateway",
87
- stack.gateway.healthy
88
- ? `✓ ${stack.gateway.state} · combined packing (runtime: core,loop; gateway: gates)`
89
- : `✗ ${stack.gateway.state}: model calls fail; see nylorun logs gateway`,
87
+ local.gateway.healthy
88
+ ? `✓ ${local.gateway.state} · combined packing (runtime: core,loop; gateway: gates)`
89
+ : `✗ ${local.gateway.state}: model calls fail; see nylorun logs gateway`,
90
90
  ]);
91
- if (stack.tenant)
91
+ if (local.tenant)
92
92
  rows.push([
93
- "tenant",
94
- stack.tenant.state === "open"
95
- ? `✓ ${stack.tenant.id ?? "?"} open`
96
- : `✗ ${stack.tenant.id ?? "?"} unavailable${stack.tenant.cause ? `: ${stack.tenant.cause.code}: ${stack.tenant.cause.repair}` : " (opening)"}`,
93
+ "tenant id",
94
+ local.tenant.state === "open"
95
+ ? `✓ ${local.tenant.id ?? "?"} open`
96
+ : `✗ ${local.tenant.id ?? "?"} unavailable${local.tenant.cause ? `: ${local.tenant.cause.code}: ${local.tenant.cause.repair}` : " (opening)"}`,
97
97
  ]);
98
- rows.push(["studio", `${stack.studio.url ?? "?"} · ${stack.studio.state}`]);
98
+ rows.push(["studio", `${local.studio.url ?? "?"} · ${local.studio.state}`]);
99
99
  }
100
100
  }
101
101
  const width = Math.max(...rows.map(([key]) => key.length)) + 2;
package/dist/home.d.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  /**
2
- * The Host root: an explicit home, `NYLORUN_HOME`, or `~/.nylorun`. The stack
2
+ * The Host root: an explicit home, `NYLORUN_HOME`, or `~/.nylorun`. Compose
3
3
  * bind-mounts it into the Runtime and Studio containers, and `@nylorun/admin`
4
4
  * reads `host.json` and the admin key from it.
5
5
  */
package/dist/home.js CHANGED
@@ -1,7 +1,7 @@
1
1
  import { homedir } from "node:os";
2
2
  import { join, resolve } from "node:path";
3
3
  /**
4
- * The Host root: an explicit home, `NYLORUN_HOME`, or `~/.nylorun`. The stack
4
+ * The Host root: an explicit home, `NYLORUN_HOME`, or `~/.nylorun`. Compose
5
5
  * bind-mounts it into the Runtime and Studio containers, and `@nylorun/admin`
6
6
  * reads `host.json` and the admin key from it.
7
7
  */
@@ -1,7 +1,7 @@
1
- /** The derived principal a Project uses; the stack's Runtime registers it on its Tenant. */
1
+ /** The derived principal a Project uses; the local Runtime registers it on its Tenant. */
2
2
  export declare const PROJECT_PRINCIPAL_ID = "project";
3
3
  /**
4
- * Key of a derived principal on the stack's Tenant, from the admin key. A copy of
4
+ * Key of a derived principal on the local Tenant, from the admin key. A copy of
5
5
  * `deriveTenantKey` in `@nylorun/admin` (nylorun depends on `@nylorun/core` only); both are
6
6
  * tested against the same fixed vector.
7
7
  */
@@ -1,8 +1,8 @@
1
1
  import { createHmac } from "node:crypto";
2
- /** The derived principal a Project uses; the stack's Runtime registers it on its Tenant. */
2
+ /** The derived principal a Project uses; the local Runtime registers it on its Tenant. */
3
3
  export const PROJECT_PRINCIPAL_ID = "project";
4
4
  /**
5
- * Key of a derived principal on the stack's Tenant, from the admin key. A copy of
5
+ * Key of a derived principal on the local Tenant, from the admin key. A copy of
6
6
  * `deriveTenantKey` in `@nylorun/admin` (nylorun depends on `@nylorun/core` only); both are
7
7
  * tested against the same fixed vector.
8
8
  */