Recipes

Copy-paste examples for the most common tasks. All examples assume NeuroSkill™ is running locally. See the API reference and CLI docs for full schemas.

Before you start: Launch NeuroSkill™ and ensure your Muse headset is connected and showing green signal quality. The WebSocket server starts automatically on ws://localhost:8375. Use skill status to confirm it's reachable.

Streaming

Stream live metrics

Python

Connect to the WebSocket server and print focus score + frontal alpha every epoch (~4 Hz). Install pip install websockets first.

Python · stream_metrics.py
import asyncio, json import websockets async def stream(): async with websockets.connect("ws://localhost:8375") as ws: async for raw in ws:
            msg  = json.loads(raw) if msg["event"] != "eeg-bands": continue p     = msg["payload"]
            focus = p["focus_score"]
            faa   = p["faa"]
            af7_a = p["channels"][1]["rel_alpha"] # AF7 print(f"focus={focus:.0f}  FAA={faa:+.3f}  AF7α={af7_a:.3f}")

asyncio.run(stream())

Stream live metrics

Node.js

Same stream using the ws package. Install with npm install ws.

JavaScript · stream.mjs
import WebSocket from 'ws'; const ws = new WebSocket('ws://localhost:8375');

ws.on('open', () => console.log('connected to NeuroSkill™'));

ws.on('message', (raw) => { const { event, payload: p } = JSON.parse(raw); if (event !== 'eeg-bands') return; const { focus_score, faa, channels } = p;
  console.log(`focus=${focus_score.toFixed(0)}  FAA=${faa.toFixed(3)}  AF7α=${channels[1].rel_alpha.toFixed(3)}`);
});

ws.on('error', (err) => console.error('NeuroSkill™ not running?', err.message));

Labels & Events

Label an event

Python

Send a timestamped annotation from Python — useful for marking stimulus onset, task start, or any experiment event.

Python · label.py
import asyncio, json import websockets async def label(text: str): async with websockets.connect("ws://localhost:8375") as ws: await ws.send(json.dumps({ "command": "label", "params":  {"label": text},
        }))
        resp = json.loads(await ws.recv())
        ts   = resp["payload"]["timestamp"] print(f"labeled '${text}' at t=${ts}") # Example: mark stimulus onset in an experiment asyncio.run(label("stimulus onset — trial 1"))

Label from the terminal

bash

One-liner using the CLI — handy from a second terminal or a keybinding while recording.

bash
# Label a single moment skill label "meditation start" # Label with auto-generated timestamp in the message skill label "task begin — $(date -u +%FT%TZ)" # Label multiple events in a loop for i in 1 2 3 4 5; do skill label "trial $i start" sleep 30 done

Reports

Get device status as JSON

bash

Pull a one-shot status snapshot — battery level, per-channel signal quality, and current brain scores.

bash
# Full status as pretty JSON skill status --json | jq . # Just battery + quality summary skill status --json | jq '{
  battery:  .battery_percent,
  quality:  [.channels[] | {ch: .channel, q: .quality}],
  focus:    .focus_score,
  relax:    .relaxation_score
}' # Exit non-zero if any channel is not "Good" skill status --json \
  | jq -e 'all(.channels[].quality == "Good")' \
  && echo "all channels good" \
  || echo "signal quality issue"

Generate a sleep report

bash

Export the AASM sleep staging summary for the latest session. Requires a session of at least 30 minutes.

bash
# Print sleep summary to terminal skill sleep --session latest # Export as JSON skill sleep --session latest --json | jq '{
  efficiency:   .efficiency,
  total_min:    .total_minutes,
  rem_pct:      .rem_percent,
  n3_pct:       .n3_percent,
  onset_min:    .sleep_onset_minutes
}' # Save report with date-stamped filename skill sleep --session latest --json \
  > "sleep_$(date +%Y-%m-%d).json"

Automation

Alert when focus drops

Python

Monitor the stream and send a macOS notification when focus falls below a threshold for more than N consecutive epochs (~5 s each).

Python · focus_alert.py
import asyncio, json, subprocess import websockets

