# ClaudeDo.Installer WPF GUI installer, updater, and configuration tool for ClaudeDo. Not WiX/NSIS — the app is its own installer. Note: this is the one project where `System.Windows` is correct (WPF, not Avalonia). ## Project Facts - `true`, `WinExe`, `net8.0-windows` - `true` — allows Linux CI to cross-compile - Single-file framework-dependent publish: `dotnet publish -r win-x64 -p:PublishSingleFile=true` (needs .NET 8 Desktop Runtime) - Entry point: `App.xaml` / `App.xaml.cs` (no `Program.cs`) - References: `ClaudeDo.Data`, `ClaudeDo.Releases`, `ClaudeDo.Localization` - Manifests: `app.manifest` (requireAdministrator, Release) / `app.debug.manifest` (asInvoker, Debug) - Only CLI arg: `--replace-self ` (self-update handoff) ## Startup Sequence (`App.OnStartup`) 1. Load locale 2. Self-update preflight — `SelfUpdater.DecideUpdateAsync` checks Gitea API; if a newer installer exists, download + checksum verify + relaunch with `--replace-self ` 3. Detect mode — `InstallModeDetector` reads `install.json` + Gitea API 4. Open `WizardWindow` (FreshInstall / Update) or `SettingsWindow` (Config) ## Modes (`Core/InstallerMode.cs`) | Mode | Condition | Window | |---|---|---| | `FreshInstall` | No `install.json` | Full wizard (all pages) | | `Update` | `install.json` present + newer release available | Wizard — Welcome + Install pages only | | `Config` | Current version, or Gitea API unreachable | `SettingsWindow` (settings / repair / uninstall) | ## Install Pipelines Each step implements `IInstallStep`; `InstallerService` runs them sequentially, stops on failure. **FreshInstall:** `DownloadAndExtractStep` → `WriteConfigStep` → `InitDatabaseStep` → `RegisterMcpStep` (optional) → `RegisterAutostartStep` → `CreateShortcutsStep` → `WriteUninstallRegistryStep` → `WriteInstallManifestStep` → `StartWorkerStep` **Update:** `StopWorkerStep` → `DownloadAndExtractStep` → `RegisterAutostartStep` → `RegisterMcpStep` → `StartWorkerStep` → `WriteInstallManifestStep` → `WriteUninstallRegistryStep` **Repair** (via `SettingsViewModel`): `StopWorkerStep` → `DownloadAndExtractStep` → `RegisterAutostartStep` → `StartWorkerStep` **Uninstall** (`UninstallRunner`): Stop worker → remove legacy task/service → delete HKLM uninstall key + shortcuts → delete install dir (cmd.exe trampoline if uninstaller exe is inside it) → optionally delete `~/.todo-app` ## Folder Layout ``` Installer/ Steps/ — one class per action (see pipeline lists above) Core/ — InstallContext, InstallerMode, InstallModeDetector, InstallManifest(+Store), ConfigModels, InstallerService, UninstallRunner, PageResolver, AutostartShortcut, ShortcutFactory, ProcessRunner, DarkTitleBar Interfaces/ — IInstallStep + StepResult/StepStatus/StepProgress, IInstallerPage Pages/ — WelcomePage, PathsPage, ServicePage, UiSettingsPage, InstallPage (each: ViewModel + View.xaml) Views/ — WizardWindow(+WizardViewModel), SettingsWindow(+SettingsViewModel), SelfUpdatePromptWindow ``` ## Key Step Behaviors **`RegisterMcpStep`** — registers the external MCP endpoint with the Claude CLI: ``` claude mcp remove --scope user claudedo claude mcp add --transport http --scope user claudedo http://127.0.0.1:{ExternalMcpPort}/mcp ``` Non-fatal if `claude` CLI is missing or too old (prints the manual command). Server name: `claudedo`. **`RegisterAutostartStep`** — creates a per-user Startup-folder shortcut `ClaudeDo Worker.lnk` (`Environment.SpecialFolder.Startup`). Also migrates away from legacy mechanisms: - Deletes legacy Windows service: `sc.exe stop/delete ClaudeDoWorker` - Deletes legacy scheduled task: `schtasks /Delete /TN ClaudeDoWorker` No new service or scheduled task is created. Rationale: the worker must run in the user's interactive session so Claude CLI auth works. ## `InstallContext` Defaults | Property | Default | |---|---| | `InstallDirectory` | `C:\Program Files\ClaudeDo` | | `DbPath` | `~/.todo-app/todo.db` | | `LogRoot` | `~/.todo-app/logs` | | `SandboxRoot` | `~/.todo-app/sandbox` | | `WorktreeRootStrategy` | `sibling` | | `SignalRPort` | `47821` | | `ExternalMcpPort` | `47822` | | `QueueBackstopIntervalMs` | `30000` | | `ClaudeBin` | `claude` | | `AutoStart` | `true` | | `SignalRUrl` | `http://127.0.0.1:47821/hub` | ## Files Written by Install | Path | Content | |---|---| | `~/.todo-app/worker.config.json` | Worker config | | `~/.todo-app/ui.config.json` | UI config | | `~/.todo-app/todo.db` | SQLite DB (EF migrations) | | `\install.json` | Install manifest | | `\app\` | UI binaries | | `\worker\` | Worker binaries | | `\uninstaller\ClaudeDo.Installer.exe` | Uninstaller copy | | `HKLM\Software\Microsoft\Windows\CurrentVersion\Uninstall\ClaudeDo` | Uninstall registry key | | Start Menu shortcut | `ClaudeDo.lnk` | | Desktop shortcut (optional) | `ClaudeDo.lnk` | | `%APPDATA%\Microsoft\Windows\Start Menu\Programs\Startup\ClaudeDo Worker.lnk` | Worker autostart | The Apps & Features uninstall string and "Rerun Installer" both point at `\uninstaller\ClaudeDo.Installer.exe` with no `/uninstall` flag — Config mode is detected from `install.json`.