Skip to content

Survey: laptop services & proxies — declarative coverage and conversion backlog #2775

Open

Description

@dezren39

Survey taken 2026-10-30 on the laptop (amd), ordered by Drew alongside the muse-proxy direct-mode NixOS pass. Cross-refs: #2753 (direct mode), #2104 (proxy-supervisor retirement / per-proxy HM units), #1752 (PM hand-unit gaps — see status note below), #883 (stale-tree ExecStart trap).

Phase A result (today's stack)

The muse-proxy / muse-direct stack was already declarative — no functional change was needed:

  • systemd.user.services.muse-proxy in home/common/default.nix (Proxy service-model redesign: automatic flake services, retire proxy-supervisor ownership, restore consumer Wants #2104) generates exactly the live unit: evaluating this flake at origin/main yields ExecStart /nix/store/7bxcdg21iqjmiinxh0bl92kyjwrbmkdn-muse-proxy-start-unit, byte-identical to the running unit, and nixosConfigurations.amd evaluates clean end to end.
  • The unit runs bin/muse-proxy-start.sh from the live checkout (egress unpinned, META_API_KEY unset by the script); direct mode reads ~/.config/muse/auth.json at runtime — the credential is never in the config. The muse-direct provider lives in .opencode/opencode.jsonc with baseURL http://127.0.0.1:{env:MUSE_PROXY_PORT:-18747}/v1, the port defined once as museProxyPort in home/common/default.nix.
  • PR docs(nix): record muse-proxy direct mode in its Home Manager unit (#2753) #2774 (merged, 4189b191) only extended the unit comment so the NixOS source of truth records direct mode; re-evaluation after the edit produces the identical ExecStart, so nothing is superseded at activation and no restart is implied. There is no remaining activation step for this stack beyond the next ordinary rebuild.

Headline finding: the retired fleet-proxy-supervisor's units are still alive

#2104 retired the supervisor and made the per-proxy Home Manager units the sole owners of the canonical ports. In reality, seven fps-* transient units (started via systemd-run, no supervisor process exists) are still running, and four of them hold canonical ports, so their declarative replacements crash-loop:

Port Listener today Declarative unit state
18742 clef fps-clef-proxy-18742 (since 2026-10-28 20:57) clef-proxy auto-restart, 1,170 restarts, exit 1
18743 agy fps-agy-proxy-18743 (since 2026-10-28 13:02) agy-proxy auto-restart, 1,168 restarts, exit 1
18745 antigravity-ls fps-antigravity-ls-proxy-18745 (since 2026-10-28 20:57) antigravity-ls-proxy auto-restart, 1,169 restarts, exit 1
18749 claude-code fps-claude-code-proxy-18749 (since 2026-10-28 13:05) claude-code-proxy auto-restart, 1,169 restarts, exit 1
19744 / 19746 / 19748 fps-codex-proxy-19744, fps-design-code-proxy-19746, fps-commandcode-proxy-19748 (all since 2026-10-29 23:08) squat the +1000 alternates canonical ports correctly held by the declarative units

The proxies themselves also still write ~/.local/state/<proxy>/endpoint.json (fresh timestamps, incl. muse-proxy at its 09:30 restart today) — the files are live state written by the proxy processes, not just stale supervisor records as the #2104 comment assumes.

Services & proxies inventory

Fleet proxies (all user units; code in bin/, run from the live checkout)

Service Port Managed today Recommendation
muse-proxy 18747 HM unit, home/common/default.nix; running, direct mode live Already declarative — done (#2774)
codex-proxy 18744 HM unit + hand drop-in codex-proxy.service.d/warm-override.conf overriding ExecStart to the checkout Remove the drop-in: post-#2104 the unit already runs the checkout, so the #480-era override is redundant
design-code-proxy 18746 HM unit, running (fps twin on 19746) Already declarative; kill the fps twin
commandcode-proxy 18748 HM unit + hand drop-in commandcode-proxy.service.d/fix-execstart.conf pointing ExecStart at ~/git/code/bin/... — the other checkout Remove the drop-in: it is the #883 stale-tree trap in live form; the HM unit already runs ~/code/bin/commandcode-proxy-start.sh
opencode-route-proxy 18750 HM unit, running Already declarative
clef-proxy 18742 HM unit declared, crash-looping behind fps transient Stop the fps unit at a natural break; unit then owns the port
agy-proxy 18743 same same
antigravity-ls-proxy 18745 same same
claude-code-proxy 18749 same same
proxy-supervise.mjs (fps) — Retired in flake (#2104); 7 transient units still running; config fossils in ~/.config/proxy-supervisor/*.bak/.unmanaged-20261026; bin/proxy-supervise.mjs.new tracked leftover Retire fully: stop transients, delete fossils after

Core AI services

Service Port Managed today Recommendation
openchamber 3000 (tailnet) HM unit, home/common/default.nix + hand drop-in openchamber.service.d/external-opencode.conf (attaches to the external OpenCode server; sets OPENCODE_HOST/OPENCODE_SKIP_START and a password env var) Convert the drop-in into the flake (or fold into the unit) so the external-opencode arrangement survives a config regeneration
opencode serve (standing server) 13420 Bare process (session scope, PPID 1, started 2026-10-30 09:18 from a shell) Leave alone operationally (session-bearing); backlog: give it a declarative unit at a natural break — it is the process OpenChamber and the fleet's sessions depend on
mcpx 34543 HM unit, home/common/default.nix (+ mcpx-reload path unit) Already declarative
t3code 3773 HM unit, home/common/default.nix Already declarative
openclaw-gateway 18789 HM unit, home/openclaw/default.nix Already declarative
desktop-commander-remote — HM unit, home/common/default.nix Already declarative
sync-models timer HM unit + timer, home/common/default.nix Already declarative

PM stack & apps

Service Port Managed today Recommendation
pm-projector — User unit declared via nixos/services/pm-stack/default.nix Already declarative
pm-aggregator 4870 (tailnet) same Already declarative
pm-dispatch 4879 (tailnet) same Already declarative
pm-tunnel (cloudflared) 20241 metrics same — this is the machine's running cloudflared; nixos/services/cloudflared/ only documents manual tunnel setup Already declarative; tidy the cloudflared module comment to point at pm-tunnel
pm-git-sync, pm-dashboard-backup, pm-projector-reconcile, quota-gatherer timers Declared via pm-stack / laptop-backups modules Already declarative
docker-pm-grist / docker-pm-kaneo / docker-pm-pad / docker-pm-postgres 3000 / 7777 / 8484 area (tailnet; owning pids not visible without sudo) System units, NixOS-generated from nixos/services/pm-apps/default.nix (oci-containers) Already declarative — #1752 looks substantially landed; verify and close or re-scope it
ready-for-agent 6056 (0.0.0.0) User unit declared via nixos/services/pm-apps/default.nix, binary from the pm-stack deployment dir Already declarative (see #1752 note above)
pm-kaneo (user unit) — Declared (pm-apps/pm-stack), timer-driven companion to the docker app Already declarative

Automation, backups, quota exporters (user timers/services)

Item Managed today Recommendation
laptop-autocommit-{hatch,hatch-personal,openclaw}, laptop-repo-keeper, laptop-untracked-review HM via nixos/home/laptop-autocommit.nix / laptop-repo-keeper.nix Already declarative
atlas-backup, openclaw-backup, supabase-backup, repo-archive-backup, cold-store-{nightly,drill}, agent-backup HM via nixos/home/laptop-backups.nix / home/common/default.nix Already declarative
meta-quota-export (svc+timer) Hand-made files in ~/.config/systemd/user/ Convert to HM (same pattern as sync-models)
cloudflare-quota-export (svc+timer) Hand-made files Convert to HM
dashboard-backup (svc+timer) Hand-made files Convert to HM (alongside pm-dashboard-backup)
oc-password-sync (svc+path) Hand-made files Convert to HM, or fold into the openchamber declaration
git-maintenance@ (svc+3 timers) Hand-placed copies of git's upstream template Leave alone (upstream template) or declare via HM for completeness
rustdesk (user svc) Hand-made file (ExecStart from /etc/profiles/per-user/...) Convert to HM or leave; low value either way

System services (NixOS)

sshd, tailscaled, docker, dnsmasq, id-primary (nixos/services/id-mail), power-guard (nixos/services/power-guard), display-manager/desktop stack — all NixOS-generated from this flake. Already declarative; no action.

Bare processes (no unit)

Process Port Recommendation
python3 -m http.server 8899 8899 on 0.0.0.0 Identify owner; retire (world-bindable directory server)
python3 /tmp/mock.py 18777 Retire (test mock)
pkgs/id debug build demo (~/git/code/pkgs/id/target/debug/id --data-dir ~/id-demo-data) 3210 Retire or replace with the packaged build; demo data dir
node ~/git/fleet/2900-394-proxy-c… 36539 Identify; retire or promote to a declared proxy
/tmp/mcpxdbg/mcpx daemon --detached 38481 Retire (debug instance; the real mcpx is a unit)
opencode serve 13420 See Core AI services — leave alone, backlog a unit

Fossils & leftovers (inert, delete after the fps stop)

  • ~/.config/systemd/user/proxy-supervisor.{service,timer}.unmanaged-20261026, ~/.config/proxy-supervisor/config.json.unmanaged-20261026 + two config.json.bak-*
  • *.backup / *.bak-* unit files next to pm-aggregator, pm-git-sync, pm-projector, quota-gatherer, repo-archive-backup, ready-for-agent units (inert, but they confuse every future survey)
  • Tracked in git under bin/: codex-proxy.mjs.pre-warm-20261024, codex-proxy.mjs.resume-build.bak, commandcode-proxy-start.sh.bak-20261025003957-netfix, muse-proxy.mjs.bak-20261024-flag-tolerance, muse-proxy.mjs.bak-20261024121323-laptop-deploy, proxy-supervise.mjs.new
  • Hand drop-in app-com.mitchellh.ghostty.service.d/overrides.conf (desktop app; noted for completeness)

Conversion checklist

Sandbox (out of scope for conversion)

The sandbox VM is not NixOS-managed: its services are ~/tools/init.sh run_steps (mcpx-service, opencode-service, muse-proxy-service, agy/commandcode/claude-code proxy services, proxy-supervisor-service, …), several deliberately disabled or stubbed by Drew's 2026-10-25 pass. Listed only so this survey is complete; no conversion is proposed.


Method: systemctl --user/system unit + timer listings, ss -tlnp port→pid→cgroup mapping, unit FragmentPath/file-type checks, and flake-source grep on the laptop, 2026-10-30. Nothing was stopped, restarted, or reconfigured during the survey.

Acceptance criteria

  • Each fps-* transient unit squatting a canonical port (18742, 18743, 18745, 18749) is stopped and its declarative Home Manager replacement is running and stable (no crash-loop) on that port, or the item is split into per-proxy follow-up issues naming the blocker.
  • The +1000 alternate-port squatters (19744, 19746, 19748) are cleared or explicitly documented as intentional.
  • Hand drop-ins and hand-managed units in the inventory (e.g. codex-proxy warm-override) are either converted to declarative config or recorded as deliberate exceptions with a reason.
  • The endpoint.json state files are documented as live proxy-written state (the Proxy service-model redesign: automatic flake services, retire proxy-supervisor ownership, restore consumer Wants #2104 assumption that they are stale supervisor records is corrected wherever it appears).
  • A post-change survey re-run shows no fps-* transient proxy units remain, and the result is posted on this issue.

Activity

  1. dezren39 commented on Oct 30, 2026

    @dezren39
    MemberAuthor

    Checklist item done 2026-10-30 ~10:06 CDT (Drew approved in chat): all 7 fps transient units stopped — fps-clef-proxy-18742, fps-agy-proxy-18743, fps-antigravity-ls-proxy-18745, fps-claude-code-proxy-18749, fps-codex-proxy-19744, fps-commandcode-proxy-19748, fps-design-code-proxy-19746. Verified after the stop: zero fps-* units remain; the Home Manager units clef-proxy / agy-proxy / antigravity-ls-proxy / claude-code-proxy are active/running on their canonical ports and their NRestarts counters are frozen (1319/1317/1318/1318 — cumulative incl. the crash-loop era, no longer climbing); ports 18742/18743/18745/18746/18747/18749 all listening; /health OK on 18742, 18747, 18749. No supervisor timer/service exists to resurrect the transients. muse-proxy (18747) untouched throughout.

  2. dezren39 commented on Oct 30, 2026

    @dezren39
    MemberAuthor

    Drop-in items cleared 2026-10-30 ~10:14 CDT (Drew approved in chat). All three hand drop-ins moved out of systemd's view (recoverable copies in ~/.config/systemd/user/_dropin-backup-2026-10-30/) + daemon-reload: (1) commandcode-proxy fix-execstart.conf — verified the HM wrapper execs $HOME/code/bin/commandcode-proxy-start.sh (correct checkout); unit restarted onto it: active/running, NRestarts=0, :18748 /health OK. (2) codex-proxy warm-override.conf — HM wrapper already execs the same $HOME/code/bin/codex-proxy.mjs; running process was already equivalent, left undisturbed, still running. (3) openchamber external-opencode.conf — the fold-in already existed: bin/openchamber-start.sh (invoked by the HM unit) exports OPENCODE_HOST (default http://127.0.0.1:13420), OPENCODE_SKIP_START=true and OPENCODE_PASSWORD (file-sourced); live process env confirmed all three, so the drop-in was pure duplication. OpenChamber not restarted. Remaining checklist: the other hand-made unit groups + fossil cleanup.

  3. dezren39 commented on Oct 30, 2026

    @dezren39
    MemberAuthor

    Intake review

    🤖 Agent note · handed off

    Still live? Yes. The body itself records PR #2774 as comment-only (no functional change, no activation step), and the headline finding — seven fps-* transient units still holding canonical/alternate ports while their declarative replacements crash-loop (~1,170 restarts each) — is a survey result from today, not a fixed item. No merged PR resolves it.

    Notes / risks: The crash-looping declarative units are the urgent slice: four canonical ports are served by units #2104 believed retired. Risk is change-window risk on the laptop (stopping a transient unit before its replacement binds cleanly drops that proxy). Suggested approach: one proxy at a time — stop the fps-* unit, start the HM unit, verify the port and endpoint.json — starting with one low-stakes proxy before repeating the pattern.

    Suggested approach: treat the acceptance criteria as a checklist; split per-proxy issues only if a single conversion blocks on something specific.

  4. added
    kind/infrastructureInfrastructure / host-portability work
    source/humanFiled directly by a human
    priority/highImportant and time-sensitive
    effort/lLarge: multi-day or open-ended; expect staged check-ins
    meta/enrichedIntake review done: acceptance criteria, links, and normalized labels added
    queue/queuedHas a queued task in the Supabase agent queue
    on Oct 30, 2026
  5. developing-today commented on Nov 3, 2026

    @developing-today
    Contributor

    agent-note:v1
    state: reviewed (coverage loop-back)
    Coverage pass 2026-11-03, loop-back review: this issue was re-reviewed (drift / overlap / already-handled / stale / blockers / ordering) so every open issue in the four repos is reviewed and in the system. Verdict: still live; in the system as task 7358 (triage, queued, priority 50) in repo-health-code-pilot. Labels audited and synced. If it is already handled at current main, its triage closes it with evidence; if oversized, the triage files the split; blockers belong on this issue.
    Found via: coverage loop-back 2026-11-03

  6. developing-today commented on Nov 3, 2026

    @developing-today
    Contributor

    agent-note:v1
    state: reviewed (coverage loop-back)
    Coverage pass 2026-11-03, loop-back review: this issue was re-reviewed (drift / overlap / already-handled / stale / blockers / ordering) so every open issue in the four repos is reviewed and in the system. Verdict: still live; in the system as task 7358 (triage, queued, priority 50) in repo-health-code-pilot. Labels audited and synced. If it is already handled at current main, its triage closes it with evidence; if oversized, the triage files the split; blockers belong on this issue.
    Found via: coverage loop-back 2026-11-03

  7. dezren39 commented on Nov 3, 2026

    @dezren39
    MemberAuthor

    🤖 Agent note · coverage finding routed here from the #2104 triage (queue task 7290, Lane P, 2026-11-03)

    One stale-reference item for this survey's declarative-coverage backlog, found while verifying #2104 (the proxy service-model redesign, PR #2107, merged 2026-10-30) live:

    • home/openclaw/default.nix (current main): the comment above systemd.user.services.openclaw-gateway still says the provider proxies "are owned by the proxy-supervisor (transient fps-* units on the canonical ports)" and that the gateway "must not Want the manual per-proxy units" — both false since feat(home): make fleet proxies automatic services, retire proxy-supervisor (#2104) #2107 retired the supervisor and made the proxy units real automatic services.
    • Same file: openclaw-gateway's After list still names agy-proxy.service, which no longer exists as a unit (agy-proxy was replaced/retired in the later antigravity rework — see home/common/default.nix:588-589). On the laptop it surfaces as agy-proxy.service not-found inactive dead in systemctl --user list-units "*proxy*". After-only, so it is harmless ordering noise, but it is exactly the kind of stale declarative reference this survey tracks.

    No separate issue filed — this survey is the tracking home. #2104 itself was closed with evidence in the same pass.

  8. 42 remaining items

  9. dezren39 commented on Nov 5, 2026

    @dezren39
    MemberAuthor

    agent-note:v1
    event: picked_up
    task: 8983
    worker: repo-worker-code
    lane: 02cafe76-eafd-4d0b-aaa6-2b7a737d68dc
    state: claimed
    verified: Fresh GitHub state: #2775 OPEN; no held/user-owned/do-not-merge/do-not-auto-edit labels; PR #2107 is MERGED; no open PR search result for #2775. Claim labels synced to task/small-fix, queue/claimed, status/in-progress, work/assigned.
    next: Fast-forward the laptop primary main, create or resume the task worktree, then make only the scoped comment/dependency corrections.
    at: 2026-11-05T07:02:46Z

  10. dezren39 commented on Nov 5, 2026

    @dezren39
    MemberAuthor

    agent-note:v1
    event: pr_opened
    task: 8983
    worker: repo-worker-code
    lane: 02cafe76-eafd-4d0b-aaa6-2b7a737d68dc
    state: claimed; PR #6113 OPEN
    verified: Changes are on queue/8983-2775-proxy-comment-cleanup at 1c2d261; targeted Nix parses/evaluation and git diff --check pass. The obsolete agy-proxy After entry is removed while commandcode/codex ordering remains.
    next: Inspect fresh PR checks; if pending beyond the five-minute active window, park task 8983 with CI resume condition.

  11. dezren39 commented on Nov 5, 2026

    @dezren39
    MemberAuthor

    🤖 Agent note · handed off

  12. added
    queue/parkedQueue task is parked (waiting on CI, time, or an event)
    status/parkedDeliberately paused with a recorded resume condition
    queue/claimedQueue worker lifecycle state
    and removed
    queue/claimedQueue worker lifecycle state
    status/parkedDeliberately paused with a recorded resume condition
    queue/parkedQueue task is parked (waiting on CI, time, or an event)
    on Nov 5, 2026
  13. dezren39 commented on Nov 5, 2026

    @dezren39
    MemberAuthor

    🤖 Agent note · handed off

  14. dezren39 commented on Nov 5, 2026

    @dezren39
    MemberAuthor

    agent-note:v1
    event: task_complete
    task: 8983
    worker: repo-worker-code
    session_id: ses_e5e5503c176ffegaHZ1Urk2VOV
    state: scoped correction ready in PR #6113; issue #2775 remains OPEN for the broader inventory/conversion checklist
    result: Corrected Home Manager ownership wording, documented live proxy-process publication/removal of endpoint.json, and removed the obsolete agy-proxy.service After edge. No runtime service behavior changed and no services were restarted.
    branch: queue/8983-2775-proxy-comment-cleanup
    head: e532ffa (includes main through e3626d1)
    validation: git diff --check; nix-instantiate --parse home/openclaw/default.nix; nix-instantiate --parse home/common/default.nix; nix eval --raw .#nixosConfigurations.amd.config.home-manager.users.user.home.activationPackage.drvPath — all pass
    CI: No GitHub Actions run exists for this head; CodeRabbit is rate-limited/neutral. The proxy-port-fallbacks workflow currently triggers only on merge_group, while nix-ci is schedule/workflow_dispatch only, so the policy-listed PR Nix-expression coverage is absent. Local targeted evaluation passed.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

effort/lLarge: multi-day or open-ended; expect staged check-inskind/infrastructureInfrastructure / host-portability workmeta/enrichedIntake review done: acceptance criteria, links, and normalized labels addedpriority/highImportant and time-sensitivequeue/claimedQueue worker lifecycle statesource/humanFiled directly by a humanstatus/in-progressQueue worker lifecycle statetask/small-fixQueue packet kind: bounded fix with reproduction and targeted testswork/assignedQueue worker lifecycle state

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions