pulse docs

Debug ML while it's training.

Track → Diagnose → Verify → Patch

Pulse catches the bug while the run is still training: about 1.3 minutes to a fix and $0.19 per task in our benchmark. Built for terminals, SSH, containers, Colab, remote servers and cloud GPUs.

Quickstart Open the dashboard ↗
installstart pulseask the agent

Try the terminal below to tick these off.

What are you trying to do?

New to Pulse?

$ pip install pulseml
getting started

Installation

Requires Python 3.9+, a supported backend (NumPy, PyTorch, TensorFlow, CuPy or JAX), and a model for the agent: sign in to OpenRouter from Pulse (no key to handle, free models available) or bring an API key.

$ pip install pulseml

Installing puts a pulse command on your path. Run it and Pulse takes you through setup.

Start Pulse

$ python3 -m pulse

To make the plain pulse command work, add Python's scripts folder to your PATH once:

$ export PATH="$PATH:$(python -c 'import sysconfig; print(sysconfig.get_path("scripts"))')" $ pulse
getting started

Try it

A simulated terminal. Click a command or type it. Tab completes, ↑ recalls.

$
getting started

Quickstart

Three steps, and no changes to your training code. Click through.

getting started

The Pulse app

This is what Pulse looks like in your terminal: the run on the left, the agent on the right. It is a working illustration, not live data. Click a thought, a tool line or an edit to open it. Press CtrlO to open all of them. Type a message, or start with / to see commands.

Colour has a job: orange for what is live, selected or worth a look, red for what is wrong, grey for everything else. The agent's thinking is orange italic, a command it ran is bold grey, and Pulse's own output is dim.

getting started

Start Pulse

One command. It does the rest: setup, running scripts, watching runs, the agent.

getting started

Supported backends

core concepts

How Pulse works

Pulse separates AI reasoning from exact numerical calculation: instead of asking a model to estimate whether a gradient or update is unusually large, Pulse calculates the quantity directly. Click a stage.

core concepts

Detection & auditing

Findings

A finding carries a check id, a variable, a severity, its numbers and a confidence. It is deduplicated on (check, variable), so "spiked to 4.12" and "4.13" aren't two problems. A check must hold for two consecutive evaluations before it is raised, except NaN and Inf, where waiting is itself the damage. Findings clear when the condition goes away and can fire again. Detection runs whether or not auto-fix is on.

When the agent looks again

After each model turn the brain asks when to come back, and why. A fix that just landed, a metric heading the wrong way or anything uncertain pulls the next look in to minutes; a smoothly descending run is left alone for an hour. A NaN, a critical finding or a fix brings the next look forward immediately, and the schedule survives a brain restart.

The audit pass

It is handed the whole run: every curve downsampled into min/mean/max buckets (a two-step spike survives), current findings, tensors, what was fixed, earlier audits, and how many samples were dropped. It is asked for what deterministic checks can't see: a loss decreasing far slower than it should, two metrics that disagree, a plausible-but-wrong value.

ML lint (mllint)

Deterministic code-level checks: incompatible loss/metric combinations, redundant activation/loss combinations, backward() without the expected optimizer update, train/eval mode issues, suspicious learning rates, and other ML-specific static patterns.

core concepts

Benchmark

Injected ML faults in real training code. Each tool must find the cause and apply the fix. Pulse runs on DeepSeek v4.1; Claude Code on Opus.

TIME TO FIX
1.3 min
Claude Code: 3.9 min
COST PER TASK
$0.19
Claude Code Opus: $0.39
CASES FIXED
11 / 11
Claude Code: 9 / 11
TRAINING THREAD
0 s
stream mode, 20k steps (single process: 0.059 s)
11 cases shown. Mean time over the cases each tool fixed: Pulse 1.3 min (11 fixes), Claude Code 3.9 min (9 fixes; one fault missed, one found but not applied). Residual's internal benchmark.
How the benchmark changed Pulse

Expanded mllint checks · minimal-fix-first behaviour · whitespace-tolerant patch matching · retry-on-mismatch patching · stronger verification of correctness and patch scope · more agentic debugging workflows.

tracking

Tracking

Pick a variable. Illustrative example, not real runtime data.

shapedtypedevicestatisticsNaN / Infhistory
tracking

GPU tracking

If nobody asks Pulse to touch the GPU, Pulse doesn't touch the GPU.

