Files
JamBuddy/CLAUDE.md
vadimwit 072920ff0e docs+config: never-delete policy — CLAUDE.md hard rule + .claude/settings.json deny list
Claude must never execute destructive/irreversible commands (rm, git branch
-d/-D, git push --delete, reset --hard, force-push, DROP, etc.) — it proposes
them for the user to run. Enforced behaviorally in CLAUDE.md (authoritative)
and as permissions.deny rules in .claude/settings.json (defense-in-depth).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-13 21:36:02 +01:00

6.1 KiB
Raw Permalink Blame History

CLAUDE.md

This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.

Destructive operations — NEVER delete (hard rule)

Claude must never EXECUTE a destructive or irreversible command. Always ask, and hand the user the exact command(s) to run themselves.

This covers (non-exhaustively):

  • Deleting files/directories: rm, rm -rf, rmdir, del, Remove-Item.
  • Deleting branches: git branch -d / -D, git push --delete, git push <remote> :branch.
  • Deleting tags/remotes: git tag -d, git remote remove / rm.
  • Discarding work: git reset --hard, git checkout -- <path>, git clean -f.
  • Force-pushing: git push -f / --force / --force-with-lease.
  • Dropping data: DROP, TRUNCATE, destructive migrations.

Instead: print the command(s) in a fenced block with a one-line note on what each does and what it affects, and let the user run them. Never run them yourself, even when the desired outcome is clear — rm and -d are prompted, never executed.

Leave regular branches alone (main, the active sprint branch) unless the user explicitly names them. Before calling any branch "stale", prove containment (git branch --merged, 0 unique commits) and report that evidence — do not act on it.

These are also enforced as permissions.deny rules in .claude/settings.json (defense-in-depth), but this behavioral rule is authoritative and covers cases the patterns can't.

Commands

# Development (Vite dev server + Electron window with hot reload)
npm run electron:dev

# Browser-only dev (no Electron)
npm run dev

# Build installers
npm run electron:build:win    # Windows NSIS installer → releases/
npm run electron:build:mac    # macOS DMG → releases/
npm run electron:build:linux  # Linux AppImage → releases/

No test suite exists. There is no lint script — no ESLint config is present.

Architecture

Electron shell (electron/main.cjs) loads dist/index.html in production or localhost:5173 in dev. The renderer process has full Web Audio API access (sandbox: false). preload.cjs uses contextIsolation: true with no exposed IPC — Electron is purely a window host; all logic lives in the renderer.

Two audio pipelines run in parallel inside AudioCapture.jsx:

Path FFT Purpose
Pitch 4096 samples (~90ms, smoothingTimeConstant=0.0) McLeod pitch detection via pitchy → feeds key detection
Chord 16384 samples (~370ms, smoothingTimeConstant=0.5) Harmonic summation chroma → feeds chord detection

The 16384 FFT gives 2.7 Hz/bin resolution, which is necessary to separate adjacent semitones on low guitar strings (~5-6 Hz apart). The chord analyser uses computeChroma() — a harmonic summation that folds each FFT bin back through 5 harmonics to cancel overtone contamination (prevents minor chords from reading as major).

State and detection logic lives entirely in App.jsx:

  • handleNote (pitch callback) → accumulates noteHistoryRef, runs Krumhansl-Schmuckler key detection every 5 notes, votes in keyVotesRef (rolling window, requires strong consensus before committing)
  • handleChroma (chord callback) → averages a ring buffer of chromaSmooth frames, runs a chroma stability gate (per-bin variance check — bails if still in transition), then matches against chord templates via matchChordFromChroma, votes in chordVotesRef
  • handleOnset (onset callback from RMS spike detection) → builds a tempo histogram from pairwise inter-onset intervals, folding all intervals into 55220 BPM range; the histogram peak drives BPM display

Both handleNote and handleChroma use useCallback(fn, []) (empty deps). All values they need from render scope are kept in refs synced via useEffect — this prevents AudioCapture's start from recreating on every render.

All music theory is in src/lib/theory.js:

  • detectKey / detectTopKeys — Krumhansl-Schmuckler correlation against major/minor profiles only (K-S cannot distinguish modes — Dorian vs natural minor look the same; user manually picks mode)
  • matchChordFromChroma — weighted coverage score (inEnergy / (inEnergy + outEnergy×0.7)), requires root presence (chroma[r] >= 0.08), margin over second-best, diatonic/bass bonuses
  • MATCH_CHORD_TYPES — the subset of chord types used in real-time detection (not all of CHORD_TYPES)
  • detectRepeatingProgression — non-overlapping pattern match over last 20 chords, length 26

src/services/audioService.js is a self-contained tuner hook (useAudioTuner) used only by Tuner.jsx. It uses its own separate AudioContext with simple autocorrelation — independent from the main pitch/chord pipeline.

Design tokens (Tailwind)

Defined in tailwind.config.js: bg-surface (#0f0f0f), bg-panel (#1a1a1a), border-border (#2a2a2a), text-accent / bg-accent (#a855f7 purple). Use these rather than raw hex in components.

Key configuration (DEFAULTS in App.jsx)

Key Purpose
chromaSmooth Ring buffer size (frames averaged before chord check)
chordVoteThreshold Consecutive matching chord frames required to commit
chordMinScore Minimum coverage score from matchChordFromChroma
keyVoteWindow / keyVoteThreshold Rolling window size and consensus count for key lock
noteHistorySize Max pitch-class history kept for K-S key detection

These are exposed in Settings.jsx as sliders. configRef keeps a ref in sync so stable callbacks can read current values.

Instrument views

Fretboard.jsx and Piano.jsx are SVG-rendered visualisers. Both accept keyInfo, currentChord, and monoColor. They call getPentatonicScale, getFullScale, getChordTones from theory.js and colour notes by tier: chord tone (purple #a855f7) > pentatonic (amber or light purple in mono) > scale (dark gray or lightest purple in mono).

GitHub Actions

.github/workflows/release.yml builds Windows and macOS installers on tagged pushes (v*) using softprops/action-gh-release@v2. Build scripts use --publish never to prevent electron-builder's own publish step.