pingthings 0.3.0 → 0.4.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 (71) hide show
  1. package/README.md +12 -0
  2. package/bin/pingthings.js +6 -0
  3. package/package.json +1 -1
  4. package/packs/0ad-civilizations/manifest.json +1 -0
  5. package/packs/7kaa-soldiers/manifest.json +1 -0
  6. package/packs/freedoom-arsenal/manifest.json +1 -0
  7. package/packs/kenney-interface/manifest.json +58 -0
  8. package/packs/kenney-interface/sounds/back-1.wav +0 -0
  9. package/packs/kenney-interface/sounds/bong.wav +0 -0
  10. package/packs/kenney-interface/sounds/click-1.wav +0 -0
  11. package/packs/kenney-interface/sounds/close-1.wav +0 -0
  12. package/packs/kenney-interface/sounds/confirmation-1.wav +0 -0
  13. package/packs/kenney-interface/sounds/confirmation-2.wav +0 -0
  14. package/packs/kenney-interface/sounds/confirmation-3.wav +0 -0
  15. package/packs/kenney-interface/sounds/error-1.wav +0 -0
  16. package/packs/kenney-interface/sounds/error-2.wav +0 -0
  17. package/packs/kenney-interface/sounds/error-3.wav +0 -0
  18. package/packs/kenney-interface/sounds/glitch-1.wav +0 -0
  19. package/packs/kenney-interface/sounds/maximize-1.wav +0 -0
  20. package/packs/kenney-interface/sounds/maximize-2.wav +0 -0
  21. package/packs/kenney-interface/sounds/open-1.wav +0 -0
  22. package/packs/kenney-interface/sounds/pluck-1.wav +0 -0
  23. package/packs/kenney-interface/sounds/question-1.wav +0 -0
  24. package/packs/kenney-interface/sounds/question-2.wav +0 -0
  25. package/packs/kenney-interface/sounds/question-3.wav +0 -0
  26. package/packs/kenney-scifi/manifest.json +58 -0
  27. package/packs/kenney-scifi/sounds/computer-1.wav +0 -0
  28. package/packs/kenney-scifi/sounds/computer-2.wav +0 -0
  29. package/packs/kenney-scifi/sounds/computer-3.wav +0 -0
  30. package/packs/kenney-scifi/sounds/door-close.wav +0 -0
  31. package/packs/kenney-scifi/sounds/door-open.wav +0 -0
  32. package/packs/kenney-scifi/sounds/engine-1.wav +0 -0
  33. package/packs/kenney-scifi/sounds/explosion-1.wav +0 -0
  34. package/packs/kenney-scifi/sounds/explosion-2.wav +0 -0
  35. package/packs/kenney-scifi/sounds/forcefield-1.wav +0 -0
  36. package/packs/kenney-scifi/sounds/forcefield-2.wav +0 -0
  37. package/packs/kenney-scifi/sounds/impact-1.wav +0 -0
  38. package/packs/kenney-scifi/sounds/impact-2.wav +0 -0
  39. package/packs/kenney-scifi/sounds/laser-large.wav +0 -0
  40. package/packs/kenney-scifi/sounds/laser-retro.wav +0 -0
  41. package/packs/kenney-scifi/sounds/low-explosion.wav +0 -0
  42. package/packs/kenney-scifi/sounds/slime.wav +0 -0
  43. package/packs/kenney-scifi/sounds/thruster-1.wav +0 -0
  44. package/packs/kenney-scifi/sounds/thruster-2.wav +0 -0
  45. package/packs/openarena-announcer/manifest.json +1 -0
  46. package/packs/retro-8bit/manifest.json +58 -0
  47. package/packs/retro-8bit/sounds/button-1.wav +0 -0
  48. package/packs/retro-8bit/sounds/button-2.wav +0 -0
  49. package/packs/retro-8bit/sounds/button-3.wav +0 -0
  50. package/packs/retro-8bit/sounds/coin-1.wav +0 -0
  51. package/packs/retro-8bit/sounds/coin-2.wav +0 -0
  52. package/packs/retro-8bit/sounds/coin-cluster.wav +0 -0
  53. package/packs/retro-8bit/sounds/coin-double.wav +0 -0
  54. package/packs/retro-8bit/sounds/damage-1.wav +0 -0
  55. package/packs/retro-8bit/sounds/error-1.wav +0 -0
  56. package/packs/retro-8bit/sounds/error-2.wav +0 -0
  57. package/packs/retro-8bit/sounds/error-3.wav +0 -0
  58. package/packs/retro-8bit/sounds/fanfare-1.wav +0 -0
  59. package/packs/retro-8bit/sounds/fanfare-2.wav +0 -0
  60. package/packs/retro-8bit/sounds/fanfare-3.wav +0 -0
  61. package/packs/retro-8bit/sounds/negative-1.wav +0 -0
  62. package/packs/retro-8bit/sounds/negative-2.wav +0 -0
  63. package/packs/retro-8bit/sounds/powerup-1.wav +0 -0
  64. package/packs/retro-8bit/sounds/powerup-2.wav +0 -0
  65. package/packs/warzone2100-command/manifest.json +1 -0
  66. package/packs/wesnoth-combat/manifest.json +1 -0
  67. package/src/cli/browse.js +75 -0
  68. package/src/cli/search.js +81 -0
  69. package/src/cli/sounds.js +76 -0
  70. package/src/cli/theme.js +34 -1
  71. package/src/packs.js +1 -0
