Add Nudge setup, removal and README
This commit is contained in:
@@ -0,0 +1,108 @@
|
||||
# Nudge setup. Run it with Setup.bat.
|
||||
# Adds a Claude Code hook that sends a phone notification through ntfy.sh
|
||||
# whenever Claude Code stops to ask you something.
|
||||
param(
|
||||
[string]$SettingsPath = (Join-Path $env:USERPROFILE '.claude\settings.json'),
|
||||
[string]$KitFolder = $PSScriptRoot,
|
||||
[switch]$NoTest
|
||||
)
|
||||
$ErrorActionPreference = 'Stop'
|
||||
|
||||
function New-Topic {
|
||||
$chars = 'abcdefghijklmnopqrstuvwxyz0123456789'
|
||||
$bytes = New-Object byte[] 16
|
||||
$rng = [System.Security.Cryptography.RandomNumberGenerator]::Create()
|
||||
$rng.GetBytes($bytes)
|
||||
$rng.Dispose()
|
||||
$s = ''
|
||||
foreach ($b in $bytes) { $s += $chars[$b % $chars.Length] }
|
||||
return 'nudge-' + $s
|
||||
}
|
||||
|
||||
$marker = 'ntfy.sh/'
|
||||
$dir = Split-Path -Parent $SettingsPath
|
||||
if (-not (Test-Path -LiteralPath $dir)) { New-Item -ItemType Directory -Path $dir -Force | Out-Null }
|
||||
$topicFile = Join-Path $dir 'nudge-topic.txt'
|
||||
|
||||
# Keep the same topic if Setup is run twice.
|
||||
if (Test-Path -LiteralPath $topicFile) {
|
||||
$topic = (Get-Content -LiteralPath $topicFile -Raw).Trim()
|
||||
} else {
|
||||
$topic = New-Topic
|
||||
[System.IO.File]::WriteAllText($topicFile, $topic, (New-Object System.Text.UTF8Encoding($false)))
|
||||
}
|
||||
|
||||
$command = 'curl.exe -s -H "Title: Claude Code" -d "Needs your attention" ' + $marker + $topic
|
||||
|
||||
# Read existing settings, or start fresh.
|
||||
$settings = $null
|
||||
if (Test-Path -LiteralPath $SettingsPath) {
|
||||
$raw = Get-Content -LiteralPath $SettingsPath -Raw
|
||||
if ($raw -and $raw.Trim().Length -gt 0) {
|
||||
try { $settings = $raw | ConvertFrom-Json }
|
||||
catch {
|
||||
Write-Host 'Your settings.json could not be read, so Nudge did not touch it.'
|
||||
Write-Host 'Nothing was changed. Fix or move that file and run Setup again.'
|
||||
exit 1
|
||||
}
|
||||
Copy-Item -LiteralPath $SettingsPath -Destination ($SettingsPath + '.nudge-backup') -Force
|
||||
}
|
||||
}
|
||||
if ($null -eq $settings) { $settings = New-Object PSObject }
|
||||
|
||||
if (-not ($settings.PSObject.Properties.Name -contains 'hooks')) {
|
||||
$settings | Add-Member -NotePropertyName 'hooks' -NotePropertyValue (New-Object PSObject)
|
||||
}
|
||||
$hooks = $settings.hooks
|
||||
if (-not ($hooks.PSObject.Properties.Name -contains 'Notification')) {
|
||||
$hooks | Add-Member -NotePropertyName 'Notification' -NotePropertyValue @()
|
||||
}
|
||||
|
||||
# Drop any earlier Nudge entry, keep everything else.
|
||||
$keep = @()
|
||||
foreach ($entry in @($hooks.Notification)) {
|
||||
$isNudge = $false
|
||||
foreach ($h in @($entry.hooks)) {
|
||||
if ($h.command -and $h.command.ToString().Contains($marker + 'nudge-')) { $isNudge = $true }
|
||||
}
|
||||
if (-not $isNudge) { $keep += $entry }
|
||||
}
|
||||
$new = [PSCustomObject]@{
|
||||
matcher = ''
|
||||
hooks = @([PSCustomObject]@{ type = 'command'; command = $command })
|
||||
}
|
||||
$hooks.Notification = @($keep + $new)
|
||||
|
||||
$json = $settings | ConvertTo-Json -Depth 20
|
||||
[System.IO.File]::WriteAllText($SettingsPath, $json, (New-Object System.Text.UTF8Encoding($false)))
|
||||
|
||||
# Make a ready-to-use chat skill with the topic filled in.
|
||||
$template = Join-Path $KitFolder 'chat-skill\SKILL.md'
|
||||
if (Test-Path -LiteralPath $template) {
|
||||
$out = Join-Path $KitFolder 'MY-SKILL.md'
|
||||
$text = (Get-Content -LiteralPath $template -Raw).Replace('YOUR-TOPIC', $topic)
|
||||
[System.IO.File]::WriteAllText($out, $text, (New-Object System.Text.UTF8Encoding($false)))
|
||||
}
|
||||
|
||||
Write-Host ''
|
||||
Write-Host 'Nudge is set up.'
|
||||
Write-Host ''
|
||||
Write-Host 'Your private topic name is:'
|
||||
Write-Host (' ' + $topic)
|
||||
Write-Host 'Keep it to yourself. Anyone who knows it can send messages to your phone.'
|
||||
Write-Host ''
|
||||
Write-Host 'Next, on your phone:'
|
||||
Write-Host ' 1. Install the ntfy app.'
|
||||
Write-Host ' 2. Tap +, type the topic name above, leave "use another server" unchecked,'
|
||||
Write-Host ' and tick "instant delivery in doze mode". Tap Subscribe.'
|
||||
Write-Host ' 3. Allow notifications, and set the ntfy battery option to Unrestricted.'
|
||||
Write-Host ''
|
||||
if (-not $NoTest) {
|
||||
$a = Read-Host 'Subscribed? Press Enter to send a test message (or type N to skip)'
|
||||
if ($a -notmatch '^[Nn]') {
|
||||
& curl.exe -s -H 'Title: Nudge' -d 'It works. This is a test from Nudge.' ($marker + $topic) | Out-Null
|
||||
Write-Host 'Test sent. It should show up on your phone in a moment.'
|
||||
}
|
||||
}
|
||||
Write-Host ''
|
||||
Write-Host 'Restart Claude Code so it loads the hook.'
|
||||
Reference in New Issue
Block a user