@quonfig/cli 0.0.52 → 0.0.54

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -17,7 +17,7 @@ $ npm install -g @quonfig/cli
17
17
  $ qfg COMMAND
18
18
  running command...
19
19
  $ qfg (--version)
20
- @quonfig/cli/0.0.52 linux-x64 node-v24.4.1
20
+ @quonfig/cli/0.0.54 linux-x64 node-v24.4.1
21
21
  $ qfg --help [COMMAND]
22
22
  USAGE
23
23
  $ qfg COMMAND
@@ -157,6 +157,7 @@ script doesn't need to know which env it's running in.
157
157
  * [`qfg sdk-key create`](#qfg-sdk-key-create)
158
158
  * [`qfg sdk-key list`](#qfg-sdk-key-list)
159
159
  * [`qfg sdk-key revoke KEYID`](#qfg-sdk-key-revoke-keyid)
160
+ * [`qfg serve`](#qfg-serve)
160
161
  * [`qfg set-default [NAME]`](#qfg-set-default-name)
161
162
  * [`qfg set-rollout [NAME]`](#qfg-set-rollout-name)
162
163
  * [`qfg sync`](#qfg-sync)
@@ -195,7 +196,7 @@ EXAMPLES
195
196
  $ qfg activity restore my.flag --yes
196
197
  ```
197
198
 
198
- _See code: [src/commands/activity.ts](https://github.com/quonfig/cli/blob/v0.0.52/src/commands/activity.ts)_
199
+ _See code: [src/commands/activity.ts](https://github.com/quonfig/cli/blob/v0.0.54/src/commands/activity.ts)_
199
200
 
200
201
  ## `qfg activity deleted`
201
202
 
@@ -224,7 +225,7 @@ EXAMPLES
224
225
  $ qfg activity deleted --json
225
226
  ```
226
227
 
227
- _See code: [src/commands/activity/deleted.ts](https://github.com/quonfig/cli/blob/v0.0.52/src/commands/activity/deleted.ts)_
228
+ _See code: [src/commands/activity/deleted.ts](https://github.com/quonfig/cli/blob/v0.0.54/src/commands/activity/deleted.ts)_
228
229
 
229
230
  ## `qfg activity feed`
230
231
 
@@ -259,7 +260,7 @@ EXAMPLES
259
260
  $ qfg activity feed --json
260
261
  ```
261
262
 
262
- _See code: [src/commands/activity/feed.ts](https://github.com/quonfig/cli/blob/v0.0.52/src/commands/activity/feed.ts)_
263
+ _See code: [src/commands/activity/feed.ts](https://github.com/quonfig/cli/blob/v0.0.54/src/commands/activity/feed.ts)_
263
264
 
264
265
  ## `qfg activity history [NAME]`
265
266
 
@@ -293,7 +294,7 @@ EXAMPLES
293
294
  $ qfg activity history request.timeout --json
294
295
  ```
295
296
 
296
- _See code: [src/commands/activity/history.ts](https://github.com/quonfig/cli/blob/v0.0.52/src/commands/activity/history.ts)_
297
+ _See code: [src/commands/activity/history.ts](https://github.com/quonfig/cli/blob/v0.0.54/src/commands/activity/history.ts)_
297
298
 
298
299
  ## `qfg activity restore [NAME]`
299
300
 
@@ -332,7 +333,7 @@ EXAMPLES
332
333
  $ qfg activity restore request.timeout --type config --yes
333
334
  ```
334
335
 
335
- _See code: [src/commands/activity/restore.ts](https://github.com/quonfig/cli/blob/v0.0.52/src/commands/activity/restore.ts)_
336
+ _See code: [src/commands/activity/restore.ts](https://github.com/quonfig/cli/blob/v0.0.54/src/commands/activity/restore.ts)_
336
337
 
337
338
  ## `qfg audit-log [NAME]`
338
339
 
@@ -360,7 +361,7 @@ EXAMPLES
360
361
  $ qfg audit-log my.flag
361
362
  ```
362
363
 
363
- _See code: [src/commands/audit-log.ts](https://github.com/quonfig/cli/blob/v0.0.52/src/commands/audit-log.ts)_
364
+ _See code: [src/commands/audit-log.ts](https://github.com/quonfig/cli/blob/v0.0.54/src/commands/audit-log.ts)_
364
365
 
365
366
  ## `qfg config-schema`
366
367
 
@@ -389,7 +390,7 @@ EXAMPLES
389
390
  $ qfg config-schema --json-schema # full JSON Schema document (copy into your editor)
390
391
  ```
391
392
 
392
- _See code: [src/commands/config-schema.ts](https://github.com/quonfig/cli/blob/v0.0.52/src/commands/config-schema.ts)_
393
+ _See code: [src/commands/config-schema.ts](https://github.com/quonfig/cli/blob/v0.0.54/src/commands/config-schema.ts)_
393
394
 
394
395
  ## `qfg create NAME`
395
396
 
@@ -474,7 +475,7 @@ EXAMPLES
474
475
  $ qfg set-rollout my.new.flag --environment production --true-percent 20
475
476
  ```
476
477
 
477
- _See code: [src/commands/create.ts](https://github.com/quonfig/cli/blob/v0.0.52/src/commands/create.ts)_
478
+ _See code: [src/commands/create.ts](https://github.com/quonfig/cli/blob/v0.0.54/src/commands/create.ts)_
478
479
 
479
480
  ## `qfg delete NAME`
480
481
 
@@ -520,7 +521,7 @@ EXAMPLES
520
521
  $ qfg delete my.config --yes
521
522
  ```
522
523
 
523
- _See code: [src/commands/delete.ts](https://github.com/quonfig/cli/blob/v0.0.52/src/commands/delete.ts)_
524
+ _See code: [src/commands/delete.ts](https://github.com/quonfig/cli/blob/v0.0.54/src/commands/delete.ts)_
524
525
 
525
526
  ## `qfg flag info [NAME]`
526
527
 
@@ -724,7 +725,7 @@ EXAMPLES
724
725
  $ qfg generate --targets node-ts -o ./dist # combine with targets
725
726
  ```
726
727
 
727
- _See code: [src/commands/generate.ts](https://github.com/quonfig/cli/blob/v0.0.52/src/commands/generate.ts)_
728
+ _See code: [src/commands/generate.ts](https://github.com/quonfig/cli/blob/v0.0.54/src/commands/generate.ts)_
728
729
 
729
730
  ## `qfg generate-new-hex-key`
730
731
 
@@ -747,7 +748,7 @@ EXAMPLES
747
748
  $ qfg generate-new-hex-key
748
749
  ```
749
750
 
750
- _See code: [src/commands/generate-new-hex-key.ts](https://github.com/quonfig/cli/blob/v0.0.52/src/commands/generate-new-hex-key.ts)_
751
+ _See code: [src/commands/generate-new-hex-key.ts](https://github.com/quonfig/cli/blob/v0.0.54/src/commands/generate-new-hex-key.ts)_
751
752
 
752
753
  ## `qfg get [NAME]`
753
754
 
@@ -779,7 +780,7 @@ EXAMPLES
779
780
  $ qfg get my.config.name --environment=production
780
781
  ```
781
782
 
782
- _See code: [src/commands/get.ts](https://github.com/quonfig/cli/blob/v0.0.52/src/commands/get.ts)_
783
+ _See code: [src/commands/get.ts](https://github.com/quonfig/cli/blob/v0.0.54/src/commands/get.ts)_
783
784
 
784
785
  ## `qfg history NAME`
785
786
 
@@ -805,7 +806,7 @@ EXAMPLES
805
806
  $ qfg history my.flag
806
807
  ```
807
808
 
808
- _See code: [src/commands/history.ts](https://github.com/quonfig/cli/blob/v0.0.52/src/commands/history.ts)_
809
+ _See code: [src/commands/history.ts](https://github.com/quonfig/cli/blob/v0.0.54/src/commands/history.ts)_
809
810
 
810
811
  ## `qfg info [NAME]`
811
812
 
@@ -853,7 +854,7 @@ EXAMPLES
853
854
  $ qfg info my.config.name --exclude-evaluations # skip 24h stats
854
855
  ```
855
856
 
856
- _See code: [src/commands/info.ts](https://github.com/quonfig/cli/blob/v0.0.52/src/commands/info.ts)_
857
+ _See code: [src/commands/info.ts](https://github.com/quonfig/cli/blob/v0.0.54/src/commands/info.ts)_
857
858
 
858
859
  ## `qfg init [DIRECTORY]`
859
860
 
@@ -893,7 +894,7 @@ EXAMPLES
893
894
  $ qfg init --dry-run
894
895
  ```
895
896
 
896
- _See code: [src/commands/init.ts](https://github.com/quonfig/cli/blob/v0.0.52/src/commands/init.ts)_
897
+ _See code: [src/commands/init.ts](https://github.com/quonfig/cli/blob/v0.0.54/src/commands/init.ts)_
897
898
 
898
899
  ## `qfg interactive`
899
900
 
@@ -923,7 +924,7 @@ EXAMPLES
923
924
  $ qfg
924
925
  ```
925
926
 
926
- _See code: [src/commands/interactive.ts](https://github.com/quonfig/cli/blob/v0.0.52/src/commands/interactive.ts)_
927
+ _See code: [src/commands/interactive.ts](https://github.com/quonfig/cli/blob/v0.0.54/src/commands/interactive.ts)_
927
928
 
928
929
  ## `qfg list`
929
930
 
@@ -963,7 +964,7 @@ EXAMPLES
963
964
  $ qfg list --feature-flags
964
965
  ```
965
966
 
966
- _See code: [src/commands/list.ts](https://github.com/quonfig/cli/blob/v0.0.52/src/commands/list.ts)_
967
+ _See code: [src/commands/list.ts](https://github.com/quonfig/cli/blob/v0.0.54/src/commands/list.ts)_
967
968
 
968
969
  ## `qfg log`
969
970
 
@@ -988,7 +989,7 @@ EXAMPLES
988
989
  $ qfg log --limit 5
989
990
  ```
990
991
 
991
- _See code: [src/commands/log.ts](https://github.com/quonfig/cli/blob/v0.0.52/src/commands/log.ts)_
992
+ _See code: [src/commands/log.ts](https://github.com/quonfig/cli/blob/v0.0.54/src/commands/log.ts)_
992
993
 
993
994
  ## `qfg log-level NAME`
994
995
 
@@ -1053,7 +1054,7 @@ EXAMPLES
1053
1054
  $ qfg log-level log-level.my-app --target=Chatty --value=INFO --environment=production
1054
1055
  ```
1055
1056
 
1056
- _See code: [src/commands/log-level.ts](https://github.com/quonfig/cli/blob/v0.0.52/src/commands/log-level.ts)_
1057
+ _See code: [src/commands/log-level.ts](https://github.com/quonfig/cli/blob/v0.0.54/src/commands/log-level.ts)_
1057
1058
 
1058
1059
  ## `qfg login`
1059
1060
 
@@ -1078,7 +1079,7 @@ EXAMPLES
1078
1079
  $ qfg login --profile myprofile
1079
1080
  ```
1080
1081
 
1081
- _See code: [src/commands/login.ts](https://github.com/quonfig/cli/blob/v0.0.52/src/commands/login.ts)_
1082
+ _See code: [src/commands/login.ts](https://github.com/quonfig/cli/blob/v0.0.54/src/commands/login.ts)_
1082
1083
 
1083
1084
  ## `qfg logout`
1084
1085
 
@@ -1101,7 +1102,7 @@ EXAMPLES
1101
1102
  $ qfg logout
1102
1103
  ```
1103
1104
 
1104
- _See code: [src/commands/logout.ts](https://github.com/quonfig/cli/blob/v0.0.52/src/commands/logout.ts)_
1105
+ _See code: [src/commands/logout.ts](https://github.com/quonfig/cli/blob/v0.0.54/src/commands/logout.ts)_
1105
1106
 
1106
1107
  ## `qfg migrate`
1107
1108
 
@@ -1164,7 +1165,7 @@ EXAMPLES
1164
1165
  $ qfg migrate --from launch --source-api-key $LAUNCH_API_KEY --dir ./quonfig-repo --staging
1165
1166
  ```
1166
1167
 
1167
- _See code: [src/commands/migrate.ts](https://github.com/quonfig/cli/blob/v0.0.52/src/commands/migrate.ts)_
1168
+ _See code: [src/commands/migrate.ts](https://github.com/quonfig/cli/blob/v0.0.54/src/commands/migrate.ts)_
1168
1169
 
1169
1170
  ## `qfg migrate doctor`
1170
1171
 
@@ -1202,7 +1203,7 @@ EXAMPLES
1202
1203
  $ qfg migrate doctor --json
1203
1204
  ```
1204
1205
 
1205
- _See code: [src/commands/migrate/doctor.ts](https://github.com/quonfig/cli/blob/v0.0.52/src/commands/migrate/doctor.ts)_
1206
+ _See code: [src/commands/migrate/doctor.ts](https://github.com/quonfig/cli/blob/v0.0.54/src/commands/migrate/doctor.ts)_
1206
1207
 
1207
1208
  ## `qfg migrate my-code`
1208
1209
 
@@ -1234,7 +1235,7 @@ EXAMPLES
1234
1235
  $ qfg migrate my-code --dry-run
1235
1236
  ```
1236
1237
 
1237
- _See code: [src/commands/migrate/my-code.ts](https://github.com/quonfig/cli/blob/v0.0.52/src/commands/migrate/my-code.ts)_
1238
+ _See code: [src/commands/migrate/my-code.ts](https://github.com/quonfig/cli/blob/v0.0.54/src/commands/migrate/my-code.ts)_
1238
1239
 
1239
1240
  ## `qfg migrate status`
1240
1241
 
@@ -1265,7 +1266,7 @@ EXAMPLES
1265
1266
  $ qfg migrate status --json
1266
1267
  ```
1267
1268
 
1268
- _See code: [src/commands/migrate/status.ts](https://github.com/quonfig/cli/blob/v0.0.52/src/commands/migrate/status.ts)_
1269
+ _See code: [src/commands/migrate/status.ts](https://github.com/quonfig/cli/blob/v0.0.54/src/commands/migrate/status.ts)_
1269
1270
 
1270
1271
  ## `qfg override [NAME] [VALUE]`
1271
1272
 
@@ -1320,7 +1321,7 @@ EXAMPLES
1320
1321
  $ qfg override my.flag true --env=staging
1321
1322
  ```
1322
1323
 
1323
- _See code: [src/commands/override.ts](https://github.com/quonfig/cli/blob/v0.0.52/src/commands/override.ts)_
1324
+ _See code: [src/commands/override.ts](https://github.com/quonfig/cli/blob/v0.0.54/src/commands/override.ts)_
1324
1325
 
1325
1326
  ## `qfg pull`
1326
1327
 
@@ -1368,7 +1369,7 @@ EXAMPLES
1368
1369
  $ qfg pull # uses QUONFIG_DIR env var
1369
1370
  ```
1370
1371
 
1371
- _See code: [src/commands/pull.ts](https://github.com/quonfig/cli/blob/v0.0.52/src/commands/pull.ts)_
1372
+ _See code: [src/commands/pull.ts](https://github.com/quonfig/cli/blob/v0.0.54/src/commands/pull.ts)_
1372
1373
 
1373
1374
  ## `qfg push`
1374
1375
 
@@ -1417,7 +1418,7 @@ EXAMPLES
1417
1418
  $ qfg push --dir ./our-config --yes
1418
1419
  ```
1419
1420
 
1420
- _See code: [src/commands/push.ts](https://github.com/quonfig/cli/blob/v0.0.52/src/commands/push.ts)_
1421
+ _See code: [src/commands/push.ts](https://github.com/quonfig/cli/blob/v0.0.54/src/commands/push.ts)_
1421
1422
 
1422
1423
  ## `qfg run [COMMAND]`
1423
1424
 
@@ -1468,7 +1469,7 @@ EXAMPLES
1468
1469
  $ qfg run --env DATABASE_URL=db.url --preserve-env --environment=staging -- npm test
1469
1470
  ```
1470
1471
 
1471
- _See code: [src/commands/run.ts](https://github.com/quonfig/cli/blob/v0.0.52/src/commands/run.ts)_
1472
+ _See code: [src/commands/run.ts](https://github.com/quonfig/cli/blob/v0.0.54/src/commands/run.ts)_
1472
1473
 
1473
1474
  ## `qfg schema NAME`
1474
1475
 
@@ -1506,7 +1507,7 @@ EXAMPLES
1506
1507
  $ qfg schema my-schema --set-json-schema=@schemas/my-schema.json --protected
1507
1508
  ```
1508
1509
 
1509
- _See code: [src/commands/schema.ts](https://github.com/quonfig/cli/blob/v0.0.52/src/commands/schema.ts)_
1510
+ _See code: [src/commands/schema.ts](https://github.com/quonfig/cli/blob/v0.0.54/src/commands/schema.ts)_
1510
1511
 
1511
1512
  ## `qfg sdk-key`
1512
1513
 
@@ -1533,7 +1534,7 @@ EXAMPLES
1533
1534
  $ qfg sdk-key revoke <key-id>
1534
1535
  ```
1535
1536
 
1536
- _See code: [src/commands/sdk-key.ts](https://github.com/quonfig/cli/blob/v0.0.52/src/commands/sdk-key.ts)_
1537
+ _See code: [src/commands/sdk-key.ts](https://github.com/quonfig/cli/blob/v0.0.54/src/commands/sdk-key.ts)_
1537
1538
 
1538
1539
  ## `qfg sdk-key create`
1539
1540
 
@@ -1565,7 +1566,7 @@ EXAMPLES
1565
1566
  $ qfg sdk-key create --environment staging --type browser
1566
1567
  ```
1567
1568
 
1568
- _See code: [src/commands/sdk-key/create.ts](https://github.com/quonfig/cli/blob/v0.0.52/src/commands/sdk-key/create.ts)_
1569
+ _See code: [src/commands/sdk-key/create.ts](https://github.com/quonfig/cli/blob/v0.0.54/src/commands/sdk-key/create.ts)_
1569
1570
 
1570
1571
  ## `qfg sdk-key list`
1571
1572
 
@@ -1594,7 +1595,7 @@ EXAMPLES
1594
1595
  $ qfg sdk-key list --environment production
1595
1596
  ```
1596
1597
 
1597
- _See code: [src/commands/sdk-key/list.ts](https://github.com/quonfig/cli/blob/v0.0.52/src/commands/sdk-key/list.ts)_
1598
+ _See code: [src/commands/sdk-key/list.ts](https://github.com/quonfig/cli/blob/v0.0.54/src/commands/sdk-key/list.ts)_
1598
1599
 
1599
1600
  ## `qfg sdk-key revoke KEYID`
1600
1601
 
@@ -1621,7 +1622,64 @@ EXAMPLES
1621
1622
  $ qfg sdk-key revoke a1b2c3d4-e5f6-7890-abcd-ef1234567890
1622
1623
  ```
1623
1624
 
1624
- _See code: [src/commands/sdk-key/revoke.ts](https://github.com/quonfig/cli/blob/v0.0.52/src/commands/sdk-key/revoke.ts)_
1625
+ _See code: [src/commands/sdk-key/revoke.ts](https://github.com/quonfig/cli/blob/v0.0.54/src/commands/sdk-key/revoke.ts)_
1626
+
1627
+ ## `qfg serve`
1628
+
1629
+ Serve a local datadir over HTTP to browser/RN SDKs.
1630
+
1631
+ ```
1632
+ USAGE
1633
+ $ qfg serve [--json] [--interactive] [--no-color] [--verbose] [--datadir <value>] [--environment <value>]
1634
+ [--port <value>] [--host <value>] [--frontend-sdk-key <value>] [--cors-origin <value>...] [--watch]
1635
+ [--allow-non-loopback]
1636
+
1637
+ FLAGS
1638
+ --allow-non-loopback Confirm a LAN-reachable bind. Required when --host is not loopback.
1639
+ --cors-origin=<value>... [default: *] Allowed CORS origin (repeatable). Default is *; required when binding to a
1640
+ non-loopback host.
1641
+ --datadir=<value> Datadir to serve (defaults to ./our-config, then ./.quonfig, then errors). Honors
1642
+ QUONFIG_DIR.
1643
+ --environment=<value> [default: development] Which environment slug to evaluate. Honors QUONFIG_ENVIRONMENT.
1644
+ --frontend-sdk-key=<value> If set, every request must present Authorization: Basic 1:<key>. If unset, the server is
1645
+ open (matches the "datadir is the source of truth" mental model).
1646
+ --host=<value> [default: 127.0.0.1] Bind address. Loopback by default; non-loopback requires
1647
+ --allow-non-loopback.
1648
+ --port=<value> [default: 6580] TCP port to listen on. Errors on collision; pass --port <n> to retry.
1649
+ --[no-]watch Reload the envelope when the datadir changes. --no-watch disables.
1650
+
1651
+ GLOBAL FLAGS
1652
+ --[no-]interactive Force interactive mode
1653
+ --json Format output as json.
1654
+ --no-color Do not colorize output
1655
+ --verbose Verbose output
1656
+
1657
+ DESCRIPTION
1658
+ Serve a local datadir over HTTP to browser/RN SDKs.
1659
+
1660
+ Reads configs from a local datadir and exposes them at
1661
+ `GET /api/v2/configs/eval-with-context/{base64url(ctx)}`. Point your
1662
+ browser SDK at the resulting URL (`http://localhost:6580` by default)
1663
+ and the same client code that talks to api-delivery in production will
1664
+ work unmodified.
1665
+
1666
+ Telemetry is intentionally not served — qfg serve has no Quonfig backend
1667
+ behind it. Disable client-side telemetry with
1668
+ `collectEvaluationSummaries: false` (and `contextUploadMode: "none"`),
1669
+ or point the SDK's `telemetryUrl` at a real endpoint.
1670
+
1671
+ The server is bound to 127.0.0.1 by default; pass --allow-non-loopback
1672
+ to confirm a LAN-reachable bind.
1673
+
1674
+ EXAMPLES
1675
+ $ qfg serve
1676
+
1677
+ $ qfg serve --datadir ./our-config --environment production
1678
+
1679
+ $ qfg serve --port 6581 --frontend-sdk-key PUBLIC_KEY
1680
+ ```
1681
+
1682
+ _See code: [src/commands/serve.ts](https://github.com/quonfig/cli/blob/v0.0.54/src/commands/serve.ts)_
1625
1683
 
1626
1684
  ## `qfg set-default [NAME]`
1627
1685
 
@@ -1692,7 +1750,7 @@ EXAMPLES
1692
1750
  $ qfg pull && qfg config-schema
1693
1751
  ```
1694
1752
 
1695
- _See code: [src/commands/set-default.ts](https://github.com/quonfig/cli/blob/v0.0.52/src/commands/set-default.ts)_
1753
+ _See code: [src/commands/set-default.ts](https://github.com/quonfig/cli/blob/v0.0.54/src/commands/set-default.ts)_
1696
1754
 
1697
1755
  ## `qfg set-rollout [NAME]`
1698
1756
 
@@ -1769,7 +1827,7 @@ EXAMPLES
1769
1827
  $ qfg set-rollout my.variant.flag --environment production --weights "a:33,b:33,c:34" --hash-by user.id
1770
1828
  ```
1771
1829
 
1772
- _See code: [src/commands/set-rollout.ts](https://github.com/quonfig/cli/blob/v0.0.52/src/commands/set-rollout.ts)_
1830
+ _See code: [src/commands/set-rollout.ts](https://github.com/quonfig/cli/blob/v0.0.54/src/commands/set-rollout.ts)_
1773
1831
 
1774
1832
  ## `qfg sync`
1775
1833
 
@@ -1801,7 +1859,7 @@ EXAMPLES
1801
1859
  $ qfg sync --watch --dir ./our-config --interval 30
1802
1860
  ```
1803
1861
 
1804
- _See code: [src/commands/sync.ts](https://github.com/quonfig/cli/blob/v0.0.52/src/commands/sync.ts)_
1862
+ _See code: [src/commands/sync.ts](https://github.com/quonfig/cli/blob/v0.0.54/src/commands/sync.ts)_
1805
1863
 
1806
1864
  ## `qfg toggle [NAME]`
1807
1865
 
@@ -1903,7 +1961,7 @@ EXAMPLES
1903
1961
  $ qfg verify --json
1904
1962
  ```
1905
1963
 
1906
- _See code: [src/commands/verify.ts](https://github.com/quonfig/cli/blob/v0.0.52/src/commands/verify.ts)_
1964
+ _See code: [src/commands/verify.ts](https://github.com/quonfig/cli/blob/v0.0.54/src/commands/verify.ts)_
1907
1965
 
1908
1966
  ## `qfg whoami`
1909
1967
 
@@ -1926,7 +1984,7 @@ EXAMPLES
1926
1984
  $ qfg whoami
1927
1985
  ```
1928
1986
 
1929
- _See code: [src/commands/whoami.ts](https://github.com/quonfig/cli/blob/v0.0.52/src/commands/whoami.ts)_
1987
+ _See code: [src/commands/whoami.ts](https://github.com/quonfig/cli/blob/v0.0.54/src/commands/whoami.ts)_
1930
1988
 
1931
1989
  ## `qfg workspace`
1932
1990
 
@@ -1949,7 +2007,7 @@ EXAMPLES
1949
2007
  $ qfg workspace
1950
2008
  ```
1951
2009
 
1952
- _See code: [src/commands/workspace.ts](https://github.com/quonfig/cli/blob/v0.0.52/src/commands/workspace.ts)_
2010
+ _See code: [src/commands/workspace.ts](https://github.com/quonfig/cli/blob/v0.0.54/src/commands/workspace.ts)_
1953
2011
 
1954
2012
  ## `qfg workspace bootstrap`
1955
2013
 
@@ -1982,7 +2040,7 @@ EXAMPLES
1982
2040
  $ qfg workspace bootstrap --dir ./our-config --skip-validate
1983
2041
  ```
1984
2042
 
1985
- _See code: [src/commands/workspace/bootstrap.ts](https://github.com/quonfig/cli/blob/v0.0.52/src/commands/workspace/bootstrap.ts)_
2043
+ _See code: [src/commands/workspace/bootstrap.ts](https://github.com/quonfig/cli/blob/v0.0.54/src/commands/workspace/bootstrap.ts)_
1986
2044
 
1987
2045
  ## `qfg workspace create SLUG`
1988
2046
 
@@ -2016,7 +2074,7 @@ EXAMPLES
2016
2074
  $ qfg workspace create my-team --org 11111111-1111-1111-1111-111111111111
2017
2075
  ```
2018
2076
 
2019
- _See code: [src/commands/workspace/create.ts](https://github.com/quonfig/cli/blob/v0.0.52/src/commands/workspace/create.ts)_
2077
+ _See code: [src/commands/workspace/create.ts](https://github.com/quonfig/cli/blob/v0.0.54/src/commands/workspace/create.ts)_
2020
2078
 
2021
2079
  ## `qfg workspace switch [SLUG]`
2022
2080
 
@@ -2044,7 +2102,7 @@ EXAMPLES
2044
2102
  $ qfg workspace switch acme/production
2045
2103
  ```
2046
2104
 
2047
- _See code: [src/commands/workspace/switch.ts](https://github.com/quonfig/cli/blob/v0.0.52/src/commands/workspace/switch.ts)_
2105
+ _See code: [src/commands/workspace/switch.ts](https://github.com/quonfig/cli/blob/v0.0.54/src/commands/workspace/switch.ts)_
2048
2106
  <!-- commandsstop -->
2049
2107
 
2050
2108
  ## Local Development
@@ -19,5 +19,11 @@ export default class Migrate extends BaseCommand {
19
19
  workspace: import("@oclif/core/lib/interfaces/parser.js").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces/parser.js").CustomOptions>;
20
20
  };
21
21
  run(): Promise<JsonObj | void>;
22
+ /**
23
+ * After a local (non-push) migration commits, the user is left at a prompt
24
+ * with a fresh directory and no obvious next move. Spell out the review →
25
+ * push flow explicitly.
26
+ */
27
+ private printLocalNextSteps;
22
28
  private resolvePushWorkspace;
23
29
  }
@@ -5,6 +5,7 @@ import { BaseCommand } from '../index.js';
5
5
  import { CrossSourceError, assertSourceMatches, readImportState } from '../migrate/import-state.js';
6
6
  import { applyLocalMigration, MigratorKeyCollisionError } from '../migrate/local-write.js';
7
7
  import { buildPushConflictSuggestion } from '../migrate/migrate-suggestion.js';
8
+ import { migrationReportPath } from '../migrate/migration-report.js';
8
9
  import { PushConflictError, PushHookRejectedError } from '../util/clone-and-stack-push.js';
9
10
  import { MigratorVerifyError, pushMigrationToCloud } from '../migrate/push-to-cloud.js';
10
11
  import { UnknownSourceError, getSource } from '../migrate/registry.js';
@@ -20,6 +21,10 @@ import { displayUrl } from '../util/git-ops.js';
20
21
  import { resolveWorkspaceUuid } from '../util/resolve-workspace.js';
21
22
  import { loadAuthConfig } from '../util/token-storage.js';
22
23
  const DEFAULT_DIR = 'quonfig-repo';
24
+ // How many fetched changes between progress lines during the (silent,
25
+ // paginated) change-history fetch. Large accounts page through thousands of
26
+ // changes 50 at a time; without periodic output the CLI looks frozen.
27
+ const FETCH_PROGRESS_INTERVAL = 1000;
23
28
  export default class Migrate extends BaseCommand {
24
29
  static description = 'Migrate flags and configs from a legacy feature-flag system into a Quonfig workspace.\n\n' +
25
30
  'Currently supported sources:\n' +
@@ -172,9 +177,28 @@ export default class Migrate extends BaseCommand {
172
177
  return this.err(error.message);
173
178
  throw error;
174
179
  }
180
+ // The fetch and write phases below are silent for a long time on a large
181
+ // account. Print a plan up front and a step line before each slow phase so
182
+ // the CLI never looks frozen, even without --verbose.
183
+ this.log(`Migrating from ${flags.from} into ${dir}.`);
184
+ if (flags['dry-run']) {
185
+ this.log('Mode: dry run — changes are summarized but nothing is written.');
186
+ }
187
+ else if (flags.push) {
188
+ this.log('Mode: migrate to a local dir, then push to the Quonfig cloud workspace.');
189
+ }
190
+ else {
191
+ this.log('Mode: local migration only — re-run with --push to also publish to a cloud workspace.');
192
+ }
193
+ this.log('');
175
194
  let duplicateResolutionsForWarn = null;
195
+ // Set to the target dir once a local (non-push) migration commits, so the
196
+ // `finally` block can print "what now?" guidance after the warnings.
197
+ let localNextStepsDir = null;
176
198
  try {
199
+ this.log(`Authenticating with ${flags.from}...`);
177
200
  await source.validateAuth(sourceApiKey);
201
+ this.log(`Reading the environment list from ${flags.from}...`);
178
202
  const environments = await source.listEnvironments();
179
203
  // Plan §4.1.1: tell the user the real history horizon BEFORE the slow
180
204
  // Phase-2 walk starts. validateAuth populated this for LD under
@@ -187,8 +211,15 @@ export default class Migrate extends BaseCommand {
187
211
  }
188
212
  const existing = readImportState(dir);
189
213
  const sinceEpochMs = computeSince(flags, existing);
214
+ this.log(`Fetching change history from ${flags.from} — this can take a few minutes for a large account...`);
190
215
  const changes = [];
191
- for await (const change of source.fetchChanges(sinceEpochMs)) {
216
+ let lastReportedFetch = 0;
217
+ for await (const change of source.fetchChanges(sinceEpochMs, (fetched) => {
218
+ if (fetched - lastReportedFetch >= FETCH_PROGRESS_INTERVAL) {
219
+ lastReportedFetch = fetched;
220
+ this.log(` ...fetched ${fetched} change(s) so far`);
221
+ }
222
+ })) {
192
223
  changes.push(change);
193
224
  }
194
225
  const toProcess = flags.recent === undefined ? changes : changes.slice(-flags.recent);
@@ -239,6 +270,8 @@ export default class Migrate extends BaseCommand {
239
270
  this.log(result.committed
240
271
  ? `Pushed ${toProcess.length} change(s). commit=${result.commitSha?.slice(0, 8) ?? ''} action=${result.action}`
241
272
  : `No net changes produced by this run. Nothing to commit or push.`);
273
+ this.log(`Migration report written to ${migrationReportPath(dir)} — review it before cutover ` +
274
+ '(it lives in the hidden .qf/ directory).');
242
275
  return {
243
276
  ...payload,
244
277
  action: result.action,
@@ -285,6 +318,10 @@ export default class Migrate extends BaseCommand {
285
318
  this.log(localResult.committed
286
319
  ? `Committed ${toProcess.length} change(s). commit=${localResult.commitSha?.slice(0, 8) ?? ''} action=${localResult.action}`
287
320
  : `No net changes produced by this run. Nothing to commit.`);
321
+ // Print "what now?" guidance from the `finally` block (after the
322
+ // warnings) so it is the last thing the user sees.
323
+ if (localResult.committed)
324
+ localNextStepsDir = dir;
288
325
  return {
289
326
  ...payload,
290
327
  action: localResult.action,
@@ -307,8 +344,33 @@ export default class Migrate extends BaseCommand {
307
344
  warnAboutCoercedSentinels(this, source.getCoercedSentinels?.() ?? null);
308
345
  warnAboutDuplicateResolutions(this, duplicateResolutionsForWarn);
309
346
  warnAboutConversionNotes(this, source.getConversionNotes?.() ?? null);
347
+ if (localNextStepsDir)
348
+ this.printLocalNextSteps(localNextStepsDir);
310
349
  }
311
350
  }
351
+ /**
352
+ * After a local (non-push) migration commits, the user is left at a prompt
353
+ * with a fresh directory and no obvious next move. Spell out the review →
354
+ * push flow explicitly.
355
+ */
356
+ printLocalNextSteps(dir) {
357
+ this.log('');
358
+ this.log('Migration written to a local directory — nothing has been pushed to Quonfig cloud yet.');
359
+ this.log('');
360
+ this.log('Next steps:');
361
+ this.log(` 1. Review the migrated config files in ${dir}`);
362
+ this.log(' 2. Read the migration report — it lists every config that was skipped,');
363
+ this.log(' coerced, or needs a manual follow-up:');
364
+ this.log(` ${migrationReportPath(dir)}`);
365
+ this.log(' (it lives in the hidden .qf/ directory — use `ls -a` to see it)');
366
+ this.log(' 3. Publish to a Quonfig workspace once the migration looks right:');
367
+ this.log(` qfg push --dir ${dir} --workspace <org-slug>/<workspace-slug>`);
368
+ this.log(' (run `qfg login` first if you have not). You can also re-run this command');
369
+ this.log(' with `--push --workspace <org-slug>/<workspace-slug>` to migrate and push');
370
+ this.log(' in one step.');
371
+ this.log('');
372
+ this.log('Re-running `qfg migrate` later picks up only the changes made since this run.');
373
+ }
312
374
  async resolvePushWorkspace(slugOrId) {
313
375
  const authConfig = await loadAuthConfig();
314
376
  if (!authConfig)
@@ -368,7 +430,7 @@ function warnAboutDroppedOverrides(cmd, dropped) {
368
430
  cmd.warn(` - ${flagPath} (${perFlag[flagPath]})`);
369
431
  }
370
432
  }
371
- cmd.warn(`If any of these envs are still in use, restore them in the source system and re-run the migration. Full detail is also written to MIGRATION_REPORT.md.`);
433
+ cmd.warn(`If any of these envs are still in use, restore them in the source system and re-run the migration. Full detail is also written to .qf/MIGRATION_REPORT.md.`);
372
434
  }
373
435
  function warnAboutDuplicateResolutions(cmd, resolved) {
374
436
  if (!resolved || resolved.total === 0)
@@ -378,7 +440,7 @@ function warnAboutDuplicateResolutions(cmd, resolved) {
378
440
  for (const entry of sorted) {
379
441
  cmd.warn(` ${entry.key} (${entry.collisionTypes.join(', ')}): kept ${entry.kept}, deleted ${entry.deleted.join(', ')}`);
380
442
  }
381
- cmd.warn('Full detail is also written to MIGRATION_REPORT.md.');
443
+ cmd.warn('Full detail is also written to .qf/MIGRATION_REPORT.md.');
382
444
  }
383
445
  function warnAboutCoercedSentinels(cmd, coerced) {
384
446
  if (!coerced || coerced.total === 0)
@@ -393,7 +455,7 @@ function warnAboutCoercedSentinels(cmd, coerced) {
393
455
  cmd.warn(` - ${flagPath} (${perFlag[flagPath]})`);
394
456
  }
395
457
  }
396
- cmd.warn(`If you want a real default for these rules, set one in the source system and re-run the migration. Full detail is also written to MIGRATION_REPORT.md.`);
458
+ cmd.warn(`If you want a real default for these rules, set one in the source system and re-run the migration. Full detail is also written to .qf/MIGRATION_REPORT.md.`);
397
459
  }
398
460
  function warnAboutConversionNotes(cmd, notes) {
399
461
  if (!notes || notes.length === 0)
@@ -402,12 +464,12 @@ function warnAboutConversionNotes(cmd, notes) {
402
464
  if (rebucketed.length > 0) {
403
465
  cmd.warn(`${rebucketed.length} flag(s)/segment(s) use a percentage rollout — LaunchDarkly and Quonfig bucket users ` +
404
466
  `differently, so individual user assignments WILL change after migration (the rollout percentage is preserved). ` +
405
- `See the "Users will be re-bucketed" section of MIGRATION_REPORT.md.`);
467
+ `See the "Users will be re-bucketed" section of .qf/MIGRATION_REPORT.md.`);
406
468
  }
407
469
  const other = notes.filter((n) => n.category !== 'rebucketed-rollout' && n.category !== 'skipped-config');
408
470
  if (other.length > 0) {
409
471
  cmd.warn(`${other.length} source concept(s) could not be converted exactly (dropped prerequisites, lossy individual ` +
410
- `targets, etc.). Nothing was silently dropped — see the "Conversion notes" section of MIGRATION_REPORT.md.`);
472
+ `targets, etc.). Nothing was silently dropped — see the "Conversion notes" section of .qf/MIGRATION_REPORT.md.`);
411
473
  }
412
474
  }
413
475
  function warnAboutSkippedConfigs(cmd, skipped) {
@@ -418,7 +480,7 @@ function warnAboutSkippedConfigs(cmd, skipped) {
418
480
  for (const entry of sorted) {
419
481
  cmd.warn(` ${entry.key}: ${entry.reason}`);
420
482
  }
421
- cmd.warn('Full detail is also written to MIGRATION_REPORT.md.');
483
+ cmd.warn('Full detail is also written to .qf/MIGRATION_REPORT.md.');
422
484
  }
423
485
  function resolveTargetDir(dirFlag, cwd) {
424
486
  if (dirFlag)
@@ -238,9 +238,15 @@ export function buildRealDeps(cmd, orgSlug) {
238
238
  }
239
239
  },
240
240
  async getOriginMainSha(dir) {
241
- // qfg-gj3i: clone-path returns the local origin/main SHA after
242
- // fetch. Bare path has no `.git/` to rev-parse — return undefined
243
- // and let the server apply its bare-path lock policy.
241
+ // Bare path: `diffHeadVsOrigin` (always called first by runPush)
242
+ // populated the probe clone. Its HEAD is our view of the workspace
243
+ // tip — and is exactly what the diff was computed against — so it is
244
+ // the correct `expectedSha` for the server-side optimistic lock
245
+ // (qfg-gj3i bare-path follow-up, qfg-nhcb). Without it the bare-path
246
+ // push omits expectedSha and the server rejects it with a 426.
247
+ if (barePathProbe)
248
+ return barePathProbe.remoteHeadSha;
249
+ // Clone path: the local origin/main SHA after fetch.
244
250
  if (!(await isGitRepo(dir)))
245
251
  return;
246
252
  return getOriginMainSha(dir);
@@ -241,7 +241,6 @@ The flag separator '--' is REQUIRED between qfg flags and the child command.`;
241
241
  const quonfig = new Quonfig({
242
242
  sdkKey,
243
243
  collectEvaluationSummaries: false,
244
- collectLoggerCounts: false,
245
244
  contextUploadMode: 'none',
246
245
  enableSSE: false,
247
246
  apiUrls: [getDeliveryUrl()],