GemmaSchool is an AI-augmented, self-sovereign homeschooling ecosystem. It transforms static curriculum into an interactive "Quest" system, running entirely on local hardware via Gemma 4 and llama.cpp β no accounts, no tokens, no cloud.
GemmaSchool returns educational power to the family. By leveraging the Gemma multimodal family, we automate the heavy lifting of homeschooling β planning, grading, and enrichment β while keeping 100% of student data private in a local Markdown vault. No cloud, no subscriptions, no tracking.
GemmaSchool is engineered for excellence in two primary Gemma 4 Good tracks:
- Future of Education: Transforming multi-step curriculum PDFs into adaptive, personalized "Daily Quests."
- Technical Excellence: Demonstrating frontier multimodal performance (Vision + Text) on home hardware using llama.cpp.
We replaced boring spreadsheets with a gamified mission hub.
- Cinematic Discovery: Every new topic triggers a "World Event." The Scout Agent uses FastSD CPU to generate widescreen hero images, making a History lesson feel like a movie premiere.
- The Emerald Glow: Real-time visual feedback. When a student completes a task, the parent's dashboard glows emerald via instant WebSocket synchronization.
Parses curriculum PDFs into structured 180-day lesson plans stored as Markdown.
Technical wins:
- Idempotency check against
vault/Daily_Quests/before generating β never wastes a model call on content that already exists - Outputs structured YAML frontmatter (subject, grade, standards alignment) so every quest is machine-readable from day one
- Writes exclusively to
vault/architect/β isolated from all other agents
Value: Turns a 300-page curriculum PDF into a full school year of gamified daily missions in one run, with zero duplicate generation across restarts.
Analyzes quest topics and generates high-fidelity visual prompts for FastSD CPU hero images.
Technical wins:
- Intent-first routing: topic analysis runs before image generation, so the visual prompt is semantically grounded in the lesson content
- Writes assets to
vault/scout/β the Auditor and Architect cannot overwrite Scout outputs - Generates 16:9 widescreen prompts optimized for FastSD CPU's OpenVINO pipeline, maximizing quality on CPU-only hardware
Value: Every new lesson automatically gets a cinematic hero image β no parent effort required. History feels like a movie; Science feels like a discovery.
Uses Gemma's native Vision capabilities to grade photos of physical worksheets and identify knowledge gaps.
Technical wins:
- Multimodal pipeline: accepts a raw photo path, runs Gemma Vision inference locally β no external OCR service needed
- Writes grading logs exclusively to
vault/auditor/β a permanent, isolated audit trail per student - Automatically patches quest frontmatter (
status: completed,knowledge_gaps: [...]) after grading β the Quest Board updates without parent involvement
Value: A parent photographs a worksheet with their phone. The Auditor grades it, identifies gaps, and updates the student's Quest Board β all in seconds, entirely offline.
Orchestrates the FastAPI bridge, WebSocket activity feed, and Semester Sweeps.
Technical wins:
- Single
inference_locksemaphore serializes all LLM calls β prevents context corruption under concurrent requests - WebSocket hub broadcasts
system.*events (model switch, restart, online) to all connected clients in real time - Semester Sweep background tasks use FastAPI's
BackgroundTasksβ long-running operations never block the HTTP response cycle
Value: The UI stays live and responsive during heavy inference. Parents see model-switch progress, agent status, and quest completions in real time without refreshing.
Manages the school-year calendar, holiday imports, and per-student scheduling via natural language.
Technical wins:
- Intent-first hybrid routing: Calendar CRUD is detected from the user prompt before any LLM call. Deterministic Python tools execute directly β zero model latency for common operations like "list events" or "import US holidays."
- Parallel read context:
asyncio.gather()fetchesvisible_events()andholidays_in_school_year()simultaneously before the model starts reasoning β pre-loading the full calendar state in a single async tick. - Tool classification: Read-only tools (
list_events_tool,list_us_holidays_tool) are marked in_READ_ONLY_TOOLSand safe for concurrent execution. Write tools (create,update,delete) always run serially to prevent file corruption. - 3-tier fallback chain: PydanticAI agent β raw
_chat_with_llama()β deterministic_fallback(). Every failure path has a recovery route; the agent never returns an unhandled exception to the user. - Isolated vault path: All calendar data lives in
vault/chronos/β no other agent can read or write it. Legacycalendar_events.jsonis auto-migrated on first boot. - SSE streaming:
stream_chronos()yieldsthinking/delta/finalevents over a live HTTP stream β the UI shows Chronos reasoning token-by-token, not as a single delayed blob.
Value: A parent types "add a week off for Thanksgiving." Chronos detects the intent, skips the LLM, creates the event, and responds in natural language β all in under 200ms on local hardware.
Your child's progress lives as plain Markdown in the vault/ directory. GemmaSchool's built-in Knowledge Grove renders a live force-directed graph of every quest and the connections between them β no external tools required.
- Nodes coloured by subject, ringed by completion status
- Amber nodes surface Knowledge Gaps detected by the Auditor
- Cross-subject clusters reveal how History, Science, and Art connect in real time
Optional: The
vault/folder is fully compatible with Obsidian. Open it there for its native graph view and note editor β everything is standard Markdown.
GemmaSchool is built in four layers. Each layer has a clear responsibility and communicates only through the interfaces defined below it.
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β Layer 4 β Frontend β
β React 18 (Vite) Β· Tailwind CSS Β· react-force-graph-2d β
β SSE streaming Β· WebSocket activity feed Β· Role-based UI β
βββββββββββββββββββββββββ¬ββββββββββββββββββββββββββββββββββ
β HTTP / WebSocket / SSE
βββββββββββββββββββββββββΌββββββββββββββββββββββββββββββββββ
β Layer 3 β Backend β
β FastAPI Β· WebSocket hub Β· BackgroundTasks β
β Routers: quests Β· calendar Β· agents Β· setup Β· vault β
β inference_lock semaphore Β· 3-tier Chronos fallback β
βββββββββββββββββββββββββ¬ββββββββββββββββββββββββββββββββββ
β OpenAI-compatible JSON (HTTP)
βββββββββββββββββββββββββΌββββββββββββββββββββββββββββββββββ
β Layer 2 β Inference Engine β
β llama.cpp server Β· ghcr.io/ggml-org/llama.cpp β
β Gemma 4 E2B / E4B / 26B GGUF Β· Vision + Text Β· SSE β
βββββββββββββββββββββββββ¬ββββββββββββββββββββββββββββββββββ
β Local filesystem (plain Markdown)
βββββββββββββββββββββββββΌββββββββββββββββββββββββββββββββββ
β Layer 1 β Storage (Vault) β
β vault/ β
β βββ chronos/ β Chronos events β
β βββ auditor/ β Grading logs β
β βββ scout/ β Images & research β
β βββ architect/ β Curriculum plans β
β βββ Daily_Quests/ β Generated quests β
β βββ Assets/ β FastSD hero images β
β βββ system_settings.json β
β βββ profiles.json β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
Chronos uses an intent-first hybrid strategy that keeps the fast path deterministic:
User Prompt
β
βΌ
_is_tool_intent()? ββYESβββΆ Deterministic Python tools βββΆ _naturalize_tool_result() βββΆ SSE stream
β (zero LLM latency)
NO
β
βΌ
STABLE_TOOLING=1? ββYESβββΆ PydanticAI agent.run() βββΆ ChronosResult
β (parallel read context pre-loaded)
NO
β
βΌ
_chat_with_llama() βββΆ raw completion βββΆ _fallback() if needed
| Property | Implementation |
|---|---|
| Streaming native | stream_chronos() yields SSE events (thinking / delta / final) token-by-token |
| Parallel reads | asyncio.gather() fetches events + holidays before model reasoning begins |
| Serial writes | create / update / delete tools always execute one at a time through the fallback path |
| Agent vault isolation | Each agent owns a subdirectory β cross-agent writes are structurally impossible |
| Every error has a path | PydanticAI β llm_chat β deterministic fallback β no unhandled exceptions reach the user |
| Inference serialized | Single asyncio.Semaphore(1) prevents concurrent model calls from corrupting context |
| Layer | Technology |
|---|---|
| Inference | llama.cpp server (ghcr.io/ggml-org/llama.cpp:server) |
| Vision | Gemma Vision via llama.cpp |
| Imaging | FastSD CPU (OpenVINO) β local 16:9 hero images |
| Backend | FastAPI + WebSockets + SSE |
| Frontend | React 18 (Vite) + Tailwind CSS (Stitch UI) |
| Graph | react-force-graph-2d β built-in Knowledge Grove |
| Storage | Local filesystem (vault/ β plain Markdown, Obsidian-compatible) |
| Containers | Docker + Docker Compose |
- Docker & Docker Compose (macOS: OrbStack recommended β lightweight alternative to Docker Desktop)
- Hardware: 8 GB+ RAM (optimised for CPU-only inference)
- No accounts or API tokens required
- Double-click
Start GemmaSchool.commandin the project folder. - It installs Homebrew, OrbStack (lightweight Docker), builds the stack, and opens the browser automatically.
git clone git@github.com:nsuderman/GemmaSchool.git
cd GemmaSchool
docker compose up --buildOpen http://localhost:5173 β the setup wizard guides you through:
- Selecting a Gemma model size for your hardware
- Downloading a public GGUF model (progress bar included)
- Writing your
.envautomatically
docker compose --profile full upCopyright 2026 Nate Suderman
This project is licensed under the Apache License, Version 2.0. See the LICENSE file for the full text.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
This project integrates the following third-party components. Each retains its own license:
| Component | License | Notes |
|---|---|---|
| llama.cpp | MIT | LLM serving engine |
| FastSD CPU | Apache 2.0 | Local image generation |
| FastAPI | MIT | Backend framework |
| React | MIT | Frontend framework |
| react-force-graph | MIT | Knowledge Grove graph |
| Tailwind CSS | MIT | Styling |
Gemma models are NOT covered by this Apache 2.0 license.
The Gemma models downloaded by the setup wizard are subject to Google's Gemma Terms of Use. By using GemmaSchool you agree to use the models only as permitted under those terms and not to redistribute model weights.
Contributions are welcome under the Apache 2.0 license. By submitting a pull request you agree that your contributions will be licensed under the same terms.
- Fork the repo
- Create a feature branch (
git checkout -b feature/my-feature) - Commit your changes
- Open a pull request against
main
GemmaSchool is an independent open-source project and is not affiliated with, endorsed by, or sponsored by Google. "Gemma" is a trademark of Google LLC.
