Windows 11 CLI to locate application install directories, executables, and (in progress) config/data paths. Emits deterministic JSON (plus CSV/text). Core discovery, ranking scaffold, and baseline tests are now in place.
| Area | Implemented | Notes |
|---|---|---|
| Registry uninstall | Yes | HKLM/HKCU + WOW6432Node |
| App Paths | Yes | HKLM/HKCU App Paths; exe + optional Path dir |
| Start Menu shortcuts | Yes | .lnk resolution (COM) user + common |
| Processes | Yes | Running processes; synergy evidence |
| PATH search | Yes | where.exe + PATH scan |
| MSIX / Store | Yes | PowerShell enumeration + env fake provider |
| Services & Tasks | Yes | ImagePath + scheduled task parsing |
| Heuristic FS scan | Yes | Bounded depth/time roots |
| Index cache | Removed | Will return if cold latency >2s |
| Ranking | Phase 2 | Span compactness, noise penalties, refined diminishing returns |
| Config/Data rules | Partial | Seeded YAML rule pack; expanding |
| Existence filtering | Yes | Drops non-existent paths (live + cache sanitize) |
| Evidence emission | Yes | Optional via --evidence |
| Snapshot tests | Yes | Verify deterministic outputs |
| Single-file publish | Yes | Win x64/ARM64 + SBOM |
| Plugin system | Pending | Data-only aliases/rules planned |
Basic:
applocate code
applocate "visual studio code" --json --limit 5
applocate chrome --csv --confidence-min 0.75 --evidenceOptions (implemented CLI surface):
<query> App name / alias / partial tokens
--json | --csv | --text Output (default text)
--limit <N> Max hits after filtering (applied after optional collapse)
--confidence-min <f> Filter threshold (0-1)
--strict Deprecated/no-op (behavior integrated into default heuristics)
--user | --machine Scope filters
--all Return ALL hits (no per-type collapsing)
--exe | --install-dir | --config | --data Type filters (any combination)
--running Include running process enumeration
--pid <n> Target specific process id (implies --running)
--package-source Show package type & source list in text/CSV output
--threads <n> Max parallel source queries (default=min(logical CPU,16))
--trace Per-source timing diagnostics (stderr; prefix [trace])
--evidence Include evidence dictionary (if available)
--evidence-keys <k1,k2> Only include specified evidence keys (implies --evidence)
# (cache/index options removed – may return if future sources are slow)
--timeout <sec> Per-source soft timeout (default 5)
--no-color Disable ANSI color in text output
--verbose Verbose diagnostics (warnings)
--help Show help
-- Treat following tokens as literal query
Default behavior (without --all): results are collapsed to the single best hit per type (exe, install_dir, config, data) using confidence, then tie‑broken by scope (machine over user) and evidence richness. Use --all to inspect every distinct hit (useful for debugging ranking or seeing alternate install roots).
Planned / not yet implemented flags from original design (roadmap): --fuzzy (explicit enable), --elevate / --no-elevate. These remain on the backlog and are intentionally absent from current binary.
Exit codes: 0 (results), 1 (no matches), 2 (argument error), 3 (permission), 4 (internal).
--evidence adds key/value provenance. Examples:
Confidence heuristic (phase 1): token & fuzzy coverage, exact exe/dir boosts, alias equivalence, evidence synergy (shortcut+process), multi-source diminishing returns, penalties (temp/broken). Scores ∈ [0,1].
For deterministic tests:
APPDATA,LOCALAPPDATA,PROGRAMDATAPATHAPPLOCATE_MSIX_FAKE(JSON array of fake MSIX packages)
Example:
$env:APPLOCATE_MSIX_FAKE='[{"name":"SampleApp","family":"Sample.App_123","install":"C:/tmp/sample","version":"1.0.0.0"}]'
applocate sample --json{
"type": 1,
"scope": 0,
"path": "C:/Users/u/AppData/Local/Programs/Code/Code.exe",
"version": null,
"packageType": 3,
"source": ["StartMenuShortcutSource","RegistryUninstallSource"],
"confidence": 0.92,
"evidence": {"Shortcut":"...Code.lnk","DisplayName":"Visual Studio Code"}
}Fields are append-only; enum values only extend at tail.
- Pre-1.0: additive only (no breaking schema changes)
- 1.0+: semantic versioning
- Deterministic JSON ordering (source generator)
- Enum numeric values stable
- No network or telemetry
- Does not execute discovered binaries
- Least privilege by default
Foundation milestone reached – all primary discovery sources implemented with real enumeration logic.
Implemented:
- Core contract:
AppHitrecord & enums (stable, JSON source generator context inJsonContext). - Sources (real): Registry Uninstall (HKLM/HKCU, WOW6432Node), App Paths, Start Menu shortcuts (.lnk resolution), Running Processes, PATH search (
wherefallback), Services & Scheduled Tasks (image path extraction), MSIX/Store packages (Appx), Heuristic filesystem scan (bounded depth/timeout, curated token filters). - Evidence & Merge: Dedup + union of
Sourcearrays and merged evidence key/value sets. - Ranking: token & fuzzy coverage (Jaccard + collapsed substring), exact exe/dir boosts, alias equivalence (embedded dictionary), evidence synergy (shortcut+process), diminishing returns on multi-source, path quality penalties; final score clamped [0,1].
- (Former) indexing layer removed: on-disk cache provided minimal benefit (<500ms cold queries). Will reintroduce a snapshot/inverted index if added package manager sources push cold median >2s.
- Argument parsing: Manual robust multi-word parsing +
--sentinel, validation for numeric options, custom help text (usesSystem.CommandLineonly for usage surface). - Output formats: text (color-aware), JSON, CSV.
- Rules engine: lightweight YAML (subset) parser expands config/data hits (VSCode, Chrome examples) before ranking.
- Comprehensive automated test suite (see Tests section).
In Progress / Next Focus:
- Ranking refinement (alias weighting, fuzzy distance scoring, multi-source diminishing returns calibration).
- Acceptance scenario fixtures (VSCode, Chrome, portable app, MSIX) with golden expectations.
- Config/Data heuristics expansion via YAML rule pack (currently minimal seeds in
rules/apps.default.yaml). - Performance tuning (parallel source fan-out, thread cap, profiling cold vs warm index hits).
Upcoming Backlog:
- Plugin loading for alias/rule packs (data-only).
- DI/registration refactor for sources.
- Expanded YAML rules (50+ popular apps) & tests.
- CSV / evidence output tests and JSON contract schema doc.
- Portable app fixture harness (synthetic directory & shortcut).
- Packaging: single-file trimmed exe, optional PowerShell module export.
- CI enhancements (matrix build win-x64/arm64, cache index test artifacts, code signing optional).
- Performance benchmarks & regression guard.
src/AppLocate.Core # Domain models, abstractions, placeholder sources, ranking & rules stubs
src/AppLocate.Cli # CLI entry point (manual parsing placeholder)
tests/*.Tests # xUnit test projects
rules/apps.default.yaml # Sample rule file (placeholder)
build/publish.ps1 # Single-file publish script (win-x64 / win-arm64)
dotnet restore
dotnet build
dotnet testRun (may produce limited or no hits depending on environment):
dotnet run --project src/AppLocate.Cli -- vscode --jsonExit codes: 0 (results found), 1 (no matches), 2 (bad arguments/validation error).
pwsh ./build/publish.ps1 -X64 -Arm64 -Configuration ReleaseArtifacts land under ./artifacts/<rid>/.
Each published RID artifact now includes a CycloneDX SBOM file (sbom-<rid>.json) listing dependency components for supply-chain transparency.
Completed / Phase 1 Foundation:
- Reintroduce
System.CommandLine+ full option set - Initial ranking heuristics (phase 1) // (Removed) JSON indexing cache & related invalidation (to be reconsidered later)
- Discovery sources (registry uninstall, App Paths, start menu shortcuts, processes, PATH, services/tasks, MSIX/Store, heuristic FS)
- Golden snapshot tests (Verify) for core queries
- Deterministic CLI argument validation tests
- YAML rules engine (phase 1 subset) for config/data expansion
- Ranking calibration pass (alias & fuzzy weighting baseline)
-
--package-sourceoutput integration - Acceptance scenario scaffolding (VSCode, Chrome, portable app; MSIX placeholder)
- PowerShell module wrapper (Invoke-AppLocate / Get-AppLocateJson) // Indexing/cache layer removed; reconsider only if cold median >2s // Completed refinements since v0.1.2
- Evidence output stabilization & selective evidence emission tests
- Alias canonicalization pipeline (query variants → canonical form)
- Generic post-score noise filtering (uninstall/update/setup, cache/temp, docs/help)
- Generic auxiliary service/host/updater/helper suppression
- MSIX improvements: AppxManifest exe parsing, multi-token matching, WindowsApps path acceptance
- App Execution Alias support via PATH search + alias canonicalization (e.g.,
wt.exefor Windows Terminal) - Score breakdown output (JSON) with detailed ranking signals
- DI/registration refactor for sources (builder-based injection seams)
In Progress / Near Term:
- Expanded config/data heuristics acceptance scenarios
- Performance tuning (parallel scheduling, cold vs warm benchmarks)
- Plugin loading (data-only alias & rule packs)
- JSON schema contract & versioning documentation
- Benchmark harness (cold vs warm index, thread scaling, source timing)
Backlog / Later: // Existence filtering now always live (cache layer removed)
- Rule pack ≥50 apps finalized with tests
- Advanced ranking ML/learned weights experiment (optional)
- CI matrix (x64/ARM64), optional code signing & SBOM pipeline polish
- PowerShell module publishing & gallery packaging
- Trimming / single-file size optimization, ReadyToRun evaluation
- Plugin pack distribution format (zip/yaml catalog)
- Elevation strategy (
--elevate/--no-elevate) & privileged source gating - Additional package manager adapters (Chocolatey, Scoop, Winget integration improvements)
Categories (representative):
- Core & Models:
AppHitserialization, deterministic JSON shape. - Ranking: tokenization, alias equivalence vs evidence alias, fuzzy distance, boosts/penalties, Steam auxiliary demotion, span/coverage.
- CLI Deterministic: argument parsing/validation, exit codes, type filters,
--package-source, selective--evidence-keys. - Snapshot (Verify): golden projections with volatile fields stripped.
- Rules Parsing: YAML subset correctness and expansion.
- Acceptance (synthetic): VS Code (code/vscode), portable app, MSIX fake provider; PATH alias discovery (oh‑my‑posh), running process (
--running). - Score breakdown: JSON
breakdownpresence and stability.
Run all tests:
dotnet test AppLocate.sln -c ReleaseFilter examples:
# Ranking tests only
dotnet test tests/AppLocate.Core.Tests --filter FullyQualifiedName~RankingTests
# Acceptance scenarios
dotnet test tests/AppLocate.Cli.Tests --filter FullyQualifiedName~AcceptanceSnapshots:
- Make intentional change.
- Run tests; inspect .received. files.
- Approve by replacing .verified files (commit rationale).
Synthetic acceptance tips:
- Override
LOCALAPPDATA,APPDATA,PATHto point to temp fixtures. - Inject MSIX packages via
APPLOCATE_MSIX_FAKE(JSON array) for deterministic enumeration. - Use .lnk shortcuts to exercise Start Menu + evidence synergy.
Adding acceptance scenarios:
- Build temp layout & dummy exe(s).
- Optionally add rule entries in
rules/apps.default.yamlfor config/data. - Invoke CLI and assert required hit types & confidence ≥0.8.
- Avoid dependence on real machine installs.
Contributor guidelines:
- Keep tests deterministic; no network or real software dependencies.
- Strip/ignore volatile data in snapshots (timestamps, absolute temp roots).
- Prefer suffix or logical assertions over full absolute path equality.
- Document ranking expectation changes in commits.
- Use
[Fact(Skip=..)]sparingly with backlog reference.
Planned test expansions:
- Rule pack growth (≥50 apps) with fixtures.
- Live
--runningprocess capture scenario. - Performance regression timing harness.
See .github/copilot-instructions.md for design/extension guidance. Keep AppHit schema backward compatible.
- No network I/O, no executing discovered binaries.
- Keep JSON camelCase & deterministic ordering via source generator (
JsonContext). - Add XML docs gradually (warnings currently suppressed only by omission).
- Ranking: token coverage (+ up to 0.25), partial token Jaccard (+ up to 0.08 noise‑scaled), span compactness (+0.14) with noise penalties for excessive non‑query tokens (up to -0.12), exact filename (+0.30), alias equivalence (+0.22) vs evidence alias (+0.14), fuzzy filename similarity (Levenshtein scaled + up to 0.06), evidence boosts (shortcut/process + synergy, where, dir/exe matches), harmonic multi-source diminishing returns (cap +0.18), type baselines, and penalties (broken shortcut, temp/installer/cache paths). Scores clamped to [0,1].
This README reflects the discovery + indexing + baseline test milestone; update with each subsequent milestone (ranking calibration, rules, performance, packaging).
{"Shortcut":"C:/Users/u/.../Code.lnk"} {"ProcessId":"1234","ExeName":"Code.exe"} {"DisplayName":"Google Chrome","HasInstallLocation":"true"}