CESP v1.0
Coding Event Sound Pack Specification
Overview
CESP defines a universal format for sound packs that respond to coding events in agentic IDEs. A single pack works across Claude Code, Cursor, Codex, and any tool that implements the specification.
The spec covers three things: a set of event categories that IDEs emit, a manifest format (openpeon.json) that maps categories to audio files, and player behavior requirements for how sounds should be played.
Key words: MUST, SHOULD, and MAY are used per RFC 2119.
Event Categories
CESP defines 9 event categories. Players MUST support the 6 core categories. Extended categories are optional.
Core Categories
| Category | Description |
|---|---|
| session.start | Session or workspace opens |
| task.acknowledge | Tool accepted work, is processing |
| task.complete | Work finished successfully |
| task.error | Something failed |
| input.required | Blocked, waiting for user input or approval |
| resource.limit | Rate, token, or quota limit hit |
Extended Categories
| Category | Description |
|---|---|
| user.spam | User sending commands too fast |
| session.end | Session closes gracefully |
| task.progress | Long task still running |
Manifest Format
Every pack MUST include an openpeon.json file at its root.
Required Fields
| Field | Type | Description |
|---|---|---|
| cesp_version | string | "1.0" |
| name | string | Machine-readable ID (a-z0-9, hyphens, underscores) |
| display_name | string | Human-readable name (1-128 chars) |
| version | string | Semantic version (e.g. 1.0.0) |
| categories | object | Map of category names to sound arrays |
Recommended Fields
| author | object | { name, github } — pack creator |
| license | string | SPDX identifier (MIT, CC-BY-NC-4.0) |
| language | string | BCP 47 tag (en, es, ru) |
| description | string | Short description (max 256 chars) |
Sound Entry
Each sound in a category has file (relative path), label (human description), and optional sha256 (hex digest, required for registry).
Example
{
"cesp_version": "1.0",
"name": "my-pack",
"display_name": "My Sound Pack",
"version": "1.0.0",
"description": "A custom sound pack for my IDE",
"author": {
"name": "yourname",
"github": "yourname"
},
"license": "CC-BY-NC-4.0",
"language": "en",
"categories": {
"session.start": {
"sounds": [
{
"file": "sounds/hello.mp3",
"label": "Hello!",
"sha256": "abc123..."
}
]
},
"task.complete": {
"sounds": [
{
"file": "sounds/done.mp3",
"label": "Done!",
"sha256": "def456..."
}
]
}
}
}Directory Structure
my-pack/
openpeon.json # Required manifest
sounds/ # Audio files
hello.mp3
done.mp3
error.mp3
README.md # Optional
LICENSE # Optional- Manifest MUST be named
openpeon.jsonat pack root - Audio paths use forward slashes, relative to manifest
- No
../traversal above pack root - Filenames:
[a-zA-Z0-9._-]+only
Audio Constraints
| Format | Extension | MIME |
|---|---|---|
| WAV | .wav | audio/wav |
| MP3 | .mp3 | audio/mpeg |
| OGG Vorbis | .ogg | audio/ogg |
- Individual files: max 1 MB
- Total pack: max 50 MB
- Players MUST validate magic bytes (RIFF, ID3/0xFF, OggS)
IDE Mapping
Each IDE maps its own events to CESP categories. The mapping is defined by the player, not the pack.
| IDE Event | CESP Category |
|---|---|
| Claude Code: SessionStart | session.start |
| Claude Code: Stop | task.complete |
| Claude Code: Notification (permission) | input.required |
| Codex: agent-turn-complete | task.complete |
| Cursor: stop | task.complete |
Player Behavior
- Players MUST pick a random sound from the category array
- Players SHOULD avoid repeating the last played sound (no-repeat)
- Players MUST support a master volume control (0.0 to 1.0)
- Players MUST allow individual categories to be disabled
- Players SHOULD support a global mute/pause toggle
- If a category has no sounds in the pack, the player MUST silently skip it
This is a summary. For the complete specification including JSON schemas:
Full Spec on GitHub