@gapi/gcli 1.8.240 → 1.8.242

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
@@ -29,10 +29,25 @@ Commands:
29
29
  cron:create [options] Create cron
30
30
  cron:delete [options] Delete cron
31
31
  cron:list [options] List of all cron jobs for project
32
+ mq-trigger:list [options] List the message-queue triggers of a project
33
+ mq-trigger:create [options] Run a lambda for every message on a RabbitMQ queue
34
+ mq-trigger:update [options] Change a message-queue trigger (same flags as create)
35
+ mq-trigger:delete [options] Delete a message-queue trigger
32
36
  cluster:create [options] Provision a private Talos cluster for a project (runs in the background - takes several minutes; use --wait to block)
37
+ 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
38
  cluster:list [options] List every private cluster this project has (it may have several - dev/stage/prod, ...)
34
39
  cluster:teardown [options] Tear down one of a project's clusters (runs in the background - use --wait to block)
35
40
  cluster:kubeconfig [options] Print (or save) a cluster's raw kubeconfig YAML - only available once it's 'ready'
41
+ cluster:status [options] Every cluster's status, agent, nodes, CPU/memory load, autoscaling and open issues (or one with --cluster)
42
+ cluster:health [options] The latest health report of a cluster's agent, with every node
43
+ cluster:scale-events [options] Manual and autoscaler scale history, newest first
44
+ cluster:cost [options] Month-to-date cost and the monthly estimate of the project's private clusters
45
+ cluster:scale [options] Set the number of worker nodes (1-10) of a multi-node cluster - billed per node-hour
46
+ cluster:scale:control-planes [options] Set the number of control-plane nodes (1, 3 or 5)
47
+ cluster:autoscale [options] Change the worker autoscaling policy - only the flags you pass change
48
+ cluster:multi-node [options] Convert a single-node cluster to dedicated worker nodes (required for autoscaling)
49
+ cluster:single-node [options] Convert a multi-node cluster back to a single node (removes the worker nodes)
50
+ cluster:load-balancer [options] Add or remove the cluster's load balancer (billed per hour while enabled)
36
51
  rabbitmq:create [options] Provision a RabbitMQ broker for a project (a project may have several)
37
52
  rabbitmq:list [options] List every RabbitMQ broker for a project
38
53
  rabbitmq:delete [options] Delete a RabbitMQ broker
@@ -491,6 +506,69 @@ Options:
491
506
  -p, --project <project>
492
507
  -h, --help display help for command
493
508
  
509
+ --- Subcommand: mq-trigger:list ---
510
+ Usage: gcli mq-trigger:list [options]
511
+
512
+ List the message-queue triggers of a project
513
+
514
+ Options:
515
+ -p, --project <project>
516
+ -h, --help display help for command
517
+ 
518
+ --- Subcommand: mq-trigger:create ---
519
+ Usage: gcli mq-trigger:create [options]
520
+
521
+ Run a lambda for every message on a RabbitMQ queue
522
+
523
+ Options:
524
+ -p, --project <project>
525
+ -n, --name <name> Trigger name
526
+ -l, --lambda <lambda> Lambda the trigger runs per message
527
+ --request-topic <queue> Queue the trigger consumes
528
+ --response-topic <queue> Queue for the lambda response
529
+ --error-topic <queue> Queue for failed messages
530
+ --broker <rabbitMqId> RabbitMQ broker id (see rabbitmq:list) - needed
531
+ when several brokers share queue names
532
+ --max-retries <n>
533
+ --cool-down-period <seconds>
534
+ --polling-interval <seconds>
535
+ --min-replicas <n>
536
+ --max-replicas <n>
537
+ --threshold <n> Messages per replica before scaling out
538
+ -h, --help display help for command
539
+ 
540
+ --- Subcommand: mq-trigger:update ---
541
+ Usage: gcli mq-trigger:update [options]
542
+
543
+ Change a message-queue trigger (same flags as create)
544
+
545
+ Options:
546
+ -p, --project <project>
547
+ -n, --name <name> Trigger name
548
+ -l, --lambda <lambda> Lambda the trigger runs per message
549
+ --request-topic <queue> Queue the trigger consumes
550
+ --response-topic <queue> Queue for the lambda response
551
+ --error-topic <queue> Queue for failed messages
552
+ --broker <rabbitMqId> RabbitMQ broker id (see rabbitmq:list) - needed
553
+ when several brokers share queue names
554
+ --max-retries <n>
555
+ --cool-down-period <seconds>
556
+ --polling-interval <seconds>
557
+ --min-replicas <n>
558
+ --max-replicas <n>
559
+ --threshold <n> Messages per replica before scaling out
560
+ -h, --help display help for command
561
+ 
562
+ --- Subcommand: mq-trigger:delete ---
563
+ Usage: gcli mq-trigger:delete [options]
564
+
565
+ Delete a message-queue trigger
566
+
567
+ Options:
568
+ -p, --project <project>
569
+ -n, --name <name> Trigger name
570
+ -h, --help display help for command
571
+ 
494
572
  --- Subcommand: cluster:create ---
495
573
  Usage: gcli cluster:create [options]
496
574
 
@@ -508,6 +586,19 @@ Options:
508
586
  --wait Block until the cluster is ready (or errors)
509
587
  -h, --help display help for command
510
588
  
589
+ --- Subcommand: cluster:apply ---
590
+ Usage: gcli cluster:apply [options]
591
+
592
+ 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
593
+
594
+ Options:
595
+ -p, --project <project>
596
+ -spec, --spec <spec> Spec file (default: lambforge.yaml / cluster.yaml)
597
+ --dry-run Print the plan, change nothing
598
+ --yes Also apply steps that remove capacity or the load
599
+ balancer IP
600
+ -h, --help display help for command
601
+ 
511
602
  --- Subcommand: cluster:list ---
512
603
  Usage: gcli cluster:list [options]
513
604
 
@@ -539,6 +630,135 @@ Options:
539
630
  -o, --output <output> Write to this file instead of stdout
540
631
  -h, --help display help for command
541
632
  
633
+ --- Subcommand: cluster:status ---
634
+ Usage: gcli cluster:status [options]
635
+
636
+ Every cluster's status, agent, nodes, CPU/memory load, autoscaling and open issues (or one with --cluster)
637
+
638
+ Options:
639
+ -p, --project <project>
640
+ -c, --cluster <cluster> Cluster id (see cluster:list)
641
+ --clusterName <clusterName> Cluster name instead of --cluster
642
+ -h, --help display help for command
643
+ 
644
+ --- Subcommand: cluster:health ---
645
+ Usage: gcli cluster:health [options]
646
+
647
+ The latest health report of a cluster's agent, with every node
648
+
649
+ Options:
650
+ -p, --project <project>
651
+ -c, --cluster <cluster> Cluster id (see cluster:list)
652
+ --clusterName <clusterName> Cluster name instead of --cluster
653
+ -h, --help display help for command
654
+ 
655
+ --- Subcommand: cluster:scale-events ---
656
+ Usage: gcli cluster:scale-events [options]
657
+
658
+ Manual and autoscaler scale history, newest first
659
+
660
+ Options:
661
+ -p, --project <project>
662
+ -c, --cluster <cluster> Cluster id (see cluster:list)
663
+ --clusterName <clusterName> Cluster name instead of --cluster
664
+ --limit <limit> How many events (default 20)
665
+ -h, --help display help for command
666
+ 
667
+ --- Subcommand: cluster:cost ---
668
+ Usage: gcli cluster:cost [options]
669
+
670
+ Month-to-date cost and the monthly estimate of the project's private clusters
671
+
672
+ Options:
673
+ -p, --project <project>
674
+ -h, --help display help for command
675
+ 
676
+ --- Subcommand: cluster:scale ---
677
+ Usage: gcli cluster:scale [options]
678
+
679
+ Set the number of worker nodes (1-10) of a multi-node cluster - billed per node-hour
680
+
681
+ Options:
682
+ -p, --project <project>
683
+ -c, --cluster <cluster> Cluster id (see cluster:list)
684
+ --clusterName <clusterName> Cluster name instead of --cluster
685
+ --workers <workers> Worker nodes, 1-10
686
+ --wait Block until the cluster settles
687
+ -h, --help display help for command
688
+ 
689
+ --- Subcommand: cluster:scale:control-planes ---
690
+ Usage: gcli cluster:scale:control-planes [options]
691
+
692
+ Set the number of control-plane nodes (1, 3 or 5)
693
+
694
+ Options:
695
+ -p, --project <project>
696
+ -c, --cluster <cluster> Cluster id (see cluster:list)
697
+ --clusterName <clusterName> Cluster name instead of --cluster
698
+ --count <count> Control planes: 1, 3 or 5
699
+ --wait Block until the cluster settles
700
+ -h, --help display help for command
701
+ 
702
+ --- Subcommand: cluster:autoscale ---
703
+ Usage: gcli cluster:autoscale [options]
704
+
705
+ Change the worker autoscaling policy - only the flags you pass change
706
+
707
+ Options:
708
+ -p, --project <project>
709
+ -c, --cluster <cluster> Cluster id (see cluster:list)
710
+ --clusterName <clusterName> Cluster name instead of --cluster
711
+ --enable Turn autoscaling on (multi-node clusters only)
712
+ --disable Turn autoscaling off
713
+ --min <min> Minimum workers (1-10)
714
+ --max <max> Maximum workers (1-10)
715
+ --cpuUp <percent> Scale up at this CPU % (1-100)
716
+ --memUp <percent> Scale up at this memory % (1-100)
717
+ --cpuDown <percent> Scale down below this CPU % (1-100)
718
+ --memDown <percent> Scale down below this memory % (1-100)
719
+ --samples <n> Consecutive readings before acting (1-20)
720
+ --cooldown <minutes> Minutes between scale actions (1-1440)
721
+ -h, --help display help for command
722
+ 
723
+ --- Subcommand: cluster:multi-node ---
724
+ Usage: gcli cluster:multi-node [options]
725
+
726
+ Convert a single-node cluster to dedicated worker nodes (required for autoscaling)
727
+
728
+ Options:
729
+ -p, --project <project>
730
+ -c, --cluster <cluster> Cluster id (see cluster:list)
731
+ --clusterName <clusterName> Cluster name instead of --cluster
732
+ --workers <workers> Worker nodes, 1-10
733
+ --wait Block until the cluster settles
734
+ -h, --help display help for command
735
+ 
736
+ --- Subcommand: cluster:single-node ---
737
+ Usage: gcli cluster:single-node [options]
738
+
739
+ Convert a multi-node cluster back to a single node (removes the worker nodes)
740
+
741
+ Options:
742
+ -p, --project <project>
743
+ -c, --cluster <cluster> Cluster id (see cluster:list)
744
+ --clusterName <clusterName> Cluster name instead of --cluster
745
+ --wait Block until the cluster settles
746
+ -h, --help display help for command
747
+ 
748
+ --- Subcommand: cluster:load-balancer ---
749
+ Usage: gcli cluster:load-balancer [options]
750
+
751
+ Add or remove the cluster's load balancer (billed per hour while enabled)
752
+
753
+ Options:
754
+ -p, --project <project>
755
+ -c, --cluster <cluster> Cluster id (see cluster:list)
756
+ --clusterName <clusterName> Cluster name instead of --cluster
757
+ --enable Add the load balancer
758
+ --disable Remove the load balancer
759
+ --wait Block until the cluster settles
760
+ -h, --help display help for command
761
+ 
542
762
  --- Subcommand: rabbitmq:create ---
