@m6d/cortex-cli 0.12.1 → 0.14.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (76) hide show
  1. package/README.md +193 -128
  2. package/package.json +16 -5
  3. package/src/cli.ts +19 -12
  4. package/src/commands/apply.ts +186 -0
  5. package/src/commands/{cc.ts → management.ts} +173 -112
  6. package/src/commands/new.ts +83 -84
  7. package/src/commands/setup.ts +610 -0
  8. package/src/contracts/charts/chart-spec.ts +1 -1
  9. package/src/contracts/client-tools/index.ts +3 -3
  10. package/src/contracts/{runtime → datasets}/datasets.ts +7 -42
  11. package/src/contracts/datasets/index.ts +3 -0
  12. package/src/contracts/egress-policy/index.ts +16 -0
  13. package/src/contracts/{egress → egress-policy}/scrub.ts +34 -5
  14. package/src/contracts/{egress → egress-policy}/url.ts +22 -9
  15. package/src/contracts/errors/index.ts +38 -0
  16. package/src/contracts/json/index.ts +5 -0
  17. package/src/contracts/manifest/index.ts +973 -0
  18. package/src/contracts/manifest-file/index.ts +16 -0
  19. package/src/contracts/markdown/index.ts +1 -1
  20. package/src/contracts/pattern/index.ts +276 -0
  21. package/src/contracts/server/index.ts +349 -0
  22. package/src/contracts/server/reserved-names.fixtures.json +18 -0
  23. package/src/contracts/triggers/index.ts +112 -0
  24. package/src/contracts/wire/index.ts +67 -33
  25. package/src/{cc → management}/client.ts +33 -7
  26. package/src/{cc → management}/flags.ts +2 -1
  27. package/src/{cc → management}/profiles.ts +10 -8
  28. package/src/scaffold/files.ts +448 -284
  29. package/src/scaffold/ports.ts +12 -24
  30. package/src/scaffold/templates/cspell.json.txt +41 -0
  31. package/src/scaffold/templates/datasets.ts.txt +52 -0
  32. package/src/scaffold/templates/dockerignore.txt +6 -0
  33. package/src/scaffold/templates/fallowrc.jsonc.txt +8 -12
  34. package/src/scaffold/templates/gitignore.txt +1 -1
  35. package/src/scaffold/templates/server.ts.txt +40 -0
  36. package/src/scaffold/templates/setup.ts.txt +44 -0
  37. package/src/ui/prompts.ts +24 -38
  38. package/src/ui/report.ts +5 -15
  39. package/tsconfig.json +2 -3
  40. package/src/commands/graph.ts +0 -228
  41. package/src/commands/swagger.ts +0 -247
  42. package/src/config/load.ts +0 -122
  43. package/src/config/validate.ts +0 -46
  44. package/src/contracts/credentials/index.ts +0 -183
  45. package/src/contracts/egress/index.ts +0 -120
  46. package/src/contracts/graph/clients/embed.ts +0 -62
  47. package/src/contracts/graph/clients/neo4j.ts +0 -85
  48. package/src/contracts/graph/helpers.ts +0 -55
  49. package/src/contracts/graph/index.ts +0 -30
  50. package/src/contracts/graph/schema.ts +0 -65
  51. package/src/contracts/graph/types.ts +0 -125
  52. package/src/contracts/rich-text/index.ts +0 -220
  53. package/src/contracts/runtime/api.ts +0 -345
  54. package/src/contracts/runtime/auth.ts +0 -41
  55. package/src/contracts/runtime/grammar.ts +0 -169
  56. package/src/contracts/runtime/index.ts +0 -15
  57. package/src/contracts/runtime/models.ts +0 -50
  58. package/src/contracts/runtime/signature.ts +0 -255
  59. package/src/contracts/runtime/sync.ts +0 -196
  60. package/src/contracts/runtime/triggers.ts +0 -267
  61. package/src/graph/expand-domains.ts +0 -286
  62. package/src/graph/generate-cypher.ts +0 -201
  63. package/src/graph/seed.ts +0 -199
  64. package/src/graph/validate.ts +0 -78
  65. package/src/scaffold/features.ts +0 -190
  66. package/src/scaffold/templates/domains-README.md.txt +0 -16
  67. package/src/scaffold/templates/index.ts.txt +0 -18
  68. package/src/swagger/extract-endpoints.ts +0 -269
  69. package/src/swagger/generated-block.ts +0 -74
  70. package/src/swagger/openapi-schema.ts +0 -168
  71. package/src/swagger/parse-response.ts +0 -88
  72. package/src/swagger/types.ts +0 -25
  73. /package/src/contracts/{runtime → datasets}/dataset-sql-guide.ts +0 -0
  74. /package/src/contracts/{runtime → datasets}/dataset-sql.ts +0 -0
  75. /package/src/contracts/{runtime → datasets}/datasets.fixtures.json +0 -0
  76. /package/src/{cc → management}/output.ts +0 -0
