Skip to content

Latest commit

 

History

History

README.md

AutoShell

A Windows shell automation console application that provides a JSON-based command interface for controlling Windows applications, audio settings, themes, and window management.

Overview

AutoShell is part of the TypeAgent project. It runs as a console application that reads JSON commands from stdin and executes Windows shell operations. This enables programmatic control of the Windows desktop environment.

Features

  • Application Management: Launch, close, and switch between applications using friendly names
  • Window Management: Maximize, minimize, and tile windows side-by-side
  • Audio Control: Set volume levels, mute/unmute, and restore previous volume
  • Theme & Personalization: Apply themes, set wallpaper, toggle transparency, and configure title bar colors
  • Virtual Desktop Management: Create, switch, pin, and move windows across virtual desktops
  • Display Settings: Set resolution, brightness, scaling, orientation, color temperature, and blue light filter
  • Network & Connectivity: Wi-Fi, Bluetooth, airplane mode, and metered connection controls
  • Mouse & Touchpad: Cursor speed, pointer size, scroll lines, touchpad settings, and cursor trail
  • Taskbar Customization: Alignment, auto-hide, badges, Task View, Widgets, and multi-monitor display
  • Accessibility: Narrator, Magnifier, Sticky Keys, Filter Keys, and mono audio
  • Privacy Controls: Manage camera, microphone, and location access
  • Power Management: Battery saver levels and power mode configuration
  • System Settings: Notifications, game mode, focus assist, time settings, and multi-monitor behavior
  • File Explorer: Toggle file extensions and hidden/system file visibility

Requirements

Building

AutoShell requires .pas.json schema files generated by the TypeScript action schema compiler (asc). Build the TS side first, then the dotnet project:

# 1. Build TS desktop package (generates .pas.json schemas)
cd ts
pnpm install
pnpm run --filter @typeagent/action-schema-compiler... build
pnpm run -C packages/agents/desktop asc:all

# 2. Build AutoShell
cd ../dotnet
dotnet build autoShell/autoShell.csproj

If you've already run pnpm run build in the ts/ workspace, step 1 is already done.

Usage

AutoShell runs in two modes:

Interactive mode (default): Run the application and send JSON commands via stdin, one per line:

dotnet run --project autoShell.csproj
{"actionName":"Volume","parameters":{"targetVolume":50}}
{"actionName":"Mute","parameters":{"on":true}}
{"actionName":"quit","parameters":{}}

Command-line mode: Pass a JSON command (or array) as an argument for one-shot execution:

autoShell.exe {"actionName":"Volume","parameters":{"targetVolume":50}}
autoShell.exe [{"actionName":"Volume","parameters":{"targetVolume":50}},{"actionName":"Mute","parameters":{"on":true}}]

Each command returns a JSON ActionResult on stdout:

{"success":true,"message":"Volume set to 50"}
{"success":false,"message":"Invalid parameters for 'Volume': ..."}

Command Reference

Core Commands

Command Parameter Description
ApplyTheme Theme name Applies a Windows theme
CloseProgram Application name Closes an application
ConnectWifi {"ssid": "name", "password": "pass"} Connects to a Wi-Fi network
CreateDesktop JSON array of names Creates one or more virtual desktops
Debug (none) Launches the debugger
DisconnectWifi (none) Disconnects from the current Wi-Fi network
LaunchProgram Application name Opens an application (or raises if already running)
ListAppNames (none) Outputs installed applications as JSON
ListResolutions (none) Outputs available display resolutions as JSON
ListThemes (none) Outputs installed themes as JSON
ListWifiNetworks (none) Lists available Wi-Fi networks as JSON
Maximize Application name Maximizes the application window
Minimize Application name Minimizes the application window
MoveWindowToDesktop {"process": "app", "desktop": "name"} Moves a window to a specific virtual desktop
Mute true/false Mutes or unmutes system audio
NextDesktop (none) Switches to the next virtual desktop
PinWindow Application name Pins a window to appear on all virtual desktops
PreviousDesktop (none) Switches to the previous virtual desktop
quit (none) Exits the application
RestoreVolume (none) Restores previously saved volume level
SetScreenResolution "WIDTHxHEIGHT" or {"width": W, "height": H} Sets the display resolution
SetTextSize 100-225 Sets system text scaling percentage
SetThemeMode "light", "dark", "toggle", or boolean Sets light/dark mode
SetWallpaper File path Sets the desktop wallpaper
SwitchDesktop Index or name Switches to a virtual desktop by index or name
SwitchTo Application name Brings application window to foreground
Tile "app1,app2" Tiles two applications side-by-side
ToggleAirplaneMode true/false Enables or disables Windows airplane mode
ToggleNotifications (none) Toggles the Windows notification center
Volume 0-100 Sets system volume percentage
AdjustVolume {"direction": "up"/"down", "amount": 10} Adjusts volume relatively (default ±10%)

Settings Commands

Network Settings
Command Parameter Description
BluetoothToggle {"enableBluetooth": true/false} Toggles Bluetooth on/off
EnableMeteredConnections (none) Opens network status settings
EnableWifi {"enable": true/false} Enables or disables Wi-Fi
Display Settings
Command Parameter Description
AdjustColorTemperature (none) Opens Night light settings
AdjustScreenBrightness {"brightnessLevel": "increase"/"decrease"} Adjusts screen brightness ±10%
AdjustScreenOrientation (none) Opens display settings
DisplayResolutionAndAspectRatio (none) Opens display settings
DisplayScaling {"sizeOverride": "150"} Opens display settings; targets a DPI percentage
EnableBlueLightFilterSchedule {"nightLightScheduleDisabled": true/false} Enables or disables blue light filter schedule
RotationLock {"enable": true/false} Enables or disables rotation lock
Personalization Settings
Command Parameter Description
ApplyColorToTitleBar {"enableColor": true/false} Applies accent color to title bars
EnableTransparency {"enable": true/false} Enables or disables transparency effects
HighContrastTheme (none) Opens high contrast settings
SystemThemeMode {"mode": "light"/"dark"} Sets the system theme mode
Taskbar Settings
Command Parameter Description
AutoHideTaskbar {"hideWhenNotUsing": true/false} Auto-hides the taskbar
DisplaySecondsInSystrayClock {"enable": true/false} Shows seconds in system tray clock
DisplayTaskbarOnAllMonitors {"enable": true/false} Displays taskbar on all monitors
ShowBadgesOnTaskbar {"enableBadging": true/false} Shows or hides badges on taskbar
TaskbarAlignment {"alignment": "left"/"center"} Sets taskbar alignment
TaskViewVisibility {"visibility": true/false} Shows or hides Task View button
ToggleWidgetsButtonVisibility {"visibility": "show"/"hide"} Shows or hides Widgets button
Mouse & Touchpad Settings
Command Parameter Description
AdjustMousePointerSize (none) Opens mouse pointer settings
CursorTrail {"enable": true/false, "length": 2-12} Enables/disables cursor trail (length: 2–12)
EnableTouchPad (none) Opens touchpad settings
EnhancePointerPrecision {"enable": true/false} Enables or disables pointer precision
MouseCursorSpeed {"speedLevel": 1-20} Sets mouse cursor speed (default 10)
MousePointerCustomization (none) Opens mouse pointer settings
MouseWheelScrollLines {"scrollLines": 1-100} Sets mouse wheel scroll lines (default 3)
SetPrimaryMouseButton {"primaryButton": "left"/"right"} Sets primary mouse button
ToggleMouseSonar {"enable": true/false} Enables/disables "Find my pointer" Ctrl ring
TouchpadCursorSpeed (none) Opens touchpad settings
Privacy Settings
Command Parameter Description
ManageCameraAccess {"accessSetting": "allow"/"deny"} Manages camera access
ManageLocationAccess {"accessSetting": "allow"/"deny"} Manages location access
ManageMicrophoneAccess {"accessSetting": "allow"/"deny"} Manages microphone access
Power Settings
Command Parameter Description
BatterySaverActivationLevel {"thresholdValue": 0-100} Sets battery saver activation level
SetPowerModeOnBattery (none) Opens power settings
SetPowerModePluggedIn (none) Opens power settings
Accessibility Settings
Command Parameter Description
EnableFilterKeysAction (none) Toggles Filter Keys
EnableMagnifier (none) Toggles Magnifier
EnableNarratorAction (none) Toggles Narrator
EnableStickyKeys (none) Toggles Sticky Keys
MonoAudioToggle (none) Toggles mono audio
File Explorer Settings
Command Parameter Description
ShowFileExtensions {"enable": true/false} Shows or hides file extensions
ShowHiddenAndSystemFiles {"enable": true/false} Shows or hides hidden and system files
System Settings
Command Parameter Description
AutomaticDSTAdjustment {"enable": true/false} Enables or disables automatic DST adjustment
AutomaticTimeSettingAction (none) Opens date/time settings
EnableGameMode (none) Opens Game Mode settings
EnableQuietHours (none) Opens quiet hours / focus assist settings
MinimizeWindowsOnMonitorDisconnectAction (none) Opens display settings
RememberWindowLocations (none) Opens display settings

