Skip to main content
.env is the single source of truth. It is loaded automatically at startup (process.loadEnvFile), is gitignored, and is validated at boot. A missing or invalid required value fails fast with an actionable error. Start from .env.example and set the two required values. Everything else has a working default:

Variables

DEFAULT_MODEL and DEFAULT_AGENT are seeded into the settings table on the first boot only. Once a value exists there, it is authoritative and re-reading .env will not overwrite it.

PROJECTS_ROOT and path containment

PROJECTS_ROOT is the only directory Celly will mount. A project’s host directory must resolve (realpath, case-insensitive) to a path inside PROJECTS_ROOT. Anything outside is rejected before a sandbox is created. On top of containment, a sensitive-path denylist rejects any project directory that overlaps:
  • The bot repository itself (process.cwd()).
  • DATA_DIR.
  • Under the user profile: .ssh, .aws, .gnupg, .config, .docker, .kube, .azure, .npmrc, .netrc, .celly, and AppData.
  • System directories (C:\Windows, System32, Program Files, ProgramData, or /etc, /usr, /bin, /sbin, /var, /opt, /System, /Library on POSIX).
Because containment is checked both ways, you also cannot register a parent of PROJECTS_ROOT or of any denied path. PROJECTS_ROOT is intentionally not runtime-editable; changing it means editing .env and restarting.
Keep secrets out of project directories. A mounted project is treated as untrusted content, and the agent can read anything inside it (git remotes, .env files, tokens). Use the sandbox credential proxy instead of committing credentials.

DATA_DIR

DATA_DIR holds the SQLite database (bot.db), the rotating log (bot.log), per-project server logs (logs/<sandbox>.log), and the single-instance lock. It is gitignored and created on boot.
Keep DATA_DIR outside OneDrive/Dropbox-style synced folders. Cloud-sync detection is not implemented in v1, so this is on you.