@quonfig/cli 0.3.0 → 0.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (49) hide show
  1. package/README.md +157 -75
  2. package/dist/agent/skill-bundle.generated.d.ts +1 -1
  3. package/dist/agent/skill-bundle.generated.js +4 -4
  4. package/dist/codegen/code-generators/base-typescript-generator.d.ts +1 -1
  5. package/dist/codegen/schema-extractor.d.ts +1 -1
  6. package/dist/commands/config-schema.js +15 -8
  7. package/dist/commands/create.d.ts +3 -1
  8. package/dist/commands/create.js +93 -20
  9. package/dist/commands/get.d.ts +1 -0
  10. package/dist/commands/get.js +40 -3
  11. package/dist/commands/info.js +10 -1
  12. package/dist/commands/set-default.d.ts +2 -0
  13. package/dist/commands/set-default.js +70 -18
  14. package/dist/index.d.ts +6 -0
  15. package/dist/index.js +35 -3
  16. package/dist/interactive-prompt.d.ts +18 -0
  17. package/dist/interactive-prompt.js +11 -2
  18. package/dist/migrate/quonfig-target/operators.js +4 -2
  19. package/dist/migrate/quonfig-target/ruleset.d.ts +48 -0
  20. package/dist/migrate/quonfig-target/ruleset.js +132 -8
  21. package/dist/migrate/sources/flagsmith/translate.js +11 -0
  22. package/dist/migrate/sources/launchdarkly/translate.js +19 -16
  23. package/dist/push/git-pack.d.ts +12 -0
  24. package/dist/push/git-pack.js +27 -3
  25. package/dist/push/run-push.d.ts +2 -1
  26. package/dist/push/run-push.js +1 -2
  27. package/dist/ui/get-string.d.ts +18 -1
  28. package/dist/ui/get-string.js +20 -5
  29. package/dist/ui/get-value.d.ts +3 -1
  30. package/dist/ui/get-value.js +7 -7
  31. package/dist/util/clone-and-stack-push.js +8 -3
  32. package/dist/util/encryption.js +11 -20
  33. package/dist/util/git-ops.d.ts +4 -2
  34. package/dist/util/git-ops.js +4 -2
  35. package/dist/util/redact.d.ts +56 -0
  36. package/dist/util/redact.js +98 -0
  37. package/dist/util/value-source.d.ts +30 -0
  38. package/dist/util/value-source.js +81 -0
  39. package/dist/verify/regex-dialect.d.ts +39 -0
  40. package/dist/verify/regex-dialect.js +278 -0
  41. package/dist/verify/standalone.d.ts +3 -1
  42. package/dist/verify/standalone.js +4 -19
  43. package/dist/verify/validate.js +70 -2
  44. package/dist/verify/value-grammar.d.ts +7 -0
  45. package/dist/verify/value-grammar.js +52 -0
  46. package/dist/version.d.ts +1 -1
  47. package/dist/version.js +1 -1
  48. package/oclif.manifest.json +236 -192
  49. package/package.json +18 -16
@@ -292,12 +292,16 @@
292
292
  "required": true
293
293
  }
294
294
  },
295
- "description": "Create a new feature flag, config value, or other item.\n\nUse --type to specify the kind of item:\n boolean-flag On/off feature flag (sendToClientSdk defaults to true; best for gradual rollouts)\n string A string configuration value\n int An integer configuration value\n double A floating-point configuration value\n string-list A comma-separated list of strings\n json An arbitrary JSON blob\n boolean A plain boolean (not a feature flag)\n duration An ISO 8601 duration string, e.g. PT30S, PT5M, PT1H30M (SDK returns milliseconds)\n log_level A dynamic log level (value must be one of TRACE/DEBUG/INFO/WARN/ERROR/FATAL)\n\nThis sets the global default value. Override per-environment with:\n qfg set-default my.flag --environment production --value true\n\nFor a percentage rollout (gradual rollout / A/B test / canary deploy), use:\n qfg set-rollout my.flag --environment production --true-percent 20\n\nOr edit the JSON config file directly for complex targeting rules:\n qfg config-schema # full operator reference + examples\n qfg pull --dir ./config # clone workspace, then edit JSON and git push\n\nLog levels:\n qfg create log-level.my-app --type log_level --value WARN\n # Log-level keys must start with \"log-level.\".\n # For per-logger targeting, create ONE log-level config per service and add\n # rules on the \"quonfig-sdk-logging.key\" context property (e.g.\n # PROP_STARTS_WITH_ONE_OF MyPackage.) rather than one config per logger.\n\nWhen this flag has done its job, mark readyForCleanup: true in the UI and run `qfg cleanup list` to retire it.",
295
+ "description": "Create a new feature flag, config value, or other item.\n\nUse --type to specify the kind of item:\n boolean-flag On/off feature flag (sendToClientSdk defaults to true; best for gradual rollouts)\n string A string configuration value\n int An integer configuration value\n double A floating-point configuration value\n string-list A comma-separated list of strings\n json An arbitrary JSON blob\n boolean A plain boolean (not a feature flag)\n duration An ISO 8601 duration string, e.g. PT30S, PT5M, PT1H30M (SDK returns milliseconds)\n log_level A dynamic log level (value must be one of TRACE/DEBUG/INFO/WARN/ERROR/FATAL)\n\nSecrets (--secret) are encrypted client-side and are STRING-ONLY: --secret\nimplies --type string, so you can leave --type off. To store a JSON secret, store the JSON as a string secret and\nJSON.parse it in your app. The CLI never prints a secret's plaintext: it shows\na redacted fingerprint like [encrypted *****3fa9c, 51 chars, ends …a1b2].\n\nKeep the value out of argv / shell history / agent transcripts with:\n --value-stdin read the value from stdin\n --value-from-env=VAR read the value from a local env var, now\nThese are different from --env-var, which stores NO value: it tells the SDK to\nread the value from that env var at runtime.\n\nThis sets the global default value. Override per-environment with:\n qfg set-default my.flag --environment production --value true\n\nFor a percentage rollout (gradual rollout / A/B test / canary deploy), use:\n qfg set-rollout my.flag --environment production --true-percent 20\n\nOr edit the JSON config file directly for complex targeting rules:\n qfg config-schema # full operator reference + examples\n qfg pull --dir ./config # clone workspace, then edit JSON and git push\n\nLog levels:\n qfg create log-level.my-app --type log_level --value WARN\n # Log-level keys must start with \"log-level.\".\n # For per-logger targeting, create ONE log-level config per service and add\n # rules on the \"quonfig-sdk-logging.key\" context property (e.g.\n # PROP_STARTS_WITH_ONE_OF MyPackage.) rather than one config per logger.\n\nWhen this flag has done its job, mark readyForCleanup: true in the UI and run `qfg cleanup list` to retire it.",
296
296
  "examples": [
297
297
  "<%= config.bin %> <%= command.id %> my.new.flag --type boolean-flag",
298
298
  "<%= config.bin %> <%= command.id %> my.new.flag --type boolean-flag --value=true",
299
299
  "<%= config.bin %> <%= command.id %> my.new.string --type string --value=\"hello world\"",
300
- "<%= config.bin %> <%= command.id %> my.new.string --type string --value=\"hello world\" --secret",
300
+ "# Create a secret without the value ever appearing in argv (--secret implies --type string):",
301
+ "pbpaste | <%= config.bin %> <%= command.id %> stripe.api-key --secret --value-stdin",
302
+ "<%= config.bin %> <%= command.id %> stripe.api-key --secret --value-from-env STRIPE_API_KEY",
303
+ "# A JSON secret is a string secret holding JSON (JSON.parse it in your app):",
304
+ "<%= config.bin %> <%= command.id %> gcp.service-account --secret --value-stdin < sa.json",
301
305
  "<%= config.bin %> <%= command.id %> my.new.string --type string --env-var=MY_ENV_VAR_NAME",
302
306
  "<%= config.bin %> <%= command.id %> my.new.string --type json --value=\"{\\\"key\\\": \\\"value\\\"}\"",
303
307
  "<%= config.bin %> <%= command.id %> my.timeout --type duration --value PT90S",
@@ -363,15 +367,15 @@
363
367
  "type": "boolean"
364
368
  },
