Skip to main content

pytorial

A Python library for interactive command-line tutorials.

Install

pipx install pytorial
# or
uv tool install pytorial

To run from a clone instead of an installed copy, see CONTRIBUTING.md.

Usage

The package ships with three built-in tutorials. The first one is a self-guided tour of the tool itself:

tutorial run using-tutorials

The command is installed both as pytorial and as the alias tutorial. The examples use tutorial because the same spelling also works when the CLI is embedded as a tutorial subcommand inside a host application.

Companion tours: tutorial run shell-basics (shell and editor skills) and tutorial run writing-tutorials (authoring tutorials of your own).

Discover what's available

tutorial list

Pipe the same command into a script to get tab-separated rows instead of the rich table.

Run or resume

tutorial run <id>              # start or resume saved progress
tutorial run --restart <id>    # discard saved progress and start over

Review past runs

tutorial review <id>
tutorial review <id> --step 2
tutorial review <id> --run-id <run-id>

Trust author-supplied shell code

tutorial run --allow-shell <id>

A tutorial step may declare pre_command, check_command, or post_command. Those fields run author-supplied shell code, so they are opt-in: pass --allow-shell only when you trust the tutorial author. A workspace: cwd tutorial combined with --allow-shell runs that shell code in your real project directory rather than in a per-run workspace, so pass both only for tutorials you wrote or trust completely.

Writing tutorials

Take the interactive walkthrough first:

tutorial run writing-tutorials

File format

A tutorial is a single Markdown file beginning with YAML front matter:

---
id: my-tutorial
title: My Tutorial
summary: One-line description shown by `tutorial list`.
---

# First step

```tutorial-step
required_patterns:
  - some-command
hint: Try running `some-command`.
```

Step body in Markdown.
  • Required front-matter fields: id, title, summary.
  • Optional front-matter field: workspace, either fresh (default) or cwd. See "Run in your project directory" below.
  • Each top-level # Heading becomes one step.
  • A step may begin with a fenced tutorial-step YAML block. Recognised fields are required_patterns, pre_command, check_command, post_command, hint, edit_file, kind, options, and answers.
  • Without kind or edit_file, a step opens an interactive shell.
  • edit_file opens a workspace-relative file in $EDITOR, falling back to vim, vi, or nano when $EDITOR is unset.
  • kind: input, kind: single_select, and kind: multi_select prompt directly in the CLI instead of opening a shell or editor. input answers use the same string-or-{mode, pattern} format as required_patterns; select questions use literal option text in options and answers.
  • A shell step has the size of the reader's terminal, so program output wraps differently for different readers. Plain-string patterns ignore that, because they collapse whitespace, line breaks included. A regex pattern that spans several words should join them with \s+ rather than a literal space.
  • pre_command, check_command, and post_command only run when the reader passes --allow-shell.
  • Use one YAML string for each shell field. Multi-line shell scripts should use YAML | so one bash process sees the whole script and keeps cd, export, and shell options across lines.
  • Do not use YAML > for shell fields: it folds newlines into spaces and can break shell syntax.

Run in your project directory

A tutorial that scaffolds a workflow in a real project, such as cutting a release or bootstrapping a repository, can ask to run where the reader launched it instead of in a fresh per-run workspace:

---
id: release-checklist
title: Release Checklist
summary: Walk through a release in this project.
workspace: cwd
---
  • The CLI prints one line naming the directory before the first step.
  • Progress is tracked per directory: run, --restart, and list act on the run recorded in the current directory, so the same tutorial in two projects keeps two independent runs. Re-enter the same directory to resume. review still shows the latest run overall; use --run-id to pick another.
  • --restart does not clear the directory, so files left by an earlier run are still there. Prefer non-destructive post_command cleanup in these tutorials.
  • tutorial develop runs a step of such a tutorial in your current directory too, and prints the same line first. Nothing is reset between iterations, so develop an in-place tutorial inside a scratch copy of a project. (The step source you edit along the way stays in a temporary directory, never in your project.)

