I lost a six-hour agent run to a closed laptop lid, and that is the whole reason this app exists.
I had a coding agent working through a large refactor. I checked on it, saw it was moving, closed the lid, and went out. When I came back, the run wasn't finished, and it hadn't failed either. It had just stopped somewhere in the middle of a tool call. No error, no stack trace, nothing to debug. Windows had suspended the machine, and my agent went down with it.
So I made a small Windows app to fix that for devs like me who leave long jobs running and walk away. It is called Always Up, it is free, it is open source under MIT, and it is one 62 KB file with no installer and no dependencies.
Here is the problem, why the obvious fixes didn't work for me, and how I ended up solving it.
When you close the lid, Windows does not send your program a polite shutdown signal. It suspends the machine. Your process is no longer scheduled.
That is why the failure looks so strange when you open the lid again:
For a normal app, this is fine. You reopen the lid and carry on. For anything long-running, it is the worst kind of failure, because you get no signal at all about what happened, and you have to start over. I did not start by writing an app. I started by trying to configure my way out of it, the way most of us would.
1. I set the lid action to "Do nothing".
This stops suspend the moment the lid shuts. Then twenty minutes later, the machine hit its idle timeout and slept anyway. An agent that is waiting on an API response looks exactly like an idle machine to Windows. No CPU spike proves otherwise.
2. I used a keep-awake app.
Caffeine-style tools work by making a "keep the system awake" request to Windows. That request is real, and it works, but the lid action ignores it completely. These are two separate policies, and neither one overrides the other. Close the lid, sleep.
3. I turned off sleep in Power Options.
That panel does not reach every setting that matters. Two of the important ones, the unattended sleep timeout and the display off after lock timeout, are not exposed there. On newer laptops that use Modern Standby, which is a low-power idle state instead of true sleep, the machine also drifts down on its own.
The pattern I eventually understood is this: no single setting does what I want. The lid behaviour, the awake request, the idle timeouts, and the unattended timeout are four separate things. You need all of them pointing the same way at the same time.
That's genuinely annoying to set up by hand, and even more annoying to remember to undo. So I built the switch.
One toggle: Keep this PC awake with the lid closed.
Turning it on sets all the involved policies at once. Turning it off, or quitting the app, restores your original settings.
Here is the full list of what it touches, so nothing is hidden:
| What it sets | How it does it |
|---|---|
| Lid close behaviour, set separately for plugged in and on battery | The LIDACTION power setting. "Do nothing" stops the suspend. |
| Keep the system awake | |
SetThreadExecutionState with the system required flag |
|
| Keep displays on | |
SetThreadExecutionState with the display required flag. This is what keeps an external monitor lit. |
|
| Never sleep, hibernate, or blank the display on idle | The idle timeout values set to zero |
| Never sleep unattended | The unattended sleep timeout set to zero |
| Start with Windows | A scheduled task, not a Startup folder shortcut |
The display one mattered more than I expected. On a docked laptop with the lid shut, the external monitor is your only screen. If Windows blanks it, some capture, streaming, and rendering work stalls along with it.
I built it for my own setup first: a laptop on a shelf, lid closed, running agent work overnight. It turned out to cover a set of jobs that all have the same shape:
If you use a desktop, you do not need this. If your laptop only needs to stay awake with the lid open, PowerToys Awake already covers you, and it is a great tool. I built Always Up for the closed-lid case specifically, because that is the one thing nothing else solved in a single switch. I wanted an app I would actually trust running elevated on my own machine, permanently, at startup. That pushed almost every decision toward less.
C# on .NET Framework 4.x. It ships in the box on every Windows 10 and 11 machine, so no one has to download a runtime first.
WinForms with every control painted by hand. No WinUI, no WPF, no control library. That is more work up front, and it is why the whole app is one file with zero dependencies instead of a folder of DLLs.
The power API directly, not powercfg output. This one is worth explaining, because it is the kind of thing you only learn by hitting it. My first instinct was to shell out to
powercfg /query
, read the values, and write them back. That does not work for two reasons. Several of the settings I needed are hidden, so they are readable and writable through the API but are never printed in the query output at all. On top of that, the friendly names powercfg
prints are translated per language, while the underlying identifiers are not. A parser built on that output would break on any non-English Windows install. So the app reads and writes through powrprof.dll
and never parses text.Built with the compiler already on your machine. The build script calls csc.exe
from the in-box .NET Framework. No Visual Studio, no SDK, no package restore. If you would rather not trust a downloaded binary, you can clone the repo, run build.cmd
, and compile it yourself with nothing else installed.
The whole thing is two source files: AlwaysUp.cs
for the logic and `Ui.cs`
for the interface.
This one cost me an evening, and I think it is useful to anyone writing an elevated Windows app.
Always Up runs as administrator, so launching it shows a UAC prompt. If you dismiss that prompt with the keyboard, the key up event lands on the app window the instant it takes focus. There was never a matching key down, because the key was pressed while a different window was in front.
As a result, my app read a stray key up as "the user activated this control" and switched the machine's power settings on by itself at launch. It looked completely random until I traced it.
The fix is small, and I now apply it everywhere: controls that change power settings only fire on a completed gesture. Press and release inside the same control, or key down and key up in the same control. Never on a bare click event, and never on a key up on its own. The window also opens with nothing focused.
If you write elevated WinForms apps, you will run into this eventually. Save yourself the evening. This was the part I cared about most as a user, because these are machine-wide settings and the app is only borrowing them.
The awake request dies with the process. It is tied to the app's own thread, so if Always Up crashes, that request disappears instantly. A crash can never leave your machine stuck awake.
The power settings persist, so the app snapshots your original plugged-in and battery values the first time it changes anything. Restore original power settings when I exit is on by default, and a Restore originals button lets you restore them right now without quitting.
Power settings are machine-wide, so changing them requires elevation. That means a UAC prompt on launch, and I think being suspicious is the right instinct.
So here is the complete list of what the app does with that privilege: it reads and writes the power settings in the table above, it registers or deletes one scheduled task named AlwaysUp
, and it writes a small config file in your local app data folder.
It makes no network connections of any kind. It has no HTTP client, no socket, no update check, and no analytics. The only programs it ever launches are schtasks.exe
for the Start with Windows option and `powercfg`
for a read-only diagnostics dump.
All of that is verifiable. It is two files, the repo is public, and nothing clever is hidden in them.
I would not want anyone to find out this works at hour five of an overnight run, so the app has a Diagnostics button that shows you three things:
powercfg /a
, which tells you which sleep states your machine actually supports.powercfg /requests
, which tells you what is holding the machine awake right now, including other apps.If that first one reports Standby (S0 Low Power Idle), your machine uses Modern Standby, and the lid setting alone genuinely is not enough on that hardware. Leave the "never" options ticked.
My honest advice is to do a ten-minute test before you rely on it. Start a job, close the lid, wait, open it, and confirm the job kept moving. Ten minutes of testing beats losing a six-hour run, which I can tell you about from direct experience.
Finding these out during a long run is worse than reading them now, so:
AlwaysUp.exe
from the That is the whole setup. It lives in the tray; closing the window hides it, and you quit from the tray icon. Tick **Start with Windows** if you want it back at logon, which registers a scheduled task so it starts elevated without prompting you for UAC on every boot.
Repo, source, and issues: [github.com/sudoatif/always-up](https://github.com/sudoatif/always-up)
Can I keep my laptop running with the lid closed?
Yes. You need to change the lid action, the idle sleep timeouts, the unattended sleep timeout, and add a keep-awake request. All four have to agree. Always Up sets them together behind one toggle.
Will my coding agent keep running when I close my laptop?
Not by default. Windows suspends the machine, and your agent stops mid-task without an error. With the lid behaviour and the awake request both set, it keeps running.
Is this different from PowerToys Awake or a caffeine app?
Yes. Those make a keep-awake request, which the lid action ignores. They are good for keeping a machine awake with the lid open. This one is built for the closed lid case.
Does it change my settings permanently?
No. It snapshots your originals the first time it changes anything and restores them when it exits. Restore on exit is on by default, and there is a manual restore button.
Why does it need administrator rights?
Power settings are machine-wide, so writing them requires elevation. The app makes no network connections, and the source is public if you want to check.
Does it work on Modern Standby laptops?
Usually, and the idle timeout settings do real work there. Some manufacturer firmware is aggressive about low-power idle. Run Diagnostics, then test with a real job before relying on it.
I built this because I lost work, and I kept building on it because closing a laptop lid should not quietly kill whatever you left running.
If you run agents, local models, or long jobs on a Windows laptop, test it for ten minutes and see if it holds on your machine. If it does not, open an issue with the Diagnostics dump attached, and I will look at it. That dump answers most of the questions before anyone has to guess.