Shoddy Documentation

Setup

Install the runtime, install the extension. Two steps, once per machine, on Windows, macOS or Linux.

The packaged extension carries its own mill — the program that compiles and runs Shoddy — and the whole machine library. So there is nothing to clone, nothing to build, and nothing to configure. Follow Track A and you are writing Shoddy in a few minutes. Track B builds the mill from source instead. Take it only if you want to work on Shoddy itself, or want the mill on your command line without VS Code.

Which track? If you want to write programs in Shoddy, Track A is the whole story. If you want to change the language, you want Track B — and the Toolchain page after it.
WHY

Why this works: how Include finds machines/

A program folder should never need its own copy of machines/. When your program says Include "seq.shoddy" — a bare filename, no path — the mill looks in three places, in order:

  1. beside the including file, so a program’s own pieces always win;
  2. the directory named by SHODDYLIB, if you have set one. SHODDYLIB is an environment variable — a named setting your operating system hands to every program it starts;
  3. the machine library shipped with the mill that is running — machines/ beside the executable, then one level up beside its bin/.

That third rule is why nothing needs configuring. The mill inside the extension finds the machines staged beside it. A mill you build yourself finds the repo’s machines/ from bin/. Both work from any folder on disk, with no environment variables set at all.

You normally never set SHODDYLIB. Set it only if you keep several checkouts — separate copies of the repository — and want a program pinned to one of them. It is no longer part of installing Shoddy. If you do set one, the editor steps aside and lets it win.

Track A — install the extension

A1

Install the .NET 10 runtime

The mill is a .NET program, so it needs the .NET runtime — the support package that lets .NET programs run. It needs the runtime, not the much larger SDK, which is the full developer kit. Check first with dotnet --list-runtimes. If nothing at version 10 appears, install from dotnet.microsoft.com, or:

Windows
winget install Microsoft.DotNet.Runtime.10
macOS
brew install --cask dotnet-runtime
A2

Install the extension

Download the latest .vsix from the latest release, then in VS Code: Extensions view → the ··· menu → Install from VSIX… → pick the file you downloaded. Reload when prompted.

Watch outWindows may warn you about this download, because it is not from a registered publisher. That is expected. The package is not code-signed — it carries no certificate naming its publisher — so Windows SmartScreen (Windows’ built-in warning about unrecognized downloads) or a strict company security policy may object to it. Instead, the release publishes a SHA-256 checksum — a short fingerprint of the file’s exact contents — so you can verify the download yourself. Nothing here phones home, meaning nothing sends data anywhere: the mill is a local compiler.

The release page also carries sparky — the calculator packaged as an MCP server, a plug-in that lets an AI assistant use the calculator. It is a separate, self-contained download. It needs neither this extension nor the runtime. The sparky page has the per-client registration shapes — the snippet each assistant client needs.

A3

Smoke-test it

Use a scratch folder anywhere on disk — any throwaway folder will do. That is the real test, because it proves a program folder needs nothing of its own:

  1. Create check.shoddy:
    Include "stats.shoddy"
    
    Def Main()
        Print(Sum({ 1, 2, 3 }))
  2. Open the folder in VS Code and press the ▶ Run button (or ctrl+r) — expect 6.
  3. Press F5 on the same file: the perch — Shoddy’s debugger — stops on the first line. That proves the debugger half of the chain too. The VS Code page is the tour.

If step 2 reports unknown word: Sum or cannot open the include, see Troubleshooting below.

Track B — build from source

Track B is for working on the language, the mill, or the machines — and for having mill on your command line. Everything here replaces Track A’s A1–A2; it is not in addition to them. A mill you build yourself takes precedence over the extension’s bundled copy whenever the repo is your open workspace.

B1

Install the .NET 10 SDK

Check with dotnet --version. If it’s missing or older than 10, install from dotnet.microsoft.com/download, or:

Windows
winget install Microsoft.DotNet.SDK.10
macOS
brew install dotnet-sdk
B2

Clone and build the mill

The mill is not committed to the repository, so you build it yourself from the repo root. The verify run should print HELLO FROM SHODDY and a run of worked examples. (What the wrapper actually runs, and why it’s a folder publish, is on the Toolchain page.)

Windows
git clone https://github.com/shoddymills/shoddy
cd shoddy
.\build.ps1 build
bin\mill.exe run tst\examples.shoddy
macOS
git clone https://github.com/shoddymills/shoddy
cd shoddy
./build.sh build
bin/mill run tst/examples.shoddy

That is the whole setup. bin/mill finds the repo’s machines/ one level up on its own, so bare includes work immediately with nothing set. ./build.ps1 machines (./build.sh machines) compiles the library to machine DLLs up front. You can skip that: a machine is always used compiled, so the mill builds any machine you use that is missing one anyway.

B3

Put mill on your PATH Optional

This step only lets you type mill instead of the full path to bin/mill. PATH is the list of folders your terminal searches when you type a command.

Windows

System Properties → Environment Variables, and append C:\github\shoddy\bin to your user Path (safer than setx, which rewrites the whole value).

macOS
echo 'export PATH="$HOME/github/shoddy/bin:$PATH"' >> ~/.zshrc
Watch outOpen a new terminal afterward (or source ~/.zshrc). A terminal copies the environment variables once, when it launches, so terminals that are already open never see the change.
FIX

Troubleshooting

Machine-level symptoms — the ones that come from installs and paths, not from your program. Editor-side symptoms (F5 fails but ▶ works, millPath) are in the VS Code page’s table.

SymptomLikely cause
“The framework Microsoft.NETCore.App version 10 was not found” The .NET 10 runtime isn’t installed (step A1), or the terminal predates the install — open a new one
unknown word: Sum (or any library word), or “cannot open” on an Include A SHODDYLIB left over from an older install is pointing at a directory that no longer holds the machines — clear it, or point it at a real machines/ folder. With it unset, the mill finds its own
dotnet not recognized Neither runtime nor SDK is installed, or the terminal predates the install
mill not recognized (Track B) PATH doesn’t include the repo’s bin, the terminal predates the change, or the mill was never built (step B2)
macOS: works in one terminal but not another The export went into a profile that shell doesn’t read — keep it in ~/.zshrc (or ~/.zprofile for login shells)

Next: the VS Code page — the Run button, the perch, and the tasks. Going deeper: the Toolchain page is the command-line reference; the Beginner’s Guide is the door into the language itself.