claude-code-autoconfig 1.0.197 β 1.0.198
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/.claude/commands/disable-arcade-beeps.md +10 -0
- package/.claude/commands/enable-arcade-beeps.md +10 -0
- package/.claude/docs/autoconfig.docs.html +99 -2
- package/.claude/hooks/arcade-beeps.js +136 -0
- package/.claude/settings.json +8 -0
- package/.claude/sounds/pp3-getready-G4.wav +0 -0
- package/.claude/sounds/pp3-go-F#5.wav +0 -0
- package/CHANGELOG.md +3 -3
- package/README.md +11 -1
- package/bin/cli.js +8 -2
- package/package.json +1 -1
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: Turn OFF Pole Position tab status beeps
|
|
3
|
+
allowed-tools: Bash
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
Run exactly this command, then reply with a single confirmation line and nothing else:
|
|
7
|
+
|
|
8
|
+
```
|
|
9
|
+
rm -f ~/.claude/sounds/arcade-beeps.enabled && echo "arcade beeps DISABLED."
|
|
10
|
+
```
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: Turn ON Pole Position tab status beeps (awaiting = low tone, complete = high tone)
|
|
3
|
+
allowed-tools: Bash
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
Run exactly this command, then reply with a single confirmation line and nothing else:
|
|
7
|
+
|
|
8
|
+
```
|
|
9
|
+
mkdir -p ~/.claude/sounds && touch ~/.claude/sounds/arcade-beeps.enabled && echo "arcade beeps ENABLED (every turn-end beeps: awaiting=low, complete=high). Disable with /disable-arcade-beeps."
|
|
10
|
+
```
|
|
@@ -878,6 +878,16 @@
|
|
|
878
878
|
<span class="tree-file-icon">π</span>
|
|
879
879
|
<span class="file">commit-and-push.md</span>
|
|
880
880
|
</div>
|
|
881
|
+
<div class="tree-item indent-3 hidden" data-info="disable-arcade-beeps" data-parent="commands">
|
|
882
|
+
<span class="tree-spacer"></span>
|
|
883
|
+
<span class="tree-file-icon">π</span>
|
|
884
|
+
<span class="file">disable-arcade-beeps.md</span>
|
|
885
|
+
</div>
|
|
886
|
+
<div class="tree-item indent-3 hidden" data-info="enable-arcade-beeps" data-parent="commands">
|
|
887
|
+
<span class="tree-spacer"></span>
|
|
888
|
+
<span class="tree-file-icon">π</span>
|
|
889
|
+
<span class="file">enable-arcade-beeps.md</span>
|
|
890
|
+
</div>
|
|
881
891
|
<div class="tree-item indent-3 hidden" data-info="extract-rules" data-parent="commands">
|
|
882
892
|
<span class="tree-spacer"></span>
|
|
883
893
|
<span class="tree-file-icon">π</span>
|
|
@@ -933,6 +943,11 @@
|
|
|
933
943
|
<span class="tree-folder-icon">π</span>
|
|
934
944
|
<span class="folder">hooks</span>
|
|
935
945
|
</div>
|
|
946
|
+
<div class="tree-item indent-3 hidden" data-info="arcade-beeps-hook" data-parent="hooks">
|
|
947
|
+
<span class="tree-spacer"></span>
|
|
948
|
+
<span class="tree-file-icon">π</span>
|
|
949
|
+
<span class="file">arcade-beeps.js</span>
|
|
950
|
+
</div>
|
|
936
951
|
<div class="tree-item indent-3 hidden" data-info="feedback-rule-check-hook" data-parent="hooks">
|
|
937
952
|
<span class="tree-spacer"></span>
|
|
938
953
|
<span class="tree-file-icon">π</span>
|
|
@@ -1263,7 +1278,7 @@
|
|
|
1263
1278
|
title: '.claude/ Directory',
|
|
1264
1279
|
desc: 'Commands, rules, settings, and these docs. Keeps configuration organized as your project grows.'
|
|
1265
1280
|
},
|
|
1266
|
-
|
|
1281
|
+
'rules': {
|
|
1267
1282
|
title: 'rules/',
|
|
1268
1283
|
desc: 'Path-scoped context that loads when Claude works on matching files.'
|
|
1269
1284
|
},
|
|
@@ -1298,6 +1313,16 @@
|
|
|
1298
1313
|
desc: 'Runs tests, then stages all changes, generates a conventional commit message, commits, and pushes.<div style="margin-top: 12px;"><strong>Parameters</strong><div style="margin-top: 4px; opacity: 0.6;">None</div></div><div style="margin-top: 12px;"><strong>Responses</strong><table style="margin-top: 6px; border-collapse: collapse; font-size: 0.9em; text-align: left;"><tr style="text-align: left; border-bottom: 1px solid var(--border);"><th style="padding: 4px 8px 4px 0; white-space: nowrap;">Status</th><th style="padding: 4px 8px 4px 0;">Description</th></tr><tr style="border-bottom: 1px solid var(--border);"><td style="padding: 4px 8px 4px 0; vertical-align: top; white-space: nowrap;"><code>success</code></td><td style="padding: 4px 8px 4px 0; vertical-align: top;">Changes committed and pushed to current branch.</td></tr><tr style="border-bottom: 1px solid var(--border);"><td style="padding: 4px 8px 4px 0; vertical-align: top; white-space: nowrap;"><code>test-failure</code></td><td style="padding: 4px 8px 4px 0; vertical-align: top;">Tests failed β no commit made.</td></tr></table></div><div style="margin-top: 12px;"><strong>Side Effects</strong><div style="margin-top: 4px; font-size: 0.9em;">Runs test suite, stages all changes, creates git commit, pushes to remote</div></div><div style="margin-top: 12px;"><strong>Examples</strong><div style="margin-top: 6px; background: var(--bg-elevated); border-radius: 6px; padding: 8px 12px; font-family: monospace; font-size: 0.85em;"><div><code>/commit-and-push</code> <span style="opacity: 0.6;">β Run tests, commit, and push</span></div></div></div>',
|
|
1299
1314
|
trigger: '/commit-and-push'
|
|
1300
1315
|
},
|
|
1316
|
+
'disable-arcade-beeps': {
|
|
1317
|
+
title: 'disable-arcade-beeps.md',
|
|
1318
|
+
desc: 'disable-arcade-beeps.md in commands/<div style="margin-top: 12px;"><strong>Parameters</strong><div style="margin-top: 4px; opacity: 0.6;">None</div></div>',
|
|
1319
|
+
trigger: '/disable-arcade-beeps'
|
|
1320
|
+
},
|
|
1321
|
+
'enable-arcade-beeps': {
|
|
1322
|
+
title: 'enable-arcade-beeps.md',
|
|
1323
|
+
desc: 'enable-arcade-beeps.md in commands/<div style="margin-top: 12px;"><strong>Parameters</strong><div style="margin-top: 4px; opacity: 0.6;">None</div></div>',
|
|
1324
|
+
trigger: '/enable-arcade-beeps'
|
|
1325
|
+
},
|
|
1301
1326
|
'extract-rules': {
|
|
1302
1327
|
title: 'extract-rules.md',
|
|
1303
1328
|
desc: 'Scan Claude artifacts and extract structured rules into .claude/rules/<div style="margin-top: 12px;"><strong>Parameters</strong><table style="margin-top: 6px; border-collapse: collapse; font-size: 0.9em; text-align: left;"><tr style="text-align: left; border-bottom: 1px solid var(--border);"><th style="padding: 4px 8px 4px 0; white-space: nowrap;">Name</th><th style="padding: 4px 8px 4px 0; white-space: nowrap;">Type</th><th style="padding: 4px 8px 4px 0; white-space: nowrap;">Required</th><th style="padding: 4px 8px 4px 0;">Description</th></tr><tr style="border-bottom: 1px solid var(--border);"><td style="padding: 4px 8px 4px 0; vertical-align: top; white-space: nowrap;"><code>select</code></td><td style="padding: 4px 8px 4px 0; vertical-align: top; white-space: nowrap;"><code>string</code></td><td style="padding: 4px 8px 4px 0; vertical-align: top;">optional</td><td style="padding: 4px 8px 4px 0; vertical-align: top;">Write only specific rules by number: "1,3,5". Default: all.</td></tr><tr style="border-bottom: 1px solid var(--border);"><td style="padding: 4px 8px 4px 0; vertical-align: top; white-space: nowrap;"><code>keep-sources</code></td><td style="padding: 4px 8px 4px 0; vertical-align: top; white-space: nowrap;"><code>boolean</code></td><td style="padding: 4px 8px 4px 0; vertical-align: top;">optional</td><td style="padding: 4px 8px 4px 0; vertical-align: top;">Write rules but skip source cleanup (Step 8)</td></tr></table></div><div style="margin-top: 12px;"><strong>Responses</strong><table style="margin-top: 6px; border-collapse: collapse; font-size: 0.9em; text-align: left;"><tr style="text-align: left; border-bottom: 1px solid var(--border);"><th style="padding: 4px 8px 4px 0; white-space: nowrap;">Status</th><th style="padding: 4px 8px 4px 0;">Description</th></tr><tr style="border-bottom: 1px solid var(--border);"><td style="padding: 4px 8px 4px 0; vertical-align: top; white-space: nowrap;"><code>success</code></td><td style="padding: 4px 8px 4px 0; vertical-align: top;">Rules extracted, written, and sources cleaned up.</td></tr><tr style="border-bottom: 1px solid var(--border);"><td style="padding: 4px 8px 4px 0; vertical-align: top; white-space: nowrap;"><code>no-rules</code></td><td style="padding: 4px 8px 4px 0; vertical-align: top;">No extractable rules found in scanned sources.</td></tr></table></div><div style="margin-top: 12px;"><strong>Side Effects</strong><div style="margin-top: 4px; font-size: 0.9em;">Creates .claude/rules/ files and removes extracted content from source files</div></div><div style="margin-top: 12px;"><strong>Examples</strong><div style="margin-top: 6px; background: var(--bg-elevated); border-radius: 6px; padding: 8px 12px; font-family: monospace; font-size: 0.85em;"><div><code>/extract-rules</code> <span style="opacity: 0.6;">β Scan, propose, prompt for approval, write, and clean up</span></div><div><code>/extract-rules --keep-sources</code> <span style="opacity: 0.6;">β Write rules without modifying source files</span></div><div><code>/extract-rules --select 1,3</code> <span style="opacity: 0.6;">β Write only rules #1 and #3</span></div></div></div>',
|
|
@@ -1333,6 +1358,11 @@
|
|
|
1333
1358
|
desc: 'Placeholder β drop your project\'s custom subagent definitions in this directory.',
|
|
1334
1359
|
trigger: 'Background agent'
|
|
1335
1360
|
},
|
|
1361
|
+
'arcade-beeps-hook': {
|
|
1362
|
+
title: 'arcade-beeps.js',
|
|
1363
|
+
desc: 'arcade-beeps.js in hooks/',
|
|
1364
|
+
trigger: 'PostToolUse hook'
|
|
1365
|
+
},
|
|
1336
1366
|
'feedback-rule-check-hook': {
|
|
1337
1367
|
title: 'feedback-rule-check.js',
|
|
1338
1368
|
desc: 'After FEEDBACK.md is edited, notifies Claude to evaluate',
|
|
@@ -1569,7 +1599,7 @@ CRITICAL: A plausible-looking cause from code reading is NOT confirmed evidence.
|
|
|
1569
1599
|
|
|
1570
1600
|
> Run \`/autoconfig\` to populate this based on your project.`
|
|
1571
1601
|
},
|
|
1572
|
-
|
|
1602
|
+
'autoconfig-update': {
|
|
1573
1603
|
filename: 'autoconfig-update.md',
|
|
1574
1604
|
content: `<!-- @applied
|
|
1575
1605
|
-->
|
|
@@ -1656,6 +1686,32 @@ Use conventional commits: \`type(scope): description\`
|
|
|
1656
1686
|
Types: feat, fix, docs, style, refactor, test, chore
|
|
1657
1687
|
|
|
1658
1688
|
Keep the subject line under 50 chars. Add body if the change needs explanation.`
|
|
1689
|
+
},
|
|
1690
|
+
'disable-arcade-beeps': {
|
|
1691
|
+
filename: 'disable-arcade-beeps.md',
|
|
1692
|
+
content: `---
|
|
1693
|
+
description: Turn OFF Pole Position tab status beeps
|
|
1694
|
+
allowed-tools: Bash
|
|
1695
|
+
---
|
|
1696
|
+
|
|
1697
|
+
Run exactly this command, then reply with a single confirmation line and nothing else:
|
|
1698
|
+
|
|
1699
|
+
\`\`\`
|
|
1700
|
+
rm -f ~/.claude/sounds/arcade-beeps.enabled && echo "arcade beeps DISABLED."
|
|
1701
|
+
\`\`\``
|
|
1702
|
+
},
|
|
1703
|
+
'enable-arcade-beeps': {
|
|
1704
|
+
filename: 'enable-arcade-beeps.md',
|
|
1705
|
+
content: `---
|
|
1706
|
+
description: Turn ON Pole Position tab status beeps (awaiting = low tone, complete = high tone)
|
|
1707
|
+
allowed-tools: Bash
|
|
1708
|
+
---
|
|
1709
|
+
|
|
1710
|
+
Run exactly this command, then reply with a single confirmation line and nothing else:
|
|
1711
|
+
|
|
1712
|
+
\`\`\`
|
|
1713
|
+
mkdir -p ~/.claude/sounds && touch ~/.claude/sounds/arcade-beeps.enabled && echo "arcade beeps ENABLED (every turn-end beeps: awaiting=low, complete=high). Disable with /disable-arcade-beeps."
|
|
1714
|
+
\`\`\``
|
|
1659
1715
|
},
|
|
1660
1716
|
'extract-rules': {
|
|
1661
1717
|
filename: 'extract-rules.md',
|
|
@@ -1837,6 +1893,39 @@ claude-code-autoconfig ships this folder empty so you can populate it with agent
|
|
|
1837
1893
|
|
|
1838
1894
|
See Anthropic's subagents docs for the file format:
|
|
1839
1895
|
https://docs.anthropic.com/en/docs/claude-code/sub-agents`
|
|
1896
|
+
},
|
|
1897
|
+
'arcade-beeps-hook': {
|
|
1898
|
+
filename: 'arcade-beeps.js',
|
|
1899
|
+
content: `#!/usr/bin/env node
|
|
1900
|
+
/**
|
|
1901
|
+
* arcade-beeps β optional Pole-Position status cues for the Claude Code tab.
|
|
1902
|
+
* Companion to terminal-title.js. Registered (settings.json) on Stop + Notification.
|
|
1903
|
+
*
|
|
1904
|
+
* OFF unless the enable flag exists: ~/.claude/sounds/arcade-beeps.enabled
|
|
1905
|
+
* toggle via /enable-arcade-beeps /disable-arcade-beeps
|
|
1906
|
+
* The flag is GLOBAL (homedir), so one toggle covers every project you've installed into.
|
|
1907
|
+
*
|
|
1908
|
+
* Mapping (matches the β/β» tab glyph that terminal-title.js paints on the SAME event):
|
|
1909
|
+
* Stop, turn ended on a question -> β awaiting -> get-ready tick (pp3-getready-G4.wav, G4/384Hz)
|
|
1910
|
+
* Stop, turn ended normally -> β» complete -> GO beep (pp3-go-F#5.wav, F#5/759Hz)
|
|
1911
|
+
* Notification (permission_prompt) -> β awaiting -> get-ready tick
|
|
1912
|
+
*
|
|
1913
|
+
* Tones are an extracted+smoothed take on the Pole Position race-start cue (arcade-ping
|
|
1914
|
+
* envelope). LOWER tick = awaiting, HIGHER GO = complete.
|
|
1915
|
+
*
|
|
1916
|
+
* Assets resolve relative to THIS file (../sounds) so a per-project CCA install finds its own
|
|
1917
|
+
* copy at <project>/.claude/sounds β no dependency on a global sounds dir.
|
|
1918
|
+
*
|
|
1919
|
+
* Playback is cross-platform and best-effort: PowerShell SoundPlayer on Windows, afplay on
|
|
1920
|
+
* macOS, paplay||aplay on Linux. If none is present the hook simply stays silent β never errors.
|
|
1921
|
+
*
|
|
1922
|
+
* Playback BLOCKS (spawnSync) so the sound finishes inside the hook's lifetime β a detached
|
|
1923
|
+
* fire-and-forget child can be killed by the hook runner's job/process-group cleanup before it
|
|
1924
|
+
* plays. Blocking costs ~0.5s on turn-end but is reliable. Still fail-safe: wrapped so it never
|
|
1925
|
+
* throws into the turn, and every path ends in exit(0).
|
|
1926
|
+
*
|
|
1927
|
+
* State detection reuses terminal-title.js's exported inspectLastResponse (lazy-required only
|
|
1928
|
+
* when enabled) so sound and glyph agree. A tiny inline '?' check is the fallback.`
|
|
1840
1929
|
},
|
|
1841
1930
|
'feedback-rule-check-hook': {
|
|
1842
1931
|
filename: 'feedback-rule-check.js',
|
|
@@ -2082,6 +2171,10 @@ Claude reads this file but must never write to it. When Claude discovers project
|
|
|
2082
2171
|
{
|
|
2083
2172
|
"type": "command",
|
|
2084
2173
|
"command": "node .claude/hooks/terminal-title.js"
|
|
2174
|
+
},
|
|
2175
|
+
{
|
|
2176
|
+
"type": "command",
|
|
2177
|
+
"command": "node .claude/hooks/arcade-beeps.js"
|
|
2085
2178
|
}
|
|
2086
2179
|
]
|
|
2087
2180
|
}
|
|
@@ -2093,6 +2186,10 @@ Claude reads this file but must never write to it. When Claude discovers project
|
|
|
2093
2186
|
{
|
|
2094
2187
|
"type": "command",
|
|
2095
2188
|
"command": "node .claude/hooks/terminal-title.js"
|
|
2189
|
+
},
|
|
2190
|
+
{
|
|
2191
|
+
"type": "command",
|
|
2192
|
+
"command": "node .claude/hooks/arcade-beeps.js"
|
|
2096
2193
|
}
|
|
2097
2194
|
]
|
|
2098
2195
|
}
|
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* arcade-beeps β optional Pole-Position status cues for the Claude Code tab.
|
|
4
|
+
* Companion to terminal-title.js. Registered (settings.json) on Stop + Notification.
|
|
5
|
+
*
|
|
6
|
+
* OFF unless the enable flag exists: ~/.claude/sounds/arcade-beeps.enabled
|
|
7
|
+
* toggle via /enable-arcade-beeps /disable-arcade-beeps
|
|
8
|
+
* The flag is GLOBAL (homedir), so one toggle covers every project you've installed into.
|
|
9
|
+
*
|
|
10
|
+
* Mapping (matches the β/β» tab glyph that terminal-title.js paints on the SAME event):
|
|
11
|
+
* Stop, turn ended on a question -> β awaiting -> get-ready tick (pp3-getready-G4.wav, G4/384Hz)
|
|
12
|
+
* Stop, turn ended normally -> β» complete -> GO beep (pp3-go-F#5.wav, F#5/759Hz)
|
|
13
|
+
* Notification (permission_prompt) -> β awaiting -> get-ready tick
|
|
14
|
+
*
|
|
15
|
+
* Tones are an extracted+smoothed take on the Pole Position race-start cue (arcade-ping
|
|
16
|
+
* envelope). LOWER tick = awaiting, HIGHER GO = complete.
|
|
17
|
+
*
|
|
18
|
+
* Assets resolve relative to THIS file (../sounds) so a per-project CCA install finds its own
|
|
19
|
+
* copy at <project>/.claude/sounds β no dependency on a global sounds dir.
|
|
20
|
+
*
|
|
21
|
+
* Playback is cross-platform and best-effort: PowerShell SoundPlayer on Windows, afplay on
|
|
22
|
+
* macOS, paplay||aplay on Linux. If none is present the hook simply stays silent β never errors.
|
|
23
|
+
*
|
|
24
|
+
* Playback BLOCKS (spawnSync) so the sound finishes inside the hook's lifetime β a detached
|
|
25
|
+
* fire-and-forget child can be killed by the hook runner's job/process-group cleanup before it
|
|
26
|
+
* plays. Blocking costs ~0.5s on turn-end but is reliable. Still fail-safe: wrapped so it never
|
|
27
|
+
* throws into the turn, and every path ends in exit(0).
|
|
28
|
+
*
|
|
29
|
+
* State detection reuses terminal-title.js's exported inspectLastResponse (lazy-required only
|
|
30
|
+
* when enabled) so sound and glyph agree. A tiny inline '?' check is the fallback.
|
|
31
|
+
*
|
|
32
|
+
* Diagnostic log (bounded ~64KB) at ~/.claude/hooks/.titles/arcade-beeps.log records every
|
|
33
|
+
* invocation + choice, so we can prove whether the hook fires on a real Stop.
|
|
34
|
+
*/
|
|
35
|
+
const fs = require('fs');
|
|
36
|
+
const os = require('os');
|
|
37
|
+
const path = require('path');
|
|
38
|
+
const { spawnSync } = require('child_process');
|
|
39
|
+
|
|
40
|
+
const ASSET_DIR = path.join(__dirname, '..', 'sounds'); // wavs ship beside the hook
|
|
41
|
+
const FLAG = path.join(os.homedir(), '.claude', 'sounds', 'arcade-beeps.enabled'); // global toggle
|
|
42
|
+
const LOG = path.join(os.homedir(), '.claude', 'hooks', '.titles', 'arcade-beeps.log');
|
|
43
|
+
const DEBUG = process.env.ARCADE_BEEPS_DEBUG === '1';
|
|
44
|
+
|
|
45
|
+
function logLine(msg) {
|
|
46
|
+
try {
|
|
47
|
+
try { if (fs.statSync(LOG).size > 64 * 1024) fs.renameSync(LOG, `${LOG}.1`); } catch (_) { /* none yet */ }
|
|
48
|
+
fs.appendFileSync(LOG, `${new Date().toISOString()} ${msg}\n`);
|
|
49
|
+
} catch (_) { /* logging must never throw */ }
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
function enabled() { try { return fs.existsSync(FLAG); } catch (_) { return false; } }
|
|
53
|
+
function delay(ms) { return new Promise(r => setTimeout(r, ms)); }
|
|
54
|
+
|
|
55
|
+
// Pick a blocking audio player for the current OS. Returns [cmd, args].
|
|
56
|
+
function playerFor(wav) {
|
|
57
|
+
if (process.platform === 'win32') {
|
|
58
|
+
return ['powershell', ['-NoProfile', '-Command', `(New-Object Media.SoundPlayer '${wav}').PlaySync()`]];
|
|
59
|
+
}
|
|
60
|
+
if (process.platform === 'darwin') {
|
|
61
|
+
return ['afplay', [wav]];
|
|
62
|
+
}
|
|
63
|
+
// linux / other: prefer paplay (PulseAudio/PipeWire), fall back to aplay (ALSA)
|
|
64
|
+
return ['sh', ['-c', `paplay "${wav}" 2>/dev/null || aplay "${wav}" 2>/dev/null`]];
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
function play(wavName, why) {
|
|
68
|
+
if (DEBUG) process.stderr.write(`arcade-beeps: chose ${wavName} (${why})\n`);
|
|
69
|
+
logLine(`play ${wavName} (${why})`);
|
|
70
|
+
try {
|
|
71
|
+
const wav = path.join(ASSET_DIR, wavName);
|
|
72
|
+
if (!fs.existsSync(wav)) { logLine(`MISSING ${wav}`); return; }
|
|
73
|
+
// Block until the sound finishes so it can't be reaped with the hook process.
|
|
74
|
+
const [cmd, cmdArgs] = playerFor(wav);
|
|
75
|
+
spawnSync(cmd, cmdArgs, { stdio: 'ignore', windowsHide: true });
|
|
76
|
+
} catch (e) { logLine(`play-error ${e && e.message}`); }
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
// Fallback: does the last visible assistant text end on a question? (Mirrors terminal-title.js's regex.)
|
|
80
|
+
function endsOnQuestionInline(transcriptPath) {
|
|
81
|
+
try {
|
|
82
|
+
const lines = fs.readFileSync(transcriptPath, 'utf8').split('\n');
|
|
83
|
+
for (let i = lines.length - 1; i >= 0; i--) {
|
|
84
|
+
const l = lines[i].trim(); if (!l) continue;
|
|
85
|
+
let o; try { o = JSON.parse(l); } catch (_) { continue; }
|
|
86
|
+
if (!o || o.type !== 'assistant' || !o.message) continue;
|
|
87
|
+
const c = o.message.content; let t = '';
|
|
88
|
+
if (typeof c === 'string') t = c;
|
|
89
|
+
else if (Array.isArray(c)) t = c.filter(b => b && b.type === 'text' && typeof b.text === 'string').map(b => b.text).join('\n');
|
|
90
|
+
if (t.trim()) return /\?[\s)*_"]*(\([^()]*\)[\s.*_"]*)?$/.test(t);
|
|
91
|
+
}
|
|
92
|
+
} catch (_) { /* ignore */ }
|
|
93
|
+
return false;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
async function main(input) {
|
|
97
|
+
let data = {};
|
|
98
|
+
try { data = JSON.parse(input); } catch (_) { /* ignore */ }
|
|
99
|
+
const event = data.hook_event_name || '?';
|
|
100
|
+
const en = enabled();
|
|
101
|
+
logLine(`invoked event=${event} enabled=${en ? 1 : 0}`);
|
|
102
|
+
if (!en) return; // opt-in only
|
|
103
|
+
|
|
104
|
+
if (event === 'Notification') { play('pp3-getready-G4.wav', 'notification'); return; }
|
|
105
|
+
if (event !== 'Stop') return;
|
|
106
|
+
|
|
107
|
+
// awaiting (question) vs complete β same signals terminal-title.js uses, so the tone matches the glyph.
|
|
108
|
+
const sid = data.session_id || '';
|
|
109
|
+
const askFile = path.join(os.homedir(), '.claude', 'hooks', '.titles', `${sid}.ask`);
|
|
110
|
+
let pending = false;
|
|
111
|
+
try { pending = fs.existsSync(askFile); } catch (_) { /* ignore */ }
|
|
112
|
+
|
|
113
|
+
if (!pending) {
|
|
114
|
+
let inspect = null;
|
|
115
|
+
try { ({ inspectLastResponse: inspect } = require('./terminal-title.js')); } catch (_) { /* fallback below */ }
|
|
116
|
+
if (inspect) {
|
|
117
|
+
let q = inspect(data.transcript_path);
|
|
118
|
+
let n = 0;
|
|
119
|
+
while (!q.ends && (q.suspectRace || !q.found) && n < 5) { await delay(120); q = inspect(data.transcript_path); n++; }
|
|
120
|
+
pending = q.ends;
|
|
121
|
+
} else {
|
|
122
|
+
pending = endsOnQuestionInline(data.transcript_path);
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
play(pending ? 'pp3-getready-G4.wav' : 'pp3-go-F#5.wav', pending ? 'awaiting' : 'complete');
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
if (require.main === module) {
|
|
130
|
+
let input = '';
|
|
131
|
+
process.stdin.setEncoding('utf8');
|
|
132
|
+
process.stdin.on('data', c => (input += c));
|
|
133
|
+
process.stdin.on('end', async () => { try { await main(input); } catch (_) { /* ignore */ } process.exit(0); });
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
module.exports = { endsOnQuestionInline };
|
package/.claude/settings.json
CHANGED
|
@@ -42,6 +42,10 @@
|
|
|
42
42
|
{
|
|
43
43
|
"type": "command",
|
|
44
44
|
"command": "node .claude/hooks/terminal-title.js"
|
|
45
|
+
},
|
|
46
|
+
{
|
|
47
|
+
"type": "command",
|
|
48
|
+
"command": "node .claude/hooks/arcade-beeps.js"
|
|
45
49
|
}
|
|
46
50
|
]
|
|
47
51
|
}
|
|
@@ -53,6 +57,10 @@
|
|
|
53
57
|
{
|
|
54
58
|
"type": "command",
|
|
55
59
|
"command": "node .claude/hooks/terminal-title.js"
|
|
60
|
+
},
|
|
61
|
+
{
|
|
62
|
+
"type": "command",
|
|
63
|
+
"command": "node .claude/hooks/arcade-beeps.js"
|
|
56
64
|
}
|
|
57
65
|
]
|
|
58
66
|
}
|
|
Binary file
|
|
Binary file
|
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,8 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## v1.0.198
|
|
4
|
+
- feat(arcade-beeps): ship opt-in Pole Position status beeps via CCA
|
|
5
|
+
|
|
3
6
|
## v1.0.197
|
|
4
7
|
- perf(terminal-title): deliver the directive once per session; dedupe user/project hooks
|
|
5
8
|
|
|
@@ -145,6 +148,3 @@
|
|
|
145
148
|
## v1.0.149
|
|
146
149
|
- style: consolidate inside-Claude message to two lines
|
|
147
150
|
|
|
148
|
-
## v1.0.148
|
|
149
|
-
- fix: refine inside-Claude error wording
|
|
150
|
-
|
package/README.md
CHANGED
|
@@ -61,7 +61,8 @@ your-project/
|
|
|
61
61
|
βββ hooks/ # Hook scripts
|
|
62
62
|
β βββ format.js # Auto-format on Write/Edit
|
|
63
63
|
β βββ terminal-title.js # Use-case terminal tab titles + live state
|
|
64
|
-
β
|
|
64
|
+
β βββ terminal-title.directive.md # Injected title directive (tunable wording)
|
|
65
|
+
β βββ arcade-beeps.js # Optional Pole Position status beeps (opt-in)
|
|
65
66
|
βββ docs/ # Interactive documentation
|
|
66
67
|
β βββ autoconfig.docs.html # Open with /show-docs
|
|
67
68
|
βββ updates/ # Pending config updates
|
|
@@ -70,6 +71,9 @@ your-project/
|
|
|
70
71
|
β βββ readme-sync.md # Sync README & docs before publish
|
|
71
72
|
βββ scripts/ # Utility scripts
|
|
72
73
|
β βββ sync-docs.js # Regenerate interactive HTML docs
|
|
74
|
+
βββ sounds/ # Status-cue audio for arcade-beeps
|
|
75
|
+
β βββ pp3-getready-G4.wav # Awaiting tone (get-ready tick)
|
|
76
|
+
β βββ pp3-go-F#5.wav # Complete tone (GO beep)
|
|
73
77
|
βββ .mcp.json # MCP server configs (empty placeholder)
|
|
74
78
|
βββ settings.json # Permissions & security
|
|
75
79
|
```
|
|
@@ -110,6 +114,8 @@ Autoconfig is **self-configuring**. Run `/autoconfig` and Claude:
|
|
|
110
114
|
| `/gls` | Views latest screenshot for visual context |
|
|
111
115
|
| `/validate-cca-install` | Validates installation against latest published version |
|
|
112
116
|
| `/extract-rules` | Scan Claude artifacts and extract structured rules |
|
|
117
|
+
| `/enable-arcade-beeps` | Turn on opt-in Pole Position status beeps |
|
|
118
|
+
| `/disable-arcade-beeps` | Turn off the status beeps |
|
|
113
119
|
|
|
114
120
|
### Updates
|
|
115
121
|
|
|
@@ -135,6 +141,10 @@ Autoconfig writes a debug methodology to Claude's persistent memory (`MEMORY.md`
|
|
|
135
141
|
|
|
136
142
|
Run several Claude Code sessions at once and the tabs all look alike. Autoconfig retitles each tab as `{scope} β {what you're working on}` with a live state indicator β ⬀ working, β waiting on you, β» idle β so you can tell sessions apart at a glance. Claude updates the title itself as the work shifts; nothing to configure.
|
|
137
143
|
|
|
144
|
+
### Status Beeps (opt-in)
|
|
145
|
+
|
|
146
|
+
Prefer your ears to your eyes? Run `/enable-arcade-beeps` for Pole Positionβstyle tab cues that mirror the title glyph: a low get-ready tick when a session is **waiting on you** and a higher GO tone when it **finishes**. Cross-platform (Windows / macOS / Linux) and off by default β toggle back off any time with `/disable-arcade-beeps`.
|
|
147
|
+
|
|
138
148
|
### Team Feedback
|
|
139
149
|
|
|
140
150
|
When Claude makes a mistake, add an entry to `.claude/feedback/FEEDBACK.md`:
|
package/bin/cli.js
CHANGED
|
@@ -27,7 +27,7 @@ const WINDOWS_RESERVED = ['CON', 'PRN', 'AUX', 'NUL', 'COM1', 'COM2', 'COM3', 'C
|
|
|
27
27
|
'LPT6', 'LPT7', 'LPT8', 'LPT9'];
|
|
28
28
|
|
|
29
29
|
// Files/folders installed by autoconfig - don't backup these
|
|
30
|
-
const AUTOCONFIG_FILES = ['commands', 'docs', 'agents', 'migration', 'hooks', 'scripts', 'rules', 'feedback', 'settings.json', 'settings.local.json', '.mcp.json', '.autoconfig-version', '.autoconfig-plugins.json'];
|
|
30
|
+
const AUTOCONFIG_FILES = ['commands', 'docs', 'agents', 'migration', 'hooks', 'scripts', 'sounds', 'rules', 'feedback', 'settings.json', 'settings.local.json', '.mcp.json', '.autoconfig-version', '.autoconfig-plugins.json'];
|
|
31
31
|
|
|
32
32
|
function isReservedName(name) {
|
|
33
33
|
const baseName = name.replace(/\.[^.]*$/, '').toUpperCase();
|
|
@@ -775,7 +775,7 @@ if (fs.existsSync(feedbackSrc)) {
|
|
|
775
775
|
// (copyDirIfMissing), BUT the cca-managed title-hook files are ALWAYS refreshed so bug-fixes
|
|
776
776
|
// reach existing installs β without this, copyDirIfMissing leaves stale hooks in place forever
|
|
777
777
|
// (same always-overwrite rationale as scripts/ below). --force already overwrites everything.
|
|
778
|
-
const MANAGED_HOOKS = ['terminal-title.js', 'terminal-title.directive.md'];
|
|
778
|
+
const MANAGED_HOOKS = ['terminal-title.js', 'terminal-title.directive.md', 'arcade-beeps.js'];
|
|
779
779
|
if (fs.existsSync(hooksSrc)) {
|
|
780
780
|
const copyFn = forceMode ? copyDir : copyDirIfMissing;
|
|
781
781
|
copyFn(hooksSrc, path.join(claudeDest, 'hooks'));
|
|
@@ -793,6 +793,12 @@ if (fs.existsSync(scriptsSrc)) {
|
|
|
793
793
|
copyDir(scriptsSrc, path.join(claudeDest, 'scripts'));
|
|
794
794
|
}
|
|
795
795
|
|
|
796
|
+
// Copy sounds directory (binary status-cue assets for arcade-beeps; always overwrite)
|
|
797
|
+
const soundsSrc = path.join(packageDir, '.claude', 'sounds');
|
|
798
|
+
if (fs.existsSync(soundsSrc)) {
|
|
799
|
+
copyDir(soundsSrc, path.join(claudeDest, 'sounds'));
|
|
800
|
+
}
|
|
801
|
+
|
|
796
802
|
// Note: updates directory is no longer copied to user projects.
|
|
797
803
|
// Update files are only used by --pull-updates (for /autoconfig-update).
|
|
798
804
|
// On fresh install, all updates are pre-marked as applied and the content
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "claude-code-autoconfig",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.198",
|
|
4
4
|
"description": "Intelligent, self-configuring setup for Claude Code. One command analyzes your project, configures Claude, and shows you what it did.",
|
|
5
5
|
"author": "ADAC 1001 <info@adac1001.com>",
|
|
6
6
|
"license": "MIT",
|