Acoustic monitoring database toolkit in Go. Use as an MCP server for AI assistants or as a CLI for direct access.
go build -o skraak
Start the server for use with Claude Desktop or other MCP clients:
./skraak mcp --db ./db/skraak.duckdb
Claude Code config* claude mcp add --transport stdio skraak_mcp -- /home/david/go/src/skraak/skraak mcp --db /home/david/go/src/skraak/db/skraak.duckdb
claude mcp add --transport stdio test_mcp -- /home/david/go/src/skraak/skraak mcp --db /home/david/go/src/skraak/db/test.duckdb
remove: claude mcp remove skraak_mcp
Claude Desktop config (~/.config/Claude/claude_desktop_config.json):
{
"mcpServers": {
"skraak": {
"command": "/home/david/go/src/skraak/skraak",
"args": ["mcp", "--db", "/home/david/go/src/skraak/db/skraak.duckdb"]
}
}
}
# Execute SQL query
./skraak sql --db ./db/skraak.duckdb "SELECT COUNT(*) FROM file WHERE active = true"
# Create resources
./skraak create dataset --db ./db/skraak.duckdb --name "My Dataset" --type unstructured
./skraak create location --db ./db/skraak.duckdb --dataset abc123 --name "Site A" --lat -36.85 --lon 174.76 --timezone Pacific/Auckland
./skraak create cluster --db ./db/skraak.duckdb --dataset abc123 --location loc456 --name "2024-01" --sample-rate 250000
./skraak create pattern --db ./db/skraak.duckdb --record 60 --sleep 1740
# Update resources
./skraak update dataset --db ./db/skraak.duckdb --id abc123 --name "Updated Name"
./skraak update location --db ./db/skraak.duckdb --id loc123 --name "Updated Name" --lat -36.85 --lon 174.76
./skraak update cluster --db ./db/skraak.duckdb --id cluster123 --name "Updated Name"
./skraak update pattern --db ./db/skraak.duckdb --id pattern123 --record 30 --sleep 1770
# Import commands
./skraak import file --db ./db/skraak.duckdb --dataset abc123 --location loc456 --cluster clust789 --path /path/to/file.wav
./skraak import folder --db ./db/skraak.duckdb --dataset abc123 --location loc456 --cluster clust789 --path /path/to/folder
./skraak import bulk --db ./db/skraak.duckdb --dataset abc123 --csv import.csv --log progress.log
./skraak import unstructured --db ./db/skraak.duckdb --dataset 4Sh8_7p1ocks --path "/media/david/Misc-2/Manu o Kahurangi kiwi survey (3)/Andrew Digby LSK - sorted files"
./skraak import selections --db ./db/skraak.duckdb --dataset abc123 --cluster clust789 --path /path/to/Clips_filter_date
# Export dataset (for collaboration, testing, or archival)
./skraak export dataset --db ./db/skraak.duckdb --id abc123 --output export.duckdb
./skraak export dataset --db ./db/skraak.duckdb --id abc123 --output export.duckdb --dry-run
# Event log replay (sync backup databases)
./skraak replay events --db ./backup.duckdb --log ./skraak.duckdb.events.jsonl
./skraak replay events --db ./backup.duckdb --log ./events.jsonl --dry-run
./skraak replay events --db ./backup.duckdb --log ./events.jsonl --last 10
# Call analysis (extract from ML predictions, review/classify)
./skraak calls from-preds --csv predictions.csv # Extract calls, write .data files
./skraak calls from-preds --csv preds.csv --dot-data=false > calls.json # JSON output only
./skraak calls show-images --file recording.wav.data # Display spectrograms
./skraak calls classify --folder ./data --reviewer David --bind k=Kiwi # Interactive classification
skraak calls classify --folder 2025-02-25 --reviewer David --color --img-dims 600 --bind a=eurbla, --bind b=nezbel1, --bind c=comcha, --bind d=saddle3, --bind e=pipipi1, --bind f=nezfan1, --bind g=gryger1, --bind i=tui1, --bind k=kea1, --bind l=lotkoe1, --bind m=morepo2, --bind n=nezrob3, --bind o=soioys1, --bind p=malpar2, --bind r=riflem1, --bind s=silver3, --bind t=tomtit1, --bind u=nezpig2, --bind w=nezkak1, --bind x=Noise, --bind z="Don't Know", --bind 1=Kiwi+Duet, --bind 2=Kiwi+Female, --bind 3=Kiwi+Male, --bind 4=Kiwi, --bind 5=Gecko
# File utilities
./skraak xxhash --file recording.wav # XXH64 hash (same format as DB)
./skraak metadata --file recording.wav # WAV metadata as JSON
./skraak time # Current time as JSON
Query:
execute_sql - Run SQL SELECT queries (JOINs, aggregates, CTEs supported)get_current_time - Current time with timezoneWrite:
create_or_update_dataset - Create or update a datasetcreate_or_update_location - Create or update a location with GPS/timezonecreate_or_update_cluster - Create or update a cluster within a locationcreate_or_update_pattern - Create or update a cyclic recording patternImport:
import_audio_files - Batch import WAV files from a folderimport_ml_selections - Import ML-detected selections from folder structureNew Command Structure (2026-02-21): Verb-first commands for natural language flow
create dataset instead of dataset createupdate location instead of location updateQuery:
sql - Execute SQL queries directlytime - Get current time as JSONData Management:
create - Create new resources (dataset, location, cluster, pattern)update - Update existing resources (dataset, location, cluster, pattern)Import:
import bulk - Bulk import from CSV file (structured dataset)import file - Import a single WAV file (structured dataset)import folder - Import all WAV files from a folder (structured dataset)import selections - Import ML selections from folder structure (structured dataset)Export:
export dataset - Export a dataset with all related data to new databaseEvent Log:
replay events - Replay event log on backup database for synchronizationCall Analysis:
calls from-preds - Extract clustered calls from ML predictions CSV, write .data filescalls show-images - Display spectrogram images from .data file (Kitty/Sixel graphics)calls classify - Interactive TUI for reviewing and classifying audio segmentsUtilities:
xxhash - Compute XXH64 hash of a file (JSON output)metadata - Extract WAV file metadata (JSON output)MCP server provides:
schema://full - Complete database schemaschema://table/{name} - Individual table definitionsAll mutating SQL operations (INSERT, UPDATE, DELETE) are automatically logged for backup synchronization.
Event log location: <database>.events.jsonl
Features:
Replay on backup database:
# Replay all events
./skraak replay events --db ./backup.duckdb --log ./skraak.duckdb.events.jsonl
# Preview without executing
./skraak replay events --db ./backup.duckdb --log ./events.jsonl --dry-run
# Replay last N events
./skraak replay events --db ./backup.duckdb --log ./events.jsonl --last 10
Event format (JSONL):
{
"id": "V1StGXR8_Z5jdHi6B-myT",
"timestamp": "2026-02-18T14:30:22+13:00",
"tool": "create_or_update_dataset",
"queries": [{"sql": "INSERT INTO ...", "parameters": [...]}],
"success": true,
"duration_ms": 45
}
Export a dataset with all related data to a new DuckDB database for collaboration, testing, or archival.
Use cases:
Export:
# Export dataset to new database
./skraak export dataset --db ./db/skraak.duckdb --id abc123 --output export.duckdb
# Preview without creating file
./skraak export dataset --db ./db/skraak.duckdb --id abc123 --output export.duckdb --dry-run
# Overwrite existing export
./skraak export dataset --db ./db/skraak.duckdb --id abc123 --output export.duckdb --force
What's exported:
Re-import changes:
# After collaborator returns event log, replay on backup
./skraak replay events --db ./backup.duckdb --log export.duckdb.events.jsonl
Extract and review bird calls from ML predictions using a three-step workflow.
Workflow:
# Write .data files alongside audio (default)
./skraak calls from-preds --csv predictions.csv
# JSON output only (no .data files)
./skraak calls from-preds --csv preds.csv --dot-data=false > calls.json
# Override filter name (parsed from CSV filename by default)
./skraak calls from-preds --csv preds.csv --filter my-filter
# Display spectrograms from .data file (Kitty graphics protocol)
./skraak calls show-images --file recording.wav.data
# With L4 colormap (Black-Red-Yellow)
./skraak calls show-images --file recording.wav.data --color
# Use Sixel protocol (for non-Kitty terminals)
./skraak calls show-images --file recording.wav.data --sixel
# Launch TUI for reviewing and classifying segments
./skraak calls classify --folder ./data --reviewer David --bind k=Kiwi
# Multiple key bindings
./skraak calls classify --folder ./data --reviewer David \
--bind k=Kiwi --bind d='Kiwi+Duet' --bind n='Don''t Know'
# Single file mode
./skraak calls classify --file recording.wav.data --reviewer David --bind k=Kiwi
# With color and custom image size
./skraak calls classify --folder ./data --reviewer David --bind k=Kiwi --color --img-dims 224
Key bindings format:
k=Kiwi - Press 'k' to classify as Kiwi (species only)d=Kiwi+Duet - Press 'd' to classify as Kiwi with Duet call type./db/skraak.duckdb./db/test.duckdb (use for development)# Run tests
go test ./...
# Run with coverage
go test -cover ./...
See CLAUDE.md for detailed development notes.