Task style and voice¶
A SkillCred task is either a hands-on sandbox exercise or a Markdown-authored choice question. Both types live in task.en.md, where you write the prompt the candidate sees.
At a glance
| Area | The shape |
|---|---|
| Sandbox skeleton | Frontmatter → # Task → directive → optional structure → closing reminder. |
| Choice skeleton | Frontmatter → prompt → one final top-level task list. |
| Voice | Bare imperative for sandbox tasks; direct question or instruction for choice prompts. |
| Plain language | Common words, short sentences, one name per thing. Prompts travel across first languages. |
| Frontmatter | Use type: sandbox or type: choice. |
| Sandbox heading | # Task is the only H1, and it becomes the panel title. |
| Sandbox paths | Absolute paths only. |
| Copy targets | Anything the candidate copies sits in a fenced code block. |
| Sandbox admonitions | One severity per role: info, warning, note, danger, abstract, tip. |
| Sandbox closer | One of three canonical reminders, used verbatim. |
If you have never built a sandbox item before, the Quickstart walks you through your first one.
Orientation¶
Your task file lives at:
items/<id>/task.en.md
For a sandbox item, the sandbox renders the file into the candidate's instructions tool, a fixed panel on the left of their browser. The candidate cannot edit the file or see its source; everything they read comes from the rendered Markdown. Choice items render as questions with selectable answers.
About these examples
The Source block is exactly what you write in task.en.md. The Rendered preview below it is how the candidate sees that source in their instructions panel.
Sandbox document skeleton¶
Every sandbox task has the same shape:
- State the goal. One short imperative sentence at the top.
- Give the candidate what they need. Paths, commands, expected values, each in a fenced block so they can copy with a click.
Many sandbox tasks also close with a short reminder (see Sandbox closing notes).
Here is the smallest complete task. Copy it and adapt as you go.
---
type: sandbox
---
# Task
Edit the file:
```text
/home/tux/.vimrc
```
Add a line that enables line numbers.
!!! warning
Save your changes. Unsaved work will not be scored.
Task
Edit the file:
/home/tux/.vimrc
Add a line that enables line numbers.
Warning
Save your changes. Unsaved work will not be scored.
Sandbox voice¶
The directive at the top of every sandbox task is a bare imperative: a verb-first sentence with no subject. Edit the file: reads cleaner than You should edit the file: and gets the candidate moving immediately. The candidate is the implicit subject of every imperative; there is no need to address them explicitly.
A few habits keep that voice consistent across the catalog:
- Open with a verb. Common starters: Use, Create, Modify, Configure, Append, Convert, Fix, Write, Run, Identify.
- Leave first person out of the prompt: no we, no let's, no I. The candidate does the work; the prompt belongs to them.
- Explicit you is fine inside an admonition body when you are addressing the candidate directly. The directive itself stays subject-free.
- Use the fewest sentences necessary to convey the starting state. More than one is fine when the scenario genuinely needs it; narration starts when context exceeds what the candidate needs to begin.
- The tone is procedural, not conversational. Humor and encouragement read well in tutorials, but not in a scored hands-on objective.
# Task
Use Vim to edit the configuration file:
```text
/home/tux/.vimrc
```
Set the color scheme to `torte` and enable line numbers.
Task
Use Vim to edit the configuration file:
/home/tux/.vimrc
Set the color scheme to torte and enable line numbers.
When the scenario needs context (a starting state, a precondition), one short declarative sentence leads in, and the directive follows:
# Task
The Git repository has merge conflicts on the `feature` branch. The repository is at:
```text
/home/tux/repository
```
Resolve the conflicts so that `feature` can be fast-forward merged into `main`.
Task
The Git repository has merge conflicts on the feature branch. The repository is at:
/home/tux/repository
Resolve the conflicts so that feature can be fast-forward merged into main.
Plain language¶
SkillCred candidates come from many countries and many first-language backgrounds. The prompt should read just as clearly for every one of them, whatever their fluency in English.
A few habits keep prompts accessible:
- Pick the most common word for the meaning. Use reads more clearly than leverage, start than commence, after than following.
- Avoid idioms and figures of speech. Wrap up, the clock is ticking, out of the box carry meaning that does not translate.
- Use the same name for the same thing throughout the prompt. If you call a file a
Dockerfileonce, do not switch to image definition later. - Spell out unfamiliar abbreviations the first time. Familiar names the task is built around (
HTTP,YAML,kubectl) need no expansion.
The two prompts below say the same thing. The first leans on idioms and shifts vocabulary; the second is plain.
# Task
Get the hang of Vim's spell checker and knock out the misspelled words in:
```text
/home/tux/notes.md
```
Wrap up before the time runs out.
Task
Get the hang of Vim's spell checker and knock out the misspelled words in:
/home/tux/notes.md
Wrap up before the time runs out.
# Task
Correct the spelling mistakes in the file:
```text
/home/tux/notes.md
```
Use Vim's spell checker to find them.
Task
Correct the spelling mistakes in the file:
/home/tux/notes.md
Use Vim's spell checker to find them.
Frontmatter¶
The first few lines of every task.en.md file are a small YAML block between two --- lines. The platform reads it when assembling the exam; the candidate never sees it.
The type field classifies the task:
type: sandboxidentifies a hands-on task backed by a sandbox.type: choiceidentifies a question authored as a Markdown task list.
Use one flat type field. The examples in the rest of this page show the frontmatter appropriate to each task type.
---
type: sandbox
---
# Task
Customize Vim with these requirements:
Task
Customize Vim with these requirements:
Choice task grammar¶
A choice item contains a prompt followed by one top-level task list.
---
type: choice
---
Which image is smallest?
- [ ] `ubuntu:24.04`
- [x] `alpine:3.20`
- [ ] `debian:12`
Follow these rules:
- Put the complete prompt before the first top-level task list. That first list is the answer list.
- Give every top-level answer an explicit
[ ]or[x]marker. Checked answers are correct; unchecked answers are incorrect. - Provide at least two answers and check at least one. Check every correct answer when the question has more than one.
- Keep nested paragraphs, code blocks, and lists indented under their answer. A nested list is content within that answer, not another set of choices.
- Make the answer list the final top-level block. Do not put a heading, paragraph, code block, list, or other top-level content after it.
- Use Markdown formatting, links, images, inline code, and fenced code as needed, but do not use raw HTML in the prompt or answers.
The platform assigns answer identifiers and selection behavior. Authors supply only the prompt, answer text, and correct markers.
Sandbox headings¶
For a sandbox task, # Task becomes the title at the top of the candidate's instructions panel. It is the one H1 in the file, and it carries enough weight that the file rarely needs any other heading.
Two exceptions show up in practice:
### Example outputfor prompts that include a small sample of the expected result.### Informationfor a labeled block of reference data the candidate needs while solving.
Anything else (Objective, Prerequisites, Verification, or a descriptive H1 like # Build a Greeting Image) adds visual weight without adding information. The directive is the objective; the closing reminder is the verification cue.
# Task
Write a JSONPath expression that returns the `title` of every movie.
### Example output
```json
["The Matrix", "Inception"]
```
Task
Write a JSONPath expression that returns the title of every movie.
Example output
["The Matrix", "Inception"]
Sentence length and density¶
Candidates have limited time during an exam. Short prompts let them spend it on the work, not on parsing instructions.
A few guidelines that keep tasks scannable:
- The directive itself is usually one sentence, around 25 words or fewer.
- For parallel conditions, such as a group of settings or properties to configure, prose with inline
{.copy}spans is preferred. Numbered lists imply a sequence that may not exist, and they expand simple requirements into visual bulk. - Numbered lists fit ordered procedures where the candidate must do step A before step B. Bullets and tables fit reference data (key/value pairs, acceptance criteria) that does not flow naturally as prose.
- A typical task body is under 40 lines, short enough that the candidate reads it once and moves on. Tabular input data and bundled reference material can push that ceiling, but the directive itself stays compact.
- The task must include every value and constraint the candidate needs to solve it, but it should not mirror the internal scoring check list. The prompt structure serves the candidate's understanding, not the grader's implementation.
# Task
Modify the script at:
```text
/home/tux/healthcheck.sh
```
Make the script:
1. Run the `healthcheck` binary.
2. Append both STDOUT and STDERR to:
```text
/var/log/stats.log
```
3. Exit with the same status code as `healthcheck`.
Task
Modify the script at:
/home/tux/healthcheck.sh
Make the script:
- Run the
healthcheckbinary. -
Append both STDOUT and STDERR to:
/var/log/stats.log -
Exit with the same status code as
healthcheck.
Code and copy targets¶
Every fenced code block and inline `value`{.copy} span in the candidate's instructions panel comes with a one-click copy button. That detail saves the candidate from retyping long paths and exact commands during an exam, and it shapes how SkillCred tasks present copy targets.
Three forms to choose from:
- Fenced block — a path, command, multi-line value, or sequence of commands the candidate copies.
- Inline
{.copy}— a short value the candidate copies that reads naturally in the prose around it:`my-namespace`{.copy},`3000`{.copy}. - Plain inline backtick — something you are naming in prose, not asking the candidate to copy.
Common copy targets the candidate paths through during a task:
- A file path they open or edit.
- A command they run.
- An image tag, a URL, a configuration value.
- An exact string they enter into a tool.
And things that read more naturally as inline backticks, because the candidate is reading rather than copying:
feature,main, or another branch name mentioned in passing.- A field name like
titleor a config key likereplicas. - A status code like
200or404. - The
tuxuser when you name them in prose.
When a copy target is short, `value`{.copy} keeps the prose intact. When it is long, contains slashes, or warrants its own visual weight, pull it onto its own fenced line. The candidate notices the difference at exam time.
Tag every fenced block with a language¶
The opening backticks take a short language tag right after them. The tag tells the panel how to color the block and hints at what the candidate is looking at:
textfor paths, tags, URLs, and exact strings (anything that is not a real language).bashfor shell commands.json,yaml,python,dockerfile, and so on for source code and data.
Unlabeled fences and the older 4-space-indented code style render without color or framing, so they are best left out of task files.
Tables and lists are tight quarters¶
Inside a table cell, plain backticks work for prose names and `value`{.copy} works for copy targets — a fenced block would break the cell layout. Inside a numbered or bulleted list, a fenced block can be indented three spaces under the marker and it renders cleanly as part of that list item.
Keyboard keys¶
When the candidate has to press a key or a chord (Ctrl+D, Enter, Shift+Tab), the keys go between ++ markers. The panel renders them as styled key glyphs the candidate recognizes immediately.
Exit the editor with ++ctrl+d++.
Exit the editor with Ctrl+D.
Choosing the right form¶
Here is the same task written two ways. The first leaves the candidate with two values they have to retype:
# Task
Modify the script at `/home/tux/healthcheck.sh` and build the image tagged `linux-foundation-education/hello:1.0`.
Task
Modify the script at /home/tux/healthcheck.sh and build the image tagged linux-foundation-education/hello:1.0.
The fenced version gives the candidate a copy button on each value:
# Task
Modify the script at:
```text
/home/tux/healthcheck.sh
```
Build the image and tag it as:
```text
linux-foundation-education/hello:1.0
```
Task
Modify the script at:
/home/tux/healthcheck.sh
Build the image and tag it as:
linux-foundation-education/hello:1.0
Commands the candidate runs are copy targets too. A bash fence colors the command and exposes a copy button:
# Task
Apply the manifest with:
```bash
kubectl apply -f /home/tux/deployment.yaml
```
Task
Apply the manifest with:
kubectl apply -f /home/tux/deployment.yaml
Sandbox paths¶
Every path in a sandbox task is absolute. Candidate-owned files live under /home/tux/...; system-managed files live under their usual roots (/etc, /var, /opt, /usr, /srv).
The default candidate user is tux, but the candidate may switch users during a task. A sudo command, an su to root, or a service-account shell all change which home directory ~ points to. A path like ~/my-file.txt resolves to whichever user is currently logged in, so it can suddenly point to a place the file is not. Absolute paths sidestep that confusion entirely.
A few habits that follow from the rule:
- Spell out the full path (
/home/tux/notes.md) rather than the tilde (~/notes.md). - Avoid relative paths (
./foo,../bar); they depend on the candidate's working directory. - Name
tuxas the actor when the default user is doing the work. Name other users explicitly when the task requires them (rootviasudo, a service account).
# Task
Append a license header to every shell script under:
```text
/home/tux/scripts
```
Use the header file at:
```text
/etc/license-headers/sh.txt
```
Run the rewrite as the `tux` user.
Task
Append a license header to every shell script under:
/home/tux/scripts
Use the header file at:
/etc/license-headers/sh.txt
Run the rewrite as the tux user.
Lists, tables, emphasis¶
Lists and tables both have their moment. Numbered lists work well for ordered procedures the candidate follows top-to-bottom. Bullet lists fit unordered constraints, resources, or acceptance criteria. Tables shine when you have three or more key/value rows that line up neatly.
A few small details that keep the page tidy:
- Ordered-list markers stay plain (
1.,2.,3.). Some editors emit1\.; that backslash renders literally in the panel. - Emphasis lives in
**bold**and admonition severity, not in ALL-CAPS. The exceptions are domain literals likeSTDOUTandSTDERR, which are the actual names of the things. - The format name is
Markdown, with a capital M.
# Task
Add the following key-value pairs to the top-level JSON object:
| Key | Value |
| --- | --- |
| `watermelon` | `green` |
| `lemon` | `yellow` |
| `cherry` | `red` |
Do not change the existing keys or values.
Task
Add the following key-value pairs to the top-level JSON object:
| Key | Value |
|---|---|
watermelon |
green |
lemon |
yellow |
cherry |
red |
Do not change the existing keys or values.
Admonition vocabulary¶
Admonitions are the color-coded callout boxes the panel renders from !!! type lines. Each color carries a different meaning, so picking the right one helps the candidate spot what matters at a glance.
| When you want to say… | Reach for |
|---|---|
| This is a hard prohibition; doing it invalidates the candidate's work. | !!! danger |
| A soft constraint, or a save-or-apply closing note. | !!! warning |
| A permissive caveat, an autosave reminder, or a version note. | !!! info |
| Offer a small hint for a detail the item does not measure. | !!! tip open, or ??? tip "Hint: <topic>" only when the hint is long. |
| Point at a man page, reference document, or other outside material the candidate may need. | !!! abstract "Reference Documentation" |
| List the restricted tools or resources for the task. | !!! info "Restricted environment" or !!! info "Available tools" |
Hints are scarce on a scored exam. The candidate is expected to bring the knowledge the item tests, so a hint that hands over part of the answer weakens the measurement. Keep hints to the edges of the task: a pointer at the man page for a tool the item leans on but does not test, or a small !!! tip for a mechanical detail that is not what the item measures. When you point at documentation, name it and show the exact command.
Prefer an open admonition over a collapsible ??? tip. Hiding the hint behind a click rarely helps during a timed exam, and the candidate reads the whole task at once when it stays open. Reserve ??? for a hint long enough that collapsing it keeps the panel readable. Labs are different: a learner works at their own pace, so a collapsible hint lets them choose how much help they want, and it is encouraged there. See Collapsible hints in the lab guide.
The body of an admonition or collapsible block starts after a blank line, indented four spaces under the !!! type or ??? type line. A few examples covering the different roles:
!!! danger
Do not modify any task definitions or create a new Pipeline.
Danger
Do not modify any task definitions or create a new Pipeline.
!!! warning
Do not move, delete, or change any other content.
Warning
Do not move, delete, or change any other content.
!!! info
The commit message is not scored.
Info
The commit message is not scored.
!!! abstract "Reference Documentation"
```bash
man tar
```
Reference Documentation
man tar
!!! abstract "Reference Documentation"
See `pipelines.md` for the full `Pipeline` schema.
Reference Documentation
See pipelines.md for the full Pipeline schema.
Sandbox closing notes¶
Most sandbox tasks end with a short closing note that tells the candidate how to wrap up. Three notes below cover almost every situation. Pick the one that matches your task and use the wording verbatim; candidates learn these phrases across many tasks and rely on them.
!!! warning
Save your changes. Unsaved work will not be scored.
Warning
Save your changes. Unsaved work will not be scored.
!!! info
The editor is configured to automatically save any changes. There is no need to manually save the file.
Info
The editor is configured to automatically save any changes. There is no need to manually save the file.
!!! warning
Save your changes and apply them to the cluster. Unsaved or unapplied work will not be scored.
Warning
Save your changes and apply them to the cluster. Unsaved or unapplied work will not be scored.
Constraint phrasing¶
Every now and then a task needs to tell the candidate not to do something. The canonical phrasing is Do not <verb> ..., with the severity carried by the admonition color around it.
Two habits keep the wording calm:
- Do not is spelled out: no Don't, no Do NOT. The phrase already carries the prohibition.
**only**sits right next to the verb or condition it constrains, so the candidate spots the limit immediately.
Change the script so that `make apply` runs **only** if `pre-commit run --all-files` exits with a zero status.
!!! warning
Do not add extra commits.
Change the script so that make apply runs only if pre-commit run --all-files exits with a zero status.
Warning
Do not add extra commits.
Common pitfalls¶
These are the patterns reviewers push back on most often. Each collapsible shows the problem and the fix.
Tildes or relative paths
Edit `~/notes.md` and the script in `./bin/run.sh`.
Tildes and relative paths assume the candidate's working directory. Absolute paths in fenced text blocks line up across every sandbox task: /home/tux/notes.md and /home/tux/bin/run.sh.
Emoji or icons in the task
# Task
🚀 Build a container image and tag it as `sc109:demo`.
Decorative icons distract from a procedural prompt and may not localize. Plain text reads cleanly in every locale.
First-person voice
# Task
We will modify the script so that input lines are also converted to lowercase.
The candidate does the work, not "we". The bare imperative Modify the script so that ... reads more directly.
Heading-level inversion (## Context above # Task)
## Context
The Git repository at `/home/tux/repository` has merge conflicts.
# Task
Resolve the conflicts.
# Task is the panel title. Setup context fits in a sentence underneath it, not in an H2 above.
Escaped ordered-list markers
# Task
1\. Create a new Helm chart at `/home/tux/game-mullet`.
2\. Add a dependent chart.
Some editors emit 1\. to escape the period. The candidate sees the backslash literally. Plain 1., 2., 3. render the way the candidate expects.
Unlabeled fences
Run this binary:
```
/opt/refactored-doodle/bin/space-invention
```
Every fence takes a short language tag so the panel can color and frame it. text for plain literals, bash for commands, json / yaml / python / dockerfile for data and source.
ALL-CAPS emphasis
Do NOT configure the Bash prompt globally. Only configure it for the `tux` user.
The admonition severity and **bold** carry weight already. Do not and **only** read calmer and keep the rest of the prompt easy to scan.
Lowercase markdown
Recreate the following table in markdown.
The format name is capitalized: Markdown.
Friendly reminder where the canonical closer belongs
Don't forget to save your changes to the script.
The closing notes are canonical phrases candidates learn to recognize. Use the exact wording from Sandbox closing notes so the prompt feels familiar.
Two admonitions of the same color in a row
!!! warning
Do not add extra commits.
!!! warning
Do not push to the remote.
Merging them into one admonition with a bulleted body reads as a single rule, not two stacked.
Typos in task text
Sort the entries so they are properly formated.
A quick spellcheck before the pull request keeps the prompt tidy.
Related pages¶
Step-by-step contribution flow for an assigned sandbox item.
Fields and constraints enforced by skills validate item.
Practice the sandbox CLI and the item lifecycle end-to-end.