github-labels-template 0.6.1-staging.3ace40c โ†’ 0.6.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.
Files changed (3) hide show
  1. package/README.md +7 -49
  2. package/dist/index.js +16 -187
  3. package/package.json +1 -1
package/README.md CHANGED
@@ -14,9 +14,7 @@ A CLI tool to apply a curated set of GitHub labels to any repository using `gh`
14
14
  - ๐Ÿš€ **One Command Setup**: Apply all labels to any repo with `ghlt apply`
15
15
  - ๐Ÿ” **Auto-Detect Repo**: Automatically detects the current repository from git remote
16
16
  - ๐Ÿ”„ **Smart Conflict Handling**: Skips existing labels by default, `--force` to update
17
- - ๐Ÿ“‹ **List Command**: View all labels on any repo โ€” name, color, and description at a glance
18
- - ๐Ÿงน **Wipe Command**: Remove all or specific labels with a confirmation prompt
19
- - ๐Ÿšซ **Apply with Exclusions**: Skip specific labels or entire categories with `--exclude` / `--exclude-category`
17
+ - ๐Ÿงน **Wipe Command**: Remove all existing labels with a confirmation prompt
20
18
  - โœ… **Pre-Flight Checks**: Validates `gh` CLI is installed and authenticated before doing anything
21
19
  - ๐Ÿ“Š **Clear Output**: Structured logging powered by [@wgtechlabs/log-engine](https://github.com/wgtechlabs/log-engine) with color-coded levels and emoji
22
20
  - ๐ŸŽจ **ASCII Banner**: Beautiful ANSI Shadow figlet banner with version and author info
@@ -85,15 +83,6 @@ ghlt apply --category community --label bug
85
83
  # Combine with force and repo
86
84
  ghlt apply --category type --force --repo owner/repo
87
85
 
88
- # Apply all labels except specific ones
89
- ghlt apply --exclude "bug,enhancement"
90
-
91
- # Apply all labels except an entire category
92
- ghlt apply --exclude-category type
93
-
94
- # Combine: apply all community labels except hacktoberfest
95
- ghlt apply --category community --exclude hacktoberfest
96
-
97
86
  # Include custom labels from labels-custom.json
98
87
  ghlt apply --custom
99
88
 
@@ -101,16 +90,6 @@ ghlt apply --custom
101
90
  ghlt apply --custom --category type
102
91
  ```
103
92
 
104
- ### List Labels
105
-
106
- ```bash
107
- # List all labels on the current repo
108
- ghlt list
109
-
110
- # List labels on a specific repo
111
- ghlt list --repo owner/repo
112
- ```
113
-
114
93
  ### Generate Labels (AI)
115
94
 
116
95
  Generate custom labels using GitHub Copilot โ€” following the Clean Labels convention. Requires a [GitHub Copilot](https://github.com/features/copilot) subscription.
@@ -166,18 +145,6 @@ ghlt wipe --repo owner/repo
166
145
 
167
146
  # Skip confirmation prompt
168
147
  ghlt wipe --yes
169
-
170
- # Remove specific labels
171
- ghlt wipe --label "bug,enhancement"
172
-
173
- # Remove all labels from a category
174
- ghlt wipe --category type
175
-
176
- # Remove labels from multiple categories
177
- ghlt wipe --category "type,status"
178
-
179
- # Include custom labels in the selective wipe scope
180
- ghlt wipe --category type --custom
181
148
  ```
182
149
 
183
150
  ### Preview Landing Page
@@ -276,30 +243,24 @@ Broad software layers โ€” universal across any project.
276
243
  ghlt โ€” GitHub Labels Template CLI
277
244
 
278
245
  USAGE
279
- ghlt [OPTIONS] apply|wipe|migrate|generate|list|preview
246
+ ghlt [OPTIONS] apply|wipe|migrate|generate|preview
280
247
 
281
248
  OPTIONS
282
249
  -v, --version Show version number
283
250
 
284
251
  COMMANDS
285
252
  apply Apply labels from the template to a repository
286
- wipe Remove all or specific labels from a repository
253
+ wipe Remove all existing labels from a repository
287
254
  migrate Wipe all existing labels and apply the template (clean slate)
288
255
  generate Generate custom labels using AI (requires GitHub Copilot)
289
- list List all labels in a repository
290
256
  preview Preview the landing page locally in your browser
291
257
 
292
258
  OPTIONS (apply)
293
- -r, --repo <owner/repo> Target repository (default: auto-detect)
294
- -f, --force Overwrite existing labels
295
- -l, --label <name> Apply specific label(s) by name (comma-separated)
296
- -c, --category <name> Apply labels from specific category(ies) (comma-separated)
297
- -e, --exclude <name> Exclude specific label(s) by name (comma-separated)
298
- --exclude-category <name> Exclude labels from specific category(ies) (comma-separated)
299
- --custom Include custom labels from labels-custom.json
300
-
301
- OPTIONS (list)
302
259
  -r, --repo <owner/repo> Target repository (default: auto-detect)
260
+ -f, --force Overwrite existing labels
261
+ -l, --label <name> Apply specific label(s) by name (comma-separated)
262
+ -c, --category <name> Apply labels from specific category(ies) (comma-separated)
263
+ --custom Include custom labels from labels-custom.json
303
264
 
304
265
  OPTIONS (migrate)
305
266
  -r, --repo <owner/repo> Target repository (default: auto-detect)
@@ -314,9 +275,6 @@ OPTIONS (generate)
314
275
  OPTIONS (wipe)
315
276
  -r, --repo <owner/repo> Target repository (default: auto-detect)
316
277
  -y, --yes Skip confirmation prompt
317
- -l, --label <name> Remove specific label(s) by name (comma-separated)
318
- -c, --category <name> Remove labels from specific category(ies) (comma-separated)
319
- --custom Include custom labels when using --label or --category
320
278
 
321
279
  OPTIONS (preview)
322
280
  -p, --port <number> Port to serve on (default: 3000)
package/dist/index.js CHANGED
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
 
3
3
  // src/index.ts
4
- import { defineCommand as defineCommand6, runMain } from "citty";
4
+ import { defineCommand as defineCommand5, runMain } from "citty";
5
5
 
6
6
  // src/commands/apply.ts
7
7
  import { defineCommand } from "citty";
@@ -52,28 +52,6 @@ async function detectRepo() {
52
52
  return null;
53
53
  }
54
54
  }