Examples

Launch a program:

{"LaunchProgram": "notepad"} 

Set the system volume at 50%:

{"Volume": 50} 

Tile notepad on the left and calculator on the right of the screen:

{"Tile": "notepad,calculator"} 

Apply the 'dark' Windows theme:

{"ApplyTheme": "dark"} 

Set dark mode:

{"SetThemeMode": "dark"}

Toggle between light and dark mode:

{"SetThemeMode": "toggle"}

Mute the system audio:

{"Mute": true} 

Set the desktop wallpaper:

{"SetWallpaper": "C:\\Users\\Public\\Pictures\\wallpaper.jpg"}

Quit AutoShell:

{"quit": null}

Create a new virtual desktop named "Design Work":

{"CreateDesktop": "Design Work"}

Toggle the Windows notification center:

{"ToggleNotifications": true}

Enable airplane mode:

{"ToggleAirplaneMode": true}

Disable airplane mode:

{"ToggleAirplaneMode": false}

List available Wi-Fi networks:

{"ListWifiNetworks": true}

Connect to a Wi-Fi network:

{"ConnectWifi": {"ssid": "MyNetwork", "password": "MyPassword123"}}

Set system text size to 125%:

{"SetTextSize": 125}

List available display resolutions:

{"ListResolutions": true}

Set display resolution to 1920x1080:

{"SetScreenResolution": "1920x1080"}

Set display resolution with specific refresh rate:

{"SetScreenResolution": "1920x1080@144"}

Set display resolution using JSON object:

{"SetScreenResolution": {"width": 2560, "height": 1440, "refreshRate": 60}}

Enable cursor trail with length 7:

{"CursorTrail": "{\"enable\":true,\"length\":7}"}

Disable cursor trail:

{"CursorTrail": "{\"enable\":false}"}

Supported Application Friendly Names

AutoShell recognizes these friendly names (case-insensitive):

  • chrome, edge, microsoft edge
  • word, winword, excel, powerpoint, power point, outlook
  • visual studio, visual studio code
  • notepad, paint, paint 3d, calculator
  • file explorer, control panel, task manager
  • cmd, powershell
  • snipping tool, magnifier
  • spotify, copilot, m365 copilot

Additionally, AutoShell automatically discovers all installed Windows Store applications by their display names.

Architecture

AutoShell uses a handler-based architecture with dependency injection. All platform-specific (P/Invoke, COM, WMI) code is isolated behind service interfaces, keeping handlers thin and fully unit-testable.

A Roslyn source generator (autoShell.Generators) reads the .pas.json schema files at build time and generates strongly-typed C# record classes for each action's parameters. Handlers can use these generated types via AddAction<T> instead of manually extracting fields from JsonElement.

