wolframresearch/agenttools/wolfram-debugging

Claude Code and agent skill by wolframresearch/agenttools

Trust tier 3
  • community
Source check pending

Checking that the SKILL.md file is still in the repository.

Verified recipes and tested helpers for debugging Wolfram Language code. Use whenever code issues messages, returns $Failed, Failure or unevaluated calls, gives wrong results, is slow, hangs or crashes, or works in one environment but not another; for stack traces, call logs, profiles, mocks or overrides, watchpoints, ReadProtected definitions, edits that have no effect, failing tests, parallel, cloud or HTTP code. Use it even when Echo or Trace seem enough, as Trace records nothing in the MCP evaluator's default mode or the cloud.

Install

npx vskill@latest install wolframresearch/agenttools/wolfram-debugging

SKILL.md

Wolfram Language Debugging

Verified techniques for finding out why Wolfram Language code misbehaves, checked with Wolfram 15.0 in the MCP evaluator (both methods), wolframscript, wolfram -script and the cloud. Many standard techniques silently do nothing in some of these environments, so read the ground rules first. Paths are relative to this skill directory.

Prerequisites

You need a Wolfram kernel. If you have neither of the following, read references/GetWolframEngine.md; to set up the MCP server, read references/SetUpWolframMCPServer.md.

  • MCP evaluator (preferred, for example mcp__Wolfram__WolframLanguageEvaluator): a persistent kernel, so

definitions made in one call can be inspected in the next.

  • wolframscript: a fresh kernel per run, needed for first-time effects (autoloading, package loading) and for Trace

where the MCP evaluator cannot run it. -f file.wl prints only Print output; -code '...' drops string quotes (print ToString[expr, InputForm]). Always bound runs: timeout -s KILL 300 wolframscript -f file.wl < /dev/null.

Start here: where does the code run?

wl
Module[{cl = StringRiffle[ToString /@ $CommandLine, " "]},
<|"Env" -> Which[
$EvaluationEnvironment === "Script", "wolframscript",
$EvaluationEnvironment === "WebEvaluation", "CloudEvaluate",
$EvaluationEnvironment === "WebAPI", "deployed API or remote MCP server",
StringContainsQ[cl, "ChatbookSandbox"], "MCP Local",
StringContainsQ[cl, "StartMCPServer"] || StringStartsQ[$Context, "Sessions`"], "MCP Session",
MemberQ[$CommandLine, "-script"], "wolfram -script",
True, $EvaluationEnvironment],
"TraceWorks" -> Trace[1 + 1] =!= {}, "Context" -> $Context, "TimeRemaining" -> Internal`TimeRemaining[]|>]
MCP LocalMCP Sessionwolframscriptcloud
Trace, TraceScan, On[sym]workrecord nothingworkrecord nothing
context of typed symbols`Sessions<id> ``Sessions<id> ``Global ```Global ``
state between callspersists in a subkernel shared by all sessionspersists in the MCP server's own kernelnonenone
$MessageListreset per inputnever resetper scriptper call
Print, Echoshownshownstdoutdropped (the remote MCP server shows Print only)
RunProcess, LaunchKernelsblocked (protected mode)allowedallowedblocked
file writesonly below $TemporaryDirectoryanywhereanywherecloud files (remote MCP server: a throwaway directory)

MCP Local and MCP Session are the two evaluation methods of the MCP evaluator; installed local servers use Session by default. "Cloud" is CloudEvaluate, deployed APIs and the remote MCP server. wolfram -script, used by the TestReport MCP tool, also records no Trace. Everything else that differs: references/Environments.md.

Ground rules

  1. Check `Trace[1 + 1] =!= {}` before using Trace. Where it records nothing, use message handlers with Stack,

`InternalInheritedBlock` spies or stack sampling, or run the Trace in wolframscript (more workarounds: references/TracingAndPerformance.md`).

  1. Stack frames, trace items and arguments of kernel messages are wrapped in `HoldCompleteForm` (HoldForm before

version 15). Match them with _[e_] and format with ToString[Unevaluated[e], InputForm, TotalWidth -> 150]. Never extract them with First, [[1]] or ReleaseHold: that evaluates the frame again.

  1. Filter user frames with both user contexts: `MemberQ[{"Global", $Context}, Context[s]]``.
  2. Each input is parsed just before it runs, so a name in the same input as the Get/Needs that defines it is

created in your own context. An input is one line in -f scripts and in the MCP evaluator with Chatbook 2.7.28+, but the whole call with older Chatbook. Put Get/Needs in its own call and call package functions by their full names.

  1. Evaluate code under test as `StackBegin[StackComplete[expr]]`. StackBegin drops the environment's wrapper

frames (about 15 in wolframscript, 65 in CloudEvaluate); StackComplete keeps your calls, which are otherwise replaced on the stack by their right-hand sides.

  1. Return small data as the value. Raw stacks, traces and TestReportObjects can be hundreds of KB (Short has no

effect in the MCP evaluator or wolframscript), and Print output can be lost: collect diagnostics with `InternalBag`/InternalStuffBag`` and return them.

  1. Scope every change: MCP kernels are shared. Use `InternalHandlerBlock` (not InternalAddHandler``),

`InternalInheritedBlock`, Block and WithCleanup. In an MCP evaluator, never call Quit, Exit, Input, InputString, Dialog, ChoiceDialog or Run, write to "stdout", or change $RecursionLimit, $Pre, $Post, Off or SetOptions globally; in MCP Session this can silence or kill the server. In MCP Local, lower $RecursionLimit (even in a Block) only after the subkernel has printed an ordinary message (1/0; in an earlier call): a first printed message under a low limit breaks $Context` for every session.

  1. Reproduce autoloading and package-loading problems in wolframscript: MCP kernels have many packages loaded.
  2. A `Throw`-based probe can be swallowed by Catch[..., _] or EvaluationData in the code under test. If the

