{"issue":"at://did:plc:zmjoeu3stwcn44647rhxa44o/sh.tangled.repo.issue/3lvzel2uo3a22","version":2,"introduction":{"project":"AtomicXR is a Nushell-based CLI tool (`axr`) for configuring VR/XR on Linux, primarily targeting Fedora Atomic and Universal Blue distributions like Bazzite. The CLI is structured as Nushell modules under `cli/atomic-xr/`, each exporting subcommands (e.g., `envision.nu`, `flatpak.nu`, `steamvr-lh.nu`). The project is marked as no longer maintained in the README, but the repo owner is actively requesting this feature. All modules follow a consistent pattern: they use `std log`, define helper functions, and export public commands.","issue":"The issue requests a new `axr lh pair` command for pairing SteamVR Lighthouse base stations and tracked devices without requiring users to manually invoke `lighthouse_console`. The author proposes two backend tools: (1) `lighthouse_console` from SteamVR, which is available now but slower due to its async job model, or (2) `lhctl`, a faster alternative that is not yet publicly released. The author is open to implementing option 1 now and migrating to option 2 later. Key open decisions include which backend to target, how to structure the command within the existing module hierarchy, what pairing workflow to expose, and how to handle the eventual transition between backends.","approach":"This questionnaire walks through the major implementation decisions in order: first the backend tool strategy (which directly shapes the entire implementation), then the command naming and module placement within the existing CLI structure, followed by the pairing workflow UX, error handling approach, and finally testing and documentation. Branch-specific follow-ups drill into details that only matter for a given backend choice, while shared tail questions cover cross-cutting concerns like deprecation planning and documentation."},"items":[{"id":"backend_strategy","prompt":"Which backend tool strategy should the pairing command use?","context":"The issue explicitly presents two backend options — lighthouse_console (available now, slower) and lhctl (faster, not yet public). This is the foundational decision because it determines the command's implementation, performance characteristics, and maintenance trajectory.","explanation":"The existing `steamvr-lh.nu` module already has a `lh-console` helper function that locates `lighthouse_console` from PATH, Flatpak Steam, or native Steam installations. Using `lighthouse_console` means leveraging this existing infrastructure but dealing with its async job model (commands are queued and results polled). `lhctl` would be significantly faster but introduces a dependency on unreleased software. A third option is to build an abstraction layer that supports both, allowing a seamless swap later. Each path has different implications for code complexity, user experience, and long-term maintenance.","options":[{"label":"Implement using lighthouse_console now (available immediately). Use the existing `lh-console` helper in `steamvr-lh.nu` to invoke lighthouse_console for pairing operations. Accept the slower async job model as a tradeoff for immediate availability. Plan to replace the backend later when lhctl is released.","followups":[{"id":"lh_console_async_handling","prompt":"How should the command handle lighthouse_console's async job model?","context":"Because you chose to use lighthouse_console, the pairing process involves submitting async jobs and polling for results. The existing `lh-console` helper simply runs the binary, but pairing requires multi-step interaction: discovering devices, initiating pairing, and confirming success.","explanation":"lighthouse_console uses an async job queue where you submit a command and then poll for its completion. For pairing, this typically involves: (1) scanning for nearby devices, (2) sending a pair command to a specific device, and (3) waiting for confirmation. The implementation could either parse stdout from lighthouse_console interactively, use its batch/scripting mode if available, or wrap the entire flow in a loop that polls for job completion. Each approach has different reliability and complexity tradeoffs.","options":[{"label":"Parse lighthouse_console's stdout interactively — run lighthouse_console as a subprocess, send commands via stdin, and parse output line-by-line to track job status and extract pairing results. This gives the most control but requires robust text parsing."},{"label":"Use lighthouse_console's command-line arguments for batch operations — pass all necessary arguments upfront (e.g., device serial, pair command) and capture the final output. Simpler implementation but less interactive feedback for the user."},{"label":"Wrap lighthouse_console calls in a polling loop — submit the pair command, then repeatedly invoke lighthouse_console to check job status until completion or timeout. More resilient to output format changes but slower due to repeated process spawning."}]},{"id":"lh_console_migration_prep","prompt":"How much should the implementation prepare for a future lhctl migration?","context":"Since lighthouse_console is intended as a temporary backend, the code could be structured to make swapping backends easier later, or it could be kept simple with the understanding that a rewrite will happen.","explanation":"Adding an abstraction layer (e.g., a common interface that both backends implement) increases initial complexity but makes the future swap trivial. Alternatively, keeping the implementation tightly coupled to lighthouse_console is simpler now but means more work during migration. The existing codebase doesn't use abstraction patterns — modules directly call external tools (e.g., `flatpak run`, `distrobox enter`, `rpm-ostree`). Following this convention suggests a direct implementation is more idiomatic.","options":[{"label":"Keep it simple and direct — implement pairing tightly coupled to lighthouse_console, following the existing pattern in the codebase where modules directly invoke external tools. Accept that a future migration to lhctl will require rewriting the pairing logic."},{"label":"Create a thin abstraction — define the pairing workflow as a sequence of steps (discover, select, pair, verify) with the lighthouse_console implementation behind helper functions. When lhctl arrives, only the helper functions need to change, not the user-facing command logic."}]}]},{"label":"Wait for lhctl and implement using it directly. Defer this feature until lhctl is publicly released, then implement with the faster tool from the start. This avoids throwaway work but leaves users without the feature for an indefinite period.","followups":[{"id":"lhctl_interim_solution","prompt":"Should there be an interim solution while waiting for lhctl?","context":"Because you chose to wait for lhctl, users currently have no streamlined way to pair lighthouse devices through the axr CLI. The existing `axr steamvr-lh console` command already exposes lighthouse_console directly, but it requires users to know the pairing commands themselves.","explanation":"The existing `console` command in `steamvr-lh.nu` already lets users run lighthouse_console with arbitrary arguments. An interim approach could enhance the console command's documentation or add a help subcommand that prints the manual pairing steps, giving users guidance without building full automation. Alternatively, the feature could simply wait with no interim measure.","options":[{"label":"Add a help/guide subcommand (e.g., `axr steamvr-lh pair-guide`) that prints step-by-step instructions for manually pairing via lighthouse_console. Low effort, immediately useful, and can be removed or replaced when lhctl arrives."},{"label":"No interim solution — wait for lhctl and implement the full feature then. Users can continue using `axr steamvr-lh console` directly in the meantime."}]}]},{"label":"Implement with lighthouse_console now, but design the command to auto-detect and prefer lhctl when it becomes available. The command checks for lhctl on PATH first; if not found, falls back to lighthouse_console. This follows the same pattern as the existing `lh-console` helper which already checks multiple locations for lighthouse_console.","followups":[{"id":"dual_backend_detection","prompt":"How should backend detection and selection work?","context":"Because you chose the dual-backend approach, the command needs logic to detect which tools are available and select the best one. The existing `lh-console` helper in `steamvr-lh.nu` already demonstrates this pattern — it checks PATH, then Flatpak Steam, then native Steam for lighthouse_console.","explanation":"The detection could be a simple `which` check at command startup (matching the existing `lh-console` pattern), or it could include a flag to force a specific backend. A flag would be useful for debugging or when users want to explicitly choose, but adds complexity. The existing codebase doesn't use backend-selection flags — tools are auto-detected silently.","options":[{"label":"Auto-detect only, following the existing `lh-console` pattern — check for lhctl first via `which`, fall back to lighthouse_console. No user-facing flag. Log which backend was selected at debug level using `std log`."},{"label":"Auto-detect with an optional override flag (e.g., `--backend lhctl` or `--backend lighthouse_console`) — auto-detect by default but allow users to force a specific backend. Useful for testing or when both tools are installed but one is preferred."}]}]}]},{"id":"command_naming","prompt":"What should the command name and module placement be?","context":"Regardless of which backend is chosen, the new pairing command needs a name and a home within the existing module structure. The issue suggests `axr lh pair`, but the existing lighthouse module is named `steamvr-lh.nu` and is registered in `mod.nu` as `export use steamvr-lh.nu`, making the current command namespace `axr steamvr-lh`.","explanation":"The existing module already exports `calibrate` and `console` commands, accessible as `axr steamvr-lh calibrate` and `axr steamvr-lh console`. Adding `pair` to this module would make it `axr steamvr-lh pair`. However, the issue suggests `axr lh pair`, which would require either renaming the module file to `lh.nu` (a breaking change for existing `axr steamvr-lh` users) or creating a new `lh.nu` module alongside the existing one. The README notes the project is deprecated, which may reduce concern about breaking changes.","options":[{"label":"Add the `pair` command to the existing `steamvr-lh.nu` module, making it `axr steamvr-lh pair`. This is the simplest approach — no module renaming, no breaking changes, consistent with the existing command structure. The command name is slightly longer than the issue suggests but follows established conventions."},{"label":"Rename `steamvr-lh.nu` to `lh.nu` and update `mod.nu` accordingly, making all lighthouse commands available under `axr lh` (e.g., `axr lh pair`, `axr lh calibrate`, `axr lh console`). This matches the issue's suggested naming but is a breaking change for anyone using `axr steamvr-lh` commands. Given the project's deprecated status, this may be acceptable."},{"label":"Create a new `lh.nu` module that re-exports from `steamvr-lh.nu` and adds the `pair` command, providing both `axr lh pair` (new) and `axr steamvr-lh pair` (alias). This avoids breaking existing commands while introducing the shorter namespace, but adds module complexity."}]},{"id":"pairing_workflow","prompt":"What pairing workflow should the command expose to users?","context":"Regardless of backend and naming choices, the user-facing pairing workflow needs to be defined. Lighthouse pairing involves discovering nearby Bluetooth LE devices (base stations, controllers, trackers) and establishing a connection with the host system.","explanation":"Pairing can be fully automated (scan, discover all devices, pair them all) or interactive (show discovered devices, let the user select which to pair). The existing `calibrate` command in `steamvr-lh.nu` uses an interactive pattern — it asks the user yes/no questions and waits for input. Other modules like `envision.nu` take a more automated approach with flags. The choice affects UX complexity and safety (auto-pairing everything might pair unintended nearby devices in shared spaces).","options":[{"label":"Interactive device selection — scan for nearby lighthouse devices, display a numbered list of discovered devices (with serial numbers and types), and let the user select which ones to pair using Nushell's `input list` or similar interactive selection. This is safer in shared spaces and gives users control over which devices are paired.","followups":[{"id":"interactive_multi_select","prompt":"Should users be able to select multiple devices at once or pair one at a time?","context":"Because you chose interactive device selection, the selection interface needs to handle the common case where users want to pair multiple devices (e.g., two base stations and two controllers) in a single session.","explanation":"Nushell's `input list` supports single selection. For multi-select, the command could loop (pair one, ask if there are more), use a custom multi-select prompt, or accept device identifiers as arguments alongside the interactive mode. The existing codebase uses simple `input` calls and `input list` for single selections.","options":[{"label":"Loop-based approach — after pairing one device, ask 'Would you like to pair another device?' and re-scan. Simple to implement using existing patterns (the `ask yn` helper in `steamvr-lh.nu`), handles the multi-device case naturally."},{"label":"Accept optional device serial numbers as arguments — if serials are provided, pair those directly without interactive selection. If no arguments given, enter interactive mode. This supports both scripted and interactive use cases."}]}]},{"label":"Fully automated — scan for all nearby unpaired lighthouse devices and pair them all automatically. Simpler UX (just run `axr lh pair` and wait), but risks pairing unintended devices in environments where multiple lighthouse setups are nearby (e.g., VR arcades, shared spaces).","followups":[{"id":"auto_pair_confirmation","prompt":"Should fully automated pairing require a confirmation step?","context":"Because you chose fully automated pairing, there's a risk of pairing unintended nearby devices. A confirmation step showing what will be paired could mitigate this without adding full interactive selection.","explanation":"The confirmation could show discovered devices and ask 'Pair all N devices? [y/n]' before proceeding, or it could include a `--yes` / `-y` flag to skip confirmation for scripted use. The existing `calibrate` command uses confirmation prompts via the `ask yn` helper.","options":[{"label":"Show discovered devices and require confirmation before pairing — display the list of found devices, then ask 'Pair all N devices? [y/n]' using the existing `ask yn` helper. Add a `--yes` flag to skip confirmation for scripted/automated use."},{"label":"No confirmation — pair immediately upon discovery. Keep the command simple and fast. Users in shared spaces can use the interactive mode (if implemented) or be careful about when they run the command."}]}]}]},{"id":"error_handling","prompt":"How should the command handle common failure scenarios?","context":"Regardless of the pairing workflow chosen, the command needs to handle failures gracefully. Common issues include: Bluetooth not available/enabled, no devices found within timeout, pairing rejected by device, and the backend tool (lighthouse_console or lhctl) not being installed.","explanation":"The existing codebase has two error handling patterns: (1) `error make` with descriptive messages and `help` fields (used in `steamvr-lh.nu`, `runtime.nu`, `oscavmgr.nu`) for fatal errors, and (2) `std log` for warnings and informational messages. The `lh-console` helper already handles the 'tool not found' case with an `error make`. Pairing-specific failures (no devices found, Bluetooth off) need their own handling strategy.","options":[{"label":"Fail fast with descriptive errors — check prerequisites (Bluetooth availability, backend tool installed) upfront before attempting any pairing. Use `error make` with helpful messages and remediation steps in the `help` field, matching the existing pattern in `lh-console` and `runtime.nu`. If pairing fails mid-process, report the specific failure and suggest next steps."},{"label":"Retry with guidance — on transient failures (no devices found, pairing timeout), automatically retry a configurable number of times with user-friendly status messages via `std log`. Only fail with `error make` on non-recoverable errors (tool not installed, Bluetooth hardware missing). Add a `--timeout` flag to control how long to scan for devices."}]},{"id":"testing_strategy","prompt":"What testing approach should be used for the new pairing command?","context":"Regardless of all previous choices, the new command needs some form of validation. The existing codebase has no test files — modules are Nushell scripts that directly invoke system tools, making traditional unit testing difficult.","explanation":"The codebase currently has zero tests. Nushell supports testing via `nu --testbin` and the `testing` module, but the existing modules are tightly coupled to system state (Flatpak, rpm-ostree, distrobox, SteamVR). Adding tests for the pairing command would be a first for this project. Options range from no tests (matching current practice) to adding integration tests that mock external tool calls.","options":[{"label":"No automated tests — match the existing codebase convention. Rely on manual testing with actual lighthouse hardware. Document the manual testing procedure in a comment or the PR description."},{"label":"Add basic smoke tests — create a test file that verifies the command's prerequisite checks (e.g., that it properly errors when lighthouse_console is not found) without requiring actual hardware. This would be the first test in the project and could establish a testing pattern for future commands."}]},{"id":"documentation","prompt":"What documentation should accompany the new command?","context":"Regardless of all implementation choices, the new command needs some level of documentation. The existing commands use Nushell's built-in doc comments (lines starting with `#` above function definitions) which are displayed by `axr -l` and `axr <command> --help`. The README currently focuses on migration away from AtomicXR.","explanation":"Nushell doc comments are the primary documentation mechanism in this codebase — every exported function has a `# Description` comment above it, and parameters have inline `# comment` annotations. The README is focused on deprecation/migration and doesn't document individual commands. Adding README documentation for a new feature in a deprecated project may send mixed signals, while inline doc comments are lightweight and follow existing conventions.","options":[{"label":"Inline Nushell doc comments only — add descriptive comments above the `pair` command and its parameters, following the existing pattern (e.g., `# Open SteamVR's lighthouse_console` on the `console` command). This is sufficient for `axr steamvr-lh pair --help` output and matches the project's documentation style."},{"label":"Inline doc comments plus a brief section in the README — add doc comments and also add a short section in the README under the legacy CLI usage area, documenting the `pair` command's purpose and basic usage. This helps users who read the README before installing."}]}]}