543
763
  Usage: gcli rabbitmq:create [options]
544
764
 
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
 
@@ -46,6 +47,20 @@ For automated pipelines (e.g., GitHub Actions), you can use `npx` with a long-li
46
47
  run: npx gcli login --ci --token ${{ secrets.GCLI_AUTH_TOKEN }}
47
48
  ```
48
49
 
50
+ Create the token in the dashboard (Project → CI/CD) with only the permissions the pipeline needs. Every project command has a permission:
51
+
52
+ | Permission | Commands |
53
+ |---|---|
54
+ | Lambdas: read / deploy / create / delete | `lambda:get/list/log/build:log/test`, `lambda:update`, `lambda:create`, `lambda:delete` |
55
+ | Environments: read / write / delete | `environment:list/get`, `environment:create/update`, `environment:delete` |
56
+ | Schedules: read / write | `cron:list`, `cron:create/delete` |
57
+ | RabbitMQ: read / install / uninstall | `rabbitmq:list`, `rabbitmq:create`, `rabbitmq:delete` |
58
+ | Queue triggers: read / manage | `mq-trigger:list`, `mq-trigger:create/update/delete` |
59
+ | Plugins: read / install | `plugin:list/installed`, `plugin:install/uninstall` |
60
+ | Clusters: read / scale / create / tear down / kubeconfig | `cluster:list/status/health/scale-events/cost`, `cluster:scale/autoscale/multi-node/single-node/load-balancer/apply`, `cluster:create/apply`, `cluster:teardown`, `cluster:kubeconfig` |
61
+
62
+ A token can also be limited to some lambdas (lambda, schedule and queue-trigger commands). Typical tokens: *Deploy only* (`lambda:update`), or *DevOps (clusters)* for an infra repo that runs `gcli cluster:apply`. A command the token may not run fails with `ci-token-missing-scope: <operation> needs <permission>`. `runner:*` and `project:list` are personal and not available to CI tokens.
63
+
49
64
  ## Authentication
50
65
 
51
66
  Before interacting with the platform, you must authenticate. You can log in using an API key or a personal access token.
@@ -95,6 +110,10 @@ gcli environment:get --name 'staging'
95
110
  # (omit --clusterId to use the shared cluster - the default). Immutable
96
111
  # after creation.
97
112
  gcli environment:create --name 'staging' --clusterId '<clusterId>'
113
+
114
+ # Resize it, or remove it
115
+ gcli environment:update --name 'staging' --maxCpu 800 --maxMemory 1024
116
+ gcli environment:delete --name 'staging'
98
117
  ```
