---
name: canvas-nav
description: "Browse or search your Canvas course structure — modules, pages, assignments, quizzes — without leaving the conversation."
---

# Canvas Course Navigator

> **Plugin**: ASU Canvas Course Builder
> **Script**: `scripts/course_navigator.py`

## Purpose

Display the full course tree (modules → text headers → pages/assignments/quizzes/discussions/files/external tools) directly in the conversation. Browse, search, and jump to any content item without clicking through Canvas.

## When to Use

- Before editing — find the page slug you need
- After building — verify the course structure looks right
- When the user says "show me the course", "what's in module 3", "find the quiz"
- As a reference while running other skills

## Commands

| Input | What It Does |
|---|---|
| "Show me the course" | Full course tree |
| "What's in Module 3?" | Filter to Module 3 |
| "Find the quiz" | Search for all quiz items |
| "Find m2-overview" | Search by page slug |
| "Refresh the tree" | Force-refresh the cached tree |

## Workflow

### Step 1 — Fetch the Course Tree

```bash
${ASUCB_PLUGIN_ROOT:-${CODEX_PLUGIN_ROOT:-${CLAUDE_PLUGIN_ROOT}}}/bin/python3 scripts/course_navigator.py --course-id {COURSE_ID} --tree
```

Or for JSON output:
```bash
${ASUCB_PLUGIN_ROOT:-${CODEX_PLUGIN_ROOT:-${CLAUDE_PLUGIN_ROOT}}}/bin/python3 scripts/course_navigator.py --course-id {COURSE_ID} --json
```

The script caches results for 5 minutes to avoid repeated API calls.

### Step 2 — Display the Tree

```
Course: BIO 101 - Intro to Biology (ID: 255160)

+ Module 0: Getting Started
    --- Welcome & Course Overview
    [P] Welcome to BIO 101 [welcome]
    [P] Syllabus [syllabus]
    [A] Introduce Yourself (25 pts) [introduce-yourself]

+ Module 1: Cell Biology
    --- Overview
    [P] Module 1 Overview [m1-overview]
    --- Prepare to Learn
    [P] Prepare to Learn [m1-prepare-to-learn]
    --- Lesson
    [P] Cell Structure & Function [m1-lesson]
    --- Assess Your Learning
    [Q] Knowledge Check 1 (15 pts)
    [A] Create an Artifact 1 (30 pts)
    [D] Discussion 1 (25 pts)
    --- Wrap Up
    [P] Conclusion [m1-conclusion]

- Module 2: Genetics (unpublished)
    ...
```

**Legend:**
```
[P] Page  [A] Assignment  [Q] Quiz  [D] Discussion
[F] File  [T] External Tool  [U] External URL  --- Text Header
+ Published  - Unpublished
```

### Step 3 — Search / Filter

```bash
${ASUCB_PLUGIN_ROOT:-${CODEX_PLUGIN_ROOT:-${CLAUDE_PLUGIN_ROOT}}}/bin/python3 scripts/course_navigator.py --course-id {COURSE_ID} --find "module 3 quiz"
${ASUCB_PLUGIN_ROOT:-${CODEX_PLUGIN_ROOT:-${CLAUDE_PLUGIN_ROOT}}}/bin/python3 scripts/course_navigator.py --course-id {COURSE_ID} --find "m2-overview"
```

### Step 4 — Quick Actions

After displaying the tree, offer:

- **Read a page**: "show me m1-overview" → fetch and display content
- **Edit a page**: "edit m1-overview" → stage for editing
- **Preview a page**: "preview m1-overview" → screenshot from Canvas
- **View a quiz**: "show me the module 3 quiz" → display questions and settings (via quiz-generator View mode)
- **View an assignment**: "show me the module 2 artifact" → display instructions, rubric, settings
- **View a discussion**: "show me the module 1 discussion" → display prompt and settings

### Reading Content

Use the tree to resolve user requests to the correct Canvas object:

**Pages** — Fetch via `canvas_api.get_page(config, slug)` and display a readable summary.

**Quizzes** — Fetch questions and display:
```
Quiz: Knowledge Check 3 (15 pts, 5 questions)
  Settings: 2 attempts, no time limit, shuffle answers
  Q1 (MC, 3 pts): "Which membrane protein..."
  Q2 (TF, 3 pts): "Active transport requires ATP."
```

**Assignments** — Fetch and display:
```
Assignment: Create an Artifact 3 (30 pts)
  Type: Online (file upload + text entry)
  Due: Mar 21, 2027
  Rubric: 4 criteria, 30 pts total
```

**Discussions** — Fetch and display:
```
Discussion: Module 3 Discussion (25 pts)
  Post-first: Yes
  Prompt: "Consider the role of..."
  Rubric: 3 criteria, 25 pts total
```

### Gradebook Summary

When the user asks "show me the gradebook setup" or "verify grading":

Fetch all assignment groups with assignments and display:
```
Gradebook Setup:
  Knowledge Checks (15%): 8 quizzes × 15 pts = 120 pts
  Create an Artifact (30%): 8 assignments × 30 pts = 240 pts
  Discussions (25%): 8 discussions × 25 pts = 200 pts
  ─────────────────────────────────────
  Total: 560 pts | Weights: 100% ✓
```

### Link Validation

When the user asks "check links" or "validate links":

1. Fetch all pages
2. Extract all `<a href="">` URLs from page HTML
3. Test each URL with a HEAD request (timeout 5s)
4. Report broken/slow/OK

## Content Cache Mode

Use this mode when the user asks to cache the course, search course content offline, refresh a local content dump, or find all references to a topic without re-fetching Canvas every time.

### Commands

```bash
${ASUCB_PLUGIN_ROOT:-${CODEX_PLUGIN_ROOT:-${CLAUDE_PLUGIN_ROOT}}}/bin/python3 scripts/course_content_cache.py dump --course-id {COURSE_ID}
${ASUCB_PLUGIN_ROOT:-${CODEX_PLUGIN_ROOT:-${CLAUDE_PLUGIN_ROOT}}}/bin/python3 scripts/course_content_cache.py dump --course-id {COURSE_ID} --include-files
${ASUCB_PLUGIN_ROOT:-${CODEX_PLUGIN_ROOT:-${CLAUDE_PLUGIN_ROOT}}}/bin/python3 scripts/course_content_cache.py refresh --course-id {COURSE_ID}
${ASUCB_PLUGIN_ROOT:-${CODEX_PLUGIN_ROOT:-${CLAUDE_PLUGIN_ROOT}}}/bin/python3 scripts/course_content_cache.py status --course-id {COURSE_ID}
```

The cache stores page HTML/text and optional extracted file text under `courses/{COURSE_ID}/content_cache/`. Use `rg` over those files for questions such as late-work policy, topic references, objective consistency, or course summaries. `dump` fetches all pages; `refresh` only fetches pages updated since the last dump timestamp. File extraction uses optional PDF/DOCX/PPTX dependencies when installed.

## Template Snapshot Mode

Use this mode when the user asks to save, list, inspect, or delete reusable course-structure templates.

### Commands

```bash
${ASUCB_PLUGIN_ROOT:-${CODEX_PLUGIN_ROOT:-${CLAUDE_PLUGIN_ROOT}}}/bin/python3 scripts/template_manager.py --save --name "BIO 101" --description "8-week intro biology" --course-id {COURSE_ID}
${ASUCB_PLUGIN_ROOT:-${CODEX_PLUGIN_ROOT:-${CLAUDE_PLUGIN_ROOT}}}/bin/python3 scripts/template_manager.py --list
${ASUCB_PLUGIN_ROOT:-${CODEX_PLUGIN_ROOT:-${CLAUDE_PLUGIN_ROOT}}}/bin/python3 scripts/template_manager.py --get --template-id {TEMPLATE_ID}
${ASUCB_PLUGIN_ROOT:-${CODEX_PLUGIN_ROOT:-${CLAUDE_PLUGIN_ROOT}}}/bin/python3 scripts/template_manager.py --delete --template-id {TEMPLATE_ID}
```

Templates are reference snapshots stored at `templates/saved/tmpl-{uuid}.json`. They capture module names/positions, item titles/types/indent levels, publication status, and source course name. They do not currently capture point values, rubrics, or page HTML, and loading a template into a new course is not implemented.

## Cache

- Course tree cached for 5 minutes at `courses/{COURSE_ID}/staging/.course-tree.json`
- After any skill that modifies course structure, suggest refreshing
- Force refresh: `${ASUCB_PLUGIN_ROOT:-${CODEX_PLUGIN_ROOT:-${CLAUDE_PLUGIN_ROOT}}}/bin/python3 scripts/course_navigator.py --course-id {COURSE_ID} --refresh --tree`

## Persistent Context

After the tree is displayed, remember it for the rest of the conversation. Use the cached tree to resolve page slugs without re-fetching.
