mirror of
https://github.com/gesellix/Bose-SoundTouch.git
synced 2026-08-18 16:46:17 +00:00
docs: track CLAUDE.md as the repo onboarding contract
Brings the file into version control so it survives a laptop switch. Aim: a self-contained briefing that doesn't rely on per-machine auto-memory or local scratch files. Notable content: - "How a new session should start" — concrete read order - "Load-bearing gotchas" — the ETag header literal must stay capitalised; rewriting to Go's canonical "Etag" breaks real speakers (encoded in handlers_etag_test.go as caseSensitiveETag/normalizedEtag) - "What never goes into this repo" — explicit list of data classes that must never be committed (real IPs, MACs, account IDs, Bose binaries, captures), since the repo is public - Pre-push quality gate codified: golangci-lint clean before git push - Trademark disclaimer for "SoundTouch" / "Bose" Drops the stale ".impeccable.md" reference (no such file in the tree) and trims the destructive-ops safety prose to the rules that actually apply during a session. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 4.7
parent
3078a37a45
commit
0fe13a9d5f
@@ -0,0 +1,186 @@
|
||||
# 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 `.gitignore`d 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
|
||||
|
||||
```bash
|
||||
# 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`:
|
||||
|
||||
```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, follow the brief direct-
|
||||
answer norms in [.junie/guidelines.md](.junie/guidelines.md):
|
||||
prioritise direct answers, avoid reverting to earlier task context
|
||||
when the user asks something out-of-scope, no assumptions in place of
|
||||
real information.
|
||||
Reference in New Issue
Block a user