| 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`.
|
shell-report
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+.
Running the server
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/null
node /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.
When to generate a notebook
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.
HTML format
<!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.
Key attributes
| 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. |
Markdown format
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
```
Variables
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.
Transforms
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>
Patterns for agent-generated reports
Structure
- 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)
Cell prose discipline
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.
Use autorun for key cells
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.
Prefer specific over broad commands
<pre data-cmd="cat package.json"></pre>
<pre data-cmd="jq '.dependencies | keys[]' package.json"></pre>
Quote commands defensively
Use " for double quotes in data-cmd attribute values:
<pre data-cmd="git log --format="%h %s" -10"></pre>
Per-cell shells for the right tool
<pre data-cmd="cat result.json | jq '.errors[]'"
data-cmd-shell="bash"></pre>
<pre data-cmd="import json, sys; d=json.load(open('data.json')); print(len(d['items']))"
data-cmd-shell="python3"></pre>
Minimal working example
<!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>
Snapshot
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.