# Canvas

> Canvas LMS coursework — plan the day around what is due, check deadlines, sync course materials, or answer questions from lecture notes and assignment descriptions. Use when the user runs /canvas, or says "what's due", "what do I have due this week", "plan my day around canvas", "sync canvas", "what did my professor post", "what's on the midterm", or asks about an assignment, syllabus, module or slide deck by name.

- Skill: `emran05/canvas` (Agent Skill)
- Install (CLI): `npx skillmds@latest add emran05/canvas`
- Raw SKILL.md: https://api.skillmd.com/api/skills/emran05/canvas/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Docs & Writing
- Author: Emran05 (https://skillmd.com/u/emran05)
- Updated: 2026-09-22
- Page: https://skillmd.com/skills/emran05/canvas

---


# /canvas — Canvas coursework

`canvas-sync` mirrors the user's Canvas courses into `~/Canvas` and indexes them under
`~/Canvas/_index/`. The CLI is `~/CanvasSync/bin/canvas-sync` (usually linked as `canvas-sync`).

**You do not read `~/Canvas` course files yourself** — that is thousands of files. Spawn the
`canvas-planner` agent (model: sonnet) and relay its answer. The only things you read directly
are `~/Canvas/_index/last_sync.json` (freshness) and whatever the CLI prints.

## Freshness check (do this first for every mode except `setup`)

```bash
canvas-sync status --json >/dev/null 2>&1 || echo "not set up"
```

Read `~/Canvas/_index/last_sync.json`; if `finished_at` is more than 60 minutes ago, run:

```bash
canvas-sync sync -q
```

If `~/Canvas/_index/` does not exist at all, go to `/canvas setup`.

## `/canvas` or `/canvas plan`

1. Freshness check above.
2. If Google Calendar MCP tools are available in this session, list today's and tomorrow's
   events and format them as plain lines (`09:00-10:15 CS 115 lecture (Babbio 122)`). If they
   are not available, skip this — do not ask the user to connect anything.
3. Spawn `canvas-planner` with: today's date and time, the calendar lines from step 2 under a
   heading "External calendar (fixed)", and "Mode: plan". Tell it to run
   `canvas-sync plan --dry-run` first: that prints the token-free context pack (timetable,
   preferences, events, ASSIGNMENTS.md, recent announcements) it should plan from.
4. Relay the plan verbatim in the terminal.
5. Offer to push it: "Send this to Telegram?" On yes, write the plan to a temp file and run
   `canvas-sync notify --text-file /tmp/canvas-plan.txt` (add `--force` if the user wants it
   during quiet hours, 23:00–07:00).

The unattended equivalent is `canvas-sync plan --push`, which runs the same prompt headlessly
from `~/CanvasSync/planner/SYSTEM.md`. Use the agent path when the user is here, because only
the interactive session can read their Google Calendar.

## `/canvas due [N]`

```bash
canvas-sync status --days ${N:-7}
```

Print the table as-is. No agent needed. Add `--json` if the user wants to filter it further.

## `/canvas sync`

```bash
canvas-sync sync
```

Show the counts and the change digest it prints. If it reports per-course errors (403/404),
name the affected courses; those scopes are simply not shared with the student. To push the
digest to Telegram: `canvas-sync notify --digest`.

## `/canvas ask <question>`

Spawn `canvas-planner` with "Mode: ask" and the question verbatim. Relay the answer with its
file citations. Good for "what did Prof. X post about the midterm", "where are the week 3
slides", "what does HW1 actually ask for".

## `/canvas setup`

First ask whether their school allows **personal access tokens** (Canvas → Account → Settings →
Approved Integrations → "+ New Access Token"). Branch:

**Tokens allowed (simplest):**
1. Token: name it `canvas-sync`, no expiry (or a year), copy it once.
2. `canvas-sync setup` — prompts for base URL (`https://sit.instructure.com`), the token (hidden),
   and the output dir; validates and prints "Authenticated as <name>".

**Tokens disabled (Stevens and similar) — use "both": cookie for material + feed for planning:**
1. Feed URL: Canvas → Account → Settings → "Calendar Feed" → copy the `…/user_<hash>.ics` URL.
2. Cookie: log into Canvas in a browser, DevTools (⌘⌥I) → Application/Storage → Cookies → copy
   `canvas_session` (and `_legacy_normandy_session`), or Network → any request → copy the whole
   `Cookie:` request header.
3. `canvas-sync setup --auth-mode cookie --cookie --feed-url "<the .ics URL>"` — it prompts for the
   cookie (hidden), validates via `/users/self`, and notes the feed fallback.
   (Feed-only, no cookie: `canvas-sync setup --auth-mode feed --feed-url "<url>"`.)

Then, for either path:
3. `canvas-sync sync` for the first full pull (a few minutes).
4. Offer scheduling: `canvas-sync install-schedule --plan-time 07:30 --sync-hours 3`
   (launchd: sync every 3 h, plan pushed to Telegram at 07:30). Check with
   `canvas-sync schedule --status`; undo with `canvas-sync uninstall-schedule`.
5. Optionally have them fill in `planner.timetable` and `planner.preferences` in
   `~/.config/canvas-sync/config.json` — the plans are much better with a real class schedule.

## `/canvas fix-cookie`

Only for cookie / "both" users. When `sync` reports "Canvas cookie expired" (or `status` looks
stale and the config's `auth_mode` is `cookie`), the web session lapsed. Have them re-copy the
`Cookie:` header (as in setup) and run:

```bash
canvas-sync auth-cookie      # prompts for the cookie (hidden), validates, saves
```

Until they do, planning still works from the Calendar Feed (due dates + events), but file
downloads and descriptions are paused.

## Notes

- The token **or session cookie** lives in `~/.config/canvas-sync/config.json` (0600). Never print
  it, never paste it into a message, never pass it to an agent.
- Course materials never leave the machine; only the plan/digest text goes to the user's own
  Telegram bot via `hermes`.
- `canvas-sync notify` respects quiet hours (23:00–07:00 by default); `--force` overrides.

