Starting the reviewer terminates any process using its target port
Source references: 3Before binding its default port, the reviewer runs `lsof -ti :<port>` and sends SIGTERM to every returned PID without checking whether the process belongs to this Skill.
If port 3117 is used by a development server, database proxy, or other work, that process can be stopped unexpectedly, interrupting sessions or losing unsaved state.
Starting the non-static viewer first finds every process listening on the target port and sends each PID SIGTERM without checking ownership. If another local application uses the default port 3117, it could be unexpectedly terminated and lose unsaved work. The user can use `--static`, or ask the author to select a free port without killing processes.
def _kill_port(port: int) -> None: """Kill any process listening on the given port.""" try: result = subprocess.run( ["lsof", "-ti", f":{port}"], capture_output=True, text=True, timeout=5, ) for pid_str in result.stdout.strip().split("\n"): if pid_str.strip(): try: os.kill(int(pid_str.strip()), signal.SIGTERM) except (ProcessLookupError, ValueError): pass if result.stdout.strip(): time.sleep(0.5) except subprocess.TimeoutExpired:Show 2 other places
def main() -> None: parser = argparse.ArgumentParser(description="Generate and serve eval review") parser.add_argument("workspace", type=Path, help="Path to workspace directory") parser.add_argument("--port", "-p", type=int, default=3117, help="Server port (default: 3117)") parser.add_argument("--skill-name", "-n", type=str, default=None, help="Skill name for header") parser.add_argument( # Kill any existing process on the target port port = args.port _kill_port(port) handler = partial(ReviewHandler, workspace, skill_name, feedback_path, previous, benchmark_path)