Share and install

Install a tutorial Markdown file or URL into the user's tutorial directory:

tutorial install path/to/tutorial.md
tutorial install https://example.com/tutorial.md
tutorial install --force path/to/tutorial.md

Use --force to overwrite an installed tutorial with the same id. The standalone CLI auto-loads installed tutorials alongside the built-ins.

Load ad hoc

To use a tutorial without installing it, point at the file or directory on the command line:

tutorial list --tutorial-path some/dir
tutorial run --tutorial-path some/dir <id>

--tutorial-path may be repeated and is appended after the built-ins.

Embedding the CLI

The package can be mounted as a subcommand inside another Typer or argparse application via add_typer_subcommand and add_argparse_subcommand in src/pytorial/cli.py. Embedded hosts prepend the using-tutorials lesson before host-specific tutorials, do not load the user's installed tutorial directory, and hide the standalone-only install command. using-tutorials is self-contained for that reason: it refers to no other tutorial and to no verb a host hides, so a learner can finish it whatever else the host mounts.

Messages that tell the learner what to type next name the command as the host mounted it (myhost tutorial review <id>), taken from the host's own parser, so the host passes nothing extra.

Platform support

Shell steps run in a PTY-backed bash session, and pre_command, check_command and post_command run through bash, so they need a POSIX system. On native Windows, use WSL.

Hosts do not need any platform logic: the tutorial subcommand is registered everywhere. Where no POSIX terminal is available,

  • tutorial --help and tutorial run --help say that shell steps need WSL;
  • tutorial run refuses a tutorial that has shell steps, or shell hooks that would execute, before it creates a run or workspace, and exits with status 1;
  • tutorial list shows needs WSL in place of the progress status for each tutorial that run would refuse;
  • tutorial list, tutorial review, and tutorials made only of question and editor steps keep working.

A host that wants to word its own note can ask pytorial.posix_terminal_available().

Contributing

For the literate sources, the make build, and the repo layout, see CONTRIBUTING.md.

Metadata

Release files for pytorial 0.10.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 pytorial 0.10.0
File Size Uploaded
pytorial-0.10.0.tar.gz 14.8 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for pytorial 0.10.0
File Interpreter ABI Platform
pytorial-0.10.0-py3-none-any.whl Python 3 none any Details

Total release size: 60.1 kB

Release files / pytorial-0.10.0.tar.gz

Download URL pytorial-0.10.0.tar.gz
Size 14.8 kB
Tags Source
SHA-256 checksum
How to use checksums
a59593de439a4c958ff1d20166769c8b7f6c62d4f1c5102441be250c5e3964d6
BLAKE2b-256 checksum
How to use checksums
fa2056a5f6cf67b3af842cbb7e87cd434a80b29a6b46b7259837d1eaad24abe3
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via poetry/2.4.3 CPython/3.14.4 Linux/7.0.0-31-generic

Release files / pytorial-0.10.0-py3-none-any.whl

Download URL pytorial-0.10.0-py3-none-any.whl
Size 45.3 kB
Tags Python 3
SHA-256 checksum
How to use checksums
830672b6bd2236677ec64a0a647ad786f7832606e9fd627ff1cd60103ccdab4c
BLAKE2b-256 checksum
How to use checksums
92069bda59266c5474efece9e61cdf12e51b4a48c69e55529a685a1e328db9fe
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via poetry/2.4.3 CPython/3.14.4 Linux/7.0.0-31-generic

Release history Release notifications | RSS feed

0.10.1

2 release files

This release

0.10.0 This release

2 release files

0.9.0

2 release files

0.8.1

2 release files

0.8

2 release files

0.7

2 release files

0.6

2 release files

0.5

2 release files

0.4

2 release files

0.3

2 release files

0.2

2 release files

0.1

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