package/README.md CHANGED
@@ -1,16 +1,17 @@
1
1
  # @m6d/cortex-cli
2
2
 
3
- The `cortex` command line: scaffold Cortex servers, and run the generators that otherwise need a
4
- hand-written script.
3
+ The `cortex` command line: scaffold a Cortex project, and manage a Cortex deployment from the
4
+ terminal.
5
5
 
6
6
  ```sh
7
7
  bunx @m6d/cortex-cli new my-app # from nowhere — scaffolds a project
8
- bunx cortex swagger sync # inside a project — reads its cortex.config.ts
9
- bunx cortex graph seed
8
+ bunx cortex agents list # against the Cortex you logged in to
9
+ bunx cortex apply # make it match ./cortex.manifest.ts
10
10
  ```
11
11
 
12
- Commands are noun-first — `cortex <resource> <verb>` — except `new`, which acts on no existing
13
- resource. Run `cortex --help`, then `cortex <resource> --help`.
12
+ Commands are noun-first, `cortex <resource> <procedure>`, except `new`, which acts on no existing
13
+ resource, `setup` and `apply`, which act on a whole deployment, and `login`, `logout` and `status`,
14
+ which act on your profiles. Run `cortex --help`, then `cortex <resource> --help`.
14
15
 
15
16
  ```sh
16
17
  bun add -d @m6d/cortex-cli
@@ -21,155 +22,219 @@ you how to install Bun when it is genuinely absent.
21
22
 
22
23
  ## `cortex new`
23
24
 
24
- Scaffolds `./<name>`: a standalone project with `cortex.config.ts`, `index.ts`, `.env` and
25
- `.env.example`, inlined eslint/prettier/cspell/fallow config, and a `docker-compose.yml` when a
26
- selection contributes a service. It then runs `bun install`, and `git init` unless the target is
27
- already inside a work tree. An existing non-empty directory is an error.
25
+ Scaffolds `./<name>`: a backend for Cortex agents, and Cortex itself to run them on.
26
+
27
+ - `server.ts` is a Cortex server built with `defineServer` from `@m6d/cortex`: one variable
28
+ (`userName`) and one native tool (`rollDice`), mounted at `/cortex` by `index.ts`.
29
+ - `cortex.manifest.ts` declares a `helper` agent on that server, for `cortex apply`.
30
+ - `docker-compose.yml` runs Cortex's app, worker and engine on the one `syscodeia/cortex` image,
31
+ with Postgres, Redis and MinIO. Only the app and the engine publish host ports. They and the
32
+ backend's port are picked at scaffold time from what was free.
33
+ - `.env` holds every setting: Cortex's secrets, the backend's key and name, the model provider, and
34
+ the `CORTEX_URL` and `CORTEX_KEY` the CLI reaches this checkout's Cortex with. It is not
35
+ committed: `setup.ts` writes it from `.env.example` on every `bun install`, generating each
36
+ secret left blank, so a fresh clone gets its own secrets and a stack that never shares the
37
+ original's volumes. `.dockerignore` keeps both out of images.
38
+ - `bun run dev` starts Cortex (`docker compose up`), the backend and `bun cortex setup --wait --yes` in
39
+ an mprocs dashboard. `bun run dev:agent` runs the same through `concurrently`, one labelled log for
40
+ coding agents and CI.
41
+ - eslint, prettier, cspell, fallow and tsconfig are inlined, so `bun run verify` works standalone.
42
+
43
+ It then runs `bun install`, and `git init` unless the target is already inside a work tree. An
44
+ existing non-empty directory is an error. So is a name like `cortex` or `cortex.`, since the
45
+ manifest takes its id from the name and Cortex keeps the id `cortex` for its own.
28
46
 
29
47
  ```sh
30
- bunx @m6d/cortex-cli new widget-backend --knowledge --redis
48
+ bunx @m6d/cortex-cli new shop --datasets
31
49
  ```
32
50
 
33
- On a TTY it asks only what the flags left open — the name, the database, and one multi-select over
34
- the undecided features. With no TTY it never prompts and behaves as `--yes`, so a missing name is a
51
+ On a TTY it asks only what the flags left open: the name, whether to set up the `helper` agent on
52
+ the first `bun run dev`, and if so the model provider (name, base URL, API key, model). It checks
53
+ the provider with one chat message to the model, and reuses it for embeddings when it serves the
54
+ stack's embedding model. With no TTY it never prompts and behaves as `--yes`, so a missing name is a
35
55
  hard error rather than a hang.
36
56
 
37
- | Flag | Default | Writes |
38
- | ------------------------------------------ | ---------- | ------------------------------------------------------------------------- |
39
- | `--database <postgres\|mssql>` | `postgres` | The `database` block. `postgres` also gets a compose service; `mssql` not |
40
- | `--attachments` / `--no-attachments` | off | `storage` + `vision` — MinIO uploads, described by a vision model |
41
- | `--redis` / `--no-redis` | off | `redis` — resumable streams across restarts |
42
- | `--auth` / `--no-auth` | off | `auth` — JWT verification via JWKS |
43
- | `--knowledge` / `--no-knowledge` | off | `neo4j` + `embedding` + `knowledge`, plus a `src/domains/` tree |
44
- | `--control-center` / `--no-control-center` | off | `controlCenter` |
45
- | `--yes` | | Accept the defaults instead of asking |
46
-
47
- Unselected features are still written to `cortex.config.ts`, commented out, alongside `reranker`
48
- and `context` — the generated config documents what else exists. Every credential and
49
- URL is a placeholder in `.env`; none of them is prompted for.
50
-
51
- ## `cortex swagger sync` / `check`
52
-
53
- Fetches every Swagger URL the config names — server-level and per-agent, deduped — and reconciles
54
- the `.endpoint.ts` files under the domains directory against it.
55
-
56
- ```sh
57
- bunx cortex swagger sync
58
- bunx cortex swagger check
59
- bunx cortex swagger sync --domains-dir ./server/src/domains
60
- ```
61
-
62
- `sync` rewrites each endpoint's params, body, and response schemas in place and prints only the
63
- files it changed; unchanged ones live in the footer count. `check` writes nothing, reports the drift
64
- it found, and exits 2 — which is what makes it a CI step.
65
-
66
- An endpoint file pointing at a route the spec no longer serves is `MISSING`. `sync` prints those
67
- last, so they are the thing you read, and still exits 0: writing is its job. `check` counts them as
68
- a finding, same as drift.
69
-
70
- `-d, --domains-dir <path>` is declared on the `swagger` group, so it works on either side of the
71
- verb. It defaults to `src/domains`, resolved relative to the config file.
72
-
73
- ## `cortex graph seed`
74
-
75
- Loads every domain the config declares — server-level `knowledge.domains` and per-agent ones,
76
- deduped — and seeds Neo4j with the concepts, endpoints, services, and rules they declare, then
77
- embeds them. Reports per domain, because a domain is the unit you edit. No
78
- flags.
57
+ | Flag | Default | Writes |
58
+ | ------------------------ | ------- | ------------------------------------------------------------------------------------------- |
59
+ | `--datasets` | off | `datasets.ts`, an in-memory `orders` table served as a dataset host, and its manifest entry |
60
+ | `--setup` / `--no-setup` | on | `cortex setup` among the processes `bun run dev` starts |
61
+ | `--yes` | | Accept the defaults instead of asking; setup then runs with no model provider |
62
+
63
+ The image runs at the Cortex release that was current when this CLI was published
64
+ (`CORTEX_VERSION` in the shell picks another); the backend depends on the `@m6d/cortex` release of
65
+ that time. A server name stops at Cortex's 100 characters, so a longer project name is
66
+ registered cut to that length.
67
+
68
+ ## `cortex setup`
69
+
70
+ Registers a `cortex new` project's backend in its Cortex, then applies its manifest. It reads the
71
+ backend's name, URL and key (`CORTEX_SERVER_*`) and the model provider (`MODEL_PROVIDER_*`) from
72
+ `.env`, and goes in the one order Cortex accepts: the server key's secret, the provider's key and
73
+ the provider, the server on the provider's model, a sync of the server, then the apply. Each step
74
+ creates what is missing and keeps what exists, so a second run changes nothing. A key's secret is
75
+ named for its value (`openai-api-key-1a2b3c4d`), so a changed key gets a new secret the provider or
76
+ server moves to, and whatever else presents the old one keeps it. A provider or server under
77
+ `.env`'s name that calls another URL belongs to something else: setup leaves it alone and stops. So
78
+ does a `MODEL_PROVIDER_*` set only in part, or a provider URL on this machine or a private network
79
+ that `EGRESS_ALLOWED_HOSTS` in `.env` does not admit. A server with no model yet gets the provider's.
79
80
 
80
81
  ```sh
