feat(remote-control): add daemon pairing command (#29913)

## Why

Users who run Codex remote control through daemon mode can keep the
daemon running, but they do not have a CLI path to mint the short-lived
manual pairing code needed to connect another device. Without this
command, they need to speak app-server JSON-RPC directly.

Related: #25675

## What Changed

- Added `codex remote-control pair`, which connects to the existing
daemon control socket and calls `remoteControl/pairing/start` with
`manualCode: true`.
- Kept the command non-lifecycle-mutating: it does not start, enable, or
restart the daemon.
- Human output labels the manual code as `Pairing code: ...`; `--json`
preserves the full pairing response.
- Added daemon socket-client, CLI formatting, and parser coverage.

## Verification

- `remote_control_client::tests::start_pairing_requests_manual_code`
verifies the daemon client sends `{ "manualCode": true }` and parses the
complete response.
-
`remote_control_cmd::tests::remote_control_pairing_human_output_labels_the_manual_code`
verifies the human-facing output.
This commit is contained in:
Anton Panasenko authored and GitHub committed 2026-06-24 18:00:06 -07:00
1 parent 35f5d02464
commit f4e6aa70e5
4 files changed
+171

No files matched your search

+9
View File
@@ -3559,6 +3559,15 @@ mod tests {
assert!(err.to_string().contains("remote-control"));
}
#[test]
fn remote_control_pair_parses() {
let cli = MultitoolCli::try_parse_from(["codex", "remote-control", "pair"]).expect("parse");
let Some(Subcommand::RemoteControl(remote_control)) = &cli.subcommand else {
panic!("expected remote-control subcommand");
};
assert_eq!(remote_control.subcommand_name(), "remote-control pair");
}
#[test]
fn remote_flag_parses_for_interactive_root() {
let cli = MultitoolCli::try_parse_from(["codex", "--remote", "unix://codex.sock"])