How @motrix/cli Discovers and Pairs with Motrix Instances: A Technical Deep Dive
The @motrix/cli tool uses a two‑stage process: first discovering the local Motrix executable via ShellEnvironmentResolver and version checks in cli‑tool‑service.ts, then establishing a secure connection through a device‑code pairing flow managed by DeviceCodeService that generates a user code, polls for UI approval, and exchanges a one‑time token.
The @motrix/cli package provides a command‑line interface for controlling the Motrix download manager. When you execute CLI commands, the tool must first locate the Motrix binary on your system and then authenticate with the running instance. This article examines the source code in the agalwood/Motrix repository to explain exactly how discovery and pairing work under the hood.
Stage 1: Executable Discovery via CliToolService
The discovery phase begins in src/main/cli/cli‑tool‑service.ts (lines 62–90), where the CliToolService class orchestrates the detection of the local Motrix installation. The service initializes a ShellEnvironmentResolver to build the correct shell context for the host platform.
To locate the binary, the service invokes resolveExecutable to find both the node runtime and the motrix command. Once located, the CLI validates the installation by executing motrix --version through the internal #runVersion method.
The service performs a critical version check: if the running Node version is 22 or higher, and the Motrix binary responds correctly, the CLI reports a Ready status and persists the executable path and version.
Stage 2: Device‑Code Pairing Flow (Spec 7b)
Once the executable is discovered, pairing follows the Spec 7b device‑code flow. The DeviceCodeService class in src/core/bridge/device‑code‑service.ts manages the entire handshake, from request generation to token exchange.
Initiating the Pairing Request
When you run motrix pairing request, the CLI instantiates DeviceCodeService and calls request(). This method (lines 48–66) generates a cryptographically random requestId and a human‑readable userCode, then stores a pending entry in memory.
The service arms a TTL (time‑to‑live) timer to prevent stale requests from accumulating. At this point, the CLI prints the user code (e.g., "ABCD‑EFGH") to the terminal.
Polling for Approval
After displaying the code, the CLI enters a polling loop via poll(requestId). Each iteration checks the entry's effectiveStatus property (lines 32–46). When you approve the request in the Motrix UI, the status flips to approved and the service returns a one‑time token to the CLI.
The polling mechanism handles the asynchronous nature of user interaction, waiting until the status change occurs or the TTL expires.
Handling UI Approval
The bridge between the Motrix UI and the CLI pairing service is handled by src/core/bridge/resolve‑cli‑pair.ts (lines 20–33). This module provides a "resolve‑pair" helper used by both the desktop IPC bridge and the HTTP /rpc endpoint.
When the user clicks approve in the interface, the system calls DeviceCodeService.approve(), and the helper returns a standardized result object. Successful approvals return {ok: true}, while failures or unavailable states return {ok: false, reason: 'unavailable'}. This normalization ensures consistent behavior across transport layers.
Practical Implementation Examples
You can interact with the discovery and pairing system via command‑line or programmatically through the Node.js API.
Command‑Line Usage
# Check discovery status and version compatibility
npx @motrix/cli status
# Initiate device-code pairing
npx @motrix/cli pairing request
# → Outputs user code: ABCD-EFGH
# Approve in Motrix UI, then the CLI receives the token automatically
Programmatic API
import { CliToolService } from '@motrix/cli';
// Stage 1: Discovery
const cli = new CliToolService({
directInstallSupported: true,
platform: process.platform,
});
const status = await cli.getStatus();
console.log(`Found Motrix ${status.version} at ${status.executablePath}`);
// Stage 2: Pairing
const { requestId, userCode } = await cli.requestPair();
console.log(`Enter code ${userCode} in Motrix UI`);
let token;
while (!token) {
const poll = await cli.pollPair(requestId);
if (poll.status === 'approved') token = poll.token;
await new Promise(r => setTimeout(r, 2000));
}
console.log('Paired successfully. Token:', token);
The public methods requestPair() and pollPair() are thin wrappers around the internal DeviceCodeService methods described above.
Summary
- Discovery relies on
CliToolServiceinsrc/main/cli/cli‑tool‑service.tsto resolve the Motrix executable usingShellEnvironmentResolverand validate it viamotrix --version, requiring Node.js 22 or newer. - Pairing utilizes
DeviceCodeServiceinsrc/core/bridge/device‑code‑service.tsto implement a Spec 7b device‑code flow, generating unique request IDs and user codes stored with TTL timers. - Approval is bridged through
src/core/bridge/resolve‑cli‑pair.ts, which normalizes results for both IPC and HTTP transports. - Authentication completes when the CLI receives a one‑time token after the user approves the request in the Motrix UI, enabling secure headless operation.
Frequently Asked Questions
What Node.js version does @motrix/cli require for discovery?
The CLI requires Node.js version 22 or higher to report a Ready status during the discovery phase. This check occurs in src/main/cli/cli‑tool‑service.ts after resolving the executable path and running motrix --version.
How does the CLI locate the Motrix binary on the system?
The CliToolService uses ShellEnvironmentResolver to build the host environment, then calls resolveExecutable to find the motrix command in the system path. It verifies the binary by executing the #runVersion method, which runs motrix --version and parses the output.
What happens if the user denies or ignores the pairing request?
If the user denies the request or the TTL timer expires, the effectiveStatus never transitions to approved. The polling loop in DeviceCodeService.poll() continues until timeout, and no one‑time token is issued, leaving the CLI unpaired and unable to authenticate.
Can pairing requests be initiated programmatically without the CLI binary?
Yes, you can instantiate CliToolService and DeviceCodeService directly in Node.js code to trigger request() and poll() methods, as shown in the implementation examples. These classes are available when importing @motrix/cli as a dependency, allowing headless automation without shelling out to the CLI binary.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →