| name | shell-report |
|---|---|
| description | Use this skill when the user wants to produce a shell report: a report that an agent or human can re-execute in the browser. Trigger when the user asks to "generate a report", "create a shell report", "write an sr file", "produce a reproducible report", "document these findings", or wants to validate agent findings interactively. Also trigger when the user asks to run `sr` or `sr.mjs`. |
sr is a shell report server. It turns an HTML (or Markdown) file into a
live, re-executable document. Elements with data-cmd attributes become cells
— the server runs the command in the user's shell and streams output back to
the browser.
One file. Zero dependencies. Node.js 18+.
sr.mjs lives alongside this SKILL.md in the skill directory. Locate it relative to this file, or find it with:
find ~/.claude/skills ~/.codex/skills -name sr.mjs 2>/dev/nullnode /path/to/skill/sr.mjs <file.html|file.md> [options]| Option | Description |
|---|---|
--port N |
Fixed port (default: ephemeral) |
--no-open |
Skip opening the browser |
--shell PATH |
Shell for all cells (default: $SHELL) |
--cwd PATH |
Working directory for all commands (default: $PWD) |
The server binds to 127.0.0.1 only. Edit the source file and the browser
reloads automatically.
Generate a notebook when you have:
- Run several commands to diagnose a problem and want the user to be able to reproduce your findings with one click
- Produced a hypothesis and want to give the user a document that proves or disproves it
- Gathered information across multiple sources that the user will want to re-query or refresh
- Results that would benefit from visualisation beyond plain text
The notebook is the handoff. It should be self-explanatory when read top to bottom, and self-verifiable when "Run all" is clicked.
<!DOCTYPE html>
<html>
<body>
<h1>Title</h1>
<p>Prose describing what this cell shows and why it matters.</p>
<pre data-cmd="command here"></pre>
<h2>Section</h2>
<p>More prose.</p>
<pre data-cmd="another command"></pre>
</body>
</html>The data-cmd value is the exact shell command. The element content is
replaced with the command's stdout on execution.
| Attribute | Description |
|---|---|
data-cmd="cmd" |
Shell command. Required on every cell. |
data-cmd-autorun |
Run on page load (boolean, no value needed). |
data-cmd-timeout="N" |
Seconds before timeout. Default: 30. |
data-cmd-var="name" |
Store trimmed stdout in window._vars.name on success. |
data-cmd-transform="fn" |
Call window.fn(el, {stdout, stderr, exitCode}) for custom rendering. |
data-cmd-shell="bash" |
Run this cell under a specific shell/interpreter. |
Use fenced code blocks with cmd, sh, bash, zsh, or shell:
# Report title
## Section
Prose here.
```bash
command here
```Extended attributes after |:
```sh git log --oneline -20 | autorun timeout=60 var=log
```Pass one cell's output into another's command with {{name}}:
<pre data-cmd="git rev-parse HEAD" data-cmd-var="sha"></pre>
<pre data-cmd="gh run list --commit {{sha}} --limit 5"></pre>Variables are interpolated before the command is sent to the server.
data-cmd-transform names a function on window. The function receives
(el, { stdout, stderr, exitCode }) and owns the element.
<table data-cmd="cat data.json" data-cmd-transform="renderTable"></table>
<script>
function renderTable(el, { stdout }) {
const rows = JSON.parse(stdout);
el.innerHTML = rows.map(r => '<tr><td>' + r.name + '</td></tr>').join('');
}
</script>- Title + one-sentence summary — what is this report about
- Hypothesis or question — what claim does this notebook investigate
- Evidence cells — commands that produce the evidence, with prose context
- Conclusion — what the evidence shows (plain text, no cell)
Every cell should be preceded by a sentence explaining:
- what the command shows
- why it is relevant to the hypothesis
Don't make the user guess why a command is there.
If a cell is central to the hypothesis and safe to run (read-only), add
data-cmd-autorun. The user will see results immediately on open, before
they even read the prose.
<!-- too broad — noisy output -->
<pre data-cmd="cat package.json"></pre>
<!-- better — targeted -->
<pre data-cmd="jq '.dependencies | keys[]' package.json"></pre>Use " for double quotes in data-cmd attribute values:
<pre data-cmd="git log --format="%h %s" -10"></pre><!-- jq for JSON -->
<pre data-cmd="cat result.json | jq '.errors[]'"
data-cmd-shell="bash"></pre>
<!-- python for more complex transforms -->
<pre data-cmd="import json, sys; d=json.load(open('data.json')); print(len(d['items']))"
data-cmd-shell="python3"></pre><!DOCTYPE html>
<html>
<body>
<h1>CI failure — 2024-03-18</h1>
<p>The build is failing on the typecheck step. This notebook traces the cause.</p>
<h2>TypeScript errors</h2>
<p>The raw compiler output from the failing step:</p>
<pre data-cmd="pnpm tsc --noEmit 2>&1 | head -60" data-cmd-autorun></pre>
<h2>Recent tsconfig changes</h2>
<p>Looking for a recent change that might have introduced stricter settings:</p>
<pre data-cmd="git log --oneline -- '*.json' | head -10"></pre>
<h2>Current base config</h2>
<pre data-cmd="cat tsconfig.base.json"></pre>
</body>
</html>The Save snapshot button exports a static HTML file with all current cell output frozen — no server needed to open it. This is the artifact to attach to a bug report or hand to a colleague.