Content Generation CLI

Generate courses, slides, tests, modules, videos, games, and simulations, grade answers, and manage learners and webhooks from the CLI.

Use this page to look up every CLI command that generates, reads, or deletes content, follows runs, and grades answers.

These commands call the Content API at /v1/content/classrooms/{classroomId}/... and need a tf_content_ key. Each one acts in the classroom chosen as described in Choose the Classroom; pass the global --classroom <id> to pick one. webhook and credits act on the organization, not a classroom.

The commands on this page describe @tutorflow/cli 0.5.0. Run tutorflow <command> --help for the flags of your installed version.

Commands Every Resource Shares

course, slide, test, module, video, game, and simulation each have these subcommands:

SubcommandWhat it does
listLists the classroom's resources. -l, --limit <n> (default 20, max 100), -p, --page <n> (default 1), -s, --search <text>.
get <id>Prints one resource.
open <id>Prints id, editorUrl, and publicUrl. On a terminal, outside JSON mode, it also opens the public page, or the editor when there is none or you pass --editor.
delete <id>Deletes the resource and prints { "id": "...", "deleted": true }. Asks for confirmation, or takes -y, --yes, which is required without a terminal or in JSON mode.
share <id>Makes the resource open by link and prints id, its visibility, publicUrl, and editorUrl. JSON mode prints the whole update answer. --listed on video and test only.
visibility <id> <value>Sets the visibility to <value>, in any case. Prints the same as share.

share and visibility send PATCH with visibility, or isPublic for a module:

Resourceshare setsvisibility values
video, testUNLISTED: opens by link, not listed or searchable. --listed sets PUBLIC.PUBLIC, UNLISTED, PRIVATE
slide, game, simulationPUBLICPUBLIC, PRIVATE
coursePUBLICPUBLIC, PRIVATE, ORGANIZATION, CLASSROOM, COURSE
moduleisPublic: truePUBLIC, PRIVATE, sent as isPublic

publicUrl stays null until a video is rendered, a game or simulation is built, or a course is published, and always in the sandbox classroom of a test key. In text mode share says which applies. A value the resource does not take exits 2 with EINVAL before any request.

bash
tutorflow course list --search python --limit 50
tutorflow --json slide get 00000000-0000-4000-8000-000000000301
tutorflow test delete 00000000-0000-4000-8000-000000000401 --yes
tutorflow --json video share 00000000-0000-4000-8000-000000000601 | jq -r .publicUrl

In text mode, list prints a table of ID, title, status, and the updated date. In JSON mode it prints the API page as returned.

Generate Courses, Slides, Tests, and Modules

course, slide, test, and module have generate [prompt], with the alias create. The prompt is the first argument. On a terminal the CLI asks for it when you leave it out; otherwise the command fails with ENOINTERACTIVE.

Flags all four share:

FlagMeaning
-l, --language <lang>Language code of the content. Default en.
-w, --waitWait for the run to finish and print the result.
--timeout <seconds>Stop waiting after this many seconds. Default 900.
--idempotency-key <key>Sent as Idempotency-Key, so a retried call does not start a second run.

tutorflow course generate

Generates a course with every lesson. The CLI's help lists the price as 3 credits for the outline plus 3 per lesson.

bash
tutorflow course generate "Beginner Python for analysts" --lessons 5 --level beginner --wait
FlagRequest field
[prompt]prompt
-n, --lessons <n>lessonCount
--level <level>level
--title <title>title (generated when omitted)
--description <text>description

tutorflow slide generate

Generates a slide deck with every page, charged per page.

bash
tutorflow slide generate "Photosynthesis" --count 8 --text-length concise --wait
FlagRequest field
[prompt]topic
-n, --count <n>slideCount
-t, --theme <themeId>themeId
--instructions <text>instructions
--text-length <length>textLength: concise or detailed

tutorflow test generate

Generates a test with auto-graded items (3 credits).

bash
tutorflow test generate "Algebra basics" --items 3 --item-types select,blank,open-ended --wait
FlagRequest field
[prompt]topic
-n, --items <n>itemCount
--item-types <list>itemTypes: comma-separated, one per question, from select, blank, open-ended, true-false, submission. The API expects as many types as items.
--level <level>level
--instructions <text>instructions
--total-score <n>totalScore

tutorflow test results <testId> lists learners' results, with -l, --limit <n> (default 20) and --cursor <cursor> (the meta.nextCursor of the previous page).

tutorflow module generate

Generates an interactive lesson module (3 credits).

