@quonfig/cli 0.2.3 → 0.3.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.
@@ -118,7 +118,7 @@
118
118
  "cleanup": {
119
119
  "aliases": [],
120
120
  "args": {},
121
- "description": "Retire feature flags that have done their job.\n\nThe cleanup workflow turns a flag's \"Ready for cleanup\" marker into an end-to-end\nremoval flow: surface the flags that are safe to retire, hand the actual code\nremoval to the qfg-flag-cleanup Claude skill, then delete the flag definition\nonce the call sites are gone.\n\nLifecycle (high-level):\n 1. Owner flips readyForCleanup=true in the UI (already exists)\n 2. qfg cleanup list see candidates + telemetry\n 3. qfg cleanup status <key> drill into one flag\n 4. qfg cleanup remove <key> handoff to the cleanup skill\n 5. PR merges, SDK redeploys, telemetry confirms 0 evals\n 6. qfg cleanup verify <key> (optional) confirm safe\n 7. qfg delete <key> remove the flag definition",
121
+ "description": "Retire feature flags that have done their job.\n\nThe cleanup workflow turns a flag's \"Ready for cleanup\" marker into an end-to-end\nremoval flow: surface the flags that are safe to retire, hand the actual code\nremoval to your coding agent with the Quonfig agent skill (install it with\n`qfg agent install-skill`), then delete the flag definition once the call\nsites are gone.\n\nLifecycle (high-level):\n 1. Owner flips readyForCleanup=true in the UI (already exists)\n 2. qfg cleanup list see candidates + telemetry\n 3. qfg cleanup status <key> drill into one flag\n 4. qfg cleanup remove <key> handoff to the agent skill\n 5. PR merges, SDK redeploys, telemetry confirms 0 evals\n 6. qfg cleanup verify <key> (optional) confirm safe\n 7. qfg delete <key> remove the flag definition",
122
122
  "examples": [
123
123
  "<%= config.bin %> cleanup list",
124
124
  "<%= config.bin %> cleanup list --json",
@@ -230,6 +230,59 @@
230
230
  "config-schema.js"
231
231
  ]
232
232
  },
233
+ "contexts": {
234
+ "aliases": [],
235
+ "args": {},
236
+ "description": "Look up contexts (organizations, users, ...) your SDKs have reported, to target them by key.",
237
+ "examples": [
238
+ "<%= config.bin %> contexts search organization formhealth"
239
+ ],
240
+ "flags": {
241
+ "json": {
242
+ "description": "Format output as json.",
243
+ "helpGroup": "GLOBAL",
244
+ "name": "json",
245
+ "allowNo": false,
246
+ "type": "boolean"
247
+ },
248
+ "interactive": {
249
+ "description": "Force interactive mode",
250
+ "helpGroup": "GLOBAL",
251
+ "name": "interactive",
252
+ "allowNo": true,
253
+ "type": "boolean"
254
+ },
255
+ "no-color": {
256
+ "description": "Do not colorize output",
257
+ "env": "NO_COLOR",
258
+ "helpGroup": "GLOBAL",
259
+ "name": "no-color",
260
+ "allowNo": false,
261
+ "type": "boolean"
262
+ },
263
+ "verbose": {
264
+ "description": "Verbose output",
265
+ "helpGroup": "GLOBAL",
266
+ "name": "verbose",
267
+ "allowNo": false,
268
+ "type": "boolean"
269
+ }
270
+ },
271
+ "hasDynamicHelp": false,
272
+ "hiddenAliases": [],
273
+ "id": "contexts",
274
+ "pluginAlias": "@quonfig/cli",
275
+ "pluginName": "@quonfig/cli",
276
+ "pluginType": "core",
277
+ "strict": true,
278
+ "enableJsonFlag": true,
279
+ "isESM": true,
280
+ "relativePath": [
281
+ "dist",
282
+ "commands",
283
+ "contexts.js"
284
+ ]
285
+ },
233
286
  "create": {
234
287
  "aliases": [],
235
288
  "args": {
@@ -2255,7 +2308,7 @@
2255
2308
  "name": "name"
2256
2309
  }
2257
2310
  },
