Arborito Python SDK
Build Pygame games, bots, kiosks, validators, and offline trainers from any .arborito course. Same capabilities as browser Arcade cartridges (window.arborito).
arborito-games is only the HTML Arcade catalog (like Flathub). This repo is for Python and native apps.
Version: 0.2.6
Naming: camelCase vs snake_case
The browser injects window.arborito with camelCase methods (fromLesson, buildCard, tasksFromLesson). The Python SDK keeps those same names on the Arcade surface so a cartridge and a Pygame game share one vocabulary.
Python-only helpers use snake_case (grade_answer, matches_any, branch_profile, from_course). CamelCase aliases exist where useful (gradeAnswer, matchesAny, branchProfile, fromCourse, lessonAction, plainText / plain_text).
Install
pip install arborito-sdk
# Rich terminal lesson editor (F2 Quiz, forms, block list):
pip install 'arborito-sdk[tui]'
# Nostr account + publish:
pip install 'arborito-sdk[nostr]'
Package name: arborito-sdk · CLI command: arborito-cli · Python import: arborito_sdk
Mental model
list → go → read | edit | quiz | ask
Library: branch (full courses) and tree (composed playlists).
Python games: use static quiz helpers without an AI server; use dynamic mode for ask.speak / reply / scene gates. Advanced is only when you write the prompt yourself.
CLI commands
Run arborito-cli.
Interactive: arborito-cli course.arborito (REPL with breadcrumb prompt).
| Area | Commands |
|---|---|
| Interactive | shell or arborito-cli course.arborito (REPL); help; exit / quit |
| Navigate | list, go N, go back, go where, go "name" (back / where shortcuts) |
| Lesson | read (enriched), edit (TUI / F2 Quiz), edit --raw, games, info |
| Study | quiz, ask |
| Search | search QUERY, search --courses QUERY |
| Branches | branch list, branch add CODE, branch open "Name", branch import, branch new, branch publish, branch export, branch remove (alias: forest / bosque) |
| Trees | tree list, tree open "Name", tree import, tree export, tree remove |
| Copy | cp branch "Name" / cp tree "Name" |
| Favorites | fav list, fav add, fav remove |
| Account | session register, session login, session logout, session whoami |
| Memory | memory due, memory report (Care pull/push runs automatically when logged in) |
| Config | config relay list|set|reset, config ai list|set … |
| Scripts | script / run / batch |
Network: only share codes XXXX-XXXX or local .arborito files, no manual nostr:// URLs. Sync and refresh run automatically when loading from the network. Full keys: CLI.md.
Quick start
pip install 'arborito-sdk[tui]'
arborito-cli course.arborito
branch import course.arborito
branch open "My Course"
list
go 1
read # enriched blocks (not raw @quiz)
edit # F2 Quiz, Ctrl+S save
quiz --rounds 5
Lesson editor (terminal)
| Command | Behaviour |
|---|---|
read |
Structured view: Quiz · concept, question, answer |
edit |
Block list + forms (requires [tui] for full UI) |
edit --raw |
Open lesson markdown in $EDITOR |
Details: CLI.md. Full WYSIWYG editing is in Arborito Construction mode.
Lesson outline (construct TOC)
Syllabus rows use an @section fence with index (path) and title. Nest depth
is the path segment count (max 8). Indexes are rewritten on every save/move:
@section
index: 1
title: Introduction
@/section
Text of the first section.
@section
index: 1.1
title: Concepts
@/section
Detail.
@section
index: 1.2
title: Exercise
@/section
More practice.
@section
index: 1.2.1
title: Extra
@/section
Nested.
@section
index: 2
title: Practice
@/section
Second root section.
- Nesting =
indexsegment count. - Humans and the machine share one coordinate (
index:). - ←→↑↓ operate on that geometry;
apply_toc_section_movereturns{ok, body, selectedIndex}whereokis path math (not whether the markdown bytes changed). - Normal
##/###without a path are content titles once the lesson already hasindex:rows. - Titles may repeat; indexes stay unique after
prepare_construct_outline_body.
API surface (static vs dynamic mode)
Same contract as browser Arcade (window.arborito). Static needs no AI server. Dynamic mode needs local llama.cpp (ai_mode="dynamic"). Prefer the scene helpers in dynamic mode; open advanced only when you own the prompt.
All Python API commands
| Mode | Call | Role |
|---|---|---|
| Dynamic | ask.fromCourse(topic) / from_course |
Practice card from the open course (greeting, origin, purpose, goodbye) |
| Dynamic | ask.speak(who, text) |
Paraphrase an authored line (no course quizzes in the prompt) |
| Dynamic | ask.reply(who, playerSaid, facts) |
NPC answers using only facts |
| Dynamic | ask.check(playerSaid, card) |
Grade against a fromCourse card (local match, then optional AI judge; local match also works static) |
| Dynamic | ask.tutor(lesson, text, opts?) |
Study chat grounded in course questionnaires (aliases: lesson_action, lessonAction) |
| Static | lesson.at / by_id / byId / plainText |
Load lesson prose for HUD / NPC |
| Static | lesson.context_for_ai / branch_profile |
Lesson / branch text for prompts |
| Static | challenge.fromLesson → modes.buildCard |
Static challenge cards |
| Static | challenge.tasksFromLesson |
Mission list from questionnaires |
| Static | quiz / matchPairs |
Classroom Q/A and Memory pairs |
| Static | quiz.matches_any / matchesAny |
Local answer match |
| Static | quiz.grade_answer / gradeAnswer |
Grade (local; LLM only in dynamic mode) |
| Static | quiz.pick / find_code_replay |
Pick pool item / code replay |
| Static | memory.due / report / isDue / getStatus |
Care / SM-2 local |
| Both | memory.pull / push / sync |
Care sync with Arborito (needs [nostr] + login) |
| Advanced | ask.json(prompt) |
Raw JSON from your prompt |
| Advanced | ask.chat(messages) |
Raw chat turn |
| Advanced | ask.with_context(query) |
Short answer grounded in indexed course context |
| Advanced | ask.npc(...) |
Legacy narrative helper — prefer speak / reply for new scene code |
| Advanced | narrative.start / advance |
YAML scene runner (programmatic; no CLI command) |
| Advanced | ai.persona / ai.arborito |
Tutor voice strings |
lesson → challenge → your UI → memory (optional)
from arborito_sdk import Arborito
api = Arborito.from_arborito("course.arborito", lang="EN")
lesson = api.lesson.at(0)
cards = api.challenge.fromLesson(lesson)
card = api.challenge.modes.buildCard(cards[0], "cloze", lang="EN")
prose = api.lesson.plainText(lesson) # NPC / HUD (strips @section, @quiz, …)
api.memory.report(lesson["id"], quality=4)
Care sync with the Arborito app (Nostr tree + account):
api = Arborito.from_share_code("ABCD-EF23", lang="EN")
api.login("player", "their-sync-secret") # restores network identity escrow
api.memory.pull() # merge Care from relays
api.memory.report(lesson["id"], quality=4)
api.memory.push() # or api.memory.sync() = pull+push
Requires pip install 'arborito-sdk[nostr]'. CLI: session login (Care syncs automatically while logged in).
Quiz helpers (detail)
lesson = api.lesson.by_id(pool_item["lessonId"])
ctx = api.lesson.context_for_ai(lesson)
ok = api.quiz.grade_answer(lesson, {"q": "…", "correct": "…"}, player_text)
match = api.quiz.matches_any(player_text, ["answer", "synonym"])
picked = api.quiz.pick(pool, session={}) # session["used"] persists
tasks = api.challenge.tasksFromLesson(lesson, {"max": 10})
replay = api.quiz.find_code_replay("echo hi", lesson=lesson)
In static mode, grade_answer only uses local matching (no LLM). Browser cartridges use the same helpers under camelCase (gradeAnswer, matchesAny, tasksFromLesson, findCodeReplay, …), see sdk-spec.md.
Loaders
| Method | Use |
|---|---|
Arborito.from_arborito(path) |
Local export (recommended) |
Arborito.from_share_code("ABCD-EF23") |
Public share code |
Arborito.from_nostr(pub, universe_id) |
Direct Nostr reference |
Arborito.from_library(...) / from_static_data(...) |
Library / in-memory trees |
Docs
- CLI.md — full CLI reference + terminal editor keys
- CHANGELOG.md — release notes
- sdk-spec.md — API contract
- PYTHON_SDK.md
Test
cd arborito-sdk && pip install -e ".[dev,nostr]" && python -m unittest discover -s tests -q
Example
# Static quiz (no AI server)
python examples/minimal_quiz.py path/to/course.arborito EN
# Scene + course speaking gate (needs llama.cpp)
python examples/ai_scene.py path/to/course.arborito EN
# Study tutor (needs llama.cpp)
python examples/ai_tutor.py path/to/course.arborito EN
Dynamic scene in a few lines
print(api.ask.speak("Mike, strict boss", "Julius is missing. Hotel Pentfive.")["line"])
print(api.ask.reply("Mike. Wants accept.", player_said, ["Julius disappeared"])["line"])
card = api.ask.from_course("greeting")
ok = api.ask.check(player_said, card)["ok"]
Study tutor: api.ask.tutor(lesson, player_said, {"persona": "Guide"}) (alias: lesson_action).
Contributing
Chat: Matrix #arborito:matrix.org · treesys.org
License
GPL-3.0-or-later, LICENSE
Metadata
Release files for arborito-sdk 0.2.6
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | |
|---|---|---|---|---|
| arborito_sdk-0.2.6.tar.gz | 172.7 kB | With provenance | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| arborito_sdk-0.2.6-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 343.8 kB
Release files / arborito_sdk-0.2.6.tar.gz
| Download URL | arborito_sdk-0.2.6.tar.gz |
|---|---|
| Size | 172.7 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
6fcc5776d2b97846e8ebf7285e3ced824238d20b47dff8b29a8475e10a7ee744
|
|
BLAKE2b-256 checksum How to use checksums |
edd6a1a4d4ec7b397500d793bd6c67324aeee915d406fbe74b044f9bd31c4657
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
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 31, 2026.
Transparency logRelease files / arborito_sdk-0.2.6-py3-none-any.whl
| Download URL | arborito_sdk-0.2.6-py3-none-any.whl |
|---|---|
| Size | 171.2 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
f201c7c3ea9aef39595a9c077e73d152a47a89124f4c5415ce361c426d03c3c1
|
|
BLAKE2b-256 checksum How to use checksums |
a53a816140b82a9e5505431e8907da1b5ca773faa15a5908359e9df627f1eb8b
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
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 31, 2026.
Transparency logSecurity for arborito-sdk 0.2.6
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.
Full provenance
All 2 files in this release have been uploaded with provenance metadata.
Attestation for arborito_sdk-0.2.6.tar.gz
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 31, 2026.
Transparency logA note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.