Windows App AutoLogin is a small desktop tray/menu-bar utility for macOS and Windows that fills Microsoft Windows App credential prompts only when the visible prompt clearly belongs to one saved account.
It is designed for the narrow case where Windows App shows a password prompt with a visible email address. The app verifies the running Microsoft client, reads the visible email, matches exactly one enabled account, loads only that account's password, fills the password field, and submits the prompt.
This project is not affiliated with Microsoft.
- Runs as a lightweight tray/menu-bar app by default.
- Opens the full settings window only on demand.
- Stores account metadata in a local config file.
- Stores passwords in the system secure store by default: macOS Keychain on macOS, Windows Credential Manager on Windows.
- Detects Windows App credential prompts.
- Auto-fills password prompts only after a visible email matches exactly one enabled account.
- Handles native secure password fields only inside a verified credential prompt.
- Keeps internal diagnostic logs bounded and redacted.
- Provides a standalone sanitized macOS UI diagnostic tool for development.
The app is intentionally conservative. It should do nothing unless the current state is unambiguous.
Before loading a password, it requires:
- Platform automation access for the exact running app: macOS Accessibility, or the current Windows desktop UI Automation session.
- A trusted Windows App process/window.
- The expected Microsoft app/process identity.
- The target app to be frontmost.
- A visible credential prompt.
- A visible email address in that prompt.
- Exactly one enabled saved account matching that email.
Before typing or submitting, it revalidates the target process, PID/window context, prompt contents, visible email, and password field.
Diagnostics use the same trusted target constraints as autofill: supported Microsoft identity, expected install path, signing identity, and verified live PID. App names, process names, and window titles are labels, not sufficient authority for diagnostic traversal.
The app does not:
- preload all saved passwords;
- cache decrypted passwords long-term;
- type when the email is missing, mismatched, duplicated, or ambiguous;
- type into an untrusted or background app;
- use the clipboard for password insertion;
- expose secrets through argv, environment variables, temp files, sockets, or HTTP APIs;
- log passwords, OTPs, tokens, recovery codes, clipboard contents, or raw secure-field values.
The runtime trust check currently supports:
Windows App
On Windows, the native implementation uses Windows UI Automation and targets the known Microsoft Windows App process identity.
On macOS, the trusted Microsoft app identity is:
- Bundle ID:
com.microsoft.rdc.macos - Microsoft Team ID:
UBF8T346G9
On macOS, the app expects the Microsoft client bundle to be installed in /Applications:
/Applications/Windows App.app
Other app names, copied bundles, unsigned bundles, modified bundles, or unexpected Windows process/path identities are rejected.
- macOS 11 or newer, or Windows 10/11.
- Rust matching the version in
Cargo.toml(rust-version = "1.93"). - Windows App installed on the same desktop session.
- macOS Accessibility permission for the exact app or binary you launch on macOS.
- macOS may also ask for Automation permission to control System Events; approve it only for the expected Windows App AutoLogin bundle.
- For macOS bundle creation:
sipsandiconutil. - For the non-publishable local signed macOS artifact: a Developer ID Application signing identity available to
codesign, plus anotarytoolkeychain profile. - For the unsigned Windows VM-test artifact: an x64 MSVC Rust toolchain and a Visual Studio Developer PowerShell environment with
cl.exe,lib.exe,link.exe, andrc.exe.
Create a non-publishable local macOS ZIP with a release-profile app bundle that uses the production bundle identity and is Developer ID signed, notarized, and stapled:
RELEASE_CARGO="$(rustup which cargo)"
RELEASE_RUSTC="$(rustup which rustc)"
RELEASE_SYSROOT="$($RELEASE_RUSTC --print sysroot)"
DEVELOPER_DIR=/Applications/Xcode.app/Contents/Developer
XCODE_TOOLCHAIN="$DEVELOPER_DIR/Toolchains/XcodeDefault.xctoolchain"
MACOS_SDKROOT="$DEVELOPER_DIR/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk"
CLANG_RESOURCE_DIR="$($XCODE_TOOLCHAIN/usr/bin/clang -print-resource-dir)"
export WAAL_RELEASE_CARGO_PATH="$RELEASE_CARGO"
export WAAL_RELEASE_RUSTC_PATH="$RELEASE_RUSTC"
export WAAL_RELEASE_RUST_SYSROOT="$RELEASE_SYSROOT"
export WAAL_MACOS_DEVELOPER_DIR="$DEVELOPER_DIR"
export WAAL_MACOS_SDKROOT="$MACOS_SDKROOT"
export WAAL_MACOS_CLANG_RESOURCE_DIR="$CLANG_RESOURCE_DIR"
# Load these values from a separately reviewed, versioned toolchain-pin
# manifest. Hashing the live tools and immediately trusting those hashes is
# only candidate generation; it is not release verification.
export WAAL_RELEASE_EXPECTED_GIT_SHA256=<reviewed-xcode-git-sha256>
export WAAL_RELEASE_EXPECTED_CARGO_SHA256=<reviewed-cargo-sha256>
export WAAL_RELEASE_EXPECTED_RUSTC_SHA256=<reviewed-rustc-sha256>
export WAAL_RELEASE_EXPECTED_CLANG_SHA256=<reviewed-clang-sha256>
export WAAL_RELEASE_EXPECTED_CLANGXX_SHA256=<reviewed-clangxx-sha256>
export WAAL_RELEASE_EXPECTED_AR_SHA256=<reviewed-ar-sha256>
export WAAL_RELEASE_EXPECTED_LD_SHA256=<reviewed-ld-sha256>
export WAAL_RELEASE_EXPECTED_LD_TAPI_SHA256=<reviewed-libtapi-sha256>
export WAAL_RELEASE_EXPECTED_LD_CODEDIRECTORY_SHA256=<reviewed-libcodedirectory-sha256>
export WAAL_RELEASE_EXPECTED_LD_LTO_SHA256=<reviewed-liblto-sha256>
export WAAL_RELEASE_EXPECTED_LD_SWIFT_DEMANGLE_SHA256=<reviewed-libswift-demangle-sha256>
export WAAL_RELEASE_EXPECTED_NOTARYTOOL_SHA256=<reviewed-notarytool-sha256>
export WAAL_RELEASE_EXPECTED_STAPLER_SHA256=<reviewed-stapler-sha256>
export WAAL_RELEASE_EXPECTED_RUST_SYSROOT_SHA256=<reviewed-sysroot-tree-sha256>
export WAAL_RELEASE_EXPECTED_MACOS_SDK_SHA256=<reviewed-sdk-tree-sha256>
export WAAL_RELEASE_EXPECTED_CLANG_RESOURCE_DIR_SHA256=<reviewed-clang-resource-tree-sha256>
export WAAL_RELEASE_EXPECTED_NATIVE_TOOLCHAIN_SHA256=<reviewed-native-aggregate-sha256>
WAAL_RELEASE_BUNDLE_ID=com.obcardinal.WindowsAppAutoLogin \
WAAL_MACOS_TEAM_ID=ABCDE12345 \
WAAL_CODESIGN_IDENTITY="Developer ID Application: Example Corp (ABCDE12345)" \
WAAL_NOTARY_PROFILE=your-notary-profile \
script/package_macos.sh --local-signed-releaseThe files are written as dist/WindowsAppAutoLogin-macos-local-signed-<40-hex-captured-commit>.zip and a matching *.zip.sha256 sidecar. The commit and tree are captured for traceability, but the local shared user security context cannot prove that Cargo produced the Mach-O from that commit before the Developer ID signer signed it. The bundle therefore records publishable=false, attestation=none-local-shared-security-context, and producer-attribution=unavailable-local-shared-security-context in its executable metadata and Contents/Resources/BUILD-INFO.txt. Do not publish it as a release.
Local invocations with --release or --release-diagnostics-artifact fail closed. The only local signed packaging entry point is --local-signed-release. A future publishable macOS artifact must be produced by a separately isolated builder and returned over an authenticated channel. Local publication still uses a same-volume atomic no-replace APFS clone followed by descriptor-bound verification and candidate cleanup: an existing artifact is never unlinked or overwritten, and older commit-labelled artifacts are preserved. These controls protect the selected package bytes; they do not provide producer attribution.
For a local macOS development bundle, use ./script/build_and_run.sh --verify instead. When exactly one Developer ID Application identity is available, the script uses it automatically so Accessibility and other TCC approvals survive rebuilds. Set WAAL_DEVELOPMENT_CODESIGN_IDENTITY=- to force the older cdhash-bound ad-hoc behavior, or set it to a specific Developer ID identity when more than one is installed. This remains a local development artifact, not a publishable release.
Build-check the Windows implementation from another host when the target is installed:
cargo check --target x86_64-pc-windows-gnu --all-targets --all-featuresLocal publishable Windows packaging is intentionally disabled. Cargo and path-based signing tools running under the same Windows security context cannot prove which process produced the bytes or prevent use of the signer as an oracle. An invocation without -Development, or with any certificate or timestamp input, therefore fails before Git, Cargo, certificates, or native tools are resolved.
For an optimized unsigned local VM-test artifact, opt in explicitly from a Visual Studio Developer PowerShell prompt:
.\script\build_windows_dist.ps1 -DevelopmentThe development package is commit-addressed for traceability, but it is not an attested release. BUILD-METADATA.txt records publishable=false, attestation=none-local-shared-security-context, the captured commit/tree, observed tool hashes, and payload hashes; SHA256SUMS.txt protects the selected package bytes. Do not publish this artifact. A future publishable Windows pipeline must run in a separately isolated builder and return output over an authenticated channel.
The Windows packager still uses a clean PowerShell child, an isolated Cargo home, a freshly materialized committed source snapshot, retained directory/file handles, and no-replace publication for the development package. Cargo is allowed to create and uplift its normal executable destination; after Cargo exits, the packager opens the exact child relative to the retained output directory, verifies that it is a non-empty regular single-link file, and denies further writes or replacement while copying it. These controls keep the selected VM-test payload internally consistent; they deliberately do not claim producer attribution against another process running as the same user.
Build and launch the local macOS development app bundle. This path uses the separate development bundle identity and prefers the stable local Developer ID signer described below, with a cdhash-bound ad-hoc fallback; it is not a production release build:
./script/build_and_run.sh --verifyThe bundle is created at:
dist/WindowsAppAutoLogin.app
For a permanent local install, copy the built app to /Applications and launch that copy:
cp -R dist/WindowsAppAutoLogin.app /Applications/
open /Applications/WindowsAppAutoLogin.appmacOS grants Accessibility and Keychain access to a specific app identity/path. If you grant access to the app in dist/ and later move it to /Applications, you may need to grant permission again.
- Build and open the app bundle.
- Use the menu-bar icon and choose Open Accounts.
- If Accessibility is missing, click Request Accessibility Access or Open Accessibility Settings.
- Enable Windows App AutoLogin in:
System Settings -> Privacy & Security -> Accessibility
- Return to the app. It checks Accessibility status every second.
- If macOS prompts for Automation permission to control System Events, approve it for the expected Windows App AutoLogin bundle. The app uses that only for Open at Login cleanup and guarded diagnostics/prompt inspection.
- Add an account in the Accounts tab.
- Save the email and password.
- Keep the account enabled.
- Start the monitor from the menu-bar item if it is not already running.
When the matching Windows App credential prompt is visible and Windows App is frontmost, the background worker attempts one guarded fill and submit sequence.
The app always keeps a lightweight supervisor in the menu bar. On a fresh launch it opens the Accounts window unless Hide main window at launch is enabled; when that setting is enabled, startup remains menu-bar only. The menu contains:
- Open Accounts
- Open Settings
- Start Monitor / Stop Monitor
- Request Accessibility Access
- Open Accessibility Settings
- Accessibility status
- Password storage status
- Last fill result
- Quit
The heavier settings UI is launched only when needed. Closing the settings window returns the app to the lightweight menu-bar process.
The settings window includes:
- Accounts: add, edit, pause, enable, or delete saved accounts.
- Settings: adjust Open at Login and storage mode.
- Diagnose: only when built with development diagnostics features.
Existing accounts can be edited without re-entering a password. Leave the password field blank to keep the saved password.
Enabled accounts must have:
- a non-empty email;
- a saved password;
- no other enabled account with the same email, ignoring case and surrounding whitespace.
The app stores configuration in the user's macOS config directory, typically:
~/Library/Application Support/WindowsAppAutoLogin/config.json
The file contains account metadata and settings only. It does not contain plaintext passwords.
Example:
{
"accounts": [],
"settings": {
"auto_start": false,
"start_minimized": false,
"use_keyring": true
}
}Password records are keyed by account ID and bound to account metadata. Manually editing account IDs or email can disconnect metadata from the saved password and fail closed.
By default, passwords are stored in the system secure store:
- Service:
WindowsAppAutoLogin - Account: the saved account ID
If Use system secure storage is disabled, passwords are stored in an encrypted local fallback file:
passwords.json
That fallback uses AES-256-GCM. Every account and every saved password revision receives a fresh independent 256-bit key. The scoped keys are stored in the system secure store under:
- Service:
WindowsAppAutoLoginFallbackKey - Account:
fallback-account-key:<random-key-id>
The former shared fallback-encryption-key entry is accepted only while migrating legacy records and is retired after the independently keyed ciphertext map is durably committed. The fallback file is not independent of Keychain or Credential Manager: if a referenced scoped key cannot be created or read from the current user's system secure store, fallback password save/load will fail. On Windows, each key is stored in Credential Manager and protected by user-bound DPAPI. The key envelope binds its random key ID to the account ID; the service name, account metadata, purpose, and normalized email hash are validation and routing metadata, not a guarantee that only this executable can decrypt it. Manual metadata edits fail closed.
Recent builds migrate saved passwords when switching storage mode. The app copies and verifies passwords in the new storage before saving the setting, then attempts to remove old copies from the previous backend. If copying or verification fails, the setting is left unchanged. If only old-copy cleanup fails after a save or migration succeeds, passwords remain available in the selected storage and cleanup remains pending for the next launch instead of being forgotten.
During storage-mode and account metadata changes, the app writes a private pending-operation journal so a restart can finish cleanup or restore a consistent config after a crash. A separate durable staged-key journal is committed before a new scoped fallback key is created; startup reconciliation preserves keys referenced by committed passwords.json records and removes only uncommitted crash orphans. Cleanup warnings mean a migration target was verified or an account save completed in the selected backend, but stale old material may remain until recovery succeeds. While a pending operation exists, stored credential changes are blocked and the app retries cleanup on startup. Manual cleanup targets, if the warning persists, are the old WindowsAppAutoLogin account-ID secure-store entries, stale passwords.json records, and retired fallback key material under WindowsAppAutoLoginFallbackKey, including legacy fallback-encryption-key or fallback.key material. Do not manually delete a scoped or legacy fallback key while a fallback password record may still reference it.
If Keychain asks for permission repeatedly, make sure you are launching the same app bundle each time and choose Always Allow only for the intended app identity. Local ad-hoc development signatures are intentionally bound to the executable cdhash, so rebuilding the development bundle changes its identity and can require a new prompt. A stable Developer ID release identity is the appropriate choice when permissions must survive rebuilds.
The autofill path is shared by the background worker and the one-shot debug command.
At a high level:
- Resolve trusted Windows App processes.
- Verify bundle ID, Team ID, path, and code signature.
- Require the target app to be frontmost.
- Detect the visible credential prompt.
- Collect visible prompt text while excluding secure/password-like fields.
- Extract the visible email.
- Match that email against enabled accounts.
- Revalidate the same frontmost prompt and target process before password load.
- Load only the matching account password.
- Detect the intended password field.
- Focus the field and set the password on that exact AX element with a target-bound
AXValueupdate after fresh prompt/focus checks. - Submit only with a bounded
AXPressaction on the verified submit button. - Post-check whether the app reached an authenticated/normal state, still shows the prompt, or ended in an unknown state.
For password insertion, the app requires a native secure password field: macOS AXSecureTextField or Windows UI Automation IsPassword. Password-like plain text controls such as macOS AXTextField or Windows plain Edit are not accepted as insertion targets, even inside a verified Windows App prompt.
Run a sanitized macOS UI diagnostic report:
cargo run --quiet --features diagnostics-ui --bin diagnose-macos-uiThe diagnostic binary prints JSON describing visible target processes, windows, controls, and selected system dialogs. Sensitive values are redacted. Raw AppleScript output is not printed.
Diagnostic target discovery uses the same trusted-target constraints as autofill: supported Microsoft identity, expected install path, signing identity, and verified live PID. App names, process names, and window titles are treated only as report labels; they are not enough to select or traverse an arbitrary process.
release-diagnostics is reserved for a future intentional support artifact produced by an isolated authenticated builder, not for the local packager or general releases. Diagnostic output is redacted and capped; signing identities, signing identifiers, Team IDs, and app bundle IDs are reduced to coarse status values before display or export. It can still include process IDs and timing data; review it before sharing with support.
Run one guarded fill attempt from a development build compiled with debug-fill or dev-tools and launched from the trusted app bundle:
/Applications/WindowsAppAutoLogin.app/Contents/MacOS/windows-app-autologin --debug-fill-onceThe one-shot command is intended for development and troubleshooting. It is available only in debug builds with the explicit debug-fill feature enabled and requires Accessibility permission for the trusted /Applications/WindowsAppAutoLogin.app bundle identity. Do not package, distribute, or leave a debug-fill build installed as the production app.
Default features:
none
Optional features:
debug-fill
diagnostics-ui
dev-tools (enables debug-fill and diagnostics-ui)
release-diagnostics (reserved for isolated release support-artifact builders)
Build a debug-only local bundle and launch its full UI with diagnostics enabled:
./script/build_and_run.sh --dev-uiStart the packaged supervisor and have it open an authorized full settings UI:
./script/build_and_run.sh --full-uiCommon local gates:
cargo fmt --check
cargo check --all-targets
cargo clippy --all-targets -- -D warnings
cargo test
./script/build_and_run.sh --verifyAdditional feature coverage:
cargo check --all-targets --all-featuresThe test suite covers the main safety decisions: visible-email matching, missing/mismatched/duplicate accounts, disabled accounts, PID/window drift, settings-generation cancellation, bounded logs, redaction, diagnostic output caps, diagnostics name-spoof rejection, and target identity checks.
script/build_and_run.sh creates a local app bundle and, when exactly one Developer ID Application identity is available, uses that stable identity so Accessibility, Automation, and Keychain approval can survive rebuilds. The result still contains development build metadata and the development bundle ID; it is not a publishable or notarized release. If no unique Developer ID identity is available, or WAAL_DEVELOPMENT_CODESIGN_IDENTITY=- is set, the script falls back to the default cdhash-bound ad-hoc signature. That fallback does not trust every ad-hoc application that copies the public bundle identifier, but its identity changes after every rebuild and macOS permissions may need to be granted again.
Current development bundle ID:
obcardinal.windows-app-autologin
The development script does not perform release packaging or notarization. Even when it uses a local Developer ID identity for stable TCC behavior, it opts into WAAL_DEVELOPMENT_RELEASE=1 and retains the separate development bundle identity.
Local script/package_macos.sh --release and script/package_macos.sh --release-diagnostics-artifact invocations fail closed because this packager cannot create a publishable or producer-attested macOS artifact. Use script/package_macos.sh --local-signed-release only for the explicitly non-publishable local signed ZIP.
The local signed path requires the Git checkout to have no tracked, non-ignored untracked, assume-unchanged, or skip-worktree changes; captures the exact 40-hex HEAD commit and tree IDs; materializes an isolated source snapshot from that commit; verifies every materialized file byte and executable mode against its Git blob before and after Cargo and bundle assembly; and rechecks the checkout, snapshot, and embedded observations before writing the package. Git uses the explicitly pinned physical Xcode executable with ambient Git configuration, replacement refs, hooks, and local filesystem-monitor execution disabled; tracked archive attributes remain harmless because the extracted file set and every byte are compared with the Git tree. Cargo runs with a new packager-owned HOME, CARGO_HOME, temporary directory, target directory, fixed system-tool path, explicit DEVELOPER_DIR and SDKROOT, and no Cargo configuration in its working-directory ancestors. The dependency graph must contain only the archived root package and locked crates.io packages—external path, Git, alternate-registry, and source-replacement inputs are rejected. Cargo, rustc, the complete Rust sysroot, physical Xcode Git, clang, clang++, ar, ld, the four Xcode linker runtime libraries, the selected macOS SDK tree, Clang resource directory, notarytool, and stapler must match separately reviewed SHA-256 pins; /usr/bin developer-tool shims are not packaging inputs. The Rust/native build inputs are copied into a private single-link snapshot, made read-only and immutable, and checked by exact tree identity before and after Cargo. Their observed hashes and the captured source identifiers are recorded in the executable metadata and signed BUILD-INFO.txt.
Before signing, the packager captures a canonical digest of the full bundle payload; the main Mach-O digest normalizes only the terminal code-signature blob and its corresponding load-command/__LINKEDIT size fields. That payload digest is rechecked around codesign, notarization, stapling, final verification, and archive creation. The script uses the production bundle identity and release Cargo profile, signs with WAAL_CODESIGN_IDENTITY, notarizes with WAAL_NOTARY_PROFILE, staples the ticket, and zips only the selected staged bundle. Pre-existing dist/*.app bundles and ignored working-copy files are excluded as inputs, and dist must be a real directory rather than a symlink. These checks establish package consistency and record observed inputs, but a process running as the same user can still substitute Cargo output before signing. The local signature, notarization, commit-labelled filename, captured identifiers, and payload hashes therefore do not attest which producer created the Mach-O or prove a producer-attested relationship to the commit.
The Rust sysroot tree digest is SHA-256 over ordinal byte-sorted regular-file entries encoded as relative/path, NUL, lowercase file SHA-256, NUL; symbolic links and special nodes are rejected. The Xcode SDK/resource-tree digest additionally supports only non-broken symbolic links whose resolved targets remain inside the same pinned root; it encodes each ordinal byte-sorted regular file as relative/path, NUL, file, NUL, lowercase file SHA-256, NUL and each link as relative/path, NUL, link, NUL, exact link text, NUL. The macOS native aggregate is SHA-256 over NUL-terminated lowercase hashes, in this exact order: clang, clang++, ar, ld, libtapi.dylib, libcodedirectory.dylib, libLTO.dylib, libswiftDemangle.dylib, the macOS SDK tree, and the Clang resource directory. The macOS observed-materials aggregate applies the same rule in this exact order: physical Xcode Git, Cargo, rustc, the Rust sysroot aggregate, the native-toolchain aggregate, notarytool, and stapler. Windows development metadata likewise records observed deterministic hashes for local tool and directory inputs. These local observations are not a producer attestation or a publishable release-materials claim.
The current local signed macOS path intentionally produces an ARM64 binary. CFBundleVersion defaults to the numeric Cargo package version and can be overridden with a valid one-to-three-component WAAL_BUILD_VERSION.
Local signed packaging refuses to continue unless WAAL_RELEASE_BUNDLE_ID, WAAL_MACOS_TEAM_ID, WAAL_CODESIGN_IDENTITY, and WAAL_NOTARY_PROFILE are set, the source checkout is clean and unchanged throughout packaging, the production bundle ID is a reverse-DNS identifier that differs from the development bundle ID, the executable metadata contains the same expected bundle ID, Team ID, captured source commit/tree, target, observed toolchain hashes, and observed materials aggregate, and the bundle passes production identity checks: expected production bundle ID, Developer ID Application signature, matching Team ID, hardened runtime, empty release entitlements, non-diagnostics build metadata, Gatekeeper assessment, and stapled notarization. It strips .DS_Store, AppleDouble ._*, and __MACOSX entries from the staged copy, validates the staged bundle and extracted ZIP, writes the ZIP and SHA-256 sidecar under immutable commit-labelled names without replacing prior files, then re-hashes and verifies the final destination archive. Those labels and metadata remain traceability observations, not producer attribution.
The project previously used development bundle ID dev.codex.windows-app-autologin; the current ID is obcardinal.windows-app-autologin. Release and development scripts do not reset privacy databases or alter Keychain access lists automatically. If an obsolete grant remains, remove only the old app entry from System Settings → Privacy & Security → Accessibility and Automation. If you deliberately want command-line cleanup, run the bundle-scoped tccutil reset Accessibility dev.codex.windows-app-autologin and tccutil reset AppleEvents dev.codex.windows-app-autologin yourself after reviewing the target. In Keychain Access, inspect the WindowsAppAutoLogin and WindowsAppAutoLoginFallbackKey items and remove only a stale application entry from Access Control; do not delete password items or the fallback key while fallback records exist. When migrating from an older or explicitly forced ad-hoc development build, remove and re-add the exact rebuilt app in System Settings once; the default stable development signature then lets that approval survive later rebuilds.
script/package_macos.sh --release-diagnostics-artifact is intentionally disabled locally and fails closed, just like --release. script/build_and_run.sh --dev-ui remains a local development diagnostics path; it builds dev-tools, includes debug-fill, uses the development identity, and must not be treated as a signed support or release artifact. Any future publishable diagnostics artifact must use a separate diagnostics identity and be produced by the isolated authenticated builder.
The app bundle sets LSUIElement=true, so it behaves like a menu-bar utility rather than a Dock-first application.
On macOS, Open at Login is trusted only for the exact canonical bundle path /Applications/WindowsAppAutoLogin.app with the expected bundle identifier; the app intentionally refuses autostart from other bundle locations, including transient build locations such as target/, dist/, /tmp, and /var/folders. On Windows, Open at Login registers the current executable path wherever the user runs it from; the app still requires the saved Startup command to exactly match the command it generated, with no extra arguments.
Check:
- The exact launched app has Accessibility permission.
- Windows App is installed in
/Applications. - Windows App is frontmost.
- The credential prompt contains a visible email.
- Exactly one enabled saved account matches that email.
- The matching account has a saved password.
- There is no duplicate enabled account with the same email.
- The Microsoft app bundle has not been copied, modified, or re-signed.
Keychain approval time is counted as password load time. If macOS prompts, approve the intended app and choose Always Allow.
Repeated prompts usually mean macOS sees a different client identity, for example:
- launching from
target/debuginstead of the.app; - rebuilding an ad-hoc signed bundle repeatedly;
- moving the app after granting permission;
- granting permission to Terminal instead of the bundled app.
The app fails closed if:
- the email is hidden;
- the prompt email does not match an enabled account;
- multiple enabled accounts match;
- the target app is not frontmost;
- the target PID/window changed;
- the platform exposes the password box only as a non-secure plain text field;
- the password field cannot be verified or focused;
- Accessibility returns an error or times out.
The diagnostic tool uses bounded Accessibility traversal and discards raw output on timeout. A timeout should not expose field values. Try closing unrelated modal dialogs and rerun:
cargo run --quiet --features diagnostics-ui --bin diagnose-macos-ui- Supports only the Microsoft Windows App identity.
- UI detection depends on macOS Accessibility data on macOS and Windows UI Automation data on Windows.
- Prompts with hidden emails, unusual localization, MFA-only flows, SSO web views, or nonstandard controls may not be fillable.
- The app intentionally prefers doing nothing over guessing.
MIT
