> ## Documentation Index
> Fetch the complete documentation index at: https://celly.agub.dev/llms.txt
> Use this file to discover all available pages before exploring further.

# Deployment on Windows

> Run Celly as a long-lived service on a Windows 11 host, with Task Scheduler at logon and the PAT headless re-login flow.

This guide covers running Celly as a long-lived service on a Windows 11 host,
including Task Scheduler setup and the personal-access-token (PAT) flow for
re-authenticating `sbx` without an interactive browser.

The bot **must** run as the logged-in user on the host: the `sbx` daemon and its
credentials are per-user, and only the host can invoke the `sbx` CLI. NSSM or a
LocalSystem service will not work.

## 1. One-time host bootstrap

Run these steps once, in order, as the user who will own the bot. Steps 1–2 need
an elevated PowerShell prompt; the rest run as the normal user.

1. Enable the Windows Hypervisor Platform:
   ```powershell theme={null}
   Enable-WindowsOptionalFeature -Online -FeatureName HypervisorPlatform -All
   ```
2. Install `sbx`:
   ```powershell theme={null}
   winget install -h Docker.sbx
   ```
3. Run the host prep step:
   ```powershell theme={null}
   sbx setup
   ```
4. Log in to Docker:
   ```powershell theme={null}
   sbx login
   ```
5. Initialize the network policy preset. It is required before the first
   sandbox, otherwise `sbx create` blocks on an interactive prompt:
   ```powershell theme={null}
   sbx policy init balanced
   ```
6. Register provider credentials used by the sandboxed agent (see
   [Providers](/guides/providers)):
   ```powershell theme={null}
   sbx secret set <provider>
   ```
7. Record the installed version. Celly targets `sbx` >= 0.45.0:
   ```powershell theme={null}
   sbx version
   ```

## 2. Build and configure the bot

1. Install the pinned Node version (24.x) and clone the repository.
2. Copy `.env.example` to `.env` and fill in `DISCORD_TOKEN` and
   `DISCORD_GUILD_ID`. See [Configuration](/guides/configuration) for the full
   variable list.
3. Install dependencies and build:
   ```powershell theme={null}
   npm ci
   npm run build
   ```
4. Run the bot once in the foreground to confirm it boots:
   ```powershell theme={null}
   node dist/index.js
   ```
   On boot it performs a preflight (`sbx version`, policy check, single-instance
   lock) and fails fast with an actionable message. Logs are written to
   `data/bot.log`.

## 3. Task Scheduler at logon

The task must run **only when the user is logged on**. Do not choose "Run
whether user is logged on or not": that option requires storing the account
password and can start the task outside the user's `sbx` session.

### Option A: PowerShell (recommended)

Run the following in a normal (non-elevated) PowerShell prompt. It registers a
task that starts Node with the repo as its working directory, never times out,
and restarts on failure.

```powershell theme={null}
$node    = (Get-Command node).Source
$repo    = "C:\Users\artur\projects\discordAI"
$action  = New-ScheduledTaskAction -Execute $node -Argument "dist\index.js" -WorkingDirectory $repo
$trigger = New-ScheduledTaskTrigger -AtLogOn -User $env:USERNAME
$settings = New-ScheduledTaskSettingsSet `
  -AllowStartIfOnBatteries -DontStopIfGoingOnBatteries `
  -ExecutionTimeLimit ([TimeSpan]::Zero) `
  -RestartCount 3 -RestartInterval (New-TimeSpan -Minutes 1)
Register-ScheduledTask -TaskName "Celly" -Action $action -Trigger $trigger `
  -Settings $settings -Description "Celly Discord bot" -Force
```

`-ExecutionTimeLimit ([TimeSpan]::Zero)` clears the default 72-hour limit so the
bot is not killed. Adjust `$repo` to the clone location.

To inspect, run, or remove the task:

```powershell theme={null}
Get-ScheduledTask -TaskName Celly | Get-ScheduledTaskInfo
Start-ScheduledTask -TaskName Celly
Unregister-ScheduledTask -TaskName Celly -Confirm:$false
```

### Option B: Task Scheduler GUI

1. Open **Task Scheduler** and choose **Create Task** (not "Basic Task").
2. **General:** name it `Celly`; select **Run only when user is logged on**.
3. **Triggers:** add **At log on**, scoped to the user who owns `sbx`.
4. **Actions:** **Start a program** with:
   * Program/script: the full path to `node.exe` (for example
     `C:\Program Files\nodejs\node.exe`).
   * Add arguments: `dist\index.js`.
   * Start in: the repository root.
5. **Settings:** uncheck **Stop the task if it runs longer than…**, and enable
   **If the task fails, restart every** 1 minute (up to 3 times).

The bot's single-instance lock prevents a second copy from double-driving
sandboxes, so a logon and a manual start cannot both run.

## 4. PAT headless re-login

`sbx` normally signs in through an interactive browser. On a headless or
re-login scenario (for example, the machine reboots and the user session starts
without a browser, or the stored credential expires), the at-logon task starts
but `sbx` is not authenticated. Re-authenticate non-interactively with a Docker
**personal access token** (PAT).

1. Create a Docker PAT: sign in at [https://hub.docker.com](https://hub.docker.com),
   open **Account settings → Personal access tokens**, and create a token with
   at least read access.
2. Feed the token to `sbx` over stdin with `--password-stdin`. Never pass the
   token as a command-line argument, where it would be visible in the process
   list and PowerShell history:
   ```powershell theme={null}
   $pat   = Read-Host "Docker PAT" -AsSecureString
   $plain = [Runtime.InteropServices.Marshal]::PtrToStringAuto(
              [Runtime.InteropServices.Marshal]::SecureStringToBSTR($pat))
   $plain | sbx login --username <docker-username> --password-stdin
   Remove-Variable plain
   ```
3. Verify:
   ```powershell theme={null}
   sbx diagnose
   ```
4. If the bot is already running, restart the scheduled task so the daemon
   picks up the new credential:
   ```powershell theme={null}
   Restart-ScheduledTask -TaskName Celly
   ```

Store the PAT the same way you store other host secrets (for example, Windows
Credential Manager) if you need to automate this step; do not commit it or put
it in `.env`.

## 5. Verifying a deployment

* `sbx diagnose` reports a healthy install, daemon, and authentication.
* `sbx policy ls` shows the `balanced` preset as the floor.
* `node scripts/smoke.mjs C:\path\to\a\project\dir` prints `smoke OK` (full
  chain: create → bootstrap → serve → health → create session → prompt →
  abort → stop → remove, with teardown on failure).
* After an at-logon start, `data/bot.log` shows the preflight passing and the
  Discord client logging in.

## 6. Troubleshooting

| Symptom                            | Cause                                                    | Fix                                                                                   |
| ---------------------------------- | -------------------------------------------------------- | ------------------------------------------------------------------------------------- |
| Boot fails: `sbx CLI not found`    | `sbx` not on the user's PATH                             | Reinstall with `winget install -h Docker.sbx`; open a new shell.                      |
| Boot fails: `run sbx login`        | Expired/unauthenticated session                          | Run the PAT flow in section 4.                                                        |
| `sbx create` hangs                 | Policy preset not initialized                            | Run `sbx policy init balanced`.                                                       |
| Bot exits: `already running`       | A second instance holds the lock                         | Stop the other process or the duplicate scheduled task.                               |
| Task starts but nothing happens    | Task configured as LocalSystem / "run whether logged on" | Recreate the task as "Run only when user is logged on".                               |
| Sandboxes not stopped after reboot | Expected                                                 | Sandboxes stop automatically when idle; the next prompt wakes them via `ensureReady`. |

## 7. Sensitive paths

`PROJECTS_ROOT` may live under the user profile (the default is
`%USERPROFILE%\Celly\projects`). The sensitive-path denylist rejects specific
sensitive subtrees (`.ssh`, `.aws`, `.gnupg`, `.config`, `.docker`, `.kube`,
`.azure`, `.npmrc`, `.netrc`, `.celly`, `AppData`), `DATA_DIR`, the bot
repository, and system directories, so keep projects out of those. See
[Configuration](/guides/configuration) for the complete list.

## 8. Limitations to plan around

* **The in-memory message queue is lost on bot restart.** Active runs are
  re-attached from session history, but queued-but-unsent prompts are dropped.
* **Role configuration accepts role IDs only**, not role names.
* **The finalization token/duration footer is descoped.**
* **Per-user command rate limiting, sandbox disk-usage warnings, and the
  `DATA_DIR` cloud-sync warning are backlog.** Keep `DATA_DIR` outside any
  OneDrive/Dropbox-synced folder yourself.
* The smoke script (`node scripts/smoke.mjs`) and live Discord interactions are
  host-only and are not exercised by the Linux test suite.

Deferred commands and features are listed in the
[commands reference](/reference/commands) and the
[changelog](/changelog).