bash
tutorflow module generate "Fractions for 5th grade" --type flashcard --wait
FlagRequest field
[prompt]topic
--type <type>type, for example markdown, ai-tutor, flashcard, or coding-lesson. Chosen from the topic when omitted.
--reference <text>referenceText: material the module should be based on

What generate prints

Without --wait, generate prints the run the API accepted and returns at once:

JSON
{
  "runId": "00000000-0000-4000-8000-000000000b01",
  "status": "queued",
  "kind": "course",
  "estimatedCredits": 21,
  "statusUrl": "/v1/content/classrooms/00000000-0000-4000-8000-000000000010/runs/00000000-0000-4000-8000-000000000b01"
}

With --wait, the CLI polls the run every 3 seconds (set TUTORFLOW_POLL_INTERVAL_MS to change it) and prints progress to stderr in text mode. It rides out up to five transient failures in a row (network errors, 429, 5xx). When the run completes, JSON mode prints the run and the resource it made:

JSON
{
  "run": {
    "runId": "00000000-0000-4000-8000-000000000b01",
    "kind": "course",
    "status": "completed",
    "resourceId": "00000000-0000-4000-8000-000000000201",
    "creditsCharged": 18
  },
  "resource": {
    "id": "00000000-0000-4000-8000-000000000201",
    "title": "Beginner Python for analysts",
    "editorUrl": "https://...",
    "publicUrl": "https://..."
  }
}

The run and resource are abridged here. resource is null when the follow-up read fails; the run is still reported. Text mode prints runId, status, creditsCharged, resourceId, title, editorUrl, and publicUrl.

If the run fails, the command exits 1 with ERUNFAILED; for a course the hint names tutorflow run resume <runId>. If --timeout passes first, it exits 1 with ETIMEOUT, and the run keeps going: pick it up with tutorflow run wait <runId>.

See Generation Runs for the run fields, stages, and time limits.

Follow Generation Runs

CommandWhat it does
tutorflow run listLists the classroom's runs, newest first. --kind course|slide|test|module, --status queued|running|completed|failed, -l, --limit <n>, --cursor <cursor>.
tutorflow run get <runId>Prints a run.
tutorflow run wait <runId>Waits like generate --wait and prints the same result. Takes --timeout <seconds> (default 900).
tutorflow run resume <runId>Resumes a failed course run. The new run writes only the unfinished lessons. Takes --idempotency-key.
bash
tutorflow --json run wait 00000000-0000-4000-8000-000000000b01 --timeout 1800

Videos

tutorflow video create

Creates a video. Each --scene <script> adds a scene with that narration script, in order. With scenes, the command prints the video after the last scene is added; without, it prints the created video.

bash
tutorflow video create --title "How rainbows form" \
  --scene "Sunlight looks white, but it holds every color." \
  --scene "Raindrops bend each color by a different amount."
FlagMeaning
--title <title>Required.
--description <text>Description.
--visibility <visibility>PUBLIC, UNLISTED, or PRIVATE.
--scene <script>Repeatable. Adds a scene with this script.
--idempotency-key <key>Sent with the create call only.

If a scene fails, the video still exists. The error names the videoId and how many scenes were added, and the hint shows the video scene add command for the rest.

Scenes

CommandWhat it does
tutorflow video scene add <videoId>Adds a scene at the end, or after --after <sceneId>, and sets the fields you pass.
tutorflow video scene update <videoId> <sceneId>Changes a scene. Pass at least one field.
tutorflow video scene delete <videoId> <sceneId>Deletes a scene. Takes -y, --yes.

add and update take --script <text> (narration), --display-text <text> (text on screen), and --duration <seconds>.

Narrate and render

CommandWhat it does
tutorflow video narrate <videoId>Generates narration for every scene without one, or only for --scene <sceneId>. 1 credit per scene. Takes --idempotency-key.
tutorflow video render <videoId>Starts an mp4 render. --generate-missing-narration narrates scenes without narration first. -w, --wait and --timeout <seconds> (default 1800).
tutorflow video render-status <videoId>Prints the render status and, once rendered, the video URL.
tutorflow video render-cancel <videoId>Cancels a running render.
bash
tutorflow video render 00000000-0000-4000-8000-000000000601 --generate-missing-narration --wait

With --wait, the command prints the final render status once renderStatus is COMPLETED. A FAILED render, or one that goes back to IDLE after rendering (cancelled), exits 1 with ERUNFAILED. Completion also arrives as the video.render.completed webhook. See Video Render.

Games and Simulations

game and simulation share one flow: create, plan with brief, then build, and revise later.

