| name | vhs-search |
| description | Search VHS Berlin courses using natural language. Converts queries like 'Find A2 German evening courses in Neukölln' into structured VHS searches, extracts results, and presents them in a clean format. Use when the user wants to find specific VHS Berlin courses. |
| argument-hint | [natural language search query] |
| allowed-tools | ["Bash","Read","Write"] |
VHS Berlin Course Search
Convert natural language queries into VHS Berlin course searches, run deterministic fetch+parse scripts, and present results cleanly.
Configuration
Read DB path from .claude/vhs-berlin-agent.local.md (frontmatter db_path), else default ~/.local/share/vhs-berlin/vhs.db.
Resolve bun
BUN=$(command -v bun 2>/dev/null || echo "$HOME/.bun/bin/bun")
Workflow
Step 1: Parse the user query
Extract structured parameters from the natural language query and build a query-json object:
| Field | Examples |
|---|
district | "Mitte", "Neukölln", "Pankow" |
category | "German", "pottery", "yoga", "cooking" |
level | "A1", "A2", "B1", "B2" (language courses) |
time | "evening", "morning", "weekend" |
keyword | free-text search term |
max_price | numeric (e.g. 90) |
Example JSON for "Find A2 German evening courses in Neukölln":
{"district": "Neukölln", "category": "German", "level": "A2", "time": "evening"}
Step 2: Run search script
$BUN run ${CLAUDE_PLUGIN_ROOT}/scripts/search.ts \
--query-json '{"district":"Neukölln","category":"German","level":"A2"}' \
--db-path "<db_path>" \
--limit 20
The script:
- Reads
config/query-registry.yaml to build the VHS search URL
- Fetches via direct HTTP (tier 1) or Jina reader fallback (tier 2)
- Parses course links with cheerio
- Upserts results into the SQLite DB (if initialized)
- Outputs JSON:
{courses, url, tier, via?, verification}
Step 3: Handle verification result
Check verification.ok in the output:
Never silently return empty results. If the script reports a verification failure, surface it.
Step 4: Check for special registration rules
After parsing, check each course title/category against config/extraction-rules.yaml patterns:
- Integration courses (Integrationskurs, Alphabetisierung): consultation required — warn the user before they try to book online
- Language courses with A1/A2/B1/B2: placement test may be required
- Seniorenkurs / für Frauen: eligibility restrictions may apply
Step 5: Present results
## Found N matching courses
### Deutsch als Fremdsprache A2.2 — Mitte
- **Where**: VHS Linienstraße
- **When**: [schedule_text]
- **Price**: [price_text]
- **Status**: [booking_status]
- **Link**: [source_url]
---
**Want to watch this search for changes?** Say "Watch this search" to save it.
If no courses found (verification ok but 0 results): suggest broadening the search or checking the VHS website directly.
See Also
vhs-watch skill — save and monitor searches
vhs-digest skill — weekly summaries
config/query-registry.yaml — URL patterns and district codes
config/extraction-rules.yaml — registration rule patterns