365
369
  "env-var": {
366
- "description": "environment variable to get value from",
370
+ "description": "store no value: the SDK reads it from this env var at RUNTIME. To read a value from a local env var NOW, use --value-from-env",
367
371
  "name": "env-var",
368
372
  "hasDynamicHelp": false,
369
373
  "multiple": false,
370
374
  "type": "option"
371
375
  },
372
376
  "type": {
377
+ "description": "kind of item to create (required, except with --secret, which implies string)",
373
378
  "name": "type",
374
- "required": true,
375
379
  "hasDynamicHelp": false,
376
380
  "multiple": false,
377
381
  "options": [
@@ -388,15 +392,29 @@
388
392
  "type": "option"
389
393
  },
390
394
  "value": {
391
- "description": "default value for your new item",
395
+ "description": "default value for your new item (for secrets prefer --value-stdin / --value-from-env)",
392
396
  "name": "value",
393
397
  "required": false,
394
398
  "hasDynamicHelp": false,
395
399
  "multiple": false,
396
400
  "type": "option"
397
401
  },
402
+ "value-from-env": {
403
+ "description": "read the value to store from this LOCAL env var now (keeps it out of argv/shell history). Not the same as --env-var",
404
+ "name": "value-from-env",
405
+ "hasDynamicHelp": false,
406
+ "helpValue": "VAR",
407
+ "multiple": false,
408
+ "type": "option"
409
+ },
410
+ "value-stdin": {
411
+ "description": "read the value to store from stdin (one trailing newline is stripped). Keeps it out of argv",
412
+ "name": "value-stdin",
413
+ "allowNo": false,
414
+ "type": "boolean"
415
+ },
398
416
  "secret": {
399
- "description": "encrypt the value of this item",
417
+ "description": "encrypt the value of this item (string-only; the CLI never prints the plaintext)",
400
418
  "name": "secret",
401
419
  "allowNo": false,
402
420
  "type": "boolean"
@@ -663,10 +681,12 @@
663
681
  "name": "name"
664
682
  }
665
683
  },
666
- "description": "Get the value of a config/feature-flag/etc.",
684
+ "description": "Get the value of a config/feature-flag/etc.\n\nSecrets (encrypted) and confidential values print REDACTED by default, as a\nfingerprint plus length (and the last 4 characters for values of 12+ chars):\n [encrypted *****3fa9c, 51 chars, ends …a1b2]\nThe fingerprint is the same one SDK telemetry and the Quonfig UI show, so you\ncan confirm a rotation landed without printing the secret. Pass --reveal to\nprint the plaintext. To inject secrets into a process, prefer `qfg run`.",
667
685
  "examples": [
668
686
  "<%= config.bin %> <%= command.id %> my.config.name",
669
- "<%= config.bin %> <%= command.id %> my.config.name --environment=production"
687
+ "<%= config.bin %> <%= command.id %> my.config.name --environment=production",
688
+ "<%= config.bin %> <%= command.id %> stripe.api-key --environment=production # redacted fingerprint",
689
+ "<%= config.bin %> <%= command.id %> stripe.api-key --environment=production --reveal # plaintext"
670
690
  ],
671
691
  "flags": {
672
692
  "json": {
@@ -725,6 +745,12 @@
725
745
  "hasDynamicHelp": false,
726
746
  "multiple": false,
727
747
  "type": "option"
748
+ },
749
+ "reveal": {
750
+ "description": "print the plaintext of a secret/confidential value (it is redacted by default)",
751
+ "name": "reveal",
752
+ "allowNo": false,
753
+ "type": "boolean"
728
754
  }
729
755
  },
730
756
  "hasDynamicHelp": false,
@@ -2308,12 +2334,16 @@
2308
2334
  "name": "name"
2309
2335
  }
2310
2336
  },
2311
- "description": "Set the fallback value for a flag or config in one environment.\n\nThe fallback is the unconditional rule at the end of the environment's rule\nlist: what users receive when no targeting rule matches. Targeting rules and\npercentage rollouts above it are kept, and the command tells you how many.\nIf the environment has no rules of its own yet, they are copied from the\nflag's default rules first, so inherited targeting is kept too.\n\nTo turn a flag on or off for EVERYONE, including users matched by targeting\nrules, add --replace-targeting. This deletes the environment's targeting\nrules (they stay in git history).\n\nTo set a percentage rollout (gradual rollout / A/B test / canary deploy) instead:\n qfg set-rollout my.flag --environment production --true-percent 20\n\nTo see all current values and rules for a flag:\n qfg info my.flag\n\nTo target specific organizations or users, write rules on their KEY\n(organization.key, user.key), not a slug or email; find a key from a name with:\n qfg contexts search organization formhealth",
2337
+ "description": "Set the fallback value for a flag or config in one environment.\n\nThe fallback is the unconditional rule at the end of the environment's rule\nlist: what users receive when no targeting rule matches. Targeting rules and\npercentage rollouts above it are kept, and the command tells you how many.\nIf the environment has no rules of its own yet, they are copied from the\nflag's default rules first, so inherited targeting is kept too.\n\nTo turn a flag on or off for EVERYONE, including users matched by targeting\nrules, add --replace-targeting. This deletes the environment's targeting\nrules (they stay in git history).\n\nTo set a percentage rollout (gradual rollout / A/B test / canary deploy) instead:\n qfg set-rollout my.flag --environment production --true-percent 20\n\nSecrets (--secret, or any config whose value is already encrypted) are\nSTRING-ONLY. To store a JSON secret, make it a string secret holding the JSON\nand JSON.parse it in your app. The CLI never prints a secret's plaintext; it\nshows a redacted fingerprint like [encrypted *****3fa9c, 51 chars, ends …a1b2].\nRotate a secret without the value entering argv / shell history:\n pbpaste | qfg set-default stripe.api-key --environment production --secret --value-stdin --confirm\n qfg set-default stripe.api-key --environment production --secret --value-from-env STRIPE_API_KEY --confirm\n(--env-var is different: it stores NO value and tells the SDK to read one from\nthat env var at runtime.)\n\nTo see all current values and rules for a flag:\n qfg info my.flag\n\nTo target specific organizations or users, write rules on their KEY\n(organization.key, user.key), not a slug or email; find a key from a name with:\n qfg contexts search organization formhealth",
2312
2338
  "examples": [
2313
2339
  "<%= config.bin %> <%= command.id %> my.flag.name # prompts for value and env",
2314
2340
  "<%= config.bin %> <%= command.id %> my.flag.name --value=true --environment=staging",
2315
2341
  "<%= config.bin %> <%= command.id %> my.flag.name --value=false --environment=production --replace-targeting # kill-switch: off for everyone",
2316
- "<%= config.bin %> <%= command.id %> my.flag.name --value=true --secret",
2342
+ "# Rotate a secret without the value entering argv:",
2343
+ "pbpaste | <%= config.bin %> <%= command.id %> my.secret --environment=production --secret --value-stdin --confirm",
2344
+ "<%= config.bin %> <%= command.id %> my.secret --environment=production --secret --value-from-env=MY_SECRET --confirm",
2345
+ "# Write the [Default] rules (inherited by every environment without its own):",
2346
+ "<%= config.bin %> <%= command.id %> my.secret --environment=\"[Default]\" --secret --value-from-env=MY_SECRET --confirm",
2317
2347
  "<%= config.bin %> <%= command.id %> my.config.name --env-var=MY_ENV_VAR_NAME --environment=production",
2318
2348
  "# For a percentage rollout, use set-rollout instead:",
2319
2349
  "<%= config.bin %> set-rollout my.flag.name --environment production --true-percent 20",
@@ -2378,14 +2408,14 @@
2378
2408
  "type": "boolean"
2379
2409
  },
2380
2410
  "env-var": {
2381
- "description": "environment variable to use as default value",
2411
+ "description": "store no value: the SDK reads it from this env var at RUNTIME. To read a value from a local env var NOW, use --value-from-env",
2382
2412
  "name": "env-var",
2383
2413
  "hasDynamicHelp": false,
2384
2414
  "multiple": false,
2385
2415
  "type": "option"
2386
2416
  },
2387
2417
  "environment": {
2388
- "description": "environment to change",
2418
+ "description": "environment to change, e.g. production. Use \"[Default]\" for the default rules that every environment without its own rules inherits",
2389
2419
  "name": "environment",
2390
2420
  "hasDynamicHelp": false,
2391
2421
  "multiple": false,
@@ -2398,12 +2428,26 @@
2398
2428
  "type": "boolean"
2399
2429
  },
2400
2430
  "value": {
2401
- "description": "new default value",
2431
+ "description": "new default value (for secrets prefer --value-stdin / --value-from-env)",
2402
2432
  "name": "value",
2403
2433
  "hasDynamicHelp": false,
2404
2434
  "multiple": false,
2405
2435
  "type": "option"
2406
2436
  },
2437
+ "value-from-env": {
2438
+ "description": "read the value to store from this LOCAL env var now (keeps it out of argv/shell history). Not the same as --env-var",
2439
+ "name": "value-from-env",
2440
+ "hasDynamicHelp": false,
2441
+ "helpValue": "VAR",
2442
+ "multiple": false,
2443
+ "type": "option"
2444
+ },
2445
+ "value-stdin": {
2446
+ "description": "read the value to store from stdin (one trailing newline is stripped). Keeps it out of argv",
2447
+ "name": "value-stdin",
2448
+ "allowNo": false,
2449
+ "type": "boolean"
2450
+ },
2407
2451
  "confirm": {
2408
2452
  "description": "confirm without prompt",
2409
2453
  "name": "confirm",
@@ -2411,7 +2455,7 @@
2411
2455
  "type": "boolean"
2412
2456
  },
2413
2457
  "secret": {
2414
- "description": "encrypt the value of this item",
2458
+ "description": "encrypt the value of this item (string-only; the CLI never prints the plaintext)",
2415
2459
  "name": "secret",
2416
2460
  "allowNo": false,
2417
2461
  "type": "boolean"
@@ -2816,18 +2860,17 @@
2816
2860
  "workspace.js"
2817
2861
  ]
2818
2862
  },
2819
- "activity:deleted": {
2863
+ "cleanup:list": {
2820
2864
  "aliases": [],
2821
2865
  "args": {},
2822
- "description": "List configs that were deleted from the workspace and have not been restored.\n\nUseful for \"did somebody delete X?\" — pair with `qfg activity restore NAME`\nto undelete a tombstoned config.",
2866
+ "description": "List feature flags marked readyForCleanup=true, with eval volume per window.\n\nColumns:\n KEY the flag key\n TYPE the flag's valueType (bool, string, int, etc.)\n EVALS_24H evals counted in today's bucket (latest day)\n EVALS_2D evals in the last 2 calendar days\n EVALS_7D evals in the last 7 calendar days\n EVALS_30D evals in the last 30 calendar days\n LAST_EVAL most recent calendar day with any evals (UTC), blank if none\n CLASS quiet (zero evals in last 2 days) or active\n\nDefault sort: quiet first, oldest LAST_EVAL at top.\n\nPass --json for the structured object (rows[]). Each row carries the columns\nabove plus the raw eval counts your agent can reason about itself.\n\nOnce you've picked a candidate, run `qfg cleanup status <key>` for the\ndrill-in, or `qfg cleanup remove <key>` to hand the removal to your coding agent\nwith the Quonfig agent skill.",
2823
2867
  "examples": [
2824
2868
  "<%= config.bin %> <%= command.id %>",
2825
2869
  "<%= config.bin %> <%= command.id %> --json"
2826
2870
  ],
2827
2871
  "flags": {
2828
2872
  "json": {
2829
- "description": "Format output as json.",
2830
- "helpGroup": "GLOBAL",
2873
+ "description": "Return structured rows for agent consumption",
2831
2874
  "name": "json",
2832
2875
  "allowNo": false,
2833
2876
  "type": "boolean"
@@ -2878,7 +2921,7 @@
2878
2921
  },
2879
2922
  "hasDynamicHelp": false,
2880
2923
  "hiddenAliases": [],
2881
- "id": "activity:deleted",
2924
+ "id": "cleanup:list",
2882
2925
  "pluginAlias": "@quonfig/cli",
2883
2926
  "pluginName": "@quonfig/cli",
2884
2927
  "pluginType": "core",
@@ -2888,18 +2931,23 @@
2888
2931
  "relativePath": [
2889
2932
  "dist",
2890
2933
  "commands",
2891
- "activity",
2892
- "deleted.js"
2934
+ "cleanup",
2935
+ "list.js"
2893
2936
  ]
2894
2937
  },
2895
- "activity:feed": {
2938
+ "cleanup:remove": {
2896
2939
  "aliases": [],
2897
- "args": {},
2898
- "description": "Recent activity across the workspace, newest first.\n\nEach entry shows who changed which config, the action (created/updated/deleted/restored),\nand the human-readable audit message produced by the server. The server already\ntranslates JSON diffs into messages — this command does not re-translate.",
2940
+ "args": {
2941
+ "name": {
2942
+ "description": "config/feature-flag/etc. name",
2943
+ "name": "name"
2944
+ }
2945
+ },
2946
+ "description": "Write a cleanup payload for a ready-for-cleanup flag and hand off to the Quonfig agent skill.\n\nModeled on `qfg migrate my-code` — this command never edits source files\nitself. It validates that the flag is marked readyForCleanup=true, refuses to\nproceed if there are still evals_2d > 0 (use --force to override), writes\n`.qf/cleanup/<key>.json` describing the flag's current rule shape +\ntelemetry, and prints how to have your coding agent remove the call sites with\nthe quonfig agent skill (its references/retire-a-flag.md), which asks the\nengineer which value should \"win\" and applies the inlining. Install the skill\nwith `qfg agent install-skill` or `claude plugin install quonfig@quonfig`.\n\nThe payload deliberately does NOT suggest a winning value; that's the\nengineer's call. Run `qfg cleanup status <key>` first if you want to inspect\ntelemetry before retiring.",
2899
2947
  "examples": [
2900
- "<%= config.bin %> <%= command.id %>",
2901
- "<%= config.bin %> <%= command.id %> --limit 5",
2902
- "<%= config.bin %> <%= command.id %> --json"
2948
+ "<%= config.bin %> <%= command.id %> my.flag.key",
2949
+ "<%= config.bin %> <%= command.id %> my.flag.key --force",
2950
+ "<%= config.bin %> <%= command.id %> my.flag.key --json"
2903
2951
  ],
2904
2952
  "flags": {
2905
2953
  "json": {
@@ -2952,18 +3000,16 @@
2952
3000
  "multiple": false,
2953
3001
  "type": "option"
2954
3002
  },
2955
- "limit": {
2956
- "description": "Maximum number of feed entries (1-100)",
2957
- "name": "limit",
2958
- "default": 30,
2959
- "hasDynamicHelp": false,
2960
- "multiple": false,
2961
- "type": "option"
3003
+ "force": {
3004
+ "description": "Skip the evals_2d > 0 safety gate (useful when telemetry is delayed but you know the flag is dead)",
3005
+ "name": "force",
3006
+ "allowNo": false,
3007
+ "type": "boolean"
2962
3008
  }
2963
3009
  },
2964
3010
  "hasDynamicHelp": false,
2965
3011
  "hiddenAliases": [],
2966
- "id": "activity:feed",
3012
+ "id": "cleanup:remove",
2967
3013
  "pluginAlias": "@quonfig/cli",
2968
3014
  "pluginName": "@quonfig/cli",
2969
3015
  "pluginType": "core",
@@ -2973,11 +3019,11 @@
2973
3019
  "relativePath": [
2974
3020
  "dist",
2975
3021
  "commands",
2976
- "activity",
2977
- "feed.js"
3022
+ "cleanup",
3023
+ "remove.js"
2978
3024
  ]
2979
3025
  },
2980
- "activity:history": {
3026
+ "cleanup:status": {
2981
3027
  "aliases": [],
2982
3028
  "args": {
2983
3029
  "name": {
@@ -2985,15 +3031,14 @@
2985
3031
  "name": "name"
2986
3032
  }
2987
3033
  },
2988
- "description": "Per-config audit trail for a flag, config, log-level, segment, or schema.\n\nResolves NAME against the workspace metadata (no need to specify type) and\nreturns the full commit history for that file with audit messages translated\nby the server. Restored entries are rendered distinctly so a recovery doesn't\nlook like a fresh create.",
3034
+ "description": "Drill into one ready-for-cleanup flag — show telemetry across all environments and the current rule shape.\n\nUse this after `qfg cleanup list` to inspect a specific flag before handing\nremoval off to the Quonfig agent skill. The eval counts come from\nanalytics.configSparklines (the same backing data the per-flag sparklines on\nthe flag detail page use), summed into 24h/2d/7d/30d windows so you can decide\nwhether it's safe to retire.\n\nPass --json for the structured object including the full rule shape per\nenvironment — the agent skill consumes this directly.",
2989
3035
  "examples": [
2990
- "<%= config.bin %> <%= command.id %> my.flag",
2991
- "<%= config.bin %> <%= command.id %> request.timeout --json"
3036
+ "<%= config.bin %> <%= command.id %> my.flag.key",
3037
+ "<%= config.bin %> <%= command.id %> my.flag.key --json"
2992
3038
  ],
2993
3039
  "flags": {
2994
3040
  "json": {
2995
- "description": "Format output as json.",
2996
- "helpGroup": "GLOBAL",
3041
+ "description": "Return structured object for agent consumption",
2997
3042
  "name": "json",
2998
3043
  "allowNo": false,
2999
3044
  "type": "boolean"
@@ -3044,7 +3089,7 @@
3044
3089
  },
3045
3090
  "hasDynamicHelp": false,
3046
3091
  "hiddenAliases": [],
3047
- "id": "activity:history",
3092
+ "id": "cleanup:status",
3048
3093
  "pluginAlias": "@quonfig/cli",
3049
3094
  "pluginName": "@quonfig/cli",
3050
3095
  "pluginType": "core",
@@ -3054,11 +3099,11 @@
3054
3099
  "relativePath": [
3055
3100
  "dist",
3056
3101
  "commands",
3057
- "activity",
3058
- "history.js"
3102
+ "cleanup",
3103
+ "status.js"
3059
3104
  ]
3060
3105
  },
3061
- "activity:restore": {
3106
+ "cleanup:verify": {
3062
3107
  "aliases": [],
3063
3108
  "args": {
3064
3109
  "name": {
@@ -3066,15 +3111,16 @@
3066
3111
  "name": "name"
3067
3112
  }
3068
3113
  },
3069
- "description": "Undelete a config that was previously removed.\n\nLooks up the most recent deletion for the key (so you see who deleted it and when),\nthen asks for confirmation before re-creating the file from the prior content.\nSchemas cannot be restored — use git history instead.",
3114
+ "description": "Confirm zero evals for a flag in the trailing N days (default 7). Exits 0 if safe to delete, non-zero otherwise.\n\nRead-only gate intended for chaining with `qfg delete` after a cleanup PR\nhas merged and the SDK has redeployed:\n\n qfg cleanup verify my.flag.key && qfg delete my.flag.key\n\nThe trailing window is stricter than the `qfg cleanup remove` 2-day gate on\npurpose — `remove` only writes a payload describing the flag, but `delete`\npermanently removes the flag definition, so we want a longer quiet period\nbefore chaining. Bump --days N if you want a more conservative window.",
3070
3115
  "examples": [
3071
- "<%= config.bin %> <%= command.id %> my.flag --yes",
3072
- "<%= config.bin %> <%= command.id %> request.timeout --type config --yes"
3116
+ "<%= config.bin %> <%= command.id %> my.flag.key",
3117
+ "<%= config.bin %> <%= command.id %> my.flag.key --days 14",
3118
+ "<%= config.bin %> <%= command.id %> my.flag.key --json",
3119
+ "<%= config.bin %> <%= command.id %> my.flag.key && <%= config.bin %> delete my.flag.key"
3073
3120
  ],
3074
3121
  "flags": {
3075
3122
  "json": {
3076
- "description": "Format output as json.",
3077
- "helpGroup": "GLOBAL",
3123
+ "description": "Return structured object for agent consumption",
3078
3124
  "name": "json",
3079
3125
  "allowNo": false,
3080
3126
  "type": "boolean"
@@ -3122,32 +3168,18 @@
3122
3168
  "multiple": false,
3123
3169
  "type": "option"
3124
3170
  },
3125
- "type": {
3126
- "description": "Config type. Optional — inferred from history when omitted.",
3127
- "name": "type",
3128
- "required": false,
3171
+ "days": {
3172
+ "description": "Number of trailing calendar days that must have zero evals",
3173
+ "name": "days",
3174
+ "default": 7,
3129
3175
  "hasDynamicHelp": false,
3130
3176
  "multiple": false,
3131
- "options": [
3132
- "feature_flag",
3133
- "config",
3134
- "log_level",
3135
- "segment",
3136
- "flag",
3137
- "log-level"
3138
- ],
3139
3177
  "type": "option"
3140
- },
3141
- "yes": {
3142
- "description": "Skip the confirmation prompt",
3143
- "name": "yes",
3144
- "allowNo": false,
3145
- "type": "boolean"
3146
3178
  }
3147
3179
  },
3148
3180
  "hasDynamicHelp": false,
3149
3181
  "hiddenAliases": [],
3150
- "id": "activity:restore",
3182
+ "id": "cleanup:verify",
3151
3183
  "pluginAlias": "@quonfig/cli",
3152
3184
  "pluginName": "@quonfig/cli",
3153
3185
  "pluginType": "core",
@@ -3157,19 +3189,17 @@
3157
3189
  "relativePath": [
3158
3190
  "dist",
3159
3191
  "commands",
3160
- "activity",
3161
- "restore.js"
3192
+ "cleanup",
3193
+ "verify.js"
3162
3194
  ]
3163
3195
  },
3164
- "agent:install-skill": {
3196
+ "activity:deleted": {
3165
3197
  "aliases": [],
3166
3198
  "args": {},
3167
- "description": "Install the Quonfig agent skill into this repo so coding agents use Quonfig correctly.\n\nWrites .claude/skills/quonfig/ (SKILL.md + references/) — the same files as\n`claude plugin install quonfig@quonfig` from github.com/quonfig/skills, embedded\nin this qfg build (no network). Claude Code picks the skill up automatically;\nfor Codex, Cursor and other agents that read AGENTS.md, add --add-pointer.\n\nSafe to re-run: files still as qfg wrote them are upgraded in place, files you\nedited are left alone (the command fails and lists them) unless you pass --force.\n\nThis skill is for APPLICATION repos (SDK + qfg + MCP usage). A workspace repo\ncreated by `qfg init` has its own AGENTS.md/CLAUDE.md for editing config JSON.",
3199
+ "description": "List configs that were deleted from the workspace and have not been restored.\n\nUseful for \"did somebody delete X?\" — pair with `qfg activity restore NAME`\nto undelete a tombstoned config.",
3168
3200
  "examples": [
3169
3201
  "<%= config.bin %> <%= command.id %>",
3170
- "<%= config.bin %> <%= command.id %> --add-pointer",
3171
- "<%= config.bin %> <%= command.id %> --dir .agents/skills",
3172
- "<%= config.bin %> <%= command.id %> --force"
3202
+ "<%= config.bin %> <%= command.id %> --json"
3173
3203
  ],
3174
3204
  "flags": {
3175
3205
  "json": {
@@ -3201,30 +3231,31 @@
3201
3231
  "allowNo": false,
3202
3232
  "type": "boolean"
3203
3233
  },
3204
- "add-pointer": {
3205
- "description": "Also append a one-line pointer to the skill in ./AGENTS.md (created if missing)",
3206
- "name": "add-pointer",
3207
- "allowNo": false,
3208
- "type": "boolean"
3209
- },
3210
- "dir": {
3211
- "description": "Skills directory to install into, relative to the current directory",
3212
- "name": "dir",
3213
- "default": ".claude/skills",
3234
+ "workspace": {
3235
+ "char": "w",
3236
+ "description": "Workspace slug to use (overrides QUONFIG_WORKSPACE env var and saved default)",
3237
+ "helpGroup": "GLOBAL",
3238
+ "name": "workspace",
3239
+ "required": false,
3214
3240
  "hasDynamicHelp": false,
3215
3241
  "multiple": false,
3216
3242
  "type": "option"
3217
3243
  },
3218
- "force": {
3219
- "description": "Overwrite skill files you have edited locally",
3220
- "name": "force",
3221
- "allowNo": false,
3222
- "type": "boolean"
3244
+ "profile": {
3245
+ "char": "p",
3246
+ "description": "Deprecated: use --workspace instead",
3247
+ "helpGroup": "GLOBAL",
3248
+ "hidden": true,
3249
+ "name": "profile",
3250
+ "required": false,
3251
+ "hasDynamicHelp": false,
3252
+ "multiple": false,
3253
+ "type": "option"
3223
3254
  }
3224
3255
  },
3225
3256
  "hasDynamicHelp": false,
3226
3257
  "hiddenAliases": [],
3227
- "id": "agent:install-skill",
3258
+ "id": "activity:deleted",
3228
3259
  "pluginAlias": "@quonfig/cli",
3229
3260
  "pluginName": "@quonfig/cli",
3230
3261
  "pluginType": "core",
@@ -3234,21 +3265,23 @@
3234
3265
  "relativePath": [
3235
3266
  "dist",
3236
3267
  "commands",
3237
- "agent",
3238
- "install-skill.js"
3268
+ "activity",
3269
+ "deleted.js"
3239
3270
  ]
3240
3271
  },
3241
- "cleanup:list": {
3272
+ "activity:feed": {
3242
3273
  "aliases": [],
3243
3274
  "args": {},
3244
- "description": "List feature flags marked readyForCleanup=true, with eval volume per window.\n\nColumns:\n KEY the flag key\n TYPE the flag's valueType (bool, string, int, etc.)\n EVALS_24H evals counted in today's bucket (latest day)\n EVALS_2D evals in the last 2 calendar days\n EVALS_7D evals in the last 7 calendar days\n EVALS_30D evals in the last 30 calendar days\n LAST_EVAL most recent calendar day with any evals (UTC), blank if none\n CLASS quiet (zero evals in last 2 days) or active\n\nDefault sort: quiet first, oldest LAST_EVAL at top.\n\nPass --json for the structured object (rows[]). Each row carries the columns\nabove plus the raw eval counts your agent can reason about itself.\n\nOnce you've picked a candidate, run `qfg cleanup status <key>` for the\ndrill-in, or `qfg cleanup remove <key>` to hand the removal to your coding agent\nwith the Quonfig agent skill.",
3275
+ "description": "Recent activity across the workspace, newest first.\n\nEach entry shows who changed which config, the action (created/updated/deleted/restored),\nand the human-readable audit message produced by the server. The server already\ntranslates JSON diffs into messages — this command does not re-translate.",
3245
3276
  "examples": [
3246
3277
  "<%= config.bin %> <%= command.id %>",
3278
+ "<%= config.bin %> <%= command.id %> --limit 5",
3247
3279
  "<%= config.bin %> <%= command.id %> --json"
3248
3280
  ],
3249
3281
  "flags": {
3250
3282
  "json": {
3251
- "description": "Return structured rows for agent consumption",
3283
+ "description": "Format output as json.",
3284
+ "helpGroup": "GLOBAL",
3252
3285
  "name": "json",
3253
3286
  "allowNo": false,
3254
3287
  "type": "boolean"
@@ -3295,11 +3328,19 @@
3295
3328
  "hasDynamicHelp": false,
3296
3329
  "multiple": false,
3297
3330
  "type": "option"
3331
+ },
3332
+ "limit": {
3333
+ "description": "Maximum number of feed entries (1-100)",
3334
+ "name": "limit",
3335
+ "default": 30,
3336
+ "hasDynamicHelp": false,
3337
+ "multiple": false,
3338
+ "type": "option"
3298
3339
  }
3299
3340
  },
3300
3341
  "hasDynamicHelp": false,
3301
3342
  "hiddenAliases": [],
3302
- "id": "cleanup:list",
3343
+ "id": "activity:feed",
3303
3344
  "pluginAlias": "@quonfig/cli",
3304
3345
  "pluginName": "@quonfig/cli",
3305
3346
  "pluginType": "core",
@@ -3309,11 +3350,11 @@
3309
3350
  "relativePath": [
3310
3351
  "dist",
3311
3352
  "commands",
3312
- "cleanup",
3313
- "list.js"
3353
+ "activity",
3354
+ "feed.js"
3314
3355
  ]
3315
3356
  },
3316
- "cleanup:remove": {
3357
+ "activity:history": {
3317
3358
  "aliases": [],
3318
3359
  "args": {
3319
3360
  "name": {
@@ -3321,11 +3362,10 @@
3321
3362
  "name": "name"
3322
3363
  }
3323
3364
  },
3324
- "description": "Write a cleanup payload for a ready-for-cleanup flag and hand off to the Quonfig agent skill.\n\nModeled on `qfg migrate my-code` — this command never edits source files\nitself. It validates that the flag is marked readyForCleanup=true, refuses to\nproceed if there are still evals_2d > 0 (use --force to override), writes\n`.qf/cleanup/<key>.json` describing the flag's current rule shape +\ntelemetry, and prints how to have your coding agent remove the call sites with\nthe quonfig agent skill (its references/retire-a-flag.md), which asks the\nengineer which value should \"win\" and applies the inlining. Install the skill\nwith `qfg agent install-skill` or `claude plugin install quonfig@quonfig`.\n\nThe payload deliberately does NOT suggest a winning value; that's the\nengineer's call. Run `qfg cleanup status <key>` first if you want to inspect\ntelemetry before retiring.",
3365
+ "description": "Per-config audit trail for a flag, config, log-level, segment, or schema.\n\nResolves NAME against the workspace metadata (no need to specify type) and\nreturns the full commit history for that file with audit messages translated\nby the server. Restored entries are rendered distinctly so a recovery doesn't\nlook like a fresh create.",
3325
3366
  "examples": [
3326
- "<%= config.bin %> <%= command.id %> my.flag.key",
3327
- "<%= config.bin %> <%= command.id %> my.flag.key --force",
3328
- "<%= config.bin %> <%= command.id %> my.flag.key --json"
3367
+ "<%= config.bin %> <%= command.id %> my.flag",
3368
+ "<%= config.bin %> <%= command.id %> request.timeout --json"
3329
3369
  ],
3330
3370
  "flags": {
3331
3371
  "json": {
@@ -3377,17 +3417,11 @@
3377
3417
  "hasDynamicHelp": false,
3378
3418
  "multiple": false,
3379
3419
  "type": "option"
3380
- },
3381
- "force": {
3382
- "description": "Skip the evals_2d > 0 safety gate (useful when telemetry is delayed but you know the flag is dead)",
3383
- "name": "force",
3384
- "allowNo": false,
3385
- "type": "boolean"
3386
3420
  }
3387
3421
  },
3388
3422
  "hasDynamicHelp": false,
3389
3423
  "hiddenAliases": [],
3390
- "id": "cleanup:remove",
3424
+ "id": "activity:history",
3391
3425
  "pluginAlias": "@quonfig/cli",
3392
3426
  "pluginName": "@quonfig/cli",
3393
3427
  "pluginType": "core",
@@ -3397,11 +3431,11 @@
3397
3431
  "relativePath": [
3398
3432
  "dist",
3399
3433
  "commands",
3400
- "cleanup",
3401
- "remove.js"
3434
+ "activity",
3435
+ "history.js"
3402
3436
  ]
3403
3437
  },
3404
- "cleanup:status": {
3438
+ "activity:restore": {
3405
3439
  "aliases": [],
3406
3440
  "args": {
3407
3441
  "name": {
@@ -3409,14 +3443,15 @@
3409
3443
  "name": "name"
3410
3444
  }
3411
3445
  },
3412
- "description": "Drill into one ready-for-cleanup flag — show telemetry across all environments and the current rule shape.\n\nUse this after `qfg cleanup list` to inspect a specific flag before handing\nremoval off to the Quonfig agent skill. The eval counts come from\nanalytics.configSparklines (the same backing data the per-flag sparklines on\nthe flag detail page use), summed into 24h/2d/7d/30d windows so you can decide\nwhether it's safe to retire.\n\nPass --json for the structured object including the full rule shape per\nenvironment — the agent skill consumes this directly.",
3446
+ "description": "Undelete a config that was previously removed.\n\nLooks up the most recent deletion for the key (so you see who deleted it and when),\nthen asks for confirmation before re-creating the file from the prior content.\nSchemas cannot be restored — use git history instead.",
3413
3447
  "examples": [
3414
- "<%= config.bin %> <%= command.id %> my.flag.key",
3415
- "<%= config.bin %> <%= command.id %> my.flag.key --json"
3448
+ "<%= config.bin %> <%= command.id %> my.flag --yes",
3449
+ "<%= config.bin %> <%= command.id %> request.timeout --type config --yes"
3416
3450
  ],
3417
3451
  "flags": {
3418
3452
  "json": {
3419
- "description": "Return structured object for agent consumption",
3453
+ "description": "Format output as json.",
3454
+ "helpGroup": "GLOBAL",
3420
3455
  "name": "json",
3421
3456
  "allowNo": false,
3422
3457
  "type": "boolean"
@@ -3463,11 +3498,33 @@
3463
3498
  "hasDynamicHelp": false,
3464
3499
  "multiple": false,
3465
3500
  "type": "option"
3501
+ },
3502
+ "type": {
3503
+ "description": "Config type. Optional — inferred from history when omitted.",
3504
+ "name": "type",
3505
+ "required": false,
3506
+ "hasDynamicHelp": false,
3507
+ "multiple": false,
3508
+ "options": [
3509
+ "feature_flag",
3510
+ "config",
3511
+ "log_level",
3512
+ "segment",
3513
+ "flag",
3514
+ "log-level"
3515
+ ],
3516
+ "type": "option"
3517
+ },
3518
+ "yes": {
3519
+ "description": "Skip the confirmation prompt",
3520
+ "name": "yes",
3521
+ "allowNo": false,
3522
+ "type": "boolean"
3466
3523
  }
3467
3524
  },
3468
3525
  "hasDynamicHelp": false,
3469
3526
  "hiddenAliases": [],
3470
- "id": "cleanup:status",
3527
+ "id": "activity:restore",
3471
3528
  "pluginAlias": "@quonfig/cli",
3472
3529
  "pluginName": "@quonfig/cli",
3473
3530
  "pluginType": "core",
@@ -3477,28 +3534,34 @@
3477
3534
  "relativePath": [
3478
3535
  "dist",
3479
3536
  "commands",
3480
- "cleanup",
3481
- "status.js"
3537
+ "activity",
3538
+ "restore.js"
3482
3539
  ]
3483
3540
  },
3484
- "cleanup:verify": {
3541
+ "contexts:search": {
3485
3542
  "aliases": [],
3486
3543
  "args": {
3487
- "name": {
3488
- "description": "config/feature-flag/etc. name",
3489
- "name": "name"
3544
+ "contextType": {
3545
+ "description": "Context type to search, e.g. organization or user (the part before \".key\" in a rule)",
3546
+ "name": "contextType",
3547
+ "required": true
3548
+ },
3549
+ "query": {
3550
+ "description": "Case-insensitive text matched against each context key and its reported properties (e.g. a name)",
3551
+ "name": "query",
3552
+ "required": true
3490
3553
  }
3491
3554
  },
3492
- "description": "Confirm zero evals for a flag in the trailing N days (default 7). Exits 0 if safe to delete, non-zero otherwise.\n\nRead-only gate intended for chaining with `qfg delete` after a cleanup PR\nhas merged and the SDK has redeployed:\n\n qfg cleanup verify my.flag.key && qfg delete my.flag.key\n\nThe trailing window is stricter than the `qfg cleanup remove` 2-day gate on\npurpose — `remove` only writes a payload describing the flag, but `delete`\npermanently removes the flag definition, so we want a longer quiet period\nbefore chaining. Bump --days N if you want a more conservative window.",
3555
+ "description": "Find a context's key from a name, to target it in a rule.\n\nTargeting rules should match a context by its KEY (<contextType>.key, e.g.\norganization.key or user.key), not by a slug, email or name. This searches the\ncontexts your SDKs have reported through telemetry, matching the query against\neach context's key and properties, and prints each match's key, its name and\nits email (blank when the context reported none), most recently seen first.\n\nOnly contexts your SDKs have reported are searchable. If nothing matches, the key\nis unknown: get it from whoever owns that customer rather than targeting a slug\nor email instead.\n\nPass a key as the query to see its name and email.\n\n--json prints {contexts: [{key, name, email?}]}: name is null when the context\nreported no name, and email is present only when it reported one.",
3493
3556
  "examples": [
3494
- "<%= config.bin %> <%= command.id %> my.flag.key",
3495
- "<%= config.bin %> <%= command.id %> my.flag.key --days 14",
3496
- "<%= config.bin %> <%= command.id %> my.flag.key --json",
3497
- "<%= config.bin %> <%= command.id %> my.flag.key && <%= config.bin %> delete my.flag.key"
3557
+ "<%= config.bin %> <%= command.id %> organization formhealth",
3558
+ "<%= config.bin %> <%= command.id %> user barry@example.com --environment production",
3559
+ "<%= config.bin %> <%= command.id %> organization formhealth --json"
3498
3560
  ],
3499
3561
  "flags": {
3500
3562
  "json": {
3501
- "description": "Return structured object for agent consumption",
3563
+ "description": "Format output as json.",
3564
+ "helpGroup": "GLOBAL",
3502
3565
  "name": "json",
3503
3566
  "allowNo": false,
3504
3567
  "type": "boolean"
@@ -3546,10 +3609,17 @@
3546
3609
  "multiple": false,
3547
3610
  "type": "option"
3548
3611
  },
3549
- "days": {
3550
- "description": "Number of trailing calendar days that must have zero evals",
3551
- "name": "days",
3552
- "default": 7,
3612
+ "environment": {
3613
+ "description": "Only contexts reported from this environment (default: every environment)",
3614
+ "name": "environment",
3615
+ "hasDynamicHelp": false,
3616
+ "multiple": false,
3617
+ "type": "option"
3618
+ },
3619
+ "limit": {
3620
+ "description": "Maximum number of matches (1-100)",
3621
+ "name": "limit",
3622
+ "default": 20,
3553
3623
  "hasDynamicHelp": false,
3554
3624
  "multiple": false,
3555
3625
  "type": "option"
@@ -3557,7 +3627,7 @@
3557
3627
  },
3558
3628
  "hasDynamicHelp": false,
3559
3629
  "hiddenAliases": [],
3560
- "id": "cleanup:verify",
3630
+ "id": "contexts:search",
3561
3631
  "pluginAlias": "@quonfig/cli",
3562
3632
  "pluginName": "@quonfig/cli",
3563
3633
  "pluginType": "core",
@@ -3567,29 +3637,19 @@
3567
3637
  "relativePath": [
3568
3638
  "dist",
3569
3639
  "commands",
3570
- "cleanup",
3571
- "verify.js"
3640
+ "contexts",
3641
+ "search.js"
3572
3642
  ]
3573
3643
  },
3574
- "contexts:search": {
3644
+ "agent:install-skill": {
3575
3645
  "aliases": [],
3576
- "args": {
3577
- "contextType": {
3578
- "description": "Context type to search, e.g. organization or user (the part before \".key\" in a rule)",
3579
- "name": "contextType",
3580
- "required": true
3581
- },
3582
- "query": {
3583
- "description": "Case-insensitive text matched against each context key and its reported properties (e.g. a name)",
3584
- "name": "query",
3585
- "required": true
3586
- }
3587
- },
3588
- "description": "Find a context's key from a name, to target it in a rule.\n\nTargeting rules should match a context by its KEY (<contextType>.key, e.g.\norganization.key or user.key), not by a slug, email or name. This searches the\ncontexts your SDKs have reported through telemetry, matching the query against\neach context's key and properties, and prints each match's key, its name and\nits email (blank when the context reported none), most recently seen first.\n\nOnly contexts your SDKs have reported are searchable. If nothing matches, the key\nis unknown: get it from whoever owns that customer rather than targeting a slug\nor email instead.\n\nPass a key as the query to see its name and email.\n\n--json prints {contexts: [{key, name, email?}]}: name is null when the context\nreported no name, and email is present only when it reported one.",
3646
+ "args": {},
3647
+ "description": "Install the Quonfig agent skill into this repo so coding agents use Quonfig correctly.\n\nWrites .claude/skills/quonfig/ (SKILL.md + references/) — the same files as\n`claude plugin install quonfig@quonfig` from github.com/quonfig/skills, embedded\nin this qfg build (no network). Claude Code picks the skill up automatically;\nfor Codex, Cursor and other agents that read AGENTS.md, add --add-pointer.\n\nSafe to re-run: files still as qfg wrote them are upgraded in place, files you\nedited are left alone (the command fails and lists them) unless you pass --force.\n\nThis skill is for APPLICATION repos (SDK + qfg + MCP usage). A workspace repo\ncreated by `qfg init` has its own AGENTS.md/CLAUDE.md for editing config JSON.",
3589
3648
  "examples": [
3590
- "<%= config.bin %> <%= command.id %> organization formhealth",
3591
- "<%= config.bin %> <%= command.id %> user barry@example.com --environment production",
3592
- "<%= config.bin %> <%= command.id %> organization formhealth --json"
3649
+ "<%= config.bin %> <%= command.id %>",
3650
+ "<%= config.bin %> <%= command.id %> --add-pointer",
3651
+ "<%= config.bin %> <%= command.id %> --dir .agents/skills",
3652
+ "<%= config.bin %> <%= command.id %> --force"
3593
3653
  ],
3594
3654
  "flags": {
3595
3655
  "json": {
@@ -3621,46 +3681,30 @@
3621
3681
  "allowNo": false,
3622
3682
  "type": "boolean"
3623
3683
  },
3624
- "workspace": {
3625
- "char": "w",
3626
- "description": "Workspace slug to use (overrides QUONFIG_WORKSPACE env var and saved default)",
3627
- "helpGroup": "GLOBAL",
3628
- "name": "workspace",
3629
- "required": false,
3630
- "hasDynamicHelp": false,
3631
- "multiple": false,
3632
- "type": "option"
3633
- },
3634
- "profile": {
3635
- "char": "p",
3636
- "description": "Deprecated: use --workspace instead",
3637
- "helpGroup": "GLOBAL",
3638
- "hidden": true,
3639
- "name": "profile",
3640
- "required": false,
3641
- "hasDynamicHelp": false,
3642
- "multiple": false,
3643
- "type": "option"
3684
+ "add-pointer": {
3685
+ "description": "Also append a one-line pointer to the skill in ./AGENTS.md (created if missing)",
3686
+ "name": "add-pointer",
3687
+ "allowNo": false,
3688
+ "type": "boolean"
3644
3689
  },
3645
- "environment": {
3646
- "description": "Only contexts reported from this environment (default: every environment)",
3647
- "name": "environment",
3690
+ "dir": {
3691
+ "description": "Skills directory to install into, relative to the current directory",
3692
+ "name": "dir",
3693
+ "default": ".claude/skills",
3648
3694
  "hasDynamicHelp": false,
3649
3695
  "multiple": false,
3650
3696
  "type": "option"
3651
3697
  },
3652
- "limit": {
3653
- "description": "Maximum number of matches (1-100)",
3654
- "name": "limit",
3655
- "default": 20,
3656
- "hasDynamicHelp": false,
3657
- "multiple": false,
3658
- "type": "option"
3698
+ "force": {
3699
+ "description": "Overwrite skill files you have edited locally",
3700
+ "name": "force",
3701
+ "allowNo": false,
3702
+ "type": "boolean"
3659
3703
  }
3660
3704
  },
3661
3705
  "hasDynamicHelp": false,
3662
3706
  "hiddenAliases": [],
3663
- "id": "contexts:search",
3707
+ "id": "agent:install-skill",
3664
3708
  "pluginAlias": "@quonfig/cli",
3665
3709
  "pluginName": "@quonfig/cli",
3666
3710
  "pluginType": "core",
@@ -3670,8 +3714,8 @@
3670
3714
  "relativePath": [
3671
3715
  "dist",
3672
3716
  "commands",
3673
- "contexts",
3674
- "search.js"
3717
+ "agent",
3718
+ "install-skill.js"
3675
3719
  ]
3676
3720
  },
3677
3721
  "migrate:doctor": {
@@ -4383,5 +4427,5 @@
4383
4427
  ]
4384
4428
  }
4385
4429
  },
4386
- "version": "0.3.0"
4430
+ "version": "0.5.0"
4387
4431
  }