Skip to main content

Consumer CLI for the learnctl catalog — install and study hands-on courses.

Project description

learnctl

A rich Textual TUI host for the learning-coach skill. learnctl reads a Package the skill generates, calls coach.py for all deterministic state, runs declarative lab checks on the host, and walks the learner through the protocol turn-by-turn with a live terminal UI.

Built on the principle the skill enforces: the LLM is a build-time author, not a run-time dependency. v1 runs the entire free path with no model wired up — discover, resume, active-recall warm-up, prerequisite check, primer reading, hands-on task, declarative verifier, hint ladder, solution, scoring, advance. The two metered LLM turns (interview and the opt-in diagnose) are defined slots that v2 will fill via a pluggable provider.

Install

pip install -e .
export LEARNCTL_COACH=/path/to/learning-coach/scripts/coach.py

Commands

learnctl discover              # list topics under ./learning + progress
learnctl status <topic>        # one-shot dashboard (no TUI)
learnctl study   <topic>       # launch the TUI session

A <topic> is a slug (docker), a folder path (learning/docker), or a state.json path. --root <path> overrides the workspace root for slug lookup.

Keyboard shortcuts (TUI)

The control bar is docked to the bottom of the screen so it can never scroll out of view, and every action has a keyboard shortcut as a fallback:

Key Action Available when
r Reveal answer / Run check recall reveal, task step, verify retry
h Show next hint verify failed and rungs remain
s Show solution verify failed
g / f / m Got it / Fuzzy / Missed (self-rate recall) after recall reveal
c Continue / Dismiss most other turns
1 / 2 / 3 Score 60 / 75 / 90 (manual interview) after the interview
q Quit always

Architecture

Five layers, bottom-up:

Layer File Responsibility
engine engine.py Typed subprocess wrapper around coach.py. The only layer that touches state. Parses the ---JSON--- block from each command into typed results. Subprocess (not import) on purpose — validates the host contract any language could implement.
package package.py Read-only loader for path.json + scenario.json + Markdown. Pure file I/O, no logic.
verifier verifier.py Executes the declarative verify.checks on the host: command and script checks run via subprocess with timeouts; file checks read the filesystem. Evaluates expect (contains/regex/equals/exit_code/json with path matching, including json-lines). Honors per-check os restrictions. v1 runs directly on the host; container isolation is a future opt-in.
session session.py The protocol state machine. Walks WARMUP → PREREQS → PRIMER → TASK → VERIFY → INTERVIEW → SCORE → DONE, emitting Turn objects with type, say, data, expects. The active-recall trio (recall_prompt → recall_reveal → recall_grade) is enforced here — the answer is withheld from the prompt envelope by construction, so no host can leak it early. Host-agnostic and unit-testable without a terminal.
tui tui.py Textual app. Renders say as Markdown in a scrolling transcript, shows the right control buttons for each expects, streams hint rungs into a log, and resumes the session with the chosen response.

Plus __main__.py for the CLI entry point. The session has a stub for a future provider layer (interview / diagnose) — has_llm=False in v1 keeps those turns manual.

Tests

LEARNCTL_COACH=/path/to/coach.py python3 tests/test_foundation.py
LEARNCTL_COACH=/path/to/coach.py python3 tests/test_session.py
LEARNCTL_COACH=/path/to/coach.py python3 tests/test_tui.py
  • test_foundation.py — 8 unit tests for the engine, package, and verifier layers including the expect matchers and the Docker-style json-lines path.
  • test_session.py — drives the full free-path session end-to-end and asserts the turn sequence.
  • test_tui.py — runs the Textual app headlessly via app.run_test(), clicking every button along the path and asserting the final mastery score.

All three currently pass against the real coach.py from the skill.

What's intentionally not in v1

  • LLM provider. The interview turn collects a score manually (score buttons in the TUI); the diagnose button falls back to revealing the solution. v2 will add an interface for interview() / diagnose() / ask() with a null implementation for the offline case and concrete providers (Anthropic, etc.) for hosts that wire one up.
  • Container sandbox. The verifier executes on the host with per-check timeouts; v2 can opt-in to a Docker-based sandbox. The skill's authoring safety contract (scoped, non-destructive, transparent, reversible) is the current safety boundary.
  • Generation commands. learnctl consumes packages; generating them is the skill's job. The CLI doesn't wrap init/add-scenario/add-item because those are author-side commands a chat agent or another tool runs.

Cost model

Zero LLM calls per session in v1 — the entire free path is deterministic and free. v2's metered turns (interview, optional diagnose) match the skill's design: ~1 model call per stage plus opt-in diagnoses when novel-stuck.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

learnctl-0.30.0.tar.gz (337.2 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

learnctl-0.30.0-py3-none-any.whl (186.5 kB view details)

Uploaded Python 3

File details

Details for the file learnctl-0.30.0.tar.gz.

File metadata

  • Download URL: learnctl-0.30.0.tar.gz
  • Upload date:
  • Size: 337.2 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.13.1

File hashes

Hashes for learnctl-0.30.0.tar.gz
Algorithm Hash digest
SHA256 625bb4f76d9622bd626b002b7a013a42e94121202a0f1df19e7fa9cd1dc9dbed
MD5 41d15f0d87f25ccb9601f8f17d103659
BLAKE2b-256 c9a7d2a92bd16e6176d9ab31754ffd850dcc6f0e3571d512b0c2eb9fded07472

See more details on using hashes here.

File details

Details for the file learnctl-0.30.0-py3-none-any.whl.

File metadata

  • Download URL: learnctl-0.30.0-py3-none-any.whl
  • Upload date:
  • Size: 186.5 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.13.1

File hashes

Hashes for learnctl-0.30.0-py3-none-any.whl
Algorithm Hash digest
SHA256 f346ec136d8ce282ead5add565dbb358bdffec0f8485b45cb2cc5769bb173a2a
MD5 06357a5b8afb8e1997e3d3c6abf6d8ca
BLAKE2b-256 ebec2ed201c81141b9b7f5b1cc2a6d4092893cc3e1c7d07c33d675d29e435d2f

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page