location
Location tracking, place recognition, visit history, and calendar attendance
Codex 또는 Claude로 설치 이 Prompt를 복사해 Codex, Claude 또는 다른 어시스턴트에 붙여 넣으면 Skill 페이지를 검토하고 설치를 진행할 수 있습니다.
메뉴
Location tracking, place recognition, visit history, and calendar attendance
Codex 또는 Claude로 설치 이 Prompt를 복사해 Codex, Claude 또는 다른 어시스턴트에 붙여 넣으면 Skill 페이지를 검토하고 설치를 진행할 수 있습니다.
SOC 직업 분류 기준
Calendar operations with CalDAV
Git repository management, GitLab merge requests, and GitHub pull requests
Persistent memory writes — USER.md (behavioral) and the knowledge graph (facts).
Accounting operations (ledger, invoicing, transactions, work log, investment portfolio) — runs in-process via the vendored money package
Send a push notification to the user's configured ntfy device(s). One-way (bot to phone), no reply channel.
Briefing formatting guidelines for chat messages
| name | location |
| triggers | ["location","gps","where","place","places","visit","visits","track","position","coordinates","attendance","reverse geocode","day summary","neighborhood","summary"] |
| description | Location tracking, place recognition, visit history, and calendar attendance |
| cli | true |
| env | [{"var":"LOCATION_DB_PATH","from":"setup_env"},{"var":"CALDAV_URL","from":"config","config_path":"caldav_url","when":"caldav_url","gate_has_discovered_calendars":true},{"var":"CALDAV_USERNAME","from":"config","config_path":"caldav_username","when":"caldav_url","gate_has_discovered_calendars":true},{"var":"CALDAV_PASSWORD","from":"config","config_path":"caldav_password","when":"caldav_url","gate_has_discovered_calendars":true,"sensitive":true}] |
GPS-based location tracking via the Overland iOS app. Tracks location pings, resolves named places, and records visits.
Places (named geofences) are stored in the database. Full CRUD via CLI:
places — list all saved places (includes id for each)learn — save current GPS position as a named placeupdate — modify an existing place (category, name, radius, coordinates, notes)delete — remove a place (also clears place assignment from historical pings)place-stats — visit count, first/last/longest visit, total time spent (derived from pings)Changes take effect on the next incoming GPS ping (no restart needed).
The web UI surfaces "discovered clusters" — recurring locations that aren't yet saved as named places. The same flow is available via CLI:
discover — find clusters of stationary pings not assigned to any place. Filters out clusters near existing places or inside dismissed zones.dismiss-cluster — record a lat/lon/radius zone so future discover calls skip it (use when the user doesn't want a place suggested again).list-dismissed — list dismissed cluster zones with their ids.restore-dismissed — un-dismiss a zone by id (so it can surface again).Run istota-skill location --help (or istota-skill location <subcommand> --help) to see the live argument list.
All commands output JSON. LOCATION_DB_PATH (the user's per-user location.db) is set automatically by the skill's setup_env hook. The reverse-geocode and day-summary subcommands also read ISTOTA_DB_PATH (the framework DB) for the cross-user reverse-geocode cache.
# Current location + place/visit info
istota-skill location current
# Recent pings (default: last 20; --date returns all pings for that day)
istota-skill location history
istota-skill location history --limit 50
istota-skill location history --date 2026-02-15
istota-skill location history --date 2026-02-15 --tz America/New_York
# List known places (each entry includes id, name, lat, lon, radius_meters, category, notes)
istota-skill location places
# Save current location as a named place (inserts into DB)
# Takes effect immediately on the next incoming ping
istota-skill location learn "coffee shop"
istota-skill location learn "gym" --category gym --radius 75
istota-skill location learn "office" --notes "side entrance, 4th floor"
# Update an existing place — identify by --name or --id
# Only specified fields are changed; others are left as-is
istota-skill location update --name "coffee shop" --category food
istota-skill location update --name "old name" --rename "new name"
istota-skill location update --id 42 --radius 200 --notes "back entrance"
istota-skill location update --id 42 --notes "" # clear notes
istota-skill location update --name "office" --lat 40.71 --lon -74.01
# Delete a place — identify by --name or --id
# Also removes the place assignment from historical pings
istota-skill location delete --name "coffee shop"
istota-skill location delete --id 42
# Check calendar attendance via GPS pings
# Requires CALDAV_URL, CALDAV_USERNAME, CALDAV_PASSWORD env vars
istota-skill location attendance
istota-skill location attendance --date 2026-02-15
istota-skill location attendance --event "dentist"
# Reverse geocode a single coordinate pair
istota-skill location reverse-geocode --lat 40.71 --lon -74.01
# Day summary: clusters pings into stops, resolves names via saved places
# or reverse geocoding, filters transit, merges consecutive same-location stops
istota-skill location day-summary --date 2026-03-08
istota-skill location day-summary --date 2026-03-08 --tz America/New_York
# Visit statistics for a place (by name or id)
istota-skill location place-stats --name "home"
istota-skill location place-stats --id 42
# Find unknown recurring clusters
istota-skill location discover
istota-skill location discover --min-pings 20
# Dismiss a cluster zone so it stops surfacing in discover
istota-skill location dismiss-cluster --lat 40.71 --lon -73.98 --radius 200
# List / un-dismiss
istota-skill location list-dismissed
istota-skill location restore-dismissed 7
Aliased as last (istota-skill location last).
{
"last_ping": {
"timestamp": "2026-02-20T10:30:00Z",
"lat": 40.71,
"lon": -73.98,
"accuracy": 5,
"activity_type": "stationary",
"place": "home"
},
"current_visit": {
"place_name": "home",
"entered_at": "2026-02-20T08:00:00Z",
"duration_minutes": 150,
"ping_count": 30
}
}
[
{
"timestamp": "2026-02-20T10:30:00Z",
"lat": 40.71,
"lon": -73.98,
"accuracy": 5,
"place": "home",
"activity_type": "stationary"
}
]
[
{
"id": 1,
"name": "home",
"lat": 40.71,
"lon": -73.98,
"radius_meters": 150,
"category": "home",
"notes": null
}
]
{
"status": "ok",
"place": "coffee shop",
"lat": 40.75,
"lon": -73.99,
"radius_meters": 100,
"message": "Saved 'coffee shop' at 40.7500, -73.9900"
}
{
"status": "ok",
"place": {
"id": 42,
"name": "coffee shop",
"lat": 40.75,
"lon": -73.99,
"radius_meters": 100,
"category": "food",
"notes": null
}
}
{
"status": "ok",
"deleted": "coffee shop"
}
{
"place_id": 42,
"total_visits": 12,
"first_visit": "2026-01-08T09:00:00Z",
"last_visit": "2026-04-22T18:30:00Z",
"avg_duration_min": 75,
"total_duration_min": 902,
"longest_visit_min": 210
}
{
"clusters": [
{
"lat": 40.7580,
"lon": -73.9855,
"total_pings": 38,
"first_seen": "2026-03-01T08:00:00Z",
"last_seen": "2026-04-25T17:30:00Z",
"radius_meters": 75
}
]
}
{
"dismissed": [
{
"id": 7,
"lat": 40.71,
"lon": -73.98,
"radius_meters": 100,
"dismissed_at": "2026-04-20T12:00:00Z"
}
]
}
{
"display_name": "123 Main St, New York, NY 10001, USA",
"neighborhood": "Downtown",
"suburb": "Central LA",
"road": "Main St",
"city": "New York",
"source": "nominatim"
}
Clusters the day's pings into stops. Resolves location names by: (1) direct place match from ping data, (2) proximity match against saved places (100m minimum radius), (3) reverse geocoding via Nominatim. Filters out transit clusters (1-2 pings without a place match). Merges consecutive stops at the same location.
{
"date": "2026-03-08",
"timezone": "America/Los_Angeles",
"ping_count": 120,
"transit_pings": 8,
"stops": [
{
"location": "home",
"location_source": "saved_place",
"arrived": "08:00",
"departed": "09:30",
"ping_count": 20,
"lat": 40.71,
"lon": -74.01
},
{
"location": "Magnolia Park",
"location_source": "nominatim",
"road": "Elm St",
"neighborhood": null,
"suburb": "Magnolia Park",
"arrived": "10:15",
"departed": "12:30",
"ping_count": 25,
"lat": 40.78,
"lon": -73.96
}
]
}
Cross-references calendar events with GPS pings to confirm attendance. Skips all-day events, events without a location, and virtual meetings. Resolves event locations by matching against known places first, then geocoding via Nominatim (results cached in DB). Uses a 30-minute buffer around event times and a default 200m radius (or the place's radius if matched).
{
"date": "2026-02-20",
"events": [
{
"summary": "Dentist",
"uid": "abc123",
"start": "2026-02-20T10:00:00-08:00",
"end": "2026-02-20T11:00:00-08:00",
"location": "123 Main St",
"location_resolved": true,
"resolution_source": "geocode",
"event_lat": 40.71,
"event_lon": -73.98,
"radius_meters": 200,
"attended": true,
"first_nearby_ping": "2026-02-20T09:45:00Z",
"last_nearby_ping": "2026-02-20T10:55:00Z",
"nearby_ping_count": 12
}
]
}