atris/skills/calendar/SKILL.md
Google Calendar integration via AtrisOS API. View, create, and manage calendar events. Use when user asks about calendar, schedule, meetings, or events.
npx skillsauth add atrislabs/atris calendarInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
Drop this in
~/.claude/skills/calendar/SKILL.mdand Claude Code becomes your calendar assistant.
Before any calendar operation, run this bootstrap to ensure everything is set up:
#!/bin/bash
set -e
# 1. Check if atris CLI is installed
if ! command -v atris &> /dev/null; then
echo "Installing atris CLI..."
npm install -g atris
fi
# 2. Check if logged in to AtrisOS
if [ ! -f ~/.atris/credentials.json ]; then
echo "Not logged in to AtrisOS."
echo ""
echo "Option 1 (interactive): Run 'atris login' and follow prompts"
echo "Option 2 (non-interactive): Get token from https://atris.ai/auth/cli"
echo " Then run: atris login --token YOUR_TOKEN"
echo ""
exit 1
fi
# 3. Extract token (try node first, then python3, then jq)
if command -v node &> /dev/null; then
TOKEN=$(node -e "console.log(require('$HOME/.atris/credentials.json').token)")
elif command -v python3 &> /dev/null; then
TOKEN=$(python3 -c "import json,os; print(json.load(open(os.path.expanduser('~/.atris/credentials.json')))['token'])")
elif command -v jq &> /dev/null; then
TOKEN=$(jq -r '.token' ~/.atris/credentials.json)
else
echo "Error: Need node, python3, or jq to read credentials"
exit 1
fi
# 4. Check Google Calendar connection status (also validates token)
STATUS=$(curl -s "https://api.atris.ai/api/integrations/google-calendar/status" \
-H "Authorization: Bearer $TOKEN")
# Check for token expiry
if echo "$STATUS" | grep -q "Token expired\|Not authenticated"; then
echo "Token expired. Please re-authenticate:"
echo " Run: atris login --force"
exit 1
fi
# Parse connected status
if command -v node &> /dev/null; then
CONNECTED=$(node -e "try{console.log(JSON.parse('$STATUS').connected||false)}catch(e){console.log(false)}")
elif command -v python3 &> /dev/null; then
CONNECTED=$(echo "$STATUS" | python3 -c "import sys,json; print(json.load(sys.stdin).get('connected', False))")
else
CONNECTED=$(echo "$STATUS" | jq -r '.connected // false')
fi
if [ "$CONNECTED" != "true" ] && [ "$CONNECTED" != "True" ]; then
echo "Google Calendar not connected. Getting authorization URL..."
AUTH=$(curl -s -X POST "https://api.atris.ai/api/integrations/google-calendar/start" \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{"redirect_uri":"https://api.atris.ai/api/integrations/google-calendar/callback"}')
if command -v node &> /dev/null; then
URL=$(node -e "try{console.log(JSON.parse('$AUTH').auth_url||'')}catch(e){console.log('')}")
elif command -v python3 &> /dev/null; then
URL=$(echo "$AUTH" | python3 -c "import sys,json; print(json.load(sys.stdin).get('auth_url', ''))")
else
URL=$(echo "$AUTH" | jq -r '.auth_url // empty')
fi
echo ""
echo "Open this URL to connect your Google Calendar:"
echo "$URL"
echo ""
echo "After authorizing, run your calendar command again."
exit 0
fi
echo "Ready. Google Calendar is connected."
export ATRIS_TOKEN="$TOKEN"
Important: Run this script ONCE before calendar operations. If it exits with instructions, follow them, then run again.
Base: https://api.atris.ai/api/integrations
All requests require: -H "Authorization: Bearer $TOKEN"
TOKEN=$(node -e "console.log(require('$HOME/.atris/credentials.json').token)")
# Next 7 days (default)
curl -s "https://api.atris.ai/api/integrations/google-calendar/events" \
-H "Authorization: Bearer $TOKEN"
# Next N days
curl -s "https://api.atris.ai/api/integrations/google-calendar/events?days=14" \
-H "Authorization: Bearer $TOKEN"
# Custom date range (ISO 8601)
curl -s "https://api.atris.ai/api/integrations/google-calendar/events?time_min=2026-02-15T00:00:00Z&time_max=2026-02-16T00:00:00Z" \
-H "Authorization: Bearer $TOKEN"
curl -s "https://api.atris.ai/api/integrations/google-calendar/events/today" \
-H "Authorization: Bearer $TOKEN"
curl -s "https://api.atris.ai/api/integrations/google-calendar/events/{event_id}" \
-H "Authorization: Bearer $TOKEN"
curl -s -X POST "https://api.atris.ai/api/integrations/google-calendar/events" \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{
"summary": "Meeting with Hugo",
"start": "2026-02-15T14:00:00-08:00",
"end": "2026-02-15T15:00:00-08:00",
"description": "Discuss project roadmap",
"location": "Zoom",
"attendees": ["[email protected]"],
"timezone": "America/Los_Angeles"
}'
IMPORTANT: Use POST to create events. Do NOT use PUT — that is for updating existing events.
curl -s -X PUT "https://api.atris.ai/api/integrations/google-calendar/events/{event_id}" \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{
"summary": "Updated meeting title",
"start": "2026-02-15T15:00:00-08:00",
"end": "2026-02-15T16:00:00-08:00",
"timezone": "America/Los_Angeles"
}'
curl -s -X DELETE "https://api.atris.ai/api/integrations/google-calendar/events/{event_id}" \
-H "Authorization: Bearer $TOKEN"
curl -s "https://api.atris.ai/api/integrations/google-calendar/status" \
-H "Authorization: Bearer $TOKEN"
curl -s -X DELETE "https://api.atris.ai/api/integrations/google-calendar" \
-H "Authorization: Bearer $TOKEN"
GET /google-calendar/events/todayGET /google-calendar/events?days=7POST /google-calendar/events with summary, start, end, attendeesGET /google-calendar/events/todayGET /google-calendar/events/todayGET /google-calendar/events/todayDELETE /google-calendar/events/{event_id}When showing calendar events, use this format:
Today's Schedule (Feb 15, 2026)
9:00 AM - 9:30 AM Team Standup
Google Meet
10:00 AM - 11:00 AM Product Review
Conference Room B
with [email protected], [email protected]
1:00 PM - 1:30 PM 1:1 with Manager
Zoom
3 events today
Rules:
| Error | Meaning | Solution |
|-------|---------|----------|
| Token expired | AtrisOS session expired | Run atris login |
| Calendar not connected | OAuth not completed | Re-run bootstrap, complete OAuth flow |
| 401 Unauthorized | Invalid/expired token | Run atris login |
| 400 Calendar not connected | No calendar credentials | Complete OAuth via bootstrap |
| 429 Rate limited | Too many requests | Wait 60s, retry |
| Invalid grant | Google revoked access | Re-connect calendar via bootstrap |
Local token (~/.atris/credentials.json): Your AtrisOS auth token, stored locally with 600 permissions.
Calendar credentials: Your Google Calendar refresh token is stored server-side in AtrisOS encrypted vault. Never stored on your local machine.
Access control: AtrisOS API enforces that you can only access your own calendar. No cross-user access possible.
OAuth scopes: Only requests necessary Calendar permissions (read events, manage events).
HTTPS only: All API communication encrypted in transit.
# Setup (one time)
npm install -g atris && atris login
# Get token
TOKEN=$(node -e "console.log(require('$HOME/.atris/credentials.json').token)")
# Check connection
curl -s "https://api.atris.ai/api/integrations/google-calendar/status" -H "Authorization: Bearer $TOKEN"
# Today's events
curl -s "https://api.atris.ai/api/integrations/google-calendar/events/today" -H "Authorization: Bearer $TOKEN"
development
Wake a team member by name — 'gm <member>' or 'wake up <member>' — and run ONE closed-loop tick: boot, inbox, claim, one bounded slice, verify, commit+push, proof, receipt. Optionally dispatch the build to an engine (codex/cursor/devin). Triggers on: gm, good morning, wake up <member>, wake the team, run a tick as <member>.
development
Dispatch coding work to an installed terminal agent — Codex, Cursor, or Devin — as an interchangeable worker engine. Claude orchestrates: writes the bounded prompt, the engine builds, Claude verifies and lands. Triggers on: use codex, use cursor, use devin, engine, dispatch to, worker agent, second opinion build.
development
Live RL tuner for skills. Watches skill invocations, reads user reaction, proposes targeted SKILL.md overlay edits, requires explicit approval, writes scorecards. The in-session half of the skill-RL loop (Path B). Triggers on: tune, sharpen, skill feedback, that was shit, that was great, make X better.
development
Run one RL improvement tick on the workspace via POST /api/improve. Ships one verifiable change, scores it, writes the scorecard. The thing you pay for. Triggers on: improve, make this better, ship one thing, run a tick, get smarter.