Skip to content

feat: add auto-detect daemon for Claude Code / Codex / OpenClaw instances#75

Open
liaoandi wants to merge 2 commits intoringhyacinth:masterfrom
liaoandi:feat/auto_detect_daemon
Open

feat: add auto-detect daemon for Claude Code / Codex / OpenClaw instances#75
liaoandi wants to merge 2 commits intoringhyacinth:masterfrom
liaoandi:feat/auto_detect_daemon

Conversation

@liaoandi
Copy link
Copy Markdown
Contributor

Summary

  • Auto-detect running Claude Code / Codex / OpenClaw processes and sync to Star Office
  • Auto-join new instances, push state updates, auto-remove on exit
  • Graceful shutdown cleans up all tracked agents

Implements #65.

Files

scripts/auto_detect/
├── __init__.py
├── README.md
├── detector.py    # process detection (pgrep + ps, merged & deduplicated)
├── client.py      # Star Office API client (join/push/leave/set_state)
└── daemon.py      # main polling loop + state sync

Pure addition — no changes to existing code.

Key design decisions

  • No external dependencies — stdlib only (urllib, subprocess, json)
  • pgrep + ps merged detection — both sources run every cycle and results are deduplicated, because pgrep and ps each miss different processes on macOS
  • PID-sorted detection — stable disambiguation when multiple agents share the same working directory
  • Push self-healing — 3 consecutive push failures trigger automatic re-join (handles backend restarts)
  • Per-instance state isolation — state file path hashed from url+key, safe for multiple daemons
  • Atomic state persistence — write-to-tmp-then-rename prevents corruption on crash

Usage

python scripts/auto_detect/daemon.py
python scripts/auto_detect/daemon.py --url https://office.hyacinth.im --key ocj_xxx --interval 15
python -m scripts.auto_detect.daemon  # module mode also works

Test plan

  • Startup: detects all running Claude Code / Codex / OpenClaw instances
  • New process auto-joins within one poll cycle
  • Process exit triggers auto-leave within one poll cycle
  • Push self-healing: stale agentId re-joins after 3 consecutive failures
  • Persistent agents cleaned up when log file disappears
  • Multi-instance: different keys use separate state files
  • Graceful shutdown: SIGTERM cleans up all agents
  • Module mode: python -m scripts.auto_detect.daemon works

概要

  • 自动检测本机运行的 Claude Code / Codex / OpenClaw 进程,同步到 Star Office
  • 新实例自动加入、推送状态更新、退出时自动移除
  • 优雅关闭时清理所有已追踪的 agent

实现 #65

