Skip to content

aporonaut/Envoke

Repository files navigation

Envoke

PowerShell 5.1+ Windows 10 | 11

Envoke, the portmanteau of Environment and Invoke, automatically launches and arranges your desktop applications at Windows startup. Define your apps and time-of-day schedules in a single JSON config, and Envoke selects the right set for the moment; work hours, home hours, or any custom profile you create.

Key features:

  • Config-driven - define apps and schedules in one JSON file, no scripting required
  • Environment switching - auto-selects Work, Home, or any custom profile based on day and hour
  • Parallel launching - apps in the same priority group launch concurrently on PowerShell 7+
  • Window maximization - each app's window is detected and maximized after launch
  • One run per boot - a registry-based boot guard prevents duplicate launches

Table of Contents


Quick Start

1. Install the module.

Install-Module Envoke -Scope CurrentUser

Or clone the repository directly:

git clone https://github.com/aporonaut/Envoke.git
cd Envoke

2. Configure your apps.

copy Envoke\config.example.jsonc Envoke\config.json

Open Envoke\config.json in a text editor, remove all comment lines (lines starting with //), and replace the placeholder paths with your actual app paths.

Important: ConvertFrom-Json does not support JSONC comments. Remove all // lines before saving, or the config will fail to parse.

See Envoke/config.example.jsonc for the full annotated template with examples for every app type.

3. Set up Task Scheduler.

schtasks /Create /XML "EnvokeTask.xml" /TN "Envoke"

After import, open Task Scheduler (taskschd.msc), find the Envoke task, go to the Actions tab, and update the path in the Arguments field to point to your actual Envoke.vbs location.

4. Verify your setup.

Import-Module .\Envoke\Envoke.psd1
Test-EnvkInstallation

A table of check results appears with Pass/Fail/Warn status and actionable messages for any issues found.

Prerequisites
Requirement Details
Operating System Windows 10 or Windows 11
PowerShell 5.1 Included with Windows - no installation needed
PowerShell 7+ (optional) Enables parallel app launching

Check your PowerShell version:

$PSVersionTable.PSVersion

Install PowerShell 7+ (optional):

winget install --id Microsoft.PowerShell --source winget

If you have PowerShell 5.1 only, everything works - apps just launch sequentially instead of in parallel.


Configuration

Configuration lives in a single JSON file: Envoke\config.json.

Create your config from the template:

copy Envoke\config.example.jsonc Envoke\config.json

Open the file, remove all // comment lines (required - JSON does not support comments), and fill in your app paths.

VS Code tip: The $schema field in the config enables IntelliSense, autocomplete, and inline validation while editing. Keep that line in your config.json.

See Envoke/config.example.jsonc for a fully commented template with examples for every app type - standard Win32 apps, UWP/Store apps, Electron apps, and background apps.

Config structure overview

Config structure overview

The config has three top-level sections:

settings (optional) - global behavior controls:

  • windowTimeoutSeconds: how long to wait for each app's window to appear (default: 120)
  • parallelLimit: max concurrent app launches per priority group on PS 7+ (default: 5)
  • forceSequential: set to true to always launch apps one at a time (default: false)

apps - the application catalog. Define each app once with its path, process name, and default arguments. Apps referenced by multiple environments are listed here once.

environments - named launch profiles. Each environment lists which apps to launch (by name from the catalog) and optionally when to activate (by day and hour). An environment without a schedule block is the fallback - it activates when no scheduled environment matches.

Environment selection logic

Environment selection logic

When the script runs at boot, it evaluates each environment's schedule against the current day and hour:

  • If the current day is in the environment's days list and the current hour is between startHour and endHour, that environment is selected.
  • If no scheduled environment matches, the fallback environment (no schedule block) is selected.
  • If multiple environments match, the priority field on the environment resolves the overlap - higher priority wins. If priorities tie, the first match by config order is used.

App Discovery Reference

When configuring apps, you need three things: the file path to launch it, the process name for window detection, and for UWP/Store apps, the AppUserModelId. Use the commands below to find each.

Find an app's file path

Apps on the system PATH (e.g., explorer.exe):

Get-Command app.exe | Select-Object Source

Apps installed via Start Menu shortcut (resolves the .lnk to the actual .exe):

$shortcut = Get-ChildItem "$env:APPDATA\Microsoft\Windows\Start Menu" -Recurse -Filter "*AppName*.lnk" | Select-Object -First 1
(New-Object -ComObject WScript.Shell).CreateShortcut($shortcut.FullName).TargetPath

Verify a file path exists:

Test-Path "C:\path\to\app.exe"

Find an app's process name

Launch the app, then run:

Get-Process | Where-Object { $_.MainWindowTitle -ne '' } | Select-Object ProcessName, MainWindowTitle | Format-Table -AutoSize

The ProcessName column is what you put in the processName field in the config.

Electron apps (VS Code, Teams, Slack, ClickUp, etc.) often spawn a child process with a different name than the launcher executable. Always verify with the command above - use the name from ProcessName, not the .exe file name.

Find a UWP / Store app's AppUserModelId

Microsoft Store apps use a special path format: shell:AppsFolder\{AppUserModelId}.

Get-StartApps | Where-Object { $_.Name -like '*AppName*' }

Example output:

Name      AppID
----      -----
Teams     MSTeams_8wekyb3d8bbwe!MSTeams

In your config, use:

"path": "shell:AppsFolder\\MSTeams_8wekyb3d8bbwe!MSTeams"

Quick reference

What you need Command
File path (PATH apps) Get-Command app.exe | Select-Object Source
File path (Start Menu shortcut) See Find an app's file path above
Process name Get-Process | Where-Object { $_.MainWindowTitle -ne '' } | Select-Object ProcessName, MainWindowTitle
UWP / Store AppUserModelId Get-StartApps | Where-Object { $_.Name -like '*AppName*' }
Verify file path Test-Path "C:\path\to\app.exe"
Verify PATH executable Get-Command app.exe -ErrorAction SilentlyContinue

Task Scheduler Setup

Envoke runs at Windows logon via Task Scheduler. There are two ways to set it up.

Option A: Import XML (recommended)

1. Import the template:

schtasks /Create /XML "C:\path\to\repo\EnvokeTask.xml" /TN "Envoke"

Replace C:\path\to\repo with the actual path to your cloned repository.

2. Update the VBS path:

The imported task uses a placeholder path. You must update it:

  1. Open Task Scheduler: press Win+R, type taskschd.msc, press Enter
  2. In the left panel, click Task Scheduler Library
  3. Find and double-click the Envoke task
  4. Click the Actions tab
  5. Select the action and click Edit
  6. In the Arguments field, replace the placeholder path with your actual path: "C:\Users\YourName\Documents\Envoke\Envoke.vbs"
  7. Click OK on all dialogs

Task Scheduler Actions tab

What the XML configures:

  • Trigger: at user logon, with a 30-second delay to let the desktop fully load
  • Action: wscript.exe calling Envoke.vbs (windowless execution)
  • No administrator rights required

Option B: Manual setup

Click to expand manual Task Scheduler setup
  1. Open Task Scheduler: Win+R -> taskschd.msc -> Enter
  2. In the Actions panel (right side), click Create Task (not "Create Basic Task")
  3. General tab:
    • Name: Envoke
    • Ensure "Run only when user is logged on" is checked (no elevation needed)
  4. Triggers tab: Click New
    • Begin the task: At log on
    • Specific user: your account
    • Check Delay task for: 30 seconds
    • Click OK
  5. Actions tab: Click New
    • Action: Start a program
    • Program/script: wscript.exe
    • Add arguments: "C:\path\to\your\Envoke.vbs"
    • Click OK
  6. Conditions tab:
    • Uncheck "Stop if the computer switches to battery power"
  7. Settings tab:
    • Check "Allow task to be run on demand"
    • If task is already running: Do not start a new instance
  8. Click OK to save

Why the VBS wrapper?

The Task Scheduler action calls wscript.exe Envoke.vbs rather than powershell.exe Envoke.ps1 directly. This is intentional: the -WindowStyle Hidden flag in Task Scheduler is unreliable and often shows a brief PowerShell window at logon. The VBS wrapper (wscript.exe + window style 0) reliably suppresses the window every time.

The VBS wrapper also includes the required PowerShell flags so you never need to edit it:

  • -STA - required by UIAutomationClient for window detection
  • -NonInteractive - suppresses prompts that would block a windowless process
  • -ExecutionPolicy Bypass - prevents execution policy from blocking the script

Manual Testing

Before relying on Task Scheduler, test the script directly from a PowerShell prompt.

Test Work environment (bypasses boot guard, does not affect registry):

.\Envoke.ps1 -SkipBootGuard -Environment Work

Test Home environment:

.\Envoke.ps1 -SkipBootGuard -Environment Home

Parameters:

Parameter Type Description
-ConfigPath String Path to a custom config file. Omit to use the default search order.
-Environment String Force a specific environment (e.g., Work, Home). Omit for automatic schedule-based selection.
-SkipBootGuard Switch Bypass the boot guard; allow repeated runs without affecting boot-session tracking.
-EnableDebug Switch Enable DEBUG-level log entries for verbose output. Use with -SkipBootGuard for test runs.
-Sequential Switch Force sequential app launching regardless of PS version or config settings. Useful for troubleshooting.

What to look for when testing:

  • Each configured app should launch and its window should maximize
  • The log file updates at $env:LOCALAPPDATA\Envoke\Logs\
  • No error messages appear in the console output

Tips and FAQ

How do I add a new app?

  1. Add an entry to the apps catalog in config.json with its path, processName, and arguments
  2. Add a reference to the app in the desired environment's apps list
  3. See Envoke/config.example.jsonc for examples of each app type

How do I add a custom environment?

Add a new key to the environments block with a schedule (or omit it for a fallback). Example:

"Evening": {
  "schedule": {
    "days": ["Monday", "Tuesday", "Wednesday", "Thursday", "Friday"],
    "startHour": 18,
    "endHour": 23
  },
  "apps": [
    { "name": "Browser" },
    { "name": "ChatApp" }
  ]
}

Can I have overlapping schedules?

Yes. When multiple environments match the current day and hour, the environment-level priority field resolves the overlap - higher priority wins. If priorities tie, the first match by config order is used. In interactive debug mode, you are prompted to choose.

How do I disable parallel launching?

Set "forceSequential": true in the settings block of your config, or pass -Sequential to Envoke.ps1 when testing.

The config fails to parse - what's wrong?

The most common cause is leaving // comment lines in config.json. Remove all lines starting with //. Only pure JSON is valid; JSONC comments are not supported by ConvertFrom-Json.


Troubleshooting

Task Scheduler fires but nothing happens.

The VBS path in the Task Scheduler action is wrong. Open Task Scheduler, find the Envoke task, go to the Actions tab, and verify the path in the Arguments field matches your actual Envoke.vbs location.

Apps launch but windows do not maximize.

The -STA flag is missing from the PowerShell invocation. If you are running the VBS wrapper via Task Scheduler, this flag is already included - check that the task is actually calling wscript.exe Envoke.vbs and not powershell.exe directly. If running PowerShell directly in a test, add -STA to your PowerShell invocation.

"Module not found" error in the log.

The Envoke\ module folder must be in the same directory as Envoke.ps1. Verify the folder structure is intact and that you have not moved any files out of the cloned repo folder.

Task fires too early - apps fail before the desktop is ready.

Increase the startup delay in the Task Scheduler trigger. The included XML uses 30 seconds. For slower machines or cold boots:

  1. Open Task Scheduler -> double-click Envoke
  2. Go to the Triggers tab -> edit the logon trigger
  3. Increase the delay to 60 seconds (or more if needed)

App path not found.

Verify the path exists:

Test-Path "C:\path\to\your\app.exe"

For UWP apps, verify the AppUserModelId:

Get-StartApps | Where-Object { $_.Name -like '*AppName*' }

The boot guard is preventing a re-run during testing.

By design, the script only runs once per boot session. For repeated testing, use -SkipBootGuard:

.\Envoke.ps1 -SkipBootGuard -Environment Work

Where is the log file?

explorer $env:LOCALAPPDATA\Envoke\Logs

The log file name includes the date; logs older than 30 days are rotated automatically.


Verifying Your Setup

After configuring the app and setting up Task Scheduler, run the built-in diagnostic:

Import-Module .\Envoke\Envoke.psd1
Test-EnvkInstallation

Test-EnvkInstallation output

The function checks four areas and prints a summary table:

Area What is checked
Module PS version, UIAutomationClient assembly
Config File exists, parses as valid JSON, app paths resolve
Task Scheduler Envoke task exists with correct trigger
Permissions Log directory is writable, registry path is accessible

Each check reports Pass, Fail, or Warn with a message explaining what to do if anything is not right.

To check a config file in a non-default location:

Test-EnvkInstallation -ConfigPath "D:\MyConfigs\config.json"

Project Structure

Envoke/
├── Envoke.ps1                   Entry point - imports the module and calls Invoke-EnvkStartup
├── Envoke.vbs                   VBS wrapper - called by wscript.exe from Task Scheduler at logon
├── EnvokeTask.xml               Importable Task Scheduler task template
└── Envoke/
    ├── Envoke.psd1              Module manifest (lists all exported functions)
    ├── config.example.jsonc     Fully annotated configuration template
    ├── config.schema.json       JSON Schema - enables VS Code IntelliSense when editing config
    ├── Public/                  Exported functions (Test-EnvkInstallation, Invoke-EnvkStartup, etc.)
    └── Private/                 Internal helpers (not imported into your session)

The structure above reflects the repository layout. When installed via Install-Module, the module lands in the standard PowerShell module path ($env:PSModulePath).


Acknowledgments

Claude Code GSD @glittercowboy

Envoke was designed and prototyped by hand, then enhanced and productionized with Claude Code as structured by the GSD workflow system, created by TÂCHES (@glittercowboy).

GSD is a lightweight and powerful meta-prompting, context engineering, and spec-driven development system for Claude Code. I've used this project (Envoke) to test a few other similar systems, GSD is the one I liked most in terms of software engineering completeness.

It works for both greenfield and brownfield projects, minimises context rot, and methodically goes through a discuss → research → plan → execute → test → debug cycle repeating through phases that break the project down into targeted contexts.

If you build with Claude Code, it's worth a look.


License / Contributing

This project is licensed under the MIT License - free to use, modify, and distribute with attribution.

Contributions are welcome. To get started:

  • Report a bug - open an issue with steps to reproduce and your PowerShell version ($PSVersionTable.PSVersion)
  • Request a feature - open an issue describing the use case before writing code
  • Submit a PR - fork the repo, make your changes, and open a pull request against main

Before submitting a PR:

  • Test your changes manually with -SkipBootGuard -Environment Work and -Environment Home
  • Follow existing code patterns - PascalCase Verb-Noun functions, comment-based help on public functions, Write-EnvkLog for output
  • Keep scope focused - one fix or feature per PR

AlAnsari

About

PowerShell automation that launches and manages desktop applications on Windows boot based on time-of-day environment detection

Topics

Resources

License

Stars

Watchers

Forks

Packages

 
 
 

Contributors