Skip to content

Schedule view in sidebar: list and manage Windows scheduled tasks (0.2.0)#8

Merged
shaase-ctrl merged 1 commit into
mainfrom
feat/schedule-view
May 10, 2026
Merged

Schedule view in sidebar: list and manage Windows scheduled tasks (0.2.0)#8
shaase-ctrl merged 1 commit into
mainfrom
feat/schedule-view

Conversation

@shaase-ctrl
Copy link
Copy Markdown
Owner

Why

A hand-written Windows scheduled task running 2026-04-22_backup-claude-workstation.ps1 writes loose-file Claude AppData snapshots into an OneDrive-synced folder. The nested local-agent-mode-sessions\<UUID>\<UUID>\local_<UUID>\... paths blow past the 260-character limit when combined with the OneDrive root and OneDrive refuses to sync them. ClaudePortable solves this by writing a single ZIP, but until now had no way to see that the legacy task even exists. schedule show could only query one named task at a time.

What

A 6th sidebar section "Schedule" that enumerates every Windows scheduled task on this machine via schtasks.exe /Query /FO CSV /V, parses the German + English locale CSV output, and classifies each entry as:

  • ClaudePortable (green pill) - name starts with ClaudePortable- or Author contains ClaudePortable
  • Claude-related (orange pill) - foreign task whose name, action, args, or working directory matches a marker like .claude, Claude_pzs8sxrjxfjjc, Cowork, CoWork\Backup, local-agent-mode-sessions, claude-desktop, anthropic
  • Other (gray pill) - everything else

Per-row Run / Disable / Enable / Delete / View XML buttons, gated by MessageBox confirmation for destructive actions. View XML copies the raw schtasks /Query /XML output to the clipboard.

CLI parity:

claudeportable schedule list [--all|--managed|--relevant] [--json]
claudeportable schedule disable|enable|run <name>

Existing install / show / remove / emit subcommands are untouched.

How it stays small

  • No new NuGet dependencies. Custom MVVM + AsyncRelayCommand reused.
  • Single small CSV reader inline rather than pulling in Microsoft.VisualBasic.FileIO.TextFieldParser.
  • TaskSchedulerInstaller keeps its public surface and just adds 5 methods, all routed through one new internal Func<> seam so tests can record exact schtasks argv without invoking the executable.
  • ScheduledTaskClassifier is a pure static function over a stable, testable marker list.

Tests

61 -> 98 xUnit cases. New:

  • ScheduledTaskCsvParserTests - feeds a canned German-locale schtasks /Query /FO CSV /V fixture covering \Claude-Desktop-Backup, \ClaudePortable-Daily, an Adobe task, an Office task in a subfolder, and a disabled task. Asserts row count, executable / args split for quoted and unquoted paths, FolderPath/Name split, State on disabled rows, and ManagedBy classification.
  • ScheduledTaskClassifierTests - table-driven coverage including case-insensitivity, marker-in-working-directory-only, and the legacy backup PS1.
  • TaskSchedulerInstallerCommandShapeTests - per-method argv assertions for Install / Delete / Disable / Enable / RunNow / GetTaskXml / Enumerate.

Out of scope

  • Does NOT auto-disable, auto-delete, or migrate any task. The user clicks each action explicitly with a confirmation dialog.
  • Does NOT touch the existing backup engine or archive format. A 0.1.x backup ZIP restores identically on 0.2.0.
  • No code-signing change.

Release

CHANGELOG.md added under [0.2.0]. scripts/build-exe.ps1 and src/ClaudePortable.Installer/build-msi.ps1 default version bumped to 0.2.0. Tag v0.2.0 on main will trigger the existing release.yml workflow.

Test plan

  • dotnet build ClaudePortable.slnx -c Release clean
  • dotnet test ClaudePortable.slnx -c Release 98/98 pass
  • claudeportable schedule list --all lists all tasks on this Windows 11 machine and classifies them
  • claudeportable schedule list --all --json emits camelCase JSON
  • Launch GUI, click "Schedule" in sidebar, verify Refresh loads tasks, filter radio buttons, status pill colors, Disable/Run/View XML buttons work
  • Merge + tag v0.2.0 -> verify release.yml builds MSI + portable exe artifacts

…2.0)

New sidebar section that lists every scheduled task via schtasks /Query
/FO CSV /V and classifies each as ClaudePortable-managed (green),
foreign-but-Claude-related (orange), or unrelated (gray). Per-row buttons
run / disable / enable / delete / show XML; destructive actions gate
behind a confirmation dialog.

CLI parity: schedule list [--all|--managed|--relevant] [--json], plus
schedule disable|enable|run <name>. Existing install / show / remove /
emit subcommands unchanged.

TaskSchedulerInstaller gains EnumerateAsync / DisableAsync / EnableAsync
/ RunNowAsync / GetTaskXmlAsync and routes all calls through an
internal Func<> seam so unit tests can assert exact schtasks argv
without invoking the executable. ScheduledTaskClassifier is a pure
static function over a stable marker list so it stays testable.

Motivating use case: legacy hand-written backup PowerShell tasks that
write loose-file Claude backups into a long-path OneDrive folder
silently outcompete ClaudePortable's ZIP output and break sync. The new
view surfaces them so the user can disable or delete them from inside
the app.

Tests: 37 new xUnit cases (CSV parser with German schtasks fixture,
relevance classifier, installer command shapes). 61 -> 98 cases total.
@shaase-ctrl shaase-ctrl merged commit ca73f4d into main May 10, 2026
1 check passed
@shaase-ctrl shaase-ctrl deleted the feat/schedule-view branch May 10, 2026 22:10
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant