Files
Bose-SoundTouch/CLAUDE.md
T
Tobias GesellchenandClaude Opus 4.7 27b5090ce5 docs(CLAUDE.md): inline communication principles; drop .junie/ pointer
Two reasons:

1. Survives a laptop switch. The principles previously lived only in
   .junie/guidelines.md; that file is per-machine tool config.
   Centralising in CLAUDE.md (which IS tracked) means the rules
   travel with the repo instead of with the workstation.
2. Single source of truth. Other AI assistants pointed at this repo
   should defer to CLAUDE.md, not maintain their own copies that drift.

The .junie/ dir becomes a per-machine breadcrumb that points back at
CLAUDE.md, and is .gitignore'd in a separate commit.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-17 19:14:05 +02:00

7.3 KiB

CLAUDE.md

Entry point for any Claude Code (or human) session working on this repository. Read it before touching code.

What this project is

Go library and toolset for controlling Bose SoundTouch speakers via the local network API, plus a local cloud-service emulator. Bose discontinued the SoundTouch cloud — this project keeps existing speakers usable without it.

Module: github.com/gesellix/bose-soundtouch

Two binaries:

  • soundtouch-cli — command-line control of one or more speakers (status, play, presets, groups, migration, …).
  • soundtouch-service — local replacement for streaming.bose.com and the bmx services, default port 8000.

Per-session pickup notes live in two local files at the repo root:

  • NEXT.md — current "pick up here" log of open items.
  • DONE.md — archive of recently resolved items.

Both are .gitignored on purpose; they don't follow the repo.

How a new session should start

  1. Read this file.
  2. Read NEXT.md if it's present — that's where running context lives.
  3. Skim README.md for the user-facing pitch.
  4. Skim docs/ for the area you're touching. Long-form notes (analysis, guides, troubleshooting) live there, not in the code.
  5. Run make check once to confirm the local environment compiles, vets, and tests cleanly.

Build, test, run

# Build
make build          # CLI + service for current platform
make build-all      # Cross-platform builds (Linux, macOS, Windows)
make install        # Install to $GOPATH/bin

# Quality
make test           # Unit tests
make test-coverage  # Coverage reports
make check          # fmt + vet + test
make lint           # golangci-lint

# Development
make dev-service    # Run local service on port 8000
make dev-discover   # Discover devices on the LAN
make dev-info HOST=<ip>  # Get device info

# Docker
make docker-build
make docker-run-host

Pre-push quality gate: make lint (golangci-lint) must be clean before git push. CI runs it on every PR; running it locally first saves a round-trip. make check covers lint is its own target — combine as needed.

Project structure

cmd/
  soundtouch-cli/      # CLI tool for device control
  soundtouch-service/  # Local cloud service emulator
  soundtouch-web/      # Web UI (TuneIn browser, device control)
  soundtouch-backup/   # On-device backup helper
  example-*/           # Usage examples
pkg/
  client/              # HTTP + WebSocket client for the SoundTouch Web API
  models/              # XML/JSON data structures
  discovery/           # Device discovery (mDNS + UPnP, unified interface)
  config/              # Configuration management
  service/
    bmx/               # Bose Media eXchange service emulation
    marge/             # Device-management service emulation
    handlers/          # HTTP request handlers
    proxy/             # HTTP proxy with request recording
    datastore/         # Persistent device data storage
    certmanager/       # TLS certificate management
    setup/             # Device migration and configuration
    spotify/           # Spotify integration
    stockholm/         # Optional Stockholm frontend bridge
examples/              # Feature demonstration programs
docs/                  # Long-form analysis, guides, troubleshooting
.junie/                # Communication-style guidelines (see below)

Key technologies

  • Go 1.26+
  • chi v5 — HTTP router
  • gorilla/websocket — WebSocket for real-time events
  • hashicorp/mdns — mDNS device discovery
  • miekg/dns — DNS operations and a custom DNS server
  • urfave/cli/v2 — CLI framework

Architecture notes

  • pkg/client is the core library for device API calls (HTTP + WebSocket).
  • pkg/service is the local cloud replacement; routes wire to the handlers in pkg/service/handlers/ via chi middleware.
  • Discovery supports both mDNS and UPnP/SSDP behind a unified interface.
  • The SoundTouch Web API uses XML on the wire; internal service-to-service messages use JSON.
  • Tests cover unit, integration, parity (local vs. official Bose API recordings), and regression. Reproducer tests should be refactored into permanent regression or documentation tests rather than deleted.

Load-bearing gotchas

ETag header literal must stay capitalised

Bose speakers emit the response header with exact capitalisation ETag. Go's http.Header.Set canonicalises to Etag (lowercase t). Real speakers parse strictly — Etag is rejected. The codebase deliberately bypasses the canonicalisation path; do not rewrite the string literal "ETag" to "Etag" anywhere in pkg/service/handlers/ or in tests.

The contrast is encoded in two named constants in pkg/service/handlers/handlers_etag_test.go:

const normalizedEtag    = "Etag" // what http.Header.Set produces
const caseSensitiveETag = "ETag" // what the speaker actually expects

Linter suppressions on the canonical-header check live alongside the test code. Static-analysis warnings about "ETag" are expected; don't "fix" them.

Destructive git or filesystem actions need explicit confirmation

git reset --hard, git checkout that would overwrite local changes, git clean -fd, rm -rf on non-build paths, git stash drop — all should be proposed in writing with their consequences before running, unless the user has already authorised that specific action in this session. Prefer reversible alternatives (git stash over git reset --hard).

What never goes into this repo

This repository is public. The following must never be committed:

  • Real LAN IPs of personal networks. Use RFC-5737 documentation ranges in examples and fixtures: 192.0.2.0/24, 198.51.100.0/24, 203.0.113.0/24.
  • Real MAC addresses or speaker device IDs from anyone's actual hardware. Use AA:BB:CC:DD:EE:FF or DEVICEID01 style placeholders.
  • Bose account IDs, serial numbers, or tokens belonging to anyone other than the committer's own test devices — and even those should be sanitised before publication when feasible.
  • Bose firmware binaries, NAND dumps, or decompiled Bose code.
  • Wi-Fi SSIDs or credentials, captured or otherwise.
  • Network captures, traces, or logs that include data from accounts or devices other than your own test hardware.
  • Personal identifiers: real names of speakers ("LivingRoom", custom device names), private email addresses, household member names visible in source IDs.

If you spot any of the above already in the tree, treat it as a sanitisation task: stop, flag it to the maintainer, propose a remediation commit before continuing.

Disclaimers

"SoundTouch" and "Bose" are registered trademarks of Bose Corporation. This project is an unofficial, community-built effort, not affiliated with, endorsed by, or authorised by Bose.

Communication style

When working with a human user in this repo:

  • Prioritise direct answers to the question being asked, even when it sits outside the current task or project context. Don't divert back to whatever you were doing when the user asks something else.
  • Don't substitute assumptions for real information. When something is unclear, ask or check, rather than guessing and proceeding.

These principles also apply to other AI assistants pointed at this repo. Tool-specific config dirs (e.g. .junie/, .claude/) should defer to this file as the source of truth instead of carrying their own copies.