autoShell/
├── AutoShell.cs              # Entry point — stdin/stdout command loop
├── ActionDispatcher.cs       # Routes JSON keys to handlers; Create() wires all dependencies
├── IAppRegistry.cs           # App registry interface (shared across handlers)
├── WindowsAppRegistry.cs     # Maps friendly app names to paths and AppUserModelIDs
├── Handlers/
│   ├── IActionHandler.cs     # Handler interface (SupportedActions + Handle)
│   ├── ActionHandlerBase.cs  # Base class — AddAction/AddAction<T> registration + dispatch
│   ├── AppActionHandler.cs           # LaunchProgram, CloseProgram, ListAppNames
│   ├── AudioActionHandler.cs         # Volume, Mute, RestoreVolume
│   ├── DisplayActionHandler.cs       # SetScreenResolution, ListResolutions, SetTextSize
│   ├── NetworkActionHandler.cs       # ConnectWifi, ToggleAirplaneMode, etc.
│   ├── SystemActionHandler.cs        # Debug, ToggleNotifications
│   ├── ThemeActionHandler.cs         # ApplyTheme, ListThemes, SetThemeMode, SetWallpaper
│   ├── VirtualDesktopActionHandler.cs  # CreateDesktop, SwitchDesktop, PinWindow, etc.
│   ├── WindowActionHandler.cs        # Maximize, Minimize, SwitchTo, Tile
│   └── Settings/
│       ├── SettingsHandlerBase.cs     # Extends ActionHandlerBase with registry patterns
│       ├── AccessibilitySettingsHandler.cs
│       ├── DisplaySettingsHandler.cs
│       ├── FileExplorerSettingsHandler.cs
│       ├── MouseSettingsHandler.cs
│       ├── PersonalizationSettingsHandler.cs
│       ├── PowerSettingsHandler.cs
│       ├── PrivacySettingsHandler.cs
│       ├── SystemSettingsHandler.cs
│       └── TaskbarSettingsHandler.cs
├── Services/                 # Interfaces + Windows implementations
│   ├── IAudioService.cs / WindowsAudioService.cs
│   ├── IBrightnessService.cs / WindowsBrightnessService.cs
│   ├── IDebuggerService.cs / WindowsDebuggerService.cs
│   ├── IDisplayService.cs / WindowsDisplayService.cs
│   ├── INetworkService.cs / WindowsNetworkService.cs
│   ├── IProcessService.cs / WindowsProcessService.cs
│   ├── IRegistryService.cs / WindowsRegistryService.cs
│   ├── ISystemParametersService.cs / WindowsSystemParametersService.cs
│   ├── IVirtualDesktopService.cs / WindowsVirtualDesktopService.cs
│   ├── IWindowService.cs / WindowsWindowService.cs
│   └── Interop/
│       ├── CoreAudioInterop.cs   # COM interop definitions for Windows audio
│       └── UIAutomation.cs       # UI Automation helpers (last-resort)
├── Logging/
│   ├── ILogger.cs            # Logging interface (Error, Warning, Info, Debug)
│   └── ConsoleLogger.cs      # Colored console + diagnostics output
└── autoShell.Tests/          # unit, integration, and E2E tests

autoShell.Generators/         # Roslyn source generator (netstandard2.0)
├── ActionParamsGenerator.cs  # IIncrementalGenerator entry point
├── SchemaParser.cs           # Parses .pas.json → ActionDefinition list
└── RecordEmitter.cs          # Generates C# records from ActionDefinitions

Key design decisions

  • ActionDispatcher.Create() is the composition root — it creates all concrete services and wires them into handlers. Tests bypass this and inject mocks directly.
  • Single handler hierarchy — All handlers inherit from ActionHandlerBase, which provides AddAction(name, handler) and AddAction<T>(name, handler) registration with dictionary-based dispatch. Actions are registered once in the constructor; SupportedActions and Handle() are auto-derived.
  • Source-generated parameter records — The .pas.json schema files in ts/packages/agents/desktop/dist/ are the single source of truth for action definitions. A Roslyn source generator reads them at build time and produces strongly-typed C# records (e.g., MuteParams, VolumeParams) in the autoShell.Handlers.Generated namespace. Handlers use AddAction<T> to get auto-deserialized parameters.
  • SettingsHandlerBase extends ActionHandlerBase with registry-specific convenience methods: AddRegistryToggleAction, AddRegistryMapAction, and AddOpenSettingsAction. These internally delegate to AddAction with wrapper lambdas. Specialized actions use AddSpecializedAction directly.
  • Handlers are thin — they receive typed parameters and delegate to services. No P/Invoke or COM code lives in handlers.
  • Services own all platform calls — P/Invoke, COM, WMI, and registry access are encapsulated behind interfaces (I*Service / Windows*Service).
  • ILogger abstracts all diagnostic output with four levels: Error (red), Warning (yellow), Info (cyan), and Debug (diagnostics only). ConsoleLogger preserves the original colored formatting.

Source generator (autoShell.Generators)

The autoShell.Generators project is a Roslyn incremental source generator that runs automatically during every build of autoShell.csproj. It reads the .pas.json schema files and generates strongly-typed C# parameter records so handlers don't need to manually extract fields from raw JSON.

How it works:

  1. The .pas.json files from ts/packages/agents/desktop/dist/ are included as AdditionalFiles in autoShell.csproj
  2. During compilation, the Roslyn compiler loads autoShell.Generators.dll as an analyzer
  3. ActionParamsGenerator (the IIncrementalGenerator entry point) filters for .pas.json files and passes each to the pipeline
  4. SchemaParser extracts action definitions — action name, parameter names, and types — from the schema JSON structure
  5. RecordEmitter produces C# source for each action, emitting internal record classes with [JsonPropertyName] attributes
  6. The compiler compiles the generated records alongside the hand-written source code

Project structure:

File Purpose
ActionParamsGenerator.cs IIncrementalGenerator entry point — wires the pipeline
SchemaParser.cs Parses .pas.json → list of ActionDefinition (action name + parameter fields)
RecordEmitter.cs Generates C# record source from ActionDefinition list

Generated output:

