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.- Enable the Windows Hypervisor Platform:
- Install
sbx: - Run the host prep step:
- Log in to Docker:
- Initialize the network policy preset. It is required before the first
sandbox, otherwise
sbx createblocks on an interactive prompt: - Register provider credentials used by the sandboxed agent (see
Providers):
- Record the installed version. Celly targets
sbx>= 0.45.0:
2. Build and configure the bot
- Install the pinned Node version (24.x) and clone the repository.
- Copy
.env.exampleto.envand fill inDISCORD_TOKENandDISCORD_GUILD_ID. See Configuration for the full variable list. - Install dependencies and build:
- Run the bot once in the foreground to confirm it boots:
On boot it performs a preflight (
sbx version, policy check, single-instance lock) and fails fast with an actionable message. Logs are written todata/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’ssbx 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.-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:
Option B: Task Scheduler GUI
- Open Task Scheduler and choose Create Task (not “Basic Task”).
- General: name it
Celly; select Run only when user is logged on. - Triggers: add At log on, scoped to the user who owns
sbx. - Actions: Start a program with:
- Program/script: the full path to
node.exe(for exampleC:\Program Files\nodejs\node.exe). - Add arguments:
dist\index.js. - Start in: the repository root.
- Program/script: the full path to
- Settings: uncheck Stop the task if it runs longer than…, and enable If the task fails, restart every 1 minute (up to 3 times).
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).
- Create a Docker PAT: sign in at https://hub.docker.com, open Account settings → Personal access tokens, and create a token with at least read access.
- Feed the token to
sbxover 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: - Verify:
- If the bot is already running, restart the scheduled task so the daemon
picks up the new credential:
.env.
5. Verifying a deployment
sbx diagnosereports a healthy install, daemon, and authentication.sbx policy lsshows thebalancedpreset as the floor.node scripts/smoke.mjs C:\path\to\a\project\dirprintssmoke OK(full chain: create → bootstrap → serve → health → create session → prompt → abort → stop → remove, with teardown on failure).- After an at-logon start,
data/bot.logshows the preflight passing and the Discord client logging in.
6. Troubleshooting
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 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_DIRcloud-sync warning are backlog. KeepDATA_DIRoutside 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.