package/README.md CHANGED
@@ -134,6 +134,9 @@ For different sounds based on what Claude is doing, set up multiple hooks:
134
134
  | `pingthings config [key] [val]` | Show or update configuration |
135
135
  | `pingthings init` | Set up Claude Code hooks automatically |
136
136
  | `pingthings create <dir>` | Create a pack from audio files |
137
+ | `pingthings browse [category]` | Browse packs by category |
138
+ | `pingthings search <term>` | Search packs and sounds |
139
+ | `pingthings sounds [pack]` | List individual sounds in a pack |
137
140
  | `pingthings install <source>` | Install a pack from GitHub or local path |
138
141
  | `pingthings uninstall <pack>` | Remove a user-installed pack |
139
142
 
@@ -219,6 +222,15 @@ Sci-fi military commander voice lines from **Warzone 2100** — 21 sounds includ
219
222
  ### 0ad-civilizations
220
223
  Ancient civilization voice lines and alerts from **0 A.D.** — 28 sounds with Greek, Latin, and Persian voice acknowledgements ("my lord", "as you wish", "by your order") plus alarm sounds (victory, defeat, attack). License: CC-BY-SA 3.0.
221
224
 
225
+ ### retro-8bit
226
+ Classic 8-bit chiptune notification sounds — 18 sounds including coins, fanfares, power-ups, error buzzes, and button clicks. Perfect for that retro gaming feel. License: CC0.
227
+
228
+ ### kenney-interface
229
+ Clean modern UI notification sounds by **Kenney** — 18 sounds including confirmations, questions, errors, glitches, and bongs. Professional and minimal. License: CC0.
230
+
231
+ ### kenney-scifi
232
+ Futuristic sci-fi notification sounds by **Kenney** — 18 sounds including computer noises, force fields, lasers, explosions, and thrusters. License: CC0.
233
+
222
234
  ## Custom packs
223
235
 
224
236
  Place packs in `~/.config/pingthings/packs/<pack-name>/`:
