A lightweight Python script that pulls your Canvas assignments, due dates, submission statuses, and calendar events — then generates a clean daily Markdown summary and SQLite database you can actually query.
Built because Canvas's own interface buries the things you need to see every morning under three menus and a notification badge.
| File | What it is |
|---|---|
canvas_summary.md |
Daily human-readable snapshot: upcoming work, missing assignments, per-course stats |
canvas_data.db |
SQLite database — query anything: overdue by course, completion rates, all submissions |
- Python 3.9+
- A Canvas account (any school that uses Instructure Canvas)
pip install canvastogoCreate a .env file in the directory where you plan to run the dashboard:
CANVAS_TOKEN=your_token_here
CANVAS_BASE_URL=https://your-school.instructure.com
KEEP_COURSE_IDS=123456,789012 # optional — leave blank for all active courses
OUTPUT_DIR= # optional — defaults to this folder
Getting your Canvas token:
Canvas → your profile picture (top-left) → Settings → scroll to "Approved Integrations" → + New Access Token
Finding course IDs:
Open a course in Canvas. The URL will look like /courses/204930 — that number is the course ID.
canvas-dashboardcrontab -eAdd this line to run at 8:00 AM every day:
0 8 * * * cd /path/to/canvas-dashboard && .venv/bin/canvas-dashboard >> canvas_dashboard.log 2>&1
Create ~/Library/LaunchAgents/com.canvasdashboard.plist:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN"
"http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>Label</key>
<string>com.canvasdashboard</string>
<key>ProgramArguments</key>
<array>
<string>/path/to/.venv/bin/canvas-dashboard</string>
</array>
<key>WorkingDirectory</key>
<string>/path/to/canvas-dashboard</string>
<key>StartCalendarInterval</key>
<dict>
<key>Hour</key><integer>8</integer>
<key>Minute</key><integer>0</integer>
</dict>
<key>StandardOutPath</key>
<string>/path/to/canvas-dashboard/canvas_dashboard.log</string>
<key>StandardErrorPath</key>
<string>/path/to/canvas-dashboard/canvas_dashboard.log</string>
<key>EnvironmentVariables</key>
<dict>
<key>PATH</key>
<string>/usr/local/bin:/usr/bin:/bin</string>
</dict>
</dict>
</plist>Load it:
launchctl load ~/Library/LaunchAgents/com.canvasdashboard.plistNote on external drives (macOS): If you store this project on an external drive, replace
/path/to/with the full volume path (e.g./Volumes/MyDrive/projects/canvas-dashboard/). The script itself works fine on external drives — the only gotcha is that launchd runs before the drive mounts at login, so either delay the scheduled time or use a symlink from~/canvas_dashboard → /Volumes/YourDrive/canvas-dashboard.
Same as the macOS cron approach above.
- Open Task Scheduler → Create Basic Task
- Trigger: Daily at your preferred time
- Action: Start a program
- Program:
C:\path\to\Scripts\canvas-dashboard.exe - Start in:
C:\path\to\canvas-dashboard\
- Program:
sqlite3 canvas_data.db
-- Upcoming assignments
SELECT name, due_at FROM assignments WHERE due_at > datetime('now') ORDER BY due_at;
-- Missing work
SELECT a.name, c.name FROM submissions s
JOIN assignments a ON s.assignment_id = a.id
JOIN courses c ON a.course_id = c.id
WHERE s.missing = 1;
-- Completion rate by course
SELECT c.name,
COUNT(DISTINCT a.id) AS total,
COUNT(DISTINCT CASE WHEN s.workflow_state='submitted' THEN a.id END) AS submitted
FROM courses c
LEFT JOIN assignments a ON c.id = a.course_id
LEFT JOIN submissions s ON a.id = s.assignment_id
GROUP BY c.id;- Your API token lives only in
.envwhich is excluded from version control via.gitignore - The token gives read access to your Canvas data — treat it like a password
- Revoke and regenerate tokens at any time: Canvas → Settings → Approved Integrations
KEEP_COURSE_IDS is optional. If you leave it blank, the script tracks all active enrollments. If your school uses a multi-term system and old courses keep showing up as "active," add just your current course IDs to filter them out.
MIT — use it, modify it, share it.