@theholocron/cli 4.17.0 → 4.17.1

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
@@ -424,7 +424,7 @@ holds the orchestration + the Holocron-specific credential resolution
424
424
  `astromech.reusableTemplates()` to `theholocron/.github` (a pure sync target —
425
425
  never hand-edit its `.github/workflows/*`).
426
426
  - `src/commands/` — `setup`, `sync`, `doctor`, `deploy`, `secret set`,
427
- `secrets sync`, `npm publish-initial`, `sync-github`, `upgrade node`,
427
+ `secrets sync`, `publish`, `bump-versions`, `sync-github`, `upgrade node`,
428
428
  `upgrade deps`, `plugin create`, `auth`
429
429
 
430
430
  ## Status
package/dist/cli.mjs CHANGED
@@ -1208,8 +1208,8 @@ const COMMAND_CONTEXTS = {
1208
1208
  "auth unset": "global",
1209
1209
  "auth list": "global",
1210
1210
  "auth check": "global",
1211
- "npm bump-versions": "global",
1212
- "npm publish-initial": "global",
1211
+ "bump-versions": "global",
1212
+ publish: "global",
1213
1213
  "skills install": "global",
1214
1214
  "skills remove": "global",
1215
1215
  "skills update": "global",
@@ -1894,177 +1894,6 @@ async function runNpmBumpVersions(input) {
1894
1894
  };
1895
1895
  }
1896
1896
  //#endregion
