module.exports = {
  apps: [
    {
      name: 'officer',
      script: 'bun',
      args: 'start',
      watch: false,
    },
    // The Anthropic credential proxy. Despite the old name (`officer-claude`) this process does NOT
    // run agents — it holds the proxy secret and forwards to api.anthropic.com. The process that runs
    // agents is `officer-agent` below.
    {
      name: 'officer-anthropic-proxy',
      script: 'bun',
      args: 'run src/servers/sidecar/claude/index.ts',
      watch: false,
    },
    // The process that actually runs `claude`. It used to be spawned on demand by the main server,
    // which made every agent session a grandchild of `officer` and killed it on every restart. As a PM2
    // peer it survives them. It resolves the owner from the database and the proxy secret from the
    // proxy's state file, so it needs nothing from `officer` in order to start.
    {
      name: 'officer-agent',
      script: 'bun',
      args: 'run src/servers/sidecar/claude/user-instance.ts',
      watch: false,
    },
    {
      name: 'officer-opencode',
      script: 'bun',
      args: 'run src/servers/sidecar/opencode/index.ts',
      watch: false,
    },
    {
      name: 'officer-email',
      script: 'bun',
      args: 'run src/servers/sidecar/email/index.ts',
      watch: false,
    },
    // The only sidecar run by `node` rather than `bun`, and the only one that is not TypeScript: node-pty
    // is a native addon. It also does not use sidecar/connect.ts, and carries its own copy of the
    // reconnect loop.
    {
      name: 'officer-pty',
      script: 'node',
      args: 'src/servers/sidecar/pty/index.mjs',
      watch: false,
    },
    {
      name: 'officer-vnc',
      script: 'bun',
      args: 'run src/servers/sidecar/vnc/index.ts',
      watch: false,
    },
    {
      name: 'officer-music',
      script: 'bun',
      args: 'run src/servers/sidecar/music/index.ts',
      watch: false,
    },
    {
      name: 'officer-vault',
      script: 'bun',
      args: 'run src/servers/sidecar/vault/index.ts',
      watch: false,
    },
    {
      name: 'officer-slskd',
      script: 'bun',
      args: 'run src/servers/sidecar/slskd/index.ts',
      watch: false,
    },
    {
      name: 'officer-headscale',
      script: 'bun',
      args: 'run src/servers/sidecar/headscale/index.ts',
      watch: false,
    },
    {
      name: 'officer-transmission',
      script: 'bun',
      args: 'run src/servers/sidecar/transmission/index.ts',
      watch: false,
    },
    // The books. Wraps a self-hosted InvoiceShelf. Instances, their Sanctum tokens and the company each one
    // is pinned to are set by the owner from /invoices/settings and stored encrypted in
    // `invoiceshelf_accounts` — read here, never from the environment, because Bun auto-loads `.env` into
    // every process in this directory and `officer` would hold the token too.
    {
      name: 'officer-invoiceshelf',
      script: 'bun',
      args: 'run src/servers/sidecar/invoiceshelf/index.ts',
      watch: false,
    },
    // Video. Wraps a self-hosted Jellyfin. Servers, and the access token each one is signed in with, are set
    // by the owner from /jellyfin and stored encrypted in `jellyfin_servers` — read here, never from the
    // environment. Video only: Officer's own player owns audio.
    {
      name: 'officer-jellyfin',
      script: 'bun',
      args: 'run src/servers/sidecar/jellyfin/index.ts',
      watch: false,
    },
    // Notes. Wraps a self-hosted Memos. The instance URL and its personal access token are set by the
    // owner from the UI and stored in `service_connections` — read here, never from the environment.
    {
      name: 'officer-memos',
      script: 'bun',
      args: 'run src/servers/sidecar/memos/index.ts',
      watch: false,
    },
    // Code hosting. Wraps a self-hosted Gitea. The instance URL and its personal access token are set by
    // the owner from /gitea and stored in `service_connections` — read here, never from the environment.
    {
      name: 'officer-gitea',
      script: 'bun',
      args: 'run src/servers/sidecar/gitea/index.ts',
      watch: false,
    },
    // Calendar and contacts. Supervises Radicale (CalDAV/CardDAV) on a loopback port and owns the
    // collections under DATA_PATH/dav. Two doors: /dav for phones (DAVx5, iOS, Thunderbird — HTTP Basic
    // against a scoped app password) and /api/caldav for Officer's own UI. The protocol is Radicale's;
    // the platform authenticates and forwards. See docs/nextcloud-replacement.md.
    {
      name: 'officer-caldav',
      script: 'bun',
      args: 'run src/servers/sidecar/caldav/index.ts',
      watch: false,
    },
    // The photo library. Wraps a self-hosted Immich. The instance and its key are set by the owner from
    // /photos/settings and stored encrypted in `photos_config` — read here, never from the environment,
    // because Bun auto-loads `.env` into every process in this directory and `officer` would hold it too.
    {
      name: 'officer-photos',
      script: 'bun',
      args: 'run src/servers/sidecar/photos/index.ts',
      watch: false,
    },
    // The bitcoin wallet. Holds seed material (sealed under an owner passphrase) and node credentials, so
    // it is the one sidecar whose restart has a security-relevant side effect: every wallet relocks.
    // The one place anything leaves this machine to tell the owner something: push (APNs + FCM) and the
    // Discord webhook, behind one interface. A sidecar rather than platform code because the producers
    // are spread across sidecars, and a platform-owned notifier would make every one of them call back in.
    {
      name: 'officer-notify',
      script: 'bun',
      args: 'run src/servers/sidecar/notify/index.ts',
      watch: false,
    },
    {
      name: 'officer-wallet',
      script: 'bun',
      args: 'run src/servers/sidecar/wallet/index.ts',
      watch: false,
    },
  ],
};
