Fallback runtime-designed handler for Canvas assignments that don't fit any of the 5 specific skills (canvas-ics33 / canvas-reading-annotation / canvas-essay / canvas-zybooks / canvas-inside).
Install the "canvas-generic" agent skill from https://github.com/X-isdoingreat/canvas-pilot/tree/main/.claude/skills/canvas-generic into .claude/skills/canvas-generic/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "canvas-generic", then confirm the skill loads.
Claude Code copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
Type this inside Codex. $skill-installer <name> installs a curated skill from openai/skills. The installer writes to $CODEX_HOME/skills (default ~/.codex/skills). Restart Codex if the skill does not show up.
skills CLI
$ npx skills add X-isdoingreat/canvas-pilot --skill canvas-generic -a codex
Project install goes to .agents/skills/; add -g for ~/.codex/skills/.
Install the "canvas-generic" agent skill from https://github.com/X-isdoingreat/canvas-pilot/tree/main/.claude/skills/canvas-generic into .agents/skills/canvas-generic/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "canvas-generic", then confirm the skill loads.
Codex copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
skills CLI
$ npx skills add X-isdoingreat/canvas-pilot --skill canvas-generic -a cursor
Project install goes to .agents/skills/; add -g for ~/.cursor/skills/.
Install the "canvas-generic" agent skill from https://github.com/X-isdoingreat/canvas-pilot/tree/main/.claude/skills/canvas-generic into .cursor/skills/canvas-generic/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "canvas-generic", then confirm the skill loads.
Cursor copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
--scope user (default) or --scope workspace; --path is the subfolder of the repo that holds the skill; --consent skips the security confirmation prompt.
skills CLI
$ npx skills add X-isdoingreat/canvas-pilot --skill canvas-generic -a gemini-cli
Project install goes to .agents/skills/; add -g for ~/.gemini/skills/.
Install the "canvas-generic" agent skill from https://github.com/X-isdoingreat/canvas-pilot/tree/main/.claude/skills/canvas-generic into .gemini/skills/canvas-generic/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "canvas-generic", then confirm the skill loads.
Gemini CLI copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
Installs for Copilot at project scope by default; add --scope user for a personal install. Preview a skill first with gh skill preview. Needs GitHub CLI 2.90.0 or later (public preview).
skills CLI
$ npx skills add X-isdoingreat/canvas-pilot --skill canvas-generic -a github-copilot
Project install goes to .agents/skills/; add -g for ~/.copilot/skills/.
Install the "canvas-generic" agent skill from https://github.com/X-isdoingreat/canvas-pilot/tree/main/.claude/skills/canvas-generic into .github/skills/canvas-generic/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "canvas-generic", then confirm the skill loads.
GitHub Copilot copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
skills CLI
$ npx skills add X-isdoingreat/canvas-pilot --skill canvas-generic -a opencode
OpenCode documents no install command of its own. Project install goes to .agents/skills/; add -g for ~/.config/opencode/skills/.
Install the "canvas-generic" agent skill from https://github.com/X-isdoingreat/canvas-pilot/tree/main/.claude/skills/canvas-generic into .opencode/skills/canvas-generic/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "canvas-generic", then confirm the skill loads.
OpenCode copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
Facts
Skill name
canvas-generic
GitHub stars
125
Token cost
~7.5k tokens
SKILL.md length
3,280 words
Files
1
Skills in repo
32
Repo updated
First seen
Licence
AGPL-3.0
At a glance
Fallback runtime-designed handler for Canvas assignments that don't fit any of the 5 specific skills (canvas-ics33 / canvas-reading-annotation / canvas-essay / canvas-zybooks / canvas-inside).
Works in 11 steps: fetch-context → find-rubric → locate-inputs → …
Tasks that involve Quizzes and assessments
SKILL.md covers §1 — Identity & contract, §2 — Stage 0: load per-cluster…, §3 — Working directory and Stage 1 — fetch-context, plus 14 more sections
Calls python
What it does
Canvas Generic is an agent skill from X-isdoingreat/canvas-pilot. Fallback runtime-designed handler for Canvas assignments that don't fit any of the 5 specific skills (canvas-ics33 / canvas-reading-annotation / canvas-essay / canvas-zybooks / canvas-inside). Invoked by canvas-execute when an assignment's routing skill is canvas-generic — typically a cluster that canvas-bootstrap §3 marked "⚠ unclear" / "⚠ inline-only-or-unknown" / "⚠ quiz-id-missing". No overlay required; the skill performs full runtime investigation (description + frontpage + modules + syllabus + attachments +…
Its SKILL.md is about 7.5k tokens, which your agent loads only when the skill is triggered. It is a single SKILL.md file with no bundled scripts.
It sits in Education, covering Quizzes and assessments, Subagents and Curriculum and course design. The repository describes itself as: Local-first Canvas LMS AI agent that learns each course's recurring assignment workflow and reuses it through scan - approval - execute with student review. The licence is AGPL-3.0.
Read from SKILL.md and the folder at commit 6b79d5b. It shows what the files ask for, not the result of running them.
Tool permissions
Pre-approves these tools, so the agent can use them without asking each time:
Bash
Read
Write
Edit
Glob
Grep
WebFetch
Skill
Agent
From allowed-tools in the SKILL.md frontmatter.
Runs code
Shell commands in SKILL.md call:
python
From the folder's file list and the shell code blocks in SKILL.md.
Network
No URLs in SKILL.md.
From URLs in SKILL.md, links to its own repository left out.
Credentials
Names no API keys, tokens, secrets or passwords.
From names ending in _API_KEY, _TOKEN, _SECRET, _KEY or _PASSWORD in SKILL.md.
Context cost
Canvas Generic loads about 7.5k tokens when it runs. Until then it costs about 230 tokens; SKILL.md has 3,280 words of instructions outside code blocks.
Always· name and description, kept in context so the agent knows when to use it
~230
When it runs· the whole SKILL.md, loaded when a task matches
~7.5k
Estimates: characters ÷ 4, the usual rule of thumb; real counts depend on the model's tokenizer. Scripts and assets cost tokens only if the agent reads them.
Safety
Auto-check: notes
The automated check noted patterns worth knowing about, such as sudo or a known installer.
NotePre-approves every shell command (allowed-tools: Bash)SKILL.md
Automated static check — not a guarantee. Review scripts before installing. It scans the text of SKILL.md for risky patterns (piping downloads into a shell, reading credential files, hidden Unicode, destructive commands); files beside SKILL.md are not scanned.
Download SKILL.mdSave it as .claude/skills/canvas-generic/SKILL.md (or your agent's skills folder).
name
canvas-generic
description
Fallback runtime-designed handler for Canvas assignments that don't fit any of the 5 specific skills (canvas-ics33 / canvas-reading-annotation / canvas-essay / canvas-zybooks / canvas-inside). Invoked by canvas-execute when an assignment's routing skill is `canvas-generic` — typically a cluster that canvas-bootstrap §3 marked "⚠ unclear" / "⚠ inline-only-or-unknown" / "⚠ quiz-id-missing". No overlay required; the skill performs full runtime investigation (description + front_page + modules + syllabus + attachments + external URLs), locates the grading rubric, downloads referenced inputs, then designs a per-assignment pipeline at runtime. Runs three sub-agent reviews (A — investigation completeness; B — verification checklist design; C — verification coverage review) and produces a draft with verification log. Auto-submit is never the default; output is always draft_ready for student review.
canvas-generic — runtime-designed pipeline for novel assignments
§1 — Identity & contract
What this skill handles: any pending Canvas assignment that does not fit the existing 5 specific skills (canvas-ics33, canvas-reading-annotation, canvas-essay, canvas-zybooks, canvas-inside). Trigger is shape mismatch — the cluster's submission types, naming pattern, and reference materials don't form a clean match for any specific skill. canvas-bootstrap routes these clusters here instead of forcing a wrong-shape specific skill or punting to canvas-skip.
Invocation: canvas-execute calls this skill when an assignment's proposed_skill == "canvas-generic". canvas-bootstrap §7 writes the courses.yaml route entry for category-4 (unclear) clusters.
Success criterion: writes result.json with status: "draft_ready" and draft_path pointing at the produced artifact (.docx / .pdf / .py / .ipynb / a folder). canvas-generic never auto-submits — there is no overlay-level authorization mechanism by design. Student reviews → student uploads.
Failure status: status: "error" with explanatory notes if (a) Sub-agent A in Stage 4 flags missing critical sources the student cannot supply, (b) the grading rubric cannot be located anywhere, (c) Stage 5 cannot classify the output mode with confidence, (d) verification fails after 3 retry rounds, (e) Sub-agent C in Stage 10 flags an unresolvable coverage gap.
Explicitly does NOT handle:
Anything one of the 5 specific skills handles correctly — those exist for a reason and carry domain-specific guards (e.g. canvas-inside's 3-layer arbitration enforcement, canvas-ics33's bundle re-clone verify, canvas-zybooks' API integration). If canvas-bootstrap can route to a specific skill, it must do so first.
Agent stops at can't-do, not shouldn't-do — this skill serves the student. Behavioral policies set by course staff (don't use AI / no collaboration / no paraphrasing) are between the student and the staff; this skill does not gate on such rules. The skill does the work regardless; whether to use the output is the student's call. The skill stops only on intrinsic can't-do:
Physically impossible — in-person attendance, paper submission, live signature, LDB-locked quiz, Respondus monitor.
Input missing and unobtainable — spec/rubric/inputs cannot be located, AND Sub-agent A's recovery attempts fail, AND the student cannot supply the missing material.
Verification fails after retries — 3 rounds at Stage 9 / 2 rounds of B↔C iteration at Stage 10.
YuJa-style soft-stop — for resources physically out of reach but possibly obtainable with student help (linked videos, password-protected pages, third-party logins), Sub-agent A surfaces them as blocking_unreachables and the skill offers to take a URL / transcript / credential from the student. Student declines → skip that input and continue with what is reachable; note in result.json.notes.
§2 — Stage 0: load per-cluster learnings overlay
Unlike the 5 specific skills which have one framework-wide overlay (_private/canvas-ics33-app.md, etc.), canvas-generic has a per-cluster learnings overlay at _private/canvas-generic-<course_id>-<cluster_slug>.md. The slug is computed deterministically via src.overlay_utils.cluster_filename_slug(cluster_norm) — bootstrap §7.1 creates the file empty when it routes a ⚠ category-4 cluster here.
Compute the path:
python
from src.overlay_utils import canvas_generic_overlay_path
path = canvas_generic_overlay_path(course_id, cluster_norm)
# e.g. "_private/canvas-generic-12345-reading-annotation-week.md"
cluster_norm comes from the invocation context (canvas-execute passes course_id + assignment_id; this skill computes cluster_norm from the assignment's name via src.recurring_patterns.normalize()).
Read the file:
If file present and has a ## User preferences (recurring) section with content: parse the bullet list. Pass the resulting user_preferences dict into Stage 5 (classify-output), Stage 6 (design-pipeline), and Stage 7 (generate) as priming. Pass workflow_notes (from the ## Workflow notes section) into Stage 6.
If file is missing: this cluster wasn't bootstrapped properly. Tell the user "canvas-generic learnings file not found at {path}. I'll proceed with a clean runtime investigation, but I won't be able to honor prior preferences. To fix, re-run canvas-bootstrap on this cluster." Then continue to Stage 1.
If file present but empty (only frontmatter + empty sections): normal — first dispatch on this cluster. Continue to Stage 1 with no priming.
What's in learnings (NOT in scope):
Pipeline design is NEVER cached in learnings. canvas-generic re-discovers output mode + pipeline stages every dispatch (Stages 5-6). The justification is that input materials may change week to week (one week reading-heavy, next week math-heavy); pipeline shape should reflect this assignment's specific shape.
Investigation results (current spec, current rubric) are NEVER cached. Stages 1-4 always run fresh; the spec might have changed.
What learnings DOES cache (user preferences only, accumulated via Layer 2 permanent rule across past dispatches):
voice register / persona preference
color rubric (for pdf_annotated mode)
citation style preference
format preferences (font, paragraph indentation, etc.)
forbidden phrases the user has objected to in past drafts
workflow tweaks ("skip the figure-caption substage — this cluster never has figures")
Why not just an overlay like the specific skills: a learnings file is per-cluster (multiple cluster files for the same course are normal), and starts empty (no manual authoring). Specific-skill overlays are per-framework (one file aggregating multiple courses) and are authored by bootstrap §6 batched ask + §8 calibration. The learnings model fits canvas-generic's "stateless runtime design + accumulated user preferences" hybrid.
If you find yourself wishing canvas-generic had richer per-cluster pipeline design baked into the overlay, that's the signal the cluster should graduate to a specific skill — see §11 below.
from src import canvas_client as cv
a = cv.get_assignment(course_id, assignment_id)
description = (a.get("description") or "")
front_page = cv.get_front_page(course_id)
modules = cv.list_modules(course_id)
syllabus = cv.get_syllabus_body(course_id)
attached_files = cv.list_assignment_files(course_id, assignment_id)
Apply the redact_behavioral_rules filter from canvas-bootstrap §5a to every external text body (description, front_page, syllabus, module wiki pages) — instructor conduct rules must never enter this skill's working set.
Front page excerpt where it mentions this assignment kind (search front_page body for assignment name fragments).
Module hits — list_modules items whose name fragment-matches the assignment.
Syllabus excerpt where it mentions this assignment kind.
Every external URL found in the above, deduped. Mark each as INSTRUCTOR_SITE / READING / THIRD_PARTY based on host.
Stage 2 — find-rubric
Locate the grading rubric in this order:
Canvas-attached rubric — cv.get_rubric(course_id, assignment_id). If present, render to investigation/rubric.md as a bulleted list of criteria + point breakdown.
Spec body grep — search spec.md + downloaded attached PDFs for rubric / criteria / graded on / points breakdown / you will be evaluated on / assessment criteria. Capture the surrounding paragraph.
Module / syllabus grep — same patterns across module wiki page bodies and syllabus.
Instructor-external URL fetch — if Stage 1 found INSTRUCTOR_SITE URLs, fetch and grep them.
If nothing found after all 4 layers: write rubric.md with the literal first line RUBRIC NOT FOUND - student must supply. Sub-agent A will flag this in Stage 4 and the skill will ask the student for the rubric URL or paste before proceeding.
Stage 3 — locate-inputs
Download every file referenced by the assignment to references/:
All attached_files from cv.list_assignment_files.
All PDFs / readings linked from spec.md or module wiki pages.
Starter code / scaffold archives if any (zip / git-bundle / GitHub Classroom).
INSTRUCTOR_SITE URLs from Stage 1 — fetch the HTML body.
For URLs that are fetchable but content-unclear (Google Doc share links, third-party platforms), attempt anonymous fetch first; if redirected to a login wall, log to investigation/unreachable.txt with the URL and the wall type.
For YuJa / password-protected / cookie-required resources: log to unreachable.txt and Sub-agent A will surface them as blocking_unreachables.
Stage 4 — Sub-agent A: review investigation
Spawn one general-purpose agent via the Agent tool. Use this exact prompt template (fill in the bracketed paths):
You are reviewing the investigation phase of a Canvas assignment that doesn't fit any specialized skill. The investigation outputs are in [runs/<today>/<work>/]. Read every file under spec.md, investigation/rubric.md, references/, and investigation/unreachable.txt. Then answer:
Is the assignment's deliverable clear? In one sentence, what is the student expected to produce?
Is the rubric documented? If rubric.md starts with RUBRIC NOT FOUND, this is critical.
Are all referenced materials downloaded under references/? List any reading / data / scaffold the spec mentions but isn't present.
Are there sources you suspect were missed (front-page links not followed, module wiki pages not pulled, instructor-site sub-pages)? List them with where to look.
Do the unreachable resources block the work, or can the assignment be completed without them?
Output strict JSON with these fields:
deliverable_clear: bool
deliverable_summary: string (one sentence)
rubric_found: bool
inputs_complete: bool
missing_sources: string[] // where-to-look hints
blocking_unreachables: string[] // unreachable resources that genuinely block the work
verdict: 'proceed' | 'recover' | 'stop'
recovery_actions: string[] // populated only when verdict == 'recover'
Do not output prose around the JSON.
Save output to investigation/review_a.json.
Handling the verdict:
stop → write result.json with status: "error", notes = a one-paragraph summary of why (paraphrase from Sub-agent A's deliverable_summary + missing_sources). End the skill.
recover → for each recovery_action:
If it's a "fetch X URL" the skill missed → run the fetch and append to references/.
If it's a "no rubric" recovery → tell the student: "I couldn't find a grading rubric anywhere for this assignment. If you have a copy or a link, paste it or send the URL. Otherwise I'll do my best with the assignment description alone, but verification will be looser." Wait for student response.
If it's a blocking_unreachable → YuJa-style soft-stop: tell the student "This assignment references [resource]. I can't reach it from here. If you can paste the relevant content or send a transcript, I'll use it; otherwise I'll proceed without it and flag the gap in my notes."
After recovery actions complete, re-run Stage 4 with the same prompt. Max 2 recovery rounds. If verdict is still not proceed after round 2, escalate to stop.
proceed → continue to Stage 5.
Stage 5 — classify-output
Pick the output mode based on spec.md + investigation/rubric.md + assignment.submission_types + what's in references/. Plus: if Stage 0's user_preferences contains a preferred_output_mode hint from prior dispatches, prefer that mode when this assignment's signals are ambiguous (e.g. when both doc_prose and pdf_typed could fit, learnings nudges toward whichever the student has settled on). Write the chosen mode as the first line of pipeline_design.md:
Mode
Trigger conditions
doc_prose
submission_types contains online_upload or online_text_entry AND rubric mentions word count / paragraph structure / essay shape. Output: .docx (or .md if rubric is silent on format).
pdf_annotated
submission_types contains online_upload AND references/ contains a reading PDF AND rubric mentions annotation / highlights / margin notes. Output: annotated copy of the source PDF.
pdf_typed
submission_types contains online_upload AND rubric mentions math notation / LaTeX / problem set / numerical answers. Output: typed PDF.
code
submission_types contains online_upload AND references/ has a scaffold OR rubric mentions "submit your code" / file extensions like .py / .js. Output: source file(s) or archive.
form_answers
submission_types contains online_text_entry AND rubric is a list of short questions OR assignment description contains a list of questions. Output: text submission body.
mixed
multiple of the above apply (e.g. lab report = pdf_typed + code). Decompose into constituent modes; treat each as a sub-pipeline.
If no mode matches with confidence (less than 80% confident the right mode is one of these): write result.json with status: "error", notes: "could not classify output mode for assignment; investigation/ has full context; please dispatch a specific skill manually or extend canvas-generic". End the skill.
Stage 6 — design-pipeline
Append the pipeline stages to pipeline_design.md. Use the template matching the Stage 5 mode. Apply Stage 0 learnings: if workflow_notes from the learnings overlay says to skip / reorder / parameterize a stage (e.g. "skip figure-caption substage — this cluster never has figures"), honor that. If user_preferences specifies voice register / citation style / format, fold those into the stage template's parameter slots (e.g. voice_register: <learnings.voice_register> instead of the default B1-B2).
doc_prose:
1. draft — prose generator, target word count from rubric, voice register inferred from
assignment context (default B1-B2 international-student for undergraduate; advanced
academic if rubric demands graduate-level voice)
2. canvas-humanizer — Skill tool invocation, voice register fixed from step 1
3. export — render to .docx (or rubric-specified format)
pdf_annotated:
1. read source PDF from references/
2. extract underscore-group answer blanks via PyMuPDF
3. annotate inline — coordinate-based left-margin notes (x < 80), color rubric
per rubric.md if specified, else default green=vocab pink=content
4. fill answer blanks at ≥90% line width in target voice
5. render output PDF
pdf_typed:
1. parse problem statements from spec.md + references/
2. solve each problem (LLM judgment + show work)
3. render solutions to LaTeX
4. compile to PDF via MathJax
code:
1. analyze scaffold in references/ (if present)
2. read tests if any (rubric "tests pass" criterion)
3. implement — test-first if tests exist, else direct-to-spec
4. run tests / lint per rubric's criteria
5. package per submission_format (single file / zip / git bundle)
form_answers:
1. extract question list from spec.md
2. answer each question, citing source from references/ where applicable
3. format as text submission body
mixed: list each constituent mode's stages with a prefix, then a concatenation step at the end.
Adjust each template's stages for rubric specifics:
Citation style mentioned in rubric → add a citations substage between draft and export.
Specific notation rule ("name each law you apply") → add to the generator prompt.
Required figure count → add to the draft prompt + Stage 8 checklist.
Show full SKILL.md (1,392 more words)Show less
Stage 7 — generate
Run the pipeline designed in Stage 6. Write artifacts to draft/.
For doc_prose: after the draft is produced, invoke canvas-humanizer via the Skill tool with input_path=draft/<filename> and voice_register from Stage 6 step 1. Humanizer writes humanized output back to the same path and writes humanizer_log.json to the work dir.
For code: if references/ contains a test scaffold, run the tests after each generation pass; iterate until passing (max 5 implementation rounds, then status: "error"). If no tests exist, generate, then run python -m py_compile (or equivalent for the language) to confirm parseable.
For pdf_annotated: use PyMuPDF following the same pattern as canvas-reading-annotation (coordinate-based left-margin annotation, ≥90% line-width answer fills). Apply the color rubric from rubric.md if specified; default green=vocab pink=content otherwise.
For pdf_typed: render via MathJax → PDF. Ensure no [placeholder] literals leak.
For form_answers: write the body to draft/submission.txt.
For mixed: run each constituent sub-pipeline producing its own artifact, then concatenate or co-locate per the rubric's stated submission shape.
Stage 8 — Sub-agent B: design verification
Spawn one general-purpose agent. Use this exact prompt template:
You are designing a verification checklist for a Canvas assignment draft. Read these files:
[runs/<today>/<work>/]investigation/rubric.md — the grading criteria
[runs/<today>/<work>/]draft/ — the produced draft
[runs/<today>/<work>/]pipeline_design.md — the chosen output mode
Produce a numbered checklist where each item is a yes/no testable proposition derived from a specific rubric line:
For numeric constraints (word count, page count, citation count, function count, problem count): the check must produce a measured number with a pass criterion threshold.
For structural constraints (thesis paragraph present, conclusion present, figure caption format, required section headings): the check must locate the expected structural element and report present/absent.
For voice/register constraints: the check must spot-check ≥3 paragraphs against named criteria from the rubric (e.g. "no contractions in academic register").
For content/correctness constraints that aren't mechanically checkable (e.g. "argument is persuasive"): mark as human_review and skip the check.
Output a markdown checklist to verification_checklist.md. Each item must be on its own line in this format:
form_answers: every question in the spec has a non-empty answer.
Save the checklist to verification_checklist.md.
Stage 9 — verify
Run every check in verification_checklist.md in order. Each check produces a line in verification.log:
PASS | word_count >= 500 | measured: 612
PASS | citation_count >= 3 | measured: 5
FAIL | thesis_in_intro_paragraph | measured: not detected in first 200 words
SKIP | argument_is_persuasive | reason: human_review (not mechanically checkable)
Use the SAME measurement primitives as the specific skills:
len(text.split()) for word count.
page_count from PyMuPDF for PDFs.
ast.parse + [node for node in ast.walk(tree) if isinstance(node, ast.FunctionDef)] for function counts.
re.findall for citation patterns.
If any FAIL: re-enter Stage 7 with the failing checks fed back into the generator prompt as explicit constraints. Max 3 retry rounds. If still failing after round 3 → result.json with status: "error", notes listing the persistent FAILs.
Stage 10 — Sub-agent C: review verification
Spawn one general-purpose agent. Use this exact prompt template:
You are reviewing whether a verification checklist actually covers the assignment's rubric. Read:
[runs/<today>/<work>/]investigation/rubric.md
[runs/<today>/<work>/]verification_checklist.md
[runs/<today>/<work>/]verification.log
Answer:
For each rubric line that is mechanically checkable, is there a corresponding check in the checklist?
Are any checks false-pass risks? Example: a "has citations" check that passes on any [1] even if it's not a real citation; a "thesis present" check that just looks for the word "thesis"; a "no placeholders" check that misses Unicode-formatted ones.
Are any rubric items un-checkable mechanically and skipped — does that leave a non-trivial grading risk?
Output strict JSON:
coverage_gaps: string[] // rubric items that should have a check but don't
false_pass_risks: string[] // checks that look like they pass but might not catch real failures
human_review_items: string[] // rubric items that are intrinsically subjective
add_checks → re-enter Stage 8 with coverage_gaps + false_pass_risks as additional inputs to Sub-agent B's prompt. Then re-run Stage 9. Max 2 rounds of B↔C iteration. If verdict is still add_checks after round 2, downgrade to human_review_required.
human_review_required → continue to Stage 11 but include review_c.human_review_items in result.json.notes so the student knows what to spot-check before uploading.
verification_sufficient → continue to Stage 11.
Stage 11 — export + result
The draft artifact is already at draft/<filename> from Stage 7. Finalize the filename if needed (e.g. attach .final suffix, rename to match Canvas's expected filename pattern from assignment.allowed_extensions).
Never auto-submit. canvas-generic has no overlay-level authorization mechanism by design. Status is always draft_ready or error. The student reviews the draft and uploads manually.
Hook contract
Hooks the skill must satisfy:
Stop hook (check-router-complete.py) — every assignment in assignments.json must have a result.json. Stage 11 writes one; on error paths in Stages 4 / 5 / 9 / 10, write the error result.json before stopping.
PostToolUse check-result-schema.py — result.json.status must be one of draft_ready / error. (No submitted because canvas-generic never submits.)
PostToolUse check-spec-grounding.py — for status: "draft_ready", if spec.md mentions external references but references/ is empty, the hook blocks. Stage 3 must download what's reachable; Stage 4 Sub-agent A must surface what isn't.
PreToolUse check-presubmit-audit.py — not relevant; canvas-generic never calls cv.submit_files.
PostToolUse check-identifier-grounding.py — for code output mode producing .py files, every suspicious identifier must be grounded in spec.md / references/ / Python builtins. Same as canvas-ics33.
§11 — When to graduate a cluster to a specific skill
canvas-generic is the runtime-design fallback. The 5 specific skills exist BECAUSE certain assignment shapes (code with test runners / quiz with arbitration / zyBook tables / annotation rubrics / long essays with citation styles) deserve a pre-designed pipeline.
Three sub-agent reviews (A / B / C) replace what the overlay would have specified. Token cost: a canvas-generic dispatch runs roughly 3× the LLM calls of a comparable specific-skill dispatch.
For low-frequency clusters (a one-off assignment, a course you take once), this is the right tradeoff.
For high-frequency clusters (an assignment kind that fires every week for a quarter), graduating to a specific skill is worth it. Signs that a cluster should graduate:
canvas-generic has run on the same cluster 4+ times.
Sub-agent C keeps flagging the same coverage_gaps each run (= the verification logic is converging on a stable shape that should be hardcoded).
The pipeline_design.md stages are essentially identical across runs (= the pipeline is converging on a stable shape).
When this happens: re-run canvas-bootstrap on the cluster, manually override the route from canvas-generic to whichever specific skill matches the converged pipeline shape (or, rarely, file an issue to add a sixth specific skill).
When invoked with a context line containing STAGE-BY-STAGE MODE AND the control file <work>/.first_run_stage_by_stage exists, run only the single stage named in the directive instead of the full pipeline. Set by canvas-bootstrap §8 during first-run calibration so the student reviews each stage before the next runs.
Behavior:
Read <work>/.first_run_stage_by_stage to confirm. If absent, run the full 11-stage pipeline as usual.
Parse the directive for the stage name (fetch-context, find-rubric, locate-inputs, sub-agent-a, classify-output, design-pipeline, generate, sub-agent-b, verify, sub-agent-c, export).
Run only that stage's substeps from §3 above. Prior stages' artifacts must already be in <work>/.
Write a 1-3 sentence English summary to <work>/stages/{stage_name}.done and STOP.
Daily dispatch via canvas-execute does not set the marker; runs full-pipeline as usual.
Canvas Generic next to the 5 skills that share the most tags, products or categories with it. Stars are the repository's; “used in” counts other GitHub owners with a copy.
Canvas Generic compared with similar skills
Skill
Stars
Used in
Tokens
Auto-check
Licence
Repo updated
Canvas Generic this skillX-isdoingreat/canvas-pilot
Runs an interactive quiz in a quick or comprehensive mode, scores your skill level by topic and generates a personalized learning path with practice projects.
Plans an OpenMAIC lesson or course series by backward design: enduring understandings and essential questions first, then performance evidence, then learning activities.
READ-ONLY diagnostic: scan HAX webcomponents, themes, CMS backends (PHP/NodeJS HAXcms), the VitePress plugin, and the Google Apps Script add-on for code surfaces that render or consume pedagogical…
Turns a PDF, paper, document, URL or topic into a chapter-by-chapter course with exercises, feedback and review, and saves progress so you can resume later.
A skill your agent uses when verified work from today or another day should become an X/Twitter post, build-in-public update, ship log, or bilingual draft.
A skill your agent uses when a short local academic draft needs role-aware syntax diversification while preserving meaning, locks, source grounding, rubric-critical openings, and document structure.
A skill your agent uses for an approved long academic-writing assignment routed by canvas-execute after the deterministic writing router selects essay.
A skill your agent uses when a local academic draft needs a meaning-preserving humanizing pass with less uniform syntax while retaining rubric, source, lock, voice, and length constraints.
Fallback runtime-designed handler for Canvas assignments that don't fit any of the 5 specific skills (canvas-ics33 / canvas-reading-annotation / canvas-essay / canvas-zybooks / canvas-inside). Canvas Generic is an agent skill from X-isdoingreat/canvas-pilot. Fallback runtime-designed handler for Canvas assignments that don't fit any of the 5 specific skills (canvas-ics33 / canvas-reading-annotation / canvas-essay / canvas-zybooks / canvas-inside).
When should I use Canvas Generic?
Canvas Generic fits situations like: tasks that involve Quizzes and assessments; tasks that involve Subagents; tasks that involve Curriculum and course design.
How do I install Canvas Generic in Claude Code?
Run `npx skills add X-isdoingreat/canvas-pilot --skill canvas-generic -a claude-code`. Or copy the skill folder (.claude/skills/canvas-generic in X-isdoingreat/canvas-pilot) into .claude/skills/canvas-generic in your project. Claude Code loads it when a task matches its description.
How do I install Canvas Generic in Codex?
Run `npx skills add X-isdoingreat/canvas-pilot --skill canvas-generic -a codex`. Or copy the skill folder (.claude/skills/canvas-generic in X-isdoingreat/canvas-pilot) into .agents/skills/canvas-generic in your project. Codex loads it when a task matches its description.
Can I use Canvas Generic in Cursor, Gemini CLI or GitHub Copilot?
Cursor, Gemini CLI, GitHub Copilot and OpenCode also load SKILL.md folders. With the skills CLI, run `npx skills add X-isdoingreat/canvas-pilot --skill canvas-generic -a cursor` (or -a gemini-cli, github-copilot or opencode for the others). To copy it by hand, put the folder in .cursor/skills/canvas-generic, .gemini/skills/canvas-generic, .github/skills/canvas-generic and .opencode/skills/canvas-generic in your project.
What does Canvas Generic need to run?
Going by SKILL.md and its folder, Canvas Generic needs the command-line tools its instructions call (python). Our summary lists: Python 3. Its frontmatter pre-approves these tools: Bash, Read, Write, Edit, Glob, Grep, WebFetch, Skill, Agent.
Does Canvas Generic access the network?
SKILL.md contains no URLs. Any network use would come from the scripts or tools the agent runs. This is read from the text; nothing was executed.
Is Canvas Generic safe to install?
Our automated static check of SKILL.md found notes only (pre-approves every shell command (allowed-tools: bash)), nothing it rates as a warning. It is not a guarantee. Review the folder before installing.
What licence does Canvas Generic use?
Canvas Generic is published under the AGPL-3.0 licence (the repository's licence). It allows redistribution, so the full SKILL.md is shown on this page.
How many tokens does Canvas Generic use?
About 7.5k tokens (SKILL.md is roughly 30k characters). Agents keep only the skill's name and description in context until a task matches; then they load SKILL.md in full.
What are the alternatives to Canvas Generic?
Skills that share tags, products or a category with Canvas Generic: AI Engineering Placement Quiz (rohitg00/ai-engineering-from-scratch, 66k stars), Codex Skill Self-Assessment (FlorianBruniaux/claude-code-ultimate-guide, 6.1k stars), Learn Law With Rohas (rohasnagpal/legal-ai-skills, 178 stars) and Understanding by Design Planner (THU-MAIC/OpenMAIC, 40k stars). The comparison table on this page puts their stars, adoption, token cost, safety result and licence side by side.
Who maintains Canvas Generic?
X-isdoingreat (a GitHub user) maintains it in X-isdoingreat/canvas-pilot, which has 125 GitHub stars. The repository holds 32 skills in this directory. The repository was last updated on July 31, 2026.
Source: X-isdoingreat/canvas-pilot on GitHub. Facts on this page come from the repository at the commit we read; the author's words are quoted as theirs.