Files
AIChatExporter/scheduling/Register-AiChatSyncTask.ps1
T
JesseMarkowitzandClaude Opus 5.5 805689c649 fix: give the Windows scheduled task the same FAILED-push backstop
The task now runs scheduling\run-sync.ps1 instead of an inline cmd.exe
loop: every provider is attempted, a run that dies without the app's
own report pushes a high-priority FAILED with the exception class only,
and each run's output is appended to cache\logs\scheduled-sync.log
because Task Scheduler keeps none. Verified under PowerShell 7.6 on
Linux with a stand-in cmd.exe; not yet run under Windows PowerShell 5.1
or Task Scheduler.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019rwKTmug58sEsJ72AuWsEi
2026-10-07 06:05:20 -04:00

95 lines
3.7 KiB
PowerShell

<#
.SYNOPSIS
Register a Windows scheduled task that runs `ai-chat-exporter sync` daily.
.DESCRIPTION
The Windows counterpart to install-systemd-timer.sh. Creates a per-user task
(no admin rights needed) that runs the exporter from this repository, with
the working directory set to the repo so .env, cache\ and exports\ resolve
exactly as they do for an interactive run.
-Provider is repeatable. The CLI takes one provider per run, so each becomes
its own action, executed in order. List only the providers that work
unattended on this machine: a web provider whose session token has expired
fails the task every day, which trains you to ignore the failures you
actually want to notice.
.EXAMPLE
.\scheduling\Register-AiChatSyncTask.ps1 -Provider chatgpt,claude
.EXAMPLE
.\scheduling\Register-AiChatSyncTask.ps1 -Provider all -Time 21:30
.EXAMPLE
.\scheduling\Register-AiChatSyncTask.ps1 -Unregister
#>
[CmdletBinding()]
param(
[string[]]$Provider = @('all'),
[string]$Time = '09:00',
[string]$TaskName = 'AiChatExporterSync',
[switch]$Unregister
)
$ErrorActionPreference = 'Stop'
$repo = Split-Path -Parent $PSScriptRoot
$launcher = Join-Path $repo 'ai-chat-exporter.cmd'
$wrapper = Join-Path $PSScriptRoot 'run-sync.ps1'
if ($Unregister) {
Unregister-ScheduledTask -TaskName $TaskName -Confirm:$false -ErrorAction SilentlyContinue
Write-Host "Removed scheduled task '$TaskName'."
return
}
foreach ($f in $launcher, $wrapper) {
if (-not (Test-Path $f)) { throw "Not found: $f" }
}
# One action running run-sync.ps1, rather than one action per provider: Task
# Scheduler runs multiple actions in order but reports only the last one's
# result, so a failure in an earlier provider would be invisible. The script
# keeps going after a failure, exits non-zero if any provider failed, and pushes
# a FAILED notification for any run that died without sending its own.
#
# Providers go as separate arguments: under -File, "chatgpt,claude" would arrive
# as one string. -WindowStyle Hidden because the output now goes to
# cache\logs\scheduled-sync.log, so the console window would only ever be blank.
$taskArgs = "-NoProfile -NonInteractive -ExecutionPolicy Bypass -WindowStyle Hidden " +
"-File `"$wrapper`" $($Provider -join ' ')"
$actions = New-ScheduledTaskAction -Execute 'powershell.exe' `
-Argument $taskArgs `
-WorkingDirectory $repo
$trigger = New-ScheduledTaskTrigger -Daily -At $Time
# StartWhenAvailable is the counterpart of systemd's Persistent=true: a machine
# that was asleep at the scheduled time runs the archive when it wakes, rather
# than skipping the day entirely.
$settings = New-ScheduledTaskSettingsSet `
-StartWhenAvailable `
-DontStopIfGoingOnBatteries `
-AllowStartIfOnBatteries `
-ExecutionTimeLimit (New-TimeSpan -Hours 2)
Register-ScheduledTask -TaskName $TaskName `
-Action $actions `
-Trigger $trigger `
-Settings $settings `
-Description 'Export AI chat history and sync it to Joplin' `
-Force | Out-Null
Write-Host "Registered '$TaskName' - daily at $Time for: $($Provider -join ', ')"
Write-Host ''
Write-Host 'Command the task will run:'
Write-Host " powershell.exe $taskArgs"
Write-Host " (working directory: $repo)"
Write-Host ''
Write-Host 'Next steps:'
Write-Host " * Run it once now: Start-ScheduledTask -TaskName $TaskName"
Write-Host " * Check the result: Get-ScheduledTaskInfo -TaskName $TaskName"
Write-Host " * Read the run output: Get-Content '$repo\cache\logs\scheduled-sync.log' -Tail 50"
Write-Host ' * The terms-of-service notice must have been acknowledged'
Write-Host ' interactively once on this machine, or the task exits 1.'