2258
- "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",
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",
2259
2312
  "examples": [
2260
2313
  "<%= config.bin %> <%= command.id %> my.flag.name # prompts for value and env",
2261
2314
  "<%= config.bin %> <%= command.id %> my.flag.name --value=true --environment=staging",
@@ -3108,10 +3161,87 @@
3108
3161
  "restore.js"
3109
3162
  ]
3110
3163
  },
3164
+ "agent:install-skill": {
3165
+ "aliases": [],
3166
+ "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.",
3168
+ "examples": [
3169
+ "<%= 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"
3173
+ ],
3174
+ "flags": {
3175
+ "json": {
3176
+ "description": "Format output as json.",
3177
+ "helpGroup": "GLOBAL",
3178
+ "name": "json",
3179
+ "allowNo": false,
3180
+ "type": "boolean"
3181
+ },
3182
+ "interactive": {
3183
+ "description": "Force interactive mode",
3184
+ "helpGroup": "GLOBAL",
3185
+ "name": "interactive",
3186
+ "allowNo": true,
3187
+ "type": "boolean"
3188
+ },
3189
+ "no-color": {
3190
+ "description": "Do not colorize output",
3191
+ "env": "NO_COLOR",
3192
+ "helpGroup": "GLOBAL",
3193
+ "name": "no-color",
3194
+ "allowNo": false,
3195
+ "type": "boolean"
3196
+ },
3197
+ "verbose": {
3198
+ "description": "Verbose output",
3199
+ "helpGroup": "GLOBAL",
3200
+ "name": "verbose",
3201
+ "allowNo": false,
3202
+ "type": "boolean"
3203
+ },
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",
3214
+ "hasDynamicHelp": false,
3215
+ "multiple": false,
3216
+ "type": "option"
3217
+ },
3218
+ "force": {
3219
+ "description": "Overwrite skill files you have edited locally",
3220
+ "name": "force",
3221
+ "allowNo": false,
3222
+ "type": "boolean"
3223
+ }
3224
+ },
3225
+ "hasDynamicHelp": false,
3226
+ "hiddenAliases": [],
3227
+ "id": "agent:install-skill",
3228
+ "pluginAlias": "@quonfig/cli",
3229
+ "pluginName": "@quonfig/cli",
3230
+ "pluginType": "core",
3231
+ "strict": true,
3232
+ "enableJsonFlag": true,
3233
+ "isESM": true,
3234
+ "relativePath": [
3235
+ "dist",
3236
+ "commands",
3237
+ "agent",
3238
+ "install-skill.js"
3239
+ ]
3240
+ },
3111
3241
  "cleanup:list": {
3112
3242
  "aliases": [],
3113
3243
  "args": {},
3114
- "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 hand off the removal to the qfg-flag-cleanup Claude skill.",
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.",
3115
3245
  "examples": [
3116
3246
  "<%= config.bin %> <%= command.id %>",
3117
3247
  "<%= config.bin %> <%= command.id %> --json"
@@ -3191,7 +3321,7 @@
3191
3321
  "name": "name"
3192
3322
  }
3193
3323
  },
3194
- "description": "Write a cleanup payload for a ready-for-cleanup flag and hand off to the qfg-flag-cleanup Claude 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 instructions to invoke the qfg-flag-cleanup skill which\nasks the engineer which value should \"win\" and applies the inlining.\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.",
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.",
3195
3325
  "examples": [
3196
3326
  "<%= config.bin %> <%= command.id %> my.flag.key",
3197
3327
  "<%= config.bin %> <%= command.id %> my.flag.key --force",
@@ -3279,7 +3409,7 @@
3279
3409
  "name": "name"
3280
3410
  }
3281
3411
  },