The generated .g.cs files are emitted to autoShell/Generated/ for inspection (gitignored — they're build artifacts). Each .pas.json schema produces one file:

Schema Generated file Example records
desktopSchema.pas.json desktopSchema.pas.g.cs VolumeParams, MuteParams, LaunchProgramParams
taskbarSchema.pas.json taskbarSchema.pas.g.cs AutoHideTaskbarParams, TaskbarAlignmentParams
displaySchema.pas.json displaySchema.pas.g.cs DisplayScalingParams, RotationLockParams
... ... ...

Type mapping:

.pas.json type C# type Default
number int 0
boolean bool false
string string ""
string-union string ""
type-union resolved inner type varies
Optional field nullable (int?, bool?, string?) null

Constraints:

  • Targets netstandard2.0 (Roslyn requirement for source generators)
  • References Microsoft.CodeAnalysis.CSharp and System.Text.Json as PrivateAssets="all"
  • Referenced by autoShell.csproj as OutputItemType="Analyzer" with ReferenceOutputAssembly="false"

Adding a New Action

This section walks through adding a new action end-to-end. There are three categories of actions, each with a different amount of work required.

Option A: Registry-based settings action (simplest)

For actions that toggle a registry value or map a string parameter to a registry entry, you only need to add a line in an existing settings handler constructor. No new files, no new classes.

Example — adding a new registry toggle:

// In an existing SettingsHandler constructor (e.g., SystemSettingsHandler.cs):
AddRegistryToggleAction("MyNewToggle", new RegistryToggleConfig(
    KeyPath: @"SOFTWARE\Microsoft\Windows\CurrentVersion\MyFeature",
    ValueName: "Enabled",
    ParameterName: "enable",
    OnValue: 1,
    OffValue: 0,
    DisplayName: "My New Feature"
));

That's it. The base class handles parameter extraction, registry writes, and success/failure responses. Other config-driven options:

  • AddRegistryMapAction — maps a string parameter (e.g., "left"/"center") to registry values
  • AddOpenSettingsAction — opens a Windows Settings URI (e.g., ms-settings:display)

Option B: Typed action in an existing handler (most common)

For actions that need custom logic but fit within an existing handler's domain.

1. Define the action in the TypeScript schema (e.g., ts/packages/agents/desktop/src/actionsSchema.ts):

The TypeScript type definitions are the single source of truth. The asc compiler transforms them into .pas.json files, which the Roslyn source generator then reads to produce C# parameter records.

// In the appropriate *Schema.ts file:
export type MyNewAction = {
    actionName: "MyAction";
    parameters: {
        level: number;
        name?: string;
    };
};

Then regenerate the schema:

cd ts/packages/agents/desktop
pnpm run asc:all

After building, this generates:

// Auto-generated in autoShell.Handlers.Generated namespace
internal record MyActionParams
{
    [JsonPropertyName("level")]
    public int Level { get; init; } = 0;

    [JsonPropertyName("name")]
    public string? Name { get; init; } = null;
}

2. Register and handle the action in the appropriate handler:

using autoShell.Handlers.Generated;

internal class AudioActionHandler : ActionHandlerBase
{
    public AudioActionHandler(IAudioService audio)
    {
        // ... existing actions ...
        AddAction<MyActionParams>("MyAction", HandleMyAction);
    }

    private ActionResult HandleMyAction(MyActionParams p)
    {
        // p.Level and p.Name are already deserialized and typed
        return ActionResult.Ok($"Did something with level {p.Level}");
    }
}

That's all the C# you need. The dispatcher automatically discovers the action through the handler's SupportedActions.

Option C: New handler with new service (rare)

For actions that require a new Windows API or a new domain.

1. Define the schema in the TypeScript schema file and run pnpm run asc:all (same as Option B, step 1).

2. Create a service interface and implementation:

// Services/IMyService.cs
internal interface IMyService
{
    void DoSomething(int level);
}

// Services/WindowsMyService.cs
internal class WindowsMyService : IMyService
{
    public void DoSomething(int level)
    {
        // P/Invoke, COM, WMI, etc.
    }
}

3. Create a handler:

// Handlers/MyActionHandler.cs
using autoShell.Handlers.Generated;
using autoShell.Services;

internal class MyActionHandler : ActionHandlerBase
{
    private readonly IMyService _myService;

    public MyActionHandler(IMyService myService)
    {
        _myService = myService;
        AddAction<MyActionParams>("MyAction", HandleMyAction);
    }

    private ActionResult HandleMyAction(MyActionParams p)
    {
        _myService.DoSomething(p.Level);
        return ActionResult.Ok($"Done at level {p.Level}");
    }
}

4. Wire it in ActionDispatcher.Create():

// In ActionDispatcher.cs, Create() method:
dispatcher.Register(
    // ... existing handlers ...
    new MyActionHandler(new WindowsMyService())
);

5. Add the service to the testable Create() overload so tests can inject a mock.

Schema-to-code type mapping

The source generator maps .pas.json types to C# as follows:

Schema type C# type Default value
number int 0
boolean bool false
string string ""
string-union string ""
Optional field nullable (int?, bool?, string?) null

Checklist

  • Action type defined in TypeScript schema (*Schema.ts)
  • Schemas regenerated with pnpm run asc:all
  • Handler method registered with AddAction<T> in the constructor
  • Handler registered in ActionDispatcher.Create() (if new handler)
  • Service interface + implementation created (if new Windows API)
  • Unit tests added for the handler logic
  • dotnet test --filter "Category!=E2E" passes

License

Copyright (c) Microsoft Corporation. Licensed under the MIT License.

Trademarks

This project may contain trademarks or logos for projects, products, or services. Authorized use of Microsoft trademarks or logos is subject to and must follow Microsoft's Trademark & Brand Guidelines.