55
- async function listLabelsDetailed(repo) {
56
- const { exitCode, stdout } = await run([
57
- "label",
58
- "list",
59
- "--repo",
60
- repo,
61
- "--json",
62
- "name,color,description",
63
- "--limit",
64
- "100"
65
- ]);
66
- if (exitCode !== 0)
67
- return [];
68
- const text = stdout.trim();
69
- if (!text)
70
- return [];
71
- try {
72
- return JSON.parse(text);
73
- } catch {
74
- return [];
75
- }
76
- }
77
55
  async function listLabels(repo) {
78
56
  const { exitCode, stdout } = await run([
79
57
  "label",
@@ -183,9 +161,7 @@ function filterLabels(allLabels, options) {
183
161
  const warnings = [];
184
162
  const labelFilter = options.label ? options.label.split(",").map((l) => l.trim().toLowerCase()).filter(Boolean) : null;
185
163
  const categoryFilter = options.category ? options.category.split(",").map((c) => c.trim().toLowerCase()).filter(Boolean) : null;
186
- const excludeLabelFilter = options.excludeLabel ? options.excludeLabel.split(",").map((l) => l.trim().toLowerCase()).filter(Boolean) : null;
187
- const excludeCategoryFilter = options.excludeCategory ? options.excludeCategory.split(",").map((c) => c.trim().toLowerCase()).filter(Boolean) : null;
188
- if (!labelFilter && !categoryFilter && !excludeLabelFilter && !excludeCategoryFilter) {
164
+ if (!labelFilter && !categoryFilter) {
189
165
  return {
190
166
  entries: Object.entries(allLabels),
191
167
  warnings
@@ -207,25 +183,7 @@ function filterLabels(allLabels, options) {
207
183
  }
208
184
  }
209
185
  }
210
- if (excludeCategoryFilter) {
211
- for (const cat of excludeCategoryFilter) {
212
- if (!validCategories.includes(cat)) {
213
- warnings.push(`Unknown exclude category "${cat}". Valid categories: ${validCategories.join(", ")}`);
214
- }
215
- }
216
- }
217
- if (excludeLabelFilter) {
218
- const allLabelNames = Object.values(allLabels).flat().map((l) => l.name.toLowerCase());
219
- for (const name of excludeLabelFilter) {
220
- if (!allLabelNames.includes(name)) {
221
- warnings.push(`Exclude label "${name}" not found in the template.`);
222
- }
223
- }
224
- }
225
- const included = Object.entries(allLabels).map(([category, categoryLabels]) => {
226
- if (!labelFilter && !categoryFilter) {
227
- return [category, categoryLabels];
228
- }
186
+ const entries = Object.entries(allLabels).map(([category, categoryLabels]) => {
229
187
  const categoryMatches = categoryFilter?.includes(category.toLowerCase()) ?? false;
230
188
  if (categoryMatches) {
231
189
  return [category, categoryLabels];
@@ -236,14 +194,6 @@ function filterLabels(allLabels, options) {
236
194
  }
237
195
  return [category, []];
238
196
  }).filter(([, categoryLabels]) => categoryLabels.length > 0);
239
- const entries = included.filter(([category]) => excludeCategoryFilter ? !excludeCategoryFilter.includes(category.toLowerCase()) : true).map(([category, categoryLabels]) => {
240
- if (!excludeLabelFilter)
241
- return [category, categoryLabels];
242
- return [
243
- category,
244
- categoryLabels.filter((l) => !excludeLabelFilter.includes(l.name.toLowerCase()))
245
- ];
246
- }).filter(([, categoryLabels]) => categoryLabels.length > 0);
247
197
  return { entries, warnings };
248
198
  }
249
199
 
@@ -356,15 +306,6 @@ var apply_default = defineCommand({
356
306
  type: "boolean",
357
307
  default: false,
358
308
  description: "Include custom labels from labels-custom.json (generated via ghlt generate)"
359
- },
360
- exclude: {
361
- type: "string",
362
- alias: "e",
363
- description: 'Exclude specific label(s) by name. Comma-separated for multiple (e.g., --exclude "bug,enhancement")'
364
- },
365
- "exclude-category": {
366
- type: "string",
367
- description: 'Exclude labels from specific category(ies). Comma-separated for multiple (e.g., --exclude-category "type,status")'
368
309
  }
369
310
  },
370
311
  async run({ args }) {
@@ -409,9 +350,7 @@ var apply_default = defineCommand({
409
350
  }
410
351
  const { entries: filteredEntries, warnings } = filterLabels(labelPool, {
411
352
  label: args.label,
412
- category: args.category,
413
- excludeLabel: args.exclude,
414
- excludeCategory: args["exclude-category"]
353
+ category: args.category
415
354
  });
416
355
  for (const w of warnings) {
417
356
  warn(w);
@@ -422,12 +361,6 @@ var apply_default = defineCommand({
422
361
  if (args.label) {
423
362
  info(`Applying specific labels: ${args.label}`);
424
363
  }
425
- if (args["exclude-category"]) {
426
- info(`Excluding categories: ${args["exclude-category"]}`);
427
- }
428
- if (args.exclude) {
429
- info(`Excluding labels: ${args.exclude}`);
430
- }
431
364
  if (filteredEntries.length === 0) {
432
365
  warn("No labels matched the specified filter(s).");
433
366
  return;
@@ -507,21 +440,6 @@ var wipe_default = defineCommand2({
507
440
  alias: "y",
508
441
  default: false,
509
442
  description: "Skip confirmation prompt"
510
- },
511
- label: {
512
- type: "string",
513
- alias: "l",
514
- description: 'Remove specific label(s) by name. Comma-separated for multiple (e.g., --label "bug,enhancement")'
515
- },
516
- category: {
517
- type: "string",
518
- alias: "c",
519
- description: 'Remove labels from specific category(ies). Comma-separated for multiple (e.g., --category "type,status")'
520
- },
521
- custom: {
522
- type: "boolean",
523
- default: false,
524
- description: "Include custom labels from labels-custom.json when using --label or --category"
525
443
  }
526
444
  },
527
445
  async run({ args }) {
@@ -544,57 +462,14 @@ var wipe_default = defineCommand2({
544
462
  info("No labels found. Nothing to wipe.");
545
463
  return;
546
464
  }
547
- const isSelective = !!(args.label || args.category);
548
- let toDelete;
549
- if (isSelective) {
550
- const labelPool = {
551
- ...labels_default
552
- };
553
- if (args.custom) {
554
- const custom = loadCustomLabels();
555
- for (const [cat, catLabels] of Object.entries(custom)) {
556
- if (!labelPool[cat])
557
- labelPool[cat] = [];
558
- for (const label of catLabels) {
559
- const exists = labelPool[cat].some((l) => l.name.toLowerCase() === label.name.toLowerCase());
560
- if (!exists)
561
- labelPool[cat].push(label);
562
- }
563
- }
564
- }
565
- const { entries: filteredEntries, warnings } = filterLabels(labelPool, {
566
- label: args.label,
567
- category: args.category
568
- });
569
- for (const w of warnings) {
570
- warn(w);
571
- }
572
- if (filteredEntries.length === 0) {
573
- warn("No labels matched the specified filter(s).");
574
- return;
575
- }
576
- const existingSet = new Set(existing.map((n) => n.toLowerCase()));
577
- toDelete = filteredEntries.flatMap(([, categoryLabels]) => categoryLabels.map((l) => l.name)).filter((name) => existingSet.has(name.toLowerCase()));
578
- if (toDelete.length === 0) {
579
- info("None of the specified labels exist on the repo. Nothing to remove.");
580
- return;
581
- }
582
- if (args.label)
583
- info(`Removing specific labels: ${args.label}`);
584
- if (args.category)
585
- info(`Removing labels from category: ${args.category}`);
586
- } else {
587
- toDelete = existing;
588
- }
589
465
  if (!args.yes) {
590
- const message = isSelective ? pc3.bold(pc3.red(`This will delete ${toDelete.length} label(s) from ${repo}.`)) : pc3.bold(pc3.red(`This will delete all ${toDelete.length} labels from ${repo}.`));
591
- const confirmed = await confirmPrompt(message);
466
+ const confirmed = await confirmPrompt(pc3.bold(pc3.red(`This will delete all ${existing.length} labels from ${repo}.`)));
592
467
  if (!confirmed)
593
468
  return;
594
469
  }
595
470
  heading("Deleting Labels");
596
471
  const counts = { deleted: 0, failed: 0 };
597
- for (const name of toDelete) {
472
+ for (const name of existing) {
598
473
  const ok = await deleteLabel(repo, name);
599
474
  if (ok) {
600
475
  success(`${name} (deleted)`);
@@ -1018,58 +893,13 @@ var migrate_default = defineCommand4({
1018
893
  }
1019
894
  });
1020
895
 
1021
- // src/commands/list.ts
1022
- import { defineCommand as defineCommand5 } from "citty";
1023
- import pc6 from "picocolors";
1024
- var list_default = defineCommand5({
1025
- meta: {
1026
- name: "list",
1027
- description: "List all labels in a repository"
1028
- },
1029
- args: {
1030
- repo: {
1031
- type: "string",
1032
- alias: "r",
1033
- description: "Target repository (owner/repo). Defaults to current repo."
1034
- }
1035
- },
1036
- async run({ args }) {
1037
- if (!await checkGhInstalled()) {
1038
- error("gh CLI is not installed. Install it from https://cli.github.com");
1039
- process.exit(1);
1040
- }
1041
- if (!await checkGhAuth()) {
1042
- error("Not authenticated. Run `gh auth login` first.");
1043
- process.exit(1);
1044
- }
1045
- const repo = args.repo || await detectRepo();
1046
- if (!repo) {
1047
- error("Could not detect repository. Use --repo <owner/repo> or run inside a git repo.");
1048
- process.exit(1);
1049
- }
1050
- info(`Target: ${repo}`);
1051
- const labels = await listLabelsDetailed(repo);
1052
- if (labels.length === 0) {
1053
- info("No labels found.");
1054
- return;
1055
- }
1056
- heading(`Labels (${labels.length} total)`);
1057
- for (const label of labels) {
1058
- const name = pc6.bold(label.name.padEnd(30));
1059
- const color = pc6.dim(`#${label.color}`);
1060
- const desc = label.description ? pc6.dim(label.description) : "";
1061
- console.log(` ${name} ${color} ${desc}`);
1062
- }
1063
- }
1064
- });
1065
-
1066
896
  // src/ui/banner.ts
1067
897
  import figlet from "figlet";
1068
- import pc7 from "picocolors";
898
+ import pc6 from "picocolors";
1069
899
  // package.json
1070
900
  var package_default = {
1071
901
  name: "github-labels-template",
1072
- version: "0.6.1-staging.3ace40c",
902
+ version: "0.6.1",
1073
903
  description: "A CLI tool to apply a curated GitHub labels template to any repository using gh CLI.",
1074
904
  type: "module",
1075
905
  bin: {
@@ -1134,15 +964,15 @@ function getAuthor() {
1134
964
  return package_default.author ?? "unknown";
1135
965
  }
1136
966
  function showBanner(minimal = false) {
1137
- console.log(pc7.cyan(`
967
+ console.log(pc6.cyan(`
1138
968
  ` + LOGO));
1139
- console.log(` ${pc7.dim("v" + getVersion())} ${pc7.dim("โ€”")} ${pc7.dim("Built by " + getAuthor())}`);
969
+ console.log(` ${pc6.dim("v" + getVersion())} ${pc6.dim("โ€”")} ${pc6.dim("Built by " + getAuthor())}`);
1140
970
  if (!minimal) {
1141
- console.log(` ${pc7.dim(package_default.description)}`);
971
+ console.log(` ${pc6.dim(package_default.description)}`);
1142
972
  console.log();
1143
- console.log(` ${pc7.yellow("Star")} ${pc7.cyan("https://gh.waren.build/github-labels-template")}`);
1144
- console.log(` ${pc7.green("Contribute")} ${pc7.cyan("https://gh.waren.build/github-labels-template/blob/main/CONTRIBUTING.md")}`);
1145
- console.log(` ${pc7.magenta("Sponsor")} ${pc7.cyan("https://warengonzaga.com/sponsor")}`);
973
+ console.log(` ${pc6.yellow("Star")} ${pc6.cyan("https://gh.waren.build/github-labels-template")}`);
974
+ console.log(` ${pc6.green("Contribute")} ${pc6.cyan("https://gh.waren.build/github-labels-template/blob/main/CONTRIBUTING.md")}`);
975
+ console.log(` ${pc6.magenta("Sponsor")} ${pc6.cyan("https://warengonzaga.com/sponsor")}`);
1146
976
  }
1147
977
  console.log();
1148
978
  }
@@ -1150,7 +980,7 @@ function showBanner(minimal = false) {
1150
980
  // src/index.ts
1151
981
  var isHelp = process.argv.includes("--help") || process.argv.includes("-h");
1152
982
  showBanner(isHelp);
1153
- var main = defineCommand6({
983
+ var main = defineCommand5({
1154
984
  meta: {
1155
985
  name: "ghlt",
1156
986
  version: getVersion(),
@@ -1167,8 +997,7 @@ var main = defineCommand6({
1167
997
  apply: apply_default,
1168
998
  wipe: wipe_default,
1169
999
  migrate: migrate_default,
1170
- generate: generate_default,
1171
- list: list_default
1000
+ generate: generate_default
1172
1001
  },
1173
1002
  run({ args }) {
1174
1003
  if (args.version) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "github-labels-template",
3
- "version": "0.6.1-staging.3ace40c",
3
+ "version": "0.6.1",
4
4
  "description": "A CLI tool to apply a curated GitHub labels template to any repository using gh CLI.",
5
5
  "type": "module",
6
6
  "bin": {