3282
- "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 qfg-flag-cleanup Claude 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 cleanup skill consumes this directly.",
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.",
3283
3413
  "examples": [
3284
3414
  "<%= config.bin %> <%= command.id %> my.flag.key",
3285
3415
  "<%= config.bin %> <%= command.id %> my.flag.key --json"
@@ -3441,6 +3571,109 @@
3441
3571
  "verify.js"
3442
3572
  ]
3443
3573
  },
3574
+ "contexts:search": {
3575
+ "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.",
3589
+ "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"
3593
+ ],
3594
+ "flags": {
3595
+ "json": {
3596
+ "description": "Format output as json.",
3597
+ "helpGroup": "GLOBAL",
3598
+ "name": "json",
3599
+ "allowNo": false,
3600
+ "type": "boolean"
3601
+ },
3602
+ "interactive": {
3603
+ "description": "Force interactive mode",
3604
+ "helpGroup": "GLOBAL",
3605
+ "name": "interactive",
3606
+ "allowNo": true,
3607
+ "type": "boolean"
3608
+ },
3609
+ "no-color": {
3610
+ "description": "Do not colorize output",
3611
+ "env": "NO_COLOR",
3612
+ "helpGroup": "GLOBAL",
3613
+ "name": "no-color",
3614
+ "allowNo": false,
3615
+ "type": "boolean"
3616
+ },
3617
+ "verbose": {
3618
+ "description": "Verbose output",
3619
+ "helpGroup": "GLOBAL",
3620
+ "name": "verbose",
3621
+ "allowNo": false,
3622
+ "type": "boolean"
3623
+ },
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"
3644
+ },
3645
+ "environment": {
3646
+ "description": "Only contexts reported from this environment (default: every environment)",
3647
+ "name": "environment",
3648
+ "hasDynamicHelp": false,
3649
+ "multiple": false,
3650
+ "type": "option"
3651
+ },
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"
3659
+ }
3660
+ },
3661
+ "hasDynamicHelp": false,
3662
+ "hiddenAliases": [],
3663
+ "id": "contexts:search",
3664
+ "pluginAlias": "@quonfig/cli",
3665
+ "pluginName": "@quonfig/cli",
3666
+ "pluginType": "core",
3667
+ "strict": true,
3668
+ "enableJsonFlag": true,
3669
+ "isESM": true,
3670
+ "relativePath": [
3671
+ "dist",
3672
+ "commands",
3673
+ "contexts",
3674
+ "search.js"
3675
+ ]
3676
+ },
3444
3677
  "migrate:doctor": {
3445
3678
  "aliases": [],
3446
3679
  "args": {},
@@ -4150,5 +4383,5 @@
4150
4383
  ]
4151
4384
  }
4152
4385
  },
4153
- "version": "0.2.3"
4386
+ "version": "0.3.0"
4154
4387
  }
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "packageManager": "yarn@4.11.0+sha512.4e54aeace9141df2f0177c266b05ec50dc044638157dae128c471ba65994ac802122d7ab35bcd9e81641228b7dcf24867d28e750e0bcae8a05277d600008ad54",
3
3
  "name": "@quonfig/cli",
4
- "version": "0.2.3",
4
+ "version": "0.3.0",
5
5
  "bugs": {
6
6
  "url": "https://github.com/quonfig/cli/issues"
7
7
  },
@@ -94,8 +94,7 @@
94
94
  }
95
95
  },
96
96
  "scripts": {
97
- "prebuild": "node scripts/generate-version.mjs",
98
- "build": "shx rm -rf dist && tsc -b",
97
+ "build": "node scripts/generate-version.mjs && shx rm -rf dist && tsc -b",
99
98
  "lint": "eslint --cache=true \"**/*.{ts,md,json}\"",
100
99
  "lint:fix": "eslint --cache=true --fix \"**/*.{ts,md,json}\"",
101
100
  "postpack": "shx rm -f oclif.manifest.json",