99
118
 
100
119
  ### Private Clusters
@@ -119,17 +138,79 @@ gcli cluster:kubeconfig --cluster '<clusterId>' --output ./kubeconfig.yaml
119
138
  gcli cluster:teardown --cluster '<clusterId>' --wait
120
139
  ```
121
140
 
122
- `cluster.yaml`:
141
+ Scale, reshape and watch a cluster (the same operations as the dashboard's
142
+ cluster page). Changes run in the background; `--wait` blocks until the
143
+ cluster is `ready` again. `--clusterName <name>` works instead of
144
+ `--cluster <id>` everywhere.
145
+
146
+ ```bash
147
+ # Health, load, autoscaling and open issues of every cluster (or one)
148
+ gcli cluster:status [--cluster '<clusterId>']
149
+ gcli cluster:health --cluster '<clusterId>' # latest agent report, per node
150
+ gcli cluster:scale-events --cluster '<clusterId>' # manual + autoscaler history
151
+ gcli cluster:cost # month-to-date + monthly estimate
152
+
153
+ # Worker nodes (1-10, billed per node-hour) and control planes (1, 3 or 5)
154
+ gcli cluster:scale --cluster '<clusterId>' --workers 3 --wait
155
+ gcli cluster:scale:control-planes --cluster '<clusterId>' --count 3 --wait
156
+
157
+ # Topology: dedicated workers (needed for autoscaling) or back to one node
158
+ gcli cluster:multi-node --cluster '<clusterId>' --workers 2 --wait
159
+ gcli cluster:single-node --cluster '<clusterId>' --wait
160
+
161
+ # Autoscaling - only the flags you pass change
162
+ gcli cluster:autoscale --cluster '<clusterId>' --enable --min 2 --max 6
163
+ gcli cluster:autoscale --cluster '<clusterId>' --cpuUp 75 --cpuDown 25 --cooldown 20
164
+ gcli cluster:autoscale --cluster '<clusterId>' --disable
165
+
166
+ # Load balancer (billed per hour while enabled)
167
+ gcli cluster:load-balancer --cluster '<clusterId>' --enable --wait
168
+ ```
169
+
170
+ #### Declarative clusters (`cluster:apply`)
171
+
172
+ Write the cluster you want in the `cluster:` section of `lambforge.yaml`
173
+ (or a standalone `cluster.yaml`) and let `cluster:apply` make it so: it
174
+ creates the cluster when it doesn't exist, then applies topology, workers,
175
+ control planes, the load balancer and autoscaling - one change at a time,
176
+ waiting for the cluster to be ready between them. Keys you leave out are
177
+ left as they are.
123
178
 
124
179
  ```yaml