1897
- //#region src/commands/npm-publish-initial.ts
1898
- /**
1899
- * `holocron npm publish-initial` — bottles up the chicken-and-egg
1900
- * bootstrap that every new npm-published holocron monorepo hits.
1901
- *
1902
- * npm requires a package to exist before Trusted Publishing can be
1903
- * configured on it. So the first publish has to happen outside the
1904
- * OIDC flow — using either a browser-auth session (`npm login
1905
- * --auth-type=web`) or an ephemeral automation token. This command
1906
- * runs the publish step + tells you exactly what to do next.
1907
- *
1908
- * Workflow:
1909
- *
1910
- * $ npm login --auth-type=web # one-time, browser-based
1911
- * $ pnpm install --frozen-lockfile
1912
- * $ pnpm build
1913
- * $ pnpm exec tsx packages/cli/src/cli.ts npm publish-initial
1914
- *
1915
- * The command itself only handles the publish step + the post-publish
1916
- * Trusted Publisher setup reminder. `pnpm install` + `pnpm build`
1917
- * stay outside the command (no pnpm-inside-pnpm).
1918
- *
1919
- * If `NPM_TOKEN` is detected in env, the command prints a final
1920
- * "revoke this token at <url>" reminder — same pattern as `rando vc
1921
- * setup` for the ephemeral GH admin PAT.
1922
- */
1923
- async function runNpmPublishInitial(input = {}) {
1924
- const print = input.print ?? ((line) => console.log(line));
1925
- const logger = input.logger ?? getLogger();
1926
- const cwd = input.cwd ?? process.cwd();
1927
- const tag = input.tag ?? "alpha";
1928
- const dryRun = input.dryRun ?? false;
1929
- const otp = input.otp;
1930
- const env = makeEnv(input.env);
1931
- const exec = input.exec ?? defaultExec$2;
1932
- const publishArgs = [
1933
- "-r",
1934
- "--filter=./packages/*",
1935
- "publish",
1936
- "--access",
1937
- "public",
1938
- "--no-git-checks",
1939
- "--tag",
1940
- tag,
1941
- ...otp ? ["--otp", otp] : []
1942
- ];
1943
- print(`Holocron npm publish-initial${dryRun ? " (dry-run)" : ""}`);
1944
- print(` cwd: ${cwd}`);
1945
- print(` tag: ${tag}`);
1946
- logger.info({
1947
- tag,
1948
- dryRun: dryRun || void 0
1949
- }, "npm publish-initial: start");
1950
- if (otp) print(` otp: <${otp.length} chars>`);
1951
- print("");
1952
- print(" → verifying npm auth (`npm whoami`)…");
1953
- const whoami = await exec("npm", ["whoami"], { cwd });
1954
- if (whoami.exitCode !== 0) {
1955
- const message = "npm is not authenticated. Run `npm login --auth-type=web` (browser flow, no token stored) or `npm login`, then re-run this command.";
1956
- print(` ✗ ${message}`);
1957
- const packageNames = input.packages ?? discoverPublicPackages(cwd);
1958
- logger.warn({ reason: "npm not authenticated" }, "npm publish-initial: done");
1959
- return {
1960
- status: "fail",
1961
- message,
1962
- packageNames
1963
- };
1964
- }
1965
- print(` ✓ authed as ${whoami.stdout.trim() || "<unknown>"}`);
1966
- const packageNames = input.packages ?? discoverPublicPackages(cwd);
1967
- const repoName = input.repoName ?? await resolveRepoName(cwd, exec);
1968
- if (dryRun) {
1969
- print("");
1970
- print(" … (dry-run) skipping actual publish");
1971
- print(` would run: pnpm ${publishArgs.join(" ")}`);
1972
- printNextSteps$1(print, env, packageNames, repoName);
1973
- logger.info({
1974
- tag,
1975
- status: "dry-run",
1976
- packages: packageNames.length
1977
- }, "npm publish-initial: done");
1978
- return {
1979
- status: "dry-run",
1980
- message: "dry-run — no publish executed",
1981
- packageNames
1982
- };
1983
- }
1984
- print("");
1985
- print(" → publishing all public @theholocron/* packages…");
1986
- const publish = await exec("pnpm", publishArgs, { cwd });
1987
- if (publish.exitCode !== 0) {
1988
- const message = `publish failed (exit ${publish.exitCode}): ${publish.stderr.trim() || publish.stdout.trim() || "no output"}`;
1989
- print(` ✗ ${message}`);
1990
- if (publish.stdout.includes("EOTP") || publish.stderr.includes("EOTP")) {
1991
- print("");
1992
- print(" → hint: your npm account requires 2FA for writes. Re-run with `--otp <code>`:");
1993
- print(` pnpm exec tsx packages/cli/src/cli.ts npm publish-initial --otp <6-digit-code>`);
1994
- }
1995
- logger.warn({
1996
- tag,
1997
- reason: message
1998
- }, "npm publish-initial: done");
1999
- return {
2000
- status: "fail",
2001
- message,
2002
- packageNames
2003
- };
2004
- }
2005
- print(" ✓ publish complete");
2006
- printNextSteps$1(print, env, packageNames, repoName);
2007
- logger.info({
2008
- tag,
2009
- status: "ok",
2010
- packages: packageNames.length
2011
- }, "npm publish-initial: done");
2012
- return {
2013
- status: "ok",
2014
- packageNames
2015
- };
2016
- }
2017
- function discoverPublicPackages(cwd) {
2018
- const packagesDir = join(cwd, "packages");
2019
- if (!existsSync(packagesDir)) return [];
2020
- return readdirSync(packagesDir, { withFileTypes: true }).filter((e) => e.isDirectory()).flatMap((e) => {
2021
- const pkgPath = join(packagesDir, e.name, "package.json");
2022
- if (!existsSync(pkgPath)) return [];
2023
- try {
2024
- const pkg = JSON.parse(readFileSync(pkgPath, "utf-8"));
2025
- return !pkg.private && pkg.name ? [pkg.name] : [];
2026
- } catch {
2027
- return [];
2028
- }
2029
- });
2030
- }
2031
- async function resolveRepoName(cwd, exec) {
2032
- const result = await exec("git", [
2033
- "remote",
2034
- "get-url",
2035
- "origin"
2036
- ], { cwd });
2037
- if (result.exitCode !== 0) return "unknown";
2038
- return /[/:]([^/:]+?)(?:\.git)?$/.exec(result.stdout.trim())?.[1] ?? "unknown";
2039
- }
2040
- function printNextSteps$1(print, env, packageNames, repoName) {
2041
- print("");
2042
- print(" → next: configure Trusted Publisher for each package on npm:");
2043
- for (const name of packageNames) print(` https://www.npmjs.com/package/${name}/access`);
2044
- print(` Publisher: GitHub Actions Org: theholocron Repo: ${repoName} Workflow: release.yml`);
2045
- if (env.get("NPM_TOKEN")) {
2046
- print("");
2047
- print(" → cleanup: $NPM_TOKEN was used. Revoke it now (no API for self-revoke; UI-only):");
2048
- print(" https://www.npmjs.com/settings/~/tokens");
2049
- }
2050
- }
2051
- const defaultExec$2 = async (cmd, args, opts) => {
2052
- const result = spawnSync(cmd, args, {
2053
- cwd: opts.cwd,
2054
- encoding: "utf8",
2055
- stdio: [
2056
- "inherit",
2057
- "pipe",
2058
- "pipe"
2059
- ]
2060
- });
2061
- return {
2062
- exitCode: result.status ?? -1,
2063
- stdout: result.stdout ?? "",
2064
- stderr: result.stderr ?? ""
2065
- };
2066
- };
2067
- //#endregion
2068
1897
  //#region src/commands/plugin-create/template-inputs.ts
