Goose-skills orthogonal-restaurant-booking
Book restaurant reservations via browser automation. Use when asked to make dinner reservations, book a table, or find availability at restaurants. Supports OpenTable, Resy, and direct restaurant booking sites.
install
source · Clone the upstream repo
git clone https://github.com/gooseworks-ai/goose-skills
Claude Code · Install into ~/.claude/skills/
T=$(mktemp -d) && git clone --depth=1 https://github.com/gooseworks-ai/goose-skills "$T" && mkdir -p ~/.claude/skills && cp -r "$T/skills/capabilities/orthogonal-restaurant-booking" ~/.claude/skills/gooseworks-ai-goose-skills-orthogonal-restaurant-booking && rm -rf "$T"
manifest:
skills/capabilities/orthogonal-restaurant-booking/SKILL.mdsource content
Restaurant Booking
Setup
Read your credentials from ~/.gooseworks/credentials.json:
export GOOSEWORKS_API_KEY=$(python3 -c "import json;print(json.load(open('$HOME/.gooseworks/credentials.json'))['api_key'])") export GOOSEWORKS_API_BASE=$(python3 -c "import json;print(json.load(open('$HOME/.gooseworks/credentials.json')).get('api_base','https://api.gooseworks.ai'))")
If ~/.gooseworks/credentials.json does not exist, tell the user to run:
npx gooseworks login
All endpoints use Bearer auth:
-H "Authorization: Bearer $GOOSEWORKS_API_KEY"
Book reservations using Notte browser automation via Orthogonal.
Requirements
- Orthogonal CLI (
) or API keynpm install -g @orth/cli - Guest info: name, email, phone
Quick Flow
- Start Notte session
- Navigate to booking site (OpenTable preferred)
- Select date/time/party size
- Fill contact form
- Submit and confirm
CLI Method (Recommended)
1. Start a Notte Session
curl -s -X POST $GOOSEWORKS_API_BASE/v1/proxy/orthogonal/run \ -H "Authorization: Bearer $GOOSEWORKS_API_KEY" \ -H "Content-Type: application/json" \ -d '{"api":"notte","path":"/sessions/start"}' --body '{"browser_type":"chromium","headless":true,"solve_captchas":true,"idle_timeout_minutes":10}'
Save the
session_id from the response.
2. Navigate to OpenTable
curl -s -X POST $GOOSEWORKS_API_BASE/v1/proxy/orthogonal/run \ -H "Authorization: Bearer $GOOSEWORKS_API_KEY" \ -H "Content-Type: application/json" \ -d '{"api":"notte","path":"/sessions/{session_id}/page/execute"}' --body '{"type":"goto","url":"https://www.opentable.com/r/{restaurant}?datetime=2026-02-17T19:00&covers=2"}'
3. Click Time Slot
curl -s -X POST $GOOSEWORKS_API_BASE/v1/proxy/orthogonal/run \ -H "Authorization: Bearer $GOOSEWORKS_API_KEY" \ -H "Content-Type: application/json" \ -d '{"api":"notte","path":"/sessions/{session_id}/page/execute"}' --body '{"type":"click","selector":"button:has-text(\"7:00 PM\")"}'
4. Select Seating (if prompted)
curl -s -X POST $GOOSEWORKS_API_BASE/v1/proxy/orthogonal/run \ -H "Authorization: Bearer $GOOSEWORKS_API_KEY" \ -H "Content-Type: application/json" \ -d '{"api":"notte","path":"/sessions/{session_id}/page/execute"}' --body '{"type":"click","selector":"button:has-text(\"Select\")"}'
5. Fill the Form
# First name curl -s -X POST $GOOSEWORKS_API_BASE/v1/proxy/orthogonal/run \ -H "Authorization: Bearer $GOOSEWORKS_API_KEY" \ -H "Content-Type: application/json" \ -d '{"api":"notte","path":"/sessions/{session_id}/page/execute"}' --body '{"type":"fill","selector":"input#firstName","value":"John"}' # Last name curl -s -X POST $GOOSEWORKS_API_BASE/v1/proxy/orthogonal/run \ -H "Authorization: Bearer $GOOSEWORKS_API_KEY" \ -H "Content-Type: application/json" \ -d '{"api":"notte","path":"/sessions/{session_id}/page/execute"}' --body '{"type":"fill","selector":"input#lastName","value":"Doe"}' # Email curl -s -X POST $GOOSEWORKS_API_BASE/v1/proxy/orthogonal/run \ -H "Authorization: Bearer $GOOSEWORKS_API_KEY" \ -H "Content-Type: application/json" \ -d '{"api":"notte","path":"/sessions/{session_id}/page/execute"}' --body '{"type":"fill","selector":"input#email","value":"john@example.com"}' # Phone curl -s -X POST $GOOSEWORKS_API_BASE/v1/proxy/orthogonal/run \ -H "Authorization: Bearer $GOOSEWORKS_API_KEY" \ -H "Content-Type: application/json" \ -d '{"api":"notte","path":"/sessions/{session_id}/page/execute"}' --body '{"type":"fill","selector":"input#phoneNumber","value":"4155551234"}'
6. Accept Terms
curl -s -X POST $GOOSEWORKS_API_BASE/v1/proxy/orthogonal/run \ -H "Authorization: Bearer $GOOSEWORKS_API_KEY" \ -H "Content-Type: application/json" \ -d '{"api":"notte","path":"/sessions/{session_id}/page/execute"}' --body '{"type":"click","selector":"text=I agree to the restaurant"}'
7. Submit Reservation
curl -s -X POST $GOOSEWORKS_API_BASE/v1/proxy/orthogonal/run \ -H "Authorization: Bearer $GOOSEWORKS_API_KEY" \ -H "Content-Type: application/json" \ -d '{"api":"notte","path":"/sessions/{session_id}/page/execute"}' --body '{"type":"click","selector":"button:has-text(\"Complete reservation\")"}'
8. Verify Confirmation
curl -s -X POST $GOOSEWORKS_API_BASE/v1/proxy/orthogonal/run \ -H "Authorization: Bearer $GOOSEWORKS_API_KEY" \ -H "Content-Type: application/json" \ -d '{"api":"notte","path":"/sessions/{session_id}/page/scrape"}' --body '{"only_main_content":true}'
Look for "confirmed" in the response.
API Method (curl)
# Start session curl -X POST "https://api.orth.sh/v1/run" \ -H "Content-Type: application/json" \ -d '{ "api": "notte", "path": "/sessions/start", "body": { "browser_type": "chromium", "headless": true, "solve_captchas": true, "idle_timeout_minutes": 10 } }' # Execute actions (same pattern) curl -X POST "https://api.orth.sh/v1/run" \ -H "Content-Type: application/json" \ -d '{ "api": "notte", "path": "/sessions/{session_id}/page/execute", "body": {"type":"goto","url":"https://www.opentable.com/..."} }'
Key Selectors (OpenTable)
| Field | Selector |
|---|---|
| First name | |
| Last name | |
| |
| Phone | |
| Terms checkbox | |
| Submit | |
| Time slots | |
| Seating select | |
Finding Restaurant IDs
Search OpenTable and extract from URL:
→ Foreign Cinemarestref=1906- Restaurant slug in URL path
Example URL format:
https://www.opentable.com/r/{restaurant-slug}?restref={id}&datetime={YYYY-MM-DDTHH:MM}&covers={n}
Tips
- OpenTable holds table for 5 minutes - move fast
- Use
action withfill
param (notvalue
withtype
)text - Click terms via label text, not checkbox directly
- No credit card needed - reservations are free
- Confirmation email sent automatically
Resy Alternative
If restaurant uses Resy:
https://resy.com/cities/{city}/venues/{restaurant}?date={YYYY-MM-DD}&seats={n}
Similar flow but different selectors. Scrape page first to identify form fields.
After Booking
- Create calendar event with
gog calendar create - Add attendees and location
- Include confirmation number in description