GPU tracking can introduce device-to-host transfer overhead. It is opt-in.

cli

Command explorer

ai

Choose your agent

debugging

Auto-fix & approver

> /autofix on
Who approves commands? (auto mode)

Some shell commands the agent wants need an OK first: ones that delete files, rewrite git state, reach outside the project, start a background process or overwrite a file. So a long run never stops to wait, a model answers that y/N. By default it is the agent's own model, asked separately.

"approver": "off" # in pulse_config.json: you answer yourself

Or set "approver": "<model>" to pick a different model. The same commands are flagged either way; only who answers changes.

What the approver sees and decides

Only the command, why it was flagged, the project folder, and what the agent was working on, never the agent's reasoning. It answers APPROVE or DENY with a reason that goes back to the agent. It is told to deny anything that could destroy work that can't be regenerated, touch files outside the project, handle credentials or use sudo, and to deny when unsure.

It also answers "apply this change?" for each edit the agent proposes, judging the diff against your request. Every applied change stays one /undo away. If it can't be reached, Pulse asks you (or declines in a non-interactive run). Every decision is printed and recorded in the agent log.

cloud

Cloud workspaces & dashboard

TRAINING MACHINE

pulse

PULSE WORKSPACE

Sessions · Incidents
Agent logs · Tracebacks
Commit · Team members
Cloud synchronization is best-effort and is not intended to block the training loop. For sensitive projects, review your cloud and telemetry configuration carefully.

What gets synced?

Dashboard

Workspaces can be named and managed from the CLI; members can leave, and admins can delete one. A run opened in the app (via /run, /monitor, or attached) gets its own session, with its environment, metric snapshots, findings and crashes as incidents, the agent's turns, and uptime, synced in the background. Sign in at the dashboard to pick a workspace, then a project, then a run. Runs show loss, grad norm, learning rate, uptime/downtime, commit, GPU and incidents. A run counts as live if it had activity in the last 5 minutes. Secret projects appear only to workspace admins and members who joined with the project's join code.

Telemetry

PULSE_TELEMETRY=off
advanced

Two processes: monitor and brain

TRAINING PROCESS

pulse_monitor.Monitor
reads values · writes frames
never blocks, never thinks

BRAIN PROCESS

pulse_brain.Brain
history · detection
the audit · the agent
For most cases, just use pulse. It is the better default. Stream mode is for when you want a run to keep going with nobody attached.

Pulse used to be one process, so a run stopped dead while the model thought. Measured on a 20k-step loop, PulseCLI.update() held the training thread for 84% of the wall clock, almost all of it two blocking model calls.

python -m pulse.brain # newest session python -m pulse.brain <session-dir> --model openrouter/deepseek/deepseek-v4.1-flash python -m pulse.brain <session-dir> --once # one pass over a finished run

Start a stream run from the training side:

$ pulse run --stream train.py
What the training process pays

Nothing is installed into the loop: no sys.settrace, no callback into user code. A background thread reads the training thread's variables a few times a second. It never converts data to answer a question about its shape; only 0-d and few-element values cross the device boundary, on a schedule; and it holds no references, so tracking a tensor doesn't keep it alive.

Why the stream is lossy on purpose

Under backpressure the oldest frame is dropped and the loss is recorded, so the brain knows its view has a hole rather than the loop being slowed. It is an append-only file, not a socket, so the brain can attach late, crash or restart without the run ever waiting.

advanced

A debugger shouldn't become the bottleneck.

Measured on a 20k-step loop in stream mode. Method and caveats: docs/overhead.md in the repo. In stream mode the training process runs no Pulse code beyond a background thread, and never waits for a model.

advanced

Keras

Keras metrics live in the callback logs dict, not in local variables, so the stream monitor can't see them by sampling. Streaming needs one line of setup, documented in docs/streaming-keras.md. In-process modes (cli, ui) patch Model.fit and need nothing.
reference

Troubleshooting

pulse not found

Add Python's scripts folder to PATH (see Installation), or use python3 -m pulse.

The app doesn't open

Pulse falls back to line-by-line screens without a real terminal (a pipe, CI), on a very small one. On Windows it needs a console that understands escape sequences: Windows Terminal, or the console of Windows 10 and later.

Keys and secrets

Don't put API keys in source code or commit them. A pasted key is never written to disk.

Was this useful? YesNo