Adom Desktop
Public Made by Adomby adom
Installs the adom-desktop CLI and its Claude skills INTO A CLOUD CONTAINER so an AI assistant there can understand and drive Adom Desktop over the relay. This is the container side, NOT the app itself. The Adom Desktop app is the signed Windows installer under Download below: run THAT on the PC you want the AI to control. Rule of thumb: pkg install here (in your Linux container), Download there (on your Windows PC). Once installed, the AI can drive file transfer, screenshots, notifications, KiCa
name: adom-desktop-installer description: How to invoke the Adom Desktop NSIS installer from a parent installer (especially Hydrogen Desktop's setup steps) — silent install, /NOLAUNCH switch for HD-managed bundling, live progress via the structured log file at %TEMP%\adom-desktop-install.log. Use when bundling AD inside another Windows installer, writing an install supervisor / setup-step UI, detecting AD's installed version, or upgrading an existing AD install programmatically.
Adom Desktop installer integration
Adom Desktop (AD) ships as a single NSIS installer:
Adom Desktop_<version>_x64-setup.exe (~4.8 MB on v1.8.45)
It installs to %LOCALAPPDATA%\Adom Desktop\ — no UAC prompt, no admin needed. Tauri-2 bundled NSIS with our customisations in src-tauri/installer-hooks.nsh.
Command-line surface
| Flag | Meaning |
|---|---|
| (none) | Installs silently, auto-launches adom-desktop.exe after install |
/S |
Standard NSIS silent flag — same behavior since the top-level SilentInstall silent directive already suppresses UI |
/NOLAUNCH |
v1.8.45+ — install silently, do NOT auto-launch after install. Caller is responsible for spawning AD with the desired flags |
/D=<path> |
Install destination override. Default is $LOCALAPPDATA\Adom Desktop. Rarely needed |
<uninstall.exe> /S |
Silent uninstall. The uninstaller lives at %LOCALAPPDATA%\Adom Desktop\uninstall.exe |
UI behavior: zero UI in all cases. SilentInstall silent is set at the top of the NSIS script, so even setup.exe invoked from Explorer runs without a window. No Welcome page, no progress bar, no Finish page.
Auto-launch: by default the installer calls ExecShell "" "$INSTDIR\adom-desktop.exe" at the end of POSTINSTALL. Pass /NOLAUNCH to suppress this. Used by HD when bundling AD because HD wants to spawn AD with --embedded --start-hidden --relay-url ... --session-token ... itself, not let AD launch standalone first and get respawned via single-instance.
Live progress log
The installer writes structured progress to %TEMP%\adom-desktop-install.log (Windows expands %TEMP% to the user's temp dir, typically C:\Users\<name>\AppData\Local\Temp). Each line is [STAGE] message\r\n:
[START] adom-desktop installer 1.8.45 starting
[PREINSTALL] Cleaning legacy desktop shortcuts
[PREINSTALL] Done. Tauri will now copy bundle files.
[POSTINSTALL] Bundle files copied. Cleaning Tauri's auto-created desktop shortcut.
[POSTINSTALL] /NOLAUNCH passed — skipping auto-launch (caller will spawn)
[DONE] adom-desktop installer complete (no-launch mode)
[START] opens with a truncated write (fresh log per install). [DONE] is always the final line — readers tailing the file can use that as the completion sentinel without needing to wait for the process exit.
Stage tags currently emitted:
[START]— once, at the top[PREINSTALL]— Tauri's beforeBuildCommand hook ran, files about to be copied[POSTINSTALL]— files copied; Tauri's standard shortcuts created and our hook is cleaning the unwanted ones[DONE]— final line, installer about to exit
The uninstaller writes the same log with [PREUNINSTALL] / [POSTUNINSTALL] stages.
Recipe: HD's setup-step UI tails the log
Spawn the installer with /NOLAUNCH, poll the log file on a 200 ms timer, surface each new line to HD's UI. When [DONE] shows up OR the process exits, the install is complete.
Rust (HD's installer driver)
use std::{env, fs, path::PathBuf, process::Command, time::Duration};
use std::os::windows::process::CommandExt;
use tokio::time::sleep;
const CREATE_NO_WINDOW: u32 = 0x08000000;
async fn install_adom_desktop<F: FnMut(String)>(
installer_path: &str,
mut on_line: F,
) -> Result<(), String> {
let log_path: PathBuf = [&env::var("TEMP").map_err(|e| e.to_string())?, "adom-desktop-install.log"]
.iter()
.collect();
// Pre-clear so we don't read stale lines from a previous install.
let _ = fs::remove_file(&log_path);
let mut child = Command::new(installer_path)
.args(["/S", "/NOLAUNCH"])
.creation_flags(CREATE_NO_WINDOW)
.spawn()
.map_err(|e| format!("spawn installer: {e}"))?;
let mut last_pos = 0usize;
loop {
// Tail any new content
if let Ok(content) = fs::read_to_string(&log_path) {
if content.len() > last_pos {
let slice = &content[last_pos..];
if let Some(last_nl) = slice.rfind('\n') {
let consumed = &slice[..=last_nl];
for line in consumed.lines() {
on_line(line.to_string());
if line.starts_with("[DONE]") {
// Don't return yet — wait for process exit
// so we surface the actual exit code, but
// we know progress streaming is finished.
}
}
last_pos += consumed.len();
}
}
}
// Check if installer has exited
if let Some(status) = child.try_wait().map_err(|e| e.to_string())? {
return if status.success() {
Ok(())
} else {
Err(format!("installer exited with {}", status))
};
}
sleep(Duration::from_millis(200)).await;
}
}
// Caller:
// install_adom_desktop(r"C:\path\to\Adom Desktop_1.8.45_x64-setup.exe", |line| {
// hd_setup_step.append_live_output(&line);
// }).await?;
Bash (debugging / scripting)
# Pre-clear stale log
rm -f "$TEMP/adom-desktop-install.log" 2>/dev/null
# Spawn installer in background, tail the log
"./Adom Desktop_1.8.45_x64-setup.exe" /S /NOLAUNCH &
INSTALLER_PID=$!
# Tail until process exits OR [DONE] appears
while kill -0 $INSTALLER_PID 2>/dev/null; do
[ -f "$TEMP/adom-desktop-install.log" ] && tail -F "$TEMP/adom-desktop-install.log" &
sleep 0.2
done
wait
echo "Installer exited"
Recipe: detect if AD is already installed (and at what version)
AD writes its uninstall info to the Windows registry under HKCU (current-user install, no admin needed):
HKCU\Software\Microsoft\Windows\CurrentVersion\Uninstall\AdomDesktop
DisplayName = "Adom Desktop"
DisplayVersion = "1.8.45"
InstallLocation = "C:\Users\<name>\AppData\Local\Adom Desktop"
UninstallString = "C:\Users\<name>\AppData\Local\Adom Desktop\uninstall.exe"
Publisher = "Adom Industries, Inc."
use winreg::enums::HKEY_CURRENT_USER;
use winreg::RegKey;
fn adom_desktop_installed_version() -> Option<String> {
let hkcu = RegKey::predef(HKEY_CURRENT_USER);
let key = hkcu
.open_subkey(r"Software\Microsoft\Windows\CurrentVersion\Uninstall\AdomDesktop")
.ok()?;
key.get_value("DisplayVersion").ok()
}
Compare with semver::Version::parse to decide whether to skip / upgrade / leave-alone.
Recipe: HD's setup-step ladder for embedding AD
The full pattern HD's setup-step UI runs when embedding AD:
1. Check installed version → registry read above
2. Decide:
no install → install bundled AD
older than bundled → install bundled AD (upgrade)
same or newer → skip install entirely
3. Run installer (silent + /NOLAUNCH) → tail log, surface to UI
4. Write embedded marker file → %LOCALAPPDATA%\Adom Desktop\embedded.json
5. Delete AD's user-facing shortcuts → Start Menu, Desktop, Startup folder
(so user can't double-launch standalone)
6. Spawn AD with embedded flags → adom-desktop.exe --embedded
--start-hidden
--relay-url ws://127.0.0.1:8765
--relay-name hydrogen-desktop
--session-token <hd's token>
7. Poll AD's direct API for liveness → GET http://127.0.0.1:47200/health
Steps 4 and 5 are also covered by AD's installer if you pass --embedded at AD's first launch (the embedded-mode detection writes the marker and AD's autostart-upgrade routine handles its own shortcuts). Doing them in HD's installer is belt-and-suspenders.
Bundle-resource pattern
HD's tauri.conf.json should include the AD installer as a bundle resource so it ships inside HD's NSIS installer:
"bundle": {
"resources": {
"resources/Adom Desktop_1.8.45_x64-setup.exe": "resources/"
}
}
At runtime HD finds it under its install dir at $INSTDIR\resources\Adom Desktop_<ver>_x64-setup.exe — pass that path to the install function above.
Versioning + upgrade strategy
| Scenario | What HD's installer should do |
|---|---|
| No AD installed | Install bundled version |
| AD older than bundled | Install bundled version (upgrade) |
| AD same as bundled | Skip install step; still spawn with embedded flags |
| AD newer than bundled | Skip install step; spawn with embedded flags. Don't downgrade — embedded mode works for any AD ≥ v1.8.42 |
The bundled AD installer is the minimum supported version for the HD release. HD can spawn newer ADs without modification.
Exit codes
NSIS returns:
0— install succeeded2— user cancelled (won't happen withSilentInstall silentsince there's no UI to cancel)- Other — install error (rare with our hooks; typical cause is disk full or
%LOCALAPPDATA%not writable)
Treat anything non-zero as a hard failure and surface the log file's last 20 lines to the user.
Where the installer lives
Public download (the user's wiki, which is what end users hit):
https://wiki-ufypy5dpx93o.adom.cloud/static/apps/adom-desktop/Adom%20Desktop_<version>_x64-setup.exe
The wiki page's metadata.install.windows_installer field points at the canonical filename for the current published version. HD's release build can fetch the latest via:
curl -fL https://wiki-ufypy5dpx93o.adom.cloud/static/apps/adom-desktop/version.json | jq -r .windows.installer_filename
# → "Adom Desktop_1.8.45_x64-setup.exe"
curl -fL "https://wiki-ufypy5dpx93o.adom.cloud/static/apps/adom-desktop/$FILENAME" -o resources/ad-setup.exe
version.json also carries the SHA256 hash of the installer so HD's build pipeline can verify the download before bundling.
---
name: adom-desktop-installer
description: How to invoke the Adom Desktop NSIS installer from a parent installer (especially Hydrogen Desktop's setup steps) — silent install, /NOLAUNCH switch for HD-managed bundling, live progress via the structured log file at %TEMP%\adom-desktop-install.log. Use when bundling AD inside another Windows installer, writing an install supervisor / setup-step UI, detecting AD's installed version, or upgrading an existing AD install programmatically.
---
# Adom Desktop installer integration
Adom Desktop (AD) ships as a single NSIS installer:
```
Adom Desktop_<version>_x64-setup.exe (~4.8 MB on v1.8.45)
```
It installs to `%LOCALAPPDATA%\Adom Desktop\` — no UAC prompt, no admin needed. Tauri-2 bundled NSIS with our customisations in `src-tauri/installer-hooks.nsh`.
## Command-line surface
| Flag | Meaning |
|---|---|
| (none) | Installs silently, auto-launches `adom-desktop.exe` after install |
| `/S` | Standard NSIS silent flag — same behavior since the top-level `SilentInstall silent` directive already suppresses UI |
| `/NOLAUNCH` | **v1.8.45+** — install silently, do NOT auto-launch after install. Caller is responsible for spawning AD with the desired flags |
| `/D=<path>` | Install destination override. Default is `$LOCALAPPDATA\Adom Desktop`. Rarely needed |
| `<uninstall.exe> /S` | Silent uninstall. The uninstaller lives at `%LOCALAPPDATA%\Adom Desktop\uninstall.exe` |
**UI behavior**: zero UI in all cases. `SilentInstall silent` is set at the top of the NSIS script, so even `setup.exe` invoked from Explorer runs without a window. No Welcome page, no progress bar, no Finish page.
**Auto-launch**: by default the installer calls `ExecShell "" "$INSTDIR\adom-desktop.exe"` at the end of POSTINSTALL. Pass `/NOLAUNCH` to suppress this. Used by HD when bundling AD because HD wants to spawn AD with `--embedded --start-hidden --relay-url ... --session-token ...` itself, not let AD launch standalone first and get respawned via single-instance.
## Live progress log
The installer writes structured progress to `%TEMP%\adom-desktop-install.log` (Windows expands `%TEMP%` to the user's temp dir, typically `C:\Users\<name>\AppData\Local\Temp`). Each line is `[STAGE] message\r\n`:
```
[START] adom-desktop installer 1.8.45 starting
[PREINSTALL] Cleaning legacy desktop shortcuts
[PREINSTALL] Done. Tauri will now copy bundle files.
[POSTINSTALL] Bundle files copied. Cleaning Tauri's auto-created desktop shortcut.
[POSTINSTALL] /NOLAUNCH passed — skipping auto-launch (caller will spawn)
[DONE] adom-desktop installer complete (no-launch mode)
```
**`[START]`** opens with a truncated write (fresh log per install). **`[DONE]`** is always the final line — readers tailing the file can use that as the completion sentinel without needing to wait for the process exit.
Stage tags currently emitted:
- `[START]` — once, at the top
- `[PREINSTALL]` — Tauri's beforeBuildCommand hook ran, files about to be copied
- `[POSTINSTALL]` — files copied; Tauri's standard shortcuts created and our hook is cleaning the unwanted ones
- `[DONE]` — final line, installer about to exit
The uninstaller writes the same log with `[PREUNINSTALL]` / `[POSTUNINSTALL]` stages.
## Recipe: HD's setup-step UI tails the log
Spawn the installer with `/NOLAUNCH`, poll the log file on a 200 ms timer, surface each new line to HD's UI. When `[DONE]` shows up OR the process exits, the install is complete.
### Rust (HD's installer driver)
```rust
use std::{env, fs, path::PathBuf, process::Command, time::Duration};
use std::os::windows::process::CommandExt;
use tokio::time::sleep;
const CREATE_NO_WINDOW: u32 = 0x08000000;
async fn install_adom_desktop<F: FnMut(String)>(
installer_path: &str,
mut on_line: F,
) -> Result<(), String> {
let log_path: PathBuf = [&env::var("TEMP").map_err(|e| e.to_string())?, "adom-desktop-install.log"]
.iter()
.collect();
// Pre-clear so we don't read stale lines from a previous install.
let _ = fs::remove_file(&log_path);
let mut child = Command::new(installer_path)
.args(["/S", "/NOLAUNCH"])
.creation_flags(CREATE_NO_WINDOW)
.spawn()
.map_err(|e| format!("spawn installer: {e}"))?;
let mut last_pos = 0usize;
loop {
// Tail any new content
if let Ok(content) = fs::read_to_string(&log_path) {
if content.len() > last_pos {
let slice = &content[last_pos..];
if let Some(last_nl) = slice.rfind('\n') {
let consumed = &slice[..=last_nl];
for line in consumed.lines() {
on_line(line.to_string());
if line.starts_with("[DONE]") {
// Don't return yet — wait for process exit
// so we surface the actual exit code, but
// we know progress streaming is finished.
}
}
last_pos += consumed.len();
}
}
}
// Check if installer has exited
if let Some(status) = child.try_wait().map_err(|e| e.to_string())? {
return if status.success() {
Ok(())
} else {
Err(format!("installer exited with {}", status))
};
}
sleep(Duration::from_millis(200)).await;
}
}
// Caller:
// install_adom_desktop(r"C:\path\to\Adom Desktop_1.8.45_x64-setup.exe", |line| {
// hd_setup_step.append_live_output(&line);
// }).await?;
```
### Bash (debugging / scripting)
```bash
# Pre-clear stale log
rm -f "$TEMP/adom-desktop-install.log" 2>/dev/null
# Spawn installer in background, tail the log
"./Adom Desktop_1.8.45_x64-setup.exe" /S /NOLAUNCH &
INSTALLER_PID=$!
# Tail until process exits OR [DONE] appears
while kill -0 $INSTALLER_PID 2>/dev/null; do
[ -f "$TEMP/adom-desktop-install.log" ] && tail -F "$TEMP/adom-desktop-install.log" &
sleep 0.2
done
wait
echo "Installer exited"
```
## Recipe: detect if AD is already installed (and at what version)
AD writes its uninstall info to the Windows registry under `HKCU` (current-user install, no admin needed):
```
HKCU\Software\Microsoft\Windows\CurrentVersion\Uninstall\AdomDesktop
DisplayName = "Adom Desktop"
DisplayVersion = "1.8.45"
InstallLocation = "C:\Users\<name>\AppData\Local\Adom Desktop"
UninstallString = "C:\Users\<name>\AppData\Local\Adom Desktop\uninstall.exe"
Publisher = "Adom Industries, Inc."
```
```rust
use winreg::enums::HKEY_CURRENT_USER;
use winreg::RegKey;
fn adom_desktop_installed_version() -> Option<String> {
let hkcu = RegKey::predef(HKEY_CURRENT_USER);
let key = hkcu
.open_subkey(r"Software\Microsoft\Windows\CurrentVersion\Uninstall\AdomDesktop")
.ok()?;
key.get_value("DisplayVersion").ok()
}
```
Compare with `semver::Version::parse` to decide whether to skip / upgrade / leave-alone.
## Recipe: HD's setup-step ladder for embedding AD
The full pattern HD's setup-step UI runs when embedding AD:
```
1. Check installed version → registry read above
2. Decide:
no install → install bundled AD
older than bundled → install bundled AD (upgrade)
same or newer → skip install entirely
3. Run installer (silent + /NOLAUNCH) → tail log, surface to UI
4. Write embedded marker file → %LOCALAPPDATA%\Adom Desktop\embedded.json
5. Delete AD's user-facing shortcuts → Start Menu, Desktop, Startup folder
(so user can't double-launch standalone)
6. Spawn AD with embedded flags → adom-desktop.exe --embedded
--start-hidden
--relay-url ws://127.0.0.1:8765
--relay-name hydrogen-desktop
--session-token <hd's token>
7. Poll AD's direct API for liveness → GET http://127.0.0.1:47200/health
```
Steps 4 and 5 are also covered by AD's installer if you pass `--embedded` at AD's first launch (the embedded-mode detection writes the marker and AD's autostart-upgrade routine handles its own shortcuts). Doing them in HD's installer is belt-and-suspenders.
## Bundle-resource pattern
HD's `tauri.conf.json` should include the AD installer as a bundle resource so it ships inside HD's NSIS installer:
```json
"bundle": {
"resources": {
"resources/Adom Desktop_1.8.45_x64-setup.exe": "resources/"
}
}
```
At runtime HD finds it under its install dir at `$INSTDIR\resources\Adom Desktop_<ver>_x64-setup.exe` — pass that path to the install function above.
## Versioning + upgrade strategy
| Scenario | What HD's installer should do |
|---|---|
| No AD installed | Install bundled version |
| AD older than bundled | Install bundled version (upgrade) |
| AD same as bundled | Skip install step; still spawn with embedded flags |
| AD newer than bundled | Skip install step; spawn with embedded flags. Don't downgrade — embedded mode works for any AD ≥ v1.8.42 |
The bundled AD installer is the minimum supported version for the HD release. HD can spawn newer ADs without modification.
## Exit codes
NSIS returns:
- `0` — install succeeded
- `2` — user cancelled (won't happen with `SilentInstall silent` since there's no UI to cancel)
- Other — install error (rare with our hooks; typical cause is disk full or `%LOCALAPPDATA%` not writable)
Treat anything non-zero as a hard failure and surface the log file's last 20 lines to the user.
## Where the installer lives
Public download (the user's wiki, which is what end users hit):
```
https://wiki-ufypy5dpx93o.adom.cloud/static/apps/adom-desktop/Adom%20Desktop_<version>_x64-setup.exe
```
The wiki page's `metadata.install.windows_installer` field points at the canonical filename for the current published version. HD's release build can fetch the latest via:
```bash
curl -fL https://wiki-ufypy5dpx93o.adom.cloud/static/apps/adom-desktop/version.json | jq -r .windows.installer_filename
# → "Adom Desktop_1.8.45_x64-setup.exe"
curl -fL "https://wiki-ufypy5dpx93o.adom.cloud/static/apps/adom-desktop/$FILENAME" -o resources/ad-setup.exe
```
`version.json` also carries the SHA256 hash of the installer so HD's build pipeline can verify the download before bundling.