TDD Workflow
hellangleZ/burn-in-cceverywhere-ralph
A skill your agent uses when writing new features, fixing bugs, or refactoring code.
Add concise Base.show and Base.summary methods to Julia types whose default REPL representation is unhelpful or overwhelming.
$ npx skills add CliMA/EnsembleKalmanProcesses.jl --skill base-show -a claude-codeProject install by default; add -g for ~/.claude/skills/.
$ gh skill install CliMA/EnsembleKalmanProcesses.jl base-show --agent claude-codeProject scope by default; add --scope user for a personal install. Needs GitHub CLI 2.90.0 or later (public preview).
$ git clone --depth 1 https://github.com/CliMA/EnsembleKalmanProcesses.jl.git skills-src && mkdir -p .claude/skills && cp -r skills-src/.claude/skills/base-show .claude/skills/base-show && rm -rf skills-srcUse ~/.claude/skills/ instead of .claude/skills for a personal install. The folder must contain SKILL.md.
Claude Code skills documentation · loads skills from .claude/skills/
Install the "base-show" agent skill from https://github.com/CliMA/EnsembleKalmanProcesses.jl/tree/main/.claude/skills/base-show into .claude/skills/base-show/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "base-show", then confirm the skill loads.Claude Code copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$skill-installer install https://github.com/CliMA/EnsembleKalmanProcesses.jl/tree/main/.claude/skills/base-showType this inside Codex. $skill-installer <name> installs a curated skill from openai/skills. The installer writes to $CODEX_HOME/skills (default ~/.codex/skills). Restart Codex if the skill does not show up.
$ npx skills add CliMA/EnsembleKalmanProcesses.jl --skill base-show -a codexProject install goes to .agents/skills/; add -g for ~/.codex/skills/.
$ gh skill install CliMA/EnsembleKalmanProcesses.jl base-show --agent codexProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/CliMA/EnsembleKalmanProcesses.jl.git skills-src && mkdir -p .agents/skills && cp -r skills-src/.claude/skills/base-show .agents/skills/base-show && rm -rf skills-srcUse ~/.agents/skills/ instead of .agents/skills for a personal install.
Codex skills documentation · loads skills from .agents/skills/
Install the "base-show" agent skill from https://github.com/CliMA/EnsembleKalmanProcesses.jl/tree/main/.claude/skills/base-show into .agents/skills/base-show/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "base-show", then confirm the skill loads.Codex copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ npx skills add CliMA/EnsembleKalmanProcesses.jl --skill base-show -a cursorProject install goes to .agents/skills/; add -g for ~/.cursor/skills/.
$ gh skill install CliMA/EnsembleKalmanProcesses.jl base-show --agent cursorProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/CliMA/EnsembleKalmanProcesses.jl.git skills-src && mkdir -p .cursor/skills && cp -r skills-src/.claude/skills/base-show .cursor/skills/base-show && rm -rf skills-srcUse ~/.cursor/skills/ instead of .cursor/skills for a personal install.
Cursor skills documentation · loads skills from .cursor/skills/, .agents/skills/, .claude/skills/, .codex/skills/
Install the "base-show" agent skill from https://github.com/CliMA/EnsembleKalmanProcesses.jl/tree/main/.claude/skills/base-show into .cursor/skills/base-show/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "base-show", then confirm the skill loads.Cursor copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ gemini skills install https://github.com/CliMA/EnsembleKalmanProcesses.jl.git --path .claude/skills/base-show--scope user (default) or --scope workspace; --path is the subfolder of the repo that holds the skill; --consent skips the security confirmation prompt.
$ npx skills add CliMA/EnsembleKalmanProcesses.jl --skill base-show -a gemini-cliProject install goes to .agents/skills/; add -g for ~/.gemini/skills/.
$ gh skill install CliMA/EnsembleKalmanProcesses.jl base-show --agent gemini-cliProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/CliMA/EnsembleKalmanProcesses.jl.git skills-src && mkdir -p .gemini/skills && cp -r skills-src/.claude/skills/base-show .gemini/skills/base-show && rm -rf skills-srcUse ~/.gemini/skills/ instead of .gemini/skills for a personal install, then run /skills reload.
Gemini CLI skills documentation · loads skills from .gemini/skills/, .agents/skills/
Install the "base-show" agent skill from https://github.com/CliMA/EnsembleKalmanProcesses.jl/tree/main/.claude/skills/base-show into .gemini/skills/base-show/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "base-show", then confirm the skill loads.Gemini CLI copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ gh skill install CliMA/EnsembleKalmanProcesses.jl base-showInstalls for Copilot at project scope by default; add --scope user for a personal install. Preview a skill first with gh skill preview. Needs GitHub CLI 2.90.0 or later (public preview).
$ npx skills add CliMA/EnsembleKalmanProcesses.jl --skill base-show -a github-copilotProject install goes to .agents/skills/; add -g for ~/.copilot/skills/.
$ git clone --depth 1 https://github.com/CliMA/EnsembleKalmanProcesses.jl.git skills-src && mkdir -p .github/skills && cp -r skills-src/.claude/skills/base-show .github/skills/base-show && rm -rf skills-srcUse ~/.copilot/skills/ instead of .github/skills for a personal install. Commit .github/skills so cloud agent and code review can use it.
GitHub Copilot skills documentation · loads skills from .github/skills/, .claude/skills/, .agents/skills/
Install the "base-show" agent skill from https://github.com/CliMA/EnsembleKalmanProcesses.jl/tree/main/.claude/skills/base-show into .github/skills/base-show/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "base-show", then confirm the skill loads.GitHub Copilot copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ npx skills add CliMA/EnsembleKalmanProcesses.jl --skill base-show -a opencodeOpenCode documents no install command of its own. Project install goes to .agents/skills/; add -g for ~/.config/opencode/skills/.
$ gh skill install CliMA/EnsembleKalmanProcesses.jl base-show --agent opencodeProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/CliMA/EnsembleKalmanProcesses.jl.git skills-src && mkdir -p .opencode/skills && cp -r skills-src/.claude/skills/base-show .opencode/skills/base-show && rm -rf skills-srcUse ~/.config/opencode/skills/ instead of .opencode/skills for a personal install.
OpenCode skills documentation · loads skills from .opencode/skills/, .claude/skills/, .agents/skills/
Install the "base-show" agent skill from https://github.com/CliMA/EnsembleKalmanProcesses.jl/tree/main/.claude/skills/base-show into .opencode/skills/base-show/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "base-show", then confirm the skill loads.OpenCode copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
base-showAdd concise Base.show and Base.summary methods to Julia types whose default REPL representation is unhelpful or overwhelming.
Base Show is an agent skill from CliMA/EnsembleKalmanProcesses.jl. Add concise Base.show and Base.summary methods to Julia types whose default REPL representation is unhelpful or overwhelming. Use this skill whenever the user mentions that a type prints badly in the REPL, asks to improve how an object is displayed or printed, wants a custom show, summary, or repr for a Julia type, or says the REPL output is noisy, verbose, or hard to read. Also trigger when the user asks to "make the REPL output nicer", "add a show method", "add a summary method", "customize display", or "fix…
Its SKILL.md is about 5.2k tokens, which your agent loads only when the skill is triggered. It is a single SKILL.md file with no bundled scripts.
It sits in Testing & QA, covering Unit testing. The repository describes itself as: Derivative-free parameter calibration and uncertainty quantification for expensive models using ensemble Kalman methods. The licence is Apache-2.0.
7 steps, taken from the step headings in SKILL.md.
Read from SKILL.md and the folder at commit d10e521. It shows what the files ask for, not the result of running them.
Pre-approves nothing: there is no allowed-tools line, so your agent's usual permission prompts apply.
From allowed-tools in the SKILL.md frontmatter.
No scripts in the folder and no shell commands in SKILL.md (its code samples are julia).
From the folder's file list and the shell code blocks in SKILL.md.
No URLs in SKILL.md.
From URLs in SKILL.md, links to its own repository left out.
Names no API keys, tokens, secrets or passwords.
From names ending in _API_KEY, _TOKEN, _SECRET, _KEY or _PASSWORD in SKILL.md.
Base Show loads about 5.2k tokens when it runs. Until then it costs about 196 tokens; SKILL.md has 1,610 words of instructions outside code blocks.
Estimates: characters ÷ 4, the usual rule of thumb; real counts depend on the model's tokenizer. Scripts and assets cost tokens only if the agent reads them.
The automated check found no risky patterns in SKILL.md.
Automated static check — not a guarantee. Review scripts before installing. It scans the text of SKILL.md for risky patterns (piping downloads into a shell, reading credential files, hidden Unicode, destructive commands); files beside SKILL.md are not scanned.
The full file from CliMA/EnsembleKalmanProcesses.jl at commit d10e521, republished under its Apache-2.0 licence (© CliMA). 1,610 words, ~5,221 tokens.
.claude/skills/base-show/SKILL.md (or your agent's skills folder).Add concise Base.show(io::IO, ::MIME"text/plain", x::T) and Base.summary(io::IO, x::T) methods to Julia types whose default REPL representation is unhelpful or
overwhelming. Julia's default show dumps every field recursively; types that hold
DataFrames, large dictionaries, nested arrays, or many scalar fields produce screens
of unreadable text at the REPL.
Base.show(io, MIME"text/plain", x) must also handle the :compact IOContext key.
When Julia renders an object as an element inside a container (e.g. printing a
Vector{MyType}), it sets :compact => true on io. Without a compact branch the
full multi-line output is repeated for every element, producing an unreadable wall of
text. The compact branch must produce exactly one line (no newlines), giving the same
kind of at-a-glance hint as Base.summary.
This skill produces both methods and accompanying unit tests so that interactive use of the package is pleasant without losing key summary information.
Skip this step if you are adding show methods to types that have none. Apply it when the user asks to retrofit existing show methods — e.g. to add the compact branch to methods that were written before this protocol existed.
Find MIME methods that lack the compact branch:
grep -n 'MIME"text/plain"' src/show.jlFor each match, check whether the function body contains get(io, :compact. Any that
do not are candidates for retrofit.
Detect the old forwarding anti-pattern (infinite-recursion risk):
grep -nA2 'function Base\.show(io::IO, x::' src/ | grep 'show(io, MIME'If this matches, a 2-arg show(io, x) is calling the MIME method — the wrong
direction. Once the MIME method gains a compact branch that calls show(io, x), you
get infinite recursion. Flag every match and reverse the direction: the 2-arg method
becomes the compact one-liner, and the MIME method calls it via show(io, x) in its
compact branch.
Identify pre-existing bespoke 2-arg shows:
A bespoke 2-arg show is one that already exists but does not follow summary style —
for example, it may omit the type name entirely or use a different format. Check each
existing Base.show(io::IO, x::T) against its paired Base.summary. If the outputs
differ substantially, the 2-arg show is bespoke and needs a custom compact test (see
Step 4).
List every concrete (non-abstract) struct defined in the package source:
grep -nrE '^(mutable )?struct ' src/Exclude abstract type declarations — they cannot be instantiated and do not need
show methods.
For each concrete type, decide whether its default show output would be noisy. A type is noisy if it holds at least one of:
DataFrame or similar tabular collectionDict with potentially many entriesArrayAlso run:
grep -nrE 'Base\.(show|summary)' src/Skip any type that already has a custom Base.show or Base.summary method — do not
overwrite existing customization.
For each noisy type without existing methods, write both a Base.show and a
Base.summary method.
Base.show — always write two overloads together:
# 3-arg MIME method: full REPL display, with compact fallback
function Base.show(io::IO, ::MIME"text/plain", x::T)
if get(io, :compact, false)
show(io, x) # delegate to the 2-arg compact method
else
println(io, "T")
println(io, " field_name : ", summary_value)
# ...
end
end
# 2-arg method: single-line compact representation (no newline)
function Base.show(io::IO, x::T)
print(io, "T (key_hint)")
endThe 3-arg (MIME) non-compact branch must:
The 2-arg method (compact representation) must:
Base.summary style: type name followed by the most essential identifying hint
in parentheses — e.g. "T (N_ens=100, 5 iter)".Julia calls the 2-arg method when rendering elements inside containers (arrays, dicts,
etc.), passing io with :compact => true. The MIME method's compact branch delegates
to it so both paths produce the same single-line output.
Base.summary — single-line description used when the object appears inside a
container or is printed in a broader context (e.g., as an element of a Vector):
function Base.summary(io::IO, x::T)
print(io, "T (key_hint)")
endThe method must:
Good examples of what to put in the hint: "847 basins", "1000×365 grid",
"empty". Avoid repeating the type name verbatim as the only content — add value.
Placement: place both methods adjacent to their type definition in the same source
file, or gather all show/summary methods in a dedicated src/show.jl included from
the main module file. Follow whatever convention is already present in the package;
default to src/show.jl if no prior convention exists.
If creating src/show.jl, add include("show.jl") to the main module file after the
type definitions it references.
Write one test block per type, covering show (full and compact), and summary. Each
test block must:
sprint(show, MIME("text/plain"), instance) and
assert that it contains the type name and that line count does not exceed 10.out2 = sprint(show, instance) (2-arg) and assert it
contains the type name and has no '\n'. Also capture
out3 = sprint(show, MIME("text/plain"), instance; context=:compact => true) and
assert out2 == out3 — both compact paths must agree.summary: capture output with sprint(summary, instance) and assert that it
contains the type name and produces exactly one line (no '\n' in output).Bespoke 2-arg shows (retrofit case): Some types may already have a 2-arg show
that intentionally does not include the type name or follow summary style — the method
is doing something custom. Using a shared check_compact(x, typename) helper will
fail the typename assertion for these. Instead, write a hand-rolled compact test:
s2 = sprint(show, instance)
@test !occursin('\n', s2) # no newline
@test s2 == sprint(show, MIME("text/plain"), instance; context = :compact => true) # paths agreeAvoid asserting exact strings so that cosmetic changes to the output do not break tests.
Run the package test suite:
julia --project -e 'using Pkg; Pkg.test()'Confirm that all new tests pass and no pre-existing tests regress.
After the tests pass and the REPL output looks good, ask the user: "Would you like to improve the base-show skill itself using skill-creator? You can suggest changes to the workflow or quality criteria, or I can analyse what came up during this session to identify improvements to the skill."
Always define the 2-arg and 3-arg MIME overloads as a pair. The MIME method's compact branch calls the 2-arg method, so both display paths (REPL and in-container) converge on the same one-liner without repetition:
function Base.show(io::IO, ::MIME"text/plain", x::MyProcess)
if get(io, :compact, false)
show(io, x)
else
println(io, "MyProcess")
# ... full multi-line body ...
end
end
function Base.show(io::IO, x::MyProcess)
print(io, "MyProcess (", nameof(typeof(x.process)), ", N_ens=", x.N_ens, ")")
endWithout the 2-arg method, [ekp] in a Vector falls back to Julia's default field
dump. Without the compact branch in the MIME method, the same dump appears whenever
the object is embedded in a container that happens to call show(io, MIME"text/plain", x) with :compact => true.
When a type holds a variable-length collection, cap the loop to keep output bounded:
function Base.show(io::IO, ::MIME"text/plain", x::ParameterDistribution)
n = length(x.name)
println(io, "ParameterDistribution with ", n, " entr", n == 1 ? "y" : "ies")
max_show = 8
for i in 1:min(n, max_show)
println(io, " '", x.name[i], "': ", sprint(summary, x.distribution[i]))
end
n > max_show && println(io, " … and ", n - max_show, " more")
endOnly print a field when it carries information:
if !isnothing(x.prior_mean)
println(io, " prior_dim: ", length(x.prior_mean))
endMatch English grammar for counts that can be 0 or 1:
print(io, "Observation (", n, " block", n == 1 ? "" : "s", ", dim=", dim, ")")Use → in summary when the type represents a transformation between spaces:
print(io, "PairedDataContainer (", m_in, "×", n_in, " → ", m_out, "×", n_out, ")")Use × for matrix dimensions, → for transformations, ∞ for unbounded constraints,
and |u| for set sizes. These are rendered cleanly in all modern Julia terminals and
communicate mathematical meaning concisely.
# Constraint summary: Constraint{NoConstraint} (−∞, ∞)
lb = get(bounds, "lower_bound", "-∞")
ub = get(bounds, "upper_bound", "∞")
print(io, "Constraint{$(T)} ($(lb), $(ub))")When a type carries a type-parameter that identifies its variant, use nameof rather
than printing the full parameterised name:
# Sampler{Float64} (prior_dim=12) — not the raw Sampler{Float64, ...} dump
print(io, "Sampler{", nameof(get_sampler_type(x)), "} (prior_dim=", length(x.prior_mean), ")")When collecting all methods in a dedicated show.jl, organise by type family with
aligned comment rulers:
# ── DataContainers ────────────────────────────────────────────────────────────
# ── Observations ─────────────────────────────────────────────────────────────
# ── EnsembleKalmanProcess ────────────────────────────────────────────────────| Criterion | Priority | Definition |
|---|---|---|
| Coverage | High | Every type classified as noisy in Step 2 has a Base.show (both overloads) and a Base.summary method. |
| Compact support | High | The 3-arg MIME show checks get(io, :compact, false) and calls the 2-arg show(io, x) in the compact branch. The 2-arg method produces exactly one line with no newline. |
| Brevity — show | High | Full (non-compact) show output is at most 10 lines for any valid instance, including edge cases. |
| Brevity — summary | High | Summary output is exactly one line (no newlines) for any valid instance. |
| Safety | High | Neither method throws on any valid instance. |
| Allocation-safety | High | All data access is O(1): use length(), size(), isempty(), or first() on lazy iterators. Never call collect(), sort(), filter(), or any function that materialises a new collection. |
| Test robustness | Medium | Tests assert structural properties, not exact strings. Cosmetic changes do not break tests. |
| No regression | High | Pre-existing tests continue to pass; no unintended changes to other source files. |
Base.show(io::IO, ::MIME"text/plain", x::MyType)if get(io, :compact, false); show(io, x); else ... end.println(io, "TypeName"). Cheap size hints may follow on the same line.Base.show(io::IO, x::MyType)print call (no println), type name followed by a parenthesised hint matching Base.summary style, e.g. print(io, "MyType (847 basins)").Base.summary(io::IO, x::MyType)print call (no println), type name followed by a parenthesised hint, e.g. print(io, "MyType (847 basins)").length(), size(), isempty(), and first() on lazy iterators such as values(dict). Do not call collect(), sort(), or any function that copies a collection.sprint(show, MIME("text/plain"), x) to capture output without side effects.sprint(show, MIME("text/plain"), x; context=:compact => true) to exercise the compact branch, and sprint(show, x) to test the 2-arg method directly.sprint(summary, x) to capture the one-line description.# Scenario: a type wraps a parameter matrix and a forward-model output matrix.
# Before (default Julia show — prints the full matrix)
julia> pdc
PairedDataContainer{Float64}(inputs=DataContainer{Float64}(data=[...50×100 matrix...]),
outputs=DataContainer{Float64}(data=[...30×100 matrix...]))
# After — custom show (two overloads)
function Base.show(io::IO, ::MIME"text/plain", x::PairedDataContainer)
if get(io, :compact, false)
show(io, x)
else
m_in, n_in = size(x.inputs.data)
m_out, n_out = size(x.outputs.data)
println(io, "PairedDataContainer")
println(io, " inputs : ", m_in, " × ", n_in, " params × samples")
println(io, " outputs: ", m_out, " × ", n_out, " obs × samples")
end
end
function Base.show(io::IO, x::PairedDataContainer)
m_in, n_in = size(x.inputs.data)
m_out, n_out = size(x.outputs.data)
print(io, "PairedDataContainer (", m_in, "×", n_in, " → ", m_out, "×", n_out, ")")
end
# julia> pdc
# PairedDataContainer
# inputs : 50 × 100 params × samples
# outputs: 30 × 100 obs × samples
# julia> [pdc, pdc]
# 2-element Vector{PairedDataContainer{Float64}}:
# PairedDataContainer (50×100 → 30×100)
# PairedDataContainer (50×100 → 30×100)
# After — custom summary (arrow notation for a mapping type; matches 2-arg show)
function Base.summary(io::IO, x::PairedDataContainer)
m_in, n_in = size(x.inputs.data)
m_out, n_out = size(x.outputs.data)
print(io, "PairedDataContainer (", m_in, "×", n_in, " → ", m_out, "×", n_out, ")")
end# Scenario: a type holds N named parameter distributions; N can be large.
# Before (default Julia show — prints every distribution in full)
julia> prior
ParameterDistribution{Parameterized, Constraint{NoConstraint}, String}(
distribution=[Parameterized(Normal{Float64}(μ=0.0, σ=1.0)), ...],
constraint=[[Constraint{NoConstraint}(bounds=nothing)], ...],
name=["amplitude", "length_scale", "noise_var", ...])
# After — custom show (two overloads)
function Base.show(io::IO, ::MIME"text/plain", x::ParameterDistribution)
if get(io, :compact, false)
show(io, x)
else
n = length(x.name)
println(io, "ParameterDistribution with ", n, " entr", n == 1 ? "y" : "ies")
max_show = 8
for i in 1:min(n, max_show)
n_con = length(batch(x)[i])
println(io, " '", x.name[i], "': ", sprint(summary, x.distribution[i]),
" [", n_con, " constraint", n_con == 1 ? "" : "s", "]")
end
n > max_show && println(io, " … and ", n - max_show, " more")
end
end
function Base.show(io::IO, x::ParameterDistribution)
n = length(x.name)
print(io, "ParameterDistribution (", n, " entr", n == 1 ? "y" : "ies", ")")
end
# julia> prior
# ParameterDistribution with 3 entries
# 'amplitude' : Parameterized (Normal) [1 constraint]
# 'length_scale': Parameterized (LogNormal) [1 constraint]
# 'noise_var' : Parameterized (Uniform) [1 constraint]
# julia> [prior, prior]
# 2-element Vector{ParameterDistribution{...}}:
# ParameterDistribution (3 entries)
# ParameterDistribution (3 entries)
# After — summary (matches 2-arg show)
function Base.summary(io::IO, x::ParameterDistribution)
n = length(x.name)
print(io, "ParameterDistribution (", n, " entr", n == 1 ? "y" : "ies", ")")
end# Scenario: a mutable struct accumulates state across EKI iterations.
# Before (default Julia show — dumps every matrix stored in the struct)
julia> ekp
EnsembleKalmanProcess{Float64, ...}(u=[50×100 matrix, 50×100 matrix, ...],
g=[...], Δt=[0.5, 0.5], rng=MersenneTwister(...), N_ens=100, ...)
# After — custom show (two overloads)
function Base.show(io::IO, ::MIME"text/plain", x::EnsembleKalmanProcess)
if get(io, :compact, false)
show(io, x)
else
n_iter = length(x.u) - 1
n_par = size(x.u[1].data, 1)
println(io, "EnsembleKalmanProcess")
println(io, " process : ", nameof(typeof(x.process)))
println(io, " N_ens : ", x.N_ens)
println(io, " N_par : ", n_par)
println(io, " n_iter : ", n_iter)
println(io, " scheduler : ", nameof(typeof(x.scheduler)))
println(io, " accelerator: ", nameof(typeof(x.accelerator)))
end
end
function Base.show(io::IO, x::EnsembleKalmanProcess)
n_iter = length(x.u) - 1
print(io, "EnsembleKalmanProcess (", nameof(typeof(x.process)),
", N_ens=", x.N_ens, ", ", n_iter, " iter)")
end
# julia> ekp
# EnsembleKalmanProcess
# process : Inversion
# N_ens : 100
# N_par : 50
# n_iter : 5
# scheduler : DefaultScheduler
# accelerator: DefaultAccelerator
# julia> [ekp, ekp]
# 2-element Vector{EnsembleKalmanProcess{...}}:
# EnsembleKalmanProcess (Inversion, N_ens=100, 5 iter)
# EnsembleKalmanProcess (Inversion, N_ens=100, 5 iter)
# After — summary (matches 2-arg show)
function Base.summary(io::IO, x::EnsembleKalmanProcess)
n_iter = length(x.u) - 1
print(io, "EnsembleKalmanProcess (", nameof(typeof(x.process)),
", N_ens=", x.N_ens, ", ", n_iter, " iter)")
end@testset "PairedDataContainer show" begin
pdc = PairedDataContainer(rand(50, 100), rand(30, 100))
out = sprint(show, MIME("text/plain"), pdc)
@test occursin("PairedDataContainer", out)
@test count(==('\n'), out) <= 10
end
@testset "PairedDataContainer show compact" begin
pdc = PairedDataContainer(rand(50, 100), rand(30, 100))
# exercise via the 2-arg method directly
out2 = sprint(show, pdc)
@test occursin("PairedDataContainer", out2)
@test !occursin('\n', out2)
# exercise via the MIME method with compact context
out3 = sprint(show, MIME("text/plain"), pdc; context=:compact => true)
@test out2 == out3 # both paths must agree
end
@testset "PairedDataContainer summary" begin
pdc = PairedDataContainer(rand(50, 100), rand(30, 100))
out = sprint(summary, pdc)
@test occursin("PairedDataContainer", out)
@test !occursin('\n', out) # must be exactly one line
end© CliMA, Apache-2.0. Rendered from Markdown: HTML in the file is shown as text, images as links, and headings moved down two levels. Raw file
Just SKILL.md in .claude/skills/base-show of CliMA/EnsembleKalmanProcesses.jl.
Open the folder on GitHubat commit d10e521
Base Show next to the 5 skills that share the most tags, products or categories with it. Stars are the repository's; “used in” counts other GitHub owners with a copy.
| Skill | Stars | Used in | Tokens | Auto-check | Licence | Repo updated |
|---|---|---|---|---|---|---|
| Base Show this skillCliMA/EnsembleKalmanProcesses.jl | 127 | — | ~5.2k | Automated safety check: Pass | Apache-2.0 | |
| TDD WorkflowhellangleZ/burn-in-cceverywhere-ralph | 112 | 11 repos | ~2.4k | Automated safety check: Pass | None | |
| Testing OpenLogi UIAprilNEA/OpenLogi | 23k | — | ~1.1k | Automated safety check: Pass | Apache-2.0 | |
| Go Testingcxuu/golang-skills | 170 | 1 repos | ~1.3k | Automated safety check: Pass | Apache-2.0 | |
| Contractssamchon/nestia | 2.2k | — | ~1.3k | Automated safety check: Pass | MIT | |
| Cohesion Over TestabilityEpicenterHQ/epicenter | 4.8k | — | ~2k | Automated safety check: Pass | Custom licence |
hellangleZ/burn-in-cceverywhere-ralph
A skill your agent uses when writing new features, fixing bugs, or refactoring code.
AprilNEA/OpenLogi
Verifies OpenLogi's native GPUI interface with focused tests, the component gallery and a mock agent, choosing the evidence that fits each change.
cxuu/golang-skills
A skill your agent uses when writing, reviewing, or improving Go test code — including table-driven tests, subtests, parallel tests, test helpers, test doubles, and assertions with cmp.Diff.
samchon/nestia
Defines self-acknowledgments for production declarations and tests.
EpicenterHQ/epicenter
Collapse test-shaped production boundaries while preserving behavior and coverage.
liaohch3/claude-tap
Tests JavaScript embedded in an HTML file in two layers: pytest checks of the logic ported to Python, and Playwright runs in a real browser for the DOM.
CliMA/EnsembleKalmanProcesses.jl
Scaffold and maintain a SLURM/HPC job-dependency tree for an EnsembleKalmanProcesses.jl (EKP) calibration pipeline.
CliMA/EnsembleKalmanProcesses.jl
Run an adversarial mathematical-accuracy review of a Julia package's src/ and test/ directories, producing a dated markdown report plus concise, self-contained fix-prompt markdowns suitable for…
CliMA/EnsembleKalmanProcesses.jl
Add or normalise Julia docstrings on public symbols (exported types, functions, and constants) so the package's public API is fully self-documenting and the Documenter.jl docs build passes its…
CliMA/EnsembleKalmanProcesses.jl
Rewrite vague, delayed, or low-context Julia error messages into structured, actionable diagnostics.
Categories
Add concise Base.show and Base.summary methods to Julia types whose default REPL representation is unhelpful or overwhelming. jl.summary methods to Julia types whose default REPL representation is unhelpful or overwhelming.
Base Show fits situations like: the user mentions that a type prints badly in the REPL; asks to improve how an object is displayed; wants a custom show; repr for a Julia type.
Run `npx skills add CliMA/EnsembleKalmanProcesses.jl --skill base-show -a claude-code`. Or copy the skill folder (.claude/skills/base-show in CliMA/EnsembleKalmanProcesses.jl) into .claude/skills/base-show in your project. Claude Code loads it when a task matches its description.
Run `npx skills add CliMA/EnsembleKalmanProcesses.jl --skill base-show -a codex`. Or copy the skill folder (.claude/skills/base-show in CliMA/EnsembleKalmanProcesses.jl) into .agents/skills/base-show in your project. Codex loads it when a task matches its description.
Cursor, Gemini CLI, GitHub Copilot and OpenCode also load SKILL.md folders. With the skills CLI, run `npx skills add CliMA/EnsembleKalmanProcesses.jl --skill base-show -a cursor` (or -a gemini-cli, github-copilot or opencode for the others). To copy it by hand, put the folder in .cursor/skills/base-show, .gemini/skills/base-show, .github/skills/base-show and .opencode/skills/base-show in your project.
SKILL.md names no scripts, command-line tools or credentials: Base Show is instructions for the agent only.
SKILL.md contains no URLs. Any network use would come from the scripts or tools the agent runs. This is read from the text; nothing was executed.
Our automated static check of SKILL.md found no risky patterns, such as piping downloads into a shell, reading credential files or hidden Unicode. It is not a guarantee. Review the folder before installing.
Base Show is published under the Apache-2.0 licence (the repository's licence). It allows redistribution, so the full SKILL.md is shown on this page.
About 5.2k tokens (SKILL.md is roughly 21k characters). Agents keep only the skill's name and description in context until a task matches; then they load SKILL.md in full.
Skills that share tags, products or a category with Base Show: TDD Workflow (hellangleZ/burn-in-cceverywhere-ralph, 112 stars), Testing OpenLogi UI (AprilNEA/OpenLogi, 23k stars), Go Testing (cxuu/golang-skills, 170 stars) and Contracts (samchon/nestia, 2.2k stars). The comparison table on this page puts their stars, adoption, token cost, safety result and licence side by side.
CliMA (a GitHub organization) maintains it in CliMA/EnsembleKalmanProcesses.jl, which has 127 GitHub stars. The repository holds 5 skills in this directory. The repository was last updated on October 7, 2026.
Source: CliMA/EnsembleKalmanProcesses.jl on GitHub. Facts on this page come from the repository at the commit we read; the author's words are quoted as theirs.