125
- name: prod
126
- imageId: <hcloud-image-id>
127
- serverType: cpx22
128
- location: nbg1
129
- workers: 2
130
- singleNode: false
180
+ cluster:
181
+ name: prod
182
+ # needed only to create it
183
+ imageId: <hcloud-image-id>
184
+ serverType: cpx22
185
+ location: nbg1
186
+ # desired state
187
+ singleNode: false # true = one node runs everything (cheapest, dev/stage)
188
+ workers: 3 # 1-10; only the initial size while autoscale is enabled
189
+ controlPlanes: 1 # 1, 3 or 5
190
+ loadBalancer: true
191
+ autoscale:
192
+ enabled: true # needs singleNode: false
193
+ minWorkers: 2
194
+ maxWorkers: 6
195
+ cpuScaleUpPercent: 70 # scale up above this (of allocatable)
196
+ memScaleUpPercent: 70
197
+ cpuScaleDownPercent: 30
198
+ memScaleDownPercent: 30
199
+ samplesToScale: 3 # consecutive readings before acting
200
+ cooldownMinutes: 15
201
+ ```
202
+
203
+ ```bash
204
+ gcli cluster:apply --dry-run # print the plan, change nothing
205
+ gcli cluster:apply # apply it
206
+ gcli cluster:apply --yes # also steps that remove capacity or the LB IP
207
+ gcli cluster:apply --spec cluster.yaml
131
208
  ```
132
209
 
210
+ Steps that remove capacity or release the load balancer's IP (going back to
211
+ `singleNode: true`, `loadBalancer: false`) are skipped unless you pass
212
+ `--yes`. Nodes and the load balancer are billed per started hour.
213
+
133
214
  ### RabbitMQ Brokers
134
215
 
135
216
  A project may have several RabbitMQ brokers, each optionally scoped to one of its private clusters.
@@ -158,6 +239,21 @@ storage:
158
239
  size: SMALL
159
240
  ```
160
241
 
242
+ ### Message-Queue Triggers
243
+
244
+ A trigger runs a lambda for every message on a RabbitMQ queue (and can publish the response and failures to other queues).
245
+
246
+ ```bash
247
+ gcli mq-trigger:create --name orders --lambda order-handler \
248
+ --request-topic orders --response-topic orders-done --error-topic orders-failed \
249
+ --broker '<brokerId>' # see rabbitmq:list; needed when brokers share queue names
250
+ gcli mq-trigger:update --name orders --max-replicas 5 --threshold 20 # only the flags you pass change
251
+ gcli mq-trigger:list
252
+ gcli mq-trigger:delete --name orders
253
+ ```
254
+
255
+ Scaling flags: `--max-retries`, `--cool-down-period`, `--polling-interval`, `--min-replicas`, `--max-replicas`, `--threshold` (messages per replica).
256
+
161
257
  ### Marketplace Plugins
