Merv-Tutor — step debugger for JavaScript & TypeScript

Introduction

Merv-Tutor is a teaching and debugging tool for small scripts. It instruments your entry file with Babel, runs it under Node, and writes a tutor-only trace to merv-reports/merv-tutor/latest.json. Open the debugger with npx merv-tutor open to step line-by-line, inspect variables in scope, and read mirrored console output — without mixing tutor noise into Playwright or Cucumber suite reports.

You will learn
  • How to install and configure a tutor-ready project
  • CLI options for run and open
  • Worked examples (JS, TS, async, multi-file)
  • How the debugger UI, Project Files panel, and complexity analysis work

Why Merv-Tutor

Requirements

RequirementVersion / notes
Node.js18+
merv-client4.0.22+ recommended
merv-tutor4.0.22+ recommended (aligned with merv-client)
merv.propertiesNot required — tutor finds the nearest package.json as project root

Install

npm install merv-client merv-tutor

Or as dev dependencies in a lesson / course repo:

npm install -D merv-client merv-tutor

Optional package.json scripts:

{
  "scripts": {
    "tutor": "merv-tutor",
    "tutor:open": "merv-tutor open"
  }
}

Configuration

Setup steps

  1. Create or open a Node project with a root package.json.
  2. Install merv-client and merv-tutor (see Install).
  3. Add a small script under a folder such as exercises/ or lessons/.
  4. Run npx merv-tutor path/to/file.js — this creates merv-reports/merv-tutor/.
  5. Open the debugger with npx merv-tutor open.
No merv.properties needed. Merv-Tutor always writes under <nearest-package.json>/merv-reports. Running from a nested folder such as javascript/ does not create a second report tree there.

Report layout on disk

PathPurpose
merv-reports/merv-tutor/latest.json Persistent project trace — only files executed via merv-tutor
merv-reports/merv-tutor.html Step debugger UI (refreshed from the package when you run / open)
merv-reports/log/ Optional NDJSON if Merv-Logs file logging is enabled (separate from the debugger)

Optional Merv-Logs

Tutor instrumentation also emits lines through MervLogger. If you already use Merv-Logs, those lines can appear under merv-reports/log/. The debugger UI itself only needs merv-tutor/latest.json.

# Optional — only if you also want NDJSON / show-logs
merv.report.folder=./merv-reports/
merv.logger.file=true
merv.logger.level=INFO

Quick start

npx merv-tutor exercises/variables.js
npx merv-tutor part1.js part2.js
npx merv-tutor open

merv-tutor open serves the report folder and opens http://127.0.0.1:6174/merv-tutor.html (same default port as merv show-report). You can run open from any project subfolder; it still opens the root-level merv-reports.

CLI reference

Run files

merv-tutor <file.js|file.ts> [more files…] [options]
OptionDescription
--keepLeave generated merv-test.js on disk for inspection
-h / --helpShow help

Open debugger

merv-tutor open [reportDir] [options]
OptionDescription
reportDirOptional path (default: project merv-reports)
--host <host>Bind host (default 127.0.0.1; use 0.0.0.0 for LAN)
--port <port>Bind port (default 6174)
--no-openPrint the URL only — do not open a browser
npx merv-tutor open
npx merv-tutor open ./merv-reports --port 6174
npx merv-tutor open --host 0.0.0.0 --no-open

Examples

Example 1 — variables & functions

Save as exercises/basics.js:

function add(x, y) {
  return x + y;
}

let a = 10;
let b = 20;
let c = add(a, b);
console.log('sum =', c);
npx merv-tutor exercises/basics.js
npx merv-tutor open

In the debugger, step until c = add(a, b) — you will see a, b, and c update in the variables table, and sum = 30 in the console panel.

Example 2 — loops & classes

Save as exercises/counter.js:

class Counter {
  constructor(start) {
    this.n = start;
  }
  bump() {
    this.n += 1;
    return this.n;
  }
}

const counter = new Counter(0);
for (let i = 0; i < 3; i++) {
  counter.bump();
}
console.log('final', counter.n);
npx merv-tutor exercises/counter.js
npx merv-tutor open

Watch loop iterations increase in the summary bar, and i / counter change each step. The analysis panel estimates loop-based complexity for teaching.

Example 3 — async / await

Save as exercises/async-demo.js:

async function load() {
  return await Promise.resolve(42);
}

load().then((v) => {
  console.log('loaded', v);
});
npx merv-tutor exercises/async-demo.js
npx merv-tutor open

Example 4 — TypeScript

Save as exercises/greet.ts:

function greet(name: string): string {
  return `Hello, ${name}`;
}

const msg: string = greet('MERV');
console.log(msg);
npx merv-tutor exercises/greet.ts
npx merv-tutor open

TypeScript is compiled with esbuild, then instrumented. The debugger shows the compiled JavaScript lines (not the original .ts text).

Example 5 — multi-file project

Run several files in one session:

npx merv-tutor exercises/basics.js exercises/counter.js
npx merv-tutor open

Or accumulate over separate commands:

npx merv-tutor src/lessons/test1.js
npx merv-tutor src/examples/test2.js
npx merv-tutor open

Both paths remain under Project Files (folder tree preserved). Click a file to see only that file’s source and steps. Re-running the same path refreshes its trace without removing others.

What is traced

Concept What you see
Assignments / variables Values updated at each step (for example a = 10)
for / while / for-of Loop body markers and loop variables each iteration
if / else Branch taken (if branch / else branch)
Functions / classes Definitions and enter / constructor / method calls
Calls / new / await Call summaries and resolved promise values where available
console.log / info / warn / error Terminal output plus console panel in the debugger
Array mutations (push, …) Array variable refreshed after mutating methods
try / catch / finally Branch markers and catch bindings

How it works

  1. Reads your file (TypeScript via esbuild).
  2. Instruments with Babel (scope-aware: variables, control flow, console.*, calls, await).
  3. Writes a temporary merv-test.js with tutor hooks.
  4. Runs node merv-test.js (console.* still prints; MervLogger itself is quiet on stdout).
  5. Updates merv-reports/merv-tutor/latest.json and refreshes merv-tutor.html.
  6. Deletes merv-test.js unless you pass --keep.

Debugger UI

Scope and shadowing

Shadowed names use Babel binding keys: global a vs block a@19 when let a is declared on line 19. When a block-scoped variable goes out of scope, it disappears from later steps.

Complexity note

Time complexity is estimated from loop nesting (O(1), O(n), O(n²)…); space from whether a collection grows inside a loop. Treat this as a teaching aid, not a proof.

Limitations

Troubleshooting

Issue What to check
Debugger page looks outdated Re-run merv-tutor or merv-tutor open so merv-tutor.html refreshes; hard-refresh the browser (Cmd+Shift+R).
Empty variables or steps Confirm merv-tutor/latest.json exists under merv-reports/merv-tutor/. Run a file first: npx merv-tutor test.js.
Wrong / empty report folder Ensure a package.json exists at the intended project root. Or pass an explicit path: npx merv-tutor open ./merv-reports.
Port already in use Another show-report / tutor server may be serving a different folder. Use --port or stop the other process.
Syntax error after instrumentation Try --keep and inspect merv-test.js; report edge cases on the forum.

What’s next

← Back to Merv-Local documentation