关键设计决策

  • 零外部依赖 — 仅使用标准库(urllibsubprocessjson
  • pgrep + ps 合并检测 — 每轮都跑两个来源并去重,因为 macOS 上 pgrep 和 ps 各自会漏掉不同的进程
  • PID 排序 — 多个 agent 在同一工作目录时,消歧标签(如 #2)在每轮保持稳定
  • Push 自愈 — 连续 3 次 push 失败后自动重新 join(应对后端重启等场景)
  • 多实例状态隔离 — state 文件路径基于 url+key 做 hash,多个 daemon 同时跑互不干扰
  • 原子化状态持久化 — 先写临时文件再 rename,防止 crash 时文件损坏

用法

python scripts/auto_detect/daemon.py
python scripts/auto_detect/daemon.py --url https://office.hyacinth.im --key ocj_xxx --interval 15
python -m scripts.auto_detect.daemon  # 也支持模块方式运行

Closes #65

🤖 Generated with Claude Code

@ringhyacinth
Copy link
Copy Markdown
Owner

Thanks a lot for this PR — this is actually a feature we'd really like to have.

Before we could consider merging it, there are two important things we'd want to address:

  1. The default port should be updated from 28791 to our current standard 19000.
  2. Since this feature can read the local status of Claude, Codex, and OpenClaw, we'd need an explicit user authorization step before any of that information is accessed. Users should clearly know what is being requested, and those agent statuses should only be read after they have actively agreed.

Ideally this should be opt-in, clearly explained to the user, and disabled by default until permission is granted.

In general, we think this is a strong direction, but it's also a relatively large upgrade touching product design, privacy expectations, and testing scope. So even if we move forward with it, we'd want to do a few more rounds of refinement and testing before merging.

Really appreciate the contribution — we're interested in the feature, but we'd want to tighten these parts before taking it further.

liaoandi and others added 2 commits March 12, 2026 16:15
…nces

Implements ringhyacinth#65. A lightweight Python daemon that auto-detects running
agent processes, syncs their status to Star Office, and cleans up on exit.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
回应 ringhyacinth 在 PR ringhyacinth#75 中的 review 意见:
1. 端口:全部脚本和文档中 28791 → 19000
2. 授权机制:默认关闭,用户需在 UI 中明确开启。Daemon 每次轮询检查授权,
   未授权不读取任何本机进程状态。关闭时自动清除所有已检测 agent。

授权机制:
- /config/auto-detect GET/POST 接口,含授权版本追踪
- 运行时配置新增:auto_detect_enabled, consent_granted_at, consent_version
- Daemon 在授权循环中等待,关闭时清除 agent
- Agent 来源标记为 "local-auto-detect",区分手动接入
- 最多 8 个自动检测 agent,超限返回 429
- daemon_status 四态语义:disabled / waiting-consent / running / stopped

前端:
- 钢蓝色像素精灵按钮(检测关闭/检测中.../检测开启 三态)
- 关闭态暗色,检测中呼吸动画,开启态亮色
- 开启需弹窗确认,关闭单击直接生效
- 弹窗锚定按钮右侧,滚动时跟随
- 访客 agent 点位避开家具(休息区/工作区)

守护进程与检测器:
- 进程存在 = writing(交互式编程工具,非后台服务)
- OpenClaw 通过 gateway.log 修改时间判断 idle/writing
- 优雅退出时清除所有已追踪 agent

其他:
- 国际化:检测相关文案支持中/英/日三语
- 压缩背景图 1MB → 105KB

---

Addresses ringhyacinth's review on PR ringhyacinth#75:
1. Port: 28791 → 19000 across all scripts and docs
2. Consent: off by default. Users must explicitly enable via UI. Daemon
   checks consent every poll — no local process state read until opted in.
   Disabling clears all detected agents.

Consent: /config/auto-detect GET/POST API, consent version tracking,
agent source tagged "local-auto-detect", max 8 agents (429 on exceed).
daemon_status: disabled / waiting-consent / running / stopped.

Frontend: steel-blue pixel sprite button with 3 states (off/detecting/on),
popup confirm to enable, single click to disable, scroll-following popup,
agent spawn points avoid furniture.

Daemon: process-based detection (running = writing). OpenClaw uses
gateway.log for idle/writing. Graceful cleanup on shutdown.

i18n: zh/en/ja. Compress office_bg_small.webp (1MB → 105KB).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@liaoandi liaoandi force-pushed the feat/auto_detect_daemon branch from d36b1f5 to 6107aa7 Compare March 16, 2026 13:07
@liaoandi
Copy link
Copy Markdown
Contributor Author

Hi @ringhyacinth, thanks for the detailed review! I've addressed both points:

1. Port: 28791 → 19000
Updated across all scripts, docs, and default configs.

2. Explicit user consent

  • Auto-detect is off by default. The daemon will not read any local process state until the user explicitly enables it.
  • A pixel-art toggle button ("检测关闭 / 检测中... / 检测开启") is added to the control bar, visually distinct (steel-blue) from the four state buttons.
  • Enable requires popup confirmation; disable is a single click.
  • Daemon checks consent on every poll cycle. When disabled, all detected agents are cleared immediately.
  • daemon_status now has four states: disabled / waiting-consent / running / stopped — so the API never lies about whether the process is alive vs. whether sync is active.

Other improvements in this update:

  • /config/auto-detect GET/POST API with auth guard and consent version tracking
  • Agent source tagged "local-auto-detect" to distinguish from manual joins
  • Max 8 auto-detect agents (429 on exceed)
  • Guest agent spawn points repositioned to avoid furniture
  • i18n: zh/en/ja for all detect UI strings
  • Dead code cleanup (removed ~100 lines of unused overlay, functions, and i18n keys)
  • Compressed office_bg_small.webp (1MB → 105KB)

Happy to iterate further if needed!

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Feature: auto-detect Claude Code / Codex / OpenClaw instances

2 participants