Skip to content

ramzxy/khor

Repository files navigation

khor

Realtime kernel orchestra for native Linux.
khor turns live system activity into deterministic music with eBPF collection, a built-in synth engine, and a control UI for shaping the result in real time.

khor dashboard overview

Live telemetry, system health, preset mapping, and output routing in the built-in dashboard.

khor runtime health and live signal lanes khor sequencer mapping and adapter routing

Overview

Khor (kernel choir) turns system activity into music on native Linux:

  • eBPF collectors aggregate low-overhead system metrics across exec, network, scheduler, block I/O, TCP retransmits, and hardware interrupts
  • /proc/pressure/memory (PSI) is polled for memory pressure — a slow-moving mood signal
  • a deterministic music engine maps those signals into notes, rhythm, and synth parameters
  • audio plays locally through miniaudio with PulseAudio, PipeWire, or ALSA
  • multi-channel MIDI output routes voice roles to separate channels for live DAW integration (melody Ch1, bass Ch2, chords Ch3, percussion Ch10)
  • optional outputs mirror the signal to OSC (UDP) and MIDI (ALSA sequencer)
  • a built-in web UI exposes status, charts, presets, and live controls
Collect Compose Perform
Trace kernel activity with eBPF probes and aggregate it into stable realtime metrics. Convert normalized signals into a deterministic step-sequencer score and synth modulation. Hear the result locally and steer it live through the dashboard, MIDI, or OSC.

Linux is the primary target. Root is not the normal run mode; use a one-time setcap for eBPF.

See ARCHITECTURE.md for the detailed dataflow.

Core Concepts

  1. eBPF Probes (The Ears): Traces execve (programs starting), net_dev_queue/netif_receive_skb (network traffic), sched_switch (context switches), block_rq_issue/block_rq_complete (disk I/O), tcp_retransmit_skb (network errors), and irq_handler_entry (hardware interrupts). Memory pressure is read from PSI (/proc/pressure/memory).
  2. Signal Pipeline (The Brain): Normalizes raw event counts into 0.0 to 1.0 control signals using logarithmic scaling and exponential smoothing. Each signal has tuned smoothing — TCP retransmits are kept spiky for percussive triggers, memory pressure is heavily smoothed as a slow mood signal.
  3. Music Engine (The Composer): A step sequencer that deterministically generates music based on these signals. Notes are tagged with MIDI channels per voice role (melody, bass, chords, percussion) for multi-track DAW routing.
  4. Audio Engine (The Voice): A custom polyphonic synthesizer (subtractive synthesis, ADSR, delay/reverb).

High-Level Architecture

graph TD
    subgraph Kernel Space
        P_Exec[Trace: Exec]
        P_Net[Trace: Network]
        P_Sched[Trace: Sched]
        P_Block[Trace: Block I/O]
        P_TCP[Trace: TCP Retransmit]
        P_IRQ[Trace: IRQ]

        P_Exec -->|Update| Map[Per-CPU Map Aggregation]
        P_Net -->|Update| Map
        P_Sched -->|Update| Map
        P_Block -->|Update| Map
        P_TCP -->|Update| Map
        P_IRQ -->|Update| Map

        Map -->|Flush Periodically| RB[BPF Ring Buffer]
    end

    subgraph Userspace Daemon
        PSI["PSI Memory Pressure"]
        Collector[BPF Collector]
        Signal[Signal Normalizer]
        Music[Music Engine]
        Audio[Audio Engine]
        MIDI[MIDI Out]
        OSC[OSC Out]
        API[HTTP API]

        RB -->|Read Events| Collector
        Collector -->|Raw Metrics| Signal
        PSI -->|Memory Pressure| Signal
        Signal -->|Smooth 0..1 Signals| Music
        Music -->|Multi-Channel Notes| Audio
        Music -->|Multi-Channel Notes| MIDI
        Music -->|Notes + Signals| OSC
        Audio -->|Sound| Speakers[Speakers]

        Signal -->|Metrics| API
        Music -->|State| API
    end

    subgraph UI
        Browser[Web Browser]
        Browser -->|Poll/SSE| API
    end
Loading

Signals

Signal Source Musical Role
exec sys_enter_execve tracepoint Note probability, accent chords, filter resonance
rx netif_receive_skb tracepoint Reverb mix, melody gating
tx net_dev_queue tracepoint Delay mix, arpeggio gating
csw sched_switch tracepoint Percussive click probability
io block_rq_complete tracepoint Filter cutoff (80Hz–9kHz)
retx tcp_retransmit_skb tracepoint Chromatic glitch stabs (deliberately off-scale)
irq irq_handler_entry tracepoint Ultra-short hi-hat texture in high octaves
mem /proc/pressure/memory PSI Mood — darkens filter, increases reverb, adds resonance strain

Quick Start (From Source)

1) System Dependencies

Ubuntu/Debian:

sudo apt-get update
sudo apt-get install -y \
  build-essential cmake pkg-config curl \
  clang llvm bpftool libbpf-dev linux-headers-$(uname -r) \
  libcap2-bin

Fedora:

sudo dnf install -y \
  gcc gcc-c++ make cmake pkgconf-pkg-config curl \
  clang llvm bpftool libbpf-devel \
  libcap

Optional (MIDI output via ALSA sequencer):

  • Ubuntu/Debian: sudo apt-get install -y libasound2-dev
  • Fedora: sudo dnf install -y alsa-lib-devel

2) Check eBPF Support

./scripts/linux-check.sh

You want /sys/kernel/btf/vmlinux present for CO-RE builds.

3) Fetch Single-Header Deps (miniaudio + httplib)

./scripts/fetch_deps.sh

4) Build

./scripts/linux-build.sh

5) Build UI + Run (Dev)

