aibox
On this page

Audio Support

Audio Support#

aibox can enable audio support for voice-capable tools. Audio is bridged from the container to the host via PulseAudio over TCP, and the required container packages live in the optional audio-voice addon.

Why Audio Matters#

Claude Code supports voice interaction. For this to work inside a container, audio output (and optionally input) must be forwarded to the host’s sound system. aibox handles this by installing PulseAudio client utilities in the container and connecting them to a PulseAudio server running on the host.

Architecture#

text
Container                          Host
┌─────────────────────┐     ┌─────────────────────┐
│  Claude Code        │     │  PulseAudio Server   │
│       │             │     │       │              │
│  pulseaudio-utils   │────>│  TCP :4714           │
│  sox                │     │       │              │
│  .asoundrc          │     │  Speakers / Mic      │
└─────────────────────┘     └─────────────────────┘

The container sets PULSE_SERVER to point at the host’s PulseAudio TCP module. Audio data flows over the network socket.

Configuration in aibox.toml#

toml
[audio]
enabled = true
backend = "pulseaudio"
install = true
pulse_server = "tcp:host.docker.internal:4714"
FieldDefaultDescription
enabledfalseWhether to set up audio environment variables in the container
backendpulseaudioAudio bridge backend. Only PulseAudio is currently supported
installtrueWhether to install the internal audio-voice tool recipe when audio is enabled
pulse_servertcp:host.docker.internal:4714PulseAudio server address

When enabled = true, the generated docker-compose.yml sets PULSE_SERVER in the container environment. When install = true, it also selects the internal audio-voice recipe during aibox apply, which installs Sox, PulseAudio client utilities, and ALSA PulseAudio plugins in the container.

Host Setup#

The fastest way to set up audio on your host is the built-in CLI command:

bash
# Check if your host is ready
aibox doctor audio

# Automatic setup (macOS: installs PulseAudio, configures TCP, creates launchd agent)
aibox apply audio

aibox apply audio handles:

  • Installing PulseAudio via Homebrew (macOS) if not present
  • Configuring ~/.config/pulse/default.pa with the TCP module on port 4714
  • Creating a launchd agent with KeepAlive so PulseAudio auto-starts and restarts on crash (macOS)
  • Loading the TCP module immediately

aibox doctor audio diagnoses: PulseAudio installation, daemon status, TCP module, persistence config, port listening, launchd agent (macOS), and connectivity.

Both commands accept --port to override the default port (4714).

Manual setup#

If you prefer manual configuration:

macOS#

  1. Install PulseAudio:

    bash
    brew install pulseaudio
  2. Enable the TCP module. Add to ~/.config/pulse/default.pa:

    text
    load-module module-native-protocol-tcp port=4714 auth-anonymous=1
  3. Start PulseAudio:

    bash
    pulseaudio --start
  4. Verify it is listening:

    bash
    lsof -i :4714

Docker Desktop and OrbStack provide host.docker.internal automatically. For Podman, check your machine’s network configuration — you may need to use the host IP directly:

toml
[audio]
enabled = true
pulse_server = "tcp:192.168.64.1:4714"

Linux#

  1. PulseAudio is likely already running. Enable the TCP module:

    bash
    pactl load-module module-native-protocol-tcp port=4714 auth-ip-acl=127.0.0.1;172.16.0.0/12;10.0.0.0/8;192.168.0.0/16

    To make this persistent, add to ~/.config/pulse/default.pa:

    text
    load-module module-native-protocol-tcp port=4714 auth-ip-acl=127.0.0.1;172.16.0.0/12;10.0.0.0/8;192.168.0.0/16
  2. Use host.docker.internal (Docker 20.10+) or the Docker bridge IP:

    toml
    [audio]
    enabled = true
    pulse_server = "tcp:host.docker.internal:4714"
Firewall

Ensure port 4714 is accessible from the container network. On systems with strict firewalls, you may need to allow traffic from the Docker/Podman bridge interface.

Claude Code OAuth in Containers#

When running claude auth inside a container with bridge networking (OrbStack, Docker Desktop), the OAuth callback may fail. Claude Code starts a temporary HTTP server on a random ephemeral port to receive the callback, but that port isn’t forwarded to the host browser.

Workaround: Use claude setup-token to authenticate manually, or authenticate on the host first. aibox bind-mounts Claude’s .claude/, .claude.json, and XDG cache/config/state locations, so credentials survive container rebuilds.

Upstream tracking

This is tracked at anthropics/claude-code#14528. A fix on the Claude Code side (e.g., configurable callback port) would resolve this properly without compromising container network isolation.

The .asoundrc File#

The seeded home configuration includes an .asoundrc file at /home/aibox/.asoundrc. This configures ALSA to route through PulseAudio, so applications that use ALSA rather than PulseAudio directly also get audio output when the audio-voice addon is installed.

Troubleshooting#

No sound output#

  1. Verify PulseAudio is running on the host:

    bash
    pulseaudio --check && echo "running" || echo "not running"
  2. Verify the TCP module is loaded:

    bash
    pactl list modules | grep module-native-protocol-tcp
  3. Test from inside the container:

    bash
    paplay /usr/share/sounds/freedesktop/stereo/bell.oga

    If the file does not exist, use sox to generate a test tone:

    bash
    play -n synth 0.5 sine 440

Connection refused#

The PULSE_SERVER address is not reachable from the container.

  • Check that the PulseAudio TCP module is listening on the correct port
  • Check that host.docker.internal resolves from inside the container:
    bash
    # From inside the container
    getent hosts host.docker.internal
  • Try using the host’s explicit IP address instead

Audio works but is choppy#

This is usually a network or resource issue. PulseAudio over TCP adds latency. Ensure the container has sufficient CPU resources and the host is not under heavy load.

Disabling audio#

If you do not need audio, set enabled = false in aibox.toml:

toml
[audio]
enabled = false

This removes the PULSE_SERVER environment variable from the container. The audio packages (sox, pulseaudio-utils) remain installed in the base image but are inert without a server to connect to.

Edit this page Updated Aug 19, 2026