Skip to main content
                           _         _   _
  ___ __ _ _ ___ ____ _ __| |_ __ __| |_| |
 / __/ _` | ' \ 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.

Python 3.10+ License: MIT PRs welcome

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 by canvasctl setup) or the ANTHROPIC_API_KEY environment 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 (mode 600).

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 setup writes your Canvas URL, token, and optional Anthropic key to ~/.config/canvasctl/config.json and sets its permissions to 600 (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.com with your own key. There is no telemetry and no middleman server.
  • Read-focused by design. canvasctl only 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/chat agent and the mcp server additionally require the optional anthropic and mcp packages (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 / chat agent.

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)

Source distribution for canvasctl 0.3.0
File Size Uploaded
canvasctl-0.3.0.tar.gz 49.8 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for canvasctl 0.3.0
File Interpreter ABI Platform
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 log

Release 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

Release history Release notifications | RSS feed

0.4.2

2 release files

0.4.1

2 release files

0.4.0

2 release files

0.3.1

2 release files

This release

0.3.0 This release

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page