// Linux light profile — the platform without the self-hosted estate around it. // // For a machine that should run the file browser, the terminal and Claude/opencode chat, and nothing // else. Paired with `OFFICER_PROFILE=light bash scripts/setup.sh`, which installs only what these // processes need: node, bun, ffmpeg, Postgres, pm2 and the two agent CLIs. // // This is a subset of ecosystem.config.cjs, not a copy of it — see ecosystem.profile.cjs for why, and // for the two checks that make a drifted profile fail loudly instead of silently starting less than it // claims. To change what runs, edit INCLUDE. To change HOW something runs, edit ecosystem.config.cjs // and every profile follows. // // The app itself is unchanged: every API route stays mounted, so features whose sidecars are absent // report themselves unavailable rather than disappearing. A profile decides which processes start, not // which code ships. // // Start with: pm2 startOrRestart ecosystem.light.config.cjs const { defineProfile } = require('./ecosystem.profile.cjs'); module.exports = defineProfile({ file: 'ecosystem.light.config.cjs', include: [ 'officer', // the app: SPA, /api, websockets 'officer-anthropic-proxy', // holds the Anthropic credential, forwards upstream 'officer-agent', // spawns `claude` — chat is dead without it 'officer-opencode', // the alternative agent 'officer-pty', // the terminal ], // Excluded by CHOICE rather than by platform limits — every one of these would run on a Linux host. // A light install simply is not running the thing behind it. excluded: { // Was in the baseline until 2026-08-11, on the reasoning that it fronts a REMOTE instance and so needs // nothing installed locally. True, and beside the point: a baseline process appears in the Permissions // screen and the dock whether or not anyone has given it a URL, so a fresh server offered to grant Gitea // access to an instance that did not exist. It is installable now — `existing` mode, URL and token — which // makes "is Gitea here" one question with one answer instead of two that disagree. 'officer-gitea': 'fronts a remote instance; installed from the app store with its URL and token', 'officer-vnc': 'no desktop to mirror on a light install', 'officer-email': 'needs the mbsync/IMAP stack the light profile does not install', 'officer-music': 'the ffprobe indexer works, but a full library index is not a light-install concern', 'officer-vault': 'reverse-proxies a self-hosted Vaultwarden container', 'officer-slskd': 'supervises the slskd daemon', 'officer-headscale': 'fronts a headscale server', 'officer-transmission': 'fronts a transmission daemon', 'officer-invoiceshelf': 'fronts an InvoiceShelf container', 'officer-jellyfin': 'fronts a Jellyfin container', 'officer-memos': 'needs an owner-configured Memos instance URL and token', 'officer-photos': 'needs an owner-configured Immich instance URL and API key', 'officer-caldav': 'supervises Radicale, which the light profile does not install', 'officer-notify': 'its producers are the queue and the email/agent sidecars; nothing to notify about', 'officer-wallet': 'holds seed and node credentials', }, });