Skip to content

feat(cli): worker start -a|--attach — foreground view, detach with Ctrl-D - #12

Merged
ralyodio merged 1 commit into
masterfrom
feat/worker-attach-mode
Jul 19, 2026
Merged

feat(cli): worker start -a|--attach — foreground view, detach with Ctrl-D#12
ralyodio merged 1 commit into
masterfrom
feat/worker-attach-mode

Conversation

@ralyodio

Copy link
Copy Markdown
Contributor

What

Adds c0mpute worker start -a|--attach: run the worker attached in the foreground watching its log, then press Ctrl-D (or Ctrl-C) to detach and leave it running in the background. Follow-up to #11 (the -d daemon).

The design decision (important)

The naive ask — "run in the foreground, then on Ctrl-D convert this process into a daemon" — isn't sound. Once worker start is up, the Tokio runtime is multi-threaded with live libp2p sockets, and fork() on a multi-threaded process is UB (it copies only the calling thread, leaving a dead runtime + half-held locks). That's exactly why -d daemonizes before the runtime starts.

So -a uses the tmux / docker attach model: the worker is a standalone background daemon the whole time, and -a attaches a live log viewer to your terminal. Detaching (Ctrl-D / Ctrl-C) just stops the viewer — it never touches the worker. Same UX as asked, but robust: nothing is lost on detach, and there's never a duplicate or momentarily-forked worker.

Behavior

  • worker start -a → launches the daemon (via the existing -d path, so the fork-before-runtime happens in that child), then streams the log.
  • If a worker is already running, -a re-attaches to it instead of spawning a second one.
  • Ctrl-D (stdin EOF) or Ctrl-C / SIGTERM → detach; prints detached — worker still running (pid N).
  • -a conflicts with -d (clap enforces).
  • The attach process never builds the async runtime — it's just a subprocess supervisor + file tail — so it returns your shell cleanly.

Testing (Linux, verified end-to-end)

  • Help shows -a; -a -d errors with a clap conflict.
  • -a spawns a separate daemon and tails its log; SIGINT detaches the viewer, daemon keeps running; worker stop cleans up.
  • Already-running case: -a prints worker already running (pid N); attaching, no duplicate spawned.
  • Ctrl-D over a real PTY: sending 0x04 detaches the viewer (worker still running (pid N)), viewer exits, daemon survives.
  • cargo build (debug) and cargo build --release both clean.

🤖 Generated with Claude Code

…rl-D

Add attach mode: `c0mpute worker start -a` runs the worker as a background
daemon and stays attached, streaming its log to the terminal. Press Ctrl-D
(stdin EOF) or Ctrl-C to detach — the worker keeps running; stop it with
`worker stop`. If a worker is already running, `-a` re-attaches to it instead
of spawning a second one.

Implemented as a supervisor + file tail that never builds the async runtime,
so it hands off to the daemon and returns the shell cleanly. This is the
tmux/docker-attach model: converting an already-running multi-threaded
foreground process into a daemon in place isn't sound (fork after the Tokio
runtime spawns threads is UB), so the worker is a standalone daemon the whole
time and `-a` just attaches a viewer. `-a` conflicts with `-d`.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@ralyodio
ralyodio merged commit ba7609b into master Jul 19, 2026
8 checks passed
@ralyodio
ralyodio deleted the feat/worker-attach-mode branch July 19, 2026 07:50
ralyodio added a commit that referenced this pull request Jul 19, 2026
Adds background-worker lifecycle from #11 and #12:
  - worker start -d|--daemon  detach and run as a daemon (PID file + log)
  - worker start -a|--attach  stream the log, Ctrl-D/Ctrl-C to detach
  - worker stop / worker status now functional (were stubs)
Ships the systemd user unit at scripts/systemd/c0mpute-worker.service.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
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.

1 participant