2069
1898
  /** Derive the standard defaults from a slug + vendor name. */
2070
1899
  function deriveDefaults$1(input) {
@@ -3037,7 +2866,7 @@ function runPluginCreate(input) {
3037
2866
  filesWritten.push(resolvedPath);
3038
2867
  }
3039
2868
  if (!input.dryRun && !input.noVerify) {
3040
- const execFn = input.exec ?? defaultExec$1;
2869
+ const execFn = input.exec ?? defaultExec$2;
3041
2870
  const pkg = `@theholocron/holocron-plugin-${inputs.slug}`;
3042
2871
  print("");
3043
2872
  print(" Verifying scaffold…");
@@ -3088,7 +2917,7 @@ function runPluginCreate(input) {
3088
2917
  };
3089
2918
  }
3090
2919
  }
3091
- if (!input.dryRun) printNextSteps(print, inputs);
2920
+ if (!input.dryRun) printNextSteps$1(print, inputs);
3092
2921
  logger.info({
3093
2922
  slug: inputs.slug,
3094
2923
  capability: inputs.capability,
@@ -3137,13 +2966,13 @@ function defaultWrite(filepath, content) {
3137
2966
  mkdirSync(path.dirname(filepath), { recursive: true });
3138
2967
  writeFileSync(filepath, content, "utf8");
3139
2968
  }
3140
- function defaultExec$1(cmd, args, opts) {
2969
+ function defaultExec$2(cmd, args, opts) {
3141
2970
  execFileSync(cmd, args, {
3142
2971
  cwd: opts.cwd,
3143
2972
  stdio: opts.stdio
3144
2973
  });
3145
2974
  }
3146
- function printNextSteps(print, inputs) {
2975
+ function printNextSteps$1(print, inputs) {
3147
2976
  print("");
3148
2977
  print(` Scaffolded @theholocron/holocron-plugin-${inputs.slug} (18 files).`);
3149
2978
  print("");
@@ -3157,6 +2986,235 @@ function printNextSteps(print, inputs) {
3157
2986
  print(" 7. Commit + push when capability is functionally complete.");
3158
2987
  }
3159
2988
  //#endregion
2989
+ //#region src/commands/publish.ts
2990
+ /**
2991
+ * `holocron publish --initial` — bottles up the chicken-and-egg bootstrap
2992
+ * that every new npm-published holocron monorepo hits.
2993
+ *
2994
+ * npm requires a package to exist before Trusted Publishing can be
2995
+ * configured on it. So the first publish has to happen outside the OIDC
2996
+ * flow — a browser-auth session (`npm login --auth-type=web`) or an
2997
+ * ephemeral automation token. This command drives the login step itself
2998
+ * (when `npm whoami` shows you're not authenticated), runs the publish
2999
+ * step, and tells you exactly what to do next.
3000
+ *
3001
+ * Workflow:
3002
+ *
3003
+ * $ pnpm install --frozen-lockfile
3004
+ * $ pnpm build
3005
+ * $ pnpm exec tsx packages/cli/src/cli.ts publish --initial
3006
+ *
3007
+ * `npm login --auth-type=web` runs automatically the first time — no
3008
+ * separate manual step. `pnpm install` + `pnpm build` stay outside the
3009
+ * command (no pnpm-inside-pnpm).
3010
+ *
3011
+ * `--initial` is required today — this command only implements the
3012
+ * bootstrap publish. A non-initial `holocron publish` (for a manual publish
3013
+ * outside the semantic-release/OIDC steady state) isn't built yet; the flag
3014
+ * exists so the surface doesn't need another rename when it is.
3015
+ *
3016
+ * If `NPM_TOKEN` is detected in env, the command prints a final
3017
+ * "revoke this token at <url>" reminder — same pattern as `rando vc
3018
+ * setup` for the ephemeral GH admin PAT.
3019
+ */
3020
+ async function runPublish(input = {}) {
3021
+ const print = input.print ?? ((line) => console.log(line));
3022
+ const logger = input.logger ?? getLogger();
3023
+ const cwd = input.cwd ?? process.cwd();
3024
+ const tag = input.tag ?? "alpha";
3025
+ const dryRun = input.dryRun ?? false;
3026
+ const otp = input.otp;
3027
+ const env = makeEnv(input.env);
3028
+ const exec = input.exec ?? defaultExec$1;
3029
+ const login = input.login ?? defaultLogin;
3030
+ const publishArgs = [
3031
+ ...hasPackagesDir(cwd) ? ["-r", "--filter=./packages/*"] : [],
3032
+ "publish",
3033
+ "--access",
3034
+ "public",
3035
+ "--no-git-checks",
3036
+ "--tag",
3037
+ tag,
3038
+ ...otp ? ["--otp", otp] : []
3039
+ ];
3040
+ print(`Holocron publish --initial${dryRun ? " (dry-run)" : ""}`);
3041
+ print(` cwd: ${cwd}`);
3042
+ print(` tag: ${tag}`);
3043
+ logger.info({
3044
+ tag,
3045
+ dryRun: dryRun || void 0
3046
+ }, "publish --initial: start");
3047
+ if (otp) print(` otp: <${otp.length} chars>`);
3048
+ print("");
3049
+ print(" → verifying npm auth (`npm whoami`)…");
3050
+ let whoami = await exec("npm", ["whoami"], { cwd });
3051
+ if (whoami.exitCode !== 0) {
3052
+ print(" not authenticated — running `npm login --auth-type=web`…");
3053
+ logger.info({}, "publish --initial: npm login");
3054
+ if ((await login(cwd)).exitCode !== 0) {
3055
+ const message = "npm login failed. Run `npm login --auth-type=web` (or `npm login`) manually, then re-run.";
3056
+ print(` ✗ ${message}`);
3057
+ const packageNames = input.packages ?? discoverPublicPackages(cwd);
3058
+ logger.warn({ reason: "npm login failed" }, "publish --initial: done");
3059
+ return {
3060
+ status: "fail",
3061
+ message,
3062
+ packageNames
3063
+ };
3064
+ }
3065
+ whoami = await exec("npm", ["whoami"], { cwd });
3066
+ if (whoami.exitCode !== 0) {
3067
+ const message = "npm login completed but `npm whoami` still fails — check your npm account.";
3068
+ print(` ✗ ${message}`);
3069
+ const packageNames = input.packages ?? discoverPublicPackages(cwd);
3070
+ logger.warn({ reason: "npm whoami still fails after login" }, "publish --initial: done");
3071
+ return {
3072
+ status: "fail",
3073
+ message,
3074
+ packageNames
3075
+ };
3076
+ }
3077
+ }
3078
+ print(` ✓ authed as ${whoami.stdout.trim() || "<unknown>"}`);
3079
+ const packageNames = input.packages ?? discoverPublicPackages(cwd);
3080
+ const repoName = input.repoName ?? await resolveRepoName(cwd, exec);
3081
+ if (packageNames.length === 0) {
3082
+ const message = "nothing to publish (no packages/* and root package.json is private or unnamed)";
3083
+ print(` ✗ ${message}`);
3084
+ logger.warn({ reason: message }, "publish --initial: done");
3085
+ return {
3086
+ status: "fail",
3087
+ message,
3088
+ packageNames
3089
+ };
3090
+ }
3091
+ if (dryRun) {
3092
+ print("");
3093
+ print(" … (dry-run) skipping actual publish");
3094
+ print(` would run: pnpm ${publishArgs.join(" ")}`);
3095
+ printNextSteps(print, env, packageNames, repoName);
3096
+ logger.info({
3097
+ tag,
3098
+ status: "dry-run",
3099
+ packages: packageNames.length
3100
+ }, "publish --initial: done");
3101
+ return {
3102
+ status: "dry-run",
3103
+ message: "dry-run — no publish executed",
3104
+ packageNames
3105
+ };
3106
+ }
3107
+ print("");
3108
+ print(" → publishing all public @theholocron/* packages…");
3109
+ const publish = await exec("pnpm", publishArgs, { cwd });
3110
+ if (publish.exitCode !== 0) {
3111
+ const message = `publish failed (exit ${publish.exitCode}): ${publish.stderr.trim() || publish.stdout.trim() || "no output"}`;
3112
+ print(` ✗ ${message}`);
3113
+ if (publish.stdout.includes("EOTP") || publish.stderr.includes("EOTP")) {
3114
+ print("");
3115
+ print(" → hint: your npm account requires 2FA for writes. Re-run with `--otp <code>`:");
3116
+ print(` pnpm exec tsx packages/cli/src/cli.ts publish --initial --otp <6-digit-code>`);
3117
+ }
3118
+ logger.warn({
3119
+ tag,
3120
+ reason: message
3121
+ }, "publish --initial: done");
3122
+ return {
3123
+ status: "fail",
3124
+ message,
3125
+ packageNames
3126
+ };
3127
+ }
3128
+ print(" ✓ publish complete");
3129
+ printNextSteps(print, env, packageNames, repoName);
3130
+ logger.info({
3131
+ tag,
3132
+ status: "ok",
3133
+ packages: packageNames.length
3134
+ }, "publish --initial: done");
3135
+ return {
3136
+ status: "ok",
3137
+ packageNames
3138
+ };
3139
+ }
3140
+ function hasPackagesDir(cwd) {
3141
+ return existsSync(join(cwd, "packages"));
3142
+ }
3143
+ /** Read a `package.json`'s `name`, when it's public (`!private && name`). */
3144
+ function publicPackageName(pkgPath) {
3145
+ if (!existsSync(pkgPath)) return void 0;
3146
+ try {
3147
+ const pkg = JSON.parse(readFileSync(pkgPath, "utf-8"));
3148
+ return !pkg.private && pkg.name ? pkg.name : void 0;
3149
+ } catch {
3150
+ return;
3151
+ }
3152
+ }
3153
+ /**
3154
+ * Monorepo (`packages/` present): every public `packages/*` workspace.
3155
+ * Single package (no `packages/`): the root `package.json`, if it's public —
3156
+ * most `node-template` scaffolds are one package at the repo root.
3157
+ */
3158
+ function discoverPublicPackages(cwd) {
3159
+ if (!hasPackagesDir(cwd)) {
3160
+ const name = publicPackageName(join(cwd, "package.json"));
3161
+ return name ? [name] : [];
3162
+ }
3163
+ const packagesDir = join(cwd, "packages");
3164
+ return readdirSync(packagesDir, { withFileTypes: true }).filter((e) => e.isDirectory()).flatMap((e) => {
3165
+ const name = publicPackageName(join(packagesDir, e.name, "package.json"));
3166
+ return name ? [name] : [];
3167
+ });
3168
+ }
3169
+ async function resolveRepoName(cwd, exec) {
3170
+ const result = await exec("git", [
3171
+ "remote",
3172
+ "get-url",
3173
+ "origin"
3174
+ ], { cwd });
3175
+ if (result.exitCode !== 0) return "unknown";
3176
+ return /[/:]([^/:]+?)(?:\.git)?$/.exec(result.stdout.trim())?.[1] ?? "unknown";
3177
+ }
3178
+ function printNextSteps(print, env, packageNames, repoName) {
3179
+ print("");
3180
+ print(" → next: configure Trusted Publisher for each package on npm:");
3181
+ for (const name of packageNames) print(` https://www.npmjs.com/package/${name}/access`);
3182
+ print(` Publisher: GitHub Actions Org: theholocron Repo: ${repoName} Workflow: release.yml`);
3183
+ if (env.get("NPM_TOKEN")) {
3184
+ print("");
3185
+ print(" → cleanup: $NPM_TOKEN was used. Revoke it now (no API for self-revoke; UI-only):");
3186
+ print(" https://www.npmjs.com/settings/~/tokens");
3187
+ }
3188
+ }
3189
+ const defaultExec$1 = async (cmd, args, opts) => {
3190
+ const result = spawnSync(cmd, args, {
3191
+ cwd: opts.cwd,
3192
+ encoding: "utf8",
3193
+ stdio: [
3194
+ "inherit",
3195
+ "pipe",
3196
+ "pipe"
3197
+ ]
3198
+ });
3199
+ return {
3200
+ exitCode: result.status ?? -1,
3201
+ stdout: result.stdout ?? "",
3202
+ stderr: result.stderr ?? ""
3203
+ };
3204
+ };
3205
+ /**
3206
+ * Fully interactive — `npm login --auth-type=web` prints a URL and waits for
3207
+ * the browser flow to complete; the operator needs to see that live, so all
3208
+ * three stdio streams are inherited (unlike `defaultExec`, which pipes
3209
+ * stdout/stderr for capture).
3210
+ */
3211
+ const defaultLogin = async (cwd) => {
3212
+ return { exitCode: spawnSync("npm", ["login", "--auth-type=web"], {
3213
+ cwd,
3214
+ stdio: "inherit"
3215
+ }).status ?? -1 };
3216
+ };
3217
+ //#endregion
3160
3218
  //#region src/commands/secret-set.ts
3161
3219
  async function runSecretSet(input) {
3162
3220
  const print = input.print ?? ((line) => console.log(line));
@@ -7337,7 +7395,7 @@ try {
7337
7395
  project: argv.project,
7338
7396
  ...argv.repo ? { repo: argv.repo } : {}
7339
7397
  })).status === "fail") process.exitCode = 1;
7340
- }).command("npm", "npm-related monorepo utilities", (y) => y.command("bump-versions <new-version>", "Bump all non-private package versions in lockstep (semantic-release prepareCmd)", (yy) => yy.positional("new-version", {
7398
+ }).command("bump-versions <new-version>", "Bump all non-private package versions in lockstep (semantic-release prepareCmd)", (y) => y.positional("new-version", {
7341
7399
  type: "string",
7342
7400
  demandOption: true,
7343
7401
  describe: "Version to set (e.g., 4.2.0 or 2.0.0-alpha.1)"
@@ -7347,7 +7405,11 @@ try {
7347
7405
  cwd: argv.cwd,
7348
7406
  dryRun: argv.dryRun
7349
7407
  })).status === "fail") process.exitCode = 1;
7350
- }).command("publish-initial", "One-shot bootstrap publish for trusted-publishing-eligible packages", (yy) => yy.option("tag", {
7408
+ }).command("publish", "Publish @theholocron/* packages to npm", (y) => y.option("initial", {
7409
+ type: "boolean",
7410
+ default: false,
7411
+ describe: "One-shot bootstrap publish for trusted-publishing-eligible packages (npm needs the package to exist before Trusted Publishing can be configured for it). Required today — a non-initial `publish` isn't implemented yet."
7412
+ }).option("tag", {
7351
7413
  type: "string",
7352
7414
  default: "alpha",
7353
7415
  describe: "npm distribution tag (defaults to alpha)"
@@ -7355,13 +7417,18 @@ try {
7355
7417
  type: "string",
7356
7418
  describe: "One-time password from your authenticator (required if npm needs 2FA for writes)"
7357
7419
  }), async (argv) => {
7358
- if ((await runNpmPublishInitial({
7420
+ if (!argv.initial) {
7421
+ getLogger().error("publish: only `--initial` is supported today. Run `holocron publish --initial`.");
7422
+ process.exitCode = 1;
7423
+ return;
7424
+ }
7425
+ if ((await runPublish({
7359
7426
  cwd: argv.cwd,
7360
7427
  tag: argv.tag,
7361
7428
  dryRun: argv.dryRun,
7362
7429
  ...argv.otp ? { otp: argv.otp } : {}
7363
7430
  })).status === "fail") process.exitCode = 1;
7364
- }).demandCommand(1, "Run `holocron npm --help` to see available npm subcommands."), () => {}).command("sync [steps..]", "Sync state from config to the provider and local files (labels, properties, teams, topics, keywords, description, homepage, readme, workflows, scripts, wiki)", (y) => y.positional("steps", {
7431
+ }).command("sync [steps..]", "Sync state from config to the provider and local files (labels, properties, teams, topics, keywords, description, homepage, readme, workflows, scripts, wiki)", (y) => y.positional("steps", {
7365
7432
  type: "string",
7366
7433
  array: true,
7367
7434
  describe: "Steps to run: labels, properties, teams, topics, keywords, description, homepage, readme, workflows, scripts, wiki (default: all)"