81
- bunx cortex graph seed
82
+ bun cortex setup # asks for a model provider when .env has none
83
+ bun cortex setup --wait --yes # what `bun run dev` runs
82
84
  ```
83
85
 
84
- Seeding is `MERGE`-based, so re-running is safe. If any statement failed, the graph is partially
85
- seeded and the command exits 1 — a half-seeded graph should not pass as success.
86
+ `--wait` waits up to 10 minutes for Cortex to answer, long enough for a first start to pull the
87
+ image. Without `-p`, setup sets up the Cortex `.env` names: a different `CORTEX_URL` exported in the
88
+ shell, which Bun lets win over `.env`, ends the run. The retried sync, a minute while Cortex cannot
89
+ reach the backend, gives up at once on any other refusal. With no model provider and `--yes`, it
90
+ registers the server and applies nothing: Cortex publishes no agent without a model. The run that
91
+ first creates something says how to sign in, with the password only on a terminal.
86
92
 
87
- ## `cortex cc`
93
+ ## Management commands
88
94
 
89
- Manage a Control Center without its console. The commands come from the
90
- Control Center's own management API (`/api/management/openapi.json`), fetched
95
+ Manage a Cortex deployment from the terminal. The commands come from
96
+ Cortex's own management API (`/api/management/openapi.json`), fetched
91
97
  on each run and cached, so the tree always matches the deployment you point
92
98
  at and a new procedure needs no CLI release.
93
99
 
94
100
  ```sh
