Goal
Automate routine Stanford administrative tasks so they can be triggered from Claude Code or a script, without manually opening a browser and clicking through forms.
Target services:
- Axess (axess.sierracedar.com) — class registration, enrollment, transcript
- Grant ED (grante-d.stanford.edu) — grant/funding management
- VSO / ASSU — student org admin
- Stanford Who (stanfordwho.stanford.edu) — directory lookups
- MyAdvisor / OASIS — advising, requirements
Architecture Options
Option A: Browser Automation with Persistent Session (Recommended)
Use Playwright (or Selenium) to drive a real browser that handles Stanford SSO + Duo 2FA.
┌─────────────┐ ┌──────────────┐ ┌─────────────────┐
│ Claude Code │────▶│ Python API │────▶│ Playwright │
│ or CLI │ │ (uutils) │ │ (headless/head) │
└─────────────┘ └──────────────┘ └─────┬───────────┘
│
┌─────────▼──────────┐
│ Stanford SSO Login │
│ (login.stanford.edu)│
│ + Duo 2FA push │
└─────────┬──────────┘
│
┌─────────▼──────────┐
│ Axess / Grant ED / │
│ ASSU / etc. │
└────────────────────┘
Pros: Works with any Stanford service, handles JavaScript-heavy UIs
Cons: Requires Duo 2FA approval once per session, fragile to UI changes
Session persistence strategy:
- Save browser cookies/state to
~/.stanford_session/ after login
- Reuse session until it expires (~8-12 hours for Stanford SSO)
- Only re-auth when session is stale (detect login redirect)
- Keep Mac awake or use
caffeinate / tmux for long-running sessions
Option B: Kerberos + API Endpoints (Limited)
Some Stanford services expose APIs or use Kerberos auth:
kinit brando9@stanford.edu for Kerberos ticket
- Use tickets to access services that support Kerberos (limited set)
- Won't work for Axess or most web-only services
Verdict: Only works for a subset of services. Not sufficient alone.
Option C: Hybrid (Recommended Implementation)
- One-time browser login with Duo 2FA → save session state
- Reuse session for all subsequent API/scrape calls until expiry
- Fall back to re-auth with Duo push when session expires
- Keep alive via periodic heartbeat request in tmux/background
Implementation Plan
Phase 1: Stanford SSO Auth Module
Phase 2: Axess Automation
Phase 3: Grant ED & Admin
Phase 4: Keep-Alive Daemon
Key Decisions Needed
- Duo 2FA flow: Can we use "Remember me for 30 days" + saved cookies, or do we need a push every time?
- Headless vs headed: Headless is faster but Stanford may block it (Cloudflare/bot detection). May need headed browser on first login.
- Always-on requirement: Session expires after ~8-12 hours. Options:
- Keep Mac awake with
caffeinate -d in tmux
- Use a cloud VM (but then need to forward Duo pushes)
- Accept re-auth every morning (one Duo push per day)
- Fragility: Stanford UI changes could break scrapers. Consider adding CI tests that verify selectors.
Security Notes
- Stanford password stored at
~/keys/stanford_password.txt (chmod 600, gitignored)
- Session cookies stored at
~/.stanford_session/ (chmod 700)
- Never commit credentials or session state
- Duo 2FA remains as second factor — can't be bypassed
Dependencies
References
Goal
Automate routine Stanford administrative tasks so they can be triggered from Claude Code or a script, without manually opening a browser and clicking through forms.
Target services:
Architecture Options
Option A: Browser Automation with Persistent Session (Recommended)
Use Playwright (or Selenium) to drive a real browser that handles Stanford SSO + Duo 2FA.
Pros: Works with any Stanford service, handles JavaScript-heavy UIs
Cons: Requires Duo 2FA approval once per session, fragile to UI changes
Session persistence strategy:
~/.stanford_session/after logincaffeinate/tmuxfor long-running sessionsOption B: Kerberos + API Endpoints (Limited)
Some Stanford services expose APIs or use Kerberos auth:
kinit brando9@stanford.edufor Kerberos ticketVerdict: Only works for a subset of services. Not sufficient alone.
Option C: Hybrid (Recommended Implementation)
Implementation Plan
Phase 1: Stanford SSO Auth Module
py_src/uutils/stanford_auth.py— handles login.stanford.edu SSO + Duo~/.stanford_session/cookies.jsonis_session_valid()pings a Stanford service~/keys/stanford_password.txt(chmod 600)Phase 2: Axess Automation
py_src/uutils/stanford_axess.py— class search, enrollment, dropsearch_classes(term, subject, course_num)→ list of sectionsenroll(class_id)→ enrollment confirmationget_schedule()→ current enrolled classesget_transcript()→ unofficial transcriptPhase 3: Grant ED & Admin
py_src/uutils/stanford_grante_d.py— grant/funding taskspy_src/uutils/stanford_admin.py— VSO/ASSU, directory, etc.Phase 4: Keep-Alive Daemon
scripts/stanford_session_keepalive.py— runs every 30 min, pings Stanford SSOKey Decisions Needed
caffeinate -din tmuxSecurity Notes
~/keys/stanford_password.txt(chmod 600, gitignored)~/.stanford_session/(chmod 700)Dependencies
References