@gapi/gcli 1.8.240 → 1.8.241

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.
@@ -68,3 +68,26 @@ shared with or generated from gql-fission's copy.
68
68
  `jest.config.js` has no `moduleNameMapper` for the `~/` tsconfig path alias
69
69
  — new test files must use relative imports (e.g. `'../src/helpers'`), not
70
70
  `'~/helpers'`, or the test silently fails to resolve the module.
71
+
72
+ ## Managing a private cluster itself (scaling, topology, autoscale)
73
+
74
+ The `cluster:*` commands that change or watch ONE cluster
75
+ (`status`, `health`, `scale-events`, `cost`, `scale`,
76
+ `scale:control-planes`, `multi-node`, `single-node`, `autoscale`,
77
+ `load-balancer`) share `commands/cluster/helpers/cluster-change.ts`:
78
+ `resolveClusterTarget` (`--cluster <id>` or `--clusterName <name>`,
79
+ required), `parseIntOption`, and `runClusterChange` (mutate → print →
80
+ `--wait` via `pollUntilReady`; ending in `error` exits non-zero). Their
81
+ selections and types live in `commands/cluster/types.ts` (newer than the
82
+ hand-kept `@introspection`).
83
+
84
+ `cluster:apply` is the declarative path: the `cluster:` section of
85
+ lambforge.yaml (`ClusterDesired` in `helpers/plan.ts`, also the type of
86
+ `load-spec.ts`'s `cluster`). Keep `planClusterChanges` pure and ordered
87
+ (create | topology → workers → control planes → load balancer →
88
+ autoscale): each step is one background job and the cluster must be
89
+ `ready` before the next. A new cluster setting = a key in `ClusterDesired`,
90
+ a check in `validateDesired`, a step in the plan, a test in
91
+ `test/cluster-apply.spec.ts`, and the README "Declarative clusters" block.
92
+ The server merges partial autoscale input into the stored policy, so the
93
+ plan sends only changed keys.
package/README-CLI.md CHANGED
@@ -30,9 +30,20 @@ Commands:
30
30
  cron:delete [options] Delete cron
31
31
  cron:list [options] List of all cron jobs for project
32
32
  cluster:create [options] Provision a private Talos cluster for a project (runs in the background - takes several minutes; use --wait to block)
33
+ cluster:apply [options] Make a private cluster match the `cluster:` section of lambforge.yaml: creates it if missing, then applies topology, workers, control planes, load balancer and autoscaling
33
34
  cluster:list [options] List every private cluster this project has (it may have several - dev/stage/prod, ...)
34
35
  cluster:teardown [options] Tear down one of a project's clusters (runs in the background - use --wait to block)
35
36
  cluster:kubeconfig [options] Print (or save) a cluster's raw kubeconfig YAML - only available once it's 'ready'
37
+ cluster:status [options] Every cluster's status, agent, nodes, CPU/memory load, autoscaling and open issues (or one with --cluster)
38
+ cluster:health [options] The latest health report of a cluster's agent, with every node
39
+ cluster:scale-events [options] Manual and autoscaler scale history, newest first
40
+ cluster:cost [options] Month-to-date cost and the monthly estimate of the project's private clusters
41
+ cluster:scale [options] Set the number of worker nodes (1-10) of a multi-node cluster - billed per node-hour
42
+ cluster:scale:control-planes [options] Set the number of control-plane nodes (1, 3 or 5)
43
+ cluster:autoscale [options] Change the worker autoscaling policy - only the flags you pass change
44
+ cluster:multi-node [options] Convert a single-node cluster to dedicated worker nodes (required for autoscaling)
45
+ cluster:single-node [options] Convert a multi-node cluster back to a single node (removes the worker nodes)
46
+ cluster:load-balancer [options] Add or remove the cluster's load balancer (billed per hour while enabled)
36
47
  rabbitmq:create [options] Provision a RabbitMQ broker for a project (a project may have several)
37
48
  rabbitmq:list [options] List every RabbitMQ broker for a project
38
49
  rabbitmq:delete [options] Delete a RabbitMQ broker
@@ -508,6 +519,19 @@ Options:
508
519
  --wait Block until the cluster is ready (or errors)
509
520
  -h, --help display help for command
510
521
  
522
+ --- Subcommand: cluster:apply ---
523
+ Usage: gcli cluster:apply [options]
524
+
525
+ Make a private cluster match the `cluster:` section of lambforge.yaml: creates it if missing, then applies topology, workers, control planes, load balancer and autoscaling
526
+
527
+ Options:
528
+ -p, --project <project>
529
+ -spec, --spec <spec> Spec file (default: lambforge.yaml / cluster.yaml)
530
+ --dry-run Print the plan, change nothing
531
+ --yes Also apply steps that remove capacity or the load
532
+ balancer IP
533
+ -h, --help display help for command
534
+ 
511
535
  --- Subcommand: cluster:list ---
512
536
  Usage: gcli cluster:list [options]
513
537
 
@@ -539,6 +563,135 @@ Options:
539
563
  -o, --output <output> Write to this file instead of stdout
540
564
  -h, --help display help for command
541
565
  
566
+ --- Subcommand: cluster:status ---
567
+ Usage: gcli cluster:status [options]
568
+
569
+ Every cluster's status, agent, nodes, CPU/memory load, autoscaling and open issues (or one with --cluster)
570
+
571
+ Options:
572
+ -p, --project <project>
573
+ -c, --cluster <cluster> Cluster id (see cluster:list)
574
+ --clusterName <clusterName> Cluster name instead of --cluster
575
+ -h, --help display help for command
576
+ 
577
+ --- Subcommand: cluster:health ---
578
+ Usage: gcli cluster:health [options]
579
+
580
+ The latest health report of a cluster's agent, with every node
581
+
582
+ Options:
583
+ -p, --project <project>
584
+ -c, --cluster <cluster> Cluster id (see cluster:list)
585
+ --clusterName <clusterName> Cluster name instead of --cluster
586
+ -h, --help display help for command
587
+ 
588
+ --- Subcommand: cluster:scale-events ---
589
+ Usage: gcli cluster:scale-events [options]
590
+
591
+ Manual and autoscaler scale history, newest first
592
+
593
+ Options:
594
+ -p, --project <project>
595
+ -c, --cluster <cluster> Cluster id (see cluster:list)
596
+ --clusterName <clusterName> Cluster name instead of --cluster
597
+ --limit <limit> How many events (default 20)
598
+ -h, --help display help for command
599
+ 
600
+ --- Subcommand: cluster:cost ---
601
+ Usage: gcli cluster:cost [options]
602
+
603
+ Month-to-date cost and the monthly estimate of the project's private clusters
604
+
605
+ Options:
606
+ -p, --project <project>
607
+ -h, --help display help for command
608
+ 
609
+ --- Subcommand: cluster:scale ---
610
+ Usage: gcli cluster:scale [options]
611
+
612
+ Set the number of worker nodes (1-10) of a multi-node cluster - billed per node-hour
613
+
614
+ Options:
615
+ -p, --project <project>
616
+ -c, --cluster <cluster> Cluster id (see cluster:list)
617
+ --clusterName <clusterName> Cluster name instead of --cluster
618
+ --workers <workers> Worker nodes, 1-10
619
+ --wait Block until the cluster settles
620
+ -h, --help display help for command
621
+ 
622
+ --- Subcommand: cluster:scale:control-planes ---
623
+ Usage: gcli cluster:scale:control-planes [options]
624
+
625
+ Set the number of control-plane nodes (1, 3 or 5)
626
+
627
+ Options:
628
+ -p, --project <project>
629
+ -c, --cluster <cluster> Cluster id (see cluster:list)
630
+ --clusterName <clusterName> Cluster name instead of --cluster
631
+ --count <count> Control planes: 1, 3 or 5
632
+ --wait Block until the cluster settles
633
+ -h, --help display help for command
634
+ 
635
+ --- Subcommand: cluster:autoscale ---
636
+ Usage: gcli cluster:autoscale [options]
637
+
638
+ Change the worker autoscaling policy - only the flags you pass change
639
+
640
+ Options:
641
+ -p, --project <project>
642
+ -c, --cluster <cluster> Cluster id (see cluster:list)
643
+ --clusterName <clusterName> Cluster name instead of --cluster
644
+ --enable Turn autoscaling on (multi-node clusters only)
645
+ --disable Turn autoscaling off
646
+ --min <min> Minimum workers (1-10)
647
+ --max <max> Maximum workers (1-10)
648
+ --cpuUp <percent> Scale up at this CPU % (1-100)
649
+ --memUp <percent> Scale up at this memory % (1-100)
650
+ --cpuDown <percent> Scale down below this CPU % (1-100)
651
+ --memDown <percent> Scale down below this memory % (1-100)
652
+ --samples <n> Consecutive readings before acting (1-20)
653
+ --cooldown <minutes> Minutes between scale actions (1-1440)
654
+ -h, --help display help for command
655
+ 
656
+ --- Subcommand: cluster:multi-node ---
657
+ Usage: gcli cluster:multi-node [options]
658
+
659
+ Convert a single-node cluster to dedicated worker nodes (required for autoscaling)
660
+
661
+ Options:
662
+ -p, --project <project>
663
+ -c, --cluster <cluster> Cluster id (see cluster:list)
664
+ --clusterName <clusterName> Cluster name instead of --cluster
665
+ --workers <workers> Worker nodes, 1-10
666
+ --wait Block until the cluster settles
667
+ -h, --help display help for command
668
+ 
669
+ --- Subcommand: cluster:single-node ---
670
+ Usage: gcli cluster:single-node [options]
671
+
672
+ Convert a multi-node cluster back to a single node (removes the worker nodes)
673
+
674
+ Options:
675
+ -p, --project <project>
676
+ -c, --cluster <cluster> Cluster id (see cluster:list)
677
+ --clusterName <clusterName> Cluster name instead of --cluster
678
+ --wait Block until the cluster settles
679
+ -h, --help display help for command
680
+ 
681
+ --- Subcommand: cluster:load-balancer ---
682
+ Usage: gcli cluster:load-balancer [options]
683
+
684
+ Add or remove the cluster's load balancer (billed per hour while enabled)
685
+
686
+ Options:
687
+ -p, --project <project>
688
+ -c, --cluster <cluster> Cluster id (see cluster:list)
689
+ --clusterName <clusterName> Cluster name instead of --cluster
690
+ --enable Add the load balancer
691
+ --disable Remove the load balancer
692
+ --wait Block until the cluster settles
693
+ -h, --help display help for command
694
+ 
542
695
  --- Subcommand: rabbitmq:create ---
543
696
  Usage: gcli rabbitmq:create [options]
544
697
 
package/README.md CHANGED
@@ -11,6 +11,7 @@ Whether you are deploying scalable serverless functions, managing cloud environm
11
11
  - [Managing Infrastructure](#managing-infrastructure)
12
12
  - [Serverless Functions (Lambdas)](#serverless-functions-lambdas)
13
13
  - [AI Integration (Model Context Protocol)](#ai-integration-model-context-protocol)
14
+ - [AI agent skill](#ai-agent-skill)
14
15
  - [Local AI Models (Ollama runner)](#local-ai-models-ollama-runner)
15
16
  - [Build System](#build-system)
16
17
  - [Command Reference](#command-reference)
@@ -24,7 +25,7 @@ You can install `gcli` using a pre-built binary or via NPM.
24
25
  For a standalone installation without Node.js dependencies:
25
26
 
26
27
  ```bash
27
- curl -L "https://github.com/Stradivario/gapi/releases/download/v1.8.198/gcli-linux" -o ~/.local/bin/gcli
28
+ curl -L "https://github.com/Stradivario/gapi/releases/latest/download/gcli-linux" -o ~/.local/bin/gcli
28
29
  chmod +x ~/.local/bin/gcli
29
30
  ```
30
31
 
@@ -95,6 +96,10 @@ gcli environment:get --name 'staging'
95
96
  # (omit --clusterId to use the shared cluster - the default). Immutable
96
97
  # after creation.
97
98
  gcli environment:create --name 'staging' --clusterId '<clusterId>'
99
+
100
+ # Resize it, or remove it
101
+ gcli environment:update --name 'staging' --maxCpu 800 --maxMemory 1024
102
+ gcli environment:delete --name 'staging'
98
103
  ```
99
104
 
100
105
  ### Private Clusters
@@ -119,17 +124,79 @@ gcli cluster:kubeconfig --cluster '<clusterId>' --output ./kubeconfig.yaml
119
124
  gcli cluster:teardown --cluster '<clusterId>' --wait
120
125
  ```
121
126
 
122
- `cluster.yaml`:
127
+ Scale, reshape and watch a cluster (the same operations as the dashboard's
128
+ cluster page). Changes run in the background; `--wait` blocks until the
129
+ cluster is `ready` again. `--clusterName <name>` works instead of
130
+ `--cluster <id>` everywhere.
131
+
132
+ ```bash
133
+ # Health, load, autoscaling and open issues of every cluster (or one)
134
+ gcli cluster:status [--cluster '<clusterId>']
135
+ gcli cluster:health --cluster '<clusterId>' # latest agent report, per node
136
+ gcli cluster:scale-events --cluster '<clusterId>' # manual + autoscaler history
137
+ gcli cluster:cost # month-to-date + monthly estimate
138
+
139
+ # Worker nodes (1-10, billed per node-hour) and control planes (1, 3 or 5)
140
+ gcli cluster:scale --cluster '<clusterId>' --workers 3 --wait
141
+ gcli cluster:scale:control-planes --cluster '<clusterId>' --count 3 --wait
142
+
143
+ # Topology: dedicated workers (needed for autoscaling) or back to one node
144
+ gcli cluster:multi-node --cluster '<clusterId>' --workers 2 --wait
145
+ gcli cluster:single-node --cluster '<clusterId>' --wait
146
+
147
+ # Autoscaling - only the flags you pass change
148
+ gcli cluster:autoscale --cluster '<clusterId>' --enable --min 2 --max 6
149
+ gcli cluster:autoscale --cluster '<clusterId>' --cpuUp 75 --cpuDown 25 --cooldown 20
150
+ gcli cluster:autoscale --cluster '<clusterId>' --disable
151
+
152
+ # Load balancer (billed per hour while enabled)
153
+ gcli cluster:load-balancer --cluster '<clusterId>' --enable --wait
154
+ ```
155
+
156
+ #### Declarative clusters (`cluster:apply`)
157
+
158
+ Write the cluster you want in the `cluster:` section of `lambforge.yaml`
159
+ (or a standalone `cluster.yaml`) and let `cluster:apply` make it so: it
160
+ creates the cluster when it doesn't exist, then applies topology, workers,
161
+ control planes, the load balancer and autoscaling - one change at a time,
162
+ waiting for the cluster to be ready between them. Keys you leave out are
163
+ left as they are.
123
164
 
124
165
  ```yaml
125
- name: prod
126
- imageId: <hcloud-image-id>
127
- serverType: cpx22
128
- location: nbg1
129
- workers: 2
130
- singleNode: false
166
+ cluster:
167
+ name: prod
168
+ # needed only to create it
169
+ imageId: <hcloud-image-id>
170
+ serverType: cpx22
171
+ location: nbg1
172
+ # desired state
173
+ singleNode: false # true = one node runs everything (cheapest, dev/stage)
174
+ workers: 3 # 1-10; only the initial size while autoscale is enabled
175
+ controlPlanes: 1 # 1, 3 or 5
176
+ loadBalancer: true
177
+ autoscale:
178
+ enabled: true # needs singleNode: false
179
+ minWorkers: 2
180
+ maxWorkers: 6
181
+ cpuScaleUpPercent: 70 # scale up above this (of allocatable)
182
+ memScaleUpPercent: 70
183
+ cpuScaleDownPercent: 30
184
+ memScaleDownPercent: 30
185
+ samplesToScale: 3 # consecutive readings before acting
186
+ cooldownMinutes: 15
187
+ ```
188
+
189
+ ```bash
190
+ gcli cluster:apply --dry-run # print the plan, change nothing
191
+ gcli cluster:apply # apply it
192
+ gcli cluster:apply --yes # also steps that remove capacity or the LB IP
193
+ gcli cluster:apply --spec cluster.yaml
131
194
  ```
132
195
 
196
+ Steps that remove capacity or release the load balancer's IP (going back to
197
+ `singleNode: true`, `loadBalancer: false`) are skipped unless you pass
198
+ `--yes`. Nodes and the load balancer are billed per started hour.
199
+
133
200
  ### RabbitMQ Brokers
134
201
 
135
202
  A project may have several RabbitMQ brokers, each optionally scoped to one of its private clusters.
@@ -285,15 +352,25 @@ options:
285
352
  external: []
286
353
  ```
287
354
 
288
- The same file can also carry `cluster:`, `rabbitmq:`, and `plugin:` sections, read by `cluster:create`, `rabbitmq:create`, and `plugin:install` respectively (each also accepts its own dedicated `--spec` file, e.g. `cluster.yaml`, if you'd rather keep them separate):
355
+ The same file can also carry `cluster:`, `rabbitmq:`, `plugin:` and `triggers:` sections, read by `cluster:apply` / `cluster:create`, `rabbitmq:create`, `plugin:install` and `cron:create` respectively (each also accepts its own dedicated `--spec` file, e.g. `cluster.yaml`, if you'd rather keep them separate):
289
356
 
290
357
  ```yaml
291
- cluster:
358
+ cluster: # every key: see "Declarative clusters" above
292
359
  name: prod
293
360
  imageId: <hcloud-image-id>
294
361
  serverType: cpx22
295
362
  location: nbg1
296
363
  workers: 2
364
+ loadBalancer: false
365
+ autoscale:
366
+ enabled: true
367
+ minWorkers: 2
368
+ maxWorkers: 5
369
+
370
+ triggers:
371
+ time:
372
+ triggerName: nightly
373
+ cron: '0 2 * * *' # cron syntax or @every 5m / @daily
297
374
 
298
375
  rabbitmq:
299
376
  name: events-broker
@@ -361,7 +438,7 @@ gcli lambda:create --project <projectId> --spec ./lambforge.yaml
361
438
  `--mcp` and `--mcpGraph <name>` are also available as CLI flags; the array fields
362
439
  (`mcpOperations`, `mcpHeaders`, `mcpForwardHeaders`) are spec-only. A full annotated example lives in
363
440
  [`example/mcp/lambforge.yaml`](./example/mcp/lambforge.yaml). Client connects at
364
- `https://<host>/<projectId>/<route>/mcp`.
441
+ `https://<host>/<projectId>/<route>` (with `route: mcp`: `https://<host>/<projectId>/mcp`).
365
442
 
366
443
  ### Conditional Configuration (Environment-Aware Specs)
367
444
 
@@ -638,10 +715,23 @@ gcli environment:update
638
715
 
639
716
  ### Function Lifecycle
640
717
 
718
+ - **List**: `gcli lambda:list` (`--clusterName <name>` for one cluster's lambdas)
641
719
  - **Update**: `gcli lambda:update --name 'my-function' --file ./new-index.ts`
642
720
  - **Delete**: `gcli lambda:delete --name 'my-function'`
643
721
  - **Get Details**: `gcli lambda:get --name 'my-function'`
644
722
 
723
+ ### Schedules (cron)
724
+
725
+ One time trigger per lambda. The platform calls the lambda's root with a
726
+ GET and an `X-Fission-Timer-Name` header.
727
+
728
+ ```bash
729
+ gcli cron:create --lambdaName 'my-function' --triggerName nightly --cron '0 2 * * *'
730
+ gcli cron:create # reads triggers.time (and function.name) from lambforge.yaml
731
+ gcli cron:list
732
+ gcli cron:delete --lambdaName 'my-function'
733
+ ```
734
+
645
735
  ### Monitoring & Testing
646
736
 
647
737
  Debug your functions directly from the terminal.
@@ -715,6 +805,33 @@ To use this with Claude Desktop or other MCP-compatible tools, add the following
715
805
  }
716
806
  ```
717
807
 
808
+ ### AI agent skill
809
+
810
+ Give a coding agent (Claude Code and other agents that read skills) the
811
+ whole platform. Paste this into the agent:
812
+
813
+ ```text
814
+ Install the Lambforge skill from https://lambforge.com/skills/platform.md and follow its setup.
815
+ ```
816
+
817
+ Or by hand for Claude Code:
818
+
819
+ ```bash
820
+ mkdir -p ~/.claude/skills/lambforge && cd ~/.claude/skills/lambforge
821
+ for f in $(curl -fsSL https://lambforge.com/skills/files.txt); do
822
+ curl -fsSLO "https://lambforge.com/skills/$f"
823
+ done
824
+ cp platform.md SKILL.md
825
+ claude mcp add --scope user lambforge -- gcli mcp:start
826
+ ```
827
+
828
+ `platform.md` covers setup (install gcli, the login command you run from
829
+ Profile -> CLI - the agent never handles your token, `gcli mcp:start`) and
830
+ the rules, and indexes topic files the agent reads on demand: gcli, MCP
831
+ tools, deploy, REST code and testing, GraphQL and federation, websites,
832
+ MCP servers, secrets, cron and queues, clusters and plugins, operations and
833
+ costs, memory and plans. Source: gql-fission `src/skills/`.
834
+
718
835
  ## Local AI Models (Ollama runner)
719
836
 
720
837
  Use models running on your own machine in the Lambforge chat - including
@@ -0,0 +1,31 @@
1
+ ## 2026-10-19 - dedicated-platform-cluster: Cluster scaling, topology, load balancer and health commands (cluster:status, health, scale, autoscale, ...)
2
+
3
+ **Feature:** dedicated-platform-cluster · **Type:** feat
4
+
5
+ - New commands (the dashboard cluster page's actions, same
6
+ cluster-provisioner operations): `cluster:status`, `cluster:health`,
7
+ `cluster:scale-events`, `cluster:cost`, `cluster:scale --workers`,
8
+ `cluster:scale:control-planes --count`, `cluster:multi-node`,
9
+ `cluster:single-node`, `cluster:autoscale` (partial: only the given
10
+ flags change), `cluster:load-balancer --enable|--disable`. All take
11
+ `--cluster <id>` or `--clusterName <name>`; mutations take `--wait`
12
+ (polls until ready; ending in `error` exits non-zero with the reason).
13
+ - `cluster:apply [--spec] [--dry-run] [--yes]`: the `cluster:` section of
14
+ lambforge.yaml / cluster.yaml is now a desired state (new keys
15
+ `controlPlanes`, `loadBalancer`, `autoscale.*`; `singleNode`, `workers`
16
+ as before). It creates the cluster when missing (in the desired shape)
17
+ and otherwise plans and applies topology → workers → control planes →
18
+ load balancer → autoscale, waiting for `ready` between jobs; destructive
19
+ steps need `--yes`. `cluster:create` also passes `controlPlanes` and
20
+ `loadBalancer` from the spec now.
21
+ - Client-side checks mirror the server's bounds (workers 1-10, control
22
+ planes 1/3/5, autoscale ranges) so a bad value fails before any request.
23
+ - `README.md` Private Clusters section, regenerated `README-CLI.md`.
24
+ - **Test:** `npx jest --coverage=false` (71 tests; new
25
+ `test/cluster-scaling.spec.ts`, `test/cluster-apply.spec.ts` (the plan),
26
+ `test/cluster-apply-command.spec.ts` (dry-run, `--yes`, create, refusals)).
27
+ - **Debug:** slice doc `docs/features/dedicated-platform-cluster.md`.
28
+ - **Verification:** jest 71/71; the built binary's `cluster:apply` read a
29
+ real lambforge.yaml and rejected `controlPlanes: 2` before any request; tsc + eslint clean; `npm run build` and
30
+ `--help` checked for every command (`release/index.js` restored after,
31
+ not a release).
@@ -0,0 +1,17 @@
1
+ ## 2026-10-19 - lambforge-agent-skill: README points to the Lambforge agent skill (gcli + mcp:start for AI agents)
2
+
3
+ **Feature:** lambforge-agent-skill · **Type:** docs
4
+
5
+ - README.md "AI agent skill" (under AI Integration): the prompt to paste into
6
+ an agent (https://lambforge.com/skills/platform.md), the manual Claude Code
7
+ install (every file from `files.txt`, `platform.md` copied to `SKILL.md`,
8
+ `claude mcp add --scope user lambforge -- gcli mcp:start`), and what the
9
+ topic files cover. The skill lives in gql-fission `src/skills/` (canonical
10
+ doc there).
11
+ - `docs/features/lambforge-agent-skill.md`: which gcli commands the skill
12
+ quotes - change them, update SKILL.md in the same change.
13
+ - **Test:** none (docs); the commands it lists were checked with
14
+ `node release/index.js <command> --help`.
15
+ - **Debug:** an agent runs a gcli command that fails → compare SKILL.md with
16
+ `gcli <command> --help`.
17
+ - **Verification:** no code change.
@@ -0,0 +1,21 @@
1
+ ## 2026-10-19 - repo: cron:create honours --cron/--triggerName; README brought up to date with every command
2
+
3
+ **Feature:** repo · **Type:** fix
4
+
5
+ - `cron:create` declared `--cron` and `--triggerName` but only read them
6
+ from the spec (`triggers.time` of lambforge.yaml / cron.yaml), so the
7
+ documented `gcli cron:create --lambdaName x --triggerName nightly --cron
8
+ '0 2 * * *'` sent an empty schedule. Flags now win, the spec fills gaps,
9
+ and a missing schedule is a clear error before any request.
10
+ - README: binary install from `releases/latest` (was pinned to v1.8.198);
11
+ `environment:update/delete`, `lambda:list` and a "Schedules (cron)"
12
+ section (the commands were missing); `triggers:` in the unified
13
+ lambforge.yaml; the MCP client URL is `https://<host>/<projectId>/<route>`
14
+ (the `/mcp` suffix was wrong - see example/mcp/lambforge.yaml); the
15
+ declarative cluster section. Every command registered in `src/commands`
16
+ now appears in README.md.
17
+ - **Test:** `npx jest --coverage=false test/cron-create.spec.ts` (flags,
18
+ flags over yaml, missing schedule).
19
+ - **Debug:** a cron with an empty schedule → an older gcli; upgrade.
20
+ - **Verification:** jest 71/71; a script compared the commands registered in
21
+ `src/commands` against README.md (no command missing).
@@ -31,3 +31,5 @@ Outline (drop sections that don't apply):
31
31
  | Feature | Doc | Notes |
32
32
  |---|---|---|
33
33
  | `local-ai-runners` | [local-ai-runners.md](local-ai-runners.md) | `runner:*` commands; canonical doc in graphql-server |
34
+ | `lambforge-agent-skill` | [lambforge-agent-skill.md](lambforge-agent-skill.md) | The agent skill that teaches gcli + `mcp:start`; canonical doc in gql-fission |
35
+ | `dedicated-platform-cluster` | [dedicated-platform-cluster.md](dedicated-platform-cluster.md) | `cluster:status/health/scale/autoscale/...` commands; canonical doc in lambforge-agent |
@@ -0,0 +1,70 @@
1
+ # dedicated-platform-cluster (gcli slice)
2
+
3
+ **Canonical doc:** `lambforge-agent/docs/features/dedicated-platform-cluster.md`
4
+ · **Since:** 2026-10-19 (cluster scaling and health commands)
5
+
6
+ The cluster page's scaling, topology, load balancer and health actions as
7
+ commands (cluster-provisioner operations, the same ones gql-fission's
8
+ `core/services/cluster/*.graphql` use; every one is USER-enabled with
9
+ `isMemberOrProjectOwner`):
10
+
11
+ | Command | Operation |
12
+ |---|---|
13
+ | `cluster:status [--cluster]` | `projectClustersOverview` (status, agent, nodes, load, autoscale, issues) |
14
+ | `cluster:health --cluster` | `clusterHealth(limit: 1)` - latest agent report + nodes |
15
+ | `cluster:scale-events --cluster [--limit]` | `clusterScaleEvents` |
16
+ | `cluster:cost` | `projectClustersOverview` (`monthToDate`, `estimatedMonthlyCostEur`) |
17
+ | `cluster:scale --workers 1-10 [--wait]` | `scaleProjectCluster` |
18
+ | `cluster:scale:control-planes --count 1/3/5 [--wait]` | `scaleControlPlanesProjectCluster` |
19
+ | `cluster:multi-node --workers [--wait]` / `cluster:single-node [--wait]` | `migrateToMultiNodeProjectCluster` / `revertToSingleNodeProjectCluster` |
20
+ | `cluster:autoscale [--enable/--disable] [--min --max --cpuUp --memUp --cpuDown --memDown --samples --cooldown]` | `updateProjectClusterAutoscale` - partial: the server merges it into the stored policy and validates (min <= max, scale-down below scale-up, single-node cannot autoscale) |
21
+ | `cluster:load-balancer --enable/--disable [--wait]` | `enable/disableLoadBalancerProjectCluster` |
22
+ | `cluster:apply [--spec] [--dry-run] [--yes]` | reconciles the `cluster:` section of lambforge.yaml: `projectClusters` (current) → plan → provision / topology / scale / control planes / load balancer / autoscale, one job at a time, waiting for `ready` between them |
23
+
24
+ ## Declarative clusters (`cluster:apply`)
25
+
26
+ `cluster:` keys: `name` (identity), `imageId` / `serverType` / `location`
27
+ (create only), `singleNode`, `workers` (1-10), `controlPlanes` (1/3/5),
28
+ `loadBalancer`, `autoscale.{enabled,minWorkers,maxWorkers,cpuScaleUpPercent,
29
+ memScaleUpPercent,cpuScaleDownPercent,memScaleDownPercent,samplesToScale,
30
+ cooldownMinutes}`. Missing keys are left alone.
31
+
32
+ - `helpers/plan.ts` `planClusterChanges(current, desired)` is pure (unit
33
+ tested): create in the desired shape (workers, control planes, load
34
+ balancer at provision time) then autoscale; otherwise topology → workers
35
+ → control planes → load balancer → autoscale (only the changed keys).
36
+ - `workers` is skipped while `autoscale.enabled` (the autoscaler owns it);
37
+ converting to multi-node already creates the workers.
38
+ - Destructive steps (to single-node, removing the load balancer) need
39
+ `--yes`; without it they are printed and skipped.
40
+ - `validateDesired` mirrors the server's bounds; a cluster that is not
41
+ `ready` is refused (apply again once it settles).
42
+
43
+ ## Files
44
+
45
+ | Path | Responsibility |
46
+ |---|---|
47
+ | `src/commands/cluster/index.ts` | registration (`--cluster` / `--clusterName` on every one) |
48
+ | `src/commands/cluster/{status,health,scale-events,cost,scale,scale-control-planes,autoscale,multi-node,single-node,load-balancer}.ts` | actions |
49
+ | `src/commands/cluster/helpers/cluster-change.ts` | target resolution, int validation, mutate → print → `--wait` (`pollUntilReady`; ends in `error` → non-zero exit) |
50
+ | `src/commands/cluster/types.ts` | local types + selections (newer than `@introspection`) |
51
+ | `src/services/gql-client.ts` | the API calls |
52
+
53
+ ## How to test
54
+
55
+ `npx jest --coverage=false test/cluster-scaling.spec.ts`; manually against a
56
+ project with a private cluster: `gcli cluster:status`, then
57
+ `gcli cluster:scale --clusterName <n> --workers 2 --wait`.
58
+
59
+ ## How to debug
60
+
61
+ | Symptom | Look at |
62
+ |---|---|
63
+ | "Pass --cluster <id> or --clusterName" | no cluster given; `gcli cluster:list` |
64
+ | autoscale refused | the server's message: single-node clusters must `cluster:multi-node` first; external clusters cannot autoscale |
65
+ | `--wait` ends in error | `gcli cluster:list` (status + error), the dashboard's cluster page |
66
+
67
+ ## Not in the CLI yet
68
+
69
+ Resource migration between clusters (`migrateResourcesToCluster` + status /
70
+ retry), Fission options, the cluster agent install/rotate - dashboard only.
@@ -0,0 +1,22 @@
1
+ # lambforge-agent-skill (gcli slice)
2
+
3
+ **Canonical doc:** `gql-fission/docs/features/lambforge-agent-skill.md` ·
4
+ **Since:** 2026-10-19
5
+
6
+ The Lambforge agent skill (entry https://lambforge.com/skills/platform.md,
7
+ topic files next to it; source in gql-fission `src/skills/`) teaches AI
8
+ agents to drive this CLI. `cli.md` lists every command, and `platform.md`,
9
+ `deploy.md`, `events.md`, `clusters.md` and `agents.md` quote gcli exactly:
10
+
11
+ - install: `npm i -g @gapi/gcli` (or `npx @gapi/gcli`);
12
+ - login: the command from Profile -> CLI (`login --token --key --url
13
+ --uploadUrl`), run by the human;
14
+ - `project:list` / `project:use`;
15
+ - `mcp:start` without `--url` (proxy to `<login url>/mcp`, token refresh on
16
+ 401/403) as the MCP server: `claude mcp add --scope user lambforge -- gcli mcp:start`;
17
+ - the `lambda:*`, `environment:*`, `cron:*`, `cluster:*`, `rabbitmq:*`,
18
+ `plugin:*`, `build`, `start` commands and flags it lists.
19
+
20
+ **When you change any of those commands, flags or `mcp:start`, update
21
+ the skill files in gql-fission in the same change** - agents copy it verbatim.
22
+ README.md "AI agent skill" points users to it.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@gapi/gcli",
3
- "version": "1.8.240",
3
+ "version": "1.8.241",
4
4
  "repository": {
5
5
  "type": "git",
6
6
  "url": "https://github.com/Stradivario/gapi.git"