BackUsing canvas-cli

Course ingestion

What canvas-cli downloads from a course, how it turns documents into searchable text, and where it all lives on disk.

Running It

Ingestion turns a Canvas course into plain files in .canvas-cli/courses/, which is everything the assistant and the workspaces read from. It happens automatically the first time you open a course in the shell. To do it ahead of time, or from a script, use the command:

canvas-cli ingest ECE216              # by course code
canvas-cli ingest "Signals and"      # or any unique part of the name
canvas-cli ingest ECE216 --json      # machine-readable summary
canvas-cli ingest ECE216 --no-feedback

Progress goes to stderr, and a summary of what was fetched follows:

Ingesting Signals and Systems...

Course ingested

	Course  Signals and Systems
	Code    ECE216
	Term    Fall 2026
	Path    .canvas-cli/courses/ece216-101

Fetched:
	- 6 assignments
	- 2 modules
	- 4 module items
	- 3 files
	- 3 assignment groups (weights and drop rules on the grading-scheme page)
	- 1 external tools (Piazza, Zoom, Ed, ... from course navigation)
	- 2 pages
	- 2 announcements

Likely syllabus sources:
	1. Course Syllabus (built-in) [syllabus_body] high
	2. Grading scheme: assignment groups and weights [page] medium

Attachments:
	- Lecture 7 - Fourier Series.pdf downloaded (module file in "Week 3: Fourier Series")
	- Lab3_Fourier_Series.pdf downloaded (module file in "Week 3: Fourier Series")
	- ECE216_Course_Outline.pdf downloaded (module file in "Course Information")

canvas-cli ingest ECE216, for the demo course used throughout these docs.

Running it again fetches everything from Canvas again and rewrites the indexes and extracted text. Files that are already on disk are not downloaded a second time, so repeat runs are quick. That also means a file your instructor replaces under the same name keeps your old copy: delete it from .canvas-cli/courses/<course>/attachments/ to fetch the new version. In the shell, /refresh in a course does the same. Ctrl C stops a run cleanly.

What’s Captured

From CanvasWhat canvas-cli keeps
CourseName, code, term, dates, and the syllabus
AssignmentsDescriptions, due dates (including per-section dates), points, submission rules, rubrics, and group weights
ModulesEvery item in order, with prerequisites and completion requirements
PagesEvery page, including ones only reachable by links from other pages
FilesThe whole Files tab, folder by folder, plus files attached to assignments, posts, and replies
Announcements and discussionsEvery post with all its replies, in thread order
Quizzes, tools, calendarTurned into reference pages; see below
Your submissionsGrader comments, feedback files, and rubric scores on your own work
Linked contentThe text of external pages and documents the course links to
LecturesSlides and recordings, found wherever they are posted or embedded

Files are downloaded four at a time, up to 200 MB each, and only from your Canvas site. The Files tab crawl skips images, audio, and video and takes up to 1,000 documents; files a module or assignment points at are always fetched.

Reference Pages

Some of the most useful information in Canvas is not in any document. Ingestion writes it into pages of its own, which search and the assistant treat like any other page:

PageContains
Quiz: <title>One per quiz: type, open, due, and lock dates, time limit, attempts, points, question count, and instructions
Grading scheme: assignment groups and weightsEach group's weight and drop rules, and roughly how much of the final grade each assignment is worth
Course tools and external linksThe course's navigation tools, such as Piazza, Ed, Zoom, or Gradescope, with what each is for
Calendar event: <title>One per event, with time, location, and description
Course calendarEvery event in date order, so exam slots and office hours are searchable

Extraction

Every downloaded document gets a plain-text copy under extracted/, organized so it can be read one section at a time:

FormatExtracted as
PDFPage by page, under ## Page N headings. Pages that are only images are marked as such.
Word (.docx)Headings, lists, tables, footnotes, headers and footers, and reviewer comments
PowerPoint (.pptx)One ## Slide N section per slide, with speaker notes and comments
Excel (.xlsx)One section per sheet, with formulas beside their values, up to 1,000 rows per sheet
Zip archivesUnpacked into <name>.zip.unpacked/, three levels deep, each file extracted
Plain text and codeKept as is: .txt, .md, .csv, .py, .c, .h, .java, .js, .ts, .s, .asm
HTMLConverted to text, keeping the indentation of code blocks

Each document keeps up to 400,000 characters, so a long textbook chapter is not cut short. When a PDF is longer than that, it is cut at a page boundary and the note says which pages were left out.

Zip archives are opened with limits, 100 MB per file, 5,000 files, and 1 GB in total, so a malicious or broken archive cannot fill your disk.

Hidden Content

Course material often hides inside other material. Ingestion follows it:

  • Canvas file links in every form course pages use: plain links, embedded PDF viewers, and module items that point at a file.
  • External content linked or embedded in pages, assignments, the syllabus, announcements, and replies. Google Docs, Slides, and Sheets are fetched through their export links; PDFs and Office files are extracted; web pages are reduced to their text; caption files (.vtt, .srt), which are usually lecture transcripts, are kept as text. Up to 30,000 characters are kept from each link. Your Canvas token is only ever sent to your Canvas site, never to an outside host.
  • Lecture recordings embedded from YouTube, Vimeo, Panopto, Kaltura, Echo360, Mediasite, Zoom, Loom, Google Drive, and Canvas Studio, numbered by lecture wherever the titles allow. Recordings are indexed, not downloaded.

Your Feedback

Ingestion also saves what graders said about your submissions: comments, attached feedback files, and rubric scores, criterion by criterion. Canvas only returns your own submissions, so nothing about other students is ever requested. Feedback appears as a ## Submission Feedback section in each assignment’s text, which is how the assistant can answer “what did I lose marks on in Lab 2?”.

To leave it out, pass --no-feedback, or set "ingestSubmissionFeedback": false in your profile’s config.json to make that the default.

JSON Output

--json prints a single JSON object instead of the summary, for scripts. It includes the counts, what happened to every attachment, and the absolute path to the course cache:

{
	"ingestion": {
		"version": 1,
		"ingestedAt": "2026-09-23T21:56:25.761Z",
		"courseId": 101,
		"courseName": "Signals and Systems",
		"courseCode": "ECE216",
		"counts": { "assignments": 6, "modules": 2, "files": 3, "pages": 2, "lectures": 1, ... },
		...
	},
	"coursePath": "/Users/you/school/.canvas-cli/courses/ece216-101",
	"announcements": ..., "discussions": ..., "externalLinks": ..., "syllabusCandidates": ...,
	"attachments": [{ "filename": "Lab3_Fourier_Series.pdf", "sourceType": "...", "status": "downloaded", "reason": "..." }]
}

Blocked APIs

Some schools block parts of the Canvas API for students, most often Files and Pages. Ingestion carries on without them: a blocked section comes back empty instead of failing the run, and the summary marks Files or Pages (API not accessible) when they come back empty. Module items and assignment descriptions usually still work, so most documents are found anyway through the links in them. Quizzes, course tools, and grading groups are optional in the same way.

Temporary errors (rate limits and server errors) are retried up to three times. Authentication and permission errors are not, since retrying cannot fix them. See Troubleshooting.