Skip to content

feat(m5.7): panopticon start-runner — SSH + reverse tunnel + remote session service#249

Draft
tildesrc wants to merge 5 commits into
mainfrom
panopticon/m5-start-runner-cmd
Draft

feat(m5.7): panopticon start-runner — SSH + reverse tunnel + remote session service#249
tildesrc wants to merge 5 commits into
mainfrom
panopticon/m5-start-runner-cmd

Conversation

@tildesrc

@tildesrc tildesrc commented Jul 8, 2026

Copy link
Copy Markdown
Contributor

Summary

  • Adds panopticon start-runner <host> subcommand to the operator CLI
  • New src/panopticon/terminal/launch.py — pure command-construction functions (build_ssh_command, build_remote_host_command, start_runner) with injectable run for unit-testability
  • Tunnel mode (default): opens a reverse SSH port forward so the remote runner and its containers can reach the local task service; requires GatewayPorts clientspecified in remote sshd_config
  • Direct mode (--no-tunnel): no port forward; for same-network deployments with a routable service URL
  • 17 new unit tests in tests/test_launch.py; no real SSH/Docker/network required
  • docs/start-runner.md operator guide covering both modes, GatewayPorts prerequisite, and keeping the runner alive

Plan: panopticon://tasks/09d0492751d1481f90ff267653a16c76/artifacts/plan.md

🤖 Generated with Claude Code

Panopticon Agent and others added 5 commits July 8, 2026 22:06
…ession service

Adds `panopticon start-runner <host>` to the operator CLI.  The command
SSHes to a remote machine, opens a reverse port forward so the remote
runner and its containers can reach the local task service, and starts
`panopticon.sessionservice.host` there.  The SSH session IS the tunnel;
closing it stops the runner.

Direct mode (`--no-tunnel`) skips the port forward for same-network
deployments with a routable service URL.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…nstalls

`python` is not on PATH on modern Linux. Default the remote interpreter to
`python3` and expose `--python CMD` so operators can pass `uv run python`
or a venv path. Multi-word values are split via shlex.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…'t SSH

The local session-service runner defaulted to socket.gethostname() as its
registered host, causing the terminal supervisor to wrap every local-task
attach in `ssh -t <hostname>`. Pass --host "" so runner_host stays null
for locally-claimed tasks; remote runners (started via start-runner) keep
their explicit --host <hostname>.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
--local runs the session service on the current machine without SSH and
registers the runner with no hostname (--host ""), so locally-claimed
tasks attach directly without SSH. Python defaults to sys.executable so
the same venv is reused automatically.

make start now uses `panopticon start-runner --local` instead of calling
python -m panopticon.sessionservice.host directly, giving a unified
operator entry point for local and remote runners alike.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Local mode runs the session-service argv directly via subprocess (no
shell), so a literal ``~`` in the default roots reached Docker as a
relative ``./~`` bind-mount source and made ``docker run`` fail with
exit 125 (and littered a stray ``./~`` tree). Expand the roots against
this machine's home in the local branch; remote/tunnel/direct modes keep
the literal ``~`` for the remote login shell to expand.

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