package/bin/pingthings.js CHANGED
@@ -15,6 +15,9 @@ const commands = {
15
15
  list: () => import('../src/cli/list.js'),
16
16
  use: () => import('../src/cli/use.js'),
17
17
  select: () => import('../src/cli/select.js'),
18
+ browse: () => import('../src/cli/browse.js'),
19
+ search: () => import('../src/cli/search.js'),
20
+ sounds: () => import('../src/cli/sounds.js'),
18
21
  preview: () => import('../src/cli/preview.js'),
19
22
  config: () => import('../src/cli/config.js'),
20
23
  install: () => import('../src/cli/install.js'),
@@ -35,6 +38,9 @@ Commands:
35
38
  play [sound] Play a sound from the active pack (random by default)
36
39
  list Show available sound packs
37
40
  select Interactive pack selector
41
+ browse [category] Browse packs by category
42
+ search <term> Search packs and sounds
43
+ sounds [pack] List individual sounds in a pack
38
44
  use <pack> Set the active sound pack
39
45
  preview <pack> Preview a random sound from a pack
40
46
  test-events [pack] Play all event sounds to hear what each one sounds like
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pingthings",
3
- "version": "0.3.0",
3
+ "version": "0.4.0",
4
4
  "description": "Notification sounds for Claude Code and other CLI tools",
5
5
  "type": "module",
6
6
  "license": "GPL-2.0",
@@ -4,6 +4,7 @@
4
4
  "version": "1.0.0",
5
5
  "license": "CC-BY-SA-3.0",
6
6
  "credits": "Wildfire Games / 0 A.D. (https://github.com/0ad/0ad) — audio licensed under CC-BY-SA 3.0",
7
+ "category": "military",
7
8
  "sounds": [
8
9
  "sounds/alarm-alert.wav",
9
10
  "sounds/alarm-attack.wav",
@@ -4,6 +4,7 @@
4
4
  "version": "1.0.0",
5
5
  "license": "GPL-2.0",
6
6
  "credits": "Enlight Software Ltd. / Seven Kingdoms: Ancient Adversaries (https://github.com/the3dfxdude/7kaa)",
7
+ "category": "military",
7
8
  "sounds": [
8
9
  "sounds/00001-CH_A2.wav",
9
10
  "sounds/00006-NO_V2.wav",
@@ -4,6 +4,7 @@
4
4
  "version": "1.0.0",
5
5
  "license": "BSD-3-Clause",
6
6
  "credits": "Freedoom contributors (https://github.com/freedoom/freedoom)",
7
+ "category": "fps",
7
8
  "sounds": [
8
9
  "sounds/dsbarexp.wav",
9
10
  "sounds/dsbfg.wav",
@@ -0,0 +1,58 @@
1
+ {
2
+ "name": "kenney-interface",
3
+ "description": "Clean modern UI notification sounds by Kenney",
4
+ "version": "1.0.0",
5
+ "license": "CC0-1.0",
6
+ "credits": "Kenney (https://kenney.nl)",
7
+ "category": "ui",
8
+ "sounds": [
9
+ "sounds/back-1.wav",
10
+ "sounds/bong.wav",
11
+ "sounds/click-1.wav",
12
+ "sounds/close-1.wav",
13
+ "sounds/confirmation-1.wav",
14
+ "sounds/confirmation-2.wav",
15
+ "sounds/confirmation-3.wav",
16
+ "sounds/error-1.wav",
17
+ "sounds/error-2.wav",
18
+ "sounds/error-3.wav",
19
+ "sounds/glitch-1.wav",
20
+ "sounds/maximize-1.wav",
21
+ "sounds/maximize-2.wav",
22
+ "sounds/open-1.wav",
23
+ "sounds/pluck-1.wav",
24
+ "sounds/question-1.wav",
25
+ "sounds/question-2.wav",
26
+ "sounds/question-3.wav"
27
+ ],
28
+ "events": {
29
+ "done": [
30
+ "sounds/confirmation-1.wav",
31
+ "sounds/confirmation-2.wav",
32
+ "sounds/confirmation-3.wav",
33
+ "sounds/click-1.wav"
34
+ ],
35
+ "permission": [
36
+ "sounds/question-1.wav",
37
+ "sounds/question-2.wav",
38
+ "sounds/question-3.wav",
39
+ "sounds/pluck-1.wav"
40
+ ],
41
+ "complete": [
42
+ "sounds/maximize-1.wav",
43
+ "sounds/maximize-2.wav",
44
+ "sounds/bong.wav",
45
+ "sounds/open-1.wav"
46
+ ],
47
+ "error": [
48
+ "sounds/error-1.wav",
49
+ "sounds/error-2.wav",
50
+ "sounds/error-3.wav",
51
+ "sounds/glitch-1.wav"
52
+ ],
53
+ "blocked": [
54
+ "sounds/close-1.wav",
55
+ "sounds/back-1.wav"
56
+ ]
57
+ }
58
+ }
@@ -0,0 +1,58 @@
1
+ {
2
+ "name": "kenney-scifi",
3
+ "description": "Futuristic sci-fi notification sounds by Kenney",
4
+ "version": "1.0.0",
5
+ "license": "CC0-1.0",
6
+ "credits": "Kenney (https://kenney.nl)",
7
+ "category": "sci-fi",
8
+ "sounds": [
9
+ "sounds/computer-1.wav",
10
+ "sounds/computer-2.wav",
11
+ "sounds/computer-3.wav",
12
+ "sounds/door-close.wav",
13
+ "sounds/door-open.wav",
14
+ "sounds/engine-1.wav",
15
+ "sounds/explosion-1.wav",
16
+ "sounds/explosion-2.wav",
17
+ "sounds/forcefield-1.wav",
18
+ "sounds/forcefield-2.wav",
19
+ "sounds/impact-1.wav",
20
+ "sounds/impact-2.wav",
21
+ "sounds/laser-large.wav",
22
+ "sounds/laser-retro.wav",
23
+ "sounds/low-explosion.wav",
24
+ "sounds/slime.wav",
25
+ "sounds/thruster-1.wav",
26
+ "sounds/thruster-2.wav"
27
+ ],
28
+ "events": {
29
+ "done": [
30
+ "sounds/computer-1.wav",
31
+ "sounds/computer-2.wav",
32
+ "sounds/computer-3.wav",
33
+ "sounds/door-open.wav"
34
+ ],
35
+ "permission": [
36
+ "sounds/forcefield-1.wav",
37
+ "sounds/forcefield-2.wav",
38
+ "sounds/laser-retro.wav"
39
+ ],
40
+ "complete": [
41
+ "sounds/thruster-1.wav",
42
+ "sounds/thruster-2.wav",
43
+ "sounds/engine-1.wav"
44
+ ],
45
+ "error": [
46
+ "sounds/explosion-1.wav",
47
+ "sounds/explosion-2.wav",
48
+ "sounds/low-explosion.wav",
49
+ "sounds/impact-1.wav",
50
+ "sounds/impact-2.wav"
51
+ ],
52
+ "blocked": [
53
+ "sounds/door-close.wav",
54
+ "sounds/laser-large.wav",
55
+ "sounds/slime.wav"
56
+ ]
57
+ }
58
+ }
@@ -4,6 +4,7 @@
4
4
  "version": "1.0.0",
5
5
  "license": "GPL-2.0",
6
6
  "credits": "OpenArena contributors (http://openarena.ws)",
7
+ "category": "arena",
7
8
  "sounds": [
8
9
  "sounds/accuracy.wav",
9
10
  "sounds/assist.wav",
@@ -0,0 +1,58 @@
1
+ {
2
+ "name": "retro-8bit",
3
+ "description": "Classic 8-bit chiptune notification sounds",
4
+ "version": "1.0.0",
5
+ "license": "CC0-1.0",
6
+ "credits": "Juhani Junkala / SubspaceAudio (https://opengameart.org/content/512-sound-effects-8-bit-style)",
7
+ "category": "retro",
8
+ "sounds": [
9
+ "sounds/button-1.wav",
10
+ "sounds/button-2.wav",
11
+ "sounds/button-3.wav",
12
+ "sounds/coin-1.wav",
13
+ "sounds/coin-2.wav",
14
+ "sounds/coin-cluster.wav",
15
+ "sounds/coin-double.wav",
16
+ "sounds/damage-1.wav",
17
+ "sounds/error-1.wav",
18
+ "sounds/error-2.wav",
19
+ "sounds/error-3.wav",
20
+ "sounds/fanfare-1.wav",
21
+ "sounds/fanfare-2.wav",
22
+ "sounds/fanfare-3.wav",
23
+ "sounds/negative-1.wav",
24
+ "sounds/negative-2.wav",
25
+ "sounds/powerup-1.wav",
26
+ "sounds/powerup-2.wav"
27
+ ],
28
+ "events": {
29
+ "done": [
30
+ "sounds/coin-1.wav",
31
+ "sounds/coin-2.wav",
32
+ "sounds/coin-double.wav",
33
+ "sounds/coin-cluster.wav"
34
+ ],
35
+ "permission": [
36
+ "sounds/button-1.wav",
37
+ "sounds/button-2.wav",
38
+ "sounds/button-3.wav"
39
+ ],
40
+ "complete": [
41
+ "sounds/fanfare-1.wav",
42
+ "sounds/fanfare-2.wav",
43
+ "sounds/fanfare-3.wav",
44
+ "sounds/powerup-1.wav",
45
+ "sounds/powerup-2.wav"
46
+ ],
47
+ "error": [
48
+ "sounds/error-1.wav",
49
+ "sounds/error-2.wav",
50
+ "sounds/error-3.wav",
51
+ "sounds/damage-1.wav"
52
+ ],
53
+ "blocked": [
54
+ "sounds/negative-1.wav",
55
+ "sounds/negative-2.wav"
56
+ ]
57
+ }
58
+ }
@@ -4,6 +4,7 @@
4
4
  "version": "1.0.0",
5
5
  "license": "GPL-2.0",
6
6
  "credits": "Warzone 2100 Project (https://github.com/Warzone2100/warzone2100)",
7
+ "category": "military",
7
8
  "sounds": [
8
9
  "sounds/construction-completed.wav",
9
10
  "sounds/design-completed.wav",
@@ -4,6 +4,7 @@
4
4
  "version": "1.0.0",
5
5
  "license": "GPL-2.0",
6
6
  "credits": "Battle for Wesnoth contributors (https://github.com/wesnoth/wesnoth) — licensed under GPL v2+",
7
+ "category": "fantasy",
7
8
  "sounds": [
8
9
  "sounds/axe.wav",
9
10
  "sounds/bow.wav",
@@ -0,0 +1,75 @@
1
+ import { readConfig } from '../config.js';
2
+ import { listPacks } from '../packs.js';
3
+
4
+ function showHelp() {
5
+ console.log(`
6
+ Usage: pingthings browse [category]
7
+
8
+ Browse packs by category.
9
+
10
+ With no arguments, shows all categories with pack counts.
11
+ With a category, shows packs in that category.
12
+
13
+ Categories: military, arena, fantasy, sci-fi, fps, retro, ui, transport, spooky, racing
14
+
15
+ Examples:
16
+ pingthings browse List all categories
17
+ pingthings browse military Show military packs
18
+ pingthings browse sci-fi Show sci-fi packs
19
+ `);
20
+ }
21
+
22
+ export default function browse(args) {
23
+ if (args.includes('--help') || args.includes('-h')) {
24
+ showHelp();
25
+ return;
26
+ }
27
+
28
+ const config = readConfig();
29
+ const packs = listPacks();
30
+ const category = args[0];
31
+
32
+ if (!category) {
33
+ // Show all categories with counts
34
+ const categories = {};
35
+ for (const pack of packs) {
36
+ const cat = pack.category || 'other';
37
+ if (!categories[cat]) categories[cat] = [];
38
+ categories[cat].push(pack);
39
+ }
40
+
41
+ console.log('\nCategories:\n');
42
+ for (const [cat, catPacks] of Object.entries(categories).sort()) {
43
+ const totalSounds = catPacks.reduce((sum, p) => sum + p.soundCount, 0);
44
+ console.log(` ${cat.padEnd(14)} ${catPacks.length} pack${catPacks.length === 1 ? '' : 's'}, ${totalSounds} sounds`);
45
+ for (const p of catPacks) {
46
+ const active = p.name === config.activePack ? ' *' : ' ';
47
+ console.log(` ${active} └ ${p.name}`);
48
+ }
49
+ }
50
+ console.log('\n * = active pack');
51
+ console.log(' Run "pingthings browse <category>" to see details.\n');
52
+ return;
53
+ }
54
+
55
+ // Show packs in a specific category
56
+ const filtered = packs.filter(p => (p.category || 'other') === category);
57
+
58
+ if (filtered.length === 0) {
59
+ console.error(`No packs found in category: ${category}`);
60
+ const allCats = [...new Set(packs.map(p => p.category || 'other'))].sort();
61
+ console.error(`Available categories: ${allCats.join(', ')}`);
62
+ process.exit(1);
63
+ }
64
+
65
+ console.log(`\n${category} packs:\n`);
66
+ for (const pack of filtered) {
67
+ const active = pack.name === config.activePack ? ' *' : ' ';
68
+ console.log(`${active} ${pack.name} (${pack.soundCount} sounds)`);
69
+ if (pack.description) {
70
+ console.log(` ${pack.description}`);
71
+ }
72
+ console.log(` License: ${pack.license}`);
73
+ }
74
+ console.log('\n * = active pack\n');
75
+ }
@@ -0,0 +1,81 @@
1
+ import { readConfig } from '../config.js';
2
+ import { listPacks, getPackSounds } from '../packs.js';
3
+ import { basename } from 'node:path';
4
+
5
+ function showHelp() {
6
+ console.log(`
7
+ Usage: pingthings search <term>
8
+
9
+ Search across all packs by name, description, category, or sound filename.
10
+
11
+ Arguments:
12
+ term Text to search for (case-insensitive)
13
+
14
+ Examples:
15
+ pingthings search sword Find packs/sounds with "sword"
16
+ pingthings search military Find military category packs
17
+ pingthings search explosion Find explosion sounds
18
+ pingthings search coin Find coin/pickup sounds
19
+ `);
20
+ }
21
+
22
+ export default function search(args) {
23
+ const term = args[0];
24
+
25
+ if (!term || term === '--help' || term === '-h') {
26
+ showHelp();
27
+ if (!term) process.exit(1);
28
+ return;
29
+ }
30
+
31
+ const query = term.toLowerCase();
32
+ const config = readConfig();
33
+ const packs = listPacks();
34
+ const results = { packs: [], sounds: [] };
35
+
36
+ for (const pack of packs) {
37
+ // Check pack-level matches
38
+ const packMatch =
39
+ pack.name.toLowerCase().includes(query) ||
40
+ pack.description.toLowerCase().includes(query) ||
41
+ (pack.category || '').toLowerCase().includes(query);
42
+
43
+ if (packMatch) {
44
+ results.packs.push(pack);
45
+ }
46
+
47
+ // Check individual sounds
48
+ const sounds = getPackSounds(pack.name);
49
+ for (const sound of sounds) {
50
+ const name = basename(sound).toLowerCase();
51
+ if (name.includes(query)) {
52
+ results.sounds.push({ pack: pack.name, sound: basename(sound), path: sound });
53
+ }
54
+ }
55
+ }
56
+
57
+ if (results.packs.length === 0 && results.sounds.length === 0) {
58
+ console.log(`No results for "${term}".`);
59
+ return;
60
+ }
61
+
62
+ if (results.packs.length > 0) {
63
+ console.log(`\nPacks matching "${term}":\n`);
64
+ for (const pack of results.packs) {
65
+ const active = pack.name === config.activePack ? ' *' : ' ';
66
+ console.log(`${active} ${pack.name} (${pack.category}, ${pack.soundCount} sounds)`);
67
+ if (pack.description) {
68
+ console.log(` ${pack.description}`);
69
+ }
70
+ }
71
+ }
72
+
73
+ if (results.sounds.length > 0) {
74
+ console.log(`\nSounds matching "${term}":\n`);
75
+ for (const s of results.sounds) {
76
+ console.log(` ${s.pack} / ${s.sound}`);
77
+ }
78
+ }
79
+
80
+ console.log('');
81
+ }
@@ -0,0 +1,76 @@
1
+ import { readConfig } from '../config.js';
2
+ import { getPackSounds, resolvePack, getPackEvents, getEventSounds } from '../packs.js';
3
+ import { basename } from 'node:path';
4
+
5
+ function showHelp() {
6
+ console.log(`
7
+ Usage: pingthings sounds [pack]
8
+
9
+ List all individual sounds in a pack.
10
+
11
+ Arguments:
12
+ pack Pack to list sounds from (defaults to active pack)
13
+
14
+ Options:
15
+ --events Show sounds grouped by event mapping
16
+
17
+ Examples:
18
+ pingthings sounds List sounds in active pack
19
+ pingthings sounds openarena-announcer List sounds in a specific pack
20
+ pingthings sounds --events Show event mappings
21
+ `);
22
+ }
23
+
24
+ export default function sounds(args) {
25
+ if (args.includes('--help') || args.includes('-h')) {
26
+ showHelp();
27
+ return;
28
+ }
29
+
30
+ const showEvents = args.includes('--events');
31
+ const packName = args.find(a => !a.startsWith('-')) || readConfig().activePack;
32
+
33
+ const pack = resolvePack(packName);
34
+ if (!pack) {
35
+ console.error(`Pack not found: ${packName}`);
36
+ console.error('Run "pingthings list" to see available packs.');
37
+ process.exit(1);
38
+ }
39
+
40
+ const allSounds = getPackSounds(packName);
41
+
42
+ if (showEvents) {
43
+ const events = getPackEvents(packName);
44
+ console.log(`\n${packName} — sounds by event:\n`);
45
+
46
+ for (const event of events) {
47
+ const eventSounds = getEventSounds(packName, event);
48
+ console.log(` ${event}:`);
49
+ for (const s of eventSounds) {
50
+ console.log(` ${basename(s)}`);
51
+ }
52
+ }
53
+
54
+ // Show unmapped sounds
55
+ const mappedPaths = new Set();
56
+ for (const event of events) {
57
+ for (const s of getEventSounds(packName, event)) {
58
+ mappedPaths.add(s);
59
+ }
60
+ }
61
+ const unmapped = allSounds.filter(s => !mappedPaths.has(s));
62
+ if (unmapped.length > 0) {
63
+ console.log(' (unmapped):');
64
+ for (const s of unmapped) {
65
+ console.log(` ${basename(s)}`);
66
+ }
67
+ }
68
+ } else {
69
+ console.log(`\n${packName} — ${allSounds.length} sounds:\n`);
70
+ for (const s of allSounds) {
71
+ console.log(` ${basename(s)}`);
72
+ }
73
+ }
74
+
75
+ console.log('');
76
+ }
package/src/cli/theme.js CHANGED
@@ -57,11 +57,44 @@ const THEMES = {
57
57
  blocked: '0ad-civilizations',
58
58
  },
59
59
  },
60
+ 'professional': {
61
+ description: 'Clean and minimal — Kenney UI sounds for everything',
62
+ activePack: 'kenney-interface',
63
+ eventPacks: {
64
+ done: 'kenney-interface',
65
+ permission: 'kenney-interface',
66
+ complete: 'kenney-interface',
67
+ error: 'kenney-interface',
68
+ blocked: 'kenney-interface',
69
+ },
70
+ },
71
+ '8bit': {
72
+ description: 'Pure retro — 8-bit chiptune for everything',
73
+ activePack: 'retro-8bit',
74
+ eventPacks: {
75
+ done: 'retro-8bit',
76
+ permission: 'retro-8bit',
77
+ complete: 'retro-8bit',
78
+ error: 'retro-8bit',
79
+ blocked: 'retro-8bit',
80
+ },
81
+ },
82
+ 'space': {
83
+ description: 'Space station — Warzone 2100 + Kenney sci-fi',
84
+ activePack: 'kenney-scifi',
85
+ eventPacks: {
86
+ done: 'kenney-scifi',
87
+ permission: 'warzone2100-command',
88
+ complete: 'warzone2100-command',
89
+ error: 'kenney-scifi',
90
+ blocked: 'kenney-scifi',
91
+ },
92
+ },
60
93
  'chaos': {
61
94
  description: 'Random pack for every event — maximum variety',
62
95
  activePack: '7kaa-soldiers',
63
96
  eventPacks: {
64
- done: '7kaa-soldiers',
97
+ done: 'retro-8bit',
65
98
  permission: 'openarena-announcer',
66
99
  complete: 'warzone2100-command',
67
100
  error: 'freedoom-arsenal',
package/src/packs.js CHANGED
@@ -57,6 +57,7 @@ function scanDirectory(dir, isBuiltIn) {
57
57
  description: manifest?.description || '',
58
58
  license: manifest?.license || 'Unknown',
59
59
  credits: manifest?.credits || '',
60
+ category: manifest?.category || 'other',
60
61
  location: packDir,
61
62
  soundCount: sounds.length,
62
63
  isBuiltIn,