Repository navigation
Expand file tree
/
Copy pathversions.yml
More file actions
3061 lines (2964 loc) · 163 KB
/
Copy pathversions.yml
File metadata and controls
3061 lines (2964 loc) · 163 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
# yaml-language-server: $schema=../../fern-versions-yml.schema.json
- version: 0.52.0
changelogEntry:
- summary: |
A custom command may now declare its own `-p` even when profiles reserve `-p` for `--profile` globally
(e.g. Twilio's `serverless start -p <port>`). Clap previously refused to build the tree ("short option
names must be unique"); now the command gets a long-only `--profile` stand-in, and the pre-clap profile
scanner stops reading `-p` as a profile once argv has named that command — `cli -p acme serverless
start -p 9000` still selects profile `acme` and passes port `9000` through.
type: fix
- summary: |
Add `CliApp::describe(path, about)` to give a one-line description to the intermediate groups
`command_under` creates (they previously rendered with a blank description in `--help`), and
`CliApp::hide_global_flags(path, flags)` to hide named root globals such as `--dry-run`, `--query` or
`--spec` from the help of a custom subtree they do not apply to. Hidden flags remain accepted.
type: feat
createdAt: "2026-10-09"
irVersion: 67
- version: 0.51.2
changelogEntry:
- summary: |
`profiles create --provision` and `profiles remove --revoke` now resolve the request URL the same way a
direct command does: `--base-url` is honored and the spec's `servers[].variables` / `x-fern-default-url`
are applied. Previously the provision/revoke call kept the raw server template (e.g.
`https://api.{region}.{city}.twilio.com`) and failed with an invalid URL unless `<NAME>_BASE_URL` or a
profile base URL was set.
type: fix
createdAt: "2026-10-08"
irVersion: 67
- version: 0.51.1
changelogEntry:
- summary: |
Includes Rust SDK Generator 0.53.1 updates.
type: fix
createdAt: "2026-10-08"
irVersion: 67
- version: 0.51.0
changelogEntry:
- summary: |
Add `config.profiles.provisionOperation`, the create-side counterpart of `revokeOperation`. When set,
`profiles create` gains `--provision`, which calls the named operation (e.g. `iam.keys.create`) with the
credentials already in the caller's environment, maps the response onto the profile's credential
(`credential: { username: sid, password: secret }`) and stores it in the OS keychain without ever printing
the secret. `revokeParameters: { Sid: sid }` records the key's identity as `credential_parameters` on the
profile — consulted only by `profiles remove --revoke`, never as a request default — so a profile owns its
API key end to end: minted on create, revoked on remove.
type: feat
createdAt: "2026-10-08"
irVersion: 67
- version: 0.50.0
changelogEntry:
- summary: |
`--dry-run` now renders the full request preview on a terminal. The default
`table` format treated the preview's `headers` array as a paginated list and
printed only the header rows, dropping the URL, method, query params and body.
Dry-run previews (REST and GraphQL) are now emitted as a key/value record;
other formats (`json`, `yaml`, ...) are unchanged.
type: fix
- summary: |
`--dry-run` output includes an `auth` block reporting the endpoint's security
schemes and whether credentials would be attached: `resolved` (naming the
requirement that was satisfied and the configured sources), `missing` (with
the sources to set), `supplied` (passed explicitly as a request parameter)
or `not_required`. Credential values are never printed; `apiKey`-in-query
values are redacted in the preview like header credentials already were.
type: feat
createdAt: "2026-10-07"
irVersion: 67
- version: 0.49.0
changelogEntry:
- summary: |
Includes Rust SDK Generator 0.53.0 updates.
type: feat
createdAt: "2026-10-05"
irVersion: 67
- version: 0.48.0
changelogEntry:
- summary: |
Includes Rust SDK Generator 0.52.0 updates.
type: feat
createdAt: "2026-10-02"
irVersion: 67
- version: 0.47.0
changelogEntry:
- summary: |
Includes Rust SDK Generator 0.51.0 updates.
type: feat
- summary: |
`profiles set <name> …` no longer creates a missing profile silently. In a
terminal it asks first. When an existing profile has a similar name it asks
"Did you mean `<closest>`? [y/N]" (yes writes to that profile), then
"Create profile `<name>`? [y/N]"; otherwise only "Create it? [y/N]".
Answering no changes nothing. When stdin or stderr is not a terminal
(scripts, CI, agents), `set` on a missing profile now fails with a hint
instead of creating it; pass `--yes` to create it without asking.
type: feat
createdAt: "2026-09-30"
irVersion: 67
- version: 0.46.0
changelogEntry:
- summary: |
Includes Rust SDK Generator 0.50.0 updates.
type: feat
createdAt: "2026-09-30"
irVersion: 67
- version: 0.45.1
changelogEntry:
- summary: |
Includes Rust SDK Generator 0.49.1 updates.
type: chore
- summary: |
Bump bundled @fern-api/generator-cli to 0.10.3. When the hosted auto-version analysis of the
full SDK diff fails, generator-cli now retries chunk-by-chunk instead of silently applying a
PATCH bump; any remaining unavailable or incomplete analysis adds a "Version bump not verified"
notice to the SDK PR body and disables automerge.
type: chore
createdAt: "2026-09-29"
irVersion: 67
- version: 0.45.0
changelogEntry:
- summary: |
Includes Rust SDK Generator 0.49.0 updates.
type: feat
createdAt: "2026-09-29"
irVersion: 67
- version: 0.44.2
changelogEntry:
- summary: |
`profiles list`, `profiles show`, and `profiles current` now report an OAuth2
client id stored in the keyring — what `profiles set <name> <CLIENT_ID_VAR>=…`
and `auth login --with-token` write — instead of only the plaintext
`oauth_client_id` from `profiles create --oauth-client-id`. The keyring id
takes precedence, matching the order requests resolve it in.
type: fix
createdAt: "2026-09-29"
irVersion: 67
- version: 0.44.1
changelogEntry:
- summary: |
A command whose operation requires authentication (its own `security:` or
the spec-level default) now fails locally with "Authentication credentials
are missing, so the request was not sent. Set ..." when no configured
credential source (flag, env var, or selected profile) satisfies any of its
security requirements, instead of sending an unauthenticated request and
surfacing the server's 401. Applies with and without `--debug`. Operations
with `security: []`, optional auth (`- {}`), no declared security, or an
auth header or `apiKey` query parameter passed explicitly as a parameter
still go out as before.
type: fix
createdAt: "2026-09-29"
irVersion: 67
- version: 0.44.0
changelogEntry:
- summary: |
The root `--help` "Environment variables" footer is now derived from the
spec instead of a static string: it lists `<PREFIX>_PROFILE`,
`<PREFIX>_OUTPUT`, `<PREFIX>_RETRIES`, and one `<PREFIX>_<VAR>` entry per
`servers[].variables` (e.g. `TWILIO_CLI_REGION`), alongside the existing
runtime-only knobs. Which of these `profiles set` can persist is
documented by that command, not the footer.
type: fix
- summary: |
A selected profile now takes precedence over environment variables for every
value it stores — credentials, `<PREFIX>_BASE_URL`, `<PREFIX>_OUTPUT`,
`<PREFIX>_RETRIES`, server variables such as `<PREFIX>_REGION`, spec
parameter defaults, and the transport settings — however the profile was
selected (`-p/--profile`, `<PREFIX>_PROFILE`, or `profiles use`). Env vars
fill in only what the profile leaves unset; explicit flags still win, and
invocations with no profile selected are unchanged. Previously only `-p`
outranked env, so an active profile's stored values were silently ignored
whenever the same variable was exported. `profiles current` now reports
exported credential vars as `credential_env_fallback` instead of
`credential_overridden_by_env` / `credential_partially_shadowed_by_env`.
`profiles set`, `profiles create --from-env`, `profiles use`, and a
profile-scoped `auth login` no longer warn that an exported credential
will shadow the stored one, since it no longer does.
type: feat
- summary: |
Profiles can now store the transport settings that were previously
env/flag-only: `profiles set <name> <PREFIX>_TIMEOUT_SECS=…`,
`<PREFIX>_PROXY=…`, `<PREFIX>_CA_BUNDLE=…`, `<PREFIX>_INSECURE=…`, and
`<PREFIX>_USER_AGENT_SUFFIX=…` persist to `profiles.toml` (inherited
through `parent`, shown by `profiles show`/`current`). For these five the
profile's stored value wins over the shell-exported global whenever a
profile is in play — `-p`, `<PREFIX>_PROFILE`, or `profiles use` alike
(flag > profile > env var > default); the env var only fills in what the
profile leaves unset.
type: feat
- summary: |
`profiles show` and `profiles current` now print the full stored account
identifier (e.g. the complete Twilio Account SID) instead of the truncated
form used in the `profiles list` table, and include the profile's
`oauth_client_id` when one is set. `profiles list` folds the OAuth client
id into the `ACCOUNT` column (shown when the profile stores no basic-auth
account) instead of a separate `OAUTH_CLIENT_ID` column.
type: fix
- summary: |
`profiles show` and `profiles current` human output now lists fields in a
fixed order (`profile`, `active`/`selected_by`, `account`/`oauth_client_id`,
then settings) instead of alphabetically, so the identifier sits in the
same place for basic-auth and OAuth profiles.
type: fix
createdAt: "2026-09-28"
irVersion: 67
- version: 0.43.0
changelogEntry:
- summary: |
Includes Rust SDK Generator 0.48.0 updates.
type: feat
createdAt: "2026-09-28"
irVersion: 67
- version: 0.42.3
changelogEntry:
- summary: |
The file-based token cache fallback now creates its credential file with
owner-only permissions (0600) at open time instead of tightening them
after the write, closing the window in which the token was briefly
world-readable under a permissive umask.
type: fix
createdAt: "2026-09-23"
irVersion: 67
- version: 0.42.2
changelogEntry:
- summary: |
Includes Rust SDK Generator 0.47.11 updates.
type: fix
createdAt: "2026-09-23"
irVersion: 67
- version: 0.42.1
changelogEntry:
- summary: |
Includes Rust SDK Generator 0.47.10 updates.
type: chore
- summary: |
Bump bundled @fern-api/generator-cli to 0.10.1. Auto-versioned MAJOR/MINOR bumps no longer
produce a version-only `changelog.md` block when the AI analysis returns an empty changelog
entry; the PR description, version bump reason, or commit message body is used instead.
type: chore
createdAt: "2026-09-22"
irVersion: 67
- version: 0.42.0
changelogEntry:
- summary: |
`config.extraDependencies` and `config.extraDevDependencies` declare additional
crates in the generated root `Cargo.toml`, so code kept in `.fernignore` (custom
command handlers, custom auth) no longer needs a post-generation script to re-add
the crates it imports. Each entry is a version requirement string or a full
dependency table (`version`, `features`, `optional`, `defaultFeatures`, `package`,
`path`, `git`, `branch`, `rev`, `registry`), matching the Rust SDK generator's
option of the same name. A crate the CLI runtime already depends on is rejected
rather than silently overridden. `Cargo.lock` is not re-resolved at generation
time; the first `cargo build` after generation records the new crates.
type: feat
createdAt: "2026-09-22"
irVersion: 67
- version: 0.41.2
changelogEntry:
- summary: |
A named `--profile` now prefers that profile's stored credentials when
selecting among multiple authentication schemes. Previously the first
scheme in spec order whose credentials resolved won, so a profile holding
only an OAuth2 credential still sent env-var basic auth under `-p <name>`.
Covers OAuth2 client credentials and `auth login` tokens (device-code /
PKCE) alike; under `--profile`, OAuth2 also resolves its client id from
the profile before the environment, so both halves of a client credential
come from the same place. Ambient selection (`<BIN>_PROFILE`,
`profiles use`) is unchanged — the environment still wins there.
type: fix
createdAt: "2026-09-21"
irVersion: 67
- version: 0.41.1
changelogEntry:
- summary: |
Includes Rust SDK Generator 0.47.9 updates.
type: fix
createdAt: "2026-09-18"
irVersion: 67
- version: 0.41.0
changelogEntry:
- summary: |
`auth login --from-env` captures the credential already in your shell into the active
profile's keyring slot, so "log me in with what I have" no longer routes through
`profiles create <name> --from-env --force` — which made users name a profile they had
already selected. Honours `-p` to target a non-active profile, and emits the same
shadow warning as the create-time capture, since `--from-env` reads the very variable
that will keep outranking the copy it just stored. Conflicts with `--with-token`.
type: feat
- summary: |
`profiles create <name>` now says when it stored no credential, pointing at
`auth login` / `--from-env`. Previously a bare create looked like it had set the
profile up, and the next `auth status` reported every keyring rung as `missing` with
no hint which command was meant to fill them. Suppressed when a credential was just
captured, when the profile inherits one, or when environment variables already supply
one — in those cases nothing is missing.
type: fix
- summary: |
`--retries <N>` on every operation, resolving `flag > <NAME>_RETRIES env > active
profile > x-fern-retries`. `N` counts attempts *after* the first, so `--retries 0`
is equivalent to `--no-retry`. Only `max_attempts` is overridden — the spec's
backoff base, factor and jitter are left alone, since the caller asked how many
times to retry rather than how to pace them.
`profiles create <name> --retries N` stores it per profile, so a user with several
profiles can allow a different number of retries in each. Inherited by child
profiles (unlike `format`): retries describe the network a profile talks to, which
a subaccount shares with its parent. `retries = 0` is distinct from unset and means
"never retry in this profile".
Additive. With no flag, no env var and no profile value the resolved policy is
byte-identical to what the spec declared, so existing CLIs are unaffected.
type: feat
- summary: |
`profiles set <name> KEY=VALUE …` sets credentials and settings on a profile using the
names you already use. `KEY` may be an environment variable this CLI reads — a
credential, or a setting like `<NAME>_RETRIES` / `<NAME>_BASE_URL` / `<NAME>_OUTPUT` /
`<NAME>_<SERVER_VAR>` — or an API parameter by its spec name. Credentials go to the OS
keyring under that profile's slot; everything else to `profiles.toml`. The profile is
created if it does not exist.
One assignment reaches **every** scheme that declares the variable. A vendor spec with
several basic schemes sharing one credential pair previously needed one
`auth login --scheme <name>` per scheme, with names a user cannot guess; now a single
`profiles set prod <NAME>_ACCOUNT_SID=… <NAME>_AUTH_TOKEN=…` covers all of them, and the
output names how many it reached.
Multi-field credentials merge, so setting one half later does not discard the other.
Every key is classified before anything is written, so a run whose third assignment is
invalid leaves the first two unapplied. An unrecognised key is rejected with a
suggestion rather than stored inert — including one that merely looks like one of this
CLI's variables.
type: feat
- summary: |
`profiles current` no longer reports `credential_overridden_by_env` when environment
variables supply only *part* of a multi-value credential. The variable is consulted and
does outrank the keyring for that field, but nothing authenticates — so claiming an
override contradicted `auth status`, which correctly reported not-logged-in. The partial
case is now reported as `credential_partially_shadowed_by_env`.
type: fix
- summary: |
`profiles list` warns when a variable is set that closely resembles one of this CLI's
credential variables but is not read — `<NAME>_ACCOUNT_ID` when the CLI reads
`<NAME>_ACCOUNT_SID`. Previously such a typo produced no diagnostic at all. Scoped to
declared names that are unset while a near neighbour is set, so it cannot fire on
unrelated variables.
type: fix
- summary: |
`profiles list`'s `[env]` row labels its environment variable names under `variables`
rather than reusing the profile `credential` key, which produced a `CREDENTIAL` column
header that every real profile row left blank. Column order is now pinned rather than
alphabetical, so the identifier leads and the explanatory `NOTE` sorts last instead of
landing ahead of the value it annotates.
type: fix
- summary: |
`profiles show <name>` prints one profile's resolved config without selecting it.
`profiles current` answers "what is in effect" and takes no name, so inspecting another
profile previously meant `-p other profiles current` — "run as if I were on other, then
tell me what's current" — which reads backwards. Reports `active` so you can tell
whether it is the default, and omits `selected_by`, which only means something for the
profile actually in play. Matches `gcloud config configurations describe NAME` and
`kubectl config get-contexts NAME`.
type: feat
- summary: |
Add named profiles, off by default behind `config.profiles.enabled`. A profile is a named bundle of request
context — a credential slot, parameter defaults, server variables, an optional base URL and output format —
resolved once per invocation. Enabling it adds a `profiles create | list | use | remove | current` group and a
global `--profile` / `-p` flag.
Precedence per value is: explicit flag, then environment variable, then profile, then the spec's own
`x-fern-default`. Environment variables sit above profiles so a CI pipeline that exports them is never
silently overridden by a developer's stored profile. For credentials the profile adds no rung to ADR-0008's
chain — it only selects which keyring account the existing `Keyring` rung reads, so two tenants can hold
separate tokens for one auth scheme. `config.profiles.commandName` renames the group for an API that already
owns the `profiles` noun.
Secrets never reach `~/.config/<bin>/profiles.toml`: the file names a keyring account, and
`profiles create --with-token` / `--from-env` write the credential to the OS keychain under an account scoped
to that profile. The file is written through `toml_edit`, so a user's comments and any field written by a newer
binary survive a round-trip.
Also fixes a latent correctness bug in the OAuth token cache, which was keyed by `token_url` alone: two
profiles authenticating against the same client-credentials endpoint would have clobbered each other's access
and refresh tokens. The key is now `<token_url>#<credential>` when a profile is selected and byte-identical to
before when none is, so existing caches keep resolving and no one is logged out by the upgrade.
HTTP basic auth gains a keyring rung it never had: both halves are stored in one entry as
`{"username":…,"password":…}` and read back field-by-field, so a per-profile SID+Token credential is
actually resolved. Previously `auth login` on a basic-auth CLI reported success, wrote an entry, and
nothing ever read it — the CLI still said "not logged in".
OAuth2 client credentials are now storable per profile. The provider reads its client id and secret
from the profile's keyring entry when the environment does not supply them, and `auth login
--with-token` collects both halves into one entry — previously the paste wrote a raw string nothing
ever read, so the credential appeared to store and the CLI still reported "not logged in". The client
secret has no plaintext rung; the client id may additionally come from `profiles.toml`, since a client
id is public by construction (RFC 6749 §2.2). `auth status` now lists every rung the resolvers
actually consult, so it no longer reports a scheme as unsatisfied where the profile does supply it.
A profile named explicitly with `--profile` / `-p` now outranks environment variables for credentials,
base URL, output format and server variables; a profile selected *ambiently* (the active profile, or
`<BIN>_PROFILE`) still loses to them. Explicit beats ambient, which is how every other flag here
already behaves, and it keeps a CI job's exported credentials authoritative against a stored default.
Matches the ordering Twilio's shipping CLI documents.
`profiles create` gains a `--<tenant-key>` flag for parameters the spec scopes most operations by —
derived from non-terminal path position, with no provider configuration — so the commonest profile
field is not stuck behind `--set`. `profiles list` renders a fixed `PROFILE … ACTIVE` column order,
with the middle columns being whatever the profiles carry. `profiles create` also accepts the name as
`--profile <NAME>`.
`profiles remove --revoke` calls a generator-named operation (`config.profiles.revokeOperation`)
before deleting the profile, on a new `Binding::invoke_operation` seam for framework-owned commands
that need to call the API without an `ArgMatches`. The flag is not registered at all when unconfigured.
Spec server variables now also read `<PREFIX>_<VARIABLE>` (`twilio` + `region` → `TWILIO_REGION`,
prefix = binary name uppercased, `-` → `_`). They were flag-or-spec-default only, so the
documented `flag > env > profile > spec default` order had no env rung for them and a region
could not be pinned for a shell session. Additive — an unset variable resolves exactly as
before. `x-fern-sdk-variables` keep their existing unprefixed spelling.
`profiles list` shows an `ACCOUNT` column — the identifier behind the stored credential
(the username half of a basic credential), truncated. It is absent for schemes with no
username field, when nothing is stored, or when the keyring read fails, so rendering the
listing never errors or blocks on a locked keychain. The keyring slot name survives as
`credentials_from` and is emitted only when it differs from the profile's own name, so it
marks exactly the row borrowing another profile's credential. `profiles current` renames
`source` to `selected_by`. A root profile whose slot is its own name no longer writes a
redundant `credential` key to `profiles.toml`.
Three changes deliberately apply to **every** generated CLI, not just those that enable profiles,
because each fixes something that was already broken:
- `auth login --with-token` on an HTTP-basic or OAuth2-client-credentials scheme now reads **two**
values from stdin rather than one. Previously it wrote a single opaque string that no resolver ever
read, so the paste reported success and did nothing; a script piping one token now exits non-zero
instead of silently no-op'ing. Bearer, API-key, PKCE and device-code paste are unchanged.
- `auth status` reports every credential rung the resolvers actually consult, so basic and
client-credentials schemes gain keyring rows, and the JSON payload gains a `profile` field
(`null` when unprofiled).
- `--schema` gains a `builtinCommands` array. Additive; `operations`, `globalFlags` and `sdkVariables`
are unchanged.
Everything else — the `profiles` group, the `--profile` / `-p` flag, reading `profiles.toml`, the
reserved-flag-name check, and every profile-sourced default — is inert unless `config.profiles.enabled`
is set. A CLI generated without the block emits byte-identical output.
`AuthCredentialSource` gains a `KeyringField` variant. The enum is not `#[non_exhaustive]`, so a
hand-authored `custom.rs` that matches it exhaustively will need a new arm; the generated scaffold
does not match on it.
Also fixes a credential-confusion bug that predates profiles. `AuthCredentialSource::Cli` resolves by
clap arg *id*, and a binding-contributed arg whose id the root already owns is dropped by the command
merge — so an auth scheme bound to `cli("format")` resolved to the user's `--format` value and sent
`json` as the credential. Such a binding is now rejected at startup, naming the reserved ids. The
generator emits `cli(...)` flags derived from scheme names (for APIs with several header schemes), so
this was reachable from generated output, not only hand-authored CLIs.
Built-in commands (`auth`, `profiles`, `completion`, `man`) now appear in `--schema` under a new
`builtinCommands` array. They were absent entirely, so an agent reading `--schema` could not discover that the
CLI had any way to authenticate or switch tenant.
A CLI generated without the `profiles` config block is byte-identical to one generated before this change.
type: feat
createdAt: "2026-09-17"
irVersion: 67
- version: 0.40.0
changelogEntry:
- summary: |
**Behavior change for multi-scheme CLIs.** The generated `main.rs` now emits
`.auth_strategy(AuthStrategy::Any)` whenever the IR's `auth.requirement` is `ANY`
(`.auth_strategy(AuthStrategy::Routing)` for `endpoint-security`). Previously the
runtime derived its strategy from the baked spec and dispatched per operation, so
each request used the scheme that operation's `security` named.
With `Any`, the first scheme in `generators.yml` order that has credentials is used
for **every** authenticated request and per-operation `security` is no longer
consulted. This matches what the SDK generators have always done for
`api.auth: any:`, and it is what makes a scheme declared only in `generators.yml`
(e.g. OAuth client-credentials layered onto a vendor spec) reachable at all —
per-operation routing could never select it, so those requests went out
unauthenticated.
Two groups are affected:
- `api.auth: any: [...]` in `generators.yml`. One `auth login` now covers every
operation. If your schemes map to different accounts or privileges, reorder
`any:` so the preferred credential is declared first — declaration order is now
the precedence lever, and it is the same lever your SDKs already use.
- Specs with two or more `components.securitySchemes` and **no** `api.auth` block.
The importer derives `ANY` from the scheme count alone, so these CLIs switch from
per-endpoint routing to first-credential-wins even though nothing in
`generators.yml` asked for it. If your operations genuinely need different
schemes, declare `api.auth: endpoint-security` to keep per-operation dispatch.
A selected scheme whose credentials fail (e.g. a rejected OAuth token exchange) now
fails the command. The SDKs instead fall through to the next scheme; the CLI is
deliberately stricter, because silently substituting one credential for another with
different privileges is worse in a terminal than a loud failure.
`ALL` over several schemes has no equivalent strategy and now warns and leaves the
runtime on its `Auto` default, rather than pinning one.
type: feat
- summary: |
OAuth2 client-credentials CLIs now send `grant_type=client_credentials` (and
`grant_type=refresh_token` on the refresh endpoint) when the spec declares
`grant_type` without a literal or default value, instead of exposing it as an
optional `<BIN>_<SCHEME>_TOKEN_GRANT_TYPE` env var that was silently omitted.
type: fix
- summary: |
Cached OAuth2 tokens in `credentials.json` are now tagged with a fingerprint of
the client credentials they were minted for. Changing the client ID/secret env
vars no longer reuses the previous client's access or refresh token.
type: fix
- summary: |
OAuth token and refresh endpoints now resolve their URL from `x-fern-default-url`
when the spec's server is templated, instead of the template filled with each
variable's default. A spec declaring `https://oauth.{region}.example.com` with
`x-fern-default-url: https://oauth.example.com` previously baked
`https://oauth.us1.example.com` into the token request — a host that need not
exist, since the regional form is often not a real name. The CLI has no way to
supply server variables, so the untemplated default is always the correct
choice; this matches what the SDK generators already do.
type: fix
createdAt: "2026-09-15"
irVersion: 67
- version: 0.39.4
changelogEntry:
- summary: |
The generated README and `reference.md` no longer list `--page-all` / `--page-limit` under the flags
"available on every operation". Since 0.38.6 those flags are only registered on operations the spec
describes how to page (`x-fern-pagination`, or a root `page_token` parameter), so the docs now list them
in a separate table introduced by "Operations the spec describes how to page ... also accept:" instead of
promising them everywhere. The previously undocumented `--page-delay` / `--no-pager` (paginated
operations), `--no-stream` (streaming operations) and `--no-extract` / `--no-retry` (every operation) are
now documented alongside them.
type: fix
createdAt: "2026-09-08"
irVersion: 67
- version: 0.39.3
changelogEntry:
- summary: |
`auth status` now lists the env vars an OAuth2 client-credentials scheme reads (e.g. `OAUTH_CLIENT_ID`,
`OAUTH_CLIENT_SECRET`, plus any required custom token-endpoint properties) with their active/missing state,
instead of reporting `(no credential sources bound)`. A valid cached access token is reported alongside
those env vars — it satisfies the scheme on its own, but the env vars stay visible so you can still tell
whether they were picked up. Multi-value schemes (OAuth2 client credentials, basic auth) are now modelled
as independent credential slots: each slot resolves on its own, so a username and password that are both
set are both shown as active rather than one shadowing the other, and `logged_in` in `--output json` is
true only when every slot resolves (or a standalone alternative does).
type: fix
- summary: |
`auth status` no longer suggests `auth login --with-token` for schemes that never read the keyring
(OAuth2 client credentials, basic auth) — a token pasted there would have been silently ignored at
request time. It now names the env vars to set instead.
type: fix
- summary: |
`auth status` no longer reports a scheme as unauthenticated just because the env vars that would mint its
token are unset when a stored login token is present — a keyring entry written by `auth login` satisfies the
scheme on its own. An auth scheme configured with an empty env-var name (e.g. `client-id-env: ""`) is now
reported as `(unbound)` instead of rendering a nameless `missing env var` row and a remedy with an empty
entry.
type: fix
createdAt: "2026-09-08"
irVersion: 67
- version: 0.39.2
changelogEntry:
- summary: |
`--page-all` now treats a step-less offset param as a page number, advancing by 1 per page, matching the
default in the TypeScript, Python, Ruby, PHP and C# SDKs. When `x-fern-pagination` does declare a `step`,
the param is treated as an item index and advanced by the number of results returned, as before.
Page-number APIs (e.g. `?page=2&pageSize=50`) previously skipped pages. Paging also continues from the
caller's own value for the offset param (`--params '{"page": 7}'` fetches 7, 8, 9, …) and no longer sends
that param twice on subsequent pages. The first request is still sent exactly as the caller wrote it —
the CLI never synthesizes a page param for it. When the caller omits the offset param, paging continues
from the param's declared default (`default: 0` / `x-fern-default`), so 0-indexed APIs fetch 1, 2, 3, …
after their implicit first page instead of skipping page 1.
type: fix
createdAt: "2026-09-03"
irVersion: 67
- version: 0.39.1
changelogEntry:
- summary: |
Includes Rust SDK Generator 0.46.7 updates.
type: chore
- summary: |
Embedded types generation no longer fails on large APIs. The rust-model subprocess
timeout is raised from 2 to 15 minutes, and its stderr is now surfaced in the error
message when it does fail.
type: fix
createdAt: "2026-09-03"
irVersion: 67
- version: 0.39.0
changelogEntry:
- summary: |
Generated `--help` output now groups flags into `Required parameters`,
`Optional parameters`, `Request options` (`--json`, `--params`, pagination,
retries, ...) and `Global options` (output format, base URL, env-backed
variables, `--help`/`--version`) instead of one flat `Options:` list, so
users and agents can see at a glance which flags an operation needs.
Runtime validation is unchanged: required parameters may still be supplied
via `--params`/`--json`. Two cases are deliberately listed as optional
because the operation runs without them: a required parameter with an
`x-fern-default`, and a required property of an object that is itself
optional (`--settings.region` where `--settings` may be omitted).
type: feat
createdAt: "2026-09-02"
irVersion: 67
- version: 0.38.13
changelogEntry:
- summary: |
Includes Rust SDK Generator 0.46.6 updates.
type: fix
createdAt: "2026-09-02"
irVersion: 67
- version: 0.38.12
changelogEntry:
- summary: |
Includes Rust SDK Generator 0.46.5 updates.
type: fix
createdAt: "2026-09-02"
irVersion: 67
- version: 0.38.11
changelogEntry:
- summary: |
`config.packageIdentity.license: MIT` now emits a LICENSE. The generator
reads `GeneratorConfig.license`, which is fed by `publish-metadata.license`,
`metadata.license` or `github.license` — none of which is
`packageIdentity.license`. A project that set only the latter got "MIT" in
`Cargo.toml` and on the npm page while shipping no LICENSE text: a package
advertising a license it does not carry. Honored as a fallback only, so any
of the three standard keys still wins and existing output is unchanged.
type: fix
- summary: |
An out-of-range integer supplied through `--params` is rejected instead of
silently mangled. Accepting a whole-valued float looked like it closed the
gap with the flag path past `u64::MAX`, but `serde_json` has already coerced
the literal to `f64` by then, so accepting meant re-serializing the double:
`--params '{"limit": 18446744073709551616}'` sent
`limit=1.8446744073709552e+19` and `1e3` sent `limit=1000.0`. The two paths
now deliberately differ beyond `u64::MAX` — the flag path carries the digits
verbatim, `--params` refuses a value it can no longer represent — which is
the safe direction, since the precision is gone before validation sees it.
type: fix
- summary: |
Every missing required input is reported at once, in a stable order.
The check returned on the first miss while iterating a hash map, so an
operation missing four required inputs named one arbitrary parameter — and a
different one on each run. Fixing them meant re-running once per parameter,
in random order, with no indication of how many remained. A missing path
parameter also short-circuited the check and hid every missing body
parameter behind it. The list now follows the spec's own parameter order,
with anything absent from it appended alphabetically. A single missing input
keeps its original one-line wording.
type: fix
createdAt: "2026-09-01"
irVersion: 67
- version: 0.38.10
changelogEntry:
- summary: |
`packageIdentity` now reaches the published npm package. The launcher's
`package.json` carried only name/version/bin/optionalDependencies plus a
hardcoded description, so npm rendered the CLI as "License: none" with no
keywords, homepage or author — while the same config already populated
`Cargo.toml`. The license is the part that matters: dependency scanners and
corporate policy gates reject unlicensed packages. `authors[0]` becomes npm's
single `author` and the rest `contributors`.
type: fix
- summary: |
A `license: MIT` entry in `generators.yml` now emits a matching LICENSE.
Fern's `LicenseConfig.Basic` mounts no file, so no generator honored it and
a repo publishing to npm as MIT shipped no LICENSE at all. The copyright
holder comes from `packageIdentity.authors[0]`, falling back to the
organization; when neither is known nothing is written, since a copyright
line naming nobody is worse than no file. `Apache-2.0` is left to
`license: { type: custom }`.
type: fix
createdAt: "2026-08-31"
irVersion: 67
- version: 0.38.9
changelogEntry:
- summary: |
Query- and path-parameter values are type-checked locally. `--limit nope`
used to serialize as `?limit=nope` and fail at the API; it now fails
immediately naming the flag and the expected type. Only numeric and boolean
types are enforced — `string` accepts anything (it is what the wire carries)
and arrays/objects are left to the style-aware serializer — so the check
catches typos without rejecting requests a server would accept.
type: fix
- summary: |
`--schema` advertises `httpMethod` and `path` again, per ADR-0006's
2026-08-28 amendment. They were dropped as HTTP-execution detail, but they
are how an agent tells a read from a write *before* running a command, which
is a safety property rather than plumbing. Additive — the `{globalFlags,
operations}` shape, the `parameters` to `input` rename and the capability
hints are unchanged.
type: fix
- summary: |
`--schema` and `--help` report the real element type of an array-typed
query, header or path parameter. Only body arrays carried one, so both
renderers fell back to the container type: `--schema` advertised
`items: {"type": "array"}` — an array of arrays — and `--help` showed
`<JSON_ARRAY>` where a single element belongs. All three spellings now
resolve: inline `type: array`, a `$ref` to an array component, and
`anyOf: [array, null]`; anything that still doesn't resolve reports
`string` rather than the container type. Advertisement-only: the value
collector branches on the element type being something other than
`string`, so no request changes on the wire — verified against two
customer specs (56 array parameters, 4 input forms each).
type: fix
- summary: |
Array-of-enum parameters are now constrained. `type: array, items:
{$ref: SomeEnum}` carries no enum of its own — it lives on `items` — so
the flag was completely unchecked while its scalar twin was enforced by a
clap `value_parser`: `--event-types bogus` reached the API, `--direction
bogus` did not. `--schema` now advertises `items.enum` and the executor
rejects a non-member before any request is sent, naming the flag and
listing the valid options. Enforced after value collection rather than by
a `value_parser`, because a repeated flag also accepts a whole JSON array
in one argument (`--event-types '["a","b"]'`) and clap would reject that
literal as a non-member; all four input forms (repeated, single, JSON
array, `--params`) are verified to serialize exactly as before.
Note this can newly reject a request that previously went out: that is the
point, but a spec whose enum is stale will now block values the API still
accepts.
type: fix
- summary: |
Body properties spelled `anyOf: [T, null]` are type-checked. Such a
property carries no `type:` of its own — the type is in the branch — and
every check downstream keyed off it, so `--json '{"name": 123}'` on a
`name` declared `anyOf: [{type: string}, {type: null}]` was forwarded to
the wire unvalidated, while the same property spelled `type: string` was
correctly rejected. Non-null values are now validated against the sole
non-null branch, at both the property level and for a `$ref`'d component
that is itself a nullable union. A genuine multi-branch union
(`oneOf: [string, array]`) is deliberately left permissive: asserting one
branch would reject values the other allows.
type: fix
- summary: |
The two mutual-exclusion errors name flags that exist. Both interpolated
the raw wire key, so combining `--json` with a body flag reported
`--event_types` where `--event-types` is registered, and an object
shorthand against its own leaf reported `--permissions.inbox_read` where
`--permissions.inbox-read` is registered — clap rejects the spelling the
error suggests, and `--schema` discloses the resolved name, so the
message contradicted the contract beside it. Both now route through
`resolve_param_flag_name`, the shared resolver the command builder and
the missing-parameter hint already use.
type: fix
- summary: |
Non-body parameter type-checking no longer rejects values the CLI used to
send. The boolean check accepted only `true|false|1|0`, case-sensitively,
so `--flag True`, `TRUE`, `False`, `yes`, `no`, `on` and `off` became hard
local failures — spellings that were forwarded before the check existed and
that the frameworks generating these specs accept. It now matches
case-insensitively over `true/false/1/0/yes/no/on/off/t/f/y/n`, and accepts
a JSON `1`/`0` (previously the string `"1"` passed while
`--params '{"flag": 1}'` failed). An empty string on a typed parameter is
accepted again, since a shell turns an unset variable into one and the
request previously went out. The integer check reads digit shape rather
than parsing as `i64`, so the flag path and the `--params` path agree on
values above `i64::MAX` and an integer with no declared `maximum` is not
rejected for its magnitude. Measured across two customer specs: 41 boolean
query parameters on one and 8 on the other were affected.
type: fix
- summary: |
Body arrays of enums advertise `items.enum` in `--schema`. The element-enum
resolution reached parameters only, so on a spec where the same enum array
appears both as a query parameter and as a body property, `--schema`
disclosed the members for one and not the other — including on operations
where the body property is required.
type: fix
- summary: |
The integer check for a non-body parameter agrees between the flag path and
`--params` past `u64::MAX`. `serde_json` widens an integer literal beyond
that to a float, so `--params '{"limit": 18446744073709551616}'` was
rejected while the identical value supplied as a flag was accepted. A
whole-valued number is an integer for this purpose; range remains a
`minimum`/`maximum` concern, checked separately.
type: fix
- summary: |
A body property spelled `{$ref: X, nullable: true}` accepts `null`.
Nullability is declared at the `$ref` *site* — a component is shared, so it
cannot be nullable for one referrer and not another — but the parser's
`$ref` early-return dropped every sibling keyword, lowering the property to
`nullable: false`. The validator's null short-circuit therefore never fired
for the one shape it exists to handle, and resolving the ref rejected `null`
with "Expected object". On one customer's OpenAPI 3.0.1 spec that blocked
`null` on 121 body properties the spec explicitly permits.
A `$ref` property that is not nullable still rejects `null`, and non-null
values are still validated against the referenced schema.
type: fix
- summary: |
Enum members are enforced when supplied through `--params`. A scalar enum
was gated only by clap's value parser, which `--params` bypasses entirely,
so `--params '{"direction":"bogus"}'` reached the wire — and for a path
parameter landed in the URL. Array element enums had the same hole for
non-string values: `--params '{"event_types":[5]}'` sent `?event_types=5`
because the check only inspected strings. The accepted set deliberately
mirrors clap's rather than just the declared wire values, so an
`x-fern-enum` display name and the `null` sentinel on a nullable parameter
are still accepted.
type: fix
- summary: |
A `$ref` to an enum component is enforced inside a request body. The
validator's component model carried no `enum` field at all, so a property
that reached its enum through a `$ref` had its members advertised in
`--schema` and never checked — `webhooks create --event-types bogus` was
accepted and sent, while the identical enum declared inline on the property,
or used as a query parameter, was rejected. Covers array elements too, and
a `const:` lowers to a single-member enum as it does elsewhere. Exact
matching is safe because the flag layer canonicalizes an `x-fern-enum`
display name to its wire value before validation.
type: fix
- summary: |
A repeatable flag's `--help` now says it is repeatable. The value name can
only show one form, and once it correctly reports the element type
(`<STRING>` rather than `<JSON_ARRAY>`) nothing on the surface indicated
that the flag can be passed more than once or handed a whole JSON array —
both of which work. The long help now discloses both forms; the one-line
form is unchanged, since it is width-limited and truncated.
type: fix
createdAt: "2026-08-31"
irVersion: 67
- version: 0.38.8
changelogEntry:
- summary: |
Fix the generated wire-test harness invoking the CLI with arguments it rejects.
It no longer passes `--no-pager`, which commands without pagination never register,
and it now passes any required global parameter (for example an API key header) as a
flag. Both cases made the binary exit during argument parsing, so the mock server saw
no request at all.
type: fix
createdAt: "2026-08-31"
irVersion: 67
- version: 0.38.7
changelogEntry:
- summary: |
Every settable property in `--schema` now discloses the flag to type.
Property keys are wire names and diverge from flags more often than they
look: a header `Idempotency-Key` becomes `--idempotency-key`, an
`x-fern-parameter-name` rename changes it outright, and a name colliding
with a builtin gets a `-param` suffix — so a spec parameter called `query`
is registered as `--query-param` because `--query` is the JMESPath global.
That last case made the contract unfollowable: `required` named `query` and
no such flag existed. The name is derived from the same
`resolve_param_flag_name` the command builder uses, and is absent when no
flag exists for that property — either the name cannot be sanitized into a
flag, or another wire name claimed the same flag first and the builder
skipped this one — meaning that property is reachable via `--params` alone.
type: fix
createdAt: "2026-08-28"
irVersion: 67
- version: 0.38.6
changelogEntry:
- summary: |
Retries no longer treat a self-generated `Idempotency-Key` as a licence to
retry. Because the key is generated for every POST/PUT/PATCH, every
non-idempotent operation was retry-eligible and a 5xx on a create retried
~4x against endpoints with no idempotency support. Retry-safety now
requires either `x-fern-idempotent: true` (the spec declaring server-side
support) or an explicit `--idempotency-key`. The auto key is still sent.
type: fix
- summary: |
`x-fern-idempotent: true` no longer suppresses the auto `Idempotency-Key`.
The marker only means the operation *exposes* `--idempotency-key`, but it
was read as "the caller supplies one" — so a marked operation invoked
without the flag retried with no key at all, while the same operation
without the marker got one. A key is now always sent on POST/PUT/PATCH
unless the caller supplied their own or `x-fern-cli-idempotency: false`
opts out.
type: fix
- summary: |
Request-body validation now checks properties behind a `$ref`. The
validator only had an object branch, so a `$ref` to a scalar or array
component was accepted whatever its value — on specs where most schemas
are component refs this meant validation was effectively off, and
`--dry-run` exited 0 on a malformed body. Bare-`$ref` component chains are
now followed too (bounded, so a cycle fails closed).
type: fix
- summary: |
Parameters declared as a bare `$ref`, or as `anyOf: [T, null]` (pydantic's
`Optional[T]`), now resolve through component schemas, so they keep their
type, `enum`, `format` and numeric bounds instead of arriving untyped.
Array-typed parameters in any of those spellings are now repeatable:
`--labels a --labels b` works, and a single JSON-array argument is
equivalent. Previously a JSON array on such a parameter went on the wire
URL-encoded as `?x=%5B%22a%22%5D`. A single value is still sent as `?x=a`,
and a true union (more than one non-null branch) is left untouched.
type: fix
- summary: |
`--page-all` / `--page-limit` / `--page-delay` / `--no-pager` are only
registered on operations the spec describes how to page. They were
advertised everywhere, and on a spec with no pagination metadata the
executor fell back to guessing `pageToken` / `nextPageToken`: one request
went out and the command exited 0 with page 1 — silent partial data.
Note for consumers: on a spec with no pagination metadata these flags now
disappear from every operation, so a script or agent already passing
`--page-all` goes from exit 0 (having silently received one page) to a
hard "unexpected argument" error. Nothing that previously worked breaks,
but the failure is now loud rather than silent.
type: fix
- summary: |
The generated npm launcher now exits non-zero when the binary dies on a
signal. `execFileSync` reports a signal death with `status: null`, which
the launcher passed to `process.exit`, and Node coerces that to 0 — so CI
timeouts (SIGTERM), SIGSEGV and OOM-kills all reported success. Signal
deaths now exit 128+signum (SIGTERM to 143).
type: fix
- summary: |
Any SemVer pre-release now publishes to npm under a non-latest dist-tag.
Only `-alpha` and `-beta` were matched, so a `v1.1.0-rc.1` or `-next.1`
tag fell through to a bare `npm publish` and would move `latest` to a
pre-release. The tag is derived from the first pre-release identifier.
type: fix
- summary: |
The custom-command SDK bridge seeds the co-generated SDK's `base_url` from
the CLI's own resolution. `ClientConfig::default()` carries an empty
`base_url` for any API that declares no environment, so `sdk::client(ctx)`
produced a client with no host and every custom command failed on a
relative URL before the injected executor could help. A spec that declares
its server per-operation rather than at the root is resolved too.
type: fix
- summary: |
Generated skills now tell agents to verify auth with `<cli> auth status`
rather than `<cli> --help`, which reads no credentials and so confirmed
nothing.
type: fix
- summary: |
npm platform binaries are built with the `dist` cargo profile, the same one
cargo-dist uses for the GitHub Release. `ci.yml` built `--release` while
`release.yml` built `--profile dist`, so the two channels shipped different
bytes under one version tag.
type: fix
- summary: |
Generated CLI repos no longer ship the vendored runtime's Apache-2.0
`LICENSE` by default, which contradicted the `license` field
`packageIdentity` writes into `Cargo.toml`. A LICENSE is now emitted only
when one is configured (`license: { type: custom }`), matching every other
Fern generator; a basic license remains package metadata only.
type: fix
- summary: |
The generated README carries an Attribution section naming the vendored
`fern-cli-sdk` runtime and its Apache-2.0 license. The runtime's source is
copied into every generated repo, and Apache-2.0 requires retaining that
notice; carrying it in the README keeps it without shipping a LICENSE file
that contradicts the repo's own declared license.
type: fix
- summary: |
The shared `generate-skills` prerequisite file no longer documents flags the
spec cannot produce. `-o, --output` and the pagination flags are emitted
only when some operation actually registers them, and the pointer at
`--schema`'s `paginable` / `binaryResponse` hints is emitted only when those
hints can appear. On an API with neither, step one of the file was
unfollowable — it named a flag the parser rejects.
type: fix
- summary: |
Generated skills state the real `--format` default (`table` on a TTY,
`json` when piped) instead of `json`, and tell agents to set **one** of
several alternative auth schemes rather than exporting every environment
variable — which set up the exact credential shadowing the CLI's own auth
errors warn about.
type: fix
- summary: |
Auth failures name only the credential sources that actually hold a value,
and the "check for shadowing" advice appears only when more than one source
is populated. Listing every *declared* source meant a CLI with two schemes
named four places when one supplied the credential, then sent the user
hunting for a conflict that could not exist.
type: fix
- summary: |
`--schema`'s `globalFlags` lists `--params`, `--no-retry`, `--no-extract`
and `--help`. All four are registered on every operation, so an agent
coding against `--schema` had no way to discover they existed.
type: fix
- summary: |
`--schema` and `--help` advertise the real element type of an array body
property. A repeated flag carries `type: string` because that is the flag
surface, which was rendered as `items: {type: string}` even for an array of
objects — an agent following the contract sent `["x"]` and the request was
rejected. Each occurrence of such a flag is now JSON-decoded, so
`--inputs '{...}' --inputs '{...}'` builds an array of objects; plain
string arrays are unchanged.
type: fix
- summary: |
`--schema`'s `input.required` no longer disagrees with the validator. An
object-valued body property the parser recurses into kept a clap-optional
shorthand flag (leaf flags can satisfy it) but was also dropped from the
advertised required list, so a caller could supply every field `--schema`
named and still be rejected for one it never mentioned.
type: fix
- summary: |
`--schema` no longer advertises a required parent object alongside its
required dotted leaves. The executor rejects combining `--a` with `--a.b`,
so listing both made the contract unsatisfiable — following it verbatim
produced "Cannot combine". The ancestor is dropped; the required leaves
already imply it. A required parent with no required leaves is unaffected.
type: fix
- summary: |
`--help` shows the real element type for a repeated flag, so an
array-of-objects flag reads `<JSON_OBJECT>` rather than `<STRING>`.