_ _ _
___ __ _ _ ___ ____ _ __| |_ __ __| |_| |
/ __/ _` | ' \ V / _` (_-< _/ _/ _| _| |
\___\__,_|_||_\_/\__,_/__/\__\__\__|\__|_|
canvasctl
Canvas in your terminal. A read-focused Canvas LMS companion that mirrors your courses into a local vault, answers questions with a Claude-powered chat agent, and plugs into Claude Code / Claude Desktop over MCP.
What is this
canvasctl mirrors your Canvas courses — assignments, quizzes, modules, files, and
announcements — into a plain-JSON vault at ~/canvas-vault/, then gives you fast
terminal answers to "what's due today?", "what changed since yesterday?", and
"export the next 60 days as a calendar." A built-in chat agent (canvasctl ask /
canvasctl chat) uses your own Anthropic API key to answer natural-language
questions by calling read-only tools over that vault. And an MCP server
(canvasctl mcp) exposes the same operations to Claude Code and Claude Desktop, so
you can ask Claude about your coursework from anywhere.
Everything runs on your machine. The only network calls it makes are to your own
school's Canvas instance and — if you opt into the agent — directly to
api.anthropic.com with your own key. It is read-focused by design: there is no
assignment submission and no mutation of Canvas.
Quick start
# 1. Install (see alternatives below if you'd rather use pipx or a venv)
curl -fsSL https://raw.githubusercontent.com/vivekp-05/canvasctl/main/install.sh | sh
# 2. Onboard — asks for your Canvas URL + access token, optionally an Anthropic key
canvasctl setup
# 3. Pull your courses into the local vault, then ask away
canvasctl sync
canvasctl today
canvasctl ask "what's due this week?"
Install alternatives
pipx, straight from git (isolated, on your $PATH):
pipx install "canvasctl[agent,mcp] @ git+https://github.com/vivekp-05/canvasctl.git"
Drop the [agent,mcp] extras if you only want the core read-only CLI without the
Claude chat agent or MCP server.
From source, with a virtualenv:
git clone https://github.com/vivekp-05/canvasctl.git
cd canvasctl
python3 -m venv .venv
source .venv/bin/activate
pip install -e ".[agent,mcp,dev]"
canvasctl --version
Features
Every read command supports --json for piping into jq, and --course <id|alias>
to scope to one course.
| Command | What it does |
|---|---|
setup |
New. Interactive onboarding wizard: prompts for your Canvas base URL and personal access token, optionally an Anthropic API key for the chat agent, and writes them to ~/.config/canvasctl/config.json (chmod 600). |
sync |
Pull all course metadata (assignments, quizzes, modules, files, announcements) into ~/canvas-vault/ in parallel, with retry/backoff for 429/5xx and graceful auth-error handling. |
today |
List items due today. |
due |
List items due in any future window — 24h, 7d, 2w, or an ISO start..end range. |
announcements (ann) |
Show recent announcements, with optional message previews. |
changes |
Replay the local change-log — snapshots are SHA-256 hashed per course/kind so you see exactly what shifted between syncs. |
status (dashboard, dash) |
One-screen overview: due today, recent announcements, recent changes, last sync time. |
list |
Tabular listing of courses, assignments, quizzes, files, modules, or announcements. |
show |
Print the full Canvas JSON for a single item. |
pull |
Download course files into <vault>/content/<course_id>/. |
ics |
Export upcoming due dates as an .ics calendar you can subscribe to in Apple/Google Calendar. |
ask |
New. One-shot question to the Claude chat agent. Uses your own Anthropic API key (model claude-opus-4-8) and answers by making read-only tool calls over the local vault — never touching Canvas write endpoints. Example: canvasctl ask "what's the biggest thing due before Friday?" |
chat |
New. Interactive REPL version of ask — a running conversation with the same tool-calling agent over your vault. |
mcp |
New. Run the MCP server (stdio) so Claude Code and Claude Desktop can call the same read-only operations. Registers one MCP tool per vault operation. |
The chat agent and MCP server are bring-your-own-key: nothing is proxied through anyone else. Your Anthropic key is read from
~/.config/canvasctl/config.json(written bycanvasctl setup) or theANTHROPIC_API_KEYenvironment variable.
Use it from Claude Code / Claude Desktop
canvasctl mcp speaks the Model Context Protocol over stdio, exposing your vault's
read operations as tools.
Claude Code — register it in one line:
claude mcp add canvasctl -- canvasctl mcp
Claude Desktop — add an entry to the mcpServers block of your
claude_desktop_config.json:
{
"mcpServers": {
"canvasctl": {
"command": "canvasctl",
"args": ["mcp"]
}
}
}
Then ask Claude things like "what canvasctl says is due this week?" or "summarize the latest announcements in my courses." See docs/mcp.md for the full tool list, setup details, and example prompts.
Layout of the local vault
~/canvas-vault/
├── state/
│ ├── config.json # vault path, aliases, last_sync_at
│ ├── metadata/
│ │ ├── _courses/courses.json
│ │ └── <course_id>/{assignments,quizzes,modules,module_items,files,announcements}.json
│ └── logs/
│ ├── last_hashes.json # for diffing between syncs
│ └── changes.jsonl # append-only change-log
├── content/ # downloaded files (canvasctl pull)
└── outputs/ # generated artifacts (canvasctl ics)
The vault is plain JSON on disk — feel free to grep, jq, or back it up directly.
Your Canvas token and Anthropic key are not stored in the vault. They live in a separate credentials file at
~/.config/canvasctl/config.json(mode600).
Security & privacy
- Bring your own keys (BYOK). You supply your own Canvas personal access token and your own Anthropic API key. Nothing is proxied through a third party.
- Treat your Canvas token like a password. A Canvas personal access token is a full-access student credential — anyone holding it can act as you across every course and setting your account can reach. Generate it under Account → Settings → New Access Token, give it a short expiry, and revoke it the moment you suspect exposure.
- Credentials live in one file, locked down.
canvasctl setupwrites your Canvas URL, token, and optional Anthropic key to~/.config/canvasctl/config.jsonand sets its permissions to600(owner read/write only). It is never committed and never copied into the vault. - Nothing leaves your machine except direct calls to Canvas and Anthropic. The
only outbound traffic is to your school's Canvas host (to sync) and, if you use the
agent, to
api.anthropic.comwith your own key. There is no telemetry and no middleman server. - Read-focused by design.
canvasctlonly reads from Canvas. There is no assignment submission, no grade posting, and no mutation of any Canvas resource — the MCP server and chat agent expose read/local operations only.
For the full threat model, see docs/security.md.
Requirements
- Python 3.10 or newer. The core CLI runs on 3.10+; the
ask/chatagent and themcpserver additionally require the optionalanthropicandmcppackages (installed via the[agent]/[mcp]extras). - A Canvas LMS account and a personal access token.
- An Anthropic API key, only if you want the
ask/chatagent.
Development
git clone https://github.com/vivekp-05/canvasctl.git
cd canvasctl
python3 -m venv .venv
source .venv/bin/activate
pip install -e ".[agent,mcp,dev]"
# Run the test suite
pytest -q
Package layout:
canvasctl/
├── cli.py # argparse + dispatch
├── client.py # Canvas REST client (retry, backoff, pagination)
├── store.py # vault layout + atomic JSON I/O + change log
├── diff.py # by-id diffing
├── records.py # normalize Canvas dicts -> due-date records
├── timeutil.py # window parsing + safe datetime handling
├── formatting.py # colors, tables, byte formatting
├── ops/ # operation registry shared by the CLI, agent, and MCP server
└── commands/ # one module per subcommand
The ops/ registry is the single source of truth for every Canvas operation: each op
is defined once (name, description, JSON schema, handler, kind) and consumed by three
surfaces — the argparse CLI, the MCP server, and the chat agent.
License
MIT © 2026 Vivek Patel.
Disclaimer
canvasctl is an independent, unofficial tool for use with Canvas LMS. It is not
affiliated with, endorsed by, or sponsored by Instructure, Inc. "Canvas" and
"Instructure" are trademarks of Instructure, Inc.
Release files for canvasctl 0.3.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| canvasctl-0.3.0.tar.gz | 49.8 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| canvasctl-0.3.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 99.5 kB
Release files / canvasctl-0.3.0.tar.gz
| Download URL | canvasctl-0.3.0.tar.gz |
|---|---|
| Size | 49.8 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
be30fc0ca13f2ac2a5ccd195a6d677977d383e4cb107aa62920aee8381414fb4
|
|
BLAKE2b-256 checksum How to use checksums |
2e18d925b927e981995c74c8c625355e7848b2f274e57271c4fc82adc150d88a
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.12
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Jul 19, 2026.
Transparency logRelease files / canvasctl-0.3.0-py3-none-any.whl
| Download URL | canvasctl-0.3.0-py3-none-any.whl |
|---|---|
| Size | 49.7 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
40ff3c96fffb84d8ddaed7419e8065ee82c0e301a5317f0bef1afb2f1f6988b3
|
|
BLAKE2b-256 checksum How to use checksums |
6926f259be0d1c2e1c35562e28cbfba518a6e8148a461739ca3fc1909274e279
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.12
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Jul 19, 2026.
Transparency log