diff --git a/machines/fry/workspaces/hermes.nix b/machines/fry/workspaces/hermes.nix index 56c35ca..9565d86 100644 --- a/machines/fry/workspaces/hermes.nix +++ b/machines/fry/workspaces/hermes.nix @@ -14,7 +14,17 @@ group = "users"; createUser = false; - extraPackages = with pkgs; [ nix git ripgrep fd jq ]; + # Share the user's workspace tree so the agent operates on the same files + # you see when SSH'd in. Codex's workspace-write sandbox keeps writes scoped + # to this dir. + workingDirectory = "/home/googlebot/workspace"; + + extraPackages = with pkgs; [ nix git ripgrep fd jq codex ]; + + environment = { + SIGNAL_HTTP_URL = "http://127.0.0.1:8080"; + CODEX_HOME = "/var/lib/hermes/.codex"; + }; # Bind-mounted from /run/agenix/hermes-env on fry (host decrypts via agenix). # Lives at /etc/... rather than /run/... because the workspace's systemd @@ -26,16 +36,58 @@ model = { provider = "openai-codex"; default = "gpt-5.5"; + # Delegate openai/* turns to the codex CLI subprocess so the agent gets + # codex's sandbox + tooling. Codex CLI must be on PATH and authenticated + # via `codex login` (separate from `hermes auth`). + openai_runtime = "codex_app_server"; }; toolsets = [ "all" ]; terminal.backend = "local"; }; }; - # Daemon sets HERMES_HOME to stateDir/.hermes via the systemd unit. Setting - # it system-wide here makes interactive `hermes` (now running as googlebot) - # pick up the same auth.json that the daemon wrote. - environment.variables.HERMES_HOME = "/var/lib/hermes/.hermes"; + # Align googlebot's interactive `hermes` / `codex` invocations with the + # daemon's persisted state dirs so logins from a shell land where the + # service expects to read them. + home-manager.users.googlebot.home.sessionVariables = { + HERMES_HOME = "/var/lib/hermes/.hermes"; + CODEX_HOME = "/var/lib/hermes/.codex"; + }; - environment.systemPackages = [ pkgs.codex ]; + home-manager.users.googlebot.home.packages = with pkgs; [ codex signal-cli ]; + + # Declarative codex CLI defaults — seeded into $CODEX_HOME on first boot, + # then codex owns the file (it rewrites config.toml on `codex login`, project + # trust grants, etc.). To re-seed after changing the defaults below, delete + # the persisted /var/lib/hermes/.codex/config.toml and restart hermes-agent. + environment.etc."hermes-codex-config.toml".text = '' + sandbox_mode = "danger-full-access" + approval_policy = "never" + ''; + + systemd.tmpfiles.rules = [ + "d /var/lib/hermes/.codex 0700 googlebot users -" + "C /var/lib/hermes/.codex/config.toml 0644 googlebot users - /etc/hermes-codex-config.toml" + ]; + + # signal-cli runs an HTTP JSON-RPC daemon on localhost; hermes-agent talks to + # it via SIGNAL_HTTP_URL. Registered as the PRIMARY device on a dedicated + # number (GV / JMP.chat / prepaid SIM) — the account identity lives entirely + # in /var/lib/hermes/signal-cli/, which is bind-mounted from the host. If + # that tree is lost, the Signal account is irrecoverable, so back it up. + systemd.services.signal-cli = { + description = "signal-cli JSON-RPC daemon for Hermes"; + wantedBy = [ "multi-user.target" ]; + after = [ "network-online.target" ]; + wants = [ "network-online.target" ]; + before = [ "hermes-agent.service" ]; + serviceConfig = { + Type = "simple"; + User = "googlebot"; + Group = "users"; + ExecStart = "${pkgs.signal-cli}/bin/signal-cli --config /var/lib/hermes/signal-cli daemon --http 127.0.0.1:8080"; + Restart = "always"; + RestartSec = "5"; + }; + }; } diff --git a/secrets/hermes-env.age b/secrets/hermes-env.age index 11c7d2f..1259c97 100644 Binary files a/secrets/hermes-env.age and b/secrets/hermes-env.age differ