CommandWhat it does
createCreates an empty game or simulation. --title <title> (required), --description <text>, --visibility PUBLIC|PRIVATE (default PRIVATE), --idempotency-key.
brief <id>Plans it (1 credit). --reference <markdown> passes reference material.
build <id>Builds it from the plan. 40 credits for a game; 20 for a 2D simulation, 30 for 3D.
revise <id>Revises it. --feedback <text> is required. Priced like build.
status <id>Prints the running step (active) and how the last one ended (last).

brief, build, and revise take -w, --wait, --timeout <seconds> (default 900), and --idempotency-key. The CLI always asks the API for the asynchronous 202 answer, not the event stream.

bash
tutorflow game create --title "Fraction match"
tutorflow game brief 00000000-0000-4000-8000-000000000701 --wait
tutorflow game build 00000000-0000-4000-8000-000000000701 --wait --timeout 600

With --wait, the command prints the { active, last } status once the step ends. A failed step exits 1 with ERUNFAILED. See Games and Simulations.

Evaluate Learner Answers

tutorflow evaluate

Grades one answer and waits for the result (1 credit).

bash
tutorflow evaluate --type open-ended \
  --question "Why is the sky blue?" \
  --student-answer "Air scatters blue light more." \
  --learner-id student-7 --concept-tags light,atmosphere
FlagRequest field
-t, --type <type>evaluationType: exact, rubric_short_answer, or open_ended. Aliases: rubric, open-ended.
-q, --question <text>questionText
-a, --student-answer <text>learnerAnswer
-e, --expected-answer <text>referenceAnswer. Required for exact.
--rubric-json <json>rubric. Required for rubric_short_answer.
--max-score <n>maxScore
-l, --language <lang>language of the feedback. Default en.
--learner-id <id>learnerExternalId: your id for the learner
--concept-tags <list>conceptTags, comma-separated
--subject <subject>subject
--idempotency-key <key>Idempotency-Key header

On a terminal the CLI asks for a missing type, question, answer, or expected answer.

tutorflow evaluation

CommandWhat it does
tutorflow evaluation listLists the classroom's evaluations, newest first. -l, --limit <n>, --cursor, --learner-id <id>, --status <status>, --type <type>.
tutorflow evaluation get <evaluationId>Prints one evaluation.
tutorflow evaluation conceptsLists the concepts evaluations have tagged in the classroom.
tutorflow evaluation mastery <learnerId>Prints a learner's mastery per concept. learnerId is the --learner-id you graded with.

Learners

Learner commands need a live key; a test key gets 403 content_sandbox_unsupported.

CommandWhat it does
tutorflow learner listLists learners. -l, --limit <n>, --cursor, --status <status>, -q, --query <text> (name or email).
tutorflow learner get <learnerId>Prints a learner.
tutorflow learner progress <learnerId>Prints the learner's course progress.
tutorflow learner inviteAdds a learner by email. --email <email> (required), --name <name>, --locale <locale> (default en), and repeatable --course <courseId> and --test <testId>.
tutorflow learner remove <learnerId>Removes the learner from the classroom. Takes -y, --yes.
bash
tutorflow learner invite --email learner@example.com --course 00000000-0000-4000-8000-000000000201

An organization member joins at once; anyone else gets an invitation. See Learners.

Webhooks

Webhook commands call /v1/content/webhooks and need a key with the webhooks:manage scope.

CommandWhat it does
tutorflow webhook listLists endpoints.
tutorflow webhook createCreates an endpoint. --url <url> (required), one or more --event <event>, --mode live|test. The signing secret is shown once.
tutorflow webhook get <webhookId>Prints an endpoint.
tutorflow webhook delete <webhookId>Deletes an endpoint. Takes -y, --yes.
tutorflow webhook test <webhookId>Sends a webhook.ping event now.
tutorflow webhook deliveries <webhookId>Lists recent deliveries, newest first.
tutorflow webhook rotate-secret <webhookId>Replaces the signing secret and shows the new one once.
bash
tutorflow webhook create --url https://example.com/hooks/tutorflow \
  --event course.generation.completed --event video.render.completed

Test endpoints receive the events of test keys. See Webhooks.

Classrooms and Credits

CommandWhat it does
tutorflow classroom listLists the classrooms the key can reach. Text mode shows ID, name, slug, and whether it is the sandbox.
tutorflow credits balancePrints the AI Credit balance the key spends from.
tutorflow credits historyLists charges, refunds, and adjustments, newest first. -l, --limit <n> (default 20, max 100), --cursor, --from <iso>, --to <iso>, --type <type>.

A test key works in the sandbox classroom and spends nothing. See Test Mode.