Tutorial Writing skill for Codex
Tutorials tested from a clean machine, step by step. Codex builds the finished project first, then writes the tutorial by retracing it in small verb-first steps, each with the exact file location, complete code and the output the reader should see. Before calling it done, it reruns every copied command in a fresh directory or container, fixes the text wherever hidden knowledge was needed, and adds troubleshooting for the errors that actually came up.
curl -fsSL codexskills.dev/install.sh \ | sh -s -- tutorial-writing Installs to ~/.agents/skills/tutorial-writing/ for every project on this machine.
curl -fsSL codexskills.dev/cli.mjs -o codex-skills.mjsnode codex-skills.mjs install tutorial-writing The CLI also searches, updates and removes skills. Run it with no arguments to pick from a list. Needs Node 20.12+.
curl -fsSL codexskills.dev/install.sh \ | sh -s -- --project tutorial-writing Installs to .agents/skills/tutorial-writing/ in the current repository. Commit it and everyone who runs Codex there gets it.
curl -fsSLO codexskills.dev/downloads/tutorial-writing.zipunzip -o tutorial-writing.zip -d ~/.agents/skills/ The archive holds the skill folder with its generated agents/openai.yaml. Unzip into .agents/skills/ to scope it to a repo.
& ([scriptblock]::Create((irm codexskills.dev/install.ps1))) tutorial-writing PowerShell 5.1 or 7. Installs to %USERPROFILE%\.agents\skills\. Add -Project for the current repo.
104-line POSIX script. No sudo, no telemetry. Read install.sh
Use it in Codex
Start a prompt with $tutorial-writing, or pick it from /skills.
You can also just describe the task: Codex reads the description below and loads the playbook when your request matches.
What Codex reads before loading it
Writes step-by-step technical tutorials that a newcomer can finish - a single concrete outcome, pinned prerequisites, one action per step, expected output after every step, complete copy-pasteable code, troubleshooting for the likely failures - and proves the tutorial works by running every step from a clean environment before publishing. Use when asked to write a tutorial, getting-started guide, quickstart, codelab or workshop, or to fix a tutorial readers report as broken or confusing.
Use it when
- You need a guided, learn-by-building tutorial or codelab
- An existing tutorial is reported broken or confusing
- A new feature needs a first-run walkthrough that newcomers can finish
Use something else when
- Readers already know the concepts and need task steps: use diataxis-docs
- You need the repo's five-minute quickstart: use readme-writing
How to check the result
Run every command and file from the rendered tutorial in a clean directory or container, in order, and confirm each documented output matches what you see.
The mistake it prevents
Showing partial code snippets without saying exactly where they go, so readers paste them in the wrong place and the next step fails.
A tutorial works when a reader with only the stated prerequisites follows it top to bottom and ends with the promised result, without guessing, searching, or reading ahead. It is tested by running it, not by reading it. A tutorial that has not been executed from a clean start in its final form is a draft.
Decide what you are writing
| Reader’s need | Document type | Skill |
|---|---|---|
| Learn by building something, guided start to finish | Tutorial | this one |
| Accomplish a specific task they already understand | How-to guide | $diataxis-docs |
| Get running in five minutes from the repo | README quickstart | $readme-writing |
| Understand why or how something works | Explanation / blog post | $blog-post-writing |
A tutorial promises one concrete outcome (“deploy a webhook receiver that verifies signatures and stores events in SQLite”), not a topic (“learn about webhooks”).
Before writing
- Define the reader: what they already know (language, tooling, terminal comfort) and what they do not. Write it down; every later choice checks against it.
- Define the outcome and the 2-4 things the reader will have learned. Cut anything that does not serve them.
- Pin the environment: OS assumptions, language and tool versions, package versions. Read
the project’s
AGENTS.md, lockfiles andengines/requires-pythonfields so the tutorial matches what the project supports. - Build the finished project first, in a scratch directory. Then write the tutorial by retracing the path in small steps. Writing first and coding second produces steps that do not connect.
Structure
# <Build/Do X with Y> (outcome in the title)
<1-2 sentences: what you will build, a screenshot or final output, time to complete.>
## What you'll learn
- 2-4 bullets
## Before you start
- Tool A 22.x or later (`node --version`)
- An account on <service> (free tier is enough) - and what it is used for
- Familiarity with <concept>: link to a primer
## Step 1: <verb-first action>
## Step 2: ...
...
## Check your work / See it run
## Troubleshooting
## Next steps
Aim for 5-10 steps for a 20-45 minute tutorial. More than 12 steps: split into a series with a working checkpoint at the end of each part.
Writing a step
Each step has one purpose, says why briefly, gives the exact action, and shows how to confirm it worked.
## Step 3: Verify the webhook signature
Anyone can send requests to your endpoint, so reject any request whose signature
does not match your signing secret.
Replace the contents of `server.js` with:
```js
// server.js (complete file)
import express from "express";
import crypto from "node:crypto";
...
```
Restart the server and send a test event with a wrong signature:
```bash
curl -i -X POST localhost:3000/webhook -H "X-Signature: wrong" -d '{"id":"evt_1"}'
```
You should see:
```text
HTTP/1.1 401 Unauthorized
```
Rules:
- Exact location. Say which file, and whether to replace the whole file, add after a named function, or change one line. Prefer showing the complete file for files under ~60 lines; partial snippets are the top cause of reader failure.
- Expected output after every command that produces output. Readers use it to know they are on track.
- One new concept per step. If a step introduces two ideas, split it.
- Commands are copy-pasteable. No
$prompt prefix inside copyable blocks, no placeholders the reader might miss; when one is unavoidable, call it out right before the block (Replace YOUR_API_KEY with the key from step 1). - Explain the why in one or two sentences. Long theory belongs in a linked explanation.
- Show the state. After structural changes, show the directory tree.
- Platform differences inline where they occur (macOS/Linux vs Windows PowerShell), not in a separate section the reader has to find.
Secrets and side effects
- Never embed real keys. Use environment variables and show how to set them; tell the
reader not to commit
.envand include it in.gitignorein the step that creates it. - If a step creates paid cloud resources, say so before the step, and include a cleanup section that deletes them.
- Use test modes and sandboxes (payment test keys, staging projects) wherever the service offers them.
Test the tutorial
This is the step that separates working tutorials from plausible ones.
- [ ] Fresh directory (or container) with only the stated prerequisites
- [ ] Copy every command and file from the rendered tutorial text, in order
- [ ] Compare actual output to the documented expected output at each step
- [ ] Note every place you needed knowledge not stated in the tutorial
- [ ] Fix the tutorial (not the environment) and rerun from the top
- [ ] Record tool and package versions used in the final run
A clean environment, when Docker is available:
docker run --rm -it -v "$PWD/tutorial-run:/work" -w /work node:22-bookworm bash
# or python:3.13-slim, etc. Match the prerequisites you listed.
Without Docker, use a new empty directory and a fresh virtual environment or npx/uvx
style isolated runs. In a Codex sandbox, installs and git clone need network access;
ask the user to approve it, and if it is not available, say which steps were not executed.
For long tutorials, extract code blocks mechanically so you test exactly what readers see:
# print every bash block from the tutorial, in order, to review and run step by step
awk '/^```(bash|sh)$/{f=1; next} /^```$/{f=0} f' docs/tutorials/webhooks.md
Read each extracted command before running it; never pipe extracted blocks straight into a shell, since tutorials often contain deliberately failing or destructive examples.
Troubleshooting section
Add the 3-6 failures readers actually hit, found during your test runs and from issues or support questions. Each entry: the exact error text (so search finds it), the cause, the fix.
**`Error: listen EADDRINUSE: address already in use :::3000`**
Another process is using port 3000. Stop it, or run `PORT=3001 npm start`.
Gotchas
- Steps that rely on state from an earlier step the reader may have skipped. Repeat the key state (“Make sure the server from step 2 is still running”).
- “Simply”, “just”, “easily”, “obviously”: cut them; they make struggling readers feel at fault.
- Unpinned dependencies: a tutorial written against
latestbreaks within months. Pin versions in install commands or the provided lockfile, and state the tested date. - Screenshots of UIs that change often. Prefer text instructions with exact labels; use screenshots only where layout matters, and note the product version.
- Hidden prerequisites: Git installed, a GitHub account, a domain, Xcode command line tools. Your clean-room run exposes these; list them all in “Before you start”.
Verification
- The final tutorial text was executed from a clean environment, top to bottom, and every documented output matched (state the date and versions in the PR or report).
- Every step has an action and a way to confirm success.
- No placeholder, secret, or unexplained file location remains.
- Cleanup instructions remove every resource the tutorial creates.
- Report to the user: tested versions, any steps not executed (network, paid services), and the troubleshooting entries added.
What the zip contains
SKILL.md plus the interface file below. Nothing runs on install.
agents/openai.yaml
Gives the Codex app a display name, a one-line description and a starter prompt for this skill.
interface:
display_name: "Tutorial Writing"
short_description: "Tutorials tested from a clean machine, step by step"
default_prompt: "$tutorial-writing Write a getting-started tutorial for our CLI that ends with a deployed app" About this skill
Written and maintained by the Codex Skills editors to the same editorial standard as every skill here: a selective description, a real workflow, known pitfalls and a way to verify the work. First published , last updated . MIT licensed. Something wrong or out of date? Tell us.