probe returns the normal result instead of your data, record without throwing.

  1. The remote MCP server evaluates every input inside `Quiet`, so handlers see every message as quieted: wrap the

code under test in Quiet[expr, None, All].

Symptom → first move → reference

symptomfirst moveread in references/
messages (which, from where?), unexplained $Failed or Failure`WolframDebuggingCollectMessages[expr]`, WolframDebuggingCaptureEvaluation[expr]``, the recipe belowMessagesAndStacks.md
unevaluated f[...] in the result, or the wrong rule fires`WolframDebuggingStuckCalls[result]`, WolframDebuggingWhyNoMatch[f[args]]``UnevaluatedCalls.md
slow, hangs, times out; Trace options`WolframDebuggingSampleStacks[expr]`, WolframDebuggingTimeCalls[expr, {f, g}]`` (no Trace needed)TracingAndPerformance.md
calls and arguments inside an evaluation; mocks (HTTP, time, randomness); a variable changes unexpectedly`WolframDebuggingLogCalls[{f, g}, expr]`, WolframDebuggingWithOverrides[{lhs :> rhs}, expr]`, WolframDebuggingWatchChanges[{x}, expr]``OverridesAndWatchpoints.md
definition or source file of a symbolSymbolDefinition MCP tool, `WolframDebuggingFindSymbolSource["Ctxname"]`DefinitionsAndSource.md
edits have no effect, symbol undefined after loading, what got loaded?`WolframDebuggingContextSourceInfo["Ctx"], WolframDebuggingLoadTrace[expr]``PackageLoading.md
a test fails, or a test file reports 0 tests`WolframDebuggingTestFailureSummary[report]`, WolframDebuggingCheckTestFile[file]``Testing.md
parallel or asynchronous code misbehaves`WolframDebuggingParallelCapture[f, list]``ParallelAndAsync.md
deployed API or HTTP request failsURLRead[req, {"StatusCode", "Headers", "Body"}], `WolframDebuggingDebugHTTPResponse[api, params]``CloudAndHTTP.md
works in one environment but not another, notebook-only code, crashes`WolframDebuggingEnvironmentInfo[]`, WolframDebuggingEnvironmentFingerprint[]``Environments.md, HeadlessAndCrashes.md

The helper package

scripts/WolframDebugging.wl packages the recipes of this skill as tested functions with small, bounded results. Load it in its own call (see rule 4), then call its functions by their full names:

wl
Get["/absolute/path/to/wolfram-debugging/scripts/WolframDebugging.wl"]
WolframDebugging`CollectMessages[myFn[-1, 1]] (* in a later call *)

The helpers work in MCP Local, MCP Session, wolframscript and (most of them) CloudEvaluate; Trace-based ones return Failure["TraceUnavailable", ...] where Trace records nothing. The remote MCP server cannot load local files: use the recipes below there. Every function, option and result shape is in references/HelperFunctions.md.

Core recipes (no helper package needed)

The examples use these definitions:

wl
otherFn[x_] := 1/x; myFn[a_, b_] := Table[otherFn[i], {i, a, b}]; suspectCode[] := Module[{k = 0}, While[True, k++]]
The stack at the first message

A "Message" handler receives Hold[Message[name, args...], willPrint], where willPrint is False for quieted messages. Throwing the stack from the handler gives the call chain that led to the message:

wl
Module[{tag, st},
st = Catch[Internal`HandlerBlock[{"Message", Replace[#, Hold[Message[_, ___], True] :> Throw[Stack[_], tag]] &},
StackBegin[StackComplete[myFn[-1, 1]]]], tag];
If[ListQ[st],
Block[{$ContextPath = Join[{"Global`", $Context}, $ContextPath]},
StringRiffle[Replace[Take[st, Position[st, _[_Message], {1}][[-1, 1]]],
_[e_] :> ToString[Unevaluated[e], InputForm, TotalWidth -> 150], {1}], "\n"]],
st]] (* st is the normal result when no message was issued *)
StackComplete[myFn[-1, 1]]
myFn[-1, 1]
Table[otherFn[i], {i, -1, 1}]
otherFn[i]
1/0
0^(-1)
Message[Power::infy, HoldCompleteForm[0^(-1)]]

