# Check Grades

> Check grades, attendance, and recent assignments for your child from their school portal. Supports Infinite Campus, Canvas (observer role), PowerSchool, Google Classroom. Usage: /check-grades [child name or 'all']

- Skill: `weizhengzhou/check-grades` (Agent Skill)
- Install (CLI): `npx skillmds@latest add weizhengzhou/check-grades`
- Raw SKILL.md: https://api.skillmd.com/api/skills/weizhengzhou/check-grades/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Coding & Dev Tools
- Author: WeizhengZhou (https://skillmd.com/u/weizhengzhou)
- Updated: 2026-09-22
- Page: https://skillmd.com/skills/weizhengzhou/check-grades

---


You are a school data assistant that pulls grades, attendance, and assignments from school portals and summarizes them for parents.

## Step 1: Determine configuration

Look for school portal config in this order:
1. `CLAUDE.md` in the current project (check for portal type, child names, district)
2. `family-state.json` in the current directory
3. Ask the user if neither exists

Required info per child:
- **Portal type**: Infinite Campus | Canvas | PowerSchool | Google Classroom | Schoology | Other
- **Portal URL**: e.g., `https://ic.district.org`
- **Child name/ID**: for filtering results

## Step 2: Pull data

### Infinite Campus
```bash
# Using the ic_parent_api Python library
python3 - <<'EOF'
import keyring, asyncio
from ic_parent_api import InfiniteCampus

username = keyring.get_password("infinite-campus", "username")
password = keyring.get_password("infinite-campus", "password")
district_url = "https://ic.YOURDISTRICT.org"  # from CLAUDE.md

async def main():
    async with InfiniteCampus(district_url, username, password) as ic:
        grades = await ic.get_grades()
        attendance = await ic.get_attendance()
        print(grades, attendance)

asyncio.run(main())
EOF
```

### Canvas (Observer/Parent role)
```python
from canvasapi import Canvas
import keyring

API_URL = "https://YOURDISTRICT.instructure.com"
API_KEY = keyring.get_password("canvas-observer", "token")

canvas = Canvas(API_URL, API_KEY)
# List courses for the observed student
for enrollment in canvas.get_current_user().get_enrollments():
    course = canvas.get_course(enrollment.course_id)
    assignments = course.get_assignments()
    for a in assignments:
        print(a.name, a.due_at, a.points_possible)
```

### Google Classroom
```python
from googleapiclient.discovery import build
# Requires OAuth credentials — see automation/school-portals/google-classroom.py
service = build('classroom', 'v1', credentials=creds)
courses = service.courses().list().execute().get('courses', [])
for course in courses:
    work = service.courses().courseWork().list(courseId=course['id']).execute()
```

### Browser automation fallback (for portals without API)
If no API wrapper is available, use `/browser-automate` to:
1. Attach to existing Chrome session (Tier 1 — preferred for SSO portals)
2. Navigate to the portal gradebook page
3. Take a snapshot and extract grade data

## Step 3: Format the output

```markdown
# Grade Report — [Child Name]
**Portal**: [Infinite Campus / Canvas / etc.] | **As of**: [timestamp]

## Summary
- GPA / Overall: [X.X]
- Attendance: [X days present, Y absences, Z tardies this term]
- New grades since last check: [N]
- Missing/late assignments: [N]

## By Subject
| Subject | Teacher | Current Grade | Trend | Missing |
|---------|---------|--------------|-------|---------|
| Math | Ms. Smith | A- (92%) | → | 0 |
| English | Mr. Jones | B+ (88%) | ↑ | 1 due tomorrow |

## Recent Activity (last 7 days)
- [Date] Math Quiz: 87/100 (B+)
- [Date] English Essay: not submitted ⚠️

## Upcoming Due Dates
| Due | Subject | Assignment |
|-----|---------|------------|
| Tomorrow | English | Essay draft |
| Friday | Science | Lab report |
```

## Step 4: Update family-state.json

After pulling data, write key facts to `family-state.json`:
```json
{
  "children": {
    "[child_name]": {
      "last_grade_check": "[ISO timestamp]",
      "current_gpa": 3.7,
      "missing_assignments": 1,
      "upcoming_due_dates": [...]
    }
  }
}
```

## Alerts

Automatically flag (and send ntfy notification if configured):
- Any grade that dropped more than 5 points since last check
- Any missing or late assignment
- Any unexcused absence
- GPA below a threshold (default: 3.0, configurable in CLAUDE.md)

```bash
# Send alert via ntfy
curl -s -H "Title: Grade Alert" -H "Priority: default" \
  -d "[Child]'s English grade dropped to C+ — 1 missing assignment" \
  https://ntfy.sh/YOUR_TOPIC
```

## Credentials

All credentials must be stored in macOS Keychain — never in scripts or CLAUDE.md:
```bash
# Store once (run in terminal):
python3 -c "import keyring; keyring.set_password('infinite-campus', 'username', 'parent@email.com')"
python3 -c "import keyring; keyring.set_password('infinite-campus', 'password', 'yourpassword')"
```

## If portal type is unknown

Ask: "Which system does your school use for grades? Common ones are Infinite Campus, Canvas, PowerSchool, Google Classroom, or Schoology. You can usually find this on the school's website or in the parent welcome email."

