Help us shape the future of Go! Take the 2026 Go Developer Survey

purdue-plan

command module
v0.0.0-...-17e0876 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Aug 19, 2026 License: MIT Imports: 22 Imported by: 0

README

purdue-plan

Your Purdue degree audit as data, in the terminal.

MyPurduePlan (Ellucian DegreeWorks) will show you a progress bar and hand you a PDF. purdue-plan gives you the same audit as structured output you can read at a glance, grep, diff, or pipe — plus what-if audits against programs you are not enrolled in, so you can price out a minor before committing to it.

$ purdue-plan todo

[MAJOR] Major in Mathematics  --  42.6%   credits applied: 16
  TODO   Linear Algebra II                need 1 class
  WIP    Ordinary Differential Equations  need 1 class  <- MA 36600
  TODO   Elements Of Complex Analysis     need 1 class
  TODO   Foundations Of Analysis          need 1 class
  TODO   Elements Of Algebra              need 1 class

[OTHER] College Of Science Requirements  --  79.6%
  TODO   TECHNICAL WRITING AND PRESENTATION
  TODO     Technical Writing              need 3 cr

Unofficial, and not affiliated with Purdue University. It reads your own records through the same API the web dashboard uses, after you sign in the same way you always do.

Install

go install github.com/upuddu/purdue-plan@latest

Or from source:

git clone https://github.com/upuddu/purdue-plan
cd purdue-plan && go build -o purdue-plan .

Requires Go 1.21+ and, for the browser login, any Chromium-family browser.

Signing in

DegreeWorks sits behind Purdue SSO (Microsoft Entra + Duo) and its session cookie is HttpOnly, so no script can read it off the page. Rather than making you copy it by hand, the CLI drives a real browser and captures the session itself:

purdue-plan login

A browser window opens at MyPurduePlan. Sign in normally — Duo included — and the CLI takes it from there. Your password is typed into the browser, never into this tool; it only ever reads the resulting cookies.

It uses its own browser profile under ~/.config/purdue-plan/browser, so your everyday browser data is untouched. Because Entra and Duo can remember that profile, later sign-ins are often instant:

purdue-plan login --headless        # reuse a remembered session, no window
purdue-plan login --browser brave   # pick a specific browser
purdue-plan login --paste           # paste a Cookie header by hand
purdue-plan login --cookie '…'      # non-interactive, for scripts

Browsers are auto-detected — Chrome, Brave, Edge, Vivaldi, Opera, Arc, Chromium — and the first installed one wins. Override with --browser (a name or an executable path) or PURDUE_PLAN_BROWSER.

Firefox and Safari cannot be driven this way. They do not speak the DevTools protocol. Use --paste: sign in in your own browser, then copy the Cookie: header from DevTools → Network → any api/… request.

Every command checks the session first; with none stored you get these instructions instead of a stack trace. Sessions last about an hour.

Commands

Command What it does
login / logout / whoami session management
degrees your declared programs, each with per-block progress
todo only what is still outstanding
audit the full requirement tree, satisfied items included
courses [pattern] the courses that can satisfy matching requirements
classes what you are enrolled in (--history for every term)
whatif audit a program you are not enrolled in
list <entity> catalog codes — minors, majors, degrees, colleges, …
search --discipline MA course catalog lookup
Flags
Flag Effect
--degree CODE which program to audit (default: your first)
--all include already-satisfied requirements
--allowed list qualifying courses inline
--json machine-readable output
--file PATH parse a saved audit offline, no session needed
--no-inprogress / --no-prereg exclude in-progress or preregistered classes
--major/--minor/--concentration/--program/--college CODE repeatable what-if goals
--catalog-year YYYYTT e.g. 202510

Status markers: DONE satisfied · WIP a class is in progress · TODO nothing applied yet. A rule sitting at 98% is almost always a course in progress, not a shortfall.

What am I enrolled in?

$ purdue-plan classes
Fall 2026  (202710)
  ECE 30100   Signals And Systems             3 cr  WIP   [preregistered]
  ECE 30200   Probabilistic Methods           3 cr  WIP   [preregistered]
  MA 36600    Ord Differential Eqs            4 cr  WIP   [preregistered]

6 classes, 19 credits

--history gives every term you have attended, with titles, grades and credits — effectively an unofficial transcript. --term "Fall 2026" or --term 202710 filters. Transfer and exam credit is flagged ([transfer credit]); it posts with a literal TR grade rather than a letter.