Frames show expressions as they were pushed (otherFn[i], not otherFn[0]). For function names only, throw Stack[] instead of Stack[_] and return st unformatted. Match Hold[Message[Power::infy, ___], True] for one message, and Hold[Message[_, ___], _] on the remote MCP server. To collect all messages without stopping, use EvaluationData[expr]["MessagesExpressions"].

Spy on, mock or override a function

`InternalInheritedBlock`` keeps the existing definitions and attributes and restores them when the block exits, even on abort:

wl
Module[{calls = Internal`Bag[], inF = False, res},
otherFn; (* evaluate the symbol first: loads an autoload stub *)
res = Internal`InheritedBlock[{otherFn},
Unprotect[otherFn];
PrependTo[DownValues[otherFn], HoldPattern[otherFn[args___] /; !inF] :>
Block[{inF = True}, Internal`StuffBag[calls, HoldComplete[args]]; otherFn[args]]];
Quiet @ myFn[-1, 1]];
{res, Internal`BagPart[calls, All]}]
(* {{-1, ComplexInfinity, 1}, {HoldComplete[-1], HoldComplete[0], HoldComplete[1]}} *)
  • To mock, prepend HoldPattern[lhs] :> fakeValue instead. Always use HoldPattern and :>; guard recursion as shown.
  • For the stack when a function gets particular arguments, prepend a rule whose condition records the stack and fails,

`HoldPattern[otherFn[0]] /; (InternalStuffBag[bag, Stack[]]; False) :> Null`, and run the code as StackBegin[StackComplete[...]] (helper: WolframDebuggingStackAtCall[expr, otherFn[0]]``).

  • Some changes leak out of the block: ClearAll/Remove of the symbol wipes the outer definitions (use Clear or

DownValues[f] = {}), and Temporary or Locked set inside stay set (never set Locked in a shared kernel).

  • Calls made from kernel C code (Total, Sum, auto-compiled Table) and literal rules such as f[0] = 1 are not

seen. HTTP requests from URLRead, URLExecute and CloudGet all go through URLFetch.

Why does f[args] stay unevaluated?
wl
Keys @ DownValues[f] (* the rules, in the order they are tried *)
Flatten @ Position[Keys @ DownValues[f], lhs_ /; MatchQ[Unevaluated @ f[20.], lhs], {1}, Heads -> False]
(* which left-hand sides match (right-hand-side conditions are not checked) *)
{Context[f], Attributes[f]} (* wrong context? Hold attributes? *)
Select[Names["*`f"], ToExpression[#, InputForm, System`Private`HasAnyEvaluationsQ] &] (* shadowing contexts *)

This is the start of the file. Read the full SKILL.md on GitHub.

Security

  • Security scanPassed, 90 of 100Pattern checks on the skill's files.
  • Model reviewPassed

Quality evaluation

  • Task evaluationNot runNo evaluation yet. Run one in Skill Studio.

Source

Popularity

7-day trend score
0

Not refreshed yet.

Works with

Any agent vskill installs to: 56 targets in all. These 39 have a page on this site.

  • Claude Code
  • Cursor
  • GitHub Copilot
  • Windsurf
  • Codex
  • Gemini CLI
  • Cline
  • Amp
  • Roo Code
  • Goose
  • Continue
  • Kilo Code
  • Junie
  • Trae
  • OpenHands
  • Qwen Code
  • AI Agent
  • Tabnine Chat
  • Sourcegraph Cody
  • Amazon Q
  • Firebase Genkit
  • Sweep
  • Devin
  • Phind
  • Mentat
  • Claude Desktop
  • Aider
  • GPT Pilot
  • Plandex
  • bolt.new
  • v0
  • Replit Agent
  • Anse
  • TypingMind
  • BetterChatGPT
  • LibreChat
  • Warp AI
  • Pieces
  • Fig AI
Embed badge
vskill VERIFIED badge
[![vskill VERIFIED](https://verified-skill.com/api/v1/skills/wolframresearch/agenttools/wolfram-debugging/badge)](https://verified-skill.com/skills/wolframresearch/agenttools/wolfram-debugging)

Something wrong with this skill or its page? Tell us.