From flatppl
Write, port, review, fix, or troubleshoot FlatPPL probabilistic models (.flatppl files) — priors, likelihoods, and the measure pipeline (lawof / kernelof / likelihoodof / bayesupdate / restrict) — grounding every construct in the public FlatPPL spec. Use when the user wants to write, draft, port (from Stan/PyMC/Turing), review, or fix a FlatPPL model or .flatppl file, check whether a model uses valid FlatPPL constructs, or troubleshoot a model that errors, fails to assemble, or produces wrong or suspect output.
How this skill is triggered — by the user, by Claude, or both
Slash command
/flatppl:flatppl-modelThe summary Claude sees in its skill listing — used to decide when to auto-load this skill
FlatPPL is a **flat, loop-free, vectorized** probabilistic language. It is new and
FlatPPL is a flat, loop-free, vectorized probabilistic language. It is new and not in your training set; your priors about its syntax are likely wrong. The one rule that prevents most errors: copy the shape of a worked example, and verify every construct against the spec — never write from memory.
The syntax in this skill (token names like iid, invlogit, Cauchy,
nonnegreals, normalize, truncate, functionof, the %%% fence) is illustrative
shape, not a token reference — it shows the form a model takes, not a guarantee the
exact spelling is current. Confirm distribution names, set names, and builtins against
the spec before emitting them. A token copied from here while believing it is grounded
is worse than a clean gap.
The spec is one public web document:
https://flatppl.github.io/flatppl-design/flatppl-design.md
Obtain the spec once, then grep it. Download the roughly 40,000-word document to a
session-local file and read it with grep/Read — exact verbatim text across the whole
document, with fast repeat lookups. Guard on existence so a session downloads at most once
(the file is the cache; never re-download one already present):
[ -f /tmp/flatppl-design.md ] || curl -fsSL https://flatppl.github.io/flatppl-design/flatppl-design.md -o /tmp/flatppl-design.md
Then grep -n '{#sec:' /tmp/flatppl-design.md to map sections to lines, or
grep -n '<construct>' to jump to a builtin. Cite section headings, not line
numbers — and only an anchor you actually grepped; never invent a plausible-looking
{#sec:...}. Show only spec-copied code as grounded; label any illustrative snippet as
illustrative. If Bash/curl/network is unavailable, fall back to the flatppl-docs skill or
WebFetch directly with narrow single-topic prompts. For general "what does X mean"
questions, or to explain what an existing model does (read-only), use
flatppl-docs. This skill writes, reviews, fixes, and troubleshoots a .flatppl
model.
grep -n '{#sec:' /tmp/flatppl-design.md to find the "Worked examples"
section, then Read it and study the 2–3 models closest to what you're building.
Copy their shape; don't assume a specific example (e.g. "eight-schools") exists —
read whichever models the section actually contains.grep the local file, or
via flatppl-docs) — don't guess. For which section a construct lives in and a
name-level index of what exists (distributions, sets, functions, measure operators),
see references/spec-reference.md, loaded on demand. A
function absent from "Functions and deterministic operations" may still be a valid
standard-module builtin — check both before rejecting it. If the spec doesn't cover it,
say so — don't invent..+, f.(x)), reductions, iid(dist, n), and ifelse(cond, a, b)
for piecewise — never a for/if statement.eta = alpha .+ X * beta, p = invlogit.(eta),
y ~ Bernoulli.(p) — broadcast over data, don't iterate.~; deterministic transforms use =. Prefer modeling
each variate as a stochastic node; measure-composition operators are allowed but
must be justified when stochastic nodes can't express the model (→ Conventions).a = elementof(nonnegreals), mu = elementof(reals). (b) Truncate a distribution:
truncate(Cauchy(0,5), interval(0, inf)) restricts support; wrap in normalize(...)
to renormalize back to a proper measure for a prior —
tau ~ normalize(truncate(Cauchy(0,5), interval(0, inf))).functionof. f = functionof(b) then f(x) —
when a plain builtin isn't enough.# is a plain line comment (### … ### block); % and %%% … %%% are
doc-comments that attach to the following binding and survive into FlatPIR. Lead
non-trivial files with a %%% … %%% doc fence (markdown + LaTeX) — the block-doc-comment
form in "Syntax" → Documentation.A model ends by assembling measures explicitly. Two common shapes:
% explicit prior + kernel + likelihood + update
prior = lawof(record(alpha = alpha, beta = beta))
forward_kernel = kernelof(record(y = y), alpha = alpha, beta = beta)
L = likelihoodof(forward_kernel, record(y = y_data))
posterior = bayesupdate(L, prior)
% joint law + condition on data
joint_model = lawof(record(mu = mu, tau = tau, theta = theta, y = y))
posterior = restrict(joint_model, y = y_data)
Which shape: use bayesupdate(likelihoodof(kernelof(...)), prior) when you have
an explicit prior, a forward kernel, and observed data (regression idiom). Use
restrict(lawof(...), data) when you build one joint law and condition on data.
restrict accepts both restrict(M, record(y = y_data)) and the keyword form
restrict(M, y = y_data) (auto-splatting); they are equivalent. Verify exact builder
names and behavior in "Measure algebra" / "Likelihoods and posteriors" if unsure.
~ / draw stochastic nodes
(Stan/Pyro-style), and measure algebra (joint, jointchain, kchain, pushfwd,
weighted). Model every variate as a stochastic node (x ~ Dist(...)); reach for
measure-composition operators only when stochastic nodes genuinely can't express the
model — and when you do, justify the choice to the user. (The final posterior
assembly — lawof / kernelof / likelihoodof / bayesupdate / restrict — is
not measure-composition modeling; keep using it as shown above.).flatppl files with a %%% … %%% doc fence._data suffix for observed values (y_data) so the
model variable (y) stays the modeled variate.There is no FlatPPL engine to run a model through today, so you cannot execute it and see output. Spec-grounding proves a model has no spec violations; it does not prove it computes the density you intended — parameterization and shape errors live in that gap. Before declaring a model done (writing) or sound (reviewing), climb this ladder; do the cheap rungs always, reach for the oracle when the model is non-trivial:
~ RHS must be a
drawable probability measure (an unnormalized truncate/weighted/sub-measure is not).iid).normalized.08-distributions.md arg names) and confirm they're the same
function. Catches sd-vs-variance, rate-vs-scale, df-only-vs-location-scale.venv works anywhere Python does and assumes
nothing — reach for uv/pixi only if the user already has them), install the minimum
quietly, run a tiny check, and delete it (leave no trace) once they confirm their
question is answered. Never install silently or assume a
stack — and NEVER install into a global / system / existing environment; installs go
only into a fresh isolated venv you delete after. If you can't isolate, don't install.
The only rung that gives positive numerical evidence. Keep it light. Opt-in venv
protocol: references/confidence-without-an-engine.md.State which rungs you climbed — "4-point SciPy oracle matched" is evidence; "looks right"
is not. A clean parse proves syntax only, never correctness. Full ladder, oracle recipes,
and the parameterization trap list: references/confidence-without-an-engine.md.
Walk the Hard invariants (no excluded constructs; ~ vs =; support constrained
correctly; broadcasting not implied loops), then add: (a) the measure pipeline
assembles a valid posterior in one of the two shapes above; (b) every
distribution/function exists in "Distributions"/"Functions"/"Standard modules"; (c)
variates are stochastic nodes, not measure-composition operators (→ Conventions) —
flag any unjustified joint/jointchain/kchain/pushfwd/weighted in the body.
When a model errors, fails to assemble, or produces wrong/suspect output, diagnose
before editing. A symptom → likely-cause → spec-section catalog is in
references/diagnostics.md (load on demand) — consult it when
a failure doesn't obviously map to a Hard invariant. The method:
if,
a ~-vs-= mixup, unconstrained support (negative scale, improper prior), or a
broadcast that silently does the wrong thing.grep that construct in
the spec — wrong arity, wrong argument type, or a name that isn't a real builtin is the
usual cause. For a numeric/semantic surprise (NaN density, mass in the wrong place),
check the measure pipeline: is support constrained, is a truncated prior renormalized,
does the likelihood condition on the right variate?If the failure is in an engine (a density/sample number that looks wrong, or two engines disagreeing) rather than the model itself, that is beyond a general modeling fix — say so plainly; it's an engine-debugging task, not a model change.
When writing: deliver the .flatppl model and quote the example or spec section
heading you relied on for any non-obvious choice. When reviewing: one finding per
issue — the construct, the invariant or shape it breaks, and the example or spec
section heading that contradicts it; lead with hard-invariant violations. When
troubleshooting: state the diagnosis (what is wrong and why), the minimal fix, and
the spec/example that backs it; if you could not reproduce or explain the failure, say so
rather than guessing. If the model is sound, say so and list what you checked.
Provides behavioral guidelines to reduce common LLM coding mistakes, focusing on simplicity, surgical changes, assumption surfacing, and verifiable success criteria.
Searches, retrieves, and installs Agent Skills from prompts.chat registry using MCP tools like search_skills and get_skill. Activates for finding skills, browsing catalogs, or extending Claude.
Creates, edits, and optimizes skills for Claude Code, including drafting, evaluating with test prompts, iterating on performance, and improving skill descriptions for better triggering accuracy.
npx claudepluginhub flatppl/flatppl-ai-skills --plugin flatppl