95
- cortex cc login # asks for the URL and a management key
96
- cortex cc status
97
- cortex cc agents list
98
- cortex cc agents create --slug support --name Support --serverId <uuid>
99
- cortex cc tools create --json tool.json --publish
100
- cortex cc tools list -o json | jq '.items[].name'
101
- cortex cc logout
101
+ cortex login # asks for the URL and a management key
102
+ cortex status
103
+ cortex agents list
104
+ cortex agents create --slug support --name Support --serverId <uuid>
105
+ cortex tools create --json tool.json --publish
106
+ cortex tools list -o json | jq '.items[].name'
107
+ cortex logout
102
108
  ```
103
109
 
104
- Profiles live in `~/.cortex/cc.json` (owner-only). `--profile <name>` picks
105
- one; `CORTEX_CC_URL` and `CORTEX_CC_KEY`, both set, win over the file for CI.
106
- `CORTEX_HOME` relocates the directory.
110
+ Profiles live in `~/.cortex/profiles.json` (owner-only). `-p, --profile <name>`,
111
+ a global option, picks one for any command, and names the one `login` saves
112
+ and `logout` forgets (`default` otherwise). `CORTEX_URL` and `CORTEX_KEY`, both
113
+ set, win over the current profile, for CI and for a project's `.env`; a
114
+ profile `-p` names wins over them. `CORTEX_HOME` relocates the directory.
107
115
 
108
- The grammar is `cortex cc <router> <procedure> [id] [flags]`. Each top-level
109
- input field is a flag typed from the API's schema; nested values take JSON,
110
- and `--json <file|->` supplies a whole body that flags then override. A
111
- required field left out is asked for on a terminal and named as the missing
112
- flag otherwise. Listings take `--pageIndex`, `--pageSize`, `--q`, and `--all`
113
- to walk every page. `-o json` prints the raw result for pipes.
116
+ The grammar is `cortex <router> <procedure> [id] [flags]`, with routers as
117
+ the API names them (`datasetHosts`, `modelProviders`). Each top-level input
118
+ field is a flag typed from the API's schema; nested values take JSON, and
119
+ `--json <file|->` supplies a whole body that flags then override. A required
120
+ field left out, `id` included, is asked for on a terminal and named as the
121
+ missing flag or positional otherwise. Listings take `--pageIndex`, `--pageSize`, `--q`, and `--all` to
122
+ walk every page. `-o json` prints the raw result for pipes.
114
123
 
115
124
  Writes to agents, tools, services, skills, triggers, and dataset hosts save
116
125
  drafts.
117
126
  `--publish` on a write the API marks publishable (`update`, and a `create`
118
127
  whose result is complete enough) runs that entity's publish procedure right
119
- after; without it the command says so and names the command. Live fields bind
120
- on the server's next config revalidation without a publish: a trigger's
121
- `credential` (a secret, so it is prompted for or piped in with `--json -`
122
- rather than passed as a flag) and a dataset host's url, access fields, and
123
- timeout. `cortex cc dataset-hosts sync <id>` reads a host's manifest, and a
124
- draft host publishes only after `dataset-hosts test` reached it once.
128
+ after; without it the command says so and names the command. Fields the API
129
+ marks live (`x-live-fields`) take effect without a publish, from agents'
130
+ next turn, and the command names them: a trigger's
131
+ `credentialName`, `fireCredentialName` and model, say, or a dataset host's
132
+ `url`, `credentials` and `timeoutMs`. `cortex datasetHosts sync <id>` reads a host's manifest, and a
133
+ draft host publishes only after `datasetHosts test` reached it once.
134
+
135
+ ## `cortex apply`
136
+
137
+ Makes Cortex match a manifest, in one transaction: what is new is
138
+ created, what changed is updated and republished, and what the manifest
139
+ created and does not list is deleted. Rows it did not create are never
140
+ touched, and a name one of them holds fails the apply.
141
+
142
+ ```sh
143
+ cortex apply # ./cortex.manifest.ts
144
+ cortex apply deploy/manifest.json --dry-run
145
+ cortex apply -p prod
146
+ ```
147
+
148
+ The path defaults to exactly `./cortex.manifest.ts` in the directory you run
149
+ in. TypeScript and JSON load the same way: the file's default export is the
150
+ manifest. `defineManifest` from `@m6d/cortex` types one as you write it:
151
+
152
+ ```ts
153
+ import { defineManifest } from "@m6d/cortex";
154
+
155
+ export default defineManifest({
156
+ id: "shop",
157
+ tools: [
158
+ {
159
+ type: "http",
160
+ name: "findOrder",
161
+ description: "Find one order by id.",
162
+ url: "https://shop.example.com/orders/{orderId}",
163
+ method: "GET",
164
+ readOnly: true,
165
+ inputSchema: {
166
+ type: "object",
167
+ properties: { orderId: { type: "string" } },
168
+ required: ["orderId"],
169
+ },
170
+ audience: { agents: ["support"] },
171
+ },
172
+ ],
173
+ });
174
+ ```
175
+
176
+ An `openapi` source makes every operation of an OpenAPI document a tool the
177
+ manifest owns, so a backend with many endpoints needs no entry per tool:
178
+
179
+ ```ts
180
+ openapi: [
181
+ {
182
+ name: "shop",
183
+ url: "https://shop.example.com/openapi.json",
184
+ credentials: [{ header: "Authorization", prefix: "Bearer ", credential: null }],
185
+ pinned: ["findOrder"],
186
+ // A GET runs at once; any other method waits for the end user's approval.
187
+ approval: { never: ["addOrderNote"], always: ["exportOrders"] },
188
+ audience: { agents: ["support"] },
189
+ },
190
+ ],
191
+ ```
192
+
193
+ Every apply reads the document first, without the source's credentials. An
194
+ operation it adds is created, a changed one updated, and a dropped one
195
+ deleted. A source with credentials is read only over https, or from a host
196
+ the deployment allows, since the document says where they go. A source needs the `tools` write permission even when nothing
197
+ changes. Each tool is named after its `operationId`, made an identifier of at
198
+ most 64 characters; an operation Cortex cannot import is left
199
+ out. Two operations that come out with one name are told apart by a number
200
+ (`getOrders`, `getOrders2`) in the order of their paths. The apply fails
201
+ when `pinned` or `approval` names a tool no operation has (`unknown_tool`)
202
+ or any name such a collision decided (`ambiguous_tool`), since a path the
203
+ document adds or drops could move it to another endpoint. It also fails when an
204
+ operation's name is already a listed tool's or another source's.
205
+
206
+ The manifest is checked against the contract before anything is sent, then
207
+ sent as written, so Cortex fills its own defaults. It goes to the
208
+ management API (`manifests/sync`, or `manifests/preview` with `--dry-run`,
209
+ which changes nothing) under the same profile the management commands use, so
210
+ the key needs `publishing:publish` and the write permission of every kind the
211
+ apply changes. The output lists each changed entry under its kind: `+`
212
+ created, `~` updated, `-` deleted. A trigger the apply creates, or whose
213
+ `fireCredential` it drops, gets a fire secret, printed once below the summary
214
+ and never again.
215
+
216
+ References between entries (mentions, service scopes, which role a
217
+ credential or secret plays) are judged on the state the apply leaves, so
218
+ the order the manifest lists them in does not matter. A dataset host's
219
+ credentials are the exception: its catalog is read with them before the
220
+ apply, so they are judged on the deployment as it stands. A credential a
221
+ trigger fires with cannot go to a host in the same apply that drops
222
+ it; drop it first, then apply again.
125
223
 
126
224
  ## Global options
127
225
 
128
- | Option | Description |
129
- | --------------- | -------------------------------------------- |
130
- | `-v, --verbose` | Print full errors and the commands being run |
131
- | `-V, --version` | Output the version number |
132
- | `-h, --help` | Display help for command |
133
-
134
- `swagger` and `graph` read the project and take `-c, --config <path>` (default
135
- `./cortex.config.ts`) on the group or the verb. `new` and `cc` do not touch a
136
- project and have no such flag.
137
-
138
- Config discovery is that exact filename in the directory you run in, with no upward search. There is
139
- no `--cwd`: Bun auto-loads `.env` relative to the process cwd before any of our code runs, so
140
- reading another directory's config from here would pair it with the wrong environment. `cd` first,
141
- or point `--config` at the file.
142
-
143
- The config is inert data — a plain object literal the CLI imports. Any key that is present but
144
- evaluates to `undefined`, usually a missing environment variable, is listed by path and stops the
145
- run.
146
-
147
- `graph seed` runs standalone: it never constructs or serves your `@m6d/cortex-server` — it only
148
- imports your `cortex.config.ts` (whose own imports may pull the server's modules in, inertly).
149
- Its Neo4j client, its embedder and its `GRAPH_SCHEMA` come from the graph contract the server
150
- reads the graph back with (each package vendors its own copy at pack time; the server re-exports
151
- it) — one contract, shared from both ends. Seeding stamps the schema
152
- version it wrote onto the graph; if that graph already carries a different one, the CLI says so and
153
- seeds anyway, noting that nodes from the old schema are not removed. Skew is caught on the reading
154
- side, where it matters: the server checks the stamp on its first resolve and refuses a graph it
155
- cannot read.
156
-
157
- `swagger` writes `.endpoint.ts` source whose generated block has to satisfy the server's own
158
- `EndpointDef`, so a codegen that outran the installed version is a loud type error in your
159
- `bun run check`.
160
-
161
- Your `cortex.config.ts` imports `@m6d/cortex-server` for `defineAgent`, so a project without it
162
- installed fails on the import — reported as an unloadable config, with the missing package named.
226
+ | Option | Description |
227
+ | ---------------------- | -------------------------------------------- |
228
+ | `-v, --verbose` | Print full errors and the commands being run |
229
+ | `-p, --profile <name>` | Which saved profile to use |
230
+ | `-V, --version` | Output the version number |
231
+ | `-h, --help` | Display help for command |
163
232
 
164
233
  ## Exit codes
165
234
 
166
- | Command | 0 | 1 | 2 |
167
- | --------------- | --------------------------------------------- | ----------------------------------- | ---------------------- |
168
- | `new` | Files written — even if `bun install` failed | Bad target, missing name, cancelled | — |
169
- | `swagger sync` | Wrote what it could, `MISSING` files included | Couldn't run | — |
170
- | `swagger check` | Every endpoint file matched and in sync | Couldn't run | Drift and/or `MISSING` |
171
- | `graph seed` | Everything seeded | A statement failed, or couldn't run | — |
172
-
173
- _Couldn't run_ means no config file, an unloadable config (a missing `@m6d/cortex-server` in the
174
- project reads as one), undefined values in it, an absent domains directory, or an unreachable
175
- Swagger host or Neo4j.
235
+ | Command | 0 | 1 |
236
+ | ------- | ---------------------------------------------------------- | --------------------------------------------------- |
237
+ | `new` | Files written — even if `bun install` failed | Bad target, missing name, cancelled |
238
+ | `setup` | Set up, or the server registered with no model to apply on | Not a project, or Cortex refused or was unreachable |
239
+ | `apply` | Applied, or previewed with `--dry-run` | Invalid manifest, or refused |
240
+ | others | The procedure ran | It failed, or couldn't run |
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@m6d/cortex-cli",
3
- "version": "0.12.1",
4
- "description": "Scaffold and operate Cortex servers",
3
+ "version": "0.14.0",
4
+ "description": "Scaffold Cortex projects and manage a Cortex deployment",
5
5
  "license": "MIT",
6
6
  "type": "module",
7
7
  "bin": {
@@ -24,7 +24,8 @@
24
24
  "@clack/prompts": "^1.7.0",
25
25
  "@commander-js/extra-typings": "^15.0.0",
26
26
  "commander": "^15.0.0",
27
- "picocolors": "^1.1.1"
27
+ "picocolors": "^1.1.1",
28
+ "zod": "^4.6.5"
28
29
  },
29
30
  "devDependencies": {
30
31
  "@cortex/contracts": "workspace:*",
@@ -35,7 +36,17 @@
35
36
  "access": "public"
36
37
  },
37
38
  "releaseWatchPaths": [
38
- "internal/contracts",
39
- "packages/cortex-server"
39
+ "apps/cortex",
40
+ "packages/cortex-typescript",
41
+ "internal/contracts/src/client-tools",
42
+ "internal/contracts/src/datasets",
43
+ "internal/contracts/src/egress-policy",
44
+ "internal/contracts/src/errors",
45
+ "internal/contracts/src/json",
46
+ "internal/contracts/src/manifest",
47
+ "internal/contracts/src/manifest-file",
48
+ "internal/contracts/src/server",
49
+ "internal/contracts/src/triggers",
50
+ "internal/contracts/src/wire"
40
51
  ]
41
52
  }
package/src/cli.ts CHANGED
@@ -1,16 +1,17 @@
1
1
  import { Command, Help } from "@commander-js/extra-typings";
2
2
 
3
3
  import pkg from "../package.json";
4
- import { registerCc } from "@/commands/cc";
5
- import { registerGraph } from "@/commands/graph";
4
+ import { registerApply } from "@/commands/apply";
5
+ import { registerManagement } from "@/commands/management";
6
6
  import { registerNew } from "@/commands/new";
7
- import { registerSwagger } from "@/commands/swagger";
7
+ import { registerSetup } from "@/commands/setup";
8
8
  import * as report from "@/ui/report";
9
9
 
10
10
  const program = new Command()
11
11
  .name("cortex")
12
- .description("Scaffold and operate Cortex servers.")
12
+ .description("Scaffold Cortex projects and manage a Cortex deployment.")
13
13
  .option("-v, --verbose", "Print full errors and the commands being run")
14
+ .option("-p, --profile <name>", "Which saved profile to use")
14
15
  .version(pkg.version, "-V, --version", "Output the version number")
15
16
  .helpOption("-h, --help", "Display help for command")
16
17
  // The implicit `help [command]` would print as a third, ungrouped section and
@@ -19,25 +20,31 @@ const program = new Command()
19
20
  // Commander appends ` [options]` to any command that has some. Left in, the
20
21
  // first command to grow a flag widens the whole list and the two-group screen
21
22
  // stops matching. `cortex <command> --help` lists them.
23
+ // Every command's help lists the root's options too, `--profile` among them.
22
24
  .configureHelp({
25
+ showGlobalOptions: true,
23
26
  subcommandTerm: function (cmd) {
24
27
  return new Help().subcommandTerm(cmd).replace(" [options]", "");
25
28
  },
26
29
  })
27
- .addHelpText("after", "\nRun `cortex <resource> --help` to see what you can do with one.");
30
+ .addHelpText(
31
+ "after",
32
+ "\nEvery other command comes from the Cortex you logged in to:\n`cortex <resource> <procedure>`. Run `cortex <resource> --help` to see a resource's.",
33
+ );
28
34
 
29
35
  // Each command owns its help group, so the two headings survive these files being
30
36
  // rewritten. Registration order fixes the order the groups print in.
31
37
  registerNew(program);
32
- registerSwagger(program);
33
- registerGraph(program);
34
- // The Control Center's commands come from its API, so this one may fetch
35
- // before parsing; it looks at argv to decide whether it needs to.
36
- await registerCc(program, process.argv.slice(2));
38
+ registerSetup(program);
39
+ registerApply(program);
40
+ // The management commands come from Cortex's API, so this one may fetch
41
+ // before parsing; it looks at argv to decide whether it needs to, which it
42
+ // does only when argv names none of the commands registered before it.
43
+ await registerManagement(program, process.argv.slice(2));
37
44
 
38
45
  // Commander's own errors print and exit on their own, and every failure the
39
- // commands predict goes through `report.fail`. Anything still reaching here is a
40
- // bug — in the CLI, or in the project's server — and it gets the same grammar
46
+ // commands predict goes through `report.fail`. Anything reaching here is a
47
+ // bug — in the CLI, or in Cortex — and it gets the same grammar
41
48
  // rather than a raw Bun stack dump.
42
49
  await program.parseAsync().catch(function (error: unknown) {
43
50
  const verbose = program.opts().verbose === true;