Evaluating a minor

The part the web UI makes tedious. Find the code, then score it against your real transcript:

$ purdue-plan list minors stat
  STAT         Statistics

$ purdue-plan whatif --degree MATH-BS --major MATH --minor STAT --allowed

[MINOR] Minor in Statistics  --  25%
  TODO   MINOR:Area I    need 1 class
         allowed: STAT 35000, STAT 35500, STAT 50300, QM 30500, IE 33000
  DONE   MINOR:Area II                 <- MA 41600
  TODO   MINOR:Area III  need 1 class
         allowed: STAT 51200
  TODO   MINOR:Area IV   need 2 classes
         allowed: IE 33600, IE 53000, STAT 41700, STAT 51300, STAT 51400

Courses you have already taken are credited automatically, so you see exactly how much of a program you have accidentally already finished.

Scripting

--json emits the flattened rule list:

purdue-plan todo --json | jq -r '.[] | select(.percent=="0") | .label'
# diff your progress between two points in time
purdue-plan audit --json > before.json
# …a semester later…
purdue-plan audit --json > after.json && diff before.json after.json

--file re-renders a saved audit with no session at all, which is handy for archiving a snapshot each term.

API notes

Reverse-engineered from the dashboard bundle. Undocumented and unstable — Ellucian can change any of it without notice.

  • GET /api/users/myself — cheap session probe.

  • GET /api/students/myself — your goals (degree, school, catalog year). Requires Accept: application/vnd.hedtech.degreeworks.dashboard.students.v1+json.

  • GET /api/audit?studentId=&school=&degree=&audit-type=AA&… — a declared program. Requires Accept: application/vnd.net.hedtech.degreeworks.dashboard.audit.v1+json.

  • POST /api/audit — what-if, plain application/json:

    {"studentId":"...","isKeepCurriculum":false,"school":"UG","degree":"MATH-BS",
     "catalogYear":"202510","goals":[{"code":"MINOR","value":"STAT"}],"classes":[]}
    

    catalogYear must be non-empty or the service answers 500 with an empty body — no error message, no hint. That one cost an afternoon. Goal codes: MAJOR, MINOR, CONC, PROGRAM, COLLEGE, SPEC, LIBL.

  • GET /api/validations/special-entities/{degrees,majors,minors,concentrations,programs,colleges,disciplines,…}

  • GET /api/courses/search/byDiscipline?page=&discipline=&courseNumber= — page is 0-based.

/api/audit/planner/whatif exists in the bundle but rejected every payload shape tried; the UI itself uses POST /api/audit, and so does this tool.

Response quirks handled here
  • percentComplete and the credit fields arrive as a JSON string or number, inconsistently.
  • classesAppliedToRule is sometimes a bare array, sometimes an object wrapping classArray.
  • requirement.courseArray holds the courses that satisfy a rule — this is what courses and --allowed read.
Why not SSH through a jump host?

A reasonable idea, and it was worth measuring rather than assuming. Running the API call from scholar.rcac.purdue.edu, i.e. from inside Purdue's network:

# on a Purdue login node, inside the campus network
$ curl -s -o /dev/null -w "%{http_code}\n" \
    https://mypurdueplan.purdue.edu/api/users/myself
401

Same 401 as from anywhere else. Authentication is per-identity (an Entra/CAS session), not per-network, so a Purdue source IP buys nothing. Separately, jump.it.purdue.edu requires a password plus Microsoft MFA and refuses key-only auth — so tunnelling could not have reduced the login burden anyway: you would MFA into SSH and still need a MyPurduePlan session on the far side.

Security

  • The session cookie is a bearer credential for your student record. It is stored at ~/.config/purdue-plan/session.json with 0600 permissions. Treat it like a password.
  • This tool never sees or stores your password. Authentication happens in the browser, against Purdue's own login pages.
  • Read-only by construction. Every endpoint it calls is a GET, except the what-if audit, which is a POST that computes a hypothesis and stores nothing. DegreeWorks' actual write endpoint, /api/registration, is never called — this tool cannot add, drop, or change a class.
  • It reads only your own records — the same ones the web dashboard shows you. It grants no access you do not already have.
  • purdue-plan logout clears the stored session; the browser profile lives in ~/.config/purdue-plan/browser and can be deleted at any time.
  • Do not commit captured audits or HAR files; they contain student records. The bundled .gitignore already excludes them.

License

MIT

Documentation

The Go Gopher

There is no documentation for this package.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL