Keeper Stress Analysis
ClickHouse/ClickHouse
Analyze ClickHouse Keeper stress-test results from play.clickhouse.com / keeperstresstests data warehouse.
After answering a data question, write down what the answer assumed so the next reader can trust the number.
$ npx skills add malloydata/publisher --skill malloy-model-as-you-go -a claude-codeProject install by default; add -g for ~/.claude/skills/.
$ gh skill install malloydata/publisher malloy-model-as-you-go --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/malloydata/publisher.git skills-src && mkdir -p .claude/skills && cp -r skills-src/skills/malloy-model-as-you-go .claude/skills/malloy-model-as-you-go && 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 "malloy-model-as-you-go" agent skill from https://github.com/malloydata/publisher/tree/main/skills/malloy-model-as-you-go into .claude/skills/malloy-model-as-you-go/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "malloy-model-as-you-go", 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/malloydata/publisher/tree/main/skills/malloy-model-as-you-goType 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 malloydata/publisher --skill malloy-model-as-you-go -a codexProject install goes to .agents/skills/; add -g for ~/.codex/skills/.
$ gh skill install malloydata/publisher malloy-model-as-you-go --agent codexProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/malloydata/publisher.git skills-src && mkdir -p .agents/skills && cp -r skills-src/skills/malloy-model-as-you-go .agents/skills/malloy-model-as-you-go && rm -rf skills-srcUse ~/.agents/skills/ instead of .agents/skills for a personal install.
Codex skills documentation · loads skills from .agents/skills/
Install the "malloy-model-as-you-go" agent skill from https://github.com/malloydata/publisher/tree/main/skills/malloy-model-as-you-go into .agents/skills/malloy-model-as-you-go/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "malloy-model-as-you-go", 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 malloydata/publisher --skill malloy-model-as-you-go -a cursorProject install goes to .agents/skills/; add -g for ~/.cursor/skills/.
$ gh skill install malloydata/publisher malloy-model-as-you-go --agent cursorProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/malloydata/publisher.git skills-src && mkdir -p .cursor/skills && cp -r skills-src/skills/malloy-model-as-you-go .cursor/skills/malloy-model-as-you-go && 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 "malloy-model-as-you-go" agent skill from https://github.com/malloydata/publisher/tree/main/skills/malloy-model-as-you-go into .cursor/skills/malloy-model-as-you-go/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "malloy-model-as-you-go", 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/malloydata/publisher.git --path skills/malloy-model-as-you-go--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 malloydata/publisher --skill malloy-model-as-you-go -a gemini-cliProject install goes to .agents/skills/; add -g for ~/.gemini/skills/.
$ gh skill install malloydata/publisher malloy-model-as-you-go --agent gemini-cliProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/malloydata/publisher.git skills-src && mkdir -p .gemini/skills && cp -r skills-src/skills/malloy-model-as-you-go .gemini/skills/malloy-model-as-you-go && 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 "malloy-model-as-you-go" agent skill from https://github.com/malloydata/publisher/tree/main/skills/malloy-model-as-you-go into .gemini/skills/malloy-model-as-you-go/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "malloy-model-as-you-go", 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 malloydata/publisher malloy-model-as-you-goInstalls 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 malloydata/publisher --skill malloy-model-as-you-go -a github-copilotProject install goes to .agents/skills/; add -g for ~/.copilot/skills/.
$ git clone --depth 1 https://github.com/malloydata/publisher.git skills-src && mkdir -p .github/skills && cp -r skills-src/skills/malloy-model-as-you-go .github/skills/malloy-model-as-you-go && 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 "malloy-model-as-you-go" agent skill from https://github.com/malloydata/publisher/tree/main/skills/malloy-model-as-you-go into .github/skills/malloy-model-as-you-go/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "malloy-model-as-you-go", 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 malloydata/publisher --skill malloy-model-as-you-go -a opencodeOpenCode documents no install command of its own. Project install goes to .agents/skills/; add -g for ~/.config/opencode/skills/.
$ gh skill install malloydata/publisher malloy-model-as-you-go --agent opencodeProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/malloydata/publisher.git skills-src && mkdir -p .opencode/skills && cp -r skills-src/skills/malloy-model-as-you-go .opencode/skills/malloy-model-as-you-go && 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 "malloy-model-as-you-go" agent skill from https://github.com/malloydata/publisher/tree/main/skills/malloy-model-as-you-go into .opencode/skills/malloy-model-as-you-go/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "malloy-model-as-you-go", 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.
malloy-model-as-you-goAfter answering a data question, write down what the answer assumed so the next reader can trust the number.
Malloy Model As You Go is an agent skill from malloydata/publisher. After answering a data question, write down what the answer assumed so the next reader can trust the number. A field with a (doc) in the model when you can edit it, an extend in the notebook when you can only author reports, or a stated assumption plus a Malloy snippet when you can only chat. Use after every answered question that rested on a judgment call, and whenever a question is asked against tables that have no model yet.
Its SKILL.md is about 4.1k 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 Databases. The repository describes itself as: Publisher is the open-source analytics engine for Malloy. It lets you define data models once — and use them everywhere. The licence is MIT.
3 steps, taken from the step headings in SKILL.md.
Read from SKILL.md and the folder at commit c43a052. 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 malloy).
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.
Malloy Model As You Go loads about 4.1k tokens when it runs. Until then it costs about 114 tokens; SKILL.md has 2,185 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 malloydata/publisher at commit c43a052, republished under its MIT licence (© malloydata). 2,185 words, ~4,052 tokens.
.claude/skills/malloy-model-as-you-go/SKILL.md (or your agent's skills folder).<!--
Copyright (c) Credible Data Inc.
SPDX-License-Identifier: MIT
-->
An analysis that lives in a chat transcript is not reproducible. The numbers were right, and six weeks later nobody can say what "revenue" excluded, which of four timestamps was the order date, or whether the last period was complete. The work is unauditable, so it gets redone.
The fix is to write the assumptions down while the query is still in front of you, in the most durable place your session can write. Answer the question, codify what the answer assumed, answer the next one. After a handful of questions there is a model, or a notebook, where every definition exists because a real question needed it, and every judgment call is on the record.
This skill is the codify step. skill:malloy-analysis answers the question; this skill
decides what to write down afterwards, and where.
Tool names are bare here -
get_context,execute_query,search_database_schema. The exact prefixed name depends on the host; match against the tools you actually have.
QUESTION → ANSWER → CODIFY ⟲
↑___________|The user gets a real answer on question one. If three tool calls have gone by without producing an insight they can read, you have drifted into modelling for its own sake. Stop and answer something.
skill:malloy-analysisThis skill starts when someone asks a data question. That question is the unit of work, and it is theirs. Do not widen it into a modelling project, and do not swap it for a more interesting one you found on the way.
A broad ask is still an ask. "Analyse the sales data" is a question whose subject is given and whose metric is not. Pick the most obvious question about that subject, say in one line which one you picked, and answer it. Never open with a row-count table and a menu of "analytical domains"; the menu is worth less than the first real answer would have been.
Load skill:malloy-analysis and follow it: discover the model, construct the query, run it,
verify it, present it. Two of its rules matter most here:
limit: 15 table
by hand drops everything below the cut, and nobody can re-run it.skill:malloy-analysis (verify before trusting) before presenting.This is what makes the analysis auditable, and it is the step most easily skipped.
Almost every query needs at least one judgment call the data cannot settle. Which of four timestamps is "the order date". Whether returns count as revenue. Whether to count lines or orders. Whether a partial final period belongs in a trend.
A judgment call made silently becomes a hidden assumption. It will be wrong for someone eventually, and by then nobody remembers it was a choice rather than a fact. So make the call, run with it, and say what you chose and what you rejected, with the other number attached whenever it is cheap to get:
Revenue here excludes cancelled and returned orders - that's $8.10M. Counting returns as revenue and netting them separately gives $9.18M. I went with the stricter one; say if your reporting does it the other way.
Not every choice rises to this. Raise it when any of these holds:
| Raise it when | Because |
|---|---|
| The alternative changes the number materially | The user would answer differently depending on which they meant |
| You are about to codify it | It stops being your choice and becomes everyone's definition |
| A reasonable analyst would pick the other one | It is a convention, not a fact |
Otherwise state it in a clause and move on. Asking about everything is as bad as asking about nothing; it turns the loop into a form and trains the reader to skim past it. And give the number under each option, not an abstract question: "$8.10M excluding them, $9.18M including" lets the user answer in one word.
If the tables have no model, define only enough to run the first query. One line is normal:
source: order_items is my_conn.table('ecommerce.order_items')Read the columns with run: source -> { select: * limit: 3 }. Prefer it to a schema
listing: it returns the columns and real values, and the values are what catch the surprises
a column list hides - a date stored as a string, a total that excludes tax, a metric column
that is null on every row.
If a schema tool returns something you cannot explain (no columns, or no tables for a filter you can see matches), that is a bug in the tool. Report it. Do not write the workaround into your model or your notes as though it were a property of the data.
No primary_key:, no dimensions, no measures, no joins, not yet. Those arrive in CODIFY,
each one paid for by a question that needed it. Adding fields because the table has them is the
habit this skill exists to break.
Add a join only when this question cannot be answered without it, then verify its cardinality
before trusting any aggregate (group_by: fk, aggregate: n is count(), having: n > 1).
If a model already exists, ground yourself in it with get_context and reuse what is there.
Run this after every answered question, while the query is still in front of you. Skipping it is how a session ends with a transcript and nothing else.
The same assumption lands in a different place depending on the session. Pick the highest rung your tools allow, and never skip codifying because the top rung is out of reach.
| You can | Codify as | Who inherits it |
|---|---|---|
| Edit the model files (a local package, a draft package, a compile or reload tool) | A dimension:, measure:, join_*:, or view: with a #(doc), in the .malloy file | Everyone who queries the model. Confirm binding decisions first (below) |
| Author notebooks or reports, but not the model (a viewer of a published package) | In the notebook: source: orders_q is orders extend { measure: ... } with the #(doc) above it, plus a markdown cell stating the assumption. A question worth re-asking becomes a cell | Readers of the report. State the decision in the cell, and say which definitions the model should adopt |
| Only answer in chat (no file or report tools) | The assumption stated in the answer, plus the Malloy snippet a modeler could paste: the measure: with its #(doc) | Nobody, until someone acts on it. That is why the snippet matters |
Tell the rungs apart by the tools you have, not by guessing at the user's role: a file-write or compile tool means the top rung; a report or notebook tool without model edits means the middle one; neither means the bottom.
Look at the query you just ran. For each dimension, measure, join, filter, and for the shape of the query itself, ask in this order:
| Codify it when | Example |
|---|---|
| A reader needs it to trust the number | the cancelled/returned exclusion - without it every revenue figure reads high |
| It encodes a business rule | a regex parsing a messy column, a status mapping, tier cutoffs |
| Another question would reuse it | revenue is sum(sale_price) - everything about orders needs it |
| It was hard to get right | a window function, a multi-step derivation, a verified join |
The first row is the one that matters. A definition is worth keeping less because it saves typing than because it stops the next reader misreading the number.
Codify thin, and leave the ad-hoc behind: filters tied to one finding, calculations that answered exactly one question. A question that needed one measure codifies one measure, not the neighbouring columns as well. An empty CODIFY is a fine outcome; say so and move on.
Then say what you did, in one line, every time:
Codified:
revenue is sum(sale_price)excluding cancelled and returned,categoryvia the products join. Left ad-hoc: thewhere: created_at > @2023- just this question's window.
That line shows the model growing and gives the reader a place to object. Never codify silently.
While a judgment call lives in one ad-hoc query it is yours, and stating it is enough. Once it is in the model file it is the definition everyone inherits, and nobody downstream sees the reasoning. So on the top rung, stop, ask, and wait for an answer before writing it down. Reporting it afterwards ("I used the midpoint, say if you'd rather have the floor") is not confirming it; by then it is already the default. On the middle rung, confirm when the report will be shared; a private notebook is still yours.
This is not only about measures. Confirm anything that changes what later questions return:
| Confirm before codifying | Because it silently sets |
|---|---|
A source-level where: | the scope of every later question against that source |
A measure: definition | the default value of that metric for everyone |
A dimension: that buckets, maps, or parses | which rows land in which group |
A join_one:/join_many: and its grain | whether aggregates fan out |
A saved view: | the shape people will re-run and cite |
Ask with the numbers attached:
I want to make
net_revenueexclude cancelled and returned. That makes it the default revenue number for every later question - $8.10M rather than $10.81M gross. Good, or does your reporting treat returns differently?
One confirmation per decision, not per question. Once the user has settled how revenue treats returns, it is settled: reuse it and stop asking. And if the user has told you to stop checking in, believe them; state each decision in a clause and keep going.
In the model (or the notebook), as a #(doc) on the definition. This is the part that
survives. Use #(doc), never a // comment, for anything a consumer needs: #(doc) is
machine-readable, so it renders in the UI and retrieval tools read it, while a // comment
reaches nobody but whoever opens the file. Keep // for maintainer-only notes. Tag formats on
the definition too: bare # currency on the measure, any scale (# currency=usd0m) only in
views.
#(doc) Order line items joined to products. Grain is one row per line, not per order.
source: order_items is my_conn.table('ecommerce.order_items') extend {
join_one: products is my_conn.table('ecommerce.products') on product_id = products.id
dimension:
#(doc) Canonical order date. Data runs 2019-01-05 to 2026-03-14, so the final year is PARTIAL - never present it as a full period.
order_date is created_at::date
measure:
#(doc) Revenue in USD, excluding cancelled and returned orders. Those are 25% of gross, so excluding them is not optional.
# currency
net_revenue is sum(sale_price) { where: status != 'Cancelled' and status != 'Returned' }
#(doc) Monthly revenue trend. The question asked on 2026-03-02.
# line_chart
view: revenue_trend is {
group_by: order_month is order_date.month
aggregate:
# currency=usd0m
net_revenue
order_by: order_month
}
}One file per analytical domain, named for it: order_revenue.malloy, not model.malloy. It
grows monotonically across the session.
In a notes file, as the reasoning. Keep an analysis-notes.md beside the model (or a
markdown cell in the notebook) recording each question, what it found, what got codified and
what was left ad-hoc, and every verification finding. The model carries the what; the notes
carry the why and the evidence. It is also what lets you resume after losing context.
A saved view: turns "we answered that once" into "re-run it". A trend wanted again next
month belongs in the file as a view: with its chart tag (skill:malloy-charts); views wanted
side by side belong in a dashboard (malloy-dashboards, where your host has it), or in a notebook
(skill:malloy-notebooks) only when the user asks for one or one already exists. A genuine one-off does not.
This departs from
skill:malloy-modelon purpose. Its "no views in source files" rule assumes a schema-first model, written before anyone asked a question, so its views would be guesses. Here every view is a question that was asked and verified. Two more of its rules do not apply either: skip access modifiers and curation (there is no discovery surface to curate when every field was paid for by a question), and keep one domain file rather than one file per table until it genuinely gets unwieldy. Everything else inskill:malloy-modelapplies:#(doc)on every field, verified join cardinality,nullifon division, agiven:for a runtime parameter.
Go back to the question, and let what you just found sharpen the next one:
Revenue is concentrated in three categories. Worth asking whether that's new - want the same cut by year?
Docs are not on this list; they happen in CODIFY, as you go. When the user wants to hand it over:
#(doc) lines for anything that drifted as the model grew. Check
grain, units, and null handling are each stated somewhere.skill:malloy-model. Being shared is not itself a reason.| Situation | Go to |
|---|---|
| Porting prior art (LookML, dbt, a metrics doc): the definitions exist and are agreed, the job is translation | skill:malloy-lookml-review, then skill:malloy-model |
| The user names the sources they want built outright, before any question | skill:malloy-model |
| A model already exists, the question rests on no judgment call, and nothing is worth keeping | skill:malloy-analysis alone |
| Open-ended exploration with no intent to keep anything | skill:malloy-analysis (its "no specific question" branch) |
WRONG Turn "what's our default rate?" into a modelling project
RIGHT Answer it, then codify what the answer assumed
WRONG Propose every dimension and measure for each table in scope
RIGHT Codify the two fields this question actually needed
WRONG Quietly pick one of four timestamps as "the order date"
RIGHT "Using created_at; shipped_at would drop 38% as nulls. OK?"
WRONG Skip codifying because you cannot edit the model
RIGHT Put the extend and its #(doc) in the notebook, or hand over the snippet
WRONG Codify the source-level where:, then mention it in the write-up
RIGHT Stop and confirm it; it scopes every question anyone asks later
WRONG The assumption lives in the chat transcript, or in a // comment
RIGHT #(doc) on the definition for what a consumer needs, plus a line in the notes
WRONG Leave the answered question as a transcript table and move on
RIGHT Save it as a view; a question worth answering is usually worth re-asking
WRONG Curate access modifiers and split one file per table to "do it properly"
RIGHT Skip both; they solve a schema-first problem this model does not have© malloydata, MIT. 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 skills/malloy-model-as-you-go of malloydata/publisher.
Open the folder on GitHubat commit c43a052
Malloy Model As You Go 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 |
|---|---|---|---|---|---|---|
| Malloy Model As You Go this skillmalloydata/publisher | 116 | — | ~4.1k | Automated safety check: Pass | MIT | |
| Keeper Stress AnalysisClickHouse/ClickHouse | 50k | — | ~4.7k | Automated safety check: Pass | Apache-2.0 | |
| Perf ComparisonClickHouse/ClickHouse | 50k | — | ~3.9k | Automated safety check: Notes | Apache-2.0 | |
| Patch Release CheckClickHouse/ClickHouse | 50k | — | ~4k | Automated safety check: Notes | Apache-2.0 | |
| Evolving The Data ModelTriliumNext/Trilium | 38k | — | ~2.1k | Automated safety check: Pass | AGPL-3.0 | |
| Hybrid Cloud Outboxesgetsentry/sentry | 46k | — | ~4.8k | Automated safety check: Pass | Custom licence |
ClickHouse/ClickHouse
Analyze ClickHouse Keeper stress-test results from play.clickhouse.com / keeperstresstests data warehouse.
ClickHouse/ClickHouse
Evaluate ClickHouse performance test results from existing CI/dashboard data or local perf.py runs.
ClickHouse/ClickHouse
Check whether ClickHouse's supported versions (last 3 majors + latest LTS) have recent stable patch releases, diagnose why the scheduled AutoReleases pipeline failed, and identify which releases…
TriliumNext/Trilium
A skill your agent uses when adding a DB migration or a new column/field to a Becca entity in Trilium ("add a migration", "new column on notes/attributes", "ALTER TABLE", "add a field to…
getsentry/sentry
Guide for creating and maintaining outbox-based eventually consistent operations in Sentry.
microsoft/garnet
Selects Garnet spin-wait policies based on the slow-path cost.
malloydata/publisher
Score one analytical answer against a verified golden, and score which of the entities the golden depends on retrieval delivered to the answerer.
malloydata/publisher
Fix a CRITICAL Trivy finding that is failing CI in this repo (a vulnerability, misconfiguration, or secret from security-scan.yml or image-scan.yml), or add, review, or retire an entry in…
malloydata/publisher
Turn a list of questions into an eval set, whatever shape it arrived in: a JSONL a customer sent, a CSV, a spreadsheet export, a markdown doc, an email thread, or a pull from production logs.
malloydata/publisher
Conduct a local Publisher evaluation loop in five steps: scrape/run, eval, diagnose, improve, checkpoint.
malloydata/publisher
Make the smallest safe Malloy model edit that closes a diagnosed model-owned gap, with a probe receipt for every factual claim.
malloydata/publisher
Decide whether ONE answer matches its golden, and say whether you believe the golden.
Categories
After answering a data question, write down what the answer assumed so the next reader can trust the number. Malloy Model As You Go is an agent skill from malloydata/publisher. After answering a data question, write down what the answer assumed so the next reader can trust the number.
Malloy Model As You Go fits situations like: databases work in your project.
Run `npx skills add malloydata/publisher --skill malloy-model-as-you-go -a claude-code`. Or copy the skill folder (skills/malloy-model-as-you-go in malloydata/publisher) into .claude/skills/malloy-model-as-you-go in your project. Claude Code loads it when a task matches its description.
Run `npx skills add malloydata/publisher --skill malloy-model-as-you-go -a codex`. Or copy the skill folder (skills/malloy-model-as-you-go in malloydata/publisher) into .agents/skills/malloy-model-as-you-go 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 malloydata/publisher --skill malloy-model-as-you-go -a cursor` (or -a gemini-cli, github-copilot or opencode for the others). To copy it by hand, put the folder in .cursor/skills/malloy-model-as-you-go, .gemini/skills/malloy-model-as-you-go, .github/skills/malloy-model-as-you-go and .opencode/skills/malloy-model-as-you-go in your project.
SKILL.md names no scripts, command-line tools or credentials: Malloy Model As You Go 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.
Malloy Model As You Go is published under the MIT licence (the repository's licence). It allows redistribution, so the full SKILL.md is shown on this page.
About 4.1k tokens (SKILL.md is roughly 16k 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 Malloy Model As You Go: Keeper Stress Analysis (ClickHouse/ClickHouse, 50k stars), Perf Comparison (ClickHouse/ClickHouse, 50k stars), Patch Release Check (ClickHouse/ClickHouse, 50k stars) and Evolving The Data Model (TriliumNext/Trilium, 38k stars). The comparison table on this page puts their stars, adoption, token cost, safety result and licence side by side.
malloydata (a GitHub organization) maintains it in malloydata/publisher, which has 116 GitHub stars. The repository holds 29 skills in this directory. The repository was last updated on October 10, 2026.
Source: malloydata/publisher on GitHub. Facts on this page come from the repository at the commit we read; the author's words are quoted as theirs.