# Ajar for Windows and Linux

Close the lid. Keep working. Ajar keeps a laptop awake with the lid shut while AI agents (Claude Code, Codex, Gemini CLI, Cursor Agent, Aider, OpenCode, Ollama and others) are working, saves battery while it's shut, and lets it sleep once the work stops.

Same product and settings file as the Mac app. Windows 10/11 and Linux with systemd (Ubuntu 20.04+, Debian 11+, Fedora 32+, Arch, Mint, Pop!_OS and similar), x86-64.

## Install

**Windows:** unzip `Ajar-windows-x86_64.zip` into a folder you'll keep (for example `C:\Users\you\Apps\Ajar`) and run `ajar-app.exe`. It appears in the system tray. Windows SmartScreen may warn because the app isn't code-signed yet: More info › Run anyway. Turn on Settings › Open at login in Ajar's menu.

**Linux:** `tar xf ajar-linux-x86_64.tar.gz && ./ajar-linux-x86_64/install.sh`. No root needed. The tray icon needs the AppIndicator library (the installer tells you the package name if it's missing); on GNOME also the "AppIndicator and KStatusNotifierItem Support" extension.

## What it does

- **When Busy** (default): awake only while an agent is working, or a command an agent started is still running (a build, a test run), plus anything you add under *Also While These Run* (Blender, ffmpeg, a Python training script…). After work stops it waits the quiet time you chose (5 min by default), then lets the laptop sleep; with the lid already shut it puts it to sleep.
- **Always**: forever, for an hour, or until 07:00. **Off**: never (holds from `ajar run` and agents still work).
- **While closed**: Max Battery pauses messaging apps and slows browsers; Balanced slows browsers, chat and music; Full Speed leaves everything alone. Only apps on a fixed list are ever touched, never the desktop or anything an agent depends on (its whole process tree and the apps above it).
- **Limits**: stops at your battery limit (15% default) and, on Linux, if it gets too hot. Only the menu can loosen these; agents, the phone and settings-file edits can't.
- **Let It Sleep Now**: ends holds and timers; agents can't keep it awake until the lid next opens.
- **Phone control** (Settings › Phone control): a QR code pairs your phone with a small control page that works from anywhere. Messages go through ntfy.sh end-to-end encrypted (AES-256-GCM, key only in the QR code).
- **Phone alerts** (ntfy): a notification when an agent goes idle and when the lid opens after a session.

## Command line and agents

```
ajar                          what it's doing
ajar run -- npm test          awake exactly as long as the command runs
ajar on 90 | on until 7 | auto | off | sleep
ajar watch blender            also stay awake while Blender is busy
ajar rule chrome pause        per-app rule while the lid is closed
ajar doctor                   health check: what Ajar has changed right now, watchdog, setup
ajar rescue                   put back everything Ajar changed, even if the app is stuck
ajar mcp-setup                commands to add Ajar's MCP server to Claude Code, Codex, Gemini
```

MCP tools: `status`, `stay_awake`, `release`, `set_mode`, `set_preset`, `set_app_rule`, `watch_app`, `energy`, `set_setting`. A hold made through MCP ends when that agent session ends.

## How it keeps working with the lid shut

| | Windows | Linux |
|---|---|---|
| Stay awake | Power requests (shown in `powercfg /requests` as "Ajar: …"), released by Windows if Ajar exits | logind inhibitor lock (sleep, idle, lid switch), released by the kernel if Ajar exits; GNOME/KDE session inhibitors too |
| Lid closed | Sets the plan's "When I close the lid" to Do nothing while holding, puts your setting back after | logind ignores the lid while the lock is held |
| Sleep when done | Restores your lid setting, then sleeps (Modern Standby: turns the screen off) | logind Suspend |
| Slow an app | Idle priority + Efficiency mode (EcoQoS) | CPU limit on the app's own systemd unit; falls back to nice only when it can be undone |
| Pause an app | NtSuspendProcess / resume | SIGSTOP / SIGCONT |
| Low power while closed | Power mode: best power efficiency | power-profiles-daemon: power-saver |
| Watchdog | Task Scheduler, every minute, also on battery | systemd user timer, every minute |

Every change to an app or setting is written to disk before it's made. If Ajar crashes, the watchdog (or Ajar's next start) puts everything back; anything that can't be put back stays recorded, shows in the menu and `ajar doctor`, and is retried. Apps are only touched if they're provably the same process (pid, start time and program name all match).

## Known limits

- **Windows lid setting**: it's a stored power-plan setting, so if Ajar is killed while holding, closing the lid won't sleep until the watchdog (within a minute) or Ajar's next start restores it. Work or school PCs may block changing it; Ajar then says so.
- **Windows heat guard**: Windows has no temperature reading without admin rights, so the heat guard is Linux-only.
- **KDE Plasma** handles the lid itself. Set System Settings › Power Management › When laptop lid closed to "Do nothing"; Ajar then sleeps the laptop on close whenever nothing is working (and not while an external monitor is connected). Ajar shows a note until this is set.
- **Activity detection** is CPU use, transcript writes and running commands. An agent waiting a long time on a slow remote response with nothing running can look idle; use `ajar run`, the MCP `stay_awake` tool, or a longer quiet time for those.
- **"Went idle"** means no activity, not success: Ajar can't tell a finished task from a crash or a question waiting for you.
- **Battery hours** are estimates. Until Ajar has measured this laptop with the lid shut, the figure is marked "rough".
- **Same-user programs**: anything running as you could still stop Ajar or change its files. The safety rules stop accidental and agent-driven loosening, not deliberate attacks.
- **Phone control** uses the phone page at https://12alexanderbell-graham.github.io/ajar/remote/ (a copy is included as `panel.html`; to host your own, set `panelUrl` in remote.json). The relay (ntfy.sh) has small free limits, and Ajar only sends when the phone asks.

## Building

```
cargo test                                               # 86 unit tests (engine runs against a mock OS)
cargo build --release --target x86_64-pc-windows-gnu     # Windows, from Linux with mingw
cargo zigbuild --release --target x86_64-unknown-linux-gnu.2.31   # Linux, runs on glibc 2.30+
tests/e2e-linux.sh                                       # 44 end-to-end checks against a fake logind
```
