3BP2ELERVNEJWM3JDYGHLYQVDK5YQ7GEZR7G6UFDHY2JXKCLPRPQC SQZWTGAV6XDIFU42C5KIBHF5GIGPTXB6552Q7FXQCGHYPGQLFB5QC QQOATNCITSSIPKVUFNZEPN73TGU244GIAW6K37SILAGQWVQ4TCQQC IFVRAERTCCDICNTYTG3TX2WASB6RXQQEJWWXQMQZJSQDQ3HLE5OQC 4AFSDSVWQCDWDJEH3DD2S7UUB2LHLQOZLH5SZ6LS4LCSBG4EORXAC OGLLBQQYE5KICDMI6EX7ZI4TZT5RB7UFHH7O2DUOZ44QQXVL5YAAC 42UVPZU3N47BJIV5KBUN4KDB2JKP5QCGMNEOTZTLWP2XNUCNOARAC JCXEAHITH33V2SFDZX6JNPNFHSZPVSVLF556TMXDVJPDWS2TBINAC L4STQEXDGCPZXDHTEUBCOQKBMTFDRVXRLNFQHPDHOVXDCJO33LQQC X3K56A54LNNXODOH6MK22NTSEUQ54BUEZ3EL6ANKXYNL4RROL73QC NKQAT3RE4IBIWXVMI5LJUINDPHTANNMORZ5N2JFA4AN6UUB72KGAC W4KEYSU7BH2BURGWJC4SQ7IE6JCKRFXNKU54E5SXMB3SCICZXDWAC GXVVTHNXT2IZPR4OB77VMU6GXFEA5TUFZ2MHMA5ASU2DSTFPLDLQC 7NS27QXZMVTZBK4VPMYL5IKGSTTAWR6NDG5SOVITNX44VNIRZPMAC RMWLXG5HGB44LH3CEA7FWTAFPSZQZQGH52OHVQJUDP6ASPVDVQJAC VZGXBNYYO3E7EPFQ4GOLNVMRXXTQDDQZUU2BZ6JHNBDY4B2QLDAAC J62FGJ3BGFTUWEOUON4ATYNDFBEUIR6FCIOZSHOVHAA7KGFYHW6AC KS7LFF6M5Y6UGBBA7G63BJRR5XS4P4R3PSZPG752NSGZ3Z6GY72QC 2Y2ZW565SRONQ2UXPLX5SRP2HDFWMRF5KDXKSKVRCHBBGEGMTVIQC │ ├── skraak.duckdb # Production ⚠️│ └── test.duckdb # Test ✅├── tools/ # 11 tools (MCP-free)│ ├── time.go, sql.go # Read tools (2)│ ├── dataset.go, location.go, cluster.go, pattern.go # Write tools (4)│ ├── import_{files,file,ml_selections,unstructured}.go, bulk_file_import.go # Import (5)
├── tools/ # tools (MCP-free)
│ ├── cluster_import.go # Centralized import logic (553 lines)│ ├── validation.go # Input validation│ ├── astronomical.go # Solar/civil night, moon phase│ ├── audiomoth_parser.go # AudioMoth WAV comment parsing│ ├── filename_parser.go # Filename timestamp parsing + timezone│ ├── selection_parser.go # ML selection parsing│ ├── wav_metadata.go # WAV header parsing│ ├── xxh64.go # XXH64 hash│ └── *_test.go # 170+ tests, 91.5% coverage
---## Available Tools### Read Tools (2)- `get_current_time` - System time with timezone- `execute_sql` - Generic SQL SELECT queries (supports JOINs, aggregates, CTEs)- Security: Read-only database + keyword validation- Limits: Default 1000 rows (max 10000)### Write Tools (4)- `create_or_update_dataset` - Omit `id` to create, provide `id` to update- `create_or_update_location` - GPS + timezone- `create_or_update_cluster` - Recording groups- `create_or_update_pattern` - Record/sleep cycles### Import Tools (4 MCP tools, 1 CLI-only)**Dataset type requirements:**- Structured imports: `import_audio_files`, `bulk_file_import`, `import_ml_selections`- Unstructured imports: `import_unstructured`**MCP Tools:**- `import_audio_files` - Batch import folder → cluster- `bulk_file_import` - CSV-driven multi-location import- `import_ml_selections` - ML detection folders (`Clips_{filter}_{date}/Species/CallType/*.wav`)**CLI-only:**- `import file` - Single file import (use `skraak import file --db ... --path /path/to/file.wav`)- `import_unstructured` - No location/cluster hierarchy**Import pipeline:**- AudioMoth comment → filename → file modtime (timestamp fallback chain)- XXH64 hash, metadata extraction, astronomical calculations- Centralized logic in `utils/cluster_import.go`## Resources & Prompts
### Resources- `schema://full` - Complete 348-line schema- `schema://table/{table_name}` - Individual table definitions### PromptsSix SQL workflow templates:1. `query_active_datasets` - Dataset querying2. `explore_database_schema` - Schema exploration3. `explore_location_hierarchy` - Hierarchy navigation4. `query_location_data` - Location analysis5. `analyze_cluster_files` - File analysis6. `system_status_check` - Health checkAll teach SQL patterns with examples (SELECT, JOIN, GROUP BY, aggregates).
## SQL**Best practices:** `WHERE active = true`, use parameterized queries for IDs, use `LEFT JOIN` to include parent records, use `COUNT(DISTINCT)` when joining.---
# Entity management./skraak create dataset --db ./db/test.duckdb --name "Test" --type unstructured./skraak create location --db ./db/test.duckdb --dataset abc123 --name "Site A" --lat -36.85 --lon 174.76 --timezone Pacific/Auckland./skraak create cluster --db ./db/test.duckdb --dataset abc123 --location loc456 --name "2024-01" --sample-rate 250000# Import./skraak import file --db ./db/test.duckdb --dataset abc123 --location loc456 --cluster clust789 --path /path/to/file.wav./skraak import folder --db ./db/test.duckdb --dataset abc123 --location loc456 --cluster clust789 --path /path/to/folder./skraak import bulk --db ./db/test.duckdb --dataset abc123 --csv import.csv --log progress.log# Utilities./skraak xxhash --file recording.wav./skraak metadata --file recording.wav./skraak time
All mutating SQL operations logged to `<database>.events.jsonl` for backup synchronization.**What's logged:**- INSERT, UPDATE, DELETE operations- On successful commit only (rollbacks discarded)**Replay on backup:**```bashskraak replay events --db backup.duckdb --log skraak.duckdb.events.jsonlskraak replay events --db backup.duckdb --log events.jsonl --dry-runskraak replay events --db backup.duckdb --log events.jsonl --last 10```**Key files:**- `db/tx_logger.go` - Transaction wrapper for logging- `cmd/replay.go` - Replay CLI command---## Dataset ExportExport a dataset with all related data to a new DuckDB database.```bashskraak export dataset --db skraak.duckdb --id abc123 --output export.duckdbskraak export dataset --db skraak.duckdb --id abc123 --output export.duckdb --dry-run```**Use cases:** Collaboration, testing (small DB vs 1.5 GB), archival**Key files:**- `tools/export.go` - Export logic with table manifest- `db/schema.go` - Schema utilities (DDL extraction, FK ordering)---## Common Issues- **Query too large:** Use `LIMIT` (default 1000, max 10000)- **Server exits immediately:** Normal - runs in stdio mode (waits for MCP input)- **SQL syntax error:** use schema resources---## Claude Desktop Configuration`~/.config/Claude/claude_desktop_config.json`:```json{"mcpServers": {"skraak": {"command": "/home/david/go/src/skraak/skraak","args": ["mcp", "--db", "/home/david/go/src/skraak/db/skraak.duckdb"]}}}```Restart Claude Desktop after changes.