Canvas quizzes
Drives a Canvas Classic Quiz end to end with the Claude in Chrome tools. The
full runbook — every trap, with the fix — is tooling/CANVAS_QUIZZES.md.
Read it before the first interaction; what follows is the shape of the job.
The page helper is tooling/canvas-quiz.js, the CLI is
scripts/canvas-quiz.mjs.
Which runbook
Check the assignment's submission_types:
["online_quiz"]+ aquiz_id→ this skill.["external_tool"]at myopenmath.com →myopenmathskill. Different machinery entirely (LTI iframe, MathQuill, per-question submits).
Ask first
Three separate asks, and they do not imply each other:
- Opening the attempt — the one people underestimate. On a 1-attempt or
timed quiz this is the irreversible step, not the submit. Always check
infofirst and quote the numbers when you ask. - Typing answers.
- Submitting. Never on your own initiative.
Never enter credentials anywhere.
Steps
Find it —
node scripts/canvas-quiz.mjs list <courseId>. The/quizzesAPI index is disabled on many courses; this walks assignments instead, which always works.Pre-flight —
node scripts/canvas-quiz.mjs info <courseId> <quizId>andattempts <courseId> <quizId>. Readallowed_attemptsandtime_limitout loud before doing anything. A timed quiz means the clock runs while you think — plan the answers before opening it.Open the attempt — a real click on Take the Quiz. A
GETon/takesilently re-renders the landing page and starts nothing; it looks broken but isn't. Confirm#submit_quiz_formexists and the.display_questioncount matchesquestion_count.Read and save, before answering. Paste
tooling/canvas-quiz.js, call__QDUMP().javascript_tooltruncates around 1 KB — chunk viaJSON.stringify(__QDUMP()).match(/[\s\S]{1,900}/g). Thennode scripts/canvas-quiz.mjs render <dump.json> output/<name>.md.Fill —
__QSET(n, choice): index or text for choice questions, an array for multiple-answers, a string for text, an object for blanks/matching.Verify —
__QVERIFY()re-reads the DOM, and__QSTATE()shows theQuiz saved at ...stamp. Screenshot: the sidebar checkmarks confirm the whole quiz at a glance. A save stamp is what proves the server has it.Stop. Leave the attempt open, answered, and saved for Max to submit — unless he says otherwise in the moment.
The four that actually cost something
- Opening is the irreversible step, not submitting, when attempts are limited.
GET /takestarts nothing. Click the button.- Multiple-answers checkboxes all have
value="1"— match by text or index.__QSETclears the group first, so an array is the final state. - A DOM-only answer is not saved. Check the
Quiz saved atstamp before walking away or reloading.
Answering from a source document
Syllabus and policy quizzes should trace to the source. Put the trace in each
question's rationale field — render prints it as a > Why: line, which makes
the saved markdown reviewable instead of a bare answer key. Call out real
judgment calls explicitly rather than letting them pass as quotes.