{"slug": "agent-skills-that-make-coding-agents-profile-data-before-charting-it", "title": "Agent skills that make coding agents profile data before charting it", "summary": "A set of 15 skills, 9 commands and 4 reviewer subagents was released to make AI coding agents run data work through a fixed eight-stage pipeline — PROFILE, CLEAN, MODEL, QUERY, VISUALIZE, ASSEMBLE, NARRATE, DISCLOSE — with a /redact command spanning all stages. The skills keep the original file read-only, log every cleaning rule with the row count it touched, persist curated data as Parquet under data/curated/, and query it with DuckDB, while four non-editing reviewers separate verified from asserted findings and audit percentages against their arithmetic. The release cites a test page built from a 200-order sales export in which a shipped check traced all 85 figures back to the curated table, with the category, channel, payment and province breakdowns each summing to $7,316.65.", "body_md": "**15 skills, 9 commands and 4 reviewer subagents** that make an AI coding agent profile a file\nbefore it cleans it, clean it before it charts it, build the dashboard by BI rules rather than by\nits own guess, and say what it did not cover instead of inventing it.\n\nData work runs in one direction. Each stage assumes the one before it happened.\n\n```\nPROFILE → CLEAN → MODEL → QUERY → VISUALIZE → ASSEMBLE → NARRATE → DISCLOSE\n/profile  /clean  /model   /query   /chart     /dashboard  /insight  /disclose\n                                                              /redact runs across all of them\n```\n\nRun a command to enter a stage by name, or just describe the task and let the router pick.\n\nA page an agent built with these skills from a 200-order sales export that holds no names or contact details. The shipped check traced all 85 figures on it back to the curated table. Every figure says which of the 200 orders it covers, and the category, channel, payment and province breakdowns each add up to the $7,316.65 at the top.\n\n**A working data architecture in your project, not an answer in a chat.**\n\n**The pipeline**\n\n- **Three layers and a trail.** The file that arrived is never written to. Cleaning happens in its\nown layer, every rule logged with the number of rows it touched. What survives is persisted as\nParquet under`data/curated/` , and everything downstream reads from there.\n- **SQL over Parquet at local speed.** DuckDB queries the curated table directly — no server, no\nload step, and a plan you can read. Grouping, ranking, joins and window functions stop being\nloops.\n- **Row work at spreadsheet scale.** A worksheet stops at 1,048,576 rows; Polars handles that\nrange in memory on an ordinary laptop, with a schema that is declared rather than guessed from\nwhichever rows it saw first. If your project already has a dataframe library, the skills tell the\nagent to use that one rather than add a second.\n- **Workbooks that survive the round trip.** Formulas, number formats, named ranges, merged\nregions and validation rules are named before anything is written back — because a library\nreturns the last value the spreadsheet computed, not the formula that computed it.\n\n**The output**\n\n- **One page, not a pile of files.** A single self-contained HTML file, with linked filters that\nmove every panel at once — no bundler, no build step, nothing to compile. Five files each\ncarrying their own copy of the drawing library is five charts, not a dashboard.\n- **Charts chosen by a rule with an author.** Cleveland and McGill measured how accurately people\nread visual encodings: position, then length, then angle, then area, and colour last. The skill\napplies that order instead of a preference, which is why nine slices in a pie get refused.\n- **A dashboard that starts from your question.** Before any layout, the agent writes down the one\nquestion the page answers and what the reader must be able to do with it. Panels are ranked\nagainst that question, and anything answering no part of it is a candidate for removal.\n\n**The guardrails**\n\n- **Four reviewers that cannot edit what they review.** One separates what was*verified* from\nwhat was*asserted* . One audits a finding against its arithmetic — the base of every percentage,\nwhether an average is weighted, whether a comparison reverses once the groups are pooled. One\nclassifies every field before anything leaves the project. One names the craft decisions a page\nnever made, and says plainly that it did not render the page. They run when the result leaves\nyour machine or somebody will act on it, and stay out of the way when it is a first look.\n- **Numbers you can trace.** Every figure on the page has a query behind it and a population it\ncovers. A number typed by hand fails the check.\n- **A written record of what was skipped** — rows, sheets, files, in counts rather than adjectives.\n- **Nothing personal leaves the project** without somebody deciding it should.\n\n| Stage | Skill | Use it when | \n|---|---|---|\n| Route | [`using-lakehouse-skills`](https://github.com/LuynoxRD/lakehouse-agent-skills/blob/main/skills/using-lakehouse-skills) | It is not obvious which skill applies, or the request jumps straight to a chart | \n| Shape | [`structured-vs-unstructured-routing`](https://github.com/LuynoxRD/lakehouse-agent-skills/blob/main/skills/structured-vs-unstructured-routing) | You are not sure the source is even a table | \n|  | [`document-extraction-integrity`](https://github.com/LuynoxRD/lakehouse-agent-skills/blob/main/skills/document-extraction-integrity) | The numbers are in a PDF, a scan or a photo | \n| Values | [`etl-before-dashboard`](https://github.com/LuynoxRD/lakehouse-agent-skills/blob/main/skills/etl-before-dashboard) | Anything is about to be charted, cleaned, joined, or has arrived a second time | \n|  | [`spreadsheet-integrity`](https://github.com/LuynoxRD/lakehouse-agent-skills/blob/main/skills/spreadsheet-integrity) | Results are being written back into a workbook | \n|  | [`honest-data-limits-disclosure`](https://github.com/LuynoxRD/lakehouse-agent-skills/blob/main/skills/honest-data-limits-disclosure) | The file is huge, the batch partly failed, or coverage is not total | \n| Storage | [`parquet-to-open-table-format`](https://github.com/LuynoxRD/lakehouse-agent-skills/blob/main/skills/parquet-to-open-table-format) | Rows need correcting, two jobs write to one folder, or a column has to survive being added | \n|  | [`duckdb-for-local-analytics`](https://github.com/LuynoxRD/lakehouse-agent-skills/blob/main/skills/duckdb-for-local-analytics) | You are grouping, ranking or joining a persisted table | \n| Output | [`chart-type-and-library-selection`](https://github.com/LuynoxRD/lakehouse-agent-skills/blob/main/skills/chart-type-and-library-selection) | Pie or bar, and which library the destination needs | \n|  | [`dashboard-color-and-visual-hierarchy`](https://github.com/LuynoxRD/lakehouse-agent-skills/blob/main/skills/dashboard-color-and-visual-hierarchy) | Choosing colours, or checking they read on both backgrounds | \n|  | [`dashboard-layout-by-widget-mix`](https://github.com/LuynoxRD/lakehouse-agent-skills/blob/main/skills/dashboard-layout-by-widget-mix) | A page has more panels than fit, or is a grid of equal tiles | \n|  | [`dashboard-visual-craft`](https://github.com/LuynoxRD/lakehouse-agent-skills/blob/main/skills/dashboard-visual-craft) | The page is styled and nothing on it ranks: one size, one gap, centred numbers, an empty first state | \n|  | [`insight-narrative-integrity`](https://github.com/LuynoxRD/lakehouse-agent-skills/blob/main/skills/insight-narrative-integrity) | Writing takeaways, a ranking, a growth figure or a cause | \n| Safety | [`data-privacy-before-llm`](https://github.com/LuynoxRD/lakehouse-agent-skills/blob/main/skills/data-privacy-before-llm) | Rows are about to be pasted into a prompt or sent to a service | \n|  | [`safe-live-database-access`](https://github.com/LuynoxRD/lakehouse-agent-skills/blob/main/skills/safe-live-database-access) | Connecting to a database other people use | \n\nOne command per stage, in the order the stages run. Each one names the skills it invokes and the artefact it leaves behind, so the next stage starts from a file rather than from memory.\n\n| Stage | Command | What it does | \n|---|---|---|\n| PROFILE | `/profile` | Profile a dataset before anything is cleaned, charted or claimed about it. | \n| CLEAN | `/clean` | Clean a profiled dataset, recording every rule and the number of rows it touched. | \n| MODEL | `/model` | Decide what one row means and persist the modelled table to columnar storage. | \n| QUERY | `/query` | Answer a question with SQL over the table that was already persisted. | \n| VISUALIZE | `/chart` | Choose the chart form the data shape allows, then the library the destination needs. | \n| ASSEMBLE | `/dashboard` | Lay out a page by what its panels are and how many of them there are. | \n| NARRATE | `/insight` | Write findings that survive their own arithmetic before they become sentences. | \n| DISCLOSE | `/disclose` | State what the run did not cover, in numbers, before the result is used. | \n| REDACT, across all of them | `/redact` | Decide what may leave the project before any rows are sent anywhere. | \n\nThey reach Claude Code, as the plugin's commands, and Gemini CLI, generated into\n`.gemini/commands/*.toml` from the same sources. Every other tool gets the same steps by\ndescribing the task: the router names the stage, and the stage names its skills.\n\nFour reviewer personas. They read and report; none of them can edit the work it reviews.\n\n| Persona | What it does | \n|---|---|\n| [`data-work-reviewer`](https://github.com/LuynoxRD/lakehouse-agent-skills/blob/main/agents/data-work-reviewer.md) | Separates what was **verified** from what was**asserted** , and says which claims have evidence behind them | \n| [`claim-auditor`](https://github.com/LuynoxRD/lakehouse-agent-skills/blob/main/agents/claim-auditor.md) | Audits a written finding against its arithmetic: the base of every percentage, whether an average is weighted, whether a comparison reverses once groups are pooled | \n| [`outbound-data-gate`](https://github.com/LuynoxRD/lakehouse-agent-skills/blob/main/agents/outbound-data-gate.md) | Classifies every field that would leave the project and decides what may go, in what form | \n| [`design-reviewer`](https://github.com/LuynoxRD/lakehouse-agent-skills/blob/main/agents/design-reviewer.md) | Names the craft decisions a page never made, each with the value from the file, and says plainly that it did not render the page | \n\nThey run when the result leaves the project or somebody will act on it. For a first look that stays on your machine, they stay out of the way.\n\nTwo session hooks come with them. One refuses to end a turn while a profiled dataset has no disclosure written, a published page has not been checked, or a page was written without the skills that own how it reads.\n\n**Installing it for someone?** If you are an AI agent and the person you work for asked you to\ninstall this pack, run the line for the tool you are running in, with their approval:\n\n| Running in | Install | \n|---|---|\n| Claude Code | `claude plugin marketplace add LuynoxRD/lakehouse-agent-skills` , then`claude plugin install lakehouse-agent-skills@lakehouse-skills` | \n| Codex | `codex plugin marketplace add LuynoxRD/lakehouse-agent-skills` , then`codex plugin add lakehouse-agent-skills@lakehouse-skills` | \n| Any other coding agent | `npx skills add LuynoxRD/lakehouse-agent-skills --skill '*' --agent <your-agent> -y` | \n\nThen tell them to start a new session, the one moment every tool is sure to load what was installed. A chat with no terminal cannot install anything; say so rather than describe an install that did not happen.\n\n**Fastest path — one command, any agent.** The open [skills CLI](https://github.com/vercel-labs/skills)\ninstalls into 77 agents. Name yours after `--agent`:\n\n```\nnpx skills add LuynoxRD/lakehouse-agent-skills --skill '*' --agent claude-code -y\nnpx skills add LuynoxRD/lakehouse-agent-skills --list       # browse before installing\n```\n\nOr one skill on its own:\n\n```\nnpx skills add LuynoxRD/lakehouse-agent-skills --skill etl-before-dashboard --agent cursor -y\n```\n\nA per-skill install copies `skills/<name>/` and nothing above it, so the shared `references/`\nchecklists do not come with it. Every skill keeps inline what it cannot work without, and says\nnext to each link what you lose when the shared file is absent — if one ever stops making sense\non its own, that is a defect in the skill.\n\nPrefer a native integration, or want the commands and subagents too? Pick your tool.\n\n## **Claude Code** — the whole pack: skills, commands, subagents, hooks\n\nThe repository is also a plugin. This is the route that brings the nine commands, the four reviewer subagents and the two session hooks along with the skills, with nothing to copy by hand:\n\n```\nclaude plugin marketplace add LuynoxRD/lakehouse-agent-skills\nclaude plugin install lakehouse-agent-skills@lakehouse-skills\nclaude plugin details lakehouse-agent-skills\n```\n\n`marketplace add` takes a GitHub repo, a URL or a path, so a local clone works the same way and is\nhow to try a change before it is merged:\n\n```\ngit clone https://github.com/LuynoxRD/lakehouse-agent-skills.git\nclaude plugin marketplace add ./lakehouse-agent-skills\nclaude plugin install lakehouse-agent-skills@lakehouse-skills\n```\n\nBoth forms are verified end to end: the clone in a throwaway project, and the GitHub one in a clean\nconfiguration once the repository was public. The inventory that comes back is 24 skills — the\nfifteen plus the nine commands, which load through the same mechanism — 4 agents, and 2 hooks.\nAbout **2,704 tokens always-on** as Claude Code 2.1.311 counts them; each skill costs its own text\nagain only when it fires.\n\n## **Cursor, opencode, Codex, Copilot, Zed and 14 more** — one shared directory\n\nNineteen tools read the same project directory, `.agents/skills`, which is the cross-tool\nconvention rather than any one product's folder: Amp, Antigravity, Antigravity CLI, Cline, Codex,\nCursor, Deep Agents, Dexto, Firebender, Gemini CLI, GitHub Copilot, Kimi Code CLI, Loaf, opencode,\nPromptScript, Replit, Universal, Warp and Zed.\n\n```\nnpx skills add LuynoxRD/lakehouse-agent-skills --skill '*' --agent cursor -y\nnpx skills add LuynoxRD/lakehouse-agent-skills --skill '*' --agent opencode -y\nnpx skills add LuynoxRD/lakehouse-agent-skills --skill '*' --agent cursor,opencode,codex -y\n```\n\n**Install for one and the rest find them too**, because they are all reading the same place.\n\n## **Windsurf, Continue, Roo, Kilo, Junie, Goose, Kiro and the long tail**\n\nThese read their own `.<tool>/skills/` directory, so name yours — or install for every agent the\nCLI knows in one go:\n\n```\nnpx skills add LuynoxRD/lakehouse-agent-skills --skill '*' --agent windsurf -y\nnpx skills add LuynoxRD/lakehouse-agent-skills --all          # every agent, every skill\n```\n\n## **Gemini CLI** — skills, plus the nine commands\n\nGemini reads the shared `.agents/skills` directory, so the universal command covers the skills:\n\n```\nnpx skills add LuynoxRD/lakehouse-agent-skills --skill '*' --agent gemini-cli -y\n```\n\nThe commands exist for Gemini as well, generated into `.gemini/commands/*.toml` from the same\nTOML sources. Copy that directory from a clone into your project to get `/profile`, `/clean` and\nthe rest.\n\n## **Any other agent**\n\nA skill is a directory with a `SKILL.md` and no build step, so it works with anything that reads\ninstruction files. Clone the repository and point your tool at `skills/`.\n\n**Nothing updates itself.** Neither route watches this repository, so what you install today stays\nas it is until you run:\n\n```\nnpx skills update                              # skills, every source\nclaude plugin update lakehouse-agent-skills    # the plugin route\n```\n\n**How far each piece reaches.** The skills go everywhere above. The nine commands reach Claude Code\nand Gemini CLI. The four subagents are generated for Claude Code, opencode, Cursor, Gemini CLI and\nCodex from one source, each in the form that tool uses to withhold editing; the two hooks are Claude\nCode only. Loading was verified end to end in Claude Code and opencode; elsewhere what was measured\nis that the files land, and a file arriving is not a skill running.\n[docs/installing.md](https://github.com/LuynoxRD/lakehouse-agent-skills/blob/main/docs/installing.md) has the full accounting.\n\n| Source | Handled by | \n|---|---|\n| Delimited text — CSV, TSV, exports and extracts | `etl-before-dashboard` | \n| Spreadsheet workbooks, read and written, through `openpyxl` | `spreadsheet-integrity` | \n| PDFs, scans and photographs of documents | `document-extraction-integrity` | \n| Records that are not all the same shape, and free text | `structured-vs-unstructured-routing` | \n| Parquet, and the point where a directory of it stops being enough | `parquet-to-open-table-format` | \n| Live databases somebody else is using | `safe-live-database-access` | \n\nCleaned data lands as Parquet under `data/curated/`, and everything downstream reads from there\nrather than from the file that arrived.\n\nThe skills add no dependency of their own. They are markdown, and they point at the tools a data project already has:\n\n- **DuckDB** for anything expressible as a query against the persisted table — grouping, ranking,\njoins, window functions. It reads Parquet and CSV directly, needs no server, and gives you a\nplan you can read.\n- **Polars** as the default for the row work that is not a query, because its schema is declared\nrather than re-derived from whichever rows it happened to see. With one standing exception:**if\nyour project already uses a dataframe library, the skills tell the agent to use that one.** Two\nlibraries disagreeing about a column is the failure the rule exists to prevent.\n- **`openpyxl`** for workbooks, which is where the formatting, formulas and merged cells that a\ndataframe silently drops actually live.\n\n`verify-output.sh` runs on Python 3 with the standard library alone, plus DuckDB when it has to\nrecompute figures — and if DuckDB is missing it says so and fails, rather than reporting the\nfigures as checked.\n\nDo not point an agent at a spreadsheet before you know two things.\n\n**A workbook is not a table. It is compressed XML.** The `.xlsx` on disk is a zip. The XML inside\nit is several times larger, and the object model a library builds from that XML is larger again —\non this repository's own 636-row fixture, 21 KB on disk is 122 KB of XML and 1.2 MB in memory. A\nmodel does not read that format. To reason about the file it is flattened to text, cell by cell,\nand the structure goes first: formulas, number formats, merged regions, the second sheet.\n\n**When an agent runs out of room it does not stop. It shrinks the file and keeps going.** Its\ncontext is finite, so it reads part of a large file, and the part quietly becomes \"the file\" in\nevery sentence that follows. The hosted fix — run Python in a sandbox — moves that ceiling to the\nsandbox's memory limit; it does not remove it, and nothing announces when it is hit. Either way the\noutput arrives looking finished, because there is no visual difference between a number that was\ncomputed and one that was made up.\n\nThat is the failure this pack exists to prevent: an agent that destroys the file's structure,\ninvents what it could not read, and hands you a dashboard of false figures without saying so.\n**Nothing here builds a dashboard before the data is profiled and cleaned**, and every stage leaves\na written record of what it did and did not touch.\n\nIn this repository's own audited runs the model reported reading a template it never opened, named a skill that does not exist, and called a page verified because a parser found no errors in it. Each of those became a rule.\n\nThe rest is what an agent cannot do, and none of it is a bug to be fixed:\n\n- **It cannot see the file's past.** How it was exported, which settings produced it, what a blank\ncell meant to whoever typed it. It sees bytes and infers, and an inference nobody wrote down is\nindistinguishable from a measurement.\n- **It cannot see the page it just built.** It emits markup; it does not render it. Text sitting on\ntop of other text looks identical to text that does not.\n- **It starts every session blind.** Nothing carries over unless it was written down, which is why\neach stage here leaves a note behind instead of a memory.\n\nMeanwhile most data still arrives as a spreadsheet, which is a document that looks like a table: a\n`Total` row an aggregate will count twice, dates that could be read two ways, leading zeros eaten\nso `007` and `7` are now one store.\n\nNone of that is exotic. Every one has a boring answer that data engineers have used for decades, and nothing in the agent's context was asking for it. These skills ask for it.\n\nSkills are tested on three levels: that they are structurally sound, that a request reaches the right one (53 prompts that must, 31 that must not, currently 100% first-place), and that a real run against fixtures with planted defects catches them.\n\nOne check runs in your project rather than ours. `verify-output.sh` reads the page an agent\ndelivered and recomputes every published figure against the table it came from. It reads markup and\nnever renders, so it prints what it could **not** verify on every run, including a clean one.\n\n```\nlakehouse-agent-skills/\n├── skills/                                 # 15 skills, a SKILL.md the only required file\n│   ├── using-lakehouse-skills/             #   Route: which skill owns this, and how much review\n│   ├── structured-vs-unstructured-routing/ #   Shape: is this even a table\n│   ├── document-extraction-integrity/      #   Shape: getting numbers off a page\n│   ├── etl-before-dashboard/               #   Values: profile, clean, model, persist  ← ships a script\n│   ├── spreadsheet-integrity/              #   Values: what a round trip through a workbook drops\n│   ├── honest-data-limits-disclosure/      #   Values: what was read, skipped, sampled\n│   ├── parquet-to-open-table-format/       #   Storage: when files stop being enough\n│   ├── duckdb-for-local-analytics/         #   Storage: asking the persisted table a question\n│   ├── chart-type-and-library-selection/   #   Output: the form, then the library  ← ships a script\n│   ├── dashboard-color-and-visual-hierarchy/ # Output: what colour encodes\n│   ├── dashboard-layout-by-widget-mix/     #   Output: where panels sit, one file  ← ships a script\n│   ├── dashboard-visual-craft/             #   Output: type, spacing, alignment, non-data ink\n│   ├── insight-narrative-integrity/        #   Output: does the sentence survive its arithmetic\n│   ├── data-privacy-before-llm/            #   Safety: what may leave the project\n│   └── safe-live-database-access/          #   Safety: connections and writes others share\n├── agents/                                 # 4 reviewer subagents, none able to edit what it reviews\n├── commands/                               # 9 lifecycle commands, as TOML — the source of truth\n├── .claude/commands/                       #   generated copy, checked for parity\n├── .gemini/commands/                       #   generated copy, checked for parity\n├── .opencode/agent/                        #   generated personas, edits denied by permission\n├── .cursor/agents/                         #   generated personas, readonly\n├── .gemini/agents/                         #   generated personas, tools allowlisted\n├── .codex/agents/                          #   generated personas, as TOML, sandboxed read-only\n├── hooks/                                  # 2 session hooks; one blocks a turn with no disclosure\n├── references/                             # 3 checklists shared by more than one skill\n├── evals/                                  # cases, synthetic fixtures, results\n├── scripts/                                # validators, eval runner, and skill-scripts/ (shipped)\n├── tests/                                  # pytest over every validator and the eval runner\n├── docs/                                   # skill anatomy, installing, the diagram above\n└── .claude-plugin/                         # plugin and marketplace manifests\n```\n\nThe three skills marked **ships a script** carry their own copy of `verify-output.sh` under\n`scripts/`, generated from one source and checked for drift, so a per-skill install brings the\ncheck with it rather than a reference to a file that is not there.\n\n[CONTRIBUTING.md](https://github.com/LuynoxRD/lakehouse-agent-skills/blob/main/CONTRIBUTING.md) has the workflow. Skills are code that runs inside somebody\nelse's agent, so nothing here fetches an installer, pipes a script into a shell, or reads\nenvironment variables — and a validator fails the build on those patterns rather than trusting\nreview to catch them. Every fixture is synthetic. `CODE_OF_CONDUCT.md` applies to every\ninteraction here, and `PRIVACY.md` says what the plugin reads and writes: nothing leaves the\nmachine. Questions go to\n[Discussions](https://github.com/LuynoxRD/lakehouse-agent-skills/discussions), anything you would\nrather not raise in public to [contacto@luynoxrd.com](mailto:contacto@luynoxrd.com), and security\nproblems follow `SECURITY.md`. [SUPPORT.md](https://github.com/LuynoxRD/lakehouse-agent-skills/blob/main/SUPPORT.md) says where each kind of request goes.", "url": "https://wpnews.pro/news/agent-skills-that-make-coding-agents-profile-data-before-charting-it", "canonical_source": "https://github.com/LuynoxRD/lakehouse-agent-skills", "published_at": "2026-10-28 15:28:51+00:00", "updated_at": "2026-10-28 15:42:04.335300+00:00", "lang": "en", "topics": ["ai-agents", "ai-tools", "developer-tools", "artificial-intelligence"], "entities": ["DuckDB", "Polars", "Parquet", "Cleveland and McGill"], "also_reported_by": [], "alternates": {"html": "https://wpnews.pro/news/agent-skills-that-make-coding-agents-profile-data-before-charting-it", "markdown": "https://wpnews.pro/news/agent-skills-that-make-coding-agents-profile-data-before-charting-it.md", "text": "https://wpnews.pro/news/agent-skills-that-make-coding-agents-profile-data-before-charting-it.txt", "jsonld": "https://wpnews.pro/news/agent-skills-that-make-coding-agents-profile-data-before-charting-it.jsonld"}}