To serve the UI directly from the daemon in dev:

npm --prefix ui ci
npm --prefix ui run build
./scripts/linux-run.sh --ui-dir ui/dist

Open http://127.0.0.1:17321.

Alternative UI dev server (hot reload):

./scripts/linux-run.sh --no-audio --no-bpf
npm --prefix ui run dev

Set VITE_API_BASE if your daemon is not on the default address/port.

Install (User Daemon + UI + systemd --user)

./scripts/install.sh

Enable eBPF without sudo/root runtime (one-time):

sudo setcap cap_bpf,cap_perfmon,cap_sys_resource,cap_sys_admin,cap_dac_read_search+ep ~/.local/bin/khor-daemon
getcap ~/.local/bin/khor-daemon

Start on login:

systemctl --user daemon-reload
systemctl --user enable --now khor.service

Open http://127.0.0.1:17321.

Uninstall:

./scripts/uninstall.sh

Runtime Notes

Audio

  • Do not run the daemon as root if you expect desktop audio. PipeWire/Pulse are per-user services.
  • If you must run with elevated privileges for eBPF, prefer the one-time setcap above.
  • Use the UI "Outputs" section to pick a playback device and adjust master gain.
  • Debug backends:
    • force ALSA: KHOR_AUDIO_BACKEND=alsa ./scripts/linux-run.sh
    • force Pulse: KHOR_AUDIO_BACKEND=pulse ./scripts/linux-run.sh

eBPF Permissions

If /api/health shows BPF disabled: EPERM (or similar):

  1. Verify the binary has caps: getcap ~/.local/bin/khor-daemon
  2. Ensure your kernel supports CAP_BPF/CAP_PERFMON (older kernels may require root).
  3. Ubuntu/Debian Users: These distros set kernel.perf_event_paranoid=3 by default, which breaks unprivileged tracepoint attachment even with capabilities. To fix this, temporarily lower the value to the upstream kernel default:
    sudo sysctl -w kernel.perf_event_paranoid=2
    To persist this across reboots, add it to /etc/sysctl.d/60-khor-perf.conf.
  4. For libbpf debug logs: KHOR_DEBUG_LIBBPF=1 ./scripts/linux-run.sh

Fake mode is off by default. Enable it explicitly:

./scripts/linux-run.sh --fake --no-bpf

Configuration

Default config path:

  • ${XDG_CONFIG_HOME:-~/.config}/khor/config.json

The UI edits config via PUT /api/config, and the daemon persists it to that file.

Key fields:

  • listen.host / listen.port
  • ui.serve / ui.dir
  • features.bpf / features.audio / features.midi / features.osc / features.fake
  • music.* (bpm, key, scale, preset, density, smoothing)
  • audio.* (backend, device, sample_rate, master_gain)
  • midi.* (port, channel)
  • osc.* (host, port)
  • bpf.* (enabled_mask, sample_interval_ms, tgid_allow, tgid_deny, cgroup_id)

CLI

~/.local/bin/khor-daemon --help

Common flags:

  • --config PATH
  • --listen HOST:PORT
  • --ui-dir PATH
  • --no-bpf, --no-audio
  • --midi, --osc
  • --fake

HTTP API (v1)

All APIs are same-origin under /api/*.

  • GET /api/health
  • GET /api/metrics
  • GET /api/config
  • PUT /api/config (partial patch supported)
  • GET /api/presets
  • POST /api/preset/select?name=ambient|percussive|arp|drone
  • GET /api/audio/devices
  • POST /api/audio/device (JSON body: {"device":"id:<hex>"} or {"device":""} for default)
  • POST /api/actions/test_note
  • GET /api/stream (SSE, ~10Hz)

Examples:

curl -s http://127.0.0.1:17321/api/health | jq .
curl -s http://127.0.0.1:17321/api/metrics | jq .
curl -s http://127.0.0.1:17321/api/presets | jq .
curl -s -X POST 'http://127.0.0.1:17321/api/actions/test_note?midi=62&vel=0.7&dur=0.3'

MIDI (Optional)

MIDI output uses the ALSA sequencer and requires headers/libs at build time.

On Fedora:

sudo dnf install -y alsa-lib-devel
./scripts/linux-build.sh
./scripts/linux-run.sh --midi

Then connect the virtual port to a synth:

aconnect -l

Multi-Channel Routing

Notes are tagged with MIDI channels by voice role so DAWs can route them to separate instruments:

Channel Role Example VST
1 Melody Pad, lead synth
2 Bass Sub bass, 808
3 Chords/Pads Strings, pad
10 Percussion Drum kit, glitch FX

In your DAW, create four tracks each receiving from the "khor" MIDI port on the corresponding channel, assign a different VST instrument to each, and you have live kernel-driven multi-instrument music.

Control signals are also sent as MIDI CC on channel 1:

CC Signal
20 exec (process activity)
21 rx (network receive)
22 tx (network transmit)
23 csw (context switches)
24 io (block I/O)
74 filter cutoff

OSC (Optional)

Enable OSC:

./scripts/linux-run.sh --osc

Default target is 127.0.0.1:9000 (configurable).

Messages:

  • /khor/note (int channel, int midi, float vel, float dur)
  • /khor/signal (string name, float value01) — names: exec, rx, tx, csw, io, retx, irq, mem
  • /khor/metrics (float exec_s, float rx_kbs, float tx_kbs, float csw_s, float blk_r_kbs, float blk_w_kbs, float retx_s, float irq_s, float mem_pct)

Tests

./scripts/linux-build.sh
cd daemon/build
ctest --output-on-failure

License

Project license: see LICENSE.

Third-party notices: see THIRD_PARTY_NOTICES.md.

About

a bio-music system for Linux that translates real-time kernel activity into generative music

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors