diff --git a/examples/c/Makefile b/examples/c/Makefile
index 912b4e5e..6a10680f 100644
--- a/examples/c/Makefile
+++ b/examples/c/Makefile
@@ -24,7 +24,7 @@ INCLUDES := -I$(OUTPUT) -I../../libbpf/include/uapi -I$(dir $(VMLINUX)) -I$(LIBB
CFLAGS := -g -Wall
ALL_LDFLAGS := $(LDFLAGS) $(EXTRA_LDFLAGS)
-APPS = minimal minimal_legacy minimal_ns bootstrap bootstrap_legacy uprobe kprobe fentry \
+APPS = minimal spy minimal_legacy minimal_ns bootstrap bootstrap_legacy uprobe kprobe fentry \
usdt sockfilter tc ksyscall task_iter lsm
CARGO ?= $(shell which cargo)
diff --git a/examples/c/Test.txt b/examples/c/Test.txt
new file mode 100644
index 00000000..e69de29b
diff --git a/examples/c/brain.py b/examples/c/brain.py
new file mode 100644
index 00000000..5cfba8c2
--- /dev/null
+++ b/examples/c/brain.py
@@ -0,0 +1,75 @@
+import sys
+import re
+from collections import deque
+from sklearn.ensemble import IsolationForest
+
+# --- TUNING PARAMETERS ---
+WINDOW_SIZE = 2000 # The AI remembers the last 2000 system events
+RETRAIN_EVERY = 300 # Refresh the model every 300 new events
+CONTAMINATION = 0.001 # Sensitivity (0.1% of events flagged as weird)
+
+# --- THE ENGINE ---
+window = deque(maxlen=WINDOW_SIZE)
+model = None
+events_since_train = 0
+
+def normalize_path(path):
+ """
+ Strips random hashes/hex from filenames (Spotify/Zen noise).
+ Example: 'data_A53F00B8.bin' -> 'data_HASH.bin'
+ """
+ return re.sub(r'[a-fA-F0-9]{8,}', 'HASH', path)
+
+def get_features(pid, comm, filename):
+ """Turns raw kernel data into a numeric vector."""
+ norm_path = normalize_path(filename)
+ return [
+ float(pid) / 100000, # Normalized PID
+ len(comm), # Process name length
+ len(norm_path), # Normalized path length
+ norm_path.count('/'), # Folder depth
+ 1 if ".cache" in filename else 0 # Cache flag
+ ]
+
+print(" KernelTrace AI: Adaptive Engine Starting...")
+
+try:
+ for line in sys.stdin:
+ try:
+ # Parse the CSV data from the C loader
+ parts = line.strip().split(',', 2)
+ if len(parts) < 3: continue
+ pid, comm, filename = parts
+
+ # 1. Feature Engineering
+ features = get_features(pid, comm, filename)
+ window.append(features)
+ events_since_train += 1
+
+ # 2. Initial Training
+ if model is None and len(window) == WINDOW_SIZE:
+ print(" Baseline captured. Protection Active.")
+ model = IsolationForest(contamination=CONTAMINATION, n_jobs=-1)
+ model.fit(list(window))
+
+ # 3. Sliding Window Retrain
+ if model and events_since_train >= RETRAIN_EVERY:
+ model.fit(list(window))
+ events_since_train = 0
+ # print("AI Brain updated with recent system patterns.")
+
+ # 4. Anomaly Detection
+ if model:
+ prediction = model.predict([features])[0]
+ if prediction == -1:
+ score = model.decision_function([features])[0]
+ # Print formatted for the Bun server pipe
+ print(f" ALERT | Score: {score:.3f} | Proc: {comm} | Path: {filename}")
+ sys.stdout.flush() # Ensure the pipe sees this immediately
+
+ except ValueError:
+ continue
+
+except KeyboardInterrupt:
+ print("\n\n Brain shutting down safely. Great hunt!")
+ sys.exit(0)
diff --git a/examples/c/index.html b/examples/c/index.html
new file mode 100644
index 00000000..31142864
--- /dev/null
+++ b/examples/c/index.html
@@ -0,0 +1,15 @@
+
+ 🛡️ KERNEL-TRACE AI ENGINE
+
+
+
+
diff --git a/examples/c/server.ts b/examples/c/server.ts
new file mode 100644
index 00000000..89453e83
--- /dev/null
+++ b/examples/c/server.ts
@@ -0,0 +1,21 @@
+// server.ts
+const server = Bun.serve({
+ port: 3000,
+ fetch(req, server) {
+ if (server.upgrade(req)) return;
+ return new Response(Bun.file("index.html"));
+ },
+ websocket: {
+ open(ws) { ws.subscribe("alerts"); },
+ message(ws, msg) {},
+ },
+});
+
+console.log("🚀 Dashboard: http://localhost:3000");
+
+// PIPE: Read Python alerts from stdin and push to browser
+const decoder = new TextDecoder();
+for await (const chunk of Bun.stdin.stream()) {
+ const text = decoder.decode(chunk);
+ server.publish("alerts", text);
+}
diff --git a/examples/c/spy b/examples/c/spy
new file mode 100755
index 00000000..ebf7c96d
Binary files /dev/null and b/examples/c/spy differ
diff --git a/examples/c/spy.bpf.c b/examples/c/spy.bpf.c
new file mode 100644
index 00000000..5518170d
--- /dev/null
+++ b/examples/c/spy.bpf.c
@@ -0,0 +1,37 @@
+#include "vmlinux.h"
+ #include
+struct event {
+ int pid;
+ char comm[16];
+ char filename[256];
+};
+
+// This defines the Ring Buffer Map
+struct {
+ __uint(type, BPF_MAP_TYPE_RINGBUF);
+ __uint(max_entries, 256 * 1024); // 256KB of memory
+} rb SEC(".maps");
+
+SEC("tp/syscalls/sys_enter_openat")
+int handle_tp(struct trace_event_raw_sys_enter *ctx) {
+ struct event *e;
+
+ // 1. Reserve space in the ring buffer for one event
+ e = bpf_ringbuf_reserve(&rb, sizeof(*e), 0);
+ if (!e)
+ return 0; // If buffer is full, just skip (don't crash the kernel!)
+
+ // 2. Fill the data
+ e->pid = bpf_get_current_pid_tgid() >> 32; // Get the actual PID
+ bpf_get_current_comm(&e->comm, sizeof(e->comm));
+
+ const char *user_ptr = (const char *)ctx->args[1];
+ bpf_probe_read_user_str(&e->filename, sizeof(e->filename), user_ptr);
+
+ // 3. Submit to the ring buffer (Python can now see it!)
+ bpf_ringbuf_submit(e, 0);
+
+ return 0;
+}
+
+char LICENSE[] SEC("license") = "Dual BSD/GPL";
diff --git a/examples/c/spy.c b/examples/c/spy.c
new file mode 100644
index 00000000..b316af56
--- /dev/null
+++ b/examples/c/spy.c
@@ -0,0 +1,61 @@
+// SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause)
+/* Copyright (c) 2020 Facebook */
+#include
+#include
+#include
+#include
+#include "minimal.skel.h"
+#include "spy.skel.h"
+
+static int libbpf_print_fn(enum libbpf_print_level level, const char *format, va_list args)
+{
+ return vfprintf(stderr, format, args);
+}
+/* This struct must match exactly what is in your spy.bpf.c */
+struct event {
+ int pid;
+ char comm[16];
+ char filename[256];
+};
+
+/* The Callback: This is called every time a new event arrives */
+static int handle_event(void *ctx, void *data, size_t data_sz) {
+ const struct event *e = data;
+
+ /* Clean output for the Python Brain to read */
+ printf("%d,%s,%s\n", e->pid, e->comm, e->filename);
+ fflush(stdout);
+ return 0;
+}
+int main(int argc, char **argv) {
+ struct spy_bpf *skel;
+ struct ring_buffer *rb = NULL;
+ int err;
+
+ skel = spy_bpf__open_and_load();
+ if (!skel) return 1;
+
+ err = spy_bpf__attach(skel);
+ if (err) goto cleanup;
+
+ /* Set up the Ring Buffer manager to use our handle_event function */
+ rb = ring_buffer__new(bpf_map__fd(skel->maps.rb), handle_event, NULL, NULL);
+ if (!rb) {
+ fprintf(stderr, "Failed to create ring buffer\n");
+ goto cleanup;
+ }
+
+ printf("KernelSpy Active. Streaming to Brain...\n");
+
+ /* Poll the buffer infinitely */
+ while (true) {
+ err = ring_buffer__poll(rb, 100 /* timeout in ms */);
+ if (err == -EINTR) continue;
+ if (err < 0) break;
+ }
+
+cleanup:
+ ring_buffer__free(rb);
+ spy_bpf__destroy(skel);
+ return 0;
+}