THRESHOLD  = 35 # focus score 0–100 EPOCHS_LOW = 3 # consecutive epochs before alerting async def monitor():
    low_streak = 0 async with websockets.connect("ws://localhost:8375") as ws: async for raw in ws:
            msg = json.loads(raw) if msg["event"] != "eeg-bands": continue focus = msg["payload"]["focus_score"] if focus < THRESHOLD:
                low_streak += 1 else:
                low_streak = 0 if low_streak == EPOCHS_LOW:
                subprocess.run([ "osascript", "-e", f'display notification "Focus dropped to {focus:.0f}" with title "Skill"',
                ])

asyncio.run(monitor())

Replace osascript with notify-send on Linux or any HTTP webhook for cross-platform use.

Record a timed session from a script

bash

Wait until NeuroSkill™ reports green signal quality, then label the start, sleep for the desired duration, label the end, and export the sleep report — all unattended.

bash · record_session.sh
#!/usr/bin/env bash set -euo pipefail
DURATION=3600 # seconds # Wait for all channels to be Good echo "Waiting for signal quality…" until skill status --json \
  | jq -e 'all(.channels[].quality == "Good")' >/dev/null 2>&1; do sleep 5 done echo "Recording for $DURATION s…" skill label "session start" sleep "$DURATION" skill label "session end" # Export report OUT="report_$(date +%Y-%m-%dT%H-%M).json" skill sleep --session latest --json > "$OUT" echo "Report saved to $OUT"

CLI

The TypeScript CLI (cli.ts) wraps the WebSocket API with mDNS auto-discovery, session-aware defaults, colourised output, and --json mode. Run npm install once in the NeuroSkill™ project root, then use npx neuroskill <command> — no global install needed. See the full CLI reference ↗ for schemas.

Full system snapshot

tsx

One call returns battery, signal quality, all 60+ scores, embedding counts, 48-hour sleep summary, session streak, and today-vs-7-day averages. Pipe --json output to jq for any field.

bash
# Colourised human-readable output npx neuroskill status # Key metrics as a compact JSON object npx neuroskill status --json | jq '{
  battery: .device.battery,
  focus:   .scores.focus,
  relax:   .scores.relaxation,
  hr:      .scores.hr,
  streak:  .history.current_streak_days
}' # Watch focus score live every 10 seconds (macOS/Linux) watch -n 10 'npx neuroskill status --json | jq ".scores.focus"'

List sessions and extract timestamps

tsx

List every recording session across all days, newest first. Pull timestamps into shell variables to feed other commands precisely.

bash
# List all sessions (colourised table) npx neuroskill sessions # Extract last session's start + end as shell variables SESSIONS=$(npx neuroskill sessions --json | jq '.sessions')
START=$(echo "$SESSIONS" | jq -r '.[0].start_utc')
END=$(echo  "$SESSIONS" | jq -r '.[0].end_utc')
echo "Last session: $START → $END" # Total recorded hours across all sessions npx neuroskill sessions --json \
  | jq '[.sessions[] | .end_utc - .start_utc] | add / 3600'

A/B session comparison

tsx

Compare any two time windows side-by-side: aggregated metric averages, per-metric deltas with percentage change, and lists of improved/declined signals. Without flags, auto-selects the last two sessions. Also queues a UMAP job automatically.

bash
# Auto: compare last two sessions npx neuroskill compare # Explicit session ranges (copy from the "rerun:" line) npx neuroskill compare \
  --a-start 1740380100 --a-end 1740382665 \
  --b-start 1740412800 --b-end 1740415510 # What improved between the two sessions? npx neuroskill compare --json | jq '.insights.improved' # Full focus delta (value, percent, direction) npx neuroskill compare --json | jq '.insights.deltas.focus' # Side-by-side focus + HR for a quick summary npx neuroskill compare --json | jq '{
  focus_a: .a.focus, focus_b: .b.focus,
  hr_a:    .a.hr,    hr_b:    .b.hr
}'

Brain Nebula™ projection with live progress

tsx

Kicks off a Brain Nebula™ projection (GPU-accelerated UMAP via wgpu/CubeCL), streams a live progress bar showing epoch count, ms/epoch, and ETA, then prints cluster analysis when done. Results are cached in ~/.skill/umap_cache/.

bash
# Run UMAP on last two sessions (shows progress bar) npx neuroskill umap # Specific session ranges npx neuroskill umap \
  --a-start 1740380100 --a-end 1740382665 \
  --b-start 1740412800 --b-end 1740415510 # Save all 3D points to a file for plotting in Python/R npx neuroskill umap --json | jq '.result.points' > umap_points.json # How well separated were the two sessions? npx neuroskill umap --json | jq '.result.analysis.separation_score'

A higher separation_score means the two sessions occupied more distinct regions of embedding space — a sign of meaningfully different brain states.

Passively stream events

tsx

Collect all broadcast events for a fixed window without sending any commands. Useful for verifying the headset is streaming, logging event rates, or piping to external tools.

bash
# 5-second listen (default) — shows event-type counts npx neuroskill listen # 30-second capture → save raw events to file npx neuroskill listen --seconds 30 --json > events.json # Count events by type from a capture file jq 'group_by(.event) | map({event: .[0].event, count: length})' events.json # Live focus score from the stream (one per epoch) npx neuroskill listen --seconds 60 --json \
  | jq '.[] | select(.event=="eeg-bands") | .payload.focus_score'

Send arbitrary commands (raw)

tsx

Send any JSON directly to the WebSocket API and print the full response. Useful for testing custom parameters, undocumented fields, or one-off queries.

bash
# Status via raw command npx neuroskill raw '{"command":"status"}' # Search with exact parameters npx neuroskill raw \
  '{"command":"search","start_utc":1740412800,"end_utc":1740415500,"k":3}' \
  --json # Backdate a label (label_start_utc overrides current time) npx neuroskill raw \
  '{"command":"label","text":"eyes closed","label_start_utc":1740412900}' \
  --json # Export a date range as CSV npx neuroskill raw \
  '{"command":"export","start_utc":1740380100,"end_utc":1740415510,"format":"csv"}' \
  --json

Chain commands into a workflow script

tsx

Combine sessions + compare + sleep into a single script that runs after every recording and emails or logs a summary.

bash · daily_report.sh
#!/usr/bin/env bash set -euo pipefail # ── 1. Fetch session list ────────────────────────────── SESSIONS=$(npx neuroskill sessions --json | jq '.sessions')
N=$(echo "$SESSIONS" | jq 'length')

[ "$N" -lt 2 ] && { echo "Need ≥ 2 sessions"; exit 1; } # ── 2. Extract last two session ranges ──────────────── B_START=$(echo "$SESSIONS" | jq -r '.[0].start_utc')
B_END=$(echo   "$SESSIONS" | jq -r '.[0].end_utc')
A_START=$(echo "$SESSIONS" | jq -r '.[1].start_utc')
A_END=$(echo   "$SESSIONS" | jq -r '.[1].end_utc') # ── 3. Compare ──────────────────────────────────────── COMPARE=$(npx neuroskill compare \
  --a-start "$A_START" --a-end "$A_END" \
  --b-start "$B_START" --b-end "$B_END" \
  --json)

IMPROVED=$(echo "$COMPARE" | jq -r '.insights.improved | join(", ")')
DECLINED=$(echo "$COMPARE" | jq -r '.insights.declined | join(", ")')
FOCUS_D=$(echo  "$COMPARE" | jq   '.insights.deltas.focus.pct // 0 | round') # ── 4. Sleep summary ────────────────────────────────── SLEEP=$(npx neuroskill sleep --start "$A_START" --end "$B_END" --json)
EFF=$(echo "$SLEEP" | jq '.analysis.efficiency_pct') # ── 5. Print report ─────────────────────────────────── echo "=== Daily Report $(date +%F) ==="
echo "Focus change:  $FOCUS_D%"
echo "Improved:      $IMPROVED"
echo "Declined:      $DECLINED"
echo "Sleep efficiency: $EFF%"

Pipe the final output to mail, curl (Slack webhook), or a cron log. The rerun: lines from each command give reproducible time-stamped invocations to store alongside the report.

All field names match the live payloads documented in the API reference and CLI docs. Run npx neuroskill status --json | jq keys to inspect available fields at runtime.

← Back to NeuroSkill™