Channel Plugin Duplicate Socket
Szotasz/marveen
Marveen flottában új channel plugin (slack-channel, telegram, stb.) telepítésekor a user-szintű ~/.claude/settings.json enabledPlugins minden agent-nek loadolja a plugin server-t, és ha az egy…
Draft answers for OWID's draft-data-update-slack-post Slack template using snapshot DVC + garden metadata + staging DB queries.
$ npx skills add owid/etl --skill draft-data-update-slack-post -a claude-codeProject install by default; add -g for ~/.claude/skills/.
$ gh skill install owid/etl draft-data-update-slack-post --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/owid/etl.git skills-src && mkdir -p .claude/skills && cp -r skills-src/.claude/skills/draft-data-update-slack-post .claude/skills/draft-data-update-slack-post && 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 "draft-data-update-slack-post" agent skill from https://github.com/owid/etl/tree/master/.claude/skills/draft-data-update-slack-post into .claude/skills/draft-data-update-slack-post/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "draft-data-update-slack-post", 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/owid/etl/tree/master/.claude/skills/draft-data-update-slack-postType 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 owid/etl --skill draft-data-update-slack-post -a codexProject install goes to .agents/skills/; add -g for ~/.codex/skills/.
$ gh skill install owid/etl draft-data-update-slack-post --agent codexProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/owid/etl.git skills-src && mkdir -p .agents/skills && cp -r skills-src/.claude/skills/draft-data-update-slack-post .agents/skills/draft-data-update-slack-post && rm -rf skills-srcUse ~/.agents/skills/ instead of .agents/skills for a personal install.
Codex skills documentation · loads skills from .agents/skills/
Install the "draft-data-update-slack-post" agent skill from https://github.com/owid/etl/tree/master/.claude/skills/draft-data-update-slack-post into .agents/skills/draft-data-update-slack-post/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "draft-data-update-slack-post", 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 owid/etl --skill draft-data-update-slack-post -a cursorProject install goes to .agents/skills/; add -g for ~/.cursor/skills/.
$ gh skill install owid/etl draft-data-update-slack-post --agent cursorProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/owid/etl.git skills-src && mkdir -p .cursor/skills && cp -r skills-src/.claude/skills/draft-data-update-slack-post .cursor/skills/draft-data-update-slack-post && 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 "draft-data-update-slack-post" agent skill from https://github.com/owid/etl/tree/master/.claude/skills/draft-data-update-slack-post into .cursor/skills/draft-data-update-slack-post/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "draft-data-update-slack-post", 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/owid/etl.git --path .claude/skills/draft-data-update-slack-post--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 owid/etl --skill draft-data-update-slack-post -a gemini-cliProject install goes to .agents/skills/; add -g for ~/.gemini/skills/.
$ gh skill install owid/etl draft-data-update-slack-post --agent gemini-cliProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/owid/etl.git skills-src && mkdir -p .gemini/skills && cp -r skills-src/.claude/skills/draft-data-update-slack-post .gemini/skills/draft-data-update-slack-post && 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 "draft-data-update-slack-post" agent skill from https://github.com/owid/etl/tree/master/.claude/skills/draft-data-update-slack-post into .gemini/skills/draft-data-update-slack-post/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "draft-data-update-slack-post", 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 owid/etl draft-data-update-slack-postInstalls 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 owid/etl --skill draft-data-update-slack-post -a github-copilotProject install goes to .agents/skills/; add -g for ~/.copilot/skills/.
$ git clone --depth 1 https://github.com/owid/etl.git skills-src && mkdir -p .github/skills && cp -r skills-src/.claude/skills/draft-data-update-slack-post .github/skills/draft-data-update-slack-post && 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 "draft-data-update-slack-post" agent skill from https://github.com/owid/etl/tree/master/.claude/skills/draft-data-update-slack-post into .github/skills/draft-data-update-slack-post/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "draft-data-update-slack-post", 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 owid/etl --skill draft-data-update-slack-post -a opencodeOpenCode documents no install command of its own. Project install goes to .agents/skills/; add -g for ~/.config/opencode/skills/.
$ gh skill install owid/etl draft-data-update-slack-post --agent opencodeProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/owid/etl.git skills-src && mkdir -p .opencode/skills && cp -r skills-src/.claude/skills/draft-data-update-slack-post .opencode/skills/draft-data-update-slack-post && 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 "draft-data-update-slack-post" agent skill from https://github.com/owid/etl/tree/master/.claude/skills/draft-data-update-slack-post into .opencode/skills/draft-data-update-slack-post/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "draft-data-update-slack-post", 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.
draft-data-update-slack-postDraft answers for OWID's draft-data-update-slack-post Slack template using snapshot DVC + garden metadata + staging DB queries.
Draft Data Update Slack Post is an agent skill from owid/etl. Draft answers for OWID's draft-data-update-slack-post Slack template using snapshot DVC + garden metadata + staging DB queries. Use when the user wants to fill the "Message about new data update" form, announce a dataset update to the internal data-updates-comms channel, or generate the FAQ-style Slack post after an ETL update. Mechanical fields (producer, dates, coverage, chart count, search URL) are filled directly; editorial fields (why it matters, caveats, what's interesting about this update) get prompts…
Its SKILL.md is about 7.4k 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 Data & Analytics, covering Data pipelines and ETL and Help center and FAQ content. It works with Slack. The repository describes itself as: A compute graph for loading and transforming OWID's data. The licence is MIT.
10 steps, taken from the first numbered list in SKILL.md.
Read from SKILL.md and the folder at commit 69ab20e. 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.
Shell commands in SKILL.md call:
makegitFrom the folder's file list and the shell code blocks in SKILL.md.
Hosts in commands or code, which the agent is likely to contact:
ourworldindata.orgadmin.owid.ioFrom 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.
Draft Data Update Slack Post loads about 7.4k tokens when it runs. Until then it costs about 196 tokens; SKILL.md has 2,946 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 owid/etl at commit 69ab20e, republished under its MIT licence (© owid). 2,946 words, ~7,436 tokens.
.claude/skills/draft-data-update-slack-post/SKILL.md (or your agent's skills folder).Generate a draft for the #data-updates-comms Slack form. The skill inspects the current branch of the ETL repo to fill the mechanical fields and seeds the editorial fields with context the user then rewrites in their own voice.
OWID's #data-updates-comms channel is not an internal "FYI I did X" log. It gives information to Charlie (OWID's Communications & Outreach Manager), who turns this input into public-facing posts on social media (Instagram, LinkedIn, X) and in newsletters.
So the form's editorial fields are written for Charlie and indirectly for the general public — not for the data team. A big mistake is writing them in an internal/engineer voice.
The reframing that matters most:
Don't tell Charlie what you'd say to your colleagues ("I updated all the WDI charts"). Tell him what you'd say to a friend who asks what you did this week ("I updated hundreds of our charts to the latest release of the World Bank's largest dataset, called the World Development Indicators. It's a core dataset with hundreds of indicators across global development. This update added new data up to 2025 for dozens of our most-viewed charts…").
What Charlie needs from each field is a reader-centric view: what work was done, what it changes or enables, what's interesting about the source, what it helps people understand about the world, and why anyone should care that it's been updated.
This skill must surface this framing to the user — both at the top of the output draft file and inside each editorial-field prompt block — so the user has it in front of them when they sit down to write. Do not delete or paraphrase the framing.
update-dataset run finishes (step 9 of that skill should delegate here with workbench/<short_name>/update-context.yml rather than re-implement).update-dataset: workbench/<short_name>/update-context.yml — reuse gathered facts first, and only gather missing fields directly.<namespace>/<new_version>/<short_name> — the updated dataset (garden path).<old_version> — for "what changed since last release".If the user only gives a branch or no input at all, infer the dataset(s) from git diff master...HEAD --name-only filtered to etl/steps/data/grapher/** or snapshots/**. If multiple new datasets are touched, ask the user which one(s) the announcement covers.
| Slack field | Source | Skill output |
|---|---|---|
| Dataset name | meta.origin.title + meta.origin.producer from snapshot DVC | filled |
| Release date | meta.origin.date_published | filled |
| Next release | producer's page (web fetch of url_main) — best effort | candidate + [verify] tag |
| Data source | meta.origin.producer, attribution_short, citation_full | filled |
| Coverage (years + countries) | garden table: year.min()..year.max(), distinct country count, presence of regions | filled |
| Charts affected | staging MySQL query on chart_dimensions joined to variables.catalogPath (filter publishedAt IS NOT NULL) | filled, with size qualifier (handful/moderate/large/massive) |
| Why this matters | seeded from meta.origin.description + dataset description + top indicator description_short | prompt with extracted snippets — user rewrites |
| Caveats | seeded from indicator description_key bullets, sanity-check workarounds (notes_to_check.md from update-dataset workbench), meta.origin.description paragraphs that mention "limitations" / "caution" | prompt with extracted snippets — user rewrites |
| Anything interesting | seeded from PR commit messages, notes_to_check.md resolutions, snapshot diff summary if available in workbench/<short_name>/ | prompt — user rewrites |
| Chart views (1–3) | update-context.yml candidates OR query staging directly using the criteria below | filled with rationale, user confirms |
| Search URL | https://ourworldindata.org/search?datasetProducts=<urlquote(datasets.name)> — value is the grapher datasets.name field (= garden dataset.title override when set, else snapshot meta.origin.title); see step 6 | filled |
The editorial fields are deliberately not auto-prosed. Slack posts in the editorial voice ("Why we have this dataset on OWID") read flat when LLM-written; the value is in the human framing. The skill's job is to surface the relevant snippets so the user doesn't have to grep for them.
Reuse update context if available.
workbench/<short_name>/update-context.yml is provided or exists, read it first and use its values for mechanical fields, chart count/views, and editorial snippets.update-dataset responsible for gathering context during the update while preserving this skill as a standalone fallback.Resolve the dataset.
<namespace>/<new_version>/<short_name> or infer from git diff.snapshots/<namespace>/<new_version>/*.dvc.etl/steps/data/garden/<namespace>/<new_version>/<short_name>.py and .meta.yml.data/garden/<namespace>/<new_version>/<short_name> (must have been run; if missing, tell the user to run the garden step first).Extract mechanical fields.
etl.files.ruamel_load (preserves comments if we ever write back) or just yaml.safe_load.from owid.catalog import Dataset
ds = Dataset("data/garden/<ns>/<ver>/<sn>")
tb = ds.read("<table>", safe_types=False).reset_index()
year_min, year_max = int(tb["year"].min()), int(tb["year"].max())
n_countries = tb["country"].nunique()
has_regions = tb["country"].isin(REGION_NAMES).any() # use etl.helpers.regionsQuery staging for affected published charts.
make query SQL="
SELECT COUNT(DISTINCT c.id) FROM charts c
JOIN chart_configs cc ON cc.id = c.configId
JOIN chart_dimensions cd ON cd.chartId = c.id
JOIN variables v ON cd.variableId = v.id
WHERE v.catalogPath LIKE '%<ns>/<ver>/<sn>%'
AND c.publishedAt IS NOT NULL"Seed the editorial fields with snippet bullets.
For each of "why it matters", "caveats", "anything interesting": don't write prose, write 2–6 substantive bullets above an empty text fenced block. Bullets are clean reader-facing prose — no Snapshot description: / Garden description: prefixes in the output. Use those as internal source pointers only.
Pick chart views — rank by actual data change, not just our intuitions about which chart is "flagship".
The picked views show up in the public announcement under "Here's what changed". If the underlying data didn't actually change between the old and new release, the announcement misrepresents the update. So the primary ranking signal is: for each published chart on the new dataset, how many of its y-variables have a different dataChecksum than the matching variable on the old dataset? This is the same signal Chart Diff uses.
Run on staging (which has both old and new variables side-by-side):
from etl.config import OWID_ENV
from sqlalchemy import text
import pandas as pd
sql = """
SELECT c.id AS chart_id, cc.slug,
JSON_UNQUOTE(JSON_EXTRACT(cc.config, '$.title')) AS title,
JSON_UNQUOTE(JSON_EXTRACT(cc.config, '$.hasMapTab')) AS has_map,
JSON_UNQUOTE(JSON_EXTRACT(cc.config, '$.type')) AS chart_type,
SUM(v_new.dataChecksum <> v_old.dataChecksum) AS n_changed,
COUNT(*) AS n_vars
FROM charts c
JOIN chart_configs cc ON cc.id = c.configId
JOIN chart_dimensions cd ON cd.chartId = c.id
JOIN variables v_new ON cd.variableId = v_new.id
LEFT JOIN variables v_old ON v_old.shortName = v_new.shortName
AND v_old.datasetId = :old_dataset_id
WHERE v_new.datasetId = :new_dataset_id
AND c.publishedAt IS NOT NULL
AND cd.property = 'y'
GROUP BY c.id
HAVING n_changed > 0
ORDER BY n_changed DESC, has_map DESC
LIMIT 30
"""
with OWID_ENV.engine.connect() as conn:
df = pd.read_sql(text(sql), conn, params={"old_dataset_id": OLD_ID, "new_dataset_id": NEW_ID})Resolve OLD_ID / NEW_ID from the datasets table by catalogPath.
Then rank the data-changed subset by chart views. Among the charts whose data actually changed, prefer the ones readers actually look at — a chart with 246 views/day and 1 changed variable is a far better announcement candidate than a chart with 3 views/day and 18 changed variables:
from etl.analytics.data import get_chart_views_last_n_days
views = get_chart_views_last_n_days(chart_ids=df["chart_id"].astype(int).tolist(), n_days=30)
df = df.merge(views[["chart_id", "views_daily"]], on="chart_id", how="left").fillna({"views_daily": 0})
df = df.sort_values(["views_daily", "n_changed"], ascending=[False, False])Apply secondary tie-breakers within the top of that ranked list:
has_map = true — readers can find their own country.probability-of-dying-by-age with 18/18), that's a slightly stronger signal than "1 of 1 changed".A checksum change is not "gained the new year." A base-year rebase or in-place revision marks every chart data-changed, including charts whose series still end at the previous year (recipient/sector tables that only update in the producer's detailed release, series absent from a preliminary file). For releases that add a partial year, additionally verify each picked view's indicators actually reach the new year (metadata.json → dimensions.years), and prefer the chart carrying the release's headline measure — the one where the announcement's own numbers are visible on open — even when its traffic is low (the announcement is how it gets discovered).
Reuse charts.selected_views from update-context.yml only if it's already been built using this views-then-checksum process (older runs picked views by intuition and produced misleading recommendations like "life expectancy now updated" when the data was effectively unchanged, or "malaria deaths" when the chart gets ~3 views a day).
Output 1–3 as [<chart title>](<admin URL>) — <rationale that names the change>. Hyperlink each title to the admin editor URL, not the bare admin path:
https://admin.owid.io/admin/charts/<id>/edithttp://staging-site-<branch>/admin/charts/<id>/editThe bare /admin/charts/<id> path takes the reader to a non-existent route on production; /edit opens the chart editor where they can verify the change. If the chart already existed before this PR (published earlier than the branch was cut — c.publishedAt is older than the first branch commit), link to production. If the chart was first published on this branch, link to staging.
Build the search URL.
The datasetProducts query parameter matches against the grapher datasets.name field (the dataset row's name column in MySQL — same value visible in the OWID admin's dataset list). When garden's gho.meta.yml sets a dataset.title override, that becomes datasets.name on upload. Otherwise it falls through to the snapshot origin's title.
An update that spans several grapher datasets gets one link covering all of them: join each dataset's datasets.name with ~ (?datasetProducts=<name 1>~<name 2>, each part quote_plus-encoded). Resolve every name the same way as below — companion datasets often carry titles of their own that differ from the main one's.
So the resolution order is:
.meta.yml → dataset.title (if set as override). This is the most common case — most large datasets carry a curated title like Global Health Observatory - World Health Organization or World Bank Poverty and Inequality Platform (PIP)..dvc → meta.origin.title (fallback).Resolve the value programmatically rather than guessing — query the grapher DB or read the garden YAML directly:
# Most reliable: grab the literal value from the prod-mirror grapher DB
make query SQL="SELECT name FROM datasets WHERE catalogPath = 'grapher/<ns>/<v>/<short>'"
# Or from the garden YAML
from etl.files import ruamel_load
meta = ruamel_load("etl/steps/data/garden/<ns>/<v>/<short>.meta.yml")
title = (meta.get("dataset") or {}).get("title") # falls through if missingBuild the URL with urllib.parse.quote_plus(title) so spaces become + and parens become %28/%29. NOT the bare producer field — that mismatches the index. And don't put the producer's homepage URL here, even as a fallback — the Slack template specifically wants this search URL form.
Important caveat: the search index bakes asynchronously after a PR merge. A correctly-formed URL can still return zero results for a few hours post-merge while the index re-bakes. If the user reports "no results", double-check the URL value against datasets.name first; if it matches, tell them to retry in a couple of hours.
Best-effort next-release date.
url_main (WebFetch) and extract any phrase like "next release", "annual update", "updated yearly" near the page header. Tag the answer [verify] so the user knows to confirm.[unknown — please confirm with the producer's release schedule].Write the draft.
ai/data-update-comms.md by default, or workbench/<short_name>/slack-announcement.md when invoked from update-dataset step 9.[filled] / [prompt] tags, no inline instructions. If a field can't be filled mechanically, write [missing — <what's needed>] inside the fenced block and stop.Show the user the file path and stop. In a git worktree, give the absolute path: a relative link opens the main checkout's copy, which may be a previous update's draft. Do not post to Slack — that's a human action. The user copy-pastes from the Markdown file into the Slack form.
The output file must use the Slack form's prompt wording verbatim as section headings. The user copy-pastes the answer text into the matching Slack fields, so each prompt is its own ## <verbatim heading>.
Keep the file lean. No "E.g.:" example lines, no [filled] / [prompt — user rewrites] tags, no inline framing instructions, no _Snippets to draw from:_ / _Candidate caveats:_ / _Context from this PR:_ label preambles, no text code fences around the answers. The skill keeps the framing reminders for itself (see "Editorial framing" below); the file is just headings → answer prose (for mechanical fields) or snippet bullets (for editorial fields).
The verbatim Slack prompt headings (do not rephrase, abbreviate, or change punctuation):
| # | Prompt heading (verbatim) |
|---|---|
| 1 | What dataset(s) did you update? |
| 2 | When was this data released? When is the next scheduled release / our plan for next update? |
| 3 | Who is the data source(s)? Is there anything our users should know about them? |
| 4 | What's the coverage of the data in terms of years and countries/regions? |
| 5 | How many charts did this update affect? |
| 6 | What does this dataset help our users understand about the world, and why is it important they know that? |
| 7 | Any important caveats or pitfalls in interpretation that users should know about this data? (optional) |
| 8 | Anything interesting to note about this update, including what you had to do? Anything else you'd like to add? (optional) |
| 9 | Add 1–3 chart views we might use in the public announcement |
| 10 | Link to the updated charts as a search result (not a chart collection anymore). Ask Charlie if you need help with this. (optional) |
The table above is the single source of truth — if the Slack form's wording changes, update it here and nowhere else.
Producers headline figures on their basis — often current prices where our charts are constant, or a measure our headline chart doesn't carry. Verify every number and ranking in the snippets against our own charts: a producer claim our charts contradict ("X overtook Y", a total a few percent off ours) must be explicitly attributed to the producer, made basis-robust (rounded so both bases agree), or dropped in favor of chart-native numbers. Rankings especially: enumerate the measure × price-basis combinations first — a "first time in history" headline may hold on exactly one of them. Put the reconciliation (which basis says what, what social copy may safely echo) in the caveats field for Charlie; keep reader-facing framing chart-native.
Before drafting fields #6, #7, #8, remember they go to Charlie, who turns them into public-facing posts — not into an internal team log. Snippets should sound like what you'd tell a curious friend, not a colleague: reader-centric, with a concrete number where possible, and what's interesting about the source. The agent uses this framing to select and phrase the snippets; the framing itself is never written into the output.
meta.origin.description, garden dataset description, and top indicator description_short; rephrase into clean prose. Do not prefix each bullet with its source label (e.g. don't write Snapshot description: "…"); just write the substantive content.description_key bullets, sanity-check workarounds, and methodology notes. Skip if there are no load-bearing caveats.editorial_context.interesting_update_snippets in update-context.yml, commit messages, and resolved workarounds. Phrase them as reader-facing facts, not engineering notes.# Data update comms draft — <dataset name>
Source: `<ns>/<new_version>/<short_name>` · Branch: `<branch>` · Generated: <iso datetime>
---
## What dataset(s) did you update?
<Dataset title — Producer>
## When was this data released? When is the next scheduled release / our plan for next update?
Released: <date_published>. Next: <best-effort or "unknown — …">.
## Who is the data source(s)? Is there anything our users should know about them?
<producer>. <citation_full or attribution_short, trimmed>.
## What's the coverage of the data in terms of years and countries/regions?
Covers <year_min>–<year_max>, <n_countries> countries<, plus OWID regions if applicable>. <Sparse-recent-year flag if applicable.>
## How many charts did this update affect?
<N> published charts (<size qualifier>)<; if update-context.yml lists published explorers/MDims, fold them in too — e.g. "10 published charts (moderate), plus 3 explorers and 1 MDim">.
## What does this dataset help our users understand about the world, and why is it important they know that?
- <substantive snippet>
- <substantive snippet>
- <substantive snippet>
## Any important caveats or pitfalls in interpretation that users should know about this data? (optional)
- <caveat snippet>
- <caveat snippet>
## Anything interesting to note about this update, including what you had to do? Anything else you'd like to add? (optional)
- <interesting snippet>
- <interesting snippet>
## Add 1–3 chart views we might use in the public announcement
> Pick chart views that represent the whole dataset, rather than, e.g., something very specific about a single country.
1. **<title>** — `<slug>` — <rationale>
2. **<title>** — `<slug>` — <rationale>
## Link to the updated charts as a search result (not a chart collection anymore). Ask Charlie if you need help with this. (optional)
https://ourworldindata.org/search?datasetProducts=<urlencoded dataset title>
---
## Pending mechanical follow-ups
- <only if any — e.g. "next release date is best-effort", "verify producer's release cadence", source-of-truth caveats>Strict rules:
(optional) suffix.## Pending mechanical follow-ups section — never inside the verbatim Slack fields.[missing] and stop on that line — don't paper over a gap.update-dataset step 8 — and the same for the other surfaces it records: only explorers with isPublished=1 and MDims with published=1 (from charts.explorers / charts.mdims in update-context.yml) count toward the announcement. Note unpublished/draft ones under ## Pending mechanical follow-ups, not in the answer.urllib.parse.quote_plus (not quote) for the search URL — Slack's input expects + for spaces in datasetProducts.data/garden/<ns>/<ver>/<sn> doesn't exist, tell the user to run the garden step before retrying. Don't fabricate coverage from the snapshot alone — the garden output is what matters for the Slack post.publishedAt IS NOT NULL filter — drafts in the count would mislead.ourworldindata.org/search?datasetProducts=….update-dataset — keep it standalone so users can invoke it after manual updates too. update-dataset should gather reusable facts in update-context.yml and step 9 should delegate here, not duplicate the Slack rendering logic..claude/skills/update-dataset/SKILL.md step 9 — the orchestrator entry point that should call this skill./owid-staff:draft-data-update-post (owid/skills-private, auto-installed here) — what happens next. This skill's Slack post is the input to the public "Data update" post on ourworldindata.org/latest; that skill either reads the Slack message directly or, inside /update-dataset (step 9b), reads update-context.yml plus the slack-announcement.md this skill produced. Two different artifacts: a 10-field internal form here, a reader-facing mini-post there. Don't draft the /latest post from this skill. Note that the /latest skill declines to post when OWID covered the same data publicly less than six months ago — that cooldown does not apply here. This Slack form runs on every update regardless, because its audience is internal and its job is to tell Charlie what changed..claude/skills/edit-faust-metadata/SKILL.md — reuses the same grapher-channel metadata patterns for chart-view selection.© owid, 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 .claude/skills/draft-data-update-slack-post of owid/etl.
Open the folder on GitHubat commit 69ab20e
Draft Data Update Slack Post 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 |
|---|---|---|---|---|---|---|
| Draft Data Update Slack Post this skillowid/etl | 158 | — | ~7.4k | Automated safety check: Pass | MIT | |
| Channel Plugin Duplicate SocketSzotasz/marveen | 115 | — | ~1.3k | Automated safety check: Notes | MIT | |
| Dag Orchestration Patternsrevfactory/harness-100 | 1.3k | — | ~1.3k | Automated safety check: Pass | Apache-2.0 | |
| Dag Orchestration Patternsrevfactory/harness-100 | 1.3k | — | ~1.1k | Automated safety check: Pass | Apache-2.0 | |
| Crawl4AI Web Scrapingsmallnest/goclaw | 598 | 1 repos | ~2.5k | Automated safety check: Pass | MIT | |
| Glue 09 10 Migrationaws-samples/aws-glue-samples | 1.5k | — | ~2.4k | Automated safety check: Pass | MIT-0 |
Szotasz/marveen
Marveen flottában új channel plugin (slack-channel, telegram, stb.) telepítésekor a user-szintű ~/.claude/settings.json enabledPlugins minden agent-nek loadolja a plugin server-t, és ha az egy…
revfactory/harness-100
Airflow DAG pattern, of , retry strategy, etc. An agent skill from revfactory/harness-100.
revfactory/harness-100
Airflow DAG 설계 패턴, 의존관계 관리, 재시도 전략, 멱등성 보장, 백필 전략 등 데이터 파이프라인 오케스트레이션 가이드.
smallnest/goclaw
Scrapes sites, handles JavaScript-heavy pages and extracts structured data with Crawl4AI, through its crwl CLI or Python SDK, including schema-based extraction without an LLM.
aws-samples/aws-glue-samples
Upgrade an AWS Glue ETL job from Glue version 0.9 or 1.0 to Glue 4.0.
aws-samples/aws-glue-samples
Migrate a legacy AWS Glue development endpoint to a Glue interactive session, following the official AWS migration checklist.
owid/etl
Find every OWID surface that references a chart, indicator, MDIM, or explorer — articles (links vs embeds), explorers, narrative charts, data insights, static viz, key-chart slots, MDIM views.
owid/etl
Add a scatter view (with GDP per capita on x) to existing OWID charts via the admin API, mirroring the admin UI's "Add scatter type" defaults, then retire the old standalone "X vs.
owid/etl
Add new survey question codes (e.g. An agent skill from owid/etl.
owid/etl
Build or refresh an OWID static visualization end to end — resolve what data it needs from an old static viz image, an indicator, or a grapher chart; check both the ETL catalog and the producer's…
owid/etl
Propose redirects from (soon-to-sunset) grapher charts to the matching views of published MDIMs.
owid/etl
Take (soon-to-sunset) OWID explorers to redirected MDIMs, end to end.
Works with
Categories
Draft answers for OWID's draft-data-update-slack-post Slack template using snapshot DVC + garden metadata + staging DB queries. Draft Data Update Slack Post is an agent skill from owid/etl. Draft answers for OWID's draft-data-update-slack-post Slack template using snapshot DVC + garden metadata + staging DB queries.
Draft Data Update Slack Post fits situations like: the user wants to fill the Message about new data update form; announce a dataset update to the internal data-updates-comms channel; generate the FAQ-style Slack post after an ETL update.
Run `npx skills add owid/etl --skill draft-data-update-slack-post -a claude-code`. Or copy the skill folder (.claude/skills/draft-data-update-slack-post in owid/etl) into .claude/skills/draft-data-update-slack-post in your project. Claude Code loads it when a task matches its description.
Run `npx skills add owid/etl --skill draft-data-update-slack-post -a codex`. Or copy the skill folder (.claude/skills/draft-data-update-slack-post in owid/etl) into .agents/skills/draft-data-update-slack-post 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 owid/etl --skill draft-data-update-slack-post -a cursor` (or -a gemini-cli, github-copilot or opencode for the others). To copy it by hand, put the folder in .cursor/skills/draft-data-update-slack-post, .gemini/skills/draft-data-update-slack-post, .github/skills/draft-data-update-slack-post and .opencode/skills/draft-data-update-slack-post in your project.
Going by SKILL.md and its folder, Draft Data Update Slack Post needs the command-line tools its instructions call (make and git). Our summary lists: Python 3.
SKILL.md names 2 domains. In commands or code: ourworldindata.org and admin.owid.io; the agent is likely to contact these when it follows the instructions. 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.
Draft Data Update Slack Post is published under the MIT licence (the repository's licence). It allows redistribution, so the full SKILL.md is shown on this page.
About 7.4k tokens (SKILL.md is roughly 30k 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 Draft Data Update Slack Post: Channel Plugin Duplicate Socket (Szotasz/marveen, 115 stars), Dag Orchestration Patterns (revfactory/harness-100, 1.3k stars), Dag Orchestration Patterns (revfactory/harness-100, 1.3k stars) and Crawl4AI Web Scraping (smallnest/goclaw, 598 stars). The comparison table on this page puts their stars, adoption, token cost, safety result and licence side by side.
owid (a GitHub organization) maintains it in owid/etl, which has 158 GitHub stars. The repository holds 35 skills in this directory. The repository was last updated on October 7, 2026.
Source: owid/etl on GitHub. Facts on this page come from the repository at the commit we read; the author's words are quoted as theirs.