bitwarden / bitwarden/agent-access

Feature request: --headless / --no-tui mode for `aac listen` (LaunchAgent / systemd / headless deployments)

Open
#156 1 comment 0 reactions 0 assignees View on GitHub
Dominant language
Rust
Stars
145
Forks
11
Avg merge
20h 57m
Merged PRs (30d)
1

Description

## Feature request: `--headless` / `--no-tui` mode for `aac listen` (LaunchAgent / systemd / headless deployments)

### Summary

`aac listen` currently uses `ratatui` for its interactive TUI display, which requires a real controlling TTY. When run under macOS `launchd`, Linux `systemd`, or any headless service manager, `ratatui` panics at process start with:

```
The application panicked (crashed).
Message: failed to initialize terminal: Os { code: 6, kind: Uncategorized, message: "Device not configured" }
Location: /Users/runner/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/ratatui-0.29.0/src/terminal/init.rs:52
```

Request: add a `--headless` (or `--no-tui`) flag to `aac listen` that disables the TUI and emits structured log lines (or JSON events) instead. This unblocks fleet deployments where `aac listen` runs as a supervised system service.

### Version

`aac 0.11.0` (`3b000d15af71be5ddcf8893b099f3a66d386be9d`)

### Reproducer (macOS launchd)

`~/Library/LaunchAgents/com.example.aac_listen.plist`:

```xml

Labelcom.example.aac_listen
ProgramArguments

/opt/homebrew/bin/aac
listen
--reusable-psk
--provider
bitwarden
-v

RunAtLoad
KeepAlive
StandardOutPath/tmp/aac_listen.log
StandardErrorPath/tmp/aac_listen.err
EnvironmentVariables

BW_SESSION...

```

`launchctl load ~/Library/LaunchAgents/com.example.aac_listen.plist` — `/tmp/aac_listen.err` fills with the ratatui panic; `KeepAlive` respawns the process; the crash loop repeats indefinitely.

### Workaround we tried (partial, insufficient)

Wrapping the invocation in `script(1) -q /dev/null` to synthesise a PTY:

```bash
exec /usr/bin/script -q /dev/null /opt/homebrew/bin/aac listen --reusable-psk --provider bitwarden -v
```

`script(1)` provides a pseudo-terminal but ratatui still panics under `launchd`'s session detachment context (empirically observed — panic message unchanged). The only reliable substrate today is a foreground `aac listen` inside `Terminal.app` (real device TTY), which is not viable for autonomous fleet operation.

### Real-world impact

We operate 3 `aac` client daemons (Bitwarden Agent Access consumers) that depend on a single `aac listen` process on the same host. When the LaunchAgent-managed `aac listen` panics on TTY init and crash-loops, every client daemon exits with `Credential request failed: Request denied` (or `Timeout waiting for credential response`) and enters its own crash-loop. This surfaced as a 3-day, 13-hour silent outage in our deployment before we diagnosed it. The only remediation was to fall back to foreground `aac listen` inside a persistent Terminal window — not a defensible production pattern.

### Suggested shape

`aac listen --headless` (or `--no-tui`) that:

- Skips all `ratatui`/`crossterm` initialisation
- Emits structured line-oriented events to stdout (or a `--log-format json` option that emits JSON per event: pair request received, credential request, credential approved, credential denied, session started, session ended, error)
- Retains all other flags (`--reusable-psk`, `--provider`, `--proxy-url`, `--verbose`)
- Optionally: auto-detect headless mode when `isatty(stdout) == false` and switch to line-oriented output automatically, without requiring the explicit flag

### Alternative approaches considered

- **`script(1)` PTY shim** — insufficient (documented above)
- **`expect` / `pty4j` full virtual-terminal wrapper** — heavier substrate; still fragile against ratatui's device-configuration probing
- **Fork ratatui / patch aac source to skip TUI init on no-TTY** — feasible as a local fork but not a durable upstream solution

An upstream `--headless` mode is the cleanest fix and would unblock a common deployment class (system service supervisors) for the broader `aac` user base.

### Files (helpful references)

- ratatui panic location: `ratatui-0.29.0/src/terminal/init.rs:52`
- Related crate: `crossterm` (used by ratatui for device detection)

Happy to test any prototype build. Thanks for `aac` — the credential-tunnel model is exactly what our multi-agent stack needed.

Contributor guide

Open the contributing guide

Research direction

Start at the `aac listen` command and trace where ratatui and crossterm initialize the terminal. Define how the headless path preserves the existing listen flags and emits line-oriented events, then verify it runs under launchd or systemd without TUI initialization and covers the listed session and credential events.

Written by the indexing model from the issue text.

Assessment

Tech stack
rust
Domain
cli, devops
Issue type
Feature
Difficulty
4/5
Estimated time
3-5 days
Activity status
Active
Clarity
Mostly clear
Newbie friendliness
55/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.