This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
- Avoid using
printstatements for debugging. Use logging instead. - Keep functions short and focused on a single responsibility.
- Use descriptive variable and function names.
- Follow PEP 8 style guidelines for Python code.
- Write unit tests for all new features and bug fixes.
- Document your code with docstrings and comments where necessary.
- Use type hints for function parameters and return values.
- Avoid global variables and mutable default arguments.
- Use context managers for resource management (e.g., file handling).
- Handle exceptions gracefully and provide meaningful error messages.
- Always fix broken tests/linting error even if you think you didn't create them
MIDI Chat Sequencer — a step sequencer with a chat-style CLI and browser-based visualization, outputting MIDI to Plugin Hosts (Element, Reason, etc).
- Syntax is command-driven. The user can use a mouse if they like, but everything should be modifiable with a command. When thinking of new features keep command control in mind
- Commands should be concise and easy to remember. Aim for a maximum of three words per command.
- Commands need to have a logical and consistent structure to make them easy to remember
- The UI should be generally read-only. Trying to combine things done via UI and commands is hard. Let's not do it
- The UI should be mostly static in that elements stay in place as the music moves with a "window" into what's happening.
- You should be able to manipulate the UI through logical command and macros
- We should be constantly building built-in macros to do common things
# Web UI (recommended)
export ANTHROPIC_API_KEY=sk-ant-... # optional, for AI input
uv run uvicorn server:app --reload
# Open http://127.0.0.1:8000
# CLI only
uv run python sequencer.pyDependencies managed via uv (Python >=3.13). uv sync to install.
uv run ruff check . # lint
uv run ruff check --fix . # auto-fix
uv run ruff format . # formatRules: E, F, W, I (isort), UP (pyupgrade), B (bugbear), SIM. Line length 100.
npx eslint static/ # JS lint
npx stylelint "static/*.css" # CSS lint
npx prettier --check static/ # formatting check
npx prettier --write static/ # auto-formatDependencies managed via npm. npm install to set up.
On macOS/Linux, a virtual MIDI port named "Chat Sequencer" is created automatically. Point your DAW's MIDI input to it.
Pattern— A named step sequence on a single MIDI channel. Steps hold(note, velocity, gate_steps)tuples. Serializable to/from dict for JSON save/load.Sequencer— The playback engine. Opens a virtual MIDI port viamido, runs a timing thread that fires note_on/note_off messages. Has an event callback system (add_listener/_notify) for real-time state pushes andget_state()for snapshots.ChatInterface— Command dispatcher.handle(line)returnstuple[bool, list[str]](continue flag + output lines). Both CLI and web UI share this.
- FastAPI serves static files and provides:
WebSocket /ws— real-time bidirectional: commands in, state/playhead/output outPOST /api/ai— natural language → Claude API → sequencer commands
- Frontend (
static/index.html,app.js,style.css) — Alpine.js for reactivity, custom CSS, no build step
The web UI is a vertical stack of four full-width sections inside <main>:
┌─────────────────────────────────────────────────────────────┐
│ TRANSPORT BAR (.transport-bar) │
│ Play/Stop, Save, Load, ?, Width preset, BPM │
├─────────────────────────────────────────┬───────────────────┤
│ DETAIL VIEW (.detail-panel) │ OVERVIEW │
│ Pattern grids with note rows, │ (.overview-panel) │
│ step headers, playhead │ Pattern list with │
│ Inside: .detail-stack, .detail- │ density bars │
│ pattern-block, .grid-container │ │
│ │ │
│ Together = PATTERN VIEW │ │
│ (.split-container) │ │
├─────────────────────────────────────────┴───────────────────┤
│ COMMAND VIEW (.command-view) │
│ MIDI monitor, log tabs (Command Log / AI Chat), │
│ command hint, dual input row │
├─────────────────────────────────────────────────────────────┤
│ SHORTCUT BAR (.shortcut-bar) │
│ Keyboard shortcut hints │
└─────────────────────────────────────────────────────────────┘
- Transport Bar — playback controls, session save/load, width preset, BPM
- Pattern View — the
.split-containerholding Detail View + Overview side-by-side- Detail View — full pattern grids (left side)
- Overview — compact pattern list with density bars (right sidebar, 260px)
- Command View — MIDI monitor, command/AI log tabs, command hint, input fields
- Shortcut Bar — keyboard shortcut reference
Server → Client: state (full patterns/bpm/playing), playhead (step number), output (command text), transport (play/stop/bpm)
Client → Server: {"type": "command", "line": "..."}
The handle() method is a flat if/elif dispatcher. Commands: play, stop, bpm, new, list, delete, mute, put, clear, show, euclid, arp, cc, pc, panic, ports, drums, save, load, help, quit.
Step specifiers support: individual (0,4,8), ranges (0-15), and stride (0-15:2).
Key helpers: note_name_to_midi(), midi_to_note_name(), parse_note_list(). DRUM_MAP maps names like "kick"→36, "snare"→38.