40ffd9b06cec6593e5838886c8bc10af5084f083
PidFile::acquire used create_new(true) with Drop-based cleanup, so a pidfile surviving power loss or SIGKILL made the daemon refuse to start until the file was deleted by hand. On AlreadyExists, read the recorded PID and probe it with kill(pid, 0): ESRCH (or unparseable content) means stale, so remove the file and retry the atomic create. A live PID keeps the refusal and now names the holding process. The retry loop is bounded to stay race-safe against a concurrent starter. Closes #1 Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
xy — HTTP MCP server supervisor
Daemon + CLI that launches and supervises HTTP-based MCP servers.
Build
cargo build --release
Run
target/release/xy daemon # foreground
Drop a server definition into $XDG_CONFIG_HOME/xy/servers/<name>.kdl
(see examples/insikt.kdl) and xy reload.
Commands:
xy list
xy status <name>
xy start <name|--all>
xy stop <name|--all>
xy restart <name|--all>
xy reload
xy logs <name> [--tail N] [--follow]
Exit codes: 0 success, 1 operational error, 2 daemon unreachable, 3 config invalid.
Description
Languages
Rust
100%