162
258
 
163
259
  Plugins (Redis, MongoDB, NATS, FalkorDB, ...) can be installed on the shared cluster or on any private cluster - the same plugin can be installed on several clusters at once.
@@ -285,15 +381,25 @@ options:
285
381
  external: []
286
382
  ```
287
383
 
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):
384
+ 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
385
 
290
386
  ```yaml
291
- cluster:
387
+ cluster: # every key: see "Declarative clusters" above
292
388
  name: prod
293
389
  imageId: <hcloud-image-id>
294
390
  serverType: cpx22
295
391
  location: nbg1
296
392
  workers: 2
393
+ loadBalancer: false
394
+ autoscale:
395
+ enabled: true
396
+ minWorkers: 2
397
+ maxWorkers: 5
398
+
399
+ triggers:
400
+ time:
401
+ triggerName: nightly
402
+ cron: '0 2 * * *' # cron syntax or @every 5m / @daily
297
403
 
298
404
  rabbitmq:
299
405
  name: events-broker
@@ -361,7 +467,7 @@ gcli lambda:create --project <projectId> --spec ./lambforge.yaml
361
467
  `--mcp` and `--mcpGraph <name>` are also available as CLI flags; the array fields
362
468
  (`mcpOperations`, `mcpHeaders`, `mcpForwardHeaders`) are spec-only. A full annotated example lives in
363
469
  [`example/mcp/lambforge.yaml`](./example/mcp/lambforge.yaml). Client connects at
364
- `https://<host>/<projectId>/<route>/mcp`.
470
+ `https://<host>/<projectId>/<route>` (with `route: mcp`: `https://<host>/<projectId>/mcp`).
365
471
 
366
472
  ### Conditional Configuration (Environment-Aware Specs)
367
473
 
@@ -638,10 +744,23 @@ gcli environment:update
638
744
 
639
745
  ### Function Lifecycle
640
746
 
747
+ - **List**: `gcli lambda:list` (`--clusterName <name>` for one cluster's lambdas)
641
748
  - **Update**: `gcli lambda:update --name 'my-function' --file ./new-index.ts`
642
749
  - **Delete**: `gcli lambda:delete --name 'my-function'`
643
750
  - **Get Details**: `gcli lambda:get --name 'my-function'`
644
751
 
752
+ ### Schedules (cron)
753
+
754
+ One time trigger per lambda. The platform calls the lambda's root with a
755
+ GET and an `X-Fission-Timer-Name` header.
756
+
757
+ ```bash
758
+ gcli cron:create --lambdaName 'my-function' --triggerName nightly --cron '0 2 * * *'
759
+ gcli cron:create # reads triggers.time (and function.name) from lambforge.yaml
760
+ gcli cron:list
761
+ gcli cron:delete --lambdaName 'my-function'
762
+ ```
763
+
645
764
  ### Monitoring & Testing
646
765
 
647
766
  Debug your functions directly from the terminal.
@@ -715,6 +834,33 @@ To use this with Claude Desktop or other MCP-compatible tools, add the following
715
834
  }
716
835
  ```
717
836
 
837
+ ### AI agent skill
838
+
839
+ Give a coding agent (Claude Code and other agents that read skills) the
840
+ whole platform. Paste this into the agent:
841
+
842
+ ```text
843
+ Install the Lambforge skill from https://lambforge.com/skills/platform.md and follow its setup.
844
+ ```
845
+
846
+ Or by hand for Claude Code:
847
+
848
+ ```bash
849
+ mkdir -p ~/.claude/skills/lambforge && cd ~/.claude/skills/lambforge
850
+ for f in $(curl -fsSL https://lambforge.com/skills/files.txt); do
851
+ curl -fsSLO "https://lambforge.com/skills/$f"
852
+ done
853
+ cp platform.md SKILL.md
854
+ claude mcp add --scope user lambforge -- gcli mcp:start
855
+ ```
856
+
857
+ `platform.md` covers setup (install gcli, the login command you run from
858
+ Profile -> CLI - the agent never handles your token, `gcli mcp:start`) and
859
+ the rules, and indexes topic files the agent reads on demand: gcli, MCP
860
+ tools, deploy, REST code and testing, GraphQL and federation, websites,
861
+ MCP servers, secrets, cron and queues, clusters and plugins, operations and
862
+ costs, memory and plans. Source: gql-fission `src/skills/`.
863
+
718
864
  ## Local AI Models (Ollama runner)
719
865
 
720
866
  Use models running on your own machine in the Lambforge chat - including
@@ -0,0 +1,21 @@
1
+ ## 2026-10-19 - ci-token-scopes: mq-trigger:list/create/update/delete commands; README documents CI token permissions per command
2
+
3
+ **Feature:** ci-token-scopes · **Type:** feat
4
+
5
+ - New `mq-trigger:list`, `mq-trigger:create`, `mq-trigger:update`,
6
+ `mq-trigger:delete` (`src/commands/triggers/message-queue/`) - message-queue
7
+ triggers had an API and a dashboard page but no CLI. Flags: `--name`,
8
+ `--lambda`, `--request-topic`, `--response-topic`, `--error-topic`,
9
+ `--broker` (RabbitMQ id), scaling counts; `update` reads the current
10
+ trigger and sends it with the passed flags on top (the service needs the
11
+ full spec).
12
+ - README: CI/CD section lists the permission each command needs (CI token
13
+ scopes now cover every project command, incl. clusters for DevOps
14
+ tokens) and a Message-Queue Triggers section; `README-CLI.md`
15
+ regenerated from the built CLI's `--help`.
16
+ - **Test:** `npx jest test/mq-trigger.spec.ts` (flag mapping, create needs
17
+ lambda + queue, numbers validated, update merged over the current trigger).
18
+ - **Debug:** `docs/features/ci-token-scopes.md`; `ci-token-missing-scope`
19
+ comes from the services - reissue the token with that permission.
20
+ - **Verification:** jest 75/75; tsc clean; `gcli mq-trigger:create --help`
21
+ from a fresh build; `release/index.js` restored after the build.
@@ -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,6 @@ 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 |
36
+ | `ci-token-scopes` | [ci-token-scopes.md](ci-token-scopes.md) | Which permission each command needs; `mq-trigger:*` commands; canonical doc in graphql-server |
@@ -0,0 +1,25 @@
1
+ # ci-token-scopes (gcli slice)
2
+
3
+ **Canonical doc:** `graphql-server/docs/features/ci-token-scopes.md` ·
4
+ **Since:** 2026-10-19
5
+
6
+ gcli itself enforces nothing - a CI/CD token (`gcli login --ci --token …`)
7
+ is checked by the services. What this package owns:
8
+
9
+ - Every project command maps to one permission (README → CI/CD
10
+ Integration has the table). A refused command prints the service error
11
+ `ci-token-missing-scope: <operation> needs <scope>` /
12
+ `ci-token-lambda-not-allowed` / `ci-token-wrong-project`.
13
+ - `mq-trigger:list/create/update/delete`
14
+ (`src/commands/triggers/message-queue/`, `GraphqlClienAPI.
15
+ listMessageQueueTriggers / saveMessageQueueTrigger / deleteMessageQueueTrigger`)
16
+ - the `mq-trigger:*` permissions had no CLI before. `update` reads the
17
+ current trigger and sends it with the given flags on top
18
+ (`mergeOverExisting`): the service hands the payload to Fission as the
19
+ whole spec and picks the cluster by `lambdaName`, so a partial payload
20
+ would drop settings. Counts are validated as whole numbers
21
+ (`toTriggerInput`). The trigger types are declared in `gql-client.ts`
22
+ (not in the bundled introspection yet).
23
+ - Not for CI tokens: `runner:*`, `project:list`, `mcp:start`.
24
+
25
+ **Test